@kirbydesign/designsystem 11.11.4 → 12.0.0-dev-286cdc0

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 (291) hide show
  1. package/README.md +7 -0
  2. package/fesm2022/kirbydesign-designsystem-accordion.mjs +246 -135
  3. package/fesm2022/kirbydesign-designsystem-accordion.mjs.map +1 -1
  4. package/fesm2022/kirbydesign-designsystem-action-group.mjs +229 -134
  5. package/fesm2022/kirbydesign-designsystem-action-group.mjs.map +1 -1
  6. package/fesm2022/kirbydesign-designsystem-avatar.mjs +102 -55
  7. package/fesm2022/kirbydesign-designsystem-avatar.mjs.map +1 -1
  8. package/fesm2022/kirbydesign-designsystem-badge.mjs +85 -42
  9. package/fesm2022/kirbydesign-designsystem-badge.mjs.map +1 -1
  10. package/fesm2022/kirbydesign-designsystem-button.mjs +203 -170
  11. package/fesm2022/kirbydesign-designsystem-button.mjs.map +1 -1
  12. package/fesm2022/kirbydesign-designsystem-calendar.mjs +524 -516
  13. package/fesm2022/kirbydesign-designsystem-calendar.mjs.map +1 -1
  14. package/fesm2022/kirbydesign-designsystem-card.mjs +439 -205
  15. package/fesm2022/kirbydesign-designsystem-card.mjs.map +1 -1
  16. package/fesm2022/kirbydesign-designsystem-chart.mjs +1388 -1469
  17. package/fesm2022/kirbydesign-designsystem-chart.mjs.map +1 -1
  18. package/fesm2022/kirbydesign-designsystem-checkbox.mjs +223 -176
  19. package/fesm2022/kirbydesign-designsystem-checkbox.mjs.map +1 -1
  20. package/fesm2022/kirbydesign-designsystem-config.mjs +50 -96
  21. package/fesm2022/kirbydesign-designsystem-config.mjs.map +1 -1
  22. package/fesm2022/kirbydesign-designsystem-data-table.mjs +180 -83
  23. package/fesm2022/kirbydesign-designsystem-data-table.mjs.map +1 -1
  24. package/fesm2022/kirbydesign-designsystem-divider.mjs +46 -19
  25. package/fesm2022/kirbydesign-designsystem-divider.mjs.map +1 -1
  26. package/fesm2022/kirbydesign-designsystem-dropdown.mjs +878 -752
  27. package/fesm2022/kirbydesign-designsystem-dropdown.mjs.map +1 -1
  28. package/fesm2022/kirbydesign-designsystem-empty-state.mjs +175 -91
  29. package/fesm2022/kirbydesign-designsystem-empty-state.mjs.map +1 -1
  30. package/fesm2022/kirbydesign-designsystem-fab-sheet.mjs +213 -85
  31. package/fesm2022/kirbydesign-designsystem-fab-sheet.mjs.map +1 -1
  32. package/fesm2022/kirbydesign-designsystem-flag.mjs +67 -33
  33. package/fesm2022/kirbydesign-designsystem-flag.mjs.map +1 -1
  34. package/fesm2022/kirbydesign-designsystem-form-field.mjs +1260 -891
  35. package/fesm2022/kirbydesign-designsystem-form-field.mjs.map +1 -1
  36. package/fesm2022/kirbydesign-designsystem-gesture.mjs +38 -23
  37. package/fesm2022/kirbydesign-designsystem-gesture.mjs.map +1 -1
  38. package/fesm2022/kirbydesign-designsystem-header.mjs +422 -182
  39. package/fesm2022/kirbydesign-designsystem-header.mjs.map +1 -1
  40. package/fesm2022/kirbydesign-designsystem-helpers-scss.mjs +16 -14
  41. package/fesm2022/kirbydesign-designsystem-helpers-scss.mjs.map +1 -1
  42. package/fesm2022/kirbydesign-designsystem-helpers.mjs +251 -361
  43. package/fesm2022/kirbydesign-designsystem-helpers.mjs.map +1 -1
  44. package/fesm2022/kirbydesign-designsystem-icon.mjs +881 -296
  45. package/fesm2022/kirbydesign-designsystem-icon.mjs.map +1 -1
  46. package/fesm2022/kirbydesign-designsystem-item-group.mjs +52 -23
  47. package/fesm2022/kirbydesign-designsystem-item-group.mjs.map +1 -1
  48. package/fesm2022/kirbydesign-designsystem-item-sliding.mjs +147 -43
  49. package/fesm2022/kirbydesign-designsystem-item-sliding.mjs.map +1 -1
  50. package/fesm2022/kirbydesign-designsystem-item.mjs +395 -151
  51. package/fesm2022/kirbydesign-designsystem-item.mjs.map +1 -1
  52. package/fesm2022/kirbydesign-designsystem-kirby-app.mjs +136 -54
  53. package/fesm2022/kirbydesign-designsystem-kirby-app.mjs.map +1 -1
  54. package/fesm2022/kirbydesign-designsystem-list.mjs +1188 -697
  55. package/fesm2022/kirbydesign-designsystem-list.mjs.map +1 -1
  56. package/fesm2022/kirbydesign-designsystem-loading-overlay.mjs +166 -76
  57. package/fesm2022/kirbydesign-designsystem-loading-overlay.mjs.map +1 -1
  58. package/fesm2022/kirbydesign-designsystem-menu.mjs +420 -311
  59. package/fesm2022/kirbydesign-designsystem-menu.mjs.map +1 -1
  60. package/fesm2022/kirbydesign-designsystem-modal.mjs +2476 -1912
  61. package/fesm2022/kirbydesign-designsystem-modal.mjs.map +1 -1
  62. package/fesm2022/kirbydesign-designsystem-page.mjs +1526 -905
  63. package/fesm2022/kirbydesign-designsystem-page.mjs.map +1 -1
  64. package/fesm2022/kirbydesign-designsystem-popover.mjs +204 -169
  65. package/fesm2022/kirbydesign-designsystem-popover.mjs.map +1 -1
  66. package/fesm2022/kirbydesign-designsystem-progress-circle.mjs +209 -158
  67. package/fesm2022/kirbydesign-designsystem-progress-circle.mjs.map +1 -1
  68. package/fesm2022/kirbydesign-designsystem-radio.mjs +537 -365
  69. package/fesm2022/kirbydesign-designsystem-radio.mjs.map +1 -1
  70. package/fesm2022/kirbydesign-designsystem-range.mjs +207 -150
  71. package/fesm2022/kirbydesign-designsystem-range.mjs.map +1 -1
  72. package/fesm2022/kirbydesign-designsystem-reorder-list.mjs +217 -104
  73. package/fesm2022/kirbydesign-designsystem-reorder-list.mjs.map +1 -1
  74. package/fesm2022/kirbydesign-designsystem-router-outlet.mjs +113 -38
  75. package/fesm2022/kirbydesign-designsystem-router-outlet.mjs.map +1 -1
  76. package/fesm2022/kirbydesign-designsystem-section-header.mjs +56 -18
  77. package/fesm2022/kirbydesign-designsystem-section-header.mjs.map +1 -1
  78. package/fesm2022/kirbydesign-designsystem-segmented-control.mjs +276 -232
  79. package/fesm2022/kirbydesign-designsystem-segmented-control.mjs.map +1 -1
  80. package/fesm2022/kirbydesign-designsystem-shared-floating.mjs +328 -382
  81. package/fesm2022/kirbydesign-designsystem-shared-floating.mjs.map +1 -1
  82. package/fesm2022/kirbydesign-designsystem-shared-portal.mjs +73 -84
  83. package/fesm2022/kirbydesign-designsystem-shared-portal.mjs.map +1 -1
  84. package/fesm2022/kirbydesign-designsystem-shared.mjs +665 -531
  85. package/fesm2022/kirbydesign-designsystem-shared.mjs.map +1 -1
  86. package/fesm2022/kirbydesign-designsystem-slide-button.mjs +140 -91
  87. package/fesm2022/kirbydesign-designsystem-slide-button.mjs.map +1 -1
  88. package/fesm2022/kirbydesign-designsystem-slide.mjs +360 -158
  89. package/fesm2022/kirbydesign-designsystem-slide.mjs.map +1 -1
  90. package/fesm2022/kirbydesign-designsystem-spinner.mjs +90 -32
  91. package/fesm2022/kirbydesign-designsystem-spinner.mjs.map +1 -1
  92. package/fesm2022/kirbydesign-designsystem-tab-navigation.mjs +348 -181
  93. package/fesm2022/kirbydesign-designsystem-tab-navigation.mjs.map +1 -1
  94. package/fesm2022/kirbydesign-designsystem-tabs.mjs +286 -121
  95. package/fesm2022/kirbydesign-designsystem-tabs.mjs.map +1 -1
  96. package/fesm2022/kirbydesign-designsystem-testing-base.mjs +6234 -3164
  97. package/fesm2022/kirbydesign-designsystem-testing-base.mjs.map +1 -1
  98. package/fesm2022/kirbydesign-designsystem-testing-jasmine.mjs +118 -95
  99. package/fesm2022/kirbydesign-designsystem-testing-jasmine.mjs.map +1 -1
  100. package/fesm2022/kirbydesign-designsystem-testing-jest.mjs +128 -101
  101. package/fesm2022/kirbydesign-designsystem-testing-jest.mjs.map +1 -1
  102. package/fesm2022/kirbydesign-designsystem-testing.mjs +236 -243
  103. package/fesm2022/kirbydesign-designsystem-testing.mjs.map +1 -1
  104. package/fesm2022/kirbydesign-designsystem-toast.mjs +98 -62
  105. package/fesm2022/kirbydesign-designsystem-toast.mjs.map +1 -1
  106. package/fesm2022/kirbydesign-designsystem-toggle-button.mjs +155 -127
  107. package/fesm2022/kirbydesign-designsystem-toggle-button.mjs.map +1 -1
  108. package/fesm2022/kirbydesign-designsystem-toggle.mjs +180 -150
  109. package/fesm2022/kirbydesign-designsystem-toggle.mjs.map +1 -1
  110. package/fesm2022/kirbydesign-designsystem-types.mjs +39 -24
  111. package/fesm2022/kirbydesign-designsystem-types.mjs.map +1 -1
  112. package/fesm2022/kirbydesign-designsystem.mjs +516 -407
  113. package/fesm2022/kirbydesign-designsystem.mjs.map +1 -1
  114. package/icons/svg/megaphone.svg +3 -0
  115. package/icons/svg/person-blocked.svg +3 -0
  116. package/icons/svg/person-check.svg +3 -0
  117. package/icons/svg/person-close.svg +3 -0
  118. package/icons/svg/person-cloud.svg +3 -0
  119. package/icons/svg/person-power.svg +3 -0
  120. package/icons/svg/person-warning.svg +3 -0
  121. package/icons/svg/phone-device-pin.svg +3 -0
  122. package/icons/svg/phone-device.svg +3 -2
  123. package/package.json +10 -10
  124. package/readme.md +37 -0
  125. package/types/kirbydesign-designsystem-accordion.d.ts +72 -39
  126. package/types/kirbydesign-designsystem-accordion.d.ts.map +1 -1
  127. package/types/kirbydesign-designsystem-action-group.d.ts +46 -39
  128. package/types/kirbydesign-designsystem-action-group.d.ts.map +1 -1
  129. package/types/kirbydesign-designsystem-avatar.d.ts +62 -26
  130. package/types/kirbydesign-designsystem-avatar.d.ts.map +1 -1
  131. package/types/kirbydesign-designsystem-badge.d.ts +30 -19
  132. package/types/kirbydesign-designsystem-badge.d.ts.map +1 -1
  133. package/types/kirbydesign-designsystem-button.d.ts +70 -45
  134. package/types/kirbydesign-designsystem-button.d.ts.map +1 -1
  135. package/types/kirbydesign-designsystem-calendar.d.ts +193 -132
  136. package/types/kirbydesign-designsystem-calendar.d.ts.map +1 -1
  137. package/types/kirbydesign-designsystem-card.d.ts +130 -66
  138. package/types/kirbydesign-designsystem-card.d.ts.map +1 -1
  139. package/types/kirbydesign-designsystem-chart.d.ts +198 -172
  140. package/types/kirbydesign-designsystem-chart.d.ts.map +1 -1
  141. package/types/kirbydesign-designsystem-checkbox.d.ts +102 -68
  142. package/types/kirbydesign-designsystem-checkbox.d.ts.map +1 -1
  143. package/types/kirbydesign-designsystem-config.d.ts +17 -21
  144. package/types/kirbydesign-designsystem-config.d.ts.map +1 -1
  145. package/types/kirbydesign-designsystem-data-table.d.ts +46 -26
  146. package/types/kirbydesign-designsystem-data-table.d.ts.map +1 -1
  147. package/types/kirbydesign-designsystem-divider.d.ts +11 -9
  148. package/types/kirbydesign-designsystem-divider.d.ts.map +1 -1
  149. package/types/kirbydesign-designsystem-dropdown.d.ts +219 -166
  150. package/types/kirbydesign-designsystem-dropdown.d.ts.map +1 -1
  151. package/types/kirbydesign-designsystem-empty-state.d.ts +58 -35
  152. package/types/kirbydesign-designsystem-empty-state.d.ts.map +1 -1
  153. package/types/kirbydesign-designsystem-fab-sheet.d.ts +34 -28
  154. package/types/kirbydesign-designsystem-fab-sheet.d.ts.map +1 -1
  155. package/types/kirbydesign-designsystem-flag.d.ts +18 -13
  156. package/types/kirbydesign-designsystem-flag.d.ts.map +1 -1
  157. package/types/kirbydesign-designsystem-form-field.d.ts +409 -242
  158. package/types/kirbydesign-designsystem-form-field.d.ts.map +1 -1
  159. package/types/kirbydesign-designsystem-gesture.d.ts +41 -46
  160. package/types/kirbydesign-designsystem-gesture.d.ts.map +1 -1
  161. package/types/kirbydesign-designsystem-header.d.ts +102 -64
  162. package/types/kirbydesign-designsystem-header.d.ts.map +1 -1
  163. package/types/kirbydesign-designsystem-helpers-scss.d.ts +6 -8
  164. package/types/kirbydesign-designsystem-helpers-scss.d.ts.map +1 -1
  165. package/types/kirbydesign-designsystem-helpers.d.ts +83 -97
  166. package/types/kirbydesign-designsystem-helpers.d.ts.map +1 -1
  167. package/types/kirbydesign-designsystem-icon.d.ts +63 -59
  168. package/types/kirbydesign-designsystem-icon.d.ts.map +1 -1
  169. package/types/kirbydesign-designsystem-item-group.d.ts +6 -9
  170. package/types/kirbydesign-designsystem-item-group.d.ts.map +1 -1
  171. package/types/kirbydesign-designsystem-item-sliding.d.ts +30 -26
  172. package/types/kirbydesign-designsystem-item-sliding.d.ts.map +1 -1
  173. package/types/kirbydesign-designsystem-item.d.ts +93 -54
  174. package/types/kirbydesign-designsystem-item.d.ts.map +1 -1
  175. package/types/kirbydesign-designsystem-kirby-app.d.ts +18 -19
  176. package/types/kirbydesign-designsystem-kirby-app.d.ts.map +1 -1
  177. package/types/kirbydesign-designsystem-list.d.ts +392 -263
  178. package/types/kirbydesign-designsystem-list.d.ts.map +1 -1
  179. package/types/kirbydesign-designsystem-loading-overlay.d.ts +35 -24
  180. package/types/kirbydesign-designsystem-loading-overlay.d.ts.map +1 -1
  181. package/types/kirbydesign-designsystem-menu.d.ts +119 -69
  182. package/types/kirbydesign-designsystem-menu.d.ts.map +1 -1
  183. package/types/kirbydesign-designsystem-modal.d.ts +578 -455
  184. package/types/kirbydesign-designsystem-modal.d.ts.map +1 -1
  185. package/types/kirbydesign-designsystem-page.d.ts +308 -226
  186. package/types/kirbydesign-designsystem-page.d.ts.map +1 -1
  187. package/types/kirbydesign-designsystem-popover.d.ts +48 -40
  188. package/types/kirbydesign-designsystem-popover.d.ts.map +1 -1
  189. package/types/kirbydesign-designsystem-progress-circle.d.ts +59 -61
  190. package/types/kirbydesign-designsystem-progress-circle.d.ts.map +1 -1
  191. package/types/kirbydesign-designsystem-radio.d.ts +147 -98
  192. package/types/kirbydesign-designsystem-radio.d.ts.map +1 -1
  193. package/types/kirbydesign-designsystem-range.d.ts +90 -45
  194. package/types/kirbydesign-designsystem-range.d.ts.map +1 -1
  195. package/types/kirbydesign-designsystem-reorder-list.d.ts +44 -32
  196. package/types/kirbydesign-designsystem-reorder-list.d.ts.map +1 -1
  197. package/types/kirbydesign-designsystem-router-outlet.d.ts +23 -18
  198. package/types/kirbydesign-designsystem-router-outlet.d.ts.map +1 -1
  199. package/types/kirbydesign-designsystem-section-header.d.ts +5 -8
  200. package/types/kirbydesign-designsystem-section-header.d.ts.map +1 -1
  201. package/types/kirbydesign-designsystem-segmented-control.d.ts +123 -100
  202. package/types/kirbydesign-designsystem-segmented-control.d.ts.map +1 -1
  203. package/types/kirbydesign-designsystem-shared-floating.d.ts +183 -128
  204. package/types/kirbydesign-designsystem-shared-floating.d.ts.map +1 -1
  205. package/types/kirbydesign-designsystem-shared-portal.d.ts +29 -28
  206. package/types/kirbydesign-designsystem-shared-portal.d.ts.map +1 -1
  207. package/types/kirbydesign-designsystem-shared.d.ts +143 -139
  208. package/types/kirbydesign-designsystem-shared.d.ts.map +1 -1
  209. package/types/kirbydesign-designsystem-slide-button.d.ts +43 -34
  210. package/types/kirbydesign-designsystem-slide-button.d.ts.map +1 -1
  211. package/types/kirbydesign-designsystem-slide.d.ts +80 -59
  212. package/types/kirbydesign-designsystem-slide.d.ts.map +1 -1
  213. package/types/kirbydesign-designsystem-spinner.d.ts +13 -14
  214. package/types/kirbydesign-designsystem-spinner.d.ts.map +1 -1
  215. package/types/kirbydesign-designsystem-tab-navigation.d.ts +78 -55
  216. package/types/kirbydesign-designsystem-tab-navigation.d.ts.map +1 -1
  217. package/types/kirbydesign-designsystem-tabs.d.ts +50 -45
  218. package/types/kirbydesign-designsystem-tabs.d.ts.map +1 -1
  219. package/types/kirbydesign-designsystem-testing-base.d.ts +2435 -815
  220. package/types/kirbydesign-designsystem-testing-base.d.ts.map +1 -1
  221. package/types/kirbydesign-designsystem-testing-jasmine.d.ts +9 -10
  222. package/types/kirbydesign-designsystem-testing-jasmine.d.ts.map +1 -1
  223. package/types/kirbydesign-designsystem-testing-jest.d.ts +9 -10
  224. package/types/kirbydesign-designsystem-testing-jest.d.ts.map +1 -1
  225. package/types/kirbydesign-designsystem-testing.d.ts +52 -58
  226. package/types/kirbydesign-designsystem-testing.d.ts.map +1 -1
  227. package/types/kirbydesign-designsystem-toast.d.ts +25 -31
  228. package/types/kirbydesign-designsystem-toast.d.ts.map +1 -1
  229. package/types/kirbydesign-designsystem-toggle-button.d.ts +62 -56
  230. package/types/kirbydesign-designsystem-toggle-button.d.ts.map +1 -1
  231. package/types/kirbydesign-designsystem-toggle.d.ts +71 -63
  232. package/types/kirbydesign-designsystem-toggle.d.ts.map +1 -1
  233. package/types/kirbydesign-designsystem-types.d.ts +15 -22
  234. package/types/kirbydesign-designsystem-types.d.ts.map +1 -1
  235. package/types/kirbydesign-designsystem.d.ts +135 -123
  236. package/types/kirbydesign-designsystem.d.ts.map +1 -1
  237. package/accordion/package.json +0 -4
  238. package/action-group/package.json +0 -4
  239. package/avatar/package.json +0 -4
  240. package/badge/package.json +0 -4
  241. package/button/package.json +0 -4
  242. package/calendar/package.json +0 -4
  243. package/card/package.json +0 -4
  244. package/chart/package.json +0 -4
  245. package/checkbox/package.json +0 -4
  246. package/config/package.json +0 -4
  247. package/data-table/package.json +0 -4
  248. package/divider/package.json +0 -4
  249. package/dropdown/package.json +0 -4
  250. package/empty-state/package.json +0 -4
  251. package/fab-sheet/package.json +0 -4
  252. package/flag/package.json +0 -4
  253. package/form-field/package.json +0 -4
  254. package/gesture/package.json +0 -4
  255. package/header/package.json +0 -4
  256. package/helpers/package.json +0 -4
  257. package/helpers/scss/package.json +0 -4
  258. package/icon/package.json +0 -4
  259. package/item/package.json +0 -4
  260. package/item-group/package.json +0 -4
  261. package/item-sliding/package.json +0 -4
  262. package/kirby-app/package.json +0 -4
  263. package/list/package.json +0 -4
  264. package/loading-overlay/package.json +0 -4
  265. package/menu/package.json +0 -4
  266. package/modal/package.json +0 -4
  267. package/page/package.json +0 -4
  268. package/popover/package.json +0 -4
  269. package/progress-circle/package.json +0 -4
  270. package/radio/package.json +0 -4
  271. package/range/package.json +0 -4
  272. package/reorder-list/package.json +0 -4
  273. package/router-outlet/package.json +0 -4
  274. package/section-header/package.json +0 -4
  275. package/segmented-control/package.json +0 -4
  276. package/shared/floating/package.json +0 -4
  277. package/shared/package.json +0 -4
  278. package/shared/portal/package.json +0 -4
  279. package/slide/package.json +0 -4
  280. package/slide-button/package.json +0 -4
  281. package/spinner/package.json +0 -4
  282. package/tab-navigation/package.json +0 -4
  283. package/tabs/package.json +0 -4
  284. package/testing/package.json +0 -4
  285. package/testing-base/package.json +0 -4
  286. package/testing-jasmine/package.json +0 -4
  287. package/testing-jest/package.json +0 -4
  288. package/toast/package.json +0 -4
  289. package/toggle/package.json +0 -4
  290. package/toggle-button/package.json +0 -4
  291. package/types/package.json +0 -4
@@ -1,1919 +1,2483 @@
1
- import * as i0 from '@angular/core';
2
- import { Optional, Component, InjectionToken, ElementRef, Input, ViewChild, ChangeDetectionStrategy, Injectable, Injector, RendererStyleFlags2, TemplateRef, HostListener, HostBinding, ViewChildren, ContentChild, EventEmitter, Output, Inject, inject } from '@angular/core';
3
- import * as i1$3 from '@angular/router';
4
- import { RouterModule, RouterOutlet, NavigationEnd, NavigationStart, ROUTES } from '@angular/router';
5
- import { of, isObservable, Subject, firstValueFrom, merge, defer, EMPTY } from 'rxjs';
6
- import { debounceTime, first, takeUntil, map, filter, startWith, pairwise, skipUntil } from 'rxjs/operators';
7
- import * as i3 from '@kirbydesign/designsystem/helpers';
8
- import { getIonModalDialogAncestor, DesignTokenHelper, observeContent, KirbyAnimation } from '@kirbydesign/designsystem/helpers';
9
- import * as i6 from '@angular/common';
10
- import { CommonModule } from '@angular/common';
11
- import { IconComponent } from '@kirbydesign/designsystem/icon';
12
- import { ButtonComponent } from '@kirbydesign/designsystem/button';
13
- import * as i1$1 from '@ionic/angular/standalone';
14
- import { IonHeader, IonToolbar, IonTitle, IonButtons, IonContent, createAnimation, ModalController as ModalController$1, IonModal, IonFooter } from '@ionic/angular/standalone';
15
- import * as i1$2 from '@kirbydesign/designsystem/shared';
16
- import { ThemeColorDirective, inheritAriaLabelText } from '@kirbydesign/designsystem/shared';
17
- import * as i1 from '@kirbydesign/designsystem/types';
18
- import { EmptyStateComponent } from '@kirbydesign/designsystem/empty-state';
19
- import { CardComponent, CardHeaderComponent } from '@kirbydesign/designsystem/card';
20
-
21
- class Modal {
22
- }
23
- /**
24
- * WARNING: This is for internal use only and should not be used outside of Kirby.
25
- */
1
+ import * as i0 from "@angular/core";
2
+ import { ChangeDetectionStrategy, Component, ContentChild, ElementRef, EventEmitter, HostBinding, HostListener, Inject, Injectable, InjectionToken, Injector, Input, Optional, Output, RendererStyleFlags2, TemplateRef, ViewChild, ViewChildren, inject } from "@angular/core";
3
+ import * as i5 from "@angular/router";
4
+ import { NavigationEnd, NavigationStart, ROUTES, RouterModule, RouterOutlet } from "@angular/router";
5
+ import { EMPTY, Subject, defer, firstValueFrom, fromEvent, isObservable, merge, of } from "rxjs";
6
+ import { debounceTime, filter, first, map, pairwise, skipUntil, startWith, takeUntil } from "rxjs/operators";
7
+ import * as i3 from "@kirbydesign/designsystem/helpers";
8
+ import { DesignTokenHelper, KirbyAnimation, getIonModalDialogAncestor, observeContent } from "@kirbydesign/designsystem/helpers";
9
+ import * as i2 from "@angular/common";
10
+ import { CommonModule } from "@angular/common";
11
+ import { IconComponent } from "@kirbydesign/designsystem/icon";
12
+ import { ButtonComponent } from "@kirbydesign/designsystem/button";
13
+ import * as i1$1 from "@ionic/angular";
14
+ import { IonButtons, IonContent, IonFooter, IonHeader, IonModal, IonTitle, IonToolbar, ModalController as ModalController$1, createAnimation } from "@ionic/angular";
15
+ import * as i1 from "@kirbydesign/designsystem/shared";
16
+ import { ThemeColorDirective, inheritAriaLabelText } from "@kirbydesign/designsystem/shared";
17
+ import * as i1$2 from "@kirbydesign/designsystem/types";
18
+ import { EmptyStateComponent } from "@kirbydesign/designsystem/empty-state";
19
+ import { CardComponent, CardHeaderComponent } from "@kirbydesign/designsystem/card";
20
+ var Modal = class {};
26
21
  var ModalElementType;
27
- (function (ModalElementType) {
28
- ModalElementType[ModalElementType["PAGE_PROGRESS"] = 0] = "PAGE_PROGRESS";
29
- ModalElementType[ModalElementType["FOOTER"] = 1] = "FOOTER";
30
- ModalElementType[ModalElementType["TITLE"] = 2] = "TITLE";
22
+ (function(ModalElementType) {
23
+ ModalElementType[ModalElementType["PAGE_PROGRESS"] = 0] = "PAGE_PROGRESS";
24
+ ModalElementType[ModalElementType["FOOTER"] = 1] = "FOOTER";
25
+ ModalElementType[ModalElementType["TITLE"] = 2] = "TITLE";
31
26
  })(ModalElementType || (ModalElementType = {}));
32
- /**
33
- * WARNING: This is for internal use only and should not be used outside of Kirby.
34
- */
35
- class ModalElementsAdvertiser {
36
- }
37
- /**
38
- * WARNING: This is for internal use only and should not be used outside of Kirby.
39
- */
40
- class ModalElementComponent {
41
- get isContainedInModal() {
42
- return this.modalElementsAdvertiser !== null;
43
- }
44
- constructor(modalElementType, elementRef, modalElementsAdvertiser) {
45
- this.modalElementType = modalElementType;
46
- this.elementRef = elementRef;
47
- this.modalElementsAdvertiser = modalElementsAdvertiser;
48
- }
49
- ngAfterViewInit() {
50
- if (this.isContainedInModal) {
51
- this.modalElementsAdvertiser.addModalElement(this.modalElementType, this.elementRef);
52
- }
53
- }
54
- ngOnDestroy() {
55
- if (this.isContainedInModal) {
56
- this.modalElementsAdvertiser.removeModalElement(this.modalElementType, this.elementRef);
57
- }
58
- }
59
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ModalElementComponent, deps: [{ token: ModalElementType }, { token: i0.ElementRef }, { token: ModalElementsAdvertiser, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
60
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.18", type: ModalElementComponent, isStandalone: false, selector: "ng-component", ngImport: i0, template: '', isInline: true }); }
61
- }
62
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ModalElementComponent, decorators: [{
63
- type: Component,
64
- args: [{
65
- template: '',
66
- standalone: false,
67
- }]
68
- }], ctorParameters: () => [{ type: ModalElementType }, { type: i0.ElementRef }, { type: ModalElementsAdvertiser, decorators: [{
69
- type: Optional
70
- }] }] });
71
-
72
- const COMPONENT_PROPS = new InjectionToken('componentProps');
73
-
74
- /*
75
- The ModalWrapperComponent class was growing large.
76
-
77
- Hence the functions responsible for moving modal elements around
78
- has been encapsulated in this class.
79
- */
80
- class ModalElementsMoverDelegate {
81
- constructor(renderer, elementRef) {
82
- this.renderer = renderer;
83
- this.elementRef = elementRef;
84
- }
85
- addFooter(footerElementRef) {
86
- // Move the footer next to ion-content
87
- this.moveChild(footerElementRef, this.elementRef);
88
- }
89
- removeFooter(footerElementRef) {
90
- this.removeChild(footerElementRef);
91
- }
92
- addPageProgress(pageProgressElementRef, ionToolbarElement) {
93
- this.moveChild(pageProgressElementRef, ionToolbarElement);
94
- }
95
- removePageProgress(pageProgressElementRef) {
96
- this.removeChild(pageProgressElementRef);
97
- }
98
- /*
99
- contentTitleElement & ionTitleElement has to be passed
100
- as arguments to the method; not part of the constructor, as they
101
- might reference completely different elements between calls.
102
-
103
- For example in a multi-page routed modal where the elements are destroyed
104
- and recreated.
105
- */
106
- addTitle(titleElementRef, contentTitleElement, hasCollapsibleTitle, ionTitleElement) {
107
- this.moveChild(titleElementRef, ionTitleElement);
108
- // If title is collapsible append it to content area; required by ionic implementation.
109
- if (hasCollapsibleTitle) {
110
- const titleElementClone = titleElementRef.nativeElement.cloneNode(true);
111
- this.moveChild(new ElementRef(titleElementClone), contentTitleElement);
112
- }
113
- }
114
- removeTitle(titleElementRef, hasCollapsibleTitle, contentTitleElement) {
115
- this.removeChild(titleElementRef);
116
- if (hasCollapsibleTitle) {
117
- const kirbyPageTitleElement = contentTitleElement.nativeElement.querySelector('kirby-page-title');
118
- this.removeChild(new ElementRef(kirbyPageTitleElement));
119
- }
120
- }
121
- moveChild(childElementRef, newParentElementRef) {
122
- const child = childElementRef.nativeElement;
123
- const newParent = newParentElementRef.nativeElement;
124
- this.renderer.removeChild(child.parentElement, child);
125
- this.renderer.appendChild(newParent, child);
126
- }
127
- removeChild(childElementRef, parentElement) {
128
- const child = childElementRef.nativeElement;
129
- if (child) {
130
- this.renderer.removeChild(parentElement || child.parentElement, child);
131
- }
132
- }
133
- }
134
-
135
- class AlertComponent {
136
- set title(title) {
137
- this.title$ = typeof title === 'string' ? of(title) : title;
138
- }
139
- set message(message) {
140
- this.message$ = typeof message === 'string' ? of(message) : message;
141
- }
142
- set okBtn(okBtn) {
143
- this.okBtn$ = typeof okBtn === 'string' ? of(okBtn) : okBtn;
144
- }
145
- set cancelBtn(cancelBtn) {
146
- this.cancelBtn$ = typeof cancelBtn === 'string' ? of(cancelBtn) : cancelBtn;
147
- }
148
- constructor(elementRef, windowRef) {
149
- this.elementRef = elementRef;
150
- this.windowRef = windowRef;
151
- this.BLUR_WRAPPER_DELAY_IN_MS = 50;
152
- this.scrollY = Math.abs(this.windowRef.nativeWindow.scrollY);
153
- }
154
- ngAfterViewInit() {
155
- setTimeout(() => {
156
- this.alertWrapper.nativeElement.focus();
157
- this.alertWrapper.nativeElement.blur();
158
- }, this.BLUR_WRAPPER_DELAY_IN_MS);
159
- }
160
- onFocusChange() {
161
- // This fixes an undesired scroll behaviour occurring on keyboard-tabbing
162
- this.windowRef.nativeWindow.scrollTo({ top: this.scrollY });
163
- }
164
- onCancel() {
165
- const ionModalElement = this.elementRef.nativeElement.closest('ion-modal');
166
- ionModalElement?.dismiss(false);
167
- }
168
- onOk() {
169
- const ionModalElement = this.elementRef.nativeElement.closest('ion-modal');
170
- ionModalElement?.dismiss(true);
171
- }
172
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: AlertComponent, deps: [{ token: i0.ElementRef }, { token: i1.WindowRef }], target: i0.ɵɵFactoryTarget.Component }); }
173
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: AlertComponent, isStandalone: true, selector: "kirby-alert", inputs: { title: "title", message: "message", iconName: "iconName", iconThemeColor: "iconThemeColor", okBtn: "okBtn", okBtnIsDestructive: "okBtnIsDestructive", cancelBtn: "cancelBtn" }, host: { properties: { "class.ion-page": "false" } }, viewQueries: [{ propertyName: "alertWrapper", first: true, predicate: ["alertWrapper"], descendants: true, static: true }], ngImport: i0, template: "<article #alertWrapper>\n <kirby-empty-state\n [iconName]=\"iconName\"\n [themeColor]=\"iconThemeColor\"\n [title]=\"title$ | async\"\n [subtitle]=\"message$ | async\"\n ></kirby-empty-state>\n <div class=\"buttongroup\">\n @if (cancelBtn$ | async; as cancelBtn) {\n <button kirby-button attentionLevel=\"3\" class=\"cancel-btn\" (click)=\"onCancel()\">\n {{ cancelBtn }}\n </button>\n }\n <button\n kirby-button\n [size]=\"(cancelBtn$ | async) ? null : 'lg'\"\n attentionLevel=\"1\"\n class=\"ok-btn\"\n [class.destructive]=\"okBtnIsDestructive\"\n (click)=\"onOk()\"\n >\n {{ okBtn$ | async }}\n </button>\n </div>\n</article>\n", styles: [".kirby-line-clamp{display:-webkit-box;-webkit-line-clamp:var(--line-clamp, none);-webkit-box-orient:vertical;overflow:hidden}article{overflow:hidden;padding:24px 16px 16px}@media(max-width:320px){article{padding:8px}}.buttongroup{display:flex;justify-content:center;column-gap:8px;flex-wrap:wrap}.buttongroup button{flex:0 1 calc(50% - 4px);margin-inline:0}.buttongroup button:not(:only-child){flex-grow:1;min-width:unset}\n"], dependencies: [{ kind: "component", type: EmptyStateComponent, selector: "kirby-empty-state", inputs: ["iconName", "title", "subtitle"] }, { kind: "component", type: ButtonComponent, selector: "button[kirby-button],Button[kirby-button],a[kirby-button]", inputs: ["attentionLevel", "noDecoration", "themeColor", "expand", "isFloating", "size", "showIconOnly"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: ThemeColorDirective, selector: "kirby-avatar[themeColor], kirby-card[themeColor], kirby-icon[themeColor], kirby-progress-circle-ring[themeColor], kirby-modal-footer[themeColor], kirby-empty-state[themeColor]", inputs: ["themeColor"] }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
174
- }
175
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: AlertComponent, decorators: [{
176
- type: Component,
177
- args: [{ imports: [IconComponent, EmptyStateComponent, ButtonComponent, CommonModule, ThemeColorDirective], selector: 'kirby-alert', host: { '[class.ion-page]': 'false' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<article #alertWrapper>\n <kirby-empty-state\n [iconName]=\"iconName\"\n [themeColor]=\"iconThemeColor\"\n [title]=\"title$ | async\"\n [subtitle]=\"message$ | async\"\n ></kirby-empty-state>\n <div class=\"buttongroup\">\n @if (cancelBtn$ | async; as cancelBtn) {\n <button kirby-button attentionLevel=\"3\" class=\"cancel-btn\" (click)=\"onCancel()\">\n {{ cancelBtn }}\n </button>\n }\n <button\n kirby-button\n [size]=\"(cancelBtn$ | async) ? null : 'lg'\"\n attentionLevel=\"1\"\n class=\"ok-btn\"\n [class.destructive]=\"okBtnIsDestructive\"\n (click)=\"onOk()\"\n >\n {{ okBtn$ | async }}\n </button>\n </div>\n</article>\n", styles: [".kirby-line-clamp{display:-webkit-box;-webkit-line-clamp:var(--line-clamp, none);-webkit-box-orient:vertical;overflow:hidden}article{overflow:hidden;padding:24px 16px 16px}@media(max-width:320px){article{padding:8px}}.buttongroup{display:flex;justify-content:center;column-gap:8px;flex-wrap:wrap}.buttongroup button{flex:0 1 calc(50% - 4px);margin-inline:0}.buttongroup button:not(:only-child){flex-grow:1;min-width:unset}\n"] }]
178
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1.WindowRef }], propDecorators: { alertWrapper: [{
179
- type: ViewChild,
180
- args: ['alertWrapper', { static: true }]
181
- }], title: [{
182
- type: Input
183
- }], message: [{
184
- type: Input
185
- }], iconName: [{
186
- type: Input
187
- }], iconThemeColor: [{
188
- type: Input
189
- }], okBtn: [{
190
- type: Input
191
- }], okBtnIsDestructive: [{
192
- type: Input
193
- }], cancelBtn: [{
194
- type: Input
195
- }] } });
196
-
197
- class AlertHelper {
198
- constructor(ionicModalController) {
199
- this.ionicModalController = ionicModalController;
200
- }
201
- async showAlert(config) {
202
- const ionModal = await this.ionicModalController.create({
203
- component: AlertComponent,
204
- componentProps: this.getComponentProps(config),
205
- cssClass: ['kirby-overlay', 'kirby-alert'],
206
- mode: 'ios',
207
- backdropDismiss: false,
208
- });
209
- await ionModal.present();
210
- return {
211
- dismiss: ionModal.dismiss.bind(ionModal),
212
- onWillDismiss: ionModal.onWillDismiss(),
213
- onDidDismiss: ionModal.onDidDismiss(),
214
- };
215
- }
216
- getComponentProps(config) {
217
- return {
218
- ...config,
219
- okBtn: this.getOkBtn(config),
220
- okBtnIsDestructive: this.getOkBtnIsDestructive(config),
221
- iconName: config.icon && config.icon.name,
222
- iconThemeColor: config.icon && config.icon.themeColor,
223
- };
224
- }
225
- getOkBtn(config) {
226
- let text;
227
- if (config.okBtn) {
228
- if (typeof config.okBtn === 'string' || isObservable(config.okBtn)) {
229
- text = config.okBtn;
230
- }
231
- else {
232
- text = config.okBtn?.text;
233
- }
234
- }
235
- return text;
236
- }
237
- getOkBtnIsDestructive(config) {
238
- return typeof config.okBtn === 'object' ? config.okBtn.isDestructive : undefined;
239
- }
240
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: AlertHelper, deps: [{ token: i1$1.ModalController }], target: i0.ɵɵFactoryTarget.Injectable }); }
241
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: AlertHelper }); }
242
- }
243
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: AlertHelper, decorators: [{
244
- type: Injectable
245
- }], ctorParameters: () => [{ type: i1$1.ModalController }] });
246
-
247
- class CanDismissHelper {
248
- constructor(alertHelper) {
249
- this.alertHelper = alertHelper;
250
- }
251
- getCanDismissCallback(callback) {
252
- return async () => {
253
- const result = await callback();
254
- if (typeof result === 'boolean')
255
- return result;
256
- const canCloseModal = await this.showAlert(result);
257
- return canCloseModal;
258
- };
259
- }
260
- async showAlert(config) {
261
- const alert = await this.alertHelper.showAlert(config);
262
- const result = await alert.onWillDismiss;
263
- return result.data;
264
- }
265
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: CanDismissHelper, deps: [{ token: AlertHelper }], target: i0.ɵɵFactoryTarget.Injectable }); }
266
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: CanDismissHelper }); }
267
- }
268
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: CanDismissHelper, decorators: [{
269
- type: Injectable
270
- }], ctorParameters: () => [{ type: AlertHelper }] });
271
-
27
+ var ModalElementsAdvertiser = class {};
28
+ var ModalElementComponent = class ModalElementComponent {
29
+ get isContainedInModal() {
30
+ return this.modalElementsAdvertiser !== null;
31
+ }
32
+ constructor(modalElementType, elementRef, modalElementsAdvertiser) {
33
+ this.modalElementType = modalElementType;
34
+ this.elementRef = elementRef;
35
+ this.modalElementsAdvertiser = modalElementsAdvertiser;
36
+ }
37
+ ngAfterViewInit() {
38
+ if (this.isContainedInModal) this.modalElementsAdvertiser.addModalElement(this.modalElementType, this.elementRef);
39
+ }
40
+ ngOnDestroy() {
41
+ if (this.isContainedInModal) this.modalElementsAdvertiser.removeModalElement(this.modalElementType, this.elementRef);
42
+ }
43
+ static {
44
+ this.ɵfac = i0.ɵɵngDeclareFactory({
45
+ minVersion: "12.0.0",
46
+ version: "22.2.3",
47
+ ngImport: i0,
48
+ type: ModalElementComponent,
49
+ deps: [
50
+ { token: ModalElementType },
51
+ { token: i0.ElementRef },
52
+ {
53
+ token: ModalElementsAdvertiser,
54
+ optional: true
55
+ }
56
+ ],
57
+ target: i0.ɵɵFactoryTarget.Component
58
+ });
59
+ }
60
+ static {
61
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
62
+ minVersion: "14.0.0",
63
+ version: "22.2.3",
64
+ type: ModalElementComponent,
65
+ isStandalone: false,
66
+ selector: "ng-component",
67
+ ngImport: i0,
68
+ template: "",
69
+ isInline: true,
70
+ changeDetection: i0.ChangeDetectionStrategy.Eager
71
+ });
72
+ }
73
+ };
74
+ i0.ɵɵngDeclareClassMetadata({
75
+ minVersion: "12.0.0",
76
+ version: "22.2.3",
77
+ ngImport: i0,
78
+ type: ModalElementComponent,
79
+ decorators: [{
80
+ type: Component,
81
+ args: [{
82
+ template: "",
83
+ standalone: false,
84
+ changeDetection: ChangeDetectionStrategy.Eager
85
+ }]
86
+ }],
87
+ ctorParameters: () => [
88
+ { type: ModalElementType },
89
+ { type: i0.ElementRef },
90
+ {
91
+ type: ModalElementsAdvertiser,
92
+ decorators: [{ type: Optional }]
93
+ }
94
+ ]
95
+ });
96
+ const COMPONENT_PROPS = new InjectionToken("componentProps");
97
+ var ModalElementsMoverDelegate = class {
98
+ constructor(renderer, elementRef) {
99
+ this.renderer = renderer;
100
+ this.elementRef = elementRef;
101
+ }
102
+ addFooter(footerElementRef) {
103
+ this.moveChild(footerElementRef, this.elementRef);
104
+ }
105
+ removeFooter(footerElementRef) {
106
+ this.removeChild(footerElementRef);
107
+ }
108
+ addPageProgress(pageProgressElementRef, ionToolbarElement) {
109
+ this.moveChild(pageProgressElementRef, ionToolbarElement);
110
+ }
111
+ removePageProgress(pageProgressElementRef) {
112
+ this.removeChild(pageProgressElementRef);
113
+ }
114
+ addTitle(titleElementRef, contentTitleElement, hasCollapsibleTitle, ionTitleElement) {
115
+ this.moveChild(titleElementRef, ionTitleElement);
116
+ if (hasCollapsibleTitle) {
117
+ const titleElementClone = titleElementRef.nativeElement.cloneNode(true);
118
+ this.moveChild(new ElementRef(titleElementClone), contentTitleElement);
119
+ }
120
+ }
121
+ removeTitle(titleElementRef, hasCollapsibleTitle, contentTitleElement) {
122
+ this.removeChild(titleElementRef);
123
+ if (hasCollapsibleTitle) {
124
+ const kirbyPageTitleElement = contentTitleElement.nativeElement.querySelector("kirby-page-title");
125
+ this.removeChild(new ElementRef(kirbyPageTitleElement));
126
+ }
127
+ }
128
+ moveChild(childElementRef, newParentElementRef) {
129
+ const child = childElementRef.nativeElement;
130
+ const newParent = newParentElementRef.nativeElement;
131
+ this.renderer.removeChild(child.parentElement, child);
132
+ this.renderer.appendChild(newParent, child);
133
+ }
134
+ removeChild(childElementRef, parentElement) {
135
+ const child = childElementRef.nativeElement;
136
+ if (child) this.renderer.removeChild(parentElement || child.parentElement, child);
137
+ }
138
+ };
139
+ var AlertComponent = class AlertComponent {
140
+ set title(title) {
141
+ this.title$ = typeof title === "string" ? of(title) : title;
142
+ }
143
+ set message(message) {
144
+ this.message$ = typeof message === "string" ? of(message) : message;
145
+ }
146
+ set okBtn(okBtn) {
147
+ this.okBtn$ = typeof okBtn === "string" ? of(okBtn) : okBtn;
148
+ }
149
+ set cancelBtn(cancelBtn) {
150
+ this.cancelBtn$ = typeof cancelBtn === "string" ? of(cancelBtn) : cancelBtn;
151
+ }
152
+ constructor(elementRef, windowRef) {
153
+ this.elementRef = elementRef;
154
+ this.windowRef = windowRef;
155
+ this.BLUR_WRAPPER_DELAY_IN_MS = 50;
156
+ this.scrollY = Math.abs(this.windowRef.nativeWindow.scrollY);
157
+ }
158
+ ngAfterViewInit() {
159
+ setTimeout(() => {
160
+ this.alertWrapper.nativeElement.focus();
161
+ this.alertWrapper.nativeElement.blur();
162
+ }, this.BLUR_WRAPPER_DELAY_IN_MS);
163
+ }
164
+ onFocusChange() {
165
+ this.windowRef.nativeWindow.scrollTo({ top: this.scrollY });
166
+ }
167
+ onCancel() {
168
+ this.elementRef.nativeElement.closest("ion-modal")?.dismiss(false);
169
+ }
170
+ onOk() {
171
+ this.elementRef.nativeElement.closest("ion-modal")?.dismiss(true);
172
+ }
173
+ static {
174
+ this.ɵfac = i0.ɵɵngDeclareFactory({
175
+ minVersion: "12.0.0",
176
+ version: "22.2.3",
177
+ ngImport: i0,
178
+ type: AlertComponent,
179
+ deps: [{ token: i0.ElementRef }, { token: i1$2.WindowRef }],
180
+ target: i0.ɵɵFactoryTarget.Component
181
+ });
182
+ }
183
+ static {
184
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
185
+ minVersion: "17.0.0",
186
+ version: "22.2.3",
187
+ type: AlertComponent,
188
+ isStandalone: true,
189
+ selector: "kirby-alert",
190
+ inputs: {
191
+ title: "title",
192
+ message: "message",
193
+ iconName: "iconName",
194
+ iconThemeColor: "iconThemeColor",
195
+ okBtn: "okBtn",
196
+ okBtnIsDestructive: "okBtnIsDestructive",
197
+ cancelBtn: "cancelBtn"
198
+ },
199
+ host: { properties: { "class.ion-page": "false" } },
200
+ viewQueries: [{
201
+ propertyName: "alertWrapper",
202
+ first: true,
203
+ predicate: ["alertWrapper"],
204
+ descendants: true,
205
+ static: true
206
+ }],
207
+ ngImport: i0,
208
+ template: "<article #alertWrapper>\n <kirby-empty-state\n [iconName]=\"iconName\"\n [themeColor]=\"iconThemeColor\"\n [title]=\"title$ | async\"\n [subtitle]=\"message$ | async\"\n ></kirby-empty-state>\n <div class=\"buttongroup\">\n @if (cancelBtn$ | async; as cancelBtn) {\n <button kirby-button attentionLevel=\"3\" class=\"cancel-btn\" (click)=\"onCancel()\">\n {{ cancelBtn }}\n </button>\n }\n <button\n kirby-button\n [size]=\"(cancelBtn$ | async) ? null : 'lg'\"\n attentionLevel=\"1\"\n class=\"ok-btn\"\n [class.destructive]=\"okBtnIsDestructive\"\n (click)=\"onOk()\"\n >\n {{ okBtn$ | async }}\n </button>\n </div>\n</article>\n",
209
+ styles: [".kirby-line-clamp{display:-webkit-box;-webkit-line-clamp:var(--line-clamp, none);-webkit-box-orient:vertical;overflow:hidden}article{overflow:hidden;padding:var(--kirby-spacing-s);padding-top:var(--kirby-spacing-m);color:var(--kirby-color-content-base)}@media(max-width:320px){article{padding:var(--kirby-spacing-xxs)}}.buttongroup{display:flex;justify-content:center;column-gap:var(--kirby-spacing-xxs);flex-wrap:wrap}.buttongroup button{flex:0 1 calc(50% - var(--kirby-spacing-xxs) / 2);margin-inline:0}.buttongroup button:not(:only-child){flex-grow:1;min-width:unset}\n"],
210
+ dependencies: [
211
+ {
212
+ kind: "component",
213
+ type: EmptyStateComponent,
214
+ selector: "kirby-empty-state",
215
+ inputs: [
216
+ "iconName",
217
+ "title",
218
+ "subtitle",
219
+ "themeColor"
220
+ ]
221
+ },
222
+ {
223
+ kind: "component",
224
+ type: ButtonComponent,
225
+ selector: "button[kirby-button],Button[kirby-button],a[kirby-button]",
226
+ inputs: [
227
+ "attentionLevel",
228
+ "noDecoration",
229
+ "themeColor",
230
+ "expand",
231
+ "isFloating",
232
+ "size",
233
+ "showIconOnly"
234
+ ]
235
+ },
236
+ {
237
+ kind: "ngmodule",
238
+ type: CommonModule
239
+ },
240
+ {
241
+ kind: "directive",
242
+ type: ThemeColorDirective,
243
+ selector: "kirby-avatar[themeColor], kirby-card[themeColor], kirby-icon[themeColor], kirby-progress-circle-ring[themeColor], kirby-modal-footer[themeColor], kirby-empty-state[themeColor]",
244
+ inputs: ["themeColor"]
245
+ },
246
+ {
247
+ kind: "pipe",
248
+ type: i2.AsyncPipe,
249
+ name: "async"
250
+ }
251
+ ],
252
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
253
+ });
254
+ }
255
+ };
256
+ i0.ɵɵngDeclareClassMetadata({
257
+ minVersion: "12.0.0",
258
+ version: "22.2.3",
259
+ ngImport: i0,
260
+ type: AlertComponent,
261
+ decorators: [{
262
+ type: Component,
263
+ args: [{
264
+ imports: [
265
+ IconComponent,
266
+ EmptyStateComponent,
267
+ ButtonComponent,
268
+ CommonModule,
269
+ ThemeColorDirective
270
+ ],
271
+ selector: "kirby-alert",
272
+ host: { "[class.ion-page]": "false" },
273
+ changeDetection: ChangeDetectionStrategy.OnPush,
274
+ template: "<article #alertWrapper>\n <kirby-empty-state\n [iconName]=\"iconName\"\n [themeColor]=\"iconThemeColor\"\n [title]=\"title$ | async\"\n [subtitle]=\"message$ | async\"\n ></kirby-empty-state>\n <div class=\"buttongroup\">\n @if (cancelBtn$ | async; as cancelBtn) {\n <button kirby-button attentionLevel=\"3\" class=\"cancel-btn\" (click)=\"onCancel()\">\n {{ cancelBtn }}\n </button>\n }\n <button\n kirby-button\n [size]=\"(cancelBtn$ | async) ? null : 'lg'\"\n attentionLevel=\"1\"\n class=\"ok-btn\"\n [class.destructive]=\"okBtnIsDestructive\"\n (click)=\"onOk()\"\n >\n {{ okBtn$ | async }}\n </button>\n </div>\n</article>\n",
275
+ styles: [".kirby-line-clamp{display:-webkit-box;-webkit-line-clamp:var(--line-clamp, none);-webkit-box-orient:vertical;overflow:hidden}article{overflow:hidden;padding:var(--kirby-spacing-s);padding-top:var(--kirby-spacing-m);color:var(--kirby-color-content-base)}@media(max-width:320px){article{padding:var(--kirby-spacing-xxs)}}.buttongroup{display:flex;justify-content:center;column-gap:var(--kirby-spacing-xxs);flex-wrap:wrap}.buttongroup button{flex:0 1 calc(50% - var(--kirby-spacing-xxs) / 2);margin-inline:0}.buttongroup button:not(:only-child){flex-grow:1;min-width:unset}\n"]
276
+ }]
277
+ }],
278
+ ctorParameters: () => [{ type: i0.ElementRef }, { type: i1$2.WindowRef }],
279
+ propDecorators: {
280
+ alertWrapper: [{
281
+ type: ViewChild,
282
+ args: ["alertWrapper", { static: true }]
283
+ }],
284
+ title: [{ type: Input }],
285
+ message: [{ type: Input }],
286
+ iconName: [{ type: Input }],
287
+ iconThemeColor: [{ type: Input }],
288
+ okBtn: [{ type: Input }],
289
+ okBtnIsDestructive: [{ type: Input }],
290
+ cancelBtn: [{ type: Input }]
291
+ }
292
+ });
293
+ var AlertHelper = class AlertHelper {
294
+ constructor(ionicModalController) {
295
+ this.ionicModalController = ionicModalController;
296
+ }
297
+ async showAlert(config) {
298
+ const ionModal = await this.ionicModalController.create({
299
+ component: AlertComponent,
300
+ componentProps: this.getComponentProps(config),
301
+ cssClass: ["kirby-overlay", "kirby-alert"],
302
+ mode: "ios",
303
+ backdropDismiss: false
304
+ });
305
+ await ionModal.present();
306
+ return {
307
+ dismiss: ionModal.dismiss.bind(ionModal),
308
+ onWillDismiss: ionModal.onWillDismiss(),
309
+ onDidDismiss: ionModal.onDidDismiss()
310
+ };
311
+ }
312
+ getComponentProps(config) {
313
+ return {
314
+ ...config,
315
+ okBtn: this.getOkBtn(config),
316
+ okBtnIsDestructive: this.getOkBtnIsDestructive(config),
317
+ iconName: config.icon && config.icon.name,
318
+ iconThemeColor: config.icon && config.icon.themeColor
319
+ };
320
+ }
321
+ getOkBtn(config) {
322
+ let text;
323
+ if (config.okBtn) {
324
+ if (typeof config.okBtn === "string" || isObservable(config.okBtn)) text = config.okBtn;
325
+ else text = config.okBtn?.text;
326
+ }
327
+ return text;
328
+ }
329
+ getOkBtnIsDestructive(config) {
330
+ return typeof config.okBtn === "object" ? config.okBtn.isDestructive : void 0;
331
+ }
332
+ static {
333
+ this.ɵfac = i0.ɵɵngDeclareFactory({
334
+ minVersion: "12.0.0",
335
+ version: "22.2.3",
336
+ ngImport: i0,
337
+ type: AlertHelper,
338
+ deps: [{ token: i1$1.ModalController }],
339
+ target: i0.ɵɵFactoryTarget.Injectable
340
+ });
341
+ }
342
+ static {
343
+ this.ɵprov = i0.ɵɵngDeclareInjectable({
344
+ minVersion: "12.0.0",
345
+ version: "22.2.3",
346
+ ngImport: i0,
347
+ type: AlertHelper
348
+ });
349
+ }
350
+ };
351
+ i0.ɵɵngDeclareClassMetadata({
352
+ minVersion: "12.0.0",
353
+ version: "22.2.3",
354
+ ngImport: i0,
355
+ type: AlertHelper,
356
+ decorators: [{ type: Injectable }],
357
+ ctorParameters: () => [{ type: i1$1.ModalController }]
358
+ });
359
+ var CanDismissHelper = class CanDismissHelper {
360
+ constructor(alertHelper) {
361
+ this.alertHelper = alertHelper;
362
+ }
363
+ getCanDismissCallback(callback) {
364
+ return async () => {
365
+ const result = await callback();
366
+ if (typeof result === "boolean") return result;
367
+ return await this.showAlert(result);
368
+ };
369
+ }
370
+ async showAlert(config) {
371
+ return (await (await this.alertHelper.showAlert(config)).onWillDismiss).data;
372
+ }
373
+ static {
374
+ this.ɵfac = i0.ɵɵngDeclareFactory({
375
+ minVersion: "12.0.0",
376
+ version: "22.2.3",
377
+ ngImport: i0,
378
+ type: CanDismissHelper,
379
+ deps: [{ token: AlertHelper }],
380
+ target: i0.ɵɵFactoryTarget.Injectable
381
+ });
382
+ }
383
+ static {
384
+ this.ɵprov = i0.ɵɵngDeclareInjectable({
385
+ minVersion: "12.0.0",
386
+ version: "22.2.3",
387
+ ngImport: i0,
388
+ type: CanDismissHelper
389
+ });
390
+ }
391
+ };
392
+ i0.ɵɵngDeclareClassMetadata({
393
+ minVersion: "12.0.0",
394
+ version: "22.2.3",
395
+ ngImport: i0,
396
+ type: CanDismissHelper,
397
+ decorators: [{ type: Injectable }],
398
+ ctorParameters: () => [{ type: AlertHelper }]
399
+ });
272
400
  const contentScrollDebounceTimeInMS = 10;
273
401
  const contentScrolledOffsetInPixels = 4;
274
- class ModalWrapperComponent {
275
- get _hasCollapsibleTitle() {
276
- return !!this.config?.collapseTitle;
277
- }
278
- static { this.KEYBOARD_HIDE_DELAY_IN_MS = 100; }
279
- set scrollDisabled(disabled) {
280
- this.ionContent.scrollY = !disabled;
281
- }
282
- set canDismiss(callback) {
283
- this.ionModalElement.canDismiss = this.canDismissHelper.getCanDismissCallback(callback);
284
- }
285
- get contentTitleElement() {
286
- /*
287
- contentTitleElement has ngIf directive dependent on _hasCollapsibleTitle; trigger CD to make sure element has been queried.
288
- Solution taken from: https://danieleyassu.com/angular-viewchild-and-ngif/
289
- */
290
- if (!this._contentTitleElement && this._hasCollapsibleTitle) {
291
- this.changeDetector.detectChanges();
292
- }
293
- return this._contentTitleElement;
294
- }
295
- get intersectionObserver() {
296
- if (!this._intersectionObserver) {
297
- this._intersectionObserver = this.createModalWrapperIntersectionObserver();
298
- }
299
- return this._intersectionObserver;
300
- }
301
- get _isDrawer() {
302
- return this.config.flavor === 'drawer';
303
- }
304
- constructor(changeDetector, injector, elementRef, renderer, zone, resizeObserverService, windowRef, platform, canDismissHelper, environmentInjector, translations) {
305
- this.changeDetector = changeDetector;
306
- this.injector = injector;
307
- this.elementRef = elementRef;
308
- this.renderer = renderer;
309
- this.zone = zone;
310
- this.resizeObserverService = resizeObserverService;
311
- this.windowRef = windowRef;
312
- this.platform = platform;
313
- this.canDismissHelper = canDismissHelper;
314
- this.environmentInjector = environmentInjector;
315
- this.translations = translations;
316
- this.scrollY = Math.abs(this.windowRef.nativeWindow.scrollY);
317
- this.VIEWPORT_RESIZE_DEBOUNCE_TIME = 100;
318
- this.keyboardVisible = false;
319
- this.toolbarButtons = [];
320
- this.delayedClose = () => { };
321
- this.viewportResized = false;
322
- this.ionModalDidPresent = new Subject();
323
- this.didPresent = firstValueFrom(this.ionModalDidPresent);
324
- this.ionModalWillDismiss = new Subject();
325
- this.willClose = firstValueFrom(this.ionModalWillDismiss);
326
- this.viewportResize = new Subject();
327
- this.viewportResize$ = this.viewportResize
328
- .asObservable()
329
- .pipe(debounceTime(this.VIEWPORT_RESIZE_DEBOUNCE_TIME));
330
- this.destroy$ = new Subject();
331
- this.willClose$ = this.ionModalWillDismiss.pipe(first());
332
- this._currentFooter = null;
333
- this.setAriaLabelFromTitleContent = () => {
334
- const titleTextContent = this.ionTitleElement?.nativeElement.textContent;
335
- if (this.ionModalDialog && titleTextContent) {
336
- this.renderer.setAttribute(this.ionModalDialog, 'aria-label', titleTextContent);
337
- }
338
- };
339
- this.setViewportHeight();
340
- this.observeViewportResize();
341
- this.modalElementsMoverDelegate = new ModalElementsMoverDelegate(renderer, elementRef);
342
- }
343
- ngOnInit() {
344
- this.ionModalElement = this.elementRef.nativeElement.closest('ion-modal');
345
- this.ionModalDialog = getIonModalDialogAncestor(this.elementRef.nativeElement);
346
- this.initializeSizing();
347
- this.initializeModalRoute();
348
- this.listenForIonModalDidPresent();
349
- this.listenForIonModalWillDismiss();
350
- this.listenForScroll();
351
- this.initializeResizeModalToModalWrapper();
352
- this.focusTitleOnDidPresent();
353
- this.componentPropsInjector = Injector.create({
354
- providers: [{ provide: COMPONENT_PROPS, useValue: this.config.componentProps }],
355
- parent: this.injector,
356
- });
357
- this.modalWrapperInjector = Injector.create({
358
- providers: [{ provide: ModalElementsAdvertiser, useExisting: ModalWrapperComponent }],
359
- parent: this.injector,
360
- });
361
- }
362
- ngAfterViewInit() {
363
- if (this.toolbarButtonsQuery) {
364
- this.toolbarButtons = this.toolbarButtonsQuery.map((buttonRef) => buttonRef.nativeElement);
365
- }
366
- this.setAriaLabel();
367
- }
368
- set currentFooter(footer) {
369
- if (this._currentFooter) {
370
- this.resizeObserverService.unobserve(this._currentFooter);
371
- }
372
- this._currentFooter = footer;
373
- if (footer !== null) {
374
- this.resizeObserverService.observe(footer, (entry) => {
375
- const [property, pixelValue] = [
376
- '--footer-height',
377
- `${Math.floor(entry.contentRect.height)}px`,
378
- ];
379
- this.setCssVar(this.elementRef.nativeElement, property, pixelValue);
380
- });
381
- }
382
- }
383
- get currentFooter() {
384
- return this._currentFooter;
385
- }
386
- addModalElement(type, modalElement) {
387
- const addModalElementFn = {
388
- [ModalElementType.FOOTER]: () => {
389
- this.modalElementsMoverDelegate.addFooter(modalElement);
390
- this.currentFooter = modalElement.nativeElement;
391
- },
392
- [ModalElementType.TITLE]: () => this.modalElementsMoverDelegate.addTitle(modalElement, this.contentTitleElement, this._hasCollapsibleTitle, this.ionTitleElement),
393
- [ModalElementType.PAGE_PROGRESS]: () => this.modalElementsMoverDelegate.addPageProgress(modalElement, this.ionToolbarElement),
394
- }[type];
395
- addModalElementFn();
396
- }
397
- removeModalElement(type, modalElement) {
398
- const removeModalElementFn = {
399
- [ModalElementType.FOOTER]: () => {
400
- this.modalElementsMoverDelegate.removeFooter(modalElement);
401
- this.currentFooter = null;
402
- },
403
- [ModalElementType.TITLE]: () => this.modalElementsMoverDelegate.removeTitle(modalElement, this._hasCollapsibleTitle, this.contentTitleElement),
404
- [ModalElementType.PAGE_PROGRESS]: () => this.modalElementsMoverDelegate.removePageProgress(modalElement),
405
- }[type];
406
- removeModalElementFn();
407
- }
408
- initializeResizeModalToModalWrapper() {
409
- if (this.config.flavor === 'drawer' && this.config.interactWithBackground) {
410
- merge(this.ionModalDidPresent, this.viewportResize$)
411
- .pipe(takeUntil(this.destroy$))
412
- .subscribe(() => {
413
- // wait for template to render
414
- setTimeout(() => {
415
- const domRect = this.elementRef.nativeElement.getBoundingClientRect();
416
- const document = this.windowRef.nativeWindow.document.documentElement;
417
- const right = document.clientWidth - domRect.right;
418
- this.renderer.setStyle(this.ionModalElement, 'top', `${domRect.top}px`);
419
- this.renderer.setStyle(this.ionModalElement, 'left', `${domRect.left}px`);
420
- this.renderer.setStyle(this.ionModalElement, 'right', `${right}px`);
421
- });
422
- });
423
- }
424
- }
425
- initializeSizing() {
426
- if (this.config.size === 'full-height')
427
- return;
428
- this.patchScrollElementSize();
429
- this.observeHeaderResize();
430
- this.observeModalFullHeight();
431
- }
432
- initializeModalRoute() {
433
- if (this.config.modalRoute) {
434
- this.onSiblingModalRouteActivated(this.config.siblingModalRouteActivated$);
435
- // Load component from modal-route inside router-outlet:
436
- this.routerOutlet.activateWith(this.config.modalRoute, this.environmentInjector);
437
- }
438
- }
439
- onSiblingModalRouteActivated(siblingModalRouteActivated$) {
440
- if (!siblingModalRouteActivated$)
441
- return;
442
- siblingModalRouteActivated$.pipe(takeUntil(this.willClose$)).subscribe((route) => {
443
- if (this.routerOutlet.isActivated) {
444
- this.routerOutlet.deactivate();
445
- }
446
- this.routerOutlet.activateWith(route, this.environmentInjector);
447
- this.focusTitle();
448
- });
449
- }
450
- patchScrollElementSize() {
451
- const supportsCssShadowParts = 'part' in HTMLElement.prototype;
452
- if (supportsCssShadowParts)
453
- return;
454
- this.ionContent.getScrollElement().then((scrollElement) => {
455
- this.renderer.setStyle(scrollElement, 'height', '100%');
456
- this.renderer.setStyle(scrollElement, 'position', 'relative');
457
- if (this.config.flavor === 'drawer') {
458
- this.renderer.setStyle(scrollElement, 'transition', 'padding-bottom ' + DesignTokenHelper.softKeyboardTransitionLeave);
459
- }
460
- });
461
- }
462
- observeModalFullHeight() {
463
- const ionModalWrapper = this.getIonModalWrapperElement();
464
- if (!ionModalWrapper)
465
- return;
466
- // Start observing when modal has finished animating:
467
- this.didPresent.then(() => {
468
- this.intersectionObserver.observe(ionModalWrapper);
469
- });
470
- }
471
- // Extracted into function for ease of testing
472
- getIonModalWrapperElement() {
473
- return this.ionModalElement.shadowRoot.querySelector('.modal-wrapper');
474
- }
475
- observeHeaderResize() {
476
- this.resizeObserverService.observe(this.ionHeaderElement.nativeElement, (entry) => {
477
- const [property, pixelValue] = ['--header-height', `${entry.contentRect.height}px`];
478
- this.setCssVar(this.elementRef.nativeElement, property, pixelValue);
479
- });
480
- }
481
- listenForIonModalDidPresent() {
482
- if (this.ionModalElement) {
483
- this.ionModalElement.addEventListener('ionModalDidPresent', () => {
484
- this.ionModalDidPresent.next();
485
- this.ionModalDidPresent.complete();
486
- });
487
- }
488
- }
489
- listenForIonModalWillDismiss() {
490
- if (this.ionModalElement) {
491
- this.ionModalElement.addEventListener('ionModalWillDismiss', () => {
492
- this.ionModalWillDismiss.next();
493
- this.ionModalWillDismiss.complete();
494
- });
495
- }
496
- }
497
- listenForScroll() {
498
- const query = `(min-width: ${DesignTokenHelper.breakpoints.medium})`;
499
- const mediaQuery = this.windowRef.nativeWindow.matchMedia(query);
500
- const enableScrollEvents = (listOrEvent) => {
501
- const isDesktop = listOrEvent.matches;
502
- this.scrollEventsEnabled = !isDesktop;
503
- };
504
- enableScrollEvents(mediaQuery);
505
- mediaQuery.onchange = enableScrollEvents;
506
- // Runs scroll subscription outside zone to avoid excessive amount of CD cycles
507
- // when ionScroll emits.
508
- this.zone.runOutsideAngular(() => {
509
- // Always subscribe as ionScroll only emits when scrollEventsEnabled is true
510
- this.ionContent.ionScroll
511
- .pipe(debounceTime(contentScrollDebounceTimeInMS), map((event) => event.detail), takeUntil(this.destroy$))
512
- .subscribe((scrollInfo) => {
513
- const contentScrolledPastOffset = scrollInfo.scrollTop > contentScrolledOffsetInPixels;
514
- if (contentScrolledPastOffset !== this.isContentScrolled) {
515
- this.isContentScrolled = contentScrolledPastOffset;
516
- this.changeDetector.detectChanges();
517
- }
518
- });
519
- });
520
- }
521
- observeTitleContentChanges() {
522
- this.mutationObserverUnobserveFn = observeContent(this.ionTitleElement.nativeElement, this.setAriaLabelFromTitleContent);
523
- }
524
- setAriaLabel() {
525
- const ariaLabel = this.config.htmlAttributes?.['aria-label'];
526
- const ionModalElementDialog = getIonModalDialogAncestor(this.ionModalElement);
527
- if (ionModalElementDialog && ariaLabel) {
528
- this.renderer.setAttribute(ionModalElementDialog, 'aria-label', ariaLabel);
529
- }
530
- else {
531
- this.setAriaLabelFromTitleContent();
532
- this.observeTitleContentChanges();
533
- }
534
- }
535
- focusTitleOnDidPresent() {
536
- this.ionModalDidPresent.pipe(takeUntil(this.willClose$)).subscribe(() => {
537
- this.focusTitle();
538
- });
539
- }
540
- focusTitle() {
541
- // Use queueMicrotask to defer our focus until after Ionic has saved a reference
542
- // to the element that should have focus restored when modal is closed.
543
- // https://github.com/ionic-team/ionic-framework/blob/v8.6.1/core/src/utils/overlays.ts#L592
544
- queueMicrotask(() => {
545
- const focusAlreadyInModalContent = this.ionContentElement?.nativeElement.contains(document.activeElement);
546
- if (focusAlreadyInModalContent)
547
- return;
548
- this.ionTitleElement?.nativeElement.focus();
549
- });
550
- }
551
- scrollToTop(scrollDuration) {
552
- this.ionContent.scrollToTop(scrollDuration || 0);
553
- }
554
- scrollToBottom(scrollDuration) {
555
- this.ionContent.scrollToBottom(scrollDuration || 0);
556
- }
557
- async close(data) {
558
- if (!this.ionModalElement) {
559
- return;
560
- }
561
- if (!this.keyboardVisible || !this.viewportResized) {
562
- // No keyboard visible or viewport not resized:
563
- // Dismiss modal and return:
564
- clearTimeout(this.delayedCloseTimeoutId);
565
- await this.ionModalElement.dismiss(data);
566
- return;
567
- }
568
- // Keyboard visible:
569
- // Blur active element and wait for keyboard to hide,
570
- // then dismiss modal and return:
571
- this.blurActiveElement();
572
- return new Promise((resolve) => {
573
- this.delayedClose = async () => {
574
- await this.ionModalElement.dismiss(data);
575
- resolve();
576
- };
577
- this.delayedCloseTimeoutId = setTimeout(this.delayedClose, ModalWrapperComponent.KEYBOARD_HIDE_DELAY_IN_MS);
578
- });
579
- }
580
- onFocusChange() {
581
- // This fixes an undesired scroll behaviour occurring on keyboard-tabbing backwards (with shift+tab):
582
- this.windowRef.nativeWindow.scrollTo({ top: this.scrollY });
583
- }
584
- _onKeyboardShow(keyboardHeight) {
585
- this.setKeyboardVisibility(keyboardHeight);
586
- }
587
- _onKeyboardHide() {
588
- this.setKeyboardVisibility(0);
589
- }
590
- toggleContentMaxHeight(freeze) {
591
- const shouldToggleMaxHeight = this.config.flavor === 'modal' && this.platform.isPhabletOrBigger();
592
- if (!shouldToggleMaxHeight)
593
- return;
594
- const style = 'max-height';
595
- const contentElement = this.ionContentElement.nativeElement;
596
- this.zone.run(() => {
597
- if (freeze) {
598
- const contentHeight = contentElement.offsetHeight;
599
- this.renderer.setStyle(contentElement, style, `${contentHeight}px`);
600
- }
601
- else {
602
- this.renderer.removeStyle(contentElement, style);
603
- }
604
- });
605
- }
606
- setKeyboardVisibility(keyboardHeight) {
607
- const keyboardAlreadyVisible = keyboardHeight > 0 && this.keyboardVisible;
608
- const keyboardAlreadyHidden = keyboardHeight === 0 && !this.keyboardVisible;
609
- if (keyboardAlreadyVisible || keyboardAlreadyHidden)
610
- return;
611
- this.keyboardVisible = keyboardHeight > 0;
612
- this.toggleContentMaxHeight(this.keyboardVisible);
613
- this.setKeyboardOverlap(keyboardHeight);
614
- }
615
- // Fall back to the live viewport height: initialViewportHeight (from a body ResizeObserver) is 0 in Ionic apps.
616
- getViewportHeight() {
617
- return this.initialViewportHeight || this.windowRef.nativeWindow.innerHeight;
618
- }
619
- getKeyboardOverlap(keyboardHeight, element) {
620
- const viewportHeight = this.getViewportHeight();
621
- if (keyboardHeight <= 0 || !element || !viewportHeight)
622
- return 0;
623
- const elementDistanceAboveBottomOfScreen = Math.floor(viewportHeight - element.getBoundingClientRect().bottom);
624
- return Math.max(keyboardHeight - elementDistanceAboveBottomOfScreen, 0);
625
- }
626
- setCssVar(element, property, value) {
627
- this.zone.run(() => this.renderer.setStyle(element, property, value, RendererStyleFlags2.DashCase));
628
- }
629
- toggleCssClass(element, klass, condition) {
630
- this.zone.run(() => condition ? this.renderer.addClass(element, klass) : this.renderer.removeClass(element, klass));
631
- }
632
- setKeyboardOverlap(keyboardHeight) {
633
- this.toggleCssClass(this.elementRef.nativeElement, 'keyboard-visible', keyboardHeight > 0);
634
- const keyboardOverlap = this.getKeyboardOverlap(keyboardHeight, this.elementRef.nativeElement);
635
- let snapFooterToKeyboard = false;
636
- const embeddedFooterElement = this.currentFooter;
637
- if (embeddedFooterElement) {
638
- this.setCssVar(embeddedFooterElement, '--keyboard-offset', `${keyboardOverlap}px`);
639
- snapFooterToKeyboard = embeddedFooterElement.classList.contains('snap-to-keyboard');
640
- }
641
- const contentElement = this.ionContentElement.nativeElement;
642
- const contentKeyboardOffset = snapFooterToKeyboard
643
- ? keyboardOverlap
644
- : this.getKeyboardOverlap(keyboardHeight, contentElement);
645
- this.setCssVar(contentElement, '--keyboard-offset', `${contentKeyboardOffset}px`);
646
- }
647
- onHeaderTouchStart(event) {
648
- if (this.keyboardVisible) {
649
- const isToolbarButtonTouch = this.toolbarButtons.some((button) => {
650
- return (event.target instanceof HTMLElement &&
651
- (event.target === button || button.contains(event.target)));
652
- });
653
- // Prevent blur if event target is a toolbar button
654
- // (to allow tap event to fire):
655
- if (!isToolbarButtonTouch) {
656
- this.blurActiveElement();
657
- }
658
- }
659
- }
660
- _onWindowResize() {
661
- this.setViewportHeight();
662
- }
663
- setViewportHeight() {
664
- const vh = (this.windowRef.nativeWindow.innerHeight * 0.01).toFixed(2);
665
- this.setCssVar(this.elementRef.nativeElement, '--vh', `${vh}px`);
666
- }
667
- observeViewportResize() {
668
- this.resizeObserverService.observe(this.windowRef.nativeWindow.document.body, (entry) => this.onViewportResize(entry));
669
- }
670
- onViewportResize(entry) {
671
- if (!this.initialViewportHeight) {
672
- // Initial observe callback, register initial height:
673
- this.initialViewportHeight = entry.contentRect.height;
674
- return;
675
- }
676
- this.viewportResized = entry.contentRect.height !== this.initialViewportHeight;
677
- if (!this.viewportResized) {
678
- // We are back to initial view port height, check for pending close func:
679
- if (this.delayedCloseTimeoutId) {
680
- clearTimeout(this.delayedCloseTimeoutId);
681
- this.delayedClose();
682
- }
683
- }
684
- this.viewportResize.next();
685
- }
686
- blurActiveElement() {
687
- const BLUR_TARGET_SELECTOR = 'input, textarea';
688
- if (this.keyboardVisible) {
689
- if (document.activeElement instanceof HTMLElement &&
690
- document.activeElement.matches(BLUR_TARGET_SELECTOR)) {
691
- document.activeElement.blur();
692
- }
693
- }
694
- }
695
- createModalWrapperIntersectionObserver() {
696
- const callback = (entries) => {
697
- const entry = entries[0];
698
- const isTouchingViewport = entry.intersectionRatio < 1;
699
- if (isTouchingViewport) {
700
- this.ionModalElement.classList.add('full-height');
701
- }
702
- else {
703
- this.ionModalElement.classList.remove('full-height');
704
- }
705
- };
706
- // Set explicit viewport root if within iframe:
707
- const root = this.windowRef.nativeWindow.frameElement
708
- ? this.windowRef.nativeWindow.document // Cast to `any` as Typescript lib.d.ts doesnt support Document type yet
709
- : undefined;
710
- const options = {
711
- rootMargin: '0px 0px -1px 0px', // `bottom: -1px` allows checking when the modal bottom is touching the viewport
712
- root,
713
- threshold: [0.99, 1],
714
- };
715
- return new IntersectionObserver(callback, options);
716
- }
717
- ngOnDestroy() {
718
- if (this.routerOutlet.isActivated) {
719
- this.routerOutlet.deactivate();
720
- }
721
- //clean up the observer
722
- this.mutationObserverUnobserveFn?.();
723
- this.intersectionObserver.disconnect();
724
- delete this._intersectionObserver;
725
- if (this.resizeObserverService) {
726
- this.resizeObserverService.unobserve(this.windowRef.nativeWindow.document.body);
727
- this.resizeObserverService.unobserve(this.ionHeaderElement.nativeElement);
728
- this.resizeObserverService.unobserve(this.currentFooter);
729
- }
730
- this.destroy$.next();
731
- this.destroy$.complete();
732
- }
733
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ModalWrapperComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.Injector }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.NgZone }, { token: i1$2.ResizeObserverService }, { token: i1.WindowRef }, { token: i3.PlatformService }, { token: CanDismissHelper }, { token: i0.EnvironmentInjector }, { token: i1$2.TranslationService }], target: i0.ɵɵFactoryTarget.Component }); }
734
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: ModalWrapperComponent, isStandalone: true, selector: "kirby-modal-wrapper", inputs: { scrollDisabled: "scrollDisabled", config: "config", content: "content" }, host: { listeners: { "window:focus": "onFocusChange()", "window:focusout": "onFocusChange()", "window:ionKeyboardDidShow": "_onKeyboardShow($event.detail.keyboardHeight)", "window:keyboardWillShow": "_onKeyboardShow($event.keyboardHeight)", "window:ionKeyboardDidHide": "_onKeyboardHide()", "window:keyboardWillHide": "_onKeyboardHide()", "window:resize": "_onWindowResize()" }, properties: { "class.collapsible-title": "this._hasCollapsibleTitle", "class.drawer": "this._isDrawer" } }, providers: [
735
- { provide: Modal, useExisting: ModalWrapperComponent },
736
- { provide: ModalElementsAdvertiser, useExisting: ModalWrapperComponent },
737
- ], queries: [{ propertyName: "templateRef", first: true, predicate: TemplateRef, descendants: true }], viewQueries: [{ propertyName: "ionContent", first: true, predicate: IonContent, descendants: true, static: true }, { propertyName: "ionContentElement", first: true, predicate: IonContent, descendants: true, read: ElementRef, static: true }, { propertyName: "ionHeaderElement", first: true, predicate: IonHeader, descendants: true, read: ElementRef, static: true }, { propertyName: "ionToolbarElement", first: true, predicate: IonToolbar, descendants: true, read: ElementRef, static: true }, { propertyName: "ionTitleElement", first: true, predicate: IonTitle, descendants: true, read: ElementRef, static: true }, { propertyName: "routerOutlet", first: true, predicate: RouterOutlet, descendants: true, static: true }, { propertyName: "_contentTitleElement", first: true, predicate: ["contentTitle"], descendants: true, read: ElementRef }, { propertyName: "toolbarButtonsQuery", predicate: ButtonComponent, descendants: true, read: ElementRef }], ngImport: i0, template: "<ion-header\n role=\"presentation\"\n [class.content-scrolled]=\"isContentScrolled\"\n (touchstart)=\"onHeaderTouchStart($event)\"\n>\n <ion-toolbar>\n <ion-title role=\"heading\" aria-level=\"2\" tabindex=\"-1\"></ion-title>\n @if (config.flavor === 'drawer' && config.drawerSupplementaryAction) {\n <ion-buttons slot=\"secondary\">\n <button\n kirby-button\n attentionLevel=\"3\"\n size=\"md\"\n (click)=\"config.drawerSupplementaryAction.action($event)\"\n >\n <kirby-icon [name]=\"config.drawerSupplementaryAction.iconName\"></kirby-icon>\n </button>\n </ion-buttons>\n }\n <ion-buttons slot=\"primary\">\n <button\n kirby-button\n attentionLevel=\"3\"\n size=\"md\"\n [noDecoration]=\"config.interactWithBackground\"\n [attr.aria-label]=\"translations.get('close')\"\n (click)=\"close()\"\n >\n <kirby-icon name=\"close\"></kirby-icon>\n </button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n<ion-content [scrollEvents]=\"scrollEventsEnabled\">\n @if (_hasCollapsibleTitle) {\n <ion-header collapse=\"condense\">\n <ion-toolbar>\n <span class=\"kirby-text-xlarge\" #contentTitle></span>\n </ion-toolbar>\n </ion-header>\n }\n\n <!-- Outlet for ModalController -->\n <ng-container\n *ngComponentOutlet=\"config.component; injector: componentPropsInjector\"\n ></ng-container>\n\n <!-- Outlet for projected content -->\n <ng-container *ngTemplateOutlet=\"content; injector: modalWrapperInjector\"></ng-container>\n\n <!-- Outlet for route-based modal -->\n <router-outlet\n name=\"kirbyModalWrapperOutlet\"\n [style.visibility]=\"config.modalRoute ? 'visible' : 'hidden'\"\n ></router-outlet>\n</ion-content>\n", styles: [".kirby-line-clamp{display:-webkit-box;-webkit-line-clamp:var(--line-clamp, none);-webkit-box-orient:vertical;overflow:hidden}ion-header{box-sizing:border-box}ion-header ion-toolbar{--padding-start: 8px;--padding-end: 8px;--padding-bottom: 7px;--padding-top: 8px;--border-width: 0;--background: transparent;--color: var(--kirby-modal-color, var(--kirby-black));border-bottom:1px solid transparent;transition:border-color .2s linear}@media(min-width:768px){ion-header ion-toolbar{--padding-start: 24px;--padding-end: 24px;--padding-bottom: 23px;--padding-top: 24px;padding-inline:0}}ion-header ion-toolbar button{color:var(--color)}:host{--vh100: var(--vh, 1vh) * 100;--header-height: 0px;--footer-height: 0px;--kirby-modal-safe-area-bottom: var(--ion-safe-area-bottom)}@media(max-width:767px){:host.drawer ion-header ion-toolbar{--padding-top: 16px}:host.drawer ion-header ion-toolbar:first-of-type{padding-top:0}}@media(min-width:768px){ion-header ion-toolbar{border-bottom-color:var(--kirby-medium)}}ion-header.content-scrolled ion-toolbar{border-bottom-color:var(--kirby-medium)}:host-context(ion-modal.no-header-area-border) ion-header ion-toolbar{border-bottom-color:transparent}@media(max-width:767px){:host-context(ion-modal.kirby-drawer:not(.kirby-modal-full-height)){padding-top:0;position:relative;contain:inherit;min-height:min(var(--min-height),var(--vh100) - var(--kirby-modal-padding-top, 0px))}:host-context(ion-modal.kirby-drawer:not(.kirby-modal-full-height)) ion-content{contain:content;max-height:calc(var(--vh100) - var(--kirby-modal-padding-top, 0px) - var(--header-height) - var(--footer-height))}:host-context(ion-modal.kirby-drawer:not(.kirby-modal-full-height)) ion-content::part(scroll){height:\"100%\";position:relative}:host-context(ion-modal.kirby-drawer:not(.kirby-modal-full-height)).drawer ion-content::part(scroll){transition:padding-bottom .15s ease-out}:host-context(ion-modal.kirby-drawer:not(.kirby-modal-full-height)).drawer.keyboard-visible ion-content::part(scroll){transition:padding-bottom .25s ease-out 1ms}}:host-context(ion-modal.kirby-drawer.interact-with-background){padding-top:0;position:relative;contain:inherit;min-height:min(var(--min-height),var(--vh100) - var(--kirby-modal-padding-top, 0px))}:host-context(ion-modal.kirby-drawer.interact-with-background) ion-content{contain:content;max-height:calc(var(--vh100) - var(--kirby-modal-padding-top, 0px) - var(--header-height) - var(--footer-height))}:host-context(ion-modal.kirby-drawer.interact-with-background) ion-content::part(scroll){height:\"100%\";position:relative}:host-context(ion-modal.kirby-drawer.interact-with-background).drawer ion-content::part(scroll){transition:padding-bottom .15s ease-out}:host-context(ion-modal.kirby-drawer.interact-with-background).drawer.keyboard-visible ion-content::part(scroll){transition:padding-bottom .25s ease-out 1ms}:host-context(ion-modal.kirby-drawer.interact-with-background) ion-header ion-toolbar{border-bottom-color:transparent}:host-context(ion-modal.modal-card:not(.kirby-drawer)) ion-header ion-toolbar:first-of-type{padding-top:var(--kirby-safe-area-top, 0)}@media(min-width:768px){:host-context(ion-modal.modal-card:not(.kirby-drawer)) ion-header ion-toolbar:first-of-type{--padding-start: 24px;--padding-end: 24px;--padding-bottom: 23px;--padding-top: 24px;padding-inline:0}}ion-title{box-sizing:border-box;padding-inline:calc(48px + var(--padding-start)) calc(48px + var(--padding-end));font-size:clamp(13px,1rem,32px);font-weight:700;outline:none}ion-content{--background: transparent;--color: var(--kirby-modal-color, var(--kirby-black));--padding-top: 24px;--padding-bottom: calc(var(--kirby-spacing-m) + var(--kirby-modal-safe-area-bottom));--padding-start: 16px;--padding-end: 16px;display:flex;flex-direction:column;height:calc(var(--height) - var(--header-height) - var(--footer-height));max-height:calc(var(--max-height) - var(--header-height) - var(--footer-height))}ion-content ::ng-deep>*{box-sizing:border-box;display:block}:host(:has(kirby-modal-footer)) ion-content{--padding-bottom: var(--kirby-spacing-m)}@media(min-width:768px){ion-content{--padding-start: 48px;--padding-end: 48px}}:host(.collapsible-title) ion-content ion-toolbar:first-of-type{--padding-top: 0px;--padding-bottom: 32px;--padding-start: 8px;--padding-end: 8px;border:none}@media(min-width:768px){:host(.collapsible-title) ion-content ion-toolbar:first-of-type{--padding-start: 16px;--padding-end: 16px}}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$3.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: ButtonComponent, selector: "button[kirby-button],Button[kirby-button],a[kirby-button]", inputs: ["attentionLevel", "noDecoration", "themeColor", "expand", "isFloating", "size", "showIconOnly"] }, { kind: "component", type: IconComponent, selector: "kirby-icon", inputs: ["size", "name"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i6.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }] }); }
738
- }
739
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ModalWrapperComponent, decorators: [{
740
- type: Component,
741
- args: [{ imports: [
742
- RouterModule,
743
- ButtonComponent,
744
- IconComponent,
745
- CommonModule,
746
- IonHeader,
747
- IonToolbar,
748
- IonTitle,
749
- IonButtons,
750
- IonContent,
751
- ], selector: 'kirby-modal-wrapper', providers: [
752
- { provide: Modal, useExisting: ModalWrapperComponent },
753
- { provide: ModalElementsAdvertiser, useExisting: ModalWrapperComponent },
754
- ], template: "<ion-header\n role=\"presentation\"\n [class.content-scrolled]=\"isContentScrolled\"\n (touchstart)=\"onHeaderTouchStart($event)\"\n>\n <ion-toolbar>\n <ion-title role=\"heading\" aria-level=\"2\" tabindex=\"-1\"></ion-title>\n @if (config.flavor === 'drawer' && config.drawerSupplementaryAction) {\n <ion-buttons slot=\"secondary\">\n <button\n kirby-button\n attentionLevel=\"3\"\n size=\"md\"\n (click)=\"config.drawerSupplementaryAction.action($event)\"\n >\n <kirby-icon [name]=\"config.drawerSupplementaryAction.iconName\"></kirby-icon>\n </button>\n </ion-buttons>\n }\n <ion-buttons slot=\"primary\">\n <button\n kirby-button\n attentionLevel=\"3\"\n size=\"md\"\n [noDecoration]=\"config.interactWithBackground\"\n [attr.aria-label]=\"translations.get('close')\"\n (click)=\"close()\"\n >\n <kirby-icon name=\"close\"></kirby-icon>\n </button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n<ion-content [scrollEvents]=\"scrollEventsEnabled\">\n @if (_hasCollapsibleTitle) {\n <ion-header collapse=\"condense\">\n <ion-toolbar>\n <span class=\"kirby-text-xlarge\" #contentTitle></span>\n </ion-toolbar>\n </ion-header>\n }\n\n <!-- Outlet for ModalController -->\n <ng-container\n *ngComponentOutlet=\"config.component; injector: componentPropsInjector\"\n ></ng-container>\n\n <!-- Outlet for projected content -->\n <ng-container *ngTemplateOutlet=\"content; injector: modalWrapperInjector\"></ng-container>\n\n <!-- Outlet for route-based modal -->\n <router-outlet\n name=\"kirbyModalWrapperOutlet\"\n [style.visibility]=\"config.modalRoute ? 'visible' : 'hidden'\"\n ></router-outlet>\n</ion-content>\n", styles: [".kirby-line-clamp{display:-webkit-box;-webkit-line-clamp:var(--line-clamp, none);-webkit-box-orient:vertical;overflow:hidden}ion-header{box-sizing:border-box}ion-header ion-toolbar{--padding-start: 8px;--padding-end: 8px;--padding-bottom: 7px;--padding-top: 8px;--border-width: 0;--background: transparent;--color: var(--kirby-modal-color, var(--kirby-black));border-bottom:1px solid transparent;transition:border-color .2s linear}@media(min-width:768px){ion-header ion-toolbar{--padding-start: 24px;--padding-end: 24px;--padding-bottom: 23px;--padding-top: 24px;padding-inline:0}}ion-header ion-toolbar button{color:var(--color)}:host{--vh100: var(--vh, 1vh) * 100;--header-height: 0px;--footer-height: 0px;--kirby-modal-safe-area-bottom: var(--ion-safe-area-bottom)}@media(max-width:767px){:host.drawer ion-header ion-toolbar{--padding-top: 16px}:host.drawer ion-header ion-toolbar:first-of-type{padding-top:0}}@media(min-width:768px){ion-header ion-toolbar{border-bottom-color:var(--kirby-medium)}}ion-header.content-scrolled ion-toolbar{border-bottom-color:var(--kirby-medium)}:host-context(ion-modal.no-header-area-border) ion-header ion-toolbar{border-bottom-color:transparent}@media(max-width:767px){:host-context(ion-modal.kirby-drawer:not(.kirby-modal-full-height)){padding-top:0;position:relative;contain:inherit;min-height:min(var(--min-height),var(--vh100) - var(--kirby-modal-padding-top, 0px))}:host-context(ion-modal.kirby-drawer:not(.kirby-modal-full-height)) ion-content{contain:content;max-height:calc(var(--vh100) - var(--kirby-modal-padding-top, 0px) - var(--header-height) - var(--footer-height))}:host-context(ion-modal.kirby-drawer:not(.kirby-modal-full-height)) ion-content::part(scroll){height:\"100%\";position:relative}:host-context(ion-modal.kirby-drawer:not(.kirby-modal-full-height)).drawer ion-content::part(scroll){transition:padding-bottom .15s ease-out}:host-context(ion-modal.kirby-drawer:not(.kirby-modal-full-height)).drawer.keyboard-visible ion-content::part(scroll){transition:padding-bottom .25s ease-out 1ms}}:host-context(ion-modal.kirby-drawer.interact-with-background){padding-top:0;position:relative;contain:inherit;min-height:min(var(--min-height),var(--vh100) - var(--kirby-modal-padding-top, 0px))}:host-context(ion-modal.kirby-drawer.interact-with-background) ion-content{contain:content;max-height:calc(var(--vh100) - var(--kirby-modal-padding-top, 0px) - var(--header-height) - var(--footer-height))}:host-context(ion-modal.kirby-drawer.interact-with-background) ion-content::part(scroll){height:\"100%\";position:relative}:host-context(ion-modal.kirby-drawer.interact-with-background).drawer ion-content::part(scroll){transition:padding-bottom .15s ease-out}:host-context(ion-modal.kirby-drawer.interact-with-background).drawer.keyboard-visible ion-content::part(scroll){transition:padding-bottom .25s ease-out 1ms}:host-context(ion-modal.kirby-drawer.interact-with-background) ion-header ion-toolbar{border-bottom-color:transparent}:host-context(ion-modal.modal-card:not(.kirby-drawer)) ion-header ion-toolbar:first-of-type{padding-top:var(--kirby-safe-area-top, 0)}@media(min-width:768px){:host-context(ion-modal.modal-card:not(.kirby-drawer)) ion-header ion-toolbar:first-of-type{--padding-start: 24px;--padding-end: 24px;--padding-bottom: 23px;--padding-top: 24px;padding-inline:0}}ion-title{box-sizing:border-box;padding-inline:calc(48px + var(--padding-start)) calc(48px + var(--padding-end));font-size:clamp(13px,1rem,32px);font-weight:700;outline:none}ion-content{--background: transparent;--color: var(--kirby-modal-color, var(--kirby-black));--padding-top: 24px;--padding-bottom: calc(var(--kirby-spacing-m) + var(--kirby-modal-safe-area-bottom));--padding-start: 16px;--padding-end: 16px;display:flex;flex-direction:column;height:calc(var(--height) - var(--header-height) - var(--footer-height));max-height:calc(var(--max-height) - var(--header-height) - var(--footer-height))}ion-content ::ng-deep>*{box-sizing:border-box;display:block}:host(:has(kirby-modal-footer)) ion-content{--padding-bottom: var(--kirby-spacing-m)}@media(min-width:768px){ion-content{--padding-start: 48px;--padding-end: 48px}}:host(.collapsible-title) ion-content ion-toolbar:first-of-type{--padding-top: 0px;--padding-bottom: 32px;--padding-start: 8px;--padding-end: 8px;border:none}@media(min-width:768px){:host(.collapsible-title) ion-content ion-toolbar:first-of-type{--padding-start: 16px;--padding-end: 16px}}\n"] }]
755
- }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i0.Injector }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.NgZone }, { type: i1$2.ResizeObserverService }, { type: i1.WindowRef }, { type: i3.PlatformService }, { type: CanDismissHelper }, { type: i0.EnvironmentInjector }, { type: i1$2.TranslationService }], propDecorators: { _hasCollapsibleTitle: [{
756
- type: HostBinding,
757
- args: ['class.collapsible-title']
758
- }], scrollDisabled: [{
759
- type: Input
760
- }], config: [{
761
- type: Input
762
- }], content: [{
763
- type: Input
764
- }], templateRef: [{
765
- type: ContentChild,
766
- args: [TemplateRef]
767
- }], toolbarButtonsQuery: [{
768
- type: ViewChildren,
769
- args: [ButtonComponent, { read: ElementRef }]
770
- }], ionContent: [{
771
- type: ViewChild,
772
- args: [IonContent, { static: true }]
773
- }], ionContentElement: [{
774
- type: ViewChild,
775
- args: [IonContent, { static: true, read: ElementRef }]
776
- }], ionHeaderElement: [{
777
- type: ViewChild,
778
- args: [IonHeader, { static: true, read: ElementRef }]
779
- }], ionToolbarElement: [{
780
- type: ViewChild,
781
- args: [IonToolbar, { static: true, read: ElementRef }]
782
- }], ionTitleElement: [{
783
- type: ViewChild,
784
- args: [IonTitle, { static: true, read: ElementRef }]
785
- }], routerOutlet: [{
786
- type: ViewChild,
787
- args: [RouterOutlet, { static: true }]
788
- }], _contentTitleElement: [{
789
- type: ViewChild,
790
- args: ['contentTitle', { read: ElementRef }]
791
- }], _isDrawer: [{
792
- type: HostBinding,
793
- args: ['class.drawer']
794
- }], onFocusChange: [{
795
- type: HostListener,
796
- args: ['window:focus']
797
- }, {
798
- type: HostListener,
799
- args: ['window:focusout']
800
- }], _onKeyboardShow: [{
801
- type: HostListener,
802
- args: ['window:ionKeyboardDidShow', ['$event.detail.keyboardHeight']]
803
- }, {
804
- type: HostListener,
805
- args: ['window:keyboardWillShow', ['$event.keyboardHeight']]
806
- }], _onKeyboardHide: [{
807
- type: HostListener,
808
- args: ['window:ionKeyboardDidHide']
809
- }, {
810
- type: HostListener,
811
- args: ['window:keyboardWillHide']
812
- }], _onWindowResize: [{
813
- type: HostListener,
814
- args: ['window:resize']
815
- }] } });
816
-
817
- class DrawerSupplementaryAction {
818
- }
819
-
820
- class ModalCompactWrapperComponent {
821
- constructor(injector, elementRef, windowRef, canDismissHelper, renderer) {
822
- this.injector = injector;
823
- this.elementRef = elementRef;
824
- this.windowRef = windowRef;
825
- this.canDismissHelper = canDismissHelper;
826
- this.renderer = renderer;
827
- this.scrollY = Math.abs(this.windowRef.nativeWindow.scrollY);
828
- this.scrollDisabled = false;
829
- this.ionModalDidPresent = new Subject();
830
- this.ionModalWillDismiss = new Subject();
831
- this.didPresent = firstValueFrom(this.ionModalDidPresent);
832
- this.willClose = firstValueFrom(this.ionModalWillDismiss);
833
- }
834
- ngOnInit() {
835
- this.ionModalElement = this.elementRef.nativeElement.closest('ion-modal');
836
- this.setAriaLabel();
837
- this.listenForIonModalDidPresent();
838
- this.listenForIonModalWillDismiss();
839
- this.componentPropsInjector = Injector.create({
840
- providers: [{ provide: COMPONENT_PROPS, useValue: this.config.componentProps }],
841
- parent: this.injector,
842
- });
843
- }
844
- listenForIonModalDidPresent() {
845
- if (this.ionModalElement) {
846
- this.ionModalElement.addEventListener('ionModalDidPresent', () => {
847
- this.ionModalDidPresent.next();
848
- this.ionModalDidPresent.complete();
849
- });
850
- }
851
- }
852
- listenForIonModalWillDismiss() {
853
- if (this.ionModalElement) {
854
- this.ionModalElement.addEventListener('ionModalWillDismiss', () => {
855
- this.ionModalWillDismiss.next();
856
- this.ionModalWillDismiss.complete();
857
- });
858
- }
859
- }
860
- setAriaLabel() {
861
- const ionModalElementDialog = getIonModalDialogAncestor(this.ionModalElement);
862
- const ariaLabel = this.config.htmlAttributes?.['aria-label'];
863
- if (ionModalElementDialog && ariaLabel) {
864
- this.renderer.setAttribute(ionModalElementDialog, 'aria-label', ariaLabel);
865
- }
866
- }
867
- async close(data) {
868
- if (this.ionModalElement) {
869
- await this.ionModalElement.dismiss(data);
870
- }
871
- }
872
- set canDismiss(callback) {
873
- this.ionModalElement.canDismiss = this.canDismissHelper.getCanDismissCallback(callback);
874
- }
875
- onFocusChange() {
876
- // This fixes an undesired scroll behaviour occurring on keyboard-tabbing backwards (with shift+tab):
877
- this.windowRef.nativeWindow.scrollTo({ top: this.scrollY });
878
- }
879
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ModalCompactWrapperComponent, deps: [{ token: i0.Injector }, { token: i0.ElementRef }, { token: i1.WindowRef }, { token: CanDismissHelper }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component }); }
880
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.18", type: ModalCompactWrapperComponent, isStandalone: true, selector: "kirby-modal-compact-wrapper", inputs: { config: "config", content: "content" }, host: { listeners: { "window:focus": "onFocusChange()", "window:focusout": "onFocusChange()" }, properties: { "class.ion-page": "false" } }, providers: [{ provide: Modal, useExisting: ModalCompactWrapperComponent }], ngImport: i0, template: "<!-- Outlet for ModalController -->\n<ng-container\n *ngComponentOutlet=\"config.component; injector: componentPropsInjector\"\n></ng-container>\n\n<!-- Outlet for projected content -->\n<ng-container *ngTemplateOutlet=\"content\"></ng-container>\n", styles: [".kirby-line-clamp{display:-webkit-box;-webkit-line-clamp:var(--line-clamp, none);-webkit-box-orient:vertical;overflow:hidden}:host{display:block;padding:24px 16px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i6.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); }
881
- }
882
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ModalCompactWrapperComponent, decorators: [{
883
- type: Component,
884
- args: [{ selector: 'kirby-modal-compact-wrapper', providers: [{ provide: Modal, useExisting: ModalCompactWrapperComponent }], imports: [CommonModule], host: { '[class.ion-page]': 'false' }, template: "<!-- Outlet for ModalController -->\n<ng-container\n *ngComponentOutlet=\"config.component; injector: componentPropsInjector\"\n></ng-container>\n\n<!-- Outlet for projected content -->\n<ng-container *ngTemplateOutlet=\"content\"></ng-container>\n", styles: [".kirby-line-clamp{display:-webkit-box;-webkit-line-clamp:var(--line-clamp, none);-webkit-box-orient:vertical;overflow:hidden}:host{display:block;padding:24px 16px}\n"] }]
885
- }], ctorParameters: () => [{ type: i0.Injector }, { type: i0.ElementRef }, { type: i1.WindowRef }, { type: CanDismissHelper }, { type: i0.Renderer2 }], propDecorators: { config: [{
886
- type: Input
887
- }], content: [{
888
- type: Input
889
- }], onFocusChange: [{
890
- type: HostListener,
891
- args: ['window:focus']
892
- }, {
893
- type: HostListener,
894
- args: ['window:focusout']
895
- }] } });
896
-
897
- class ModalAnimationBuilderService {
898
- constructor(platform) {
899
- this.platform = platform;
900
- this.easingEnter = KirbyAnimation.Easing.modal.enter;
901
- this.easingLeave = KirbyAnimation.Easing.modal.exit;
902
- this.duration = KirbyAnimation.Duration.LONG;
903
- this.SwipeToCloseDefaults = {
904
- MIN_PRESENTING_SCALE: 0.93,
905
- };
906
- this.createEnterAnimation = () => {
907
- const backdropAnimation = createAnimation()
908
- .fromTo('opacity', 0.01, 'var(--backdrop-opacity)')
909
- .beforeStyles({
910
- 'pointer-events': 'none',
911
- })
912
- .afterClearStyles(['pointer-events']);
913
- const wrapperAnimation = createAnimation().fromTo('transform', 'translateY(100vh)', 'translateY(0vh)');
914
- return { backdropAnimation, wrapperAnimation };
915
- };
916
- this.createLeaveAnimation = () => {
917
- const backdropAnimation = createAnimation().fromTo('opacity', 'var(--backdrop-opacity)', 0);
918
- const wrapperAnimation = createAnimation().fromTo('transform', 'translateY(0vh)', 'translateY(100vh)');
919
- return { backdropAnimation, wrapperAnimation };
920
- };
921
- /**
922
- * Gets the root context of a shadow dom element
923
- * On newer browsers this will be the shadowRoot,
924
- * but for older browser this may just be the
925
- * element itself.
926
- *
927
- * Useful for whenever you need to explicitly
928
- * do "myElement.shadowRoot!.querySelector(...)".
929
- */
930
- this.getElementRoot = (el, fallback = el) => {
931
- return el.shadowRoot || fallback;
932
- };
933
- }
934
- enterAnimation(currentBackdrop) {
935
- return (baseEl, opts) => {
936
- const { presentingEl } = opts;
937
- const root = this.getElementRoot(baseEl);
938
- const { wrapperAnimation, backdropAnimation } = this.createEnterAnimation();
939
- backdropAnimation.addElement(root.querySelector('ion-backdrop'));
940
- wrapperAnimation
941
- .addElement(root.querySelectorAll('.modal-wrapper, .modal-shadow'))
942
- .beforeStyles({ opacity: 1 });
943
- const baseAnimation = createAnimation('entering-base')
944
- .addElement(baseEl)
945
- .easing(this.easingEnter)
946
- .duration(this.duration)
947
- .addAnimation(wrapperAnimation);
948
- let currentBackdropAnimation;
949
- if (currentBackdrop) {
950
- currentBackdropAnimation = createAnimation()
951
- .addElement(currentBackdrop)
952
- .fromTo('opacity', 'var(--backdrop-opacity)', 0.01);
953
- }
954
- if (presentingEl) {
955
- const isMobile = !this.platform.isPhabletOrBigger();
956
- const hasCardModal = presentingEl.tagName === 'ION-MODAL' &&
957
- presentingEl.presentingElement !== undefined;
958
- const presentingElRoot = this.getElementRoot(presentingEl);
959
- const presentingAnimation = createAnimation().beforeStyles({
960
- transform: 'translateY(0)',
961
- 'transform-origin': 'top center',
962
- overflow: 'hidden',
963
- });
964
- const bodyEl = document.body;
965
- if (isMobile) {
966
- /**
967
- * Fallback for browsers that does not support `max()` (ex: Firefox)
968
- * No need to worry about statusbar padding since engines like Gecko
969
- * are not used as the engine for standalone Cordova/Capacitor apps
970
- */
971
- const transformOffset = !CSS.supports('width', 'max(0px, 1px)')
972
- ? '30px'
973
- : 'max(30px, var(--ion-safe-area-top))';
974
- const modalTransform = hasCardModal ? '-10px' : transformOffset;
975
- const toPresentingScale = this.SwipeToCloseDefaults.MIN_PRESENTING_SCALE;
976
- const finalTransform = `translateY(${modalTransform}) scale(${toPresentingScale})`;
977
- presentingAnimation
978
- .afterStyles({
979
- transform: finalTransform,
980
- })
981
- .beforeAddWrite(() => bodyEl.style.setProperty('background-color', 'black'))
982
- .addElement(presentingEl)
983
- .keyframes([
984
- {
985
- offset: 0,
986
- filter: 'contrast(1)',
987
- transform: 'translateY(0px) scale(1)',
988
- borderRadius: '0px',
989
- },
990
- {
991
- offset: 1,
992
- filter: 'contrast(0.85)',
993
- transform: finalTransform,
994
- borderRadius: '10px 10px 0 0',
995
- },
996
- ]);
997
- baseAnimation.addAnimation(presentingAnimation);
998
- }
999
- else {
1000
- baseAnimation.addAnimation(backdropAnimation);
1001
- if (currentBackdropAnimation) {
1002
- baseAnimation.addAnimation(currentBackdropAnimation);
1003
- }
1004
- if (!hasCardModal) {
1005
- wrapperAnimation.fromTo('opacity', '0', '1');
1006
- }
1007
- else {
1008
- const toPresentingScale = hasCardModal
1009
- ? this.SwipeToCloseDefaults.MIN_PRESENTING_SCALE
1010
- : 1;
1011
- const finalTransform = `translateY(-10px) scale(${toPresentingScale})`;
1012
- presentingAnimation
1013
- .afterStyles({
1014
- transform: finalTransform,
1015
- })
1016
- .addElement(presentingElRoot.querySelector('.modal-wrapper'))
1017
- .keyframes([
1018
- { offset: 0, filter: 'contrast(1)', transform: 'translateY(0) scale(1)' },
1019
- { offset: 1, filter: 'contrast(0.85)', transform: finalTransform },
1020
- ]);
1021
- const shadowAnimation = createAnimation()
1022
- .afterStyles({
1023
- transform: finalTransform,
1024
- })
1025
- .addElement(presentingElRoot.querySelector('.modal-shadow'))
1026
- .keyframes([
1027
- { offset: 0, opacity: '1', transform: 'translateY(0) scale(1)' },
1028
- { offset: 1, opacity: '0', transform: finalTransform },
1029
- ]);
1030
- baseAnimation.addAnimation([presentingAnimation, shadowAnimation]);
1031
- }
1032
- }
1033
- }
1034
- else {
1035
- baseAnimation.addAnimation(backdropAnimation);
1036
- if (currentBackdropAnimation) {
1037
- baseAnimation.addAnimation(currentBackdropAnimation);
1038
- }
1039
- }
1040
- return baseAnimation;
1041
- };
1042
- }
1043
- leaveAnimation(currentBackdrop) {
1044
- return (baseEl, opts, duration = this.duration) => {
1045
- const { presentingEl } = opts;
1046
- const root = this.getElementRoot(baseEl);
1047
- const { wrapperAnimation, backdropAnimation } = this.createLeaveAnimation();
1048
- backdropAnimation.addElement(root.querySelector('ion-backdrop'));
1049
- wrapperAnimation
1050
- .addElement(root.querySelectorAll('.modal-wrapper, .modal-shadow'))
1051
- .beforeStyles({ opacity: 1 });
1052
- const baseAnimation = createAnimation('leaving-base')
1053
- .addElement(baseEl)
1054
- .easing(this.easingLeave)
1055
- .duration(duration)
1056
- .addAnimation(wrapperAnimation);
1057
- let currentBackdropAnimation;
1058
- if (currentBackdrop) {
1059
- currentBackdropAnimation = createAnimation()
1060
- .addElement(currentBackdrop)
1061
- .fromTo('opacity', 0.01, 'var(--backdrop-opacity)')
1062
- .afterStyles({ opacity: 'var(--backdrop-opacity)' }); //Ensures backdrop is reset to default opacity after swipe to close
1063
- }
1064
- if (presentingEl) {
1065
- const isMobile = !this.platform.isPhabletOrBigger();
1066
- const hasCardModal = presentingEl.tagName === 'ION-MODAL' &&
1067
- presentingEl.presentingElement !== undefined;
1068
- const presentingElRoot = this.getElementRoot(presentingEl);
1069
- const presentingAnimation = createAnimation()
1070
- .beforeClearStyles(['transform'])
1071
- .afterClearStyles(['transform'])
1072
- .onFinish((currentStep) => {
1073
- // only reset background color if this is the last card-style modal
1074
- if (currentStep !== 1) {
1075
- return;
1076
- }
1077
- presentingEl.style.setProperty('overflow', '');
1078
- const numModals = Array.from(bodyEl.querySelectorAll('ion-modal')).filter((m) => m.presentingElement !== undefined).length;
1079
- if (numModals <= 1) {
1080
- bodyEl.style.setProperty('background-color', '');
1081
- }
1082
- });
1083
- const bodyEl = document.body;
1084
- if (isMobile) {
1085
- const transformOffset = !CSS.supports('width', 'max(0px, 1px)')
1086
- ? '30px'
1087
- : 'max(30px, var(--ion-safe-area-top))';
1088
- const modalTransform = hasCardModal ? '-10px' : transformOffset;
1089
- const toPresentingScale = this.SwipeToCloseDefaults.MIN_PRESENTING_SCALE;
1090
- const finalTransform = `translateY(${modalTransform}) scale(${toPresentingScale})`;
1091
- presentingAnimation.addElement(presentingEl).keyframes([
1092
- {
1093
- offset: 0,
1094
- filter: 'contrast(0.85)',
1095
- transform: finalTransform,
1096
- borderRadius: '10px 10px 0 0',
1097
- },
1098
- {
1099
- offset: 1,
1100
- filter: 'contrast(1)',
1101
- transform: 'translateY(0px) scale(1)',
1102
- borderRadius: '0px',
1103
- },
1104
- ]);
1105
- baseAnimation.addAnimation(presentingAnimation);
1106
- }
1107
- else {
1108
- baseAnimation.addAnimation(backdropAnimation);
1109
- if (currentBackdropAnimation) {
1110
- baseAnimation.addAnimation(currentBackdropAnimation);
1111
- }
1112
- if (!hasCardModal) {
1113
- wrapperAnimation.fromTo('opacity', '1', '0');
1114
- }
1115
- else {
1116
- const toPresentingScale = hasCardModal
1117
- ? this.SwipeToCloseDefaults.MIN_PRESENTING_SCALE
1118
- : 1;
1119
- const finalTransform = `translateY(-10px) scale(${toPresentingScale})`;
1120
- presentingAnimation
1121
- .addElement(presentingElRoot.querySelector('.modal-wrapper'))
1122
- .afterStyles({
1123
- transform: 'translate3d(0, 0, 0)',
1124
- })
1125
- .keyframes([
1126
- { offset: 0, filter: 'contrast(0.85)', transform: finalTransform },
1127
- { offset: 1, filter: 'contrast(1)', transform: 'translateY(0) scale(1)' },
1128
- ]);
1129
- const shadowAnimation = createAnimation()
1130
- .addElement(presentingElRoot.querySelector('.modal-shadow'))
1131
- .afterStyles({
1132
- transform: 'translateY(0) scale(1)',
1133
- })
1134
- .keyframes([
1135
- { offset: 0, opacity: '0', transform: finalTransform },
1136
- { offset: 1, opacity: '1', transform: 'translateY(0) scale(1)' },
1137
- ]);
1138
- baseAnimation.addAnimation([presentingAnimation, shadowAnimation]);
1139
- }
1140
- }
1141
- }
1142
- else {
1143
- baseAnimation.addAnimation(backdropAnimation);
1144
- if (currentBackdropAnimation) {
1145
- baseAnimation.addAnimation(currentBackdropAnimation);
1146
- }
1147
- }
1148
- return baseAnimation;
1149
- };
1150
- }
1151
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ModalAnimationBuilderService, deps: [{ token: i3.PlatformService }], target: i0.ɵɵFactoryTarget.Injectable }); }
1152
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ModalAnimationBuilderService, providedIn: 'root' }); }
1153
- }
1154
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ModalAnimationBuilderService, decorators: [{
1155
- type: Injectable,
1156
- args: [{ providedIn: 'root' }]
1157
- }], ctorParameters: () => [{ type: i3.PlatformService }] });
1158
-
1159
- class ModalNavigationService {
1160
- constructor(router, route) {
1161
- this.router = router;
1162
- this.route = route;
1163
- // Angular Router unsubscribes its internal events Subject during dispose() (e.g. on TestBed teardown).
1164
- // Subscribing to a closed Subject throws ObjectUnsubscribedError, so route all subscriptions through
1165
- // this defer-wrapped stream that falls back to EMPTY when the underlying Subject is already closed.
1166
- this.routerEvents$ = defer(() => {
1167
- const events = this.router.events;
1168
- return events.closed ? EMPTY : events;
1169
- });
1170
- this.navigationEndListener$ = this.routerEvents$.pipe(filter((event) => event instanceof NavigationEnd));
1171
- }
1172
- isModalRoute(url) {
1173
- return url.includes('(modal:');
1174
- }
1175
- getCurrentActivatedRoute() {
1176
- let childRoute = this.route.root;
1177
- while (childRoute.firstChild) {
1178
- childRoute = childRoute.firstChild;
1179
- }
1180
- return childRoute;
1181
- }
1182
- async getModalRoutes(routeConfig, moduleRootRoutePath) {
1183
- const flattenedRoutes = [].concat(...routeConfig);
1184
- let modalRoutes = [];
1185
- const moduleRootPaths = await this.getModuleRootPath(flattenedRoutes, moduleRootRoutePath);
1186
- if (moduleRootPaths) {
1187
- modalRoutes = this.getModalRoutePaths(flattenedRoutes, moduleRootPaths);
1188
- }
1189
- return modalRoutes;
1190
- }
1191
- async getModuleRootPath(routes, moduleRootRoutePath) {
1192
- if (moduleRootRoutePath) {
1193
- const trimmedPaths = moduleRootRoutePath
1194
- .trim()
1195
- .split('/')
1196
- .filter((path) => !!path);
1197
- const rootPath = [''];
1198
- return rootPath.concat(trimmedPaths);
1199
- }
1200
- const currentRoutePaths = await this.getCurrentRoutePaths();
1201
- const moduleRootPaths = this.getRoutePathsWithoutChildSegments(currentRoutePaths, routes);
1202
- return moduleRootPaths;
1203
- }
1204
- async getCurrentRoutePaths() {
1205
- const rootPath = [''];
1206
- const currentNavigation = this.router.currentNavigation();
1207
- if (!this.router.navigated && !currentNavigation) {
1208
- // If router hasn't navigated yet and we are not in the middle of navigating, assume root:
1209
- return rootPath;
1210
- }
1211
- if (currentNavigation) {
1212
- // Wait for current navigation to finish:
1213
- await firstValueFrom(this.navigationEndListener$);
1214
- }
1215
- let childRoute = this.route.snapshot.root;
1216
- while (childRoute.firstChild) {
1217
- childRoute = childRoute.firstChild;
1218
- }
1219
- const currentBackdropRoutePath = childRoute.pathFromRoot.filter((route) => route.outlet !== 'modal');
1220
- return rootPath.concat(...currentBackdropRoutePath.map((route) => route.url.filter((segment) => !!segment.path).map((segment) => segment.path)));
1221
- }
1222
- getRoutePathsWithoutChildSegments(routePaths, routes) {
1223
- if (!routePaths.length)
1224
- return routePaths;
1225
- const matchedChildRoute = this.findChildRouteForUrl(routePaths.join('/'), routes);
1226
- if (!matchedChildRoute)
1227
- return routePaths;
1228
- const startSlashRegex = /^\//;
1229
- const relativeChildRoute = matchedChildRoute.replace(startSlashRegex, '');
1230
- const childSegmentCount = relativeChildRoute.split('/').length;
1231
- const routePathsWithoutChildSegments = routePaths.slice(0, -childSegmentCount); // Remove child segments from end of route path array
1232
- return routePathsWithoutChildSegments;
1233
- }
1234
- findChildRouteForUrl(url, routes) {
1235
- const moduleRelativePaths = this.getRoutePaths(routes, ['']).sort().reverse(); // Ensure child paths are evaluated first
1236
- let matchedChildRoute = moduleRelativePaths.find((path) => url.endsWith(path));
1237
- if (!matchedChildRoute) {
1238
- // No static child route found matching current route - look for child route with url params:
1239
- const exactMatch = false;
1240
- matchedChildRoute = moduleRelativePaths.find((path) => path.includes('/:') && this.pathContainsChildRouteWithUrlParams(url, path, exactMatch));
1241
- }
1242
- return matchedChildRoute;
1243
- }
1244
- pathContainsChildRouteWithUrlParams(path, childRouteWithUrlParams, exactMatch) {
1245
- const pathSegments = path.split('/');
1246
- const startSlashRegex = /^\//;
1247
- let childRouteToMatch = childRouteWithUrlParams;
1248
- if (!exactMatch) {
1249
- const relativeChildRoute = childRouteWithUrlParams.replace(startSlashRegex, '');
1250
- childRouteToMatch = relativeChildRoute;
1251
- }
1252
- const childRouteSegments = childRouteToMatch.split('/');
1253
- // Match each child route segment against url
1254
- // Match backwards from end to start of child route, i.e. "url ends with child route":
1255
- const pathContainsChildRoute = childRouteSegments.reverse().every((childRouteSegment) => {
1256
- const pathSegment = pathSegments.pop();
1257
- // url params (e.g. `/:id/`) are treated as a match:
1258
- return childRouteSegment.startsWith(':') || childRouteSegment === pathSegment;
1259
- });
1260
- if (exactMatch) {
1261
- // Only match if we've reached the start of the url to match against:
1262
- return pathSegments.length === 0 && pathContainsChildRoute;
1263
- }
1264
- return pathContainsChildRoute;
1265
- }
1266
- getRoutePaths(routes, parentPath) {
1267
- return Array.isArray(routes)
1268
- ? [].concat(...routes.map((route) => this.getRoutePath(route, parentPath)))
1269
- : [];
1270
- }
1271
- getRoutePath(route, parentPath) {
1272
- const routes = [];
1273
- if (route.outlet)
1274
- return routes; // Don't return relative paths for outlet routes
1275
- const currentPath = [...parentPath];
1276
- if (route.path) {
1277
- currentPath.push(route.path);
1278
- routes.push(currentPath.join('/'));
1279
- }
1280
- return routes.concat(this.getRoutePaths(route.children, currentPath));
1281
- }
1282
- getModalRoutePath(route, parentPath) {
1283
- const modalOutletName = 'modal';
1284
- if (!!route.path && route.outlet === modalOutletName) {
1285
- const modalOutletPath = `(${modalOutletName}:${route.path})`;
1286
- const modalRoutePath = [...parentPath, modalOutletPath].join('/');
1287
- return [modalRoutePath];
1288
- }
1289
- const currentPath = [...parentPath];
1290
- if (route.path) {
1291
- currentPath.push(route.path);
1292
- }
1293
- return [].concat(...this.getModalRoutePaths(route.children, currentPath));
1294
- }
1295
- getModalRoutePaths(routes, parentPath) {
1296
- return Array.isArray(routes)
1297
- ? [].concat(...routes.map((route) => this.getModalRoutePath(route, parentPath)))
1298
- : [];
1299
- }
1300
- isNewModalWindow(navigationEnd) {
1301
- const currentNavigation = this.router.currentNavigation();
1302
- if (!currentNavigation || !currentNavigation.previousNavigation) {
1303
- return true;
1304
- }
1305
- const previousRoutePath = (currentNavigation.previousNavigation.finalUrl ||
1306
- currentNavigation.previousNavigation.extractedUrl).toString();
1307
- const wasModalRoute = this.isModalRoute(previousRoutePath);
1308
- const isModalRoute = this.isModalRoute(navigationEnd.urlAfterRedirects);
1309
- if (!wasModalRoute && isModalRoute) {
1310
- return true;
1311
- }
1312
- const currentModalRouteParent = navigationEnd.urlAfterRedirects.split('/(modal:')[0];
1313
- const previousModalRouteParent = previousRoutePath.split('/(modal:')[0];
1314
- return previousModalRouteParent !== currentModalRouteParent;
1315
- }
1316
- async waitForCurrentThenGetNavigationEndStream() {
1317
- if (this.router.currentNavigation()) {
1318
- const currentNavigationEnd = await firstValueFrom(this.navigationEndListener$);
1319
- return this.navigationEndListener$.pipe(startWith(currentNavigationEnd));
1320
- }
1321
- return this.navigationEndListener$;
1322
- }
1323
- modalRouteActivatedFor(navigationEnd$, modalRouteSet, modalRoutesContainsUrlParams) {
1324
- return navigationEnd$.pipe(filter((navigationEnd) => this.modalRouteSetContainsPath(modalRouteSet, navigationEnd, modalRoutesContainsUrlParams)), map((navigationEnd) => {
1325
- return {
1326
- route: this.getCurrentActivatedRoute(),
1327
- isNewModal: this.isNewModalWindow(navigationEnd),
1328
- };
1329
- }));
1330
- }
1331
- modalRouteDeactivatedFor(navigationEnd$, modalRouteSet, modalRoutesContainsUrlParams) {
1332
- return navigationEnd$.pipe(pairwise(),
1333
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1334
- filter(([prevNavigation, _]) => this.modalRouteSetContainsPath(modalRouteSet, prevNavigation, modalRoutesContainsUrlParams)), // Only emit if previous route was modal
1335
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1336
- map(([_, currentNavigation]) => {
1337
- const isNewModalRoute = this.isModalRoute(currentNavigation.urlAfterRedirects);
1338
- // Deactivate modal route if new route is NOT modal OR is outside current parent route:
1339
- return !isNewModalRoute || this.isNewModalWindow(currentNavigation);
1340
- }), filter((isDeactivation) => isDeactivation));
1341
- }
1342
- modalRouteSetContainsPath(modalRouteSet, navigationEnd, modalRoutesContainsUrlParams) {
1343
- const pathname = navigationEnd.urlAfterRedirects.split('?')[0];
1344
- let hasRoute = modalRouteSet.has(pathname);
1345
- if (!hasRoute && modalRoutesContainsUrlParams) {
1346
- // Use `for ... of` instead of `forEach` so we can break out of the loop if route is found:
1347
- for (const route of modalRouteSet) {
1348
- const exactMatch = true;
1349
- const routeMatchesPath = this.pathContainsChildRouteWithUrlParams(pathname, route, exactMatch);
1350
- if (routeMatchesPath) {
1351
- hasRoute = true;
1352
- break;
1353
- }
1354
- }
1355
- }
1356
- return hasRoute;
1357
- }
1358
- async getModalNavigation(routeConfig, moduleRootRoutePath) {
1359
- if (Array.isArray(routeConfig)) {
1360
- const navigationEnd$ = await this.waitForCurrentThenGetNavigationEndStream();
1361
- const modalRoutes = await this.getModalRoutes(routeConfig, moduleRootRoutePath);
1362
- const hasModalRoutes = modalRoutes.length > 0;
1363
- if (hasModalRoutes) {
1364
- const modalRoutesContainsUrlParams = modalRoutes.some((route) => route.includes('/:'));
1365
- const modalRouteSet = new Set(modalRoutes);
1366
- const activated$ = this.modalRouteActivatedFor(navigationEnd$, modalRouteSet, modalRoutesContainsUrlParams);
1367
- const deactivated$ = this.modalRouteDeactivatedFor(navigationEnd$, modalRouteSet, modalRoutesContainsUrlParams);
1368
- return { activated$, deactivated$ };
1369
- }
1370
- }
1371
- return { activated$: EMPTY, deactivated$: EMPTY };
1372
- }
1373
- async navigateToModal(path, queryParams) {
1374
- const commands = Array.isArray(path) ? [...path] : path.split('/');
1375
- const childPath = commands.pop();
1376
- const result = await this.router.navigate([...commands, { outlets: { modal: [childPath] } }], {
1377
- queryParams,
1378
- relativeTo: this.getCurrentActivatedRoute(),
1379
- });
1380
- return result;
1381
- }
1382
- async navigateWithinModal(relativePath, queryParams) {
1383
- return this.router.navigate([relativePath], {
1384
- queryParams,
1385
- relativeTo: this.getCurrentActivatedRoute(),
1386
- });
1387
- }
1388
- async navigateOutOfModalOutlet() {
1389
- const currentActivatedRoute = this.getCurrentActivatedRoute();
1390
- const currentNavigationFinalUrl = this.router.currentNavigation()?.finalUrl?.toString();
1391
- const isCurrentlyNavigatingOutOfModalOutlet = currentNavigationFinalUrl && !this.isModalRoute(currentNavigationFinalUrl);
1392
- if (currentActivatedRoute.outlet !== 'modal' || isCurrentlyNavigatingOutOfModalOutlet) {
1393
- // Nothing to do here, bail out:
1394
- return Promise.resolve(true);
1395
- }
1396
- const parentRoute = this.getBackdropRoute(currentActivatedRoute);
1397
- return this.router.navigate(['./'], {
1398
- relativeTo: parentRoute,
1399
- });
1400
- }
1401
- getBackdropRoute(currentActivatedRoute) {
1402
- let parentRoute = currentActivatedRoute.parent;
1403
- while (parentRoute && !parentRoute.component && !!parentRoute.parent) {
1404
- parentRoute = parentRoute.parent;
1405
- }
1406
- return parentRoute;
1407
- }
1408
- handleBrowserBackButton(modal) {
1409
- const popstateNavigationStart$ = this.routerEvents$.pipe(filter((event) => event instanceof NavigationStart && event.navigationTrigger === 'popstate'));
1410
- const navigationEnd$ = this.routerEvents$.pipe(filter((event) => event instanceof NavigationEnd));
1411
- navigationEnd$
1412
- .pipe(skipUntil(popstateNavigationStart$), takeUntil(modal.onWillDismiss()))
1413
- .subscribe(() => {
1414
- modal.dismiss();
1415
- });
1416
- }
1417
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ModalNavigationService, deps: [{ token: i1$3.Router }, { token: i1$3.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Injectable }); }
1418
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ModalNavigationService, providedIn: 'root' }); }
1419
- }
1420
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ModalNavigationService, decorators: [{
1421
- type: Injectable,
1422
- args: [{ providedIn: 'root' }]
1423
- }], ctorParameters: () => [{ type: i1$3.Router }, { type: i1$3.ActivatedRoute }] });
1424
-
1425
- class ModalHelper {
1426
- constructor(ionicModalController, modalAnimationBuilder, modalNavigationService, windowRef, canDismissHelper) {
1427
- this.ionicModalController = ionicModalController;
1428
- this.modalAnimationBuilder = modalAnimationBuilder;
1429
- this.modalNavigationService = modalNavigationService;
1430
- this.windowRef = windowRef;
1431
- this.canDismissHelper = canDismissHelper;
1432
- /*
1433
- isModalOpening is used to prevent additional instantiations
1434
- of modals, while a modal is already being instatiated, but not completed.
1435
- This is the recommended approach by one of the maintainers of Ionic:
1436
- https://github.com/ionic-team/ionic-framework/issues/23327#issuecomment-847028058
1437
- */
1438
- this.isModalOpening = false;
1439
- }
1440
- async showModalWindow(config) {
1441
- if (this.isModalOpening)
1442
- return;
1443
- config.flavor = config.flavor || 'modal';
1444
- let currentBackdrop;
1445
- const topMostModal = await this.ionicModalController.getTop();
1446
- if (topMostModal) {
1447
- currentBackdrop =
1448
- topMostModal.shadowRoot.querySelector('ion-backdrop');
1449
- }
1450
- const enterAnimation = this.modalAnimationBuilder.enterAnimation(currentBackdrop);
1451
- const leaveAnimation = this.modalAnimationBuilder.leaveAnimation(currentBackdrop);
1452
- const defaultModalSize = config.interactWithBackground ? null : 'medium';
1453
- const modalSize = config.size || defaultModalSize;
1454
- const allow_scroll_class = 'allow-background-scroll';
1455
- let customCssClasses = [];
1456
- if (config.cssClass) {
1457
- customCssClasses = Array.isArray(config.cssClass) ? config.cssClass : [config.cssClass];
1458
- }
1459
- if (config.interactWithBackground) {
1460
- this.windowRef.nativeWindow.document.body.classList.add(allow_scroll_class);
1461
- }
1462
- let canDismiss = true;
1463
- if (config.canDismiss) {
1464
- canDismiss = this.canDismissHelper.getCanDismissCallback(config.canDismiss);
1465
- }
1466
- this.isModalOpening = true;
1467
- const ionModal = await this.ionicModalController.create({
1468
- component: config.flavor === 'compact' ? ModalCompactWrapperComponent : ModalWrapperComponent,
1469
- cssClass: [
1470
- 'kirby-overlay',
1471
- 'kirby-modal',
1472
- modalSize ? `kirby-modal-${modalSize}` : null,
1473
- config.flavor === 'drawer' ? 'kirby-drawer' : null,
1474
- config.flavor === 'compact' ? 'kirby-modal-compact' : null,
1475
- config.interactWithBackground ? 'interact-with-background' : null,
1476
- ...customCssClasses,
1477
- ],
1478
- backdropDismiss: config.flavor === 'compact' || config.interactWithBackground ? false : true,
1479
- showBackdrop: !config.interactWithBackground,
1480
- componentProps: { config: config },
1481
- htmlAttributes: { ...config.htmlAttributes },
1482
- keyboardClose: false,
1483
- canDismiss,
1484
- enterAnimation,
1485
- leaveAnimation,
1486
- });
1487
- if (config.interactWithBackground) {
1488
- ionModal.onDidDismiss().then(() => {
1489
- this.windowRef.nativeWindow.document.body.classList.remove(allow_scroll_class);
1490
- });
1491
- }
1492
- if (config.customHeight) {
1493
- ionModal.style.setProperty('--kirby-modal-height', config.customHeight);
1494
- }
1495
- const onWillDismiss = ionModal.onWillDismiss();
1496
- const overlay = {
1497
- dismiss: ionModal.dismiss.bind(ionModal),
1498
- onWillDismiss,
1499
- onDidDismiss: ionModal.onDidDismiss(),
1500
- isDismissing: false,
1501
- };
1502
- onWillDismiss.then(() => {
1503
- overlay.isDismissing = true;
1504
- });
1505
- await ionModal.present();
1506
- /**
1507
- * Due to somewhat unexpected behavior of the ion-modal not being focused when keyboardClose
1508
- * is set to false we manually focus it, but only if focus is not already inside the modal
1509
- * See here: https://github.com/ionic-team/ionic-framework/issues/28775#issuecomment-1875475739
1510
- */
1511
- const focusedElementWithinModal = ionModal.contains(document.activeElement);
1512
- if (!focusedElementWithinModal) {
1513
- ionModal.focus();
1514
- }
1515
- // Back button should only be handled manually
1516
- // if the modal is not instantiated through a route.
1517
- if (!config.modalRoute) {
1518
- this.modalNavigationService.handleBrowserBackButton(ionModal);
1519
- }
1520
- this.isModalOpening = false;
1521
- return overlay;
1522
- }
1523
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ModalHelper, deps: [{ token: i1$1.ModalController }, { token: ModalAnimationBuilderService }, { token: ModalNavigationService }, { token: i1.WindowRef }, { token: CanDismissHelper }], target: i0.ɵɵFactoryTarget.Injectable }); }
1524
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ModalHelper }); }
1525
- }
1526
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ModalHelper, decorators: [{
1527
- type: Injectable
1528
- }], ctorParameters: () => [{ type: i1$1.ModalController }, { type: ModalAnimationBuilderService }, { type: ModalNavigationService }, { type: i1.WindowRef }, { type: CanDismissHelper }] });
1529
-
1530
- const KIRBY_ACTION_SHEET_DEPRECATION_WARNING = '[Kirby action sheet] Deprecated - Use Menu component instead';
1531
- class ActionSheetComponent {
1532
- constructor() {
1533
- this.cancelButtonText = 'Cancel';
1534
- this.hideCancel = false;
1535
- this.disabled = false;
1536
- this.cancel = new EventEmitter();
1537
- this.itemSelect = new EventEmitter();
1538
- console.warn(KIRBY_ACTION_SHEET_DEPRECATION_WARNING);
1539
- }
1540
- onItemSelect(selection) {
1541
- this.itemSelect.emit(selection);
1542
- }
1543
- onCancel() {
1544
- this.cancel.emit();
1545
- }
1546
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ActionSheetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1547
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: ActionSheetComponent, isStandalone: true, selector: "kirby-action-sheet", inputs: { cancelButtonText: "cancelButtonText", hideCancel: "hideCancel", disabled: "disabled", header: "header", subheader: "subheader", items: "items" }, outputs: { cancel: "cancel", itemSelect: "itemSelect" }, ngImport: i0, template: "<kirby-card>\n @if (header) {\n <kirby-card-header\n [title]=\"header\"\n [isTitleBold]=\"true\"\n [subtitle]=\"subheader\"\n ></kirby-card-header>\n }\n @for (item of items; track item.id) {\n <button\n kirby-button\n expand=\"block\"\n size=\"lg\"\n [noDecoration]=\"true\"\n (click)=\"onItemSelect(item)\"\n >\n {{ item.text }}\n </button>\n }\n</kirby-card>\n@if (!hideCancel) {\n <button kirby-button class=\"cancel-btn\" size=\"lg\" attentionLevel=\"3\" (click)=\"onCancel()\">\n {{ cancelButtonText }}\n </button>\n}\n", styles: [".kirby-line-clamp{display:-webkit-box;-webkit-line-clamp:var(--line-clamp, none);-webkit-box-orient:vertical;overflow:hidden}:host{--kirby-internal-margin-horizontal-default: 32px}@media(max-width:320px){:host{--kirby-internal-margin-horizontal-default: 16px}}:host{--kirby-internal-margin-horizontal-total: calc( 2 * var(--kirby-action-sheet-margin-horizontal, var(--kirby-internal-margin-horizontal-default)) );display:flex;flex-direction:column;align-items:center;justify-content:flex-end;margin:0 auto;width:calc(100vw - var(--kirby-internal-margin-horizontal-total));max-width:calc(375px - var(--kirby-internal-margin-horizontal-total));padding-bottom:var(--kirby-safe-area-bottom, 0)}:host button[kirby-button].no-decoration:focus-visible{transition:all 80ms linear 0ms;box-shadow:var(--kirby-focus-ring-md-inset)}kirby-card{align-self:stretch;pointer-events:auto;box-shadow:0 20px 30px -15px #1c1c1c4d,0 0 5px #1c1c1c14}kirby-card button[kirby-button]{margin:0;border-radius:0}kirby-card button[kirby-button]:not(:focus){border-top:1px solid var(--kirby-background-color)}.cancel-btn:focus-visible{transition:all 80ms linear 0ms;box-shadow:0 20px 30px -15px #1c1c1c4d,0 0 5px #1c1c1c14,var(--kirby-focus-ring-md-inset)}.cancel-btn{font-weight:700;margin-top:16px;margin-bottom:24px;pointer-events:auto}\n"], dependencies: [{ kind: "component", type: CardComponent, selector: "kirby-card", inputs: ["title", "subtitle", "backgroundImageUrl", "hasPadding", "sizes", "variant"] }, { kind: "component", type: CardHeaderComponent, selector: "kirby-card-header", inputs: ["title", "subtitle", "isTitleBold", "flagged", "hasPadding"] }, { kind: "component", type: ButtonComponent, selector: "button[kirby-button],Button[kirby-button],a[kirby-button]", inputs: ["attentionLevel", "noDecoration", "themeColor", "expand", "isFloating", "size", "showIconOnly"] }] }); }
1548
- }
1549
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ActionSheetComponent, decorators: [{
1550
- type: Component,
1551
- args: [{ imports: [CardComponent, CardHeaderComponent, ButtonComponent], selector: 'kirby-action-sheet', template: "<kirby-card>\n @if (header) {\n <kirby-card-header\n [title]=\"header\"\n [isTitleBold]=\"true\"\n [subtitle]=\"subheader\"\n ></kirby-card-header>\n }\n @for (item of items; track item.id) {\n <button\n kirby-button\n expand=\"block\"\n size=\"lg\"\n [noDecoration]=\"true\"\n (click)=\"onItemSelect(item)\"\n >\n {{ item.text }}\n </button>\n }\n</kirby-card>\n@if (!hideCancel) {\n <button kirby-button class=\"cancel-btn\" size=\"lg\" attentionLevel=\"3\" (click)=\"onCancel()\">\n {{ cancelButtonText }}\n </button>\n}\n", styles: [".kirby-line-clamp{display:-webkit-box;-webkit-line-clamp:var(--line-clamp, none);-webkit-box-orient:vertical;overflow:hidden}:host{--kirby-internal-margin-horizontal-default: 32px}@media(max-width:320px){:host{--kirby-internal-margin-horizontal-default: 16px}}:host{--kirby-internal-margin-horizontal-total: calc( 2 * var(--kirby-action-sheet-margin-horizontal, var(--kirby-internal-margin-horizontal-default)) );display:flex;flex-direction:column;align-items:center;justify-content:flex-end;margin:0 auto;width:calc(100vw - var(--kirby-internal-margin-horizontal-total));max-width:calc(375px - var(--kirby-internal-margin-horizontal-total));padding-bottom:var(--kirby-safe-area-bottom, 0)}:host button[kirby-button].no-decoration:focus-visible{transition:all 80ms linear 0ms;box-shadow:var(--kirby-focus-ring-md-inset)}kirby-card{align-self:stretch;pointer-events:auto;box-shadow:0 20px 30px -15px #1c1c1c4d,0 0 5px #1c1c1c14}kirby-card button[kirby-button]{margin:0;border-radius:0}kirby-card button[kirby-button]:not(:focus){border-top:1px solid var(--kirby-background-color)}.cancel-btn:focus-visible{transition:all 80ms linear 0ms;box-shadow:0 20px 30px -15px #1c1c1c4d,0 0 5px #1c1c1c14,var(--kirby-focus-ring-md-inset)}.cancel-btn{font-weight:700;margin-top:16px;margin-bottom:24px;pointer-events:auto}\n"] }]
1552
- }], ctorParameters: () => [], propDecorators: { cancelButtonText: [{
1553
- type: Input
1554
- }], hideCancel: [{
1555
- type: Input
1556
- }], disabled: [{
1557
- type: Input
1558
- }], header: [{
1559
- type: Input
1560
- }], subheader: [{
1561
- type: Input
1562
- }], items: [{
1563
- type: Input
1564
- }], cancel: [{
1565
- type: Output
1566
- }], itemSelect: [{
1567
- type: Output
1568
- }] } });
1569
-
1570
- class ActionSheetHelper {
1571
- constructor(ionicModalController) {
1572
- this.ionicModalController = ionicModalController;
1573
- }
1574
- async showActionSheet(config) {
1575
- const cancel = new EventEmitter();
1576
- const itemSelect = new EventEmitter();
1577
- const ionModal = await this.ionicModalController.create({
1578
- component: ActionSheetComponent,
1579
- cssClass: ['kirby-overlay', 'kirby-action-sheet'],
1580
- componentProps: {
1581
- ...config,
1582
- cancel: cancel,
1583
- itemSelect: itemSelect,
1584
- },
1585
- backdropDismiss: true,
1586
- });
1587
- // Remove 'modal-shadow' element as we are no longer able to hide it with CSS in Ionic 6.
1588
- // We need to remove it so it does not obstruct the backdrop-click to dismiss functionality.
1589
- ionModal.shadowRoot.querySelector('.modal-shadow').remove();
1590
- const cancelSubscription = cancel.subscribe(() => ionModal.dismiss());
1591
- const itemSelectSubscription = itemSelect.subscribe((item) => ionModal.dismiss(item));
1592
- const onDidDismiss = ionModal.onDidDismiss();
1593
- onDidDismiss.then(() => {
1594
- cancelSubscription.unsubscribe();
1595
- itemSelectSubscription.unsubscribe();
1596
- });
1597
- await ionModal.present();
1598
- return {
1599
- dismiss: ionModal.dismiss.bind(ionModal),
1600
- onWillDismiss: ionModal.onWillDismiss(),
1601
- onDidDismiss: ionModal.onDidDismiss(),
1602
- };
1603
- }
1604
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ActionSheetHelper, deps: [{ token: i1$1.ModalController }], target: i0.ɵɵFactoryTarget.Injectable }); }
1605
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ActionSheetHelper }); }
1606
- }
1607
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ActionSheetHelper, decorators: [{
1608
- type: Injectable
1609
- }], ctorParameters: () => [{ type: i1$1.ModalController }] });
1610
-
1611
- class ModalController {
1612
- constructor(modalHelper, actionSheetHelper, alertHelper, modalNavigationService, routeConfig) {
1613
- this.modalHelper = modalHelper;
1614
- this.actionSheetHelper = actionSheetHelper;
1615
- this.alertHelper = alertHelper;
1616
- this.modalNavigationService = modalNavigationService;
1617
- this.routeConfig = routeConfig;
1618
- this.overlays = [];
1619
- this.noOverlayRegisteredErrorMessage = 'No modal overlays are currently registered';
1620
- this.destroy$ = new Subject();
1621
- }
1622
- async initialize(moduleRootRoutePath) {
1623
- const modalNavigation = await this.modalNavigationService.getModalNavigation(this.routeConfig, moduleRootRoutePath);
1624
- this.onModalRouteActivated(modalNavigation.activated$);
1625
- this.onModalRouteDeactivated(modalNavigation.deactivated$);
1626
- }
1627
- onModalRouteActivated(modalRouteActivated$) {
1628
- const navigateOnWillClose = () => {
1629
- this.modalNavigationService.navigateOutOfModalOutlet();
1630
- };
1631
- const siblingModalRouteActivated$ = modalRouteActivated$.pipe(filter((modalRouteActivation) => !modalRouteActivation.isNewModal), map((modalRouteActivation) => modalRouteActivation.route));
1632
- modalRouteActivated$
1633
- .pipe(takeUntil(this.destroy$), filter(() => this.overlays.length === 0))
1634
- .subscribe(async (modalRouteActivation) => {
1635
- if (modalRouteActivation.isNewModal) {
1636
- await this.showModalRoute(modalRouteActivation.route, siblingModalRouteActivated$, navigateOnWillClose);
1637
- }
1638
- });
1639
- }
1640
- onModalRouteDeactivated(modalRouteDeactivated$) {
1641
- modalRouteDeactivated$
1642
- .pipe(takeUntil(this.destroy$), filter(() => this.overlays.some((overlay) => overlay.isDismissing !== true)))
1643
- .subscribe(async () => {
1644
- await this.hideAll();
1645
- });
1646
- }
1647
- async showModal(config, onClose) {
1648
- await this.showAndRegisterOverlay(() => this.modalHelper.showModalWindow(config), onClose);
1649
- }
1650
- async navigateToModal(path, queryParams) {
1651
- return this.modalNavigationService.navigateToModal(path, queryParams);
1652
- }
1653
- async navigateWithinModal(relativePath, queryParams) {
1654
- return this.modalNavigationService.navigateWithinModal(relativePath, queryParams);
1655
- }
1656
- async showModalRoute(modalRoute, siblingModalRouteActivated$, onWillClose) {
1657
- const config = {
1658
- ...modalRoute.snapshot.data.modalConfig,
1659
- component: null,
1660
- modalRoute: modalRoute,
1661
- siblingModalRouteActivated$: siblingModalRouteActivated$,
1662
- };
1663
- await this.showAndRegisterOverlay(() => this.modalHelper.showModalWindow(config), null, onWillClose);
1664
- }
1665
- async showActionSheet(config, onClose) {
1666
- await this.showAndRegisterOverlay(() => this.actionSheetHelper.showActionSheet(config), onClose);
1667
- }
1668
- async showAlert(config, onClose) {
1669
- await this.showAndRegisterOverlay(() => this.alertHelper.showAlert(config), onClose);
1670
- }
1671
- async showAndRegisterOverlay(showOverlay, onCloseOverlay, onWillCloseOverlay) {
1672
- const overlay = await showOverlay();
1673
- if (!overlay)
1674
- return;
1675
- this.overlays.push(overlay);
1676
- if (typeof onWillCloseOverlay === 'function') {
1677
- overlay.onWillDismiss.then((event) => onWillCloseOverlay(event.data));
1678
- }
1679
- overlay.onDidDismiss.then((event) => {
1680
- this.overlays.pop();
1681
- if (typeof onCloseOverlay === 'function') {
1682
- onCloseOverlay(event.data);
1683
- }
1684
- });
1685
- }
1686
- async hideTopmost(data) {
1687
- const overlay = this.overlays[this.overlays.length - 1];
1688
- if (!overlay) {
1689
- throw new Error(this.noOverlayRegisteredErrorMessage);
1690
- }
1691
- return overlay.dismiss(data);
1692
- }
1693
- async hideAll() {
1694
- await Promise.all(this.overlays
1695
- .filter((overlay) => overlay.isDismissing !== true)
1696
- .map(async (overlay) => {
1697
- await overlay.dismiss();
1698
- }));
1699
- }
1700
- getTopMost() {
1701
- return this.overlays[this.overlays.length - 1];
1702
- }
1703
- ngOnDestroy() {
1704
- this.destroy$.next();
1705
- this.destroy$.complete();
1706
- }
1707
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ModalController, deps: [{ token: ModalHelper }, { token: ActionSheetHelper }, { token: AlertHelper }, { token: ModalNavigationService }, { token: ROUTES, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
1708
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ModalController }); }
1709
- }
1710
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ModalController, decorators: [{
1711
- type: Injectable
1712
- }], ctorParameters: () => [{ type: ModalHelper }, { type: ActionSheetHelper }, { type: AlertHelper }, { type: ModalNavigationService }, { type: undefined, decorators: [{
1713
- type: Optional
1714
- }, {
1715
- type: Inject,
1716
- args: [ROUTES]
1717
- }] }] });
1718
-
402
+ var ModalWrapperComponent = class ModalWrapperComponent {
403
+ get _hasCollapsibleTitle() {
404
+ return !!this.config?.collapseTitle;
405
+ }
406
+ static {
407
+ this.KEYBOARD_HIDE_DELAY_IN_MS = 100;
408
+ }
409
+ set scrollDisabled(disabled) {
410
+ this.ionContent.scrollY = !disabled;
411
+ }
412
+ set canDismiss(callback) {
413
+ this.ionModalElement.canDismiss = this.canDismissHelper.getCanDismissCallback(callback);
414
+ }
415
+ get contentTitleElement() {
416
+ if (!this._contentTitleElement && this._hasCollapsibleTitle) this.changeDetector.detectChanges();
417
+ return this._contentTitleElement;
418
+ }
419
+ get intersectionObserver() {
420
+ if (!this._intersectionObserver) this._intersectionObserver = this.createModalWrapperIntersectionObserver();
421
+ return this._intersectionObserver;
422
+ }
423
+ get _isDrawer() {
424
+ return this.config.flavor === "drawer";
425
+ }
426
+ constructor(changeDetector, injector, elementRef, renderer, zone, resizeObserverService, windowRef, platform, canDismissHelper, environmentInjector, translations) {
427
+ this.changeDetector = changeDetector;
428
+ this.injector = injector;
429
+ this.elementRef = elementRef;
430
+ this.renderer = renderer;
431
+ this.zone = zone;
432
+ this.resizeObserverService = resizeObserverService;
433
+ this.windowRef = windowRef;
434
+ this.platform = platform;
435
+ this.canDismissHelper = canDismissHelper;
436
+ this.environmentInjector = environmentInjector;
437
+ this.translations = translations;
438
+ this.scrollY = Math.abs(this.windowRef.nativeWindow.scrollY);
439
+ this.VIEWPORT_RESIZE_DEBOUNCE_TIME = 100;
440
+ this.keyboardVisible = false;
441
+ this.toolbarButtons = [];
442
+ this.delayedClose = () => {};
443
+ this.viewportResized = false;
444
+ this.ionModalDidPresent = new Subject();
445
+ this.didPresent = firstValueFrom(this.ionModalDidPresent);
446
+ this.ionModalWillDismiss = new Subject();
447
+ this.willClose = firstValueFrom(this.ionModalWillDismiss);
448
+ this.viewportResize = new Subject();
449
+ this.viewportResize$ = this.viewportResize.asObservable().pipe(debounceTime(this.VIEWPORT_RESIZE_DEBOUNCE_TIME));
450
+ this.destroy$ = new Subject();
451
+ this.willClose$ = this.ionModalWillDismiss.pipe(first());
452
+ this._currentFooter = null;
453
+ this.setAriaLabelFromTitleContent = () => {
454
+ const titleTextContent = this.ionTitleElement?.nativeElement.textContent;
455
+ if (this.ionModalDialog && titleTextContent) this.renderer.setAttribute(this.ionModalDialog, "aria-label", titleTextContent);
456
+ };
457
+ this.setViewportHeight();
458
+ this.observeViewportResize();
459
+ this.modalElementsMoverDelegate = new ModalElementsMoverDelegate(renderer, elementRef);
460
+ }
461
+ ngOnInit() {
462
+ this.ionModalElement = this.elementRef.nativeElement.closest("ion-modal");
463
+ this.ionModalDialog = getIonModalDialogAncestor(this.elementRef.nativeElement);
464
+ this.initializeSizing();
465
+ this.initializeModalRoute();
466
+ this.listenForIonModalDidPresent();
467
+ this.listenForIonModalWillDismiss();
468
+ this.listenForScroll();
469
+ this.initializeResizeModalToModalWrapper();
470
+ this.focusTitleOnDidPresent();
471
+ this.componentPropsInjector = Injector.create({
472
+ providers: [{
473
+ provide: COMPONENT_PROPS,
474
+ useValue: this.config.componentProps
475
+ }],
476
+ parent: this.injector
477
+ });
478
+ this.modalWrapperInjector = Injector.create({
479
+ providers: [{
480
+ provide: ModalElementsAdvertiser,
481
+ useExisting: ModalWrapperComponent
482
+ }],
483
+ parent: this.injector
484
+ });
485
+ }
486
+ ngAfterViewInit() {
487
+ if (this.toolbarButtonsQuery) this.toolbarButtons = this.toolbarButtonsQuery.map((buttonRef) => buttonRef.nativeElement);
488
+ this.setAriaLabel();
489
+ }
490
+ set currentFooter(footer) {
491
+ if (this._currentFooter) this.resizeObserverService.unobserve(this._currentFooter);
492
+ this._currentFooter = footer;
493
+ if (footer !== null) this.resizeObserverService.observe(footer, (entry) => {
494
+ const [property, pixelValue] = ["--footer-height", `${Math.floor(entry.contentRect.height)}px`];
495
+ this.setCssVar(this.elementRef.nativeElement, property, pixelValue);
496
+ });
497
+ }
498
+ get currentFooter() {
499
+ return this._currentFooter;
500
+ }
501
+ addModalElement(type, modalElement) {
502
+ const addModalElementFn = {
503
+ [ModalElementType.FOOTER]: () => {
504
+ this.modalElementsMoverDelegate.addFooter(modalElement);
505
+ this.currentFooter = modalElement.nativeElement;
506
+ },
507
+ [ModalElementType.TITLE]: () => this.modalElementsMoverDelegate.addTitle(modalElement, this.contentTitleElement, this._hasCollapsibleTitle, this.ionTitleElement),
508
+ [ModalElementType.PAGE_PROGRESS]: () => this.modalElementsMoverDelegate.addPageProgress(modalElement, this.ionToolbarElement)
509
+ }[type];
510
+ addModalElementFn();
511
+ }
512
+ removeModalElement(type, modalElement) {
513
+ const removeModalElementFn = {
514
+ [ModalElementType.FOOTER]: () => {
515
+ this.modalElementsMoverDelegate.removeFooter(modalElement);
516
+ this.currentFooter = null;
517
+ },
518
+ [ModalElementType.TITLE]: () => this.modalElementsMoverDelegate.removeTitle(modalElement, this._hasCollapsibleTitle, this.contentTitleElement),
519
+ [ModalElementType.PAGE_PROGRESS]: () => this.modalElementsMoverDelegate.removePageProgress(modalElement)
520
+ }[type];
521
+ removeModalElementFn();
522
+ }
523
+ initializeResizeModalToModalWrapper() {
524
+ if (this.config.flavor === "drawer" && this.config.interactWithBackground) merge(this.ionModalDidPresent, this.viewportResize$).pipe(takeUntil(this.destroy$)).subscribe(() => {
525
+ setTimeout(() => {
526
+ const domRect = this.elementRef.nativeElement.getBoundingClientRect();
527
+ const right = this.windowRef.nativeWindow.document.documentElement.clientWidth - domRect.right;
528
+ this.renderer.setStyle(this.ionModalElement, "top", `${domRect.top}px`);
529
+ this.renderer.setStyle(this.ionModalElement, "left", `${domRect.left}px`);
530
+ this.renderer.setStyle(this.ionModalElement, "right", `${right}px`);
531
+ });
532
+ });
533
+ }
534
+ initializeSizing() {
535
+ if (this.config.size === "full-height") return;
536
+ this.patchScrollElementSize();
537
+ this.observeHeaderResize();
538
+ this.observeModalFullHeight();
539
+ }
540
+ initializeModalRoute() {
541
+ if (this.config.modalRoute) {
542
+ this.onSiblingModalRouteActivated(this.config.siblingModalRouteActivated$);
543
+ this.routerOutlet.activateWith(this.config.modalRoute, this.environmentInjector);
544
+ }
545
+ }
546
+ onSiblingModalRouteActivated(siblingModalRouteActivated$) {
547
+ if (!siblingModalRouteActivated$) return;
548
+ siblingModalRouteActivated$.pipe(takeUntil(this.willClose$)).subscribe((route) => {
549
+ if (this.routerOutlet.isActivated) this.routerOutlet.deactivate();
550
+ this.routerOutlet.activateWith(route, this.environmentInjector);
551
+ this.focusTitle();
552
+ });
553
+ }
554
+ patchScrollElementSize() {
555
+ if ("part" in HTMLElement.prototype) return;
556
+ this.ionContent.getScrollElement().then((scrollElement) => {
557
+ this.renderer.setStyle(scrollElement, "height", "100%");
558
+ this.renderer.setStyle(scrollElement, "position", "relative");
559
+ if (this.config.flavor === "drawer") this.renderer.setStyle(scrollElement, "transition", "padding-bottom " + DesignTokenHelper.softKeyboardTransitionLeave);
560
+ });
561
+ }
562
+ observeModalFullHeight() {
563
+ const ionModalWrapper = this.getIonModalWrapperElement();
564
+ if (!ionModalWrapper) return;
565
+ this.didPresent.then(() => {
566
+ this.intersectionObserver.observe(ionModalWrapper);
567
+ });
568
+ }
569
+ getIonModalWrapperElement() {
570
+ return this.ionModalElement.shadowRoot.querySelector(".modal-wrapper");
571
+ }
572
+ observeHeaderResize() {
573
+ this.resizeObserverService.observe(this.ionHeaderElement.nativeElement, (entry) => {
574
+ const [property, pixelValue] = ["--header-height", `${entry.contentRect.height}px`];
575
+ this.setCssVar(this.elementRef.nativeElement, property, pixelValue);
576
+ });
577
+ }
578
+ listenForIonModalDidPresent() {
579
+ if (this.ionModalElement) this.ionModalElement.addEventListener("ionModalDidPresent", () => {
580
+ this.ionModalDidPresent.next();
581
+ this.ionModalDidPresent.complete();
582
+ });
583
+ }
584
+ listenForIonModalWillDismiss() {
585
+ if (this.ionModalElement) this.ionModalElement.addEventListener("ionModalWillDismiss", () => {
586
+ this.ionModalWillDismiss.next();
587
+ this.ionModalWillDismiss.complete();
588
+ });
589
+ }
590
+ listenForScroll() {
591
+ const query = `(min-width: ${DesignTokenHelper.breakpoints.medium})`;
592
+ const mediaQuery = this.windowRef.nativeWindow.matchMedia(query);
593
+ const enableScrollEvents = (listOrEvent) => {
594
+ const isDesktop = listOrEvent.matches;
595
+ this.scrollEventsEnabled = !isDesktop;
596
+ };
597
+ enableScrollEvents(mediaQuery);
598
+ mediaQuery.onchange = enableScrollEvents;
599
+ this.zone.runOutsideAngular(() => {
600
+ fromEvent(this.ionContentElement.nativeElement, "ionScroll").pipe(debounceTime(contentScrollDebounceTimeInMS), map((event) => event.detail), takeUntil(this.destroy$)).subscribe((scrollInfo) => {
601
+ const contentScrolledPastOffset = scrollInfo.scrollTop > contentScrolledOffsetInPixels;
602
+ if (contentScrolledPastOffset !== this.isContentScrolled) {
603
+ this.isContentScrolled = contentScrolledPastOffset;
604
+ this.changeDetector.detectChanges();
605
+ }
606
+ });
607
+ });
608
+ }
609
+ observeTitleContentChanges() {
610
+ this.mutationObserverUnobserveFn = observeContent(this.ionTitleElement.nativeElement, this.setAriaLabelFromTitleContent);
611
+ }
612
+ setAriaLabel() {
613
+ const ariaLabel = this.config.htmlAttributes?.["aria-label"];
614
+ const ionModalElementDialog = getIonModalDialogAncestor(this.ionModalElement);
615
+ if (ionModalElementDialog && ariaLabel) this.renderer.setAttribute(ionModalElementDialog, "aria-label", ariaLabel);
616
+ else {
617
+ this.setAriaLabelFromTitleContent();
618
+ this.observeTitleContentChanges();
619
+ }
620
+ }
621
+ focusTitleOnDidPresent() {
622
+ this.ionModalDidPresent.pipe(takeUntil(this.willClose$)).subscribe(() => {
623
+ this.focusTitle();
624
+ });
625
+ }
626
+ focusTitle() {
627
+ queueMicrotask(() => {
628
+ if (this.ionContentElement?.nativeElement.contains(document.activeElement)) return;
629
+ this.ionTitleElement?.nativeElement.focus();
630
+ });
631
+ }
632
+ scrollToTop(scrollDuration) {
633
+ this.ionContent.scrollToTop(scrollDuration || 0);
634
+ }
635
+ scrollToBottom(scrollDuration) {
636
+ this.ionContent.scrollToBottom(scrollDuration || 0);
637
+ }
638
+ async close(data) {
639
+ if (!this.ionModalElement) return;
640
+ if (!this.keyboardVisible || !this.viewportResized) {
641
+ clearTimeout(this.delayedCloseTimeoutId);
642
+ await this.ionModalElement.dismiss(data);
643
+ return;
644
+ }
645
+ this.blurActiveElement();
646
+ return new Promise((resolve) => {
647
+ this.delayedClose = async () => {
648
+ await this.ionModalElement.dismiss(data);
649
+ resolve();
650
+ };
651
+ this.delayedCloseTimeoutId = setTimeout(this.delayedClose, ModalWrapperComponent.KEYBOARD_HIDE_DELAY_IN_MS);
652
+ });
653
+ }
654
+ onFocusChange() {
655
+ this.windowRef.nativeWindow.scrollTo({ top: this.scrollY });
656
+ }
657
+ _onKeyboardShow(keyboardHeight) {
658
+ this.setKeyboardVisibility(keyboardHeight);
659
+ }
660
+ _onKeyboardHide() {
661
+ this.setKeyboardVisibility(0);
662
+ }
663
+ toggleContentMaxHeight(freeze) {
664
+ if (!(this.config.flavor === "modal" && this.platform.isPhabletOrBigger())) return;
665
+ const style = "max-height";
666
+ const contentElement = this.ionContentElement.nativeElement;
667
+ this.zone.run(() => {
668
+ if (freeze) {
669
+ const contentHeight = contentElement.offsetHeight;
670
+ this.renderer.setStyle(contentElement, style, `${contentHeight}px`);
671
+ } else this.renderer.removeStyle(contentElement, style);
672
+ });
673
+ }
674
+ setKeyboardVisibility(keyboardHeight) {
675
+ const keyboardAlreadyVisible = keyboardHeight > 0 && this.keyboardVisible;
676
+ const keyboardAlreadyHidden = keyboardHeight === 0 && !this.keyboardVisible;
677
+ if (keyboardAlreadyVisible || keyboardAlreadyHidden) return;
678
+ this.keyboardVisible = keyboardHeight > 0;
679
+ this.toggleContentMaxHeight(this.keyboardVisible);
680
+ this.setKeyboardOverlap(keyboardHeight);
681
+ }
682
+ getViewportHeight() {
683
+ return this.initialViewportHeight || this.windowRef.nativeWindow.innerHeight;
684
+ }
685
+ getKeyboardOverlap(keyboardHeight, element) {
686
+ const viewportHeight = this.getViewportHeight();
687
+ if (keyboardHeight <= 0 || !element || !viewportHeight) return 0;
688
+ const elementDistanceAboveBottomOfScreen = Math.floor(viewportHeight - element.getBoundingClientRect().bottom);
689
+ return Math.max(keyboardHeight - elementDistanceAboveBottomOfScreen, 0);
690
+ }
691
+ setCssVar(element, property, value) {
692
+ this.zone.run(() => this.renderer.setStyle(element, property, value, RendererStyleFlags2.DashCase));
693
+ }
694
+ toggleCssClass(element, klass, condition) {
695
+ this.zone.run(() => condition ? this.renderer.addClass(element, klass) : this.renderer.removeClass(element, klass));
696
+ }
697
+ setKeyboardOverlap(keyboardHeight) {
698
+ this.toggleCssClass(this.elementRef.nativeElement, "keyboard-visible", this.keyboardVisible);
699
+ this.liftFooterAboveKeyboard(keyboardHeight);
700
+ this.reserveContentScrollRoom(keyboardHeight);
701
+ }
702
+ liftFooterAboveKeyboard(keyboardHeight) {
703
+ const footer = this.currentFooter;
704
+ if (!footer) return;
705
+ const keyboardOverlap = this.getKeyboardOverlap(keyboardHeight, this.elementRef.nativeElement);
706
+ this.setCssVar(footer, "--keyboard-offset", `${keyboardOverlap}px`);
707
+ }
708
+ reserveContentScrollRoom(keyboardHeight) {
709
+ const contentKeyboardOverlap = this.currentFooter?.classList.contains("snap-to-keyboard") ?? false ? this.getKeyboardOverlap(keyboardHeight, this.elementRef.nativeElement) : this.getKeyboardOverlap(keyboardHeight, this.ionContentElement.nativeElement);
710
+ this.setCssVar(this.elementRef.nativeElement, "--kirby-keyboard-content-overlap", `${contentKeyboardOverlap}px`);
711
+ }
712
+ onHeaderTouchStart(event) {
713
+ if (this.keyboardVisible) {
714
+ if (!this.toolbarButtons.some((button) => {
715
+ return event.target instanceof HTMLElement && (event.target === button || button.contains(event.target));
716
+ })) this.blurActiveElement();
717
+ }
718
+ }
719
+ _onWindowResize() {
720
+ this.setViewportHeight();
721
+ }
722
+ setViewportHeight() {
723
+ const vh = (this.windowRef.nativeWindow.innerHeight * .01).toFixed(2);
724
+ this.setCssVar(this.elementRef.nativeElement, "--vh", `${vh}px`);
725
+ }
726
+ observeViewportResize() {
727
+ this.resizeObserverService.observe(this.windowRef.nativeWindow.document.body, (entry) => this.onViewportResize(entry));
728
+ }
729
+ onViewportResize(entry) {
730
+ if (!this.initialViewportHeight) {
731
+ this.initialViewportHeight = entry.contentRect.height;
732
+ return;
733
+ }
734
+ this.viewportResized = entry.contentRect.height !== this.initialViewportHeight;
735
+ if (!this.viewportResized) {
736
+ if (this.delayedCloseTimeoutId) {
737
+ clearTimeout(this.delayedCloseTimeoutId);
738
+ this.delayedClose();
739
+ }
740
+ }
741
+ this.viewportResize.next();
742
+ }
743
+ blurActiveElement() {
744
+ const BLUR_TARGET_SELECTOR = "input, textarea";
745
+ if (this.keyboardVisible) {
746
+ if (document.activeElement instanceof HTMLElement && document.activeElement.matches(BLUR_TARGET_SELECTOR)) document.activeElement.blur();
747
+ }
748
+ }
749
+ createModalWrapperIntersectionObserver() {
750
+ const callback = (entries) => {
751
+ if (entries[0].intersectionRatio < 1) this.ionModalElement.classList.add("full-height");
752
+ else this.ionModalElement.classList.remove("full-height");
753
+ };
754
+ const options = {
755
+ rootMargin: "0px 0px -1px 0px",
756
+ root: this.windowRef.nativeWindow.frameElement ? this.windowRef.nativeWindow.document : void 0,
757
+ threshold: [.99, 1]
758
+ };
759
+ return new IntersectionObserver(callback, options);
760
+ }
761
+ ngOnDestroy() {
762
+ if (this.routerOutlet.isActivated) this.routerOutlet.deactivate();
763
+ this.mutationObserverUnobserveFn?.();
764
+ this.intersectionObserver.disconnect();
765
+ delete this._intersectionObserver;
766
+ if (this.resizeObserverService) {
767
+ this.resizeObserverService.unobserve(this.windowRef.nativeWindow.document.body);
768
+ this.resizeObserverService.unobserve(this.ionHeaderElement.nativeElement);
769
+ this.resizeObserverService.unobserve(this.currentFooter);
770
+ }
771
+ this.destroy$.next();
772
+ this.destroy$.complete();
773
+ }
774
+ static {
775
+ this.ɵfac = i0.ɵɵngDeclareFactory({
776
+ minVersion: "12.0.0",
777
+ version: "22.2.3",
778
+ ngImport: i0,
779
+ type: ModalWrapperComponent,
780
+ deps: [
781
+ { token: i0.ChangeDetectorRef },
782
+ { token: i0.Injector },
783
+ { token: i0.ElementRef },
784
+ { token: i0.Renderer2 },
785
+ { token: i0.NgZone },
786
+ { token: i1.ResizeObserverService },
787
+ { token: i1$2.WindowRef },
788
+ { token: i3.PlatformService },
789
+ { token: CanDismissHelper },
790
+ { token: i0.EnvironmentInjector },
791
+ { token: i1.TranslationService }
792
+ ],
793
+ target: i0.ɵɵFactoryTarget.Component
794
+ });
795
+ }
796
+ static {
797
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
798
+ minVersion: "17.0.0",
799
+ version: "22.2.3",
800
+ type: ModalWrapperComponent,
801
+ isStandalone: true,
802
+ selector: "kirby-modal-wrapper",
803
+ inputs: {
804
+ scrollDisabled: "scrollDisabled",
805
+ config: "config",
806
+ content: "content"
807
+ },
808
+ host: {
809
+ listeners: {
810
+ "window:focus": "onFocusChange()",
811
+ "window:focusout": "onFocusChange()",
812
+ "window:ionKeyboardDidShow": "_onKeyboardShow($event.detail.keyboardHeight)",
813
+ "window:keyboardWillShow": "_onKeyboardShow($event.keyboardHeight)",
814
+ "window:ionKeyboardDidHide": "_onKeyboardHide()",
815
+ "window:keyboardWillHide": "_onKeyboardHide()",
816
+ "window:resize": "_onWindowResize()"
817
+ },
818
+ properties: {
819
+ "class.collapsible-title": "this._hasCollapsibleTitle",
820
+ "class.drawer": "this._isDrawer"
821
+ }
822
+ },
823
+ providers: [{
824
+ provide: Modal,
825
+ useExisting: ModalWrapperComponent
826
+ }, {
827
+ provide: ModalElementsAdvertiser,
828
+ useExisting: ModalWrapperComponent
829
+ }],
830
+ queries: [{
831
+ propertyName: "templateRef",
832
+ first: true,
833
+ predicate: TemplateRef,
834
+ descendants: true
835
+ }],
836
+ viewQueries: [
837
+ {
838
+ propertyName: "ionContent",
839
+ first: true,
840
+ predicate: IonContent,
841
+ descendants: true,
842
+ static: true
843
+ },
844
+ {
845
+ propertyName: "ionContentElement",
846
+ first: true,
847
+ predicate: IonContent,
848
+ descendants: true,
849
+ read: ElementRef,
850
+ static: true
851
+ },
852
+ {
853
+ propertyName: "ionHeaderElement",
854
+ first: true,
855
+ predicate: IonHeader,
856
+ descendants: true,
857
+ read: ElementRef,
858
+ static: true
859
+ },
860
+ {
861
+ propertyName: "ionToolbarElement",
862
+ first: true,
863
+ predicate: IonToolbar,
864
+ descendants: true,
865
+ read: ElementRef,
866
+ static: true
867
+ },
868
+ {
869
+ propertyName: "ionTitleElement",
870
+ first: true,
871
+ predicate: IonTitle,
872
+ descendants: true,
873
+ read: ElementRef,
874
+ static: true
875
+ },
876
+ {
877
+ propertyName: "routerOutlet",
878
+ first: true,
879
+ predicate: RouterOutlet,
880
+ descendants: true,
881
+ static: true
882
+ },
883
+ {
884
+ propertyName: "_contentTitleElement",
885
+ first: true,
886
+ predicate: ["contentTitle"],
887
+ descendants: true,
888
+ read: ElementRef
889
+ },
890
+ {
891
+ propertyName: "toolbarButtonsQuery",
892
+ predicate: ButtonComponent,
893
+ descendants: true,
894
+ read: ElementRef
895
+ }
896
+ ],
897
+ ngImport: i0,
898
+ template: "<ion-header\n role=\"presentation\"\n [class.content-scrolled]=\"isContentScrolled\"\n (touchstart)=\"onHeaderTouchStart($event)\"\n>\n <ion-toolbar>\n <ion-title role=\"heading\" aria-level=\"2\" tabindex=\"-1\"></ion-title>\n @if (config.flavor === 'drawer' && config.drawerSupplementaryAction) {\n <ion-buttons slot=\"secondary\">\n <button\n kirby-button\n attentionLevel=\"3\"\n size=\"md\"\n (click)=\"config.drawerSupplementaryAction.action($event)\"\n >\n <kirby-icon [name]=\"config.drawerSupplementaryAction.iconName\"></kirby-icon>\n </button>\n </ion-buttons>\n }\n <ion-buttons slot=\"primary\">\n <button\n kirby-button\n attentionLevel=\"3\"\n size=\"md\"\n [noDecoration]=\"config.interactWithBackground\"\n [attr.aria-label]=\"translations.get('close')\"\n (click)=\"close()\"\n >\n <kirby-icon name=\"close\"></kirby-icon>\n </button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n<ion-content [scrollEvents]=\"scrollEventsEnabled\">\n @if (_hasCollapsibleTitle) {\n <ion-header collapse=\"condense\">\n <ion-toolbar>\n <span class=\"kirby-text-xlarge\" #contentTitle></span>\n </ion-toolbar>\n </ion-header>\n }\n\n <!-- Outlet for ModalController -->\n <ng-container\n *ngComponentOutlet=\"config.component; injector: componentPropsInjector\"\n ></ng-container>\n\n <!-- Outlet for projected content -->\n <ng-container *ngTemplateOutlet=\"content; injector: modalWrapperInjector\"></ng-container>\n\n <!-- Outlet for route-based modal -->\n <router-outlet\n name=\"kirbyModalWrapperOutlet\"\n [style.visibility]=\"config.modalRoute ? 'visible' : 'hidden'\"\n ></router-outlet>\n</ion-content>\n",
899
+ styles: [".kirby-line-clamp{display:-webkit-box;-webkit-line-clamp:var(--line-clamp, none);-webkit-box-orient:vertical;overflow:hidden}ion-header{box-sizing:border-box}ion-header ion-toolbar{--padding-start: var(--kirby-spacing-xxs);--padding-end: var(--kirby-spacing-xxs);--padding-bottom: calc(var(--kirby-spacing-xxs) - var(--kirby-stroke-xs));--padding-top: var(--kirby-spacing-xxs);--border-width: 0;--background: transparent;--color: var(--kirby-modal-color, var(--kirby-color-content-base));border-bottom:var(--kirby-stroke-xs) solid transparent;transition:border-color var(--kirby-transition-duration-quick) linear}@media(min-width:768px){ion-header ion-toolbar{--padding-start: var(--kirby-spacing-m);--padding-end: var(--kirby-spacing-m);--padding-bottom: calc(var(--kirby-spacing-m) - var(--kirby-stroke-xs));--padding-top: var(--kirby-spacing-m);padding-inline:0}}ion-header ion-toolbar button{color:var(--color)}:host{--vh100: var(--vh, 1vh) * 100;--header-height: 0px;--footer-height: 0px;--kirby-modal-safe-area-bottom: var(--ion-safe-area-bottom)}@media(max-width:767px){:host.drawer ion-header ion-toolbar{--padding-top: var(--kirby-spacing-s)}:host.drawer ion-header ion-toolbar:first-of-type{padding-top:0}}@media(min-width:768px){ion-header ion-toolbar{border-bottom-color:var(--kirby-color-border-base-silent)}}ion-header.content-scrolled ion-toolbar{border-bottom-color:var(--kirby-color-border-base-silent)}:host-context(ion-modal.no-header-area-border) ion-header ion-toolbar{border-bottom-color:transparent}@media(max-width:767px){:host-context(ion-modal.kirby-drawer:not(.kirby-modal-full-height)){padding-top:0;position:relative;contain:inherit;min-height:min(var(--min-height),var(--vh100) - var(--kirby-modal-padding-top, 0px))}:host-context(ion-modal.kirby-drawer:not(.kirby-modal-full-height)) ion-content{contain:content;max-height:calc(var(--vh100) - var(--kirby-modal-padding-top, 0px) - var(--header-height) - var(--footer-height))}:host-context(ion-modal.kirby-drawer:not(.kirby-modal-full-height)) ion-content::part(scroll){height:\"100%\";position:relative}:host-context(ion-modal.kirby-drawer:not(.kirby-modal-full-height)).drawer ion-content::part(scroll){transition:padding-bottom var(--kirby-transition-soft-keyboard-leave)}:host-context(ion-modal.kirby-drawer:not(.kirby-modal-full-height)).drawer.keyboard-visible ion-content::part(scroll){transition:padding-bottom var(--kirby-transition-soft-keyboard-enter)}}:host-context(ion-modal.kirby-drawer.interact-with-background){padding-top:0;position:relative;contain:inherit;min-height:min(var(--min-height),var(--vh100) - var(--kirby-modal-padding-top, 0px))}:host-context(ion-modal.kirby-drawer.interact-with-background) ion-content{contain:content;max-height:calc(var(--vh100) - var(--kirby-modal-padding-top, 0px) - var(--header-height) - var(--footer-height))}:host-context(ion-modal.kirby-drawer.interact-with-background) ion-content::part(scroll){height:\"100%\";position:relative}:host-context(ion-modal.kirby-drawer.interact-with-background).drawer ion-content::part(scroll){transition:padding-bottom var(--kirby-transition-soft-keyboard-leave)}:host-context(ion-modal.kirby-drawer.interact-with-background).drawer.keyboard-visible ion-content::part(scroll){transition:padding-bottom var(--kirby-transition-soft-keyboard-enter)}:host-context(ion-modal.kirby-drawer.interact-with-background) ion-header ion-toolbar{border-bottom-color:transparent}:host-context(ion-modal.modal-card:not(.kirby-drawer)) ion-header ion-toolbar:first-of-type{padding-top:var(--kirby-safe-area-top, 0)}@media(min-width:768px){:host-context(ion-modal.modal-card:not(.kirby-drawer)) ion-header ion-toolbar:first-of-type{--padding-start: var(--kirby-spacing-m);--padding-end: var(--kirby-spacing-m);--padding-bottom: calc(var(--kirby-spacing-m) - var(--kirby-stroke-xs));--padding-top: var(--kirby-spacing-m);padding-inline:0}}ion-title{box-sizing:border-box;padding-inline:calc(48px + var(--padding-start)) calc(48px + var(--padding-end));font-size:min(var(--kirby-font-size-n),19.2px);font-weight:var(--kirby-font-weight-bold);outline:none}ion-content{--background: transparent;--color: var(--kirby-modal-color, var(--kirby-color-content-base));--padding-top: var(--kirby-spacing-m);--padding-bottom: calc(var(--kirby-spacing-m) + var(--kirby-modal-safe-area-bottom));--padding-start: var(--kirby-spacing-s);--padding-end: var(--kirby-spacing-s);display:flex;flex-direction:column;height:calc(var(--height) - var(--header-height) - var(--footer-height));max-height:calc(var(--max-height) - var(--header-height) - var(--footer-height))}ion-content ::ng-deep>*{box-sizing:border-box;display:block}:host(:has(kirby-modal-footer)) ion-content{--padding-bottom: var(--kirby-spacing-m)}:host(.keyboard-visible) ion-content{--padding-bottom: calc( var(--kirby-spacing-m) + var(--kirby-keyboard-content-overlap, 0px) - var(--keyboard-offset, 0px) )}@media(min-width:768px){ion-content{--padding-start: var(--kirby-spacing-xxl);--padding-end: var(--kirby-spacing-xxl)}}:host(.collapsible-title) ion-content ion-toolbar:first-of-type{--padding-top: 0px;--padding-bottom: var(--kirby-spacing-l);--padding-start: var(--kirby-spacing-xxs);--padding-end: var(--kirby-spacing-xxs);border:none}@media(min-width:768px){:host(.collapsible-title) ion-content ion-toolbar:first-of-type{--padding-start: var(--kirby-spacing-s);--padding-end: var(--kirby-spacing-s)}}\n"],
900
+ dependencies: [
901
+ {
902
+ kind: "ngmodule",
903
+ type: RouterModule
904
+ },
905
+ {
906
+ kind: "directive",
907
+ type: i5.RouterOutlet,
908
+ selector: "router-outlet",
909
+ inputs: ["name", "routerOutletData"],
910
+ outputs: [
911
+ "activate",
912
+ "deactivate",
913
+ "attach",
914
+ "detach"
915
+ ],
916
+ exportAs: ["outlet"]
917
+ },
918
+ {
919
+ kind: "component",
920
+ type: ButtonComponent,
921
+ selector: "button[kirby-button],Button[kirby-button],a[kirby-button]",
922
+ inputs: [
923
+ "attentionLevel",
924
+ "noDecoration",
925
+ "themeColor",
926
+ "expand",
927
+ "isFloating",
928
+ "size",
929
+ "showIconOnly"
930
+ ]
931
+ },
932
+ {
933
+ kind: "component",
934
+ type: IconComponent,
935
+ selector: "kirby-icon",
936
+ inputs: ["size", "name"]
937
+ },
938
+ {
939
+ kind: "ngmodule",
940
+ type: CommonModule
941
+ },
942
+ {
943
+ kind: "directive",
944
+ type: i2.NgComponentOutlet,
945
+ selector: "[ngComponentOutlet]",
946
+ inputs: [
947
+ "ngComponentOutlet",
948
+ "ngComponentOutletInputs",
949
+ "ngComponentOutletInjector",
950
+ "ngComponentOutletEnvironmentInjector",
951
+ "ngComponentOutletContent",
952
+ "ngComponentOutletNgModule"
953
+ ],
954
+ exportAs: ["ngComponentOutlet"]
955
+ },
956
+ {
957
+ kind: "directive",
958
+ type: i2.NgTemplateOutlet,
959
+ selector: "[ngTemplateOutlet]",
960
+ inputs: [
961
+ "ngTemplateOutletContext",
962
+ "ngTemplateOutlet",
963
+ "ngTemplateOutletInjector"
964
+ ]
965
+ },
966
+ {
967
+ kind: "component",
968
+ type: IonHeader,
969
+ selector: "ion-header",
970
+ inputs: [
971
+ "collapse",
972
+ "mode",
973
+ "translucent"
974
+ ]
975
+ },
976
+ {
977
+ kind: "component",
978
+ type: IonToolbar,
979
+ selector: "ion-toolbar",
980
+ inputs: ["color", "mode"]
981
+ },
982
+ {
983
+ kind: "component",
984
+ type: IonTitle,
985
+ selector: "ion-title",
986
+ inputs: ["color", "size"]
987
+ },
988
+ {
989
+ kind: "component",
990
+ type: IonButtons,
991
+ selector: "ion-buttons",
992
+ inputs: ["collapse"]
993
+ },
994
+ {
995
+ kind: "component",
996
+ type: IonContent,
997
+ selector: "ion-content",
998
+ inputs: [
999
+ "color",
1000
+ "fixedSlotPlacement",
1001
+ "forceOverscroll",
1002
+ "fullscreen",
1003
+ "scrollEvents",
1004
+ "scrollX",
1005
+ "scrollY"
1006
+ ],
1007
+ outputs: [
1008
+ "ionScrollStart",
1009
+ "ionScroll",
1010
+ "ionScrollEnd"
1011
+ ]
1012
+ }
1013
+ ],
1014
+ changeDetection: i0.ChangeDetectionStrategy.Eager
1015
+ });
1016
+ }
1017
+ };
1018
+ i0.ɵɵngDeclareClassMetadata({
1019
+ minVersion: "12.0.0",
1020
+ version: "22.2.3",
1021
+ ngImport: i0,
1022
+ type: ModalWrapperComponent,
1023
+ decorators: [{
1024
+ type: Component,
1025
+ args: [{
1026
+ imports: [
1027
+ RouterModule,
1028
+ ButtonComponent,
1029
+ IconComponent,
1030
+ CommonModule,
1031
+ IonHeader,
1032
+ IonToolbar,
1033
+ IonTitle,
1034
+ IonButtons,
1035
+ IonContent
1036
+ ],
1037
+ selector: "kirby-modal-wrapper",
1038
+ changeDetection: ChangeDetectionStrategy.Eager,
1039
+ providers: [{
1040
+ provide: Modal,
1041
+ useExisting: ModalWrapperComponent
1042
+ }, {
1043
+ provide: ModalElementsAdvertiser,
1044
+ useExisting: ModalWrapperComponent
1045
+ }],
1046
+ template: "<ion-header\n role=\"presentation\"\n [class.content-scrolled]=\"isContentScrolled\"\n (touchstart)=\"onHeaderTouchStart($event)\"\n>\n <ion-toolbar>\n <ion-title role=\"heading\" aria-level=\"2\" tabindex=\"-1\"></ion-title>\n @if (config.flavor === 'drawer' && config.drawerSupplementaryAction) {\n <ion-buttons slot=\"secondary\">\n <button\n kirby-button\n attentionLevel=\"3\"\n size=\"md\"\n (click)=\"config.drawerSupplementaryAction.action($event)\"\n >\n <kirby-icon [name]=\"config.drawerSupplementaryAction.iconName\"></kirby-icon>\n </button>\n </ion-buttons>\n }\n <ion-buttons slot=\"primary\">\n <button\n kirby-button\n attentionLevel=\"3\"\n size=\"md\"\n [noDecoration]=\"config.interactWithBackground\"\n [attr.aria-label]=\"translations.get('close')\"\n (click)=\"close()\"\n >\n <kirby-icon name=\"close\"></kirby-icon>\n </button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n<ion-content [scrollEvents]=\"scrollEventsEnabled\">\n @if (_hasCollapsibleTitle) {\n <ion-header collapse=\"condense\">\n <ion-toolbar>\n <span class=\"kirby-text-xlarge\" #contentTitle></span>\n </ion-toolbar>\n </ion-header>\n }\n\n <!-- Outlet for ModalController -->\n <ng-container\n *ngComponentOutlet=\"config.component; injector: componentPropsInjector\"\n ></ng-container>\n\n <!-- Outlet for projected content -->\n <ng-container *ngTemplateOutlet=\"content; injector: modalWrapperInjector\"></ng-container>\n\n <!-- Outlet for route-based modal -->\n <router-outlet\n name=\"kirbyModalWrapperOutlet\"\n [style.visibility]=\"config.modalRoute ? 'visible' : 'hidden'\"\n ></router-outlet>\n</ion-content>\n",
1047
+ styles: [".kirby-line-clamp{display:-webkit-box;-webkit-line-clamp:var(--line-clamp, none);-webkit-box-orient:vertical;overflow:hidden}ion-header{box-sizing:border-box}ion-header ion-toolbar{--padding-start: var(--kirby-spacing-xxs);--padding-end: var(--kirby-spacing-xxs);--padding-bottom: calc(var(--kirby-spacing-xxs) - var(--kirby-stroke-xs));--padding-top: var(--kirby-spacing-xxs);--border-width: 0;--background: transparent;--color: var(--kirby-modal-color, var(--kirby-color-content-base));border-bottom:var(--kirby-stroke-xs) solid transparent;transition:border-color var(--kirby-transition-duration-quick) linear}@media(min-width:768px){ion-header ion-toolbar{--padding-start: var(--kirby-spacing-m);--padding-end: var(--kirby-spacing-m);--padding-bottom: calc(var(--kirby-spacing-m) - var(--kirby-stroke-xs));--padding-top: var(--kirby-spacing-m);padding-inline:0}}ion-header ion-toolbar button{color:var(--color)}:host{--vh100: var(--vh, 1vh) * 100;--header-height: 0px;--footer-height: 0px;--kirby-modal-safe-area-bottom: var(--ion-safe-area-bottom)}@media(max-width:767px){:host.drawer ion-header ion-toolbar{--padding-top: var(--kirby-spacing-s)}:host.drawer ion-header ion-toolbar:first-of-type{padding-top:0}}@media(min-width:768px){ion-header ion-toolbar{border-bottom-color:var(--kirby-color-border-base-silent)}}ion-header.content-scrolled ion-toolbar{border-bottom-color:var(--kirby-color-border-base-silent)}:host-context(ion-modal.no-header-area-border) ion-header ion-toolbar{border-bottom-color:transparent}@media(max-width:767px){:host-context(ion-modal.kirby-drawer:not(.kirby-modal-full-height)){padding-top:0;position:relative;contain:inherit;min-height:min(var(--min-height),var(--vh100) - var(--kirby-modal-padding-top, 0px))}:host-context(ion-modal.kirby-drawer:not(.kirby-modal-full-height)) ion-content{contain:content;max-height:calc(var(--vh100) - var(--kirby-modal-padding-top, 0px) - var(--header-height) - var(--footer-height))}:host-context(ion-modal.kirby-drawer:not(.kirby-modal-full-height)) ion-content::part(scroll){height:\"100%\";position:relative}:host-context(ion-modal.kirby-drawer:not(.kirby-modal-full-height)).drawer ion-content::part(scroll){transition:padding-bottom var(--kirby-transition-soft-keyboard-leave)}:host-context(ion-modal.kirby-drawer:not(.kirby-modal-full-height)).drawer.keyboard-visible ion-content::part(scroll){transition:padding-bottom var(--kirby-transition-soft-keyboard-enter)}}:host-context(ion-modal.kirby-drawer.interact-with-background){padding-top:0;position:relative;contain:inherit;min-height:min(var(--min-height),var(--vh100) - var(--kirby-modal-padding-top, 0px))}:host-context(ion-modal.kirby-drawer.interact-with-background) ion-content{contain:content;max-height:calc(var(--vh100) - var(--kirby-modal-padding-top, 0px) - var(--header-height) - var(--footer-height))}:host-context(ion-modal.kirby-drawer.interact-with-background) ion-content::part(scroll){height:\"100%\";position:relative}:host-context(ion-modal.kirby-drawer.interact-with-background).drawer ion-content::part(scroll){transition:padding-bottom var(--kirby-transition-soft-keyboard-leave)}:host-context(ion-modal.kirby-drawer.interact-with-background).drawer.keyboard-visible ion-content::part(scroll){transition:padding-bottom var(--kirby-transition-soft-keyboard-enter)}:host-context(ion-modal.kirby-drawer.interact-with-background) ion-header ion-toolbar{border-bottom-color:transparent}:host-context(ion-modal.modal-card:not(.kirby-drawer)) ion-header ion-toolbar:first-of-type{padding-top:var(--kirby-safe-area-top, 0)}@media(min-width:768px){:host-context(ion-modal.modal-card:not(.kirby-drawer)) ion-header ion-toolbar:first-of-type{--padding-start: var(--kirby-spacing-m);--padding-end: var(--kirby-spacing-m);--padding-bottom: calc(var(--kirby-spacing-m) - var(--kirby-stroke-xs));--padding-top: var(--kirby-spacing-m);padding-inline:0}}ion-title{box-sizing:border-box;padding-inline:calc(48px + var(--padding-start)) calc(48px + var(--padding-end));font-size:min(var(--kirby-font-size-n),19.2px);font-weight:var(--kirby-font-weight-bold);outline:none}ion-content{--background: transparent;--color: var(--kirby-modal-color, var(--kirby-color-content-base));--padding-top: var(--kirby-spacing-m);--padding-bottom: calc(var(--kirby-spacing-m) + var(--kirby-modal-safe-area-bottom));--padding-start: var(--kirby-spacing-s);--padding-end: var(--kirby-spacing-s);display:flex;flex-direction:column;height:calc(var(--height) - var(--header-height) - var(--footer-height));max-height:calc(var(--max-height) - var(--header-height) - var(--footer-height))}ion-content ::ng-deep>*{box-sizing:border-box;display:block}:host(:has(kirby-modal-footer)) ion-content{--padding-bottom: var(--kirby-spacing-m)}:host(.keyboard-visible) ion-content{--padding-bottom: calc( var(--kirby-spacing-m) + var(--kirby-keyboard-content-overlap, 0px) - var(--keyboard-offset, 0px) )}@media(min-width:768px){ion-content{--padding-start: var(--kirby-spacing-xxl);--padding-end: var(--kirby-spacing-xxl)}}:host(.collapsible-title) ion-content ion-toolbar:first-of-type{--padding-top: 0px;--padding-bottom: var(--kirby-spacing-l);--padding-start: var(--kirby-spacing-xxs);--padding-end: var(--kirby-spacing-xxs);border:none}@media(min-width:768px){:host(.collapsible-title) ion-content ion-toolbar:first-of-type{--padding-start: var(--kirby-spacing-s);--padding-end: var(--kirby-spacing-s)}}\n"]
1048
+ }]
1049
+ }],
1050
+ ctorParameters: () => [
1051
+ { type: i0.ChangeDetectorRef },
1052
+ { type: i0.Injector },
1053
+ { type: i0.ElementRef },
1054
+ { type: i0.Renderer2 },
1055
+ { type: i0.NgZone },
1056
+ { type: i1.ResizeObserverService },
1057
+ { type: i1$2.WindowRef },
1058
+ { type: i3.PlatformService },
1059
+ { type: CanDismissHelper },
1060
+ { type: i0.EnvironmentInjector },
1061
+ { type: i1.TranslationService }
1062
+ ],
1063
+ propDecorators: {
1064
+ _hasCollapsibleTitle: [{
1065
+ type: HostBinding,
1066
+ args: ["class.collapsible-title"]
1067
+ }],
1068
+ scrollDisabled: [{ type: Input }],
1069
+ config: [{ type: Input }],
1070
+ content: [{ type: Input }],
1071
+ templateRef: [{
1072
+ type: ContentChild,
1073
+ args: [TemplateRef]
1074
+ }],
1075
+ toolbarButtonsQuery: [{
1076
+ type: ViewChildren,
1077
+ args: [ButtonComponent, { read: ElementRef }]
1078
+ }],
1079
+ ionContent: [{
1080
+ type: ViewChild,
1081
+ args: [IonContent, { static: true }]
1082
+ }],
1083
+ ionContentElement: [{
1084
+ type: ViewChild,
1085
+ args: [IonContent, {
1086
+ static: true,
1087
+ read: ElementRef
1088
+ }]
1089
+ }],
1090
+ ionHeaderElement: [{
1091
+ type: ViewChild,
1092
+ args: [IonHeader, {
1093
+ static: true,
1094
+ read: ElementRef
1095
+ }]
1096
+ }],
1097
+ ionToolbarElement: [{
1098
+ type: ViewChild,
1099
+ args: [IonToolbar, {
1100
+ static: true,
1101
+ read: ElementRef
1102
+ }]
1103
+ }],
1104
+ ionTitleElement: [{
1105
+ type: ViewChild,
1106
+ args: [IonTitle, {
1107
+ static: true,
1108
+ read: ElementRef
1109
+ }]
1110
+ }],
1111
+ routerOutlet: [{
1112
+ type: ViewChild,
1113
+ args: [RouterOutlet, { static: true }]
1114
+ }],
1115
+ _contentTitleElement: [{
1116
+ type: ViewChild,
1117
+ args: ["contentTitle", { read: ElementRef }]
1118
+ }],
1119
+ _isDrawer: [{
1120
+ type: HostBinding,
1121
+ args: ["class.drawer"]
1122
+ }],
1123
+ onFocusChange: [{
1124
+ type: HostListener,
1125
+ args: ["window:focus"]
1126
+ }, {
1127
+ type: HostListener,
1128
+ args: ["window:focusout"]
1129
+ }],
1130
+ _onKeyboardShow: [{
1131
+ type: HostListener,
1132
+ args: ["window:ionKeyboardDidShow", ["$event.detail.keyboardHeight"]]
1133
+ }, {
1134
+ type: HostListener,
1135
+ args: ["window:keyboardWillShow", ["$event.keyboardHeight"]]
1136
+ }],
1137
+ _onKeyboardHide: [{
1138
+ type: HostListener,
1139
+ args: ["window:ionKeyboardDidHide"]
1140
+ }, {
1141
+ type: HostListener,
1142
+ args: ["window:keyboardWillHide"]
1143
+ }],
1144
+ _onWindowResize: [{
1145
+ type: HostListener,
1146
+ args: ["window:resize"]
1147
+ }]
1148
+ }
1149
+ });
1150
+ var DrawerSupplementaryAction = class {};
1151
+ var ModalCompactWrapperComponent = class ModalCompactWrapperComponent {
1152
+ constructor(injector, elementRef, windowRef, canDismissHelper, renderer) {
1153
+ this.injector = injector;
1154
+ this.elementRef = elementRef;
1155
+ this.windowRef = windowRef;
1156
+ this.canDismissHelper = canDismissHelper;
1157
+ this.renderer = renderer;
1158
+ this.scrollY = Math.abs(this.windowRef.nativeWindow.scrollY);
1159
+ this.scrollDisabled = false;
1160
+ this.ionModalDidPresent = new Subject();
1161
+ this.ionModalWillDismiss = new Subject();
1162
+ this.didPresent = firstValueFrom(this.ionModalDidPresent);
1163
+ this.willClose = firstValueFrom(this.ionModalWillDismiss);
1164
+ }
1165
+ ngOnInit() {
1166
+ this.ionModalElement = this.elementRef.nativeElement.closest("ion-modal");
1167
+ this.setAriaLabel();
1168
+ this.listenForIonModalDidPresent();
1169
+ this.listenForIonModalWillDismiss();
1170
+ this.componentPropsInjector = Injector.create({
1171
+ providers: [{
1172
+ provide: COMPONENT_PROPS,
1173
+ useValue: this.config.componentProps
1174
+ }],
1175
+ parent: this.injector
1176
+ });
1177
+ }
1178
+ listenForIonModalDidPresent() {
1179
+ if (this.ionModalElement) this.ionModalElement.addEventListener("ionModalDidPresent", () => {
1180
+ this.ionModalDidPresent.next();
1181
+ this.ionModalDidPresent.complete();
1182
+ });
1183
+ }
1184
+ listenForIonModalWillDismiss() {
1185
+ if (this.ionModalElement) this.ionModalElement.addEventListener("ionModalWillDismiss", () => {
1186
+ this.ionModalWillDismiss.next();
1187
+ this.ionModalWillDismiss.complete();
1188
+ });
1189
+ }
1190
+ setAriaLabel() {
1191
+ const ionModalElementDialog = getIonModalDialogAncestor(this.ionModalElement);
1192
+ const ariaLabel = this.config.htmlAttributes?.["aria-label"];
1193
+ if (ionModalElementDialog && ariaLabel) this.renderer.setAttribute(ionModalElementDialog, "aria-label", ariaLabel);
1194
+ }
1195
+ async close(data) {
1196
+ if (this.ionModalElement) await this.ionModalElement.dismiss(data);
1197
+ }
1198
+ set canDismiss(callback) {
1199
+ this.ionModalElement.canDismiss = this.canDismissHelper.getCanDismissCallback(callback);
1200
+ }
1201
+ onFocusChange() {
1202
+ this.windowRef.nativeWindow.scrollTo({ top: this.scrollY });
1203
+ }
1204
+ static {
1205
+ this.ɵfac = i0.ɵɵngDeclareFactory({
1206
+ minVersion: "12.0.0",
1207
+ version: "22.2.3",
1208
+ ngImport: i0,
1209
+ type: ModalCompactWrapperComponent,
1210
+ deps: [
1211
+ { token: i0.Injector },
1212
+ { token: i0.ElementRef },
1213
+ { token: i1$2.WindowRef },
1214
+ { token: CanDismissHelper },
1215
+ { token: i0.Renderer2 }
1216
+ ],
1217
+ target: i0.ɵɵFactoryTarget.Component
1218
+ });
1219
+ }
1220
+ static {
1221
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
1222
+ minVersion: "14.0.0",
1223
+ version: "22.2.3",
1224
+ type: ModalCompactWrapperComponent,
1225
+ isStandalone: true,
1226
+ selector: "kirby-modal-compact-wrapper",
1227
+ inputs: {
1228
+ config: "config",
1229
+ content: "content"
1230
+ },
1231
+ host: {
1232
+ listeners: {
1233
+ "window:focus": "onFocusChange()",
1234
+ "window:focusout": "onFocusChange()"
1235
+ },
1236
+ properties: { "class.ion-page": "false" }
1237
+ },
1238
+ providers: [{
1239
+ provide: Modal,
1240
+ useExisting: ModalCompactWrapperComponent
1241
+ }],
1242
+ ngImport: i0,
1243
+ template: "<!-- Outlet for ModalController -->\n<ng-container\n *ngComponentOutlet=\"config.component; injector: componentPropsInjector\"\n></ng-container>\n\n<!-- Outlet for projected content -->\n<ng-container *ngTemplateOutlet=\"content\"></ng-container>\n",
1244
+ styles: [":host{display:block;padding:var(--kirby-spacing-m) var(--kirby-spacing-s)}\n"],
1245
+ dependencies: [
1246
+ {
1247
+ kind: "ngmodule",
1248
+ type: CommonModule
1249
+ },
1250
+ {
1251
+ kind: "directive",
1252
+ type: i2.NgComponentOutlet,
1253
+ selector: "[ngComponentOutlet]",
1254
+ inputs: [
1255
+ "ngComponentOutlet",
1256
+ "ngComponentOutletInputs",
1257
+ "ngComponentOutletInjector",
1258
+ "ngComponentOutletEnvironmentInjector",
1259
+ "ngComponentOutletContent",
1260
+ "ngComponentOutletNgModule"
1261
+ ],
1262
+ exportAs: ["ngComponentOutlet"]
1263
+ },
1264
+ {
1265
+ kind: "directive",
1266
+ type: i2.NgTemplateOutlet,
1267
+ selector: "[ngTemplateOutlet]",
1268
+ inputs: [
1269
+ "ngTemplateOutletContext",
1270
+ "ngTemplateOutlet",
1271
+ "ngTemplateOutletInjector"
1272
+ ]
1273
+ }
1274
+ ],
1275
+ changeDetection: i0.ChangeDetectionStrategy.Eager
1276
+ });
1277
+ }
1278
+ };
1279
+ i0.ɵɵngDeclareClassMetadata({
1280
+ minVersion: "12.0.0",
1281
+ version: "22.2.3",
1282
+ ngImport: i0,
1283
+ type: ModalCompactWrapperComponent,
1284
+ decorators: [{
1285
+ type: Component,
1286
+ args: [{
1287
+ selector: "kirby-modal-compact-wrapper",
1288
+ providers: [{
1289
+ provide: Modal,
1290
+ useExisting: ModalCompactWrapperComponent
1291
+ }],
1292
+ imports: [CommonModule],
1293
+ host: { "[class.ion-page]": "false" },
1294
+ changeDetection: ChangeDetectionStrategy.Eager,
1295
+ template: "<!-- Outlet for ModalController -->\n<ng-container\n *ngComponentOutlet=\"config.component; injector: componentPropsInjector\"\n></ng-container>\n\n<!-- Outlet for projected content -->\n<ng-container *ngTemplateOutlet=\"content\"></ng-container>\n",
1296
+ styles: [":host{display:block;padding:var(--kirby-spacing-m) var(--kirby-spacing-s)}\n"]
1297
+ }]
1298
+ }],
1299
+ ctorParameters: () => [
1300
+ { type: i0.Injector },
1301
+ { type: i0.ElementRef },
1302
+ { type: i1$2.WindowRef },
1303
+ { type: CanDismissHelper },
1304
+ { type: i0.Renderer2 }
1305
+ ],
1306
+ propDecorators: {
1307
+ config: [{ type: Input }],
1308
+ content: [{ type: Input }],
1309
+ onFocusChange: [{
1310
+ type: HostListener,
1311
+ args: ["window:focus"]
1312
+ }, {
1313
+ type: HostListener,
1314
+ args: ["window:focusout"]
1315
+ }]
1316
+ }
1317
+ });
1318
+ var ModalAnimationBuilderService = class ModalAnimationBuilderService {
1319
+ constructor(platform) {
1320
+ this.platform = platform;
1321
+ this.easingEnter = KirbyAnimation.Easing.modal.enter;
1322
+ this.easingLeave = KirbyAnimation.Easing.modal.exit;
1323
+ this.duration = KirbyAnimation.Duration.LONG;
1324
+ this.SwipeToCloseDefaults = { MIN_PRESENTING_SCALE: .93 };
1325
+ this.createEnterAnimation = () => {
1326
+ return {
1327
+ backdropAnimation: createAnimation().fromTo("opacity", .01, "var(--backdrop-opacity)").beforeStyles({ "pointer-events": "none" }).afterClearStyles(["pointer-events"]),
1328
+ wrapperAnimation: createAnimation().fromTo("transform", "translateY(100vh)", "translateY(0vh)")
1329
+ };
1330
+ };
1331
+ this.createLeaveAnimation = () => {
1332
+ return {
1333
+ backdropAnimation: createAnimation().fromTo("opacity", "var(--backdrop-opacity)", 0),
1334
+ wrapperAnimation: createAnimation().fromTo("transform", "translateY(0vh)", "translateY(100vh)")
1335
+ };
1336
+ };
1337
+ this.getElementRoot = (el, fallback = el) => {
1338
+ return el.shadowRoot || fallback;
1339
+ };
1340
+ }
1341
+ enterAnimation(currentBackdrop) {
1342
+ return (baseEl, opts) => {
1343
+ const { presentingEl } = opts;
1344
+ const root = this.getElementRoot(baseEl);
1345
+ const { wrapperAnimation, backdropAnimation } = this.createEnterAnimation();
1346
+ backdropAnimation.addElement(root.querySelector("ion-backdrop"));
1347
+ wrapperAnimation.addElement(root.querySelectorAll(".modal-wrapper, .modal-shadow")).beforeStyles({ opacity: 1 });
1348
+ const baseAnimation = createAnimation("entering-base").addElement(baseEl).easing(this.easingEnter).duration(this.duration).addAnimation(wrapperAnimation);
1349
+ let currentBackdropAnimation;
1350
+ if (currentBackdrop) currentBackdropAnimation = createAnimation().addElement(currentBackdrop).fromTo("opacity", "var(--backdrop-opacity)", .01);
1351
+ if (presentingEl) {
1352
+ const isMobile = !this.platform.isPhabletOrBigger();
1353
+ const hasCardModal = presentingEl.tagName === "ION-MODAL" && presentingEl.presentingElement !== void 0;
1354
+ const presentingElRoot = this.getElementRoot(presentingEl);
1355
+ const presentingAnimation = createAnimation().beforeStyles({
1356
+ transform: "translateY(0)",
1357
+ "transform-origin": "top center",
1358
+ overflow: "hidden"
1359
+ });
1360
+ const bodyEl = document.body;
1361
+ if (isMobile) {
1362
+ const transformOffset = !CSS.supports("width", "max(0px, 1px)") ? "30px" : "max(30px, var(--ion-safe-area-top))";
1363
+ const finalTransform = `translateY(${hasCardModal ? "-10px" : transformOffset}) scale(${this.SwipeToCloseDefaults.MIN_PRESENTING_SCALE})`;
1364
+ presentingAnimation.afterStyles({ transform: finalTransform }).beforeAddWrite(() => bodyEl.style.setProperty("background-color", "black")).addElement(presentingEl).keyframes([{
1365
+ offset: 0,
1366
+ filter: "contrast(1)",
1367
+ transform: "translateY(0px) scale(1)",
1368
+ borderRadius: "0px"
1369
+ }, {
1370
+ offset: 1,
1371
+ filter: "contrast(0.85)",
1372
+ transform: finalTransform,
1373
+ borderRadius: "10px 10px 0 0"
1374
+ }]);
1375
+ baseAnimation.addAnimation(presentingAnimation);
1376
+ } else {
1377
+ baseAnimation.addAnimation(backdropAnimation);
1378
+ if (currentBackdropAnimation) baseAnimation.addAnimation(currentBackdropAnimation);
1379
+ if (!hasCardModal) wrapperAnimation.fromTo("opacity", "0", "1");
1380
+ else {
1381
+ const finalTransform = `translateY(-10px) scale(${hasCardModal ? this.SwipeToCloseDefaults.MIN_PRESENTING_SCALE : 1})`;
1382
+ presentingAnimation.afterStyles({ transform: finalTransform }).addElement(presentingElRoot.querySelector(".modal-wrapper")).keyframes([{
1383
+ offset: 0,
1384
+ filter: "contrast(1)",
1385
+ transform: "translateY(0) scale(1)"
1386
+ }, {
1387
+ offset: 1,
1388
+ filter: "contrast(0.85)",
1389
+ transform: finalTransform
1390
+ }]);
1391
+ const shadowAnimation = createAnimation().afterStyles({ transform: finalTransform }).addElement(presentingElRoot.querySelector(".modal-shadow")).keyframes([{
1392
+ offset: 0,
1393
+ opacity: "1",
1394
+ transform: "translateY(0) scale(1)"
1395
+ }, {
1396
+ offset: 1,
1397
+ opacity: "0",
1398
+ transform: finalTransform
1399
+ }]);
1400
+ baseAnimation.addAnimation([presentingAnimation, shadowAnimation]);
1401
+ }
1402
+ }
1403
+ } else {
1404
+ baseAnimation.addAnimation(backdropAnimation);
1405
+ if (currentBackdropAnimation) baseAnimation.addAnimation(currentBackdropAnimation);
1406
+ }
1407
+ return baseAnimation;
1408
+ };
1409
+ }
1410
+ leaveAnimation(currentBackdrop) {
1411
+ return (baseEl, opts, duration = this.duration) => {
1412
+ const { presentingEl } = opts;
1413
+ const root = this.getElementRoot(baseEl);
1414
+ const { wrapperAnimation, backdropAnimation } = this.createLeaveAnimation();
1415
+ backdropAnimation.addElement(root.querySelector("ion-backdrop"));
1416
+ wrapperAnimation.addElement(root.querySelectorAll(".modal-wrapper, .modal-shadow")).beforeStyles({ opacity: 1 });
1417
+ const baseAnimation = createAnimation("leaving-base").addElement(baseEl).easing(this.easingLeave).duration(duration).addAnimation(wrapperAnimation);
1418
+ let currentBackdropAnimation;
1419
+ if (currentBackdrop) currentBackdropAnimation = createAnimation().addElement(currentBackdrop).fromTo("opacity", .01, "var(--backdrop-opacity)").afterStyles({ opacity: "var(--backdrop-opacity)" });
1420
+ if (presentingEl) {
1421
+ const isMobile = !this.platform.isPhabletOrBigger();
1422
+ const hasCardModal = presentingEl.tagName === "ION-MODAL" && presentingEl.presentingElement !== void 0;
1423
+ const presentingElRoot = this.getElementRoot(presentingEl);
1424
+ const presentingAnimation = createAnimation().beforeClearStyles(["transform"]).afterClearStyles(["transform"]).onFinish((currentStep) => {
1425
+ if (currentStep !== 1) return;
1426
+ presentingEl.style.setProperty("overflow", "");
1427
+ if (Array.from(bodyEl.querySelectorAll("ion-modal")).filter((m) => m.presentingElement !== void 0).length <= 1) bodyEl.style.setProperty("background-color", "");
1428
+ });
1429
+ const bodyEl = document.body;
1430
+ if (isMobile) {
1431
+ const transformOffset = !CSS.supports("width", "max(0px, 1px)") ? "30px" : "max(30px, var(--ion-safe-area-top))";
1432
+ const finalTransform = `translateY(${hasCardModal ? "-10px" : transformOffset}) scale(${this.SwipeToCloseDefaults.MIN_PRESENTING_SCALE})`;
1433
+ presentingAnimation.addElement(presentingEl).keyframes([{
1434
+ offset: 0,
1435
+ filter: "contrast(0.85)",
1436
+ transform: finalTransform,
1437
+ borderRadius: "10px 10px 0 0"
1438
+ }, {
1439
+ offset: 1,
1440
+ filter: "contrast(1)",
1441
+ transform: "translateY(0px) scale(1)",
1442
+ borderRadius: "0px"
1443
+ }]);
1444
+ baseAnimation.addAnimation(presentingAnimation);
1445
+ } else {
1446
+ baseAnimation.addAnimation(backdropAnimation);
1447
+ if (currentBackdropAnimation) baseAnimation.addAnimation(currentBackdropAnimation);
1448
+ if (!hasCardModal) wrapperAnimation.fromTo("opacity", "1", "0");
1449
+ else {
1450
+ const finalTransform = `translateY(-10px) scale(${hasCardModal ? this.SwipeToCloseDefaults.MIN_PRESENTING_SCALE : 1})`;
1451
+ presentingAnimation.addElement(presentingElRoot.querySelector(".modal-wrapper")).afterStyles({ transform: "translate3d(0, 0, 0)" }).keyframes([{
1452
+ offset: 0,
1453
+ filter: "contrast(0.85)",
1454
+ transform: finalTransform
1455
+ }, {
1456
+ offset: 1,
1457
+ filter: "contrast(1)",
1458
+ transform: "translateY(0) scale(1)"
1459
+ }]);
1460
+ const shadowAnimation = createAnimation().addElement(presentingElRoot.querySelector(".modal-shadow")).afterStyles({ transform: "translateY(0) scale(1)" }).keyframes([{
1461
+ offset: 0,
1462
+ opacity: "0",
1463
+ transform: finalTransform
1464
+ }, {
1465
+ offset: 1,
1466
+ opacity: "1",
1467
+ transform: "translateY(0) scale(1)"
1468
+ }]);
1469
+ baseAnimation.addAnimation([presentingAnimation, shadowAnimation]);
1470
+ }
1471
+ }
1472
+ } else {
1473
+ baseAnimation.addAnimation(backdropAnimation);
1474
+ if (currentBackdropAnimation) baseAnimation.addAnimation(currentBackdropAnimation);
1475
+ }
1476
+ return baseAnimation;
1477
+ };
1478
+ }
1479
+ static {
1480
+ this.ɵfac = i0.ɵɵngDeclareFactory({
1481
+ minVersion: "12.0.0",
1482
+ version: "22.2.3",
1483
+ ngImport: i0,
1484
+ type: ModalAnimationBuilderService,
1485
+ deps: [{ token: i3.PlatformService }],
1486
+ target: i0.ɵɵFactoryTarget.Injectable
1487
+ });
1488
+ }
1489
+ static {
1490
+ this.ɵprov = i0.ɵɵngDeclareInjectable({
1491
+ minVersion: "12.0.0",
1492
+ version: "22.2.3",
1493
+ ngImport: i0,
1494
+ type: ModalAnimationBuilderService,
1495
+ providedIn: "root"
1496
+ });
1497
+ }
1498
+ };
1499
+ i0.ɵɵngDeclareClassMetadata({
1500
+ minVersion: "12.0.0",
1501
+ version: "22.2.3",
1502
+ ngImport: i0,
1503
+ type: ModalAnimationBuilderService,
1504
+ decorators: [{
1505
+ type: Injectable,
1506
+ args: [{ providedIn: "root" }]
1507
+ }],
1508
+ ctorParameters: () => [{ type: i3.PlatformService }]
1509
+ });
1510
+ var ModalNavigationService = class ModalNavigationService {
1511
+ constructor(router, route) {
1512
+ this.router = router;
1513
+ this.route = route;
1514
+ this.routerEvents$ = defer(() => {
1515
+ const events = this.router.events;
1516
+ return events.closed ? EMPTY : events;
1517
+ });
1518
+ this.navigationEndListener$ = this.routerEvents$.pipe(filter((event) => event instanceof NavigationEnd));
1519
+ }
1520
+ isModalRoute(url) {
1521
+ return url.includes("(modal:");
1522
+ }
1523
+ getCurrentActivatedRoute() {
1524
+ let childRoute = this.route.root;
1525
+ while (childRoute.firstChild) childRoute = childRoute.firstChild;
1526
+ return childRoute;
1527
+ }
1528
+ async getModalRoutes(routeConfig, moduleRootRoutePath) {
1529
+ const flattenedRoutes = [].concat(...routeConfig);
1530
+ let modalRoutes = [];
1531
+ const moduleRootPaths = await this.getModuleRootPath(flattenedRoutes, moduleRootRoutePath);
1532
+ if (moduleRootPaths) modalRoutes = this.getModalRoutePaths(flattenedRoutes, moduleRootPaths);
1533
+ return modalRoutes;
1534
+ }
1535
+ async getModuleRootPath(routes, moduleRootRoutePath) {
1536
+ if (moduleRootRoutePath) {
1537
+ const trimmedPaths = moduleRootRoutePath.trim().split("/").filter((path) => !!path);
1538
+ return [""].concat(trimmedPaths);
1539
+ }
1540
+ const currentRoutePaths = await this.getCurrentRoutePaths();
1541
+ return this.getRoutePathsWithoutChildSegments(currentRoutePaths, routes);
1542
+ }
1543
+ async getCurrentRoutePaths() {
1544
+ const rootPath = [""];
1545
+ const currentNavigation = this.router.currentNavigation();
1546
+ if (!this.router.navigated && !currentNavigation) return rootPath;
1547
+ if (currentNavigation) await firstValueFrom(this.navigationEndListener$);
1548
+ let childRoute = this.route.snapshot.root;
1549
+ while (childRoute.firstChild) childRoute = childRoute.firstChild;
1550
+ const currentBackdropRoutePath = childRoute.pathFromRoot.filter((route) => route.outlet !== "modal");
1551
+ return rootPath.concat(...currentBackdropRoutePath.map((route) => route.url.filter((segment) => !!segment.path).map((segment) => segment.path)));
1552
+ }
1553
+ getRoutePathsWithoutChildSegments(routePaths, routes) {
1554
+ if (!routePaths.length) return routePaths;
1555
+ const matchedChildRoute = this.findChildRouteForUrl(routePaths.join("/"), routes);
1556
+ if (!matchedChildRoute) return routePaths;
1557
+ const childSegmentCount = matchedChildRoute.replace(/^\//, "").split("/").length;
1558
+ return routePaths.slice(0, -childSegmentCount);
1559
+ }
1560
+ findChildRouteForUrl(url, routes) {
1561
+ const moduleRelativePaths = this.getRoutePaths(routes, [""]).sort().reverse();
1562
+ let matchedChildRoute = moduleRelativePaths.find((path) => url.endsWith(path));
1563
+ if (!matchedChildRoute) {
1564
+ const exactMatch = false;
1565
+ matchedChildRoute = moduleRelativePaths.find((path) => path.includes("/:") && this.pathContainsChildRouteWithUrlParams(url, path, exactMatch));
1566
+ }
1567
+ return matchedChildRoute;
1568
+ }
1569
+ pathContainsChildRouteWithUrlParams(path, childRouteWithUrlParams, exactMatch) {
1570
+ const pathSegments = path.split("/");
1571
+ const startSlashRegex = /^\//;
1572
+ let childRouteToMatch = childRouteWithUrlParams;
1573
+ if (!exactMatch) childRouteToMatch = childRouteWithUrlParams.replace(startSlashRegex, "");
1574
+ const pathContainsChildRoute = childRouteToMatch.split("/").reverse().every((childRouteSegment) => {
1575
+ const pathSegment = pathSegments.pop();
1576
+ return childRouteSegment.startsWith(":") || childRouteSegment === pathSegment;
1577
+ });
1578
+ if (exactMatch) return pathSegments.length === 0 && pathContainsChildRoute;
1579
+ return pathContainsChildRoute;
1580
+ }
1581
+ getRoutePaths(routes, parentPath) {
1582
+ return Array.isArray(routes) ? [].concat(...routes.map((route) => this.getRoutePath(route, parentPath))) : [];
1583
+ }
1584
+ getRoutePath(route, parentPath) {
1585
+ const routes = [];
1586
+ if (route.outlet) return routes;
1587
+ const currentPath = [...parentPath];
1588
+ if (route.path) {
1589
+ currentPath.push(route.path);
1590
+ routes.push(currentPath.join("/"));
1591
+ }
1592
+ return routes.concat(this.getRoutePaths(route.children, currentPath));
1593
+ }
1594
+ getModalRoutePath(route, parentPath) {
1595
+ const modalOutletName = "modal";
1596
+ if (!!route.path && route.outlet === modalOutletName) {
1597
+ const modalOutletPath = `(${modalOutletName}:${route.path})`;
1598
+ return [[...parentPath, modalOutletPath].join("/")];
1599
+ }
1600
+ const currentPath = [...parentPath];
1601
+ if (route.path) currentPath.push(route.path);
1602
+ return [].concat(...this.getModalRoutePaths(route.children, currentPath));
1603
+ }
1604
+ getModalRoutePaths(routes, parentPath) {
1605
+ return Array.isArray(routes) ? [].concat(...routes.map((route) => this.getModalRoutePath(route, parentPath))) : [];
1606
+ }
1607
+ isNewModalWindow(navigationEnd) {
1608
+ const currentNavigation = this.router.currentNavigation();
1609
+ if (!currentNavigation || !currentNavigation.previousNavigation) return true;
1610
+ const previousRoutePath = (currentNavigation.previousNavigation.finalUrl || currentNavigation.previousNavigation.extractedUrl).toString();
1611
+ const wasModalRoute = this.isModalRoute(previousRoutePath);
1612
+ const isModalRoute = this.isModalRoute(navigationEnd.urlAfterRedirects);
1613
+ if (!wasModalRoute && isModalRoute) return true;
1614
+ const currentModalRouteParent = navigationEnd.urlAfterRedirects.split("/(modal:")[0];
1615
+ return previousRoutePath.split("/(modal:")[0] !== currentModalRouteParent;
1616
+ }
1617
+ async waitForCurrentThenGetNavigationEndStream() {
1618
+ if (this.router.currentNavigation()) {
1619
+ const currentNavigationEnd = await firstValueFrom(this.navigationEndListener$);
1620
+ return this.navigationEndListener$.pipe(startWith(currentNavigationEnd));
1621
+ }
1622
+ return this.navigationEndListener$;
1623
+ }
1624
+ modalRouteActivatedFor(navigationEnd$, modalRouteSet, modalRoutesContainsUrlParams) {
1625
+ return navigationEnd$.pipe(filter((navigationEnd) => this.modalRouteSetContainsPath(modalRouteSet, navigationEnd, modalRoutesContainsUrlParams)), map((navigationEnd) => {
1626
+ return {
1627
+ route: this.getCurrentActivatedRoute(),
1628
+ isNewModal: this.isNewModalWindow(navigationEnd)
1629
+ };
1630
+ }));
1631
+ }
1632
+ modalRouteDeactivatedFor(navigationEnd$, modalRouteSet, modalRoutesContainsUrlParams) {
1633
+ return navigationEnd$.pipe(pairwise(), filter(([prevNavigation, _]) => this.modalRouteSetContainsPath(modalRouteSet, prevNavigation, modalRoutesContainsUrlParams)), map(([_, currentNavigation]) => {
1634
+ return !this.isModalRoute(currentNavigation.urlAfterRedirects) || this.isNewModalWindow(currentNavigation);
1635
+ }), filter((isDeactivation) => isDeactivation));
1636
+ }
1637
+ modalRouteSetContainsPath(modalRouteSet, navigationEnd, modalRoutesContainsUrlParams) {
1638
+ const pathname = navigationEnd.urlAfterRedirects.split("?")[0];
1639
+ let hasRoute = modalRouteSet.has(pathname);
1640
+ if (!hasRoute && modalRoutesContainsUrlParams) {
1641
+ for (const route of modalRouteSet) if (this.pathContainsChildRouteWithUrlParams(pathname, route, true)) {
1642
+ hasRoute = true;
1643
+ break;
1644
+ }
1645
+ }
1646
+ return hasRoute;
1647
+ }
1648
+ async getModalNavigation(routeConfig, moduleRootRoutePath) {
1649
+ if (Array.isArray(routeConfig)) {
1650
+ const navigationEnd$ = await this.waitForCurrentThenGetNavigationEndStream();
1651
+ const modalRoutes = await this.getModalRoutes(routeConfig, moduleRootRoutePath);
1652
+ if (modalRoutes.length > 0) {
1653
+ const modalRoutesContainsUrlParams = modalRoutes.some((route) => route.includes("/:"));
1654
+ const modalRouteSet = new Set(modalRoutes);
1655
+ return {
1656
+ activated$: this.modalRouteActivatedFor(navigationEnd$, modalRouteSet, modalRoutesContainsUrlParams),
1657
+ deactivated$: this.modalRouteDeactivatedFor(navigationEnd$, modalRouteSet, modalRoutesContainsUrlParams)
1658
+ };
1659
+ }
1660
+ }
1661
+ return {
1662
+ activated$: EMPTY,
1663
+ deactivated$: EMPTY
1664
+ };
1665
+ }
1666
+ async navigateToModal(path, queryParams) {
1667
+ const commands = Array.isArray(path) ? [...path] : path.split("/");
1668
+ const childPath = commands.pop();
1669
+ return await this.router.navigate([...commands, { outlets: { modal: [childPath] } }], {
1670
+ queryParams,
1671
+ relativeTo: this.getCurrentActivatedRoute()
1672
+ });
1673
+ }
1674
+ async navigateWithinModal(relativePath, queryParams) {
1675
+ return this.router.navigate([relativePath], {
1676
+ queryParams,
1677
+ relativeTo: this.getCurrentActivatedRoute()
1678
+ });
1679
+ }
1680
+ async navigateOutOfModalOutlet() {
1681
+ const currentActivatedRoute = this.getCurrentActivatedRoute();
1682
+ const currentNavigationFinalUrl = this.router.currentNavigation()?.finalUrl?.toString();
1683
+ const isCurrentlyNavigatingOutOfModalOutlet = currentNavigationFinalUrl && !this.isModalRoute(currentNavigationFinalUrl);
1684
+ if (currentActivatedRoute.outlet !== "modal" || isCurrentlyNavigatingOutOfModalOutlet) return Promise.resolve(true);
1685
+ const parentRoute = this.getBackdropRoute(currentActivatedRoute);
1686
+ return this.router.navigate(["./"], { relativeTo: parentRoute });
1687
+ }
1688
+ getBackdropRoute(currentActivatedRoute) {
1689
+ let parentRoute = currentActivatedRoute.parent;
1690
+ while (parentRoute && !parentRoute.component && !!parentRoute.parent) parentRoute = parentRoute.parent;
1691
+ return parentRoute;
1692
+ }
1693
+ handleBrowserBackButton(modal) {
1694
+ const popstateNavigationStart$ = this.routerEvents$.pipe(filter((event) => event instanceof NavigationStart && event.navigationTrigger === "popstate"));
1695
+ this.routerEvents$.pipe(filter((event) => event instanceof NavigationEnd)).pipe(skipUntil(popstateNavigationStart$), takeUntil(modal.onWillDismiss())).subscribe(() => {
1696
+ modal.dismiss();
1697
+ });
1698
+ }
1699
+ static {
1700
+ this.ɵfac = i0.ɵɵngDeclareFactory({
1701
+ minVersion: "12.0.0",
1702
+ version: "22.2.3",
1703
+ ngImport: i0,
1704
+ type: ModalNavigationService,
1705
+ deps: [{ token: i5.Router }, { token: i5.ActivatedRoute }],
1706
+ target: i0.ɵɵFactoryTarget.Injectable
1707
+ });
1708
+ }
1709
+ static {
1710
+ this.ɵprov = i0.ɵɵngDeclareInjectable({
1711
+ minVersion: "12.0.0",
1712
+ version: "22.2.3",
1713
+ ngImport: i0,
1714
+ type: ModalNavigationService,
1715
+ providedIn: "root"
1716
+ });
1717
+ }
1718
+ };
1719
+ i0.ɵɵngDeclareClassMetadata({
1720
+ minVersion: "12.0.0",
1721
+ version: "22.2.3",
1722
+ ngImport: i0,
1723
+ type: ModalNavigationService,
1724
+ decorators: [{
1725
+ type: Injectable,
1726
+ args: [{ providedIn: "root" }]
1727
+ }],
1728
+ ctorParameters: () => [{ type: i5.Router }, { type: i5.ActivatedRoute }]
1729
+ });
1730
+ var ModalHelper = class ModalHelper {
1731
+ constructor(ionicModalController, modalAnimationBuilder, modalNavigationService, windowRef, canDismissHelper) {
1732
+ this.ionicModalController = ionicModalController;
1733
+ this.modalAnimationBuilder = modalAnimationBuilder;
1734
+ this.modalNavigationService = modalNavigationService;
1735
+ this.windowRef = windowRef;
1736
+ this.canDismissHelper = canDismissHelper;
1737
+ this.isModalOpening = false;
1738
+ }
1739
+ async showModalWindow(config) {
1740
+ if (this.isModalOpening) return;
1741
+ config.flavor = config.flavor || "modal";
1742
+ let currentBackdrop;
1743
+ const topMostModal = await this.ionicModalController.getTop();
1744
+ if (topMostModal) currentBackdrop = topMostModal.shadowRoot.querySelector("ion-backdrop");
1745
+ const enterAnimation = this.modalAnimationBuilder.enterAnimation(currentBackdrop);
1746
+ const leaveAnimation = this.modalAnimationBuilder.leaveAnimation(currentBackdrop);
1747
+ const defaultModalSize = config.interactWithBackground ? null : "medium";
1748
+ const modalSize = config.size || defaultModalSize;
1749
+ const allow_scroll_class = "allow-background-scroll";
1750
+ let customCssClasses = [];
1751
+ if (config.cssClass) customCssClasses = Array.isArray(config.cssClass) ? config.cssClass : [config.cssClass];
1752
+ if (config.interactWithBackground) this.windowRef.nativeWindow.document.body.classList.add(allow_scroll_class);
1753
+ let canDismiss = true;
1754
+ if (config.canDismiss) canDismiss = this.canDismissHelper.getCanDismissCallback(config.canDismiss);
1755
+ this.isModalOpening = true;
1756
+ const ionModal = await this.ionicModalController.create({
1757
+ component: config.flavor === "compact" ? ModalCompactWrapperComponent : ModalWrapperComponent,
1758
+ cssClass: [
1759
+ "kirby-overlay",
1760
+ "kirby-modal",
1761
+ modalSize ? `kirby-modal-${modalSize}` : null,
1762
+ config.flavor === "drawer" ? "kirby-drawer" : null,
1763
+ config.flavor === "compact" ? "kirby-modal-compact" : null,
1764
+ config.interactWithBackground ? "interact-with-background" : null,
1765
+ ...customCssClasses
1766
+ ],
1767
+ backdropDismiss: config.flavor === "compact" || config.interactWithBackground ? false : true,
1768
+ showBackdrop: !config.interactWithBackground,
1769
+ componentProps: { config },
1770
+ htmlAttributes: { ...config.htmlAttributes },
1771
+ keyboardClose: false,
1772
+ canDismiss,
1773
+ enterAnimation,
1774
+ leaveAnimation
1775
+ });
1776
+ if (config.interactWithBackground) ionModal.onDidDismiss().then(() => {
1777
+ this.windowRef.nativeWindow.document.body.classList.remove(allow_scroll_class);
1778
+ });
1779
+ if (config.customHeight) ionModal.style.setProperty("--kirby-modal-height", config.customHeight);
1780
+ const onWillDismiss = ionModal.onWillDismiss();
1781
+ const overlay = {
1782
+ dismiss: ionModal.dismiss.bind(ionModal),
1783
+ onWillDismiss,
1784
+ onDidDismiss: ionModal.onDidDismiss(),
1785
+ isDismissing: false
1786
+ };
1787
+ onWillDismiss.then(() => {
1788
+ overlay.isDismissing = true;
1789
+ });
1790
+ await ionModal.present();
1791
+ if (!ionModal.contains(document.activeElement)) ionModal.focus();
1792
+ if (!config.modalRoute) this.modalNavigationService.handleBrowserBackButton(ionModal);
1793
+ this.isModalOpening = false;
1794
+ return overlay;
1795
+ }
1796
+ static {
1797
+ this.ɵfac = i0.ɵɵngDeclareFactory({
1798
+ minVersion: "12.0.0",
1799
+ version: "22.2.3",
1800
+ ngImport: i0,
1801
+ type: ModalHelper,
1802
+ deps: [
1803
+ { token: i1$1.ModalController },
1804
+ { token: ModalAnimationBuilderService },
1805
+ { token: ModalNavigationService },
1806
+ { token: i1$2.WindowRef },
1807
+ { token: CanDismissHelper }
1808
+ ],
1809
+ target: i0.ɵɵFactoryTarget.Injectable
1810
+ });
1811
+ }
1812
+ static {
1813
+ this.ɵprov = i0.ɵɵngDeclareInjectable({
1814
+ minVersion: "12.0.0",
1815
+ version: "22.2.3",
1816
+ ngImport: i0,
1817
+ type: ModalHelper
1818
+ });
1819
+ }
1820
+ };
1821
+ i0.ɵɵngDeclareClassMetadata({
1822
+ minVersion: "12.0.0",
1823
+ version: "22.2.3",
1824
+ ngImport: i0,
1825
+ type: ModalHelper,
1826
+ decorators: [{ type: Injectable }],
1827
+ ctorParameters: () => [
1828
+ { type: i1$1.ModalController },
1829
+ { type: ModalAnimationBuilderService },
1830
+ { type: ModalNavigationService },
1831
+ { type: i1$2.WindowRef },
1832
+ { type: CanDismissHelper }
1833
+ ]
1834
+ });
1835
+ const KIRBY_ACTION_SHEET_DEPRECATION_WARNING = "[Kirby action sheet] Deprecated - Use Menu component instead";
1836
+ var ActionSheetComponent = class ActionSheetComponent {
1837
+ constructor() {
1838
+ this.cancelButtonText = "Cancel";
1839
+ this.hideCancel = false;
1840
+ this.disabled = false;
1841
+ this.cancel = new EventEmitter();
1842
+ this.itemSelect = new EventEmitter();
1843
+ console.warn(KIRBY_ACTION_SHEET_DEPRECATION_WARNING);
1844
+ }
1845
+ onItemSelect(selection) {
1846
+ this.itemSelect.emit(selection);
1847
+ }
1848
+ onCancel() {
1849
+ this.cancel.emit();
1850
+ }
1851
+ static {
1852
+ this.ɵfac = i0.ɵɵngDeclareFactory({
1853
+ minVersion: "12.0.0",
1854
+ version: "22.2.3",
1855
+ ngImport: i0,
1856
+ type: ActionSheetComponent,
1857
+ deps: [],
1858
+ target: i0.ɵɵFactoryTarget.Component
1859
+ });
1860
+ }
1861
+ static {
1862
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
1863
+ minVersion: "17.0.0",
1864
+ version: "22.2.3",
1865
+ type: ActionSheetComponent,
1866
+ isStandalone: true,
1867
+ selector: "kirby-action-sheet",
1868
+ inputs: {
1869
+ cancelButtonText: "cancelButtonText",
1870
+ hideCancel: "hideCancel",
1871
+ disabled: "disabled",
1872
+ header: "header",
1873
+ subheader: "subheader",
1874
+ items: "items"
1875
+ },
1876
+ outputs: {
1877
+ cancel: "cancel",
1878
+ itemSelect: "itemSelect"
1879
+ },
1880
+ ngImport: i0,
1881
+ template: "<kirby-card>\n @if (header) {\n <kirby-card-header\n [title]=\"header\"\n [isTitleBold]=\"true\"\n [subtitle]=\"subheader\"\n ></kirby-card-header>\n }\n @for (item of items; track item.id) {\n <button\n kirby-button\n expand=\"block\"\n size=\"lg\"\n [noDecoration]=\"true\"\n (click)=\"onItemSelect(item)\"\n >\n {{ item.text }}\n </button>\n }\n</kirby-card>\n@if (!hideCancel) {\n <button kirby-button class=\"cancel-btn\" size=\"lg\" attentionLevel=\"3\" (click)=\"onCancel()\">\n {{ cancelButtonText }}\n </button>\n}\n",
1882
+ styles: [".kirby-line-clamp{display:-webkit-box;-webkit-line-clamp:var(--line-clamp, none);-webkit-box-orient:vertical;overflow:hidden}:host{--kirby-internal-margin-horizontal-default: var(--kirby-spacing-l)}@media(max-width:320px){:host{--kirby-internal-margin-horizontal-default: var(--kirby-spacing-s)}}:host{--kirby-internal-margin-horizontal-total: calc( 2 * var(--kirby-action-sheet-margin-horizontal, var(--kirby-internal-margin-horizontal-default)) );display:flex;flex-direction:column;align-items:center;justify-content:flex-end;margin:0 auto;width:calc(100vw - var(--kirby-internal-margin-horizontal-total));max-width:calc(375px - var(--kirby-internal-margin-horizontal-total));padding-bottom:var(--kirby-safe-area-bottom, 0)}:host button[kirby-button].no-decoration:focus-visible{transition:all 80ms linear 0ms;box-shadow:var(--kirby-focus-ring-md-inset)}kirby-card{align-self:stretch;pointer-events:auto;box-shadow:var(--kirby-elevation-8)}kirby-card button[kirby-button]{margin:0;border-radius:0}kirby-card button[kirby-button]:not(:focus){border-top:1px solid var(--kirby-background-color)}.cancel-btn:focus-visible{transition:all 80ms linear 0ms;box-shadow:var(--kirby-elevation-8),var(--kirby-focus-ring-md-inset)}.cancel-btn{font-weight:var(--kirby-font-weight-bold);margin-top:var(--kirby-spacing-s);margin-bottom:var(--kirby-spacing-m);pointer-events:auto}\n"],
1883
+ dependencies: [
1884
+ {
1885
+ kind: "component",
1886
+ type: CardComponent,
1887
+ selector: "kirby-card",
1888
+ inputs: [
1889
+ "title",
1890
+ "subtitle",
1891
+ "backgroundImageUrl",
1892
+ "hasPadding",
1893
+ "sizes",
1894
+ "variant"
1895
+ ]
1896
+ },
1897
+ {
1898
+ kind: "component",
1899
+ type: CardHeaderComponent,
1900
+ selector: "kirby-card-header",
1901
+ inputs: [
1902
+ "title",
1903
+ "subtitle",
1904
+ "isTitleBold",
1905
+ "flagged",
1906
+ "hasPadding"
1907
+ ]
1908
+ },
1909
+ {
1910
+ kind: "component",
1911
+ type: ButtonComponent,
1912
+ selector: "button[kirby-button],Button[kirby-button],a[kirby-button]",
1913
+ inputs: [
1914
+ "attentionLevel",
1915
+ "noDecoration",
1916
+ "themeColor",
1917
+ "expand",
1918
+ "isFloating",
1919
+ "size",
1920
+ "showIconOnly"
1921
+ ]
1922
+ }
1923
+ ],
1924
+ changeDetection: i0.ChangeDetectionStrategy.Eager
1925
+ });
1926
+ }
1927
+ };
1928
+ i0.ɵɵngDeclareClassMetadata({
1929
+ minVersion: "12.0.0",
1930
+ version: "22.2.3",
1931
+ ngImport: i0,
1932
+ type: ActionSheetComponent,
1933
+ decorators: [{
1934
+ type: Component,
1935
+ args: [{
1936
+ imports: [
1937
+ CardComponent,
1938
+ CardHeaderComponent,
1939
+ ButtonComponent
1940
+ ],
1941
+ selector: "kirby-action-sheet",
1942
+ changeDetection: ChangeDetectionStrategy.Eager,
1943
+ template: "<kirby-card>\n @if (header) {\n <kirby-card-header\n [title]=\"header\"\n [isTitleBold]=\"true\"\n [subtitle]=\"subheader\"\n ></kirby-card-header>\n }\n @for (item of items; track item.id) {\n <button\n kirby-button\n expand=\"block\"\n size=\"lg\"\n [noDecoration]=\"true\"\n (click)=\"onItemSelect(item)\"\n >\n {{ item.text }}\n </button>\n }\n</kirby-card>\n@if (!hideCancel) {\n <button kirby-button class=\"cancel-btn\" size=\"lg\" attentionLevel=\"3\" (click)=\"onCancel()\">\n {{ cancelButtonText }}\n </button>\n}\n",
1944
+ styles: [".kirby-line-clamp{display:-webkit-box;-webkit-line-clamp:var(--line-clamp, none);-webkit-box-orient:vertical;overflow:hidden}:host{--kirby-internal-margin-horizontal-default: var(--kirby-spacing-l)}@media(max-width:320px){:host{--kirby-internal-margin-horizontal-default: var(--kirby-spacing-s)}}:host{--kirby-internal-margin-horizontal-total: calc( 2 * var(--kirby-action-sheet-margin-horizontal, var(--kirby-internal-margin-horizontal-default)) );display:flex;flex-direction:column;align-items:center;justify-content:flex-end;margin:0 auto;width:calc(100vw - var(--kirby-internal-margin-horizontal-total));max-width:calc(375px - var(--kirby-internal-margin-horizontal-total));padding-bottom:var(--kirby-safe-area-bottom, 0)}:host button[kirby-button].no-decoration:focus-visible{transition:all 80ms linear 0ms;box-shadow:var(--kirby-focus-ring-md-inset)}kirby-card{align-self:stretch;pointer-events:auto;box-shadow:var(--kirby-elevation-8)}kirby-card button[kirby-button]{margin:0;border-radius:0}kirby-card button[kirby-button]:not(:focus){border-top:1px solid var(--kirby-background-color)}.cancel-btn:focus-visible{transition:all 80ms linear 0ms;box-shadow:var(--kirby-elevation-8),var(--kirby-focus-ring-md-inset)}.cancel-btn{font-weight:var(--kirby-font-weight-bold);margin-top:var(--kirby-spacing-s);margin-bottom:var(--kirby-spacing-m);pointer-events:auto}\n"]
1945
+ }]
1946
+ }],
1947
+ ctorParameters: () => [],
1948
+ propDecorators: {
1949
+ cancelButtonText: [{ type: Input }],
1950
+ hideCancel: [{ type: Input }],
1951
+ disabled: [{ type: Input }],
1952
+ header: [{ type: Input }],
1953
+ subheader: [{ type: Input }],
1954
+ items: [{ type: Input }],
1955
+ cancel: [{ type: Output }],
1956
+ itemSelect: [{ type: Output }]
1957
+ }
1958
+ });
1959
+ var ActionSheetHelper = class ActionSheetHelper {
1960
+ constructor(ionicModalController) {
1961
+ this.ionicModalController = ionicModalController;
1962
+ }
1963
+ async showActionSheet(config) {
1964
+ const cancel = new EventEmitter();
1965
+ const itemSelect = new EventEmitter();
1966
+ const ionModal = await this.ionicModalController.create({
1967
+ component: ActionSheetComponent,
1968
+ cssClass: ["kirby-overlay", "kirby-action-sheet"],
1969
+ componentProps: {
1970
+ ...config,
1971
+ cancel,
1972
+ itemSelect
1973
+ },
1974
+ backdropDismiss: true
1975
+ });
1976
+ ionModal.shadowRoot.querySelector(".modal-shadow").remove();
1977
+ const cancelSubscription = cancel.subscribe(() => ionModal.dismiss());
1978
+ const itemSelectSubscription = itemSelect.subscribe((item) => ionModal.dismiss(item));
1979
+ ionModal.onDidDismiss().then(() => {
1980
+ cancelSubscription.unsubscribe();
1981
+ itemSelectSubscription.unsubscribe();
1982
+ });
1983
+ await ionModal.present();
1984
+ return {
1985
+ dismiss: ionModal.dismiss.bind(ionModal),
1986
+ onWillDismiss: ionModal.onWillDismiss(),
1987
+ onDidDismiss: ionModal.onDidDismiss()
1988
+ };
1989
+ }
1990
+ static {
1991
+ this.ɵfac = i0.ɵɵngDeclareFactory({
1992
+ minVersion: "12.0.0",
1993
+ version: "22.2.3",
1994
+ ngImport: i0,
1995
+ type: ActionSheetHelper,
1996
+ deps: [{ token: i1$1.ModalController }],
1997
+ target: i0.ɵɵFactoryTarget.Injectable
1998
+ });
1999
+ }
2000
+ static {
2001
+ this.ɵprov = i0.ɵɵngDeclareInjectable({
2002
+ minVersion: "12.0.0",
2003
+ version: "22.2.3",
2004
+ ngImport: i0,
2005
+ type: ActionSheetHelper
2006
+ });
2007
+ }
2008
+ };
2009
+ i0.ɵɵngDeclareClassMetadata({
2010
+ minVersion: "12.0.0",
2011
+ version: "22.2.3",
2012
+ ngImport: i0,
2013
+ type: ActionSheetHelper,
2014
+ decorators: [{ type: Injectable }],
2015
+ ctorParameters: () => [{ type: i1$1.ModalController }]
2016
+ });
2017
+ var ModalController = class ModalController {
2018
+ constructor(modalHelper, actionSheetHelper, alertHelper, modalNavigationService, routeConfig) {
2019
+ this.modalHelper = modalHelper;
2020
+ this.actionSheetHelper = actionSheetHelper;
2021
+ this.alertHelper = alertHelper;
2022
+ this.modalNavigationService = modalNavigationService;
2023
+ this.routeConfig = routeConfig;
2024
+ this.overlays = [];
2025
+ this.noOverlayRegisteredErrorMessage = "No modal overlays are currently registered";
2026
+ this.destroy$ = new Subject();
2027
+ }
2028
+ async initialize(moduleRootRoutePath) {
2029
+ const modalNavigation = await this.modalNavigationService.getModalNavigation(this.routeConfig, moduleRootRoutePath);
2030
+ this.onModalRouteActivated(modalNavigation.activated$);
2031
+ this.onModalRouteDeactivated(modalNavigation.deactivated$);
2032
+ }
2033
+ onModalRouteActivated(modalRouteActivated$) {
2034
+ const navigateOnWillClose = () => {
2035
+ this.modalNavigationService.navigateOutOfModalOutlet();
2036
+ };
2037
+ const siblingModalRouteActivated$ = modalRouteActivated$.pipe(filter((modalRouteActivation) => !modalRouteActivation.isNewModal), map((modalRouteActivation) => modalRouteActivation.route));
2038
+ modalRouteActivated$.pipe(takeUntil(this.destroy$), filter(() => this.overlays.length === 0)).subscribe(async (modalRouteActivation) => {
2039
+ if (modalRouteActivation.isNewModal) await this.showModalRoute(modalRouteActivation.route, siblingModalRouteActivated$, navigateOnWillClose);
2040
+ });
2041
+ }
2042
+ onModalRouteDeactivated(modalRouteDeactivated$) {
2043
+ modalRouteDeactivated$.pipe(takeUntil(this.destroy$), filter(() => this.overlays.some((overlay) => overlay.isDismissing !== true))).subscribe(async () => {
2044
+ await this.hideAll();
2045
+ });
2046
+ }
2047
+ async showModal(config, onClose) {
2048
+ await this.showAndRegisterOverlay(() => this.modalHelper.showModalWindow(config), onClose);
2049
+ }
2050
+ async navigateToModal(path, queryParams) {
2051
+ return this.modalNavigationService.navigateToModal(path, queryParams);
2052
+ }
2053
+ async navigateWithinModal(relativePath, queryParams) {
2054
+ return this.modalNavigationService.navigateWithinModal(relativePath, queryParams);
2055
+ }
2056
+ async showModalRoute(modalRoute, siblingModalRouteActivated$, onWillClose) {
2057
+ const config = {
2058
+ ...modalRoute.snapshot.data.modalConfig,
2059
+ component: null,
2060
+ modalRoute,
2061
+ siblingModalRouteActivated$
2062
+ };
2063
+ await this.showAndRegisterOverlay(() => this.modalHelper.showModalWindow(config), null, onWillClose);
2064
+ }
2065
+ async showActionSheet(config, onClose) {
2066
+ await this.showAndRegisterOverlay(() => this.actionSheetHelper.showActionSheet(config), onClose);
2067
+ }
2068
+ async showAlert(config, onClose) {
2069
+ await this.showAndRegisterOverlay(() => this.alertHelper.showAlert(config), onClose);
2070
+ }
2071
+ async showAndRegisterOverlay(showOverlay, onCloseOverlay, onWillCloseOverlay) {
2072
+ const overlay = await showOverlay();
2073
+ if (!overlay) return;
2074
+ this.overlays.push(overlay);
2075
+ if (typeof onWillCloseOverlay === "function") overlay.onWillDismiss.then((event) => onWillCloseOverlay(event.data));
2076
+ overlay.onDidDismiss.then((event) => {
2077
+ this.overlays.pop();
2078
+ if (typeof onCloseOverlay === "function") onCloseOverlay(event.data);
2079
+ });
2080
+ }
2081
+ async hideTopmost(data) {
2082
+ const overlay = this.overlays[this.overlays.length - 1];
2083
+ if (!overlay) throw new Error(this.noOverlayRegisteredErrorMessage);
2084
+ return overlay.dismiss(data);
2085
+ }
2086
+ async hideAll() {
2087
+ await Promise.all(this.overlays.filter((overlay) => overlay.isDismissing !== true).map(async (overlay) => {
2088
+ await overlay.dismiss();
2089
+ }));
2090
+ }
2091
+ getTopMost() {
2092
+ return this.overlays[this.overlays.length - 1];
2093
+ }
2094
+ ngOnDestroy() {
2095
+ this.destroy$.next();
2096
+ this.destroy$.complete();
2097
+ }
2098
+ static {
2099
+ this.ɵfac = i0.ɵɵngDeclareFactory({
2100
+ minVersion: "12.0.0",
2101
+ version: "22.2.3",
2102
+ ngImport: i0,
2103
+ type: ModalController,
2104
+ deps: [
2105
+ { token: ModalHelper },
2106
+ { token: ActionSheetHelper },
2107
+ { token: AlertHelper },
2108
+ { token: ModalNavigationService },
2109
+ {
2110
+ token: ROUTES,
2111
+ optional: true
2112
+ }
2113
+ ],
2114
+ target: i0.ɵɵFactoryTarget.Injectable
2115
+ });
2116
+ }
2117
+ static {
2118
+ this.ɵprov = i0.ɵɵngDeclareInjectable({
2119
+ minVersion: "12.0.0",
2120
+ version: "22.2.3",
2121
+ ngImport: i0,
2122
+ type: ModalController
2123
+ });
2124
+ }
2125
+ };
2126
+ i0.ɵɵngDeclareClassMetadata({
2127
+ minVersion: "12.0.0",
2128
+ version: "22.2.3",
2129
+ ngImport: i0,
2130
+ type: ModalController,
2131
+ decorators: [{ type: Injectable }],
2132
+ ctorParameters: () => [
2133
+ { type: ModalHelper },
2134
+ { type: ActionSheetHelper },
2135
+ { type: AlertHelper },
2136
+ { type: ModalNavigationService },
2137
+ {
2138
+ type: void 0,
2139
+ decorators: [{ type: Optional }, {
2140
+ type: Inject,
2141
+ args: [ROUTES]
2142
+ }]
2143
+ }
2144
+ ]
2145
+ });
1719
2146
  const CanDismissModalGuard = async (_component, _currentRoute, currentState, nextState) => {
1720
- const modalNavService = inject(ModalNavigationService);
1721
- const currentRouteIsModal = modalNavService.isModalRoute(currentState.url);
1722
- const nextRouteIsModal = modalNavService.isModalRoute(nextState.url);
1723
- const isNavigatingWithinModal = currentRouteIsModal && nextRouteIsModal;
1724
- if (isNavigatingWithinModal) {
1725
- return true;
1726
- }
1727
- const modalController = inject(ModalController);
1728
- const topMostModal = modalController.getTopMost();
1729
- if (topMostModal) {
1730
- if (topMostModal.isDismissing) {
1731
- return true;
1732
- }
1733
- return topMostModal.dismiss();
1734
- }
1735
- else {
1736
- // Declarative modals are not created through Kirby Modalcontroller, let's try Ionic:
1737
- const ionicModalController = inject(ModalController$1);
1738
- const ionModal = await ionicModalController.getTop();
1739
- if (ionModal) {
1740
- return ionModal.dismiss();
1741
- }
1742
- }
1743
- return true;
2147
+ const modalNavService = inject(ModalNavigationService);
2148
+ const currentRouteIsModal = modalNavService.isModalRoute(currentState.url);
2149
+ const nextRouteIsModal = modalNavService.isModalRoute(nextState.url);
2150
+ if (currentRouteIsModal && nextRouteIsModal) return true;
2151
+ const topMostModal = inject(ModalController).getTopMost();
2152
+ if (topMostModal) {
2153
+ if (topMostModal.isDismissing) return true;
2154
+ return topMostModal.dismiss();
2155
+ } else {
2156
+ const ionModal = await inject(ModalController$1).getTop();
2157
+ if (ionModal) return ionModal.dismiss();
2158
+ }
2159
+ return true;
1744
2160
  };
1745
-
1746
- class ModalComponent {
1747
- set canDismiss(canDismiss) {
1748
- typeof canDismiss === 'boolean'
1749
- ? (this._canDismiss = canDismiss)
1750
- : (this._canDismiss = this.canDismissHelper.getCanDismissCallback(canDismiss));
1751
- }
1752
- constructor(canDismissHelper, modalNavigationService, windowRef, elementRef) {
1753
- this.canDismissHelper = canDismissHelper;
1754
- this.modalNavigationService = modalNavigationService;
1755
- this.windowRef = windowRef;
1756
- this.elementRef = elementRef;
1757
- this.isOpen = false;
1758
- this.size = 'medium';
1759
- this.scrollDisabled = false;
1760
- // NOTE: input properties forwarded to modal-wrapper ModalConfig
1761
- this.collapseTitle = false;
1762
- this.customHeight = undefined;
1763
- this.flavor = 'modal';
1764
- this.drawerSupplementaryAction = undefined;
1765
- this.interactWithBackground = false;
1766
- // end NOTE
1767
- this.willPresent = new EventEmitter();
1768
- this.didPresent = new EventEmitter();
1769
- this.didDismiss = new EventEmitter();
1770
- this.willDismiss = new EventEmitter();
1771
- /**
1772
- * We populate the ModalConfig with defaults here. This ensures that we can
1773
- * guard for `if (key in this._config)` and only update the config when any of these
1774
- * inputs change.
1775
- */
1776
- this._config = {
1777
- collapseTitle: this.collapseTitle,
1778
- customHeight: this.customHeight,
1779
- flavor: this.flavor,
1780
- drawerSupplementaryAction: this.drawerSupplementaryAction,
1781
- interactWithBackground: this.interactWithBackground,
1782
- };
1783
- this._canDismiss = true;
1784
- }
1785
- ngOnInit() {
1786
- this.forwardAriaLabel();
1787
- }
1788
- ngOnChanges(changes) {
1789
- this.updateModalConfigOnChange(changes);
1790
- }
1791
- scrollToTop(scrollDuration) {
1792
- this.ionContent.scrollToTop(scrollDuration);
1793
- }
1794
- scrollToBottom(scrollDuration) {
1795
- this.ionContent.scrollToBottom(scrollDuration);
1796
- }
1797
- _onWillPresent(event) {
1798
- this.willPresent.emit(event);
1799
- if (this.interactWithBackground) {
1800
- this.windowRef.nativeWindow.document.body.classList.add('allow-background-scroll');
1801
- }
1802
- }
1803
- _onDidPresent(event) {
1804
- this.modalNavigationService.handleBrowserBackButton(this.modalElement.nativeElement);
1805
- this.didPresent.emit(event);
1806
- }
1807
- _onWillDismiss(event) {
1808
- if (this.interactWithBackground) {
1809
- this.windowRef.nativeWindow.document.body.classList.remove('allow-background-scroll');
1810
- }
1811
- this.willDismiss.emit(event);
1812
- }
1813
- _onDidDismiss(event) {
1814
- this.didDismiss.emit(event);
1815
- }
1816
- updateModalConfigOnChange(changes) {
1817
- Object.entries(changes).forEach(([key]) => {
1818
- const isModalConfigProperty = key in this._config;
1819
- if (isModalConfigProperty) {
1820
- this._config[key] = changes[key].currentValue;
1821
- }
1822
- });
1823
- }
1824
- forwardAriaLabel() {
1825
- // Instead of setting aria label on ion-modal in the template we forward it to modal-wrapper for consistency
1826
- // and so we do not start listening for title changes in the modal-wrapper.
1827
- this._config.htmlAttributes = {
1828
- 'aria-label': inheritAriaLabelText(this.elementRef.nativeElement),
1829
- };
1830
- }
1831
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ModalComponent, deps: [{ token: CanDismissHelper }, { token: ModalNavigationService }, { token: i1.WindowRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
1832
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: ModalComponent, isStandalone: true, selector: "kirby-modal", inputs: { isOpen: "isOpen", trigger: "trigger", size: "size", scrollDisabled: "scrollDisabled", canDismiss: "canDismiss", collapseTitle: "collapseTitle", customHeight: "customHeight", flavor: "flavor", drawerSupplementaryAction: "drawerSupplementaryAction", interactWithBackground: "interactWithBackground" }, outputs: { willPresent: "willPresent", didPresent: "didPresent", didDismiss: "didDismiss", willDismiss: "willDismiss" }, queries: [{ propertyName: "template", first: true, predicate: TemplateRef, descendants: true, static: true }], viewQueries: [{ propertyName: "modalElement", first: true, predicate: IonModal, descendants: true, read: ElementRef, static: true }, { propertyName: "ionContent", first: true, predicate: IonContent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<ion-modal\n class=\"kirby-modal kirby-overlay kirby-modal-{{ size }}\"\n [ngClass]=\"[\n flavor === 'compact' ? 'kirby-modal-compact' : 'kirby-' + flavor,\n interactWithBackground ? 'interact-with-background' : '',\n ]\"\n [isOpen]=\"isOpen\"\n [trigger]=\"trigger\"\n [canDismiss]=\"_canDismiss\"\n [showBackdrop]=\"!interactWithBackground\"\n [style.--kirby-modal-height]=\"customHeight\"\n (willPresent)=\"_onWillPresent($event)\"\n (didPresent)=\"_onDidPresent($event)\"\n (willDismiss)=\"_onWillDismiss($event)\"\n (didDismiss)=\"_onDidDismiss($event)\"\n>\n <ng-template>\n @if (flavor === 'compact') {\n <kirby-modal-compact-wrapper\n [config]=\"_config\"\n [content]=\"template\"\n ></kirby-modal-compact-wrapper>\n } @else {\n <kirby-modal-wrapper\n class=\"ion-page\"\n [config]=\"_config\"\n [content]=\"template\"\n [scrollDisabled]=\"scrollDisabled\"\n ></kirby-modal-wrapper>\n }\n </ng-template>\n</ion-modal>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: IonModal, selector: "ion-modal" }, { kind: "component", type: ModalWrapperComponent, selector: "kirby-modal-wrapper", inputs: ["scrollDisabled", "config", "content"] }, { kind: "component", type: ModalCompactWrapperComponent, selector: "kirby-modal-compact-wrapper", inputs: ["config", "content"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1833
- }
1834
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ModalComponent, decorators: [{
1835
- type: Component,
1836
- args: [{ selector: 'kirby-modal', imports: [
1837
- CommonModule,
1838
- IconComponent,
1839
- IonModal,
1840
- ModalWrapperComponent,
1841
- ModalCompactWrapperComponent,
1842
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-modal\n class=\"kirby-modal kirby-overlay kirby-modal-{{ size }}\"\n [ngClass]=\"[\n flavor === 'compact' ? 'kirby-modal-compact' : 'kirby-' + flavor,\n interactWithBackground ? 'interact-with-background' : '',\n ]\"\n [isOpen]=\"isOpen\"\n [trigger]=\"trigger\"\n [canDismiss]=\"_canDismiss\"\n [showBackdrop]=\"!interactWithBackground\"\n [style.--kirby-modal-height]=\"customHeight\"\n (willPresent)=\"_onWillPresent($event)\"\n (didPresent)=\"_onDidPresent($event)\"\n (willDismiss)=\"_onWillDismiss($event)\"\n (didDismiss)=\"_onDidDismiss($event)\"\n>\n <ng-template>\n @if (flavor === 'compact') {\n <kirby-modal-compact-wrapper\n [config]=\"_config\"\n [content]=\"template\"\n ></kirby-modal-compact-wrapper>\n } @else {\n <kirby-modal-wrapper\n class=\"ion-page\"\n [config]=\"_config\"\n [content]=\"template\"\n [scrollDisabled]=\"scrollDisabled\"\n ></kirby-modal-wrapper>\n }\n </ng-template>\n</ion-modal>\n" }]
1843
- }], ctorParameters: () => [{ type: CanDismissHelper }, { type: ModalNavigationService }, { type: i1.WindowRef }, { type: i0.ElementRef }], propDecorators: { modalElement: [{
1844
- type: ViewChild,
1845
- args: [IonModal, { static: true, read: ElementRef }]
1846
- }], ionContent: [{
1847
- type: ViewChild,
1848
- args: [IonContent]
1849
- }], template: [{
1850
- type: ContentChild,
1851
- args: [TemplateRef, { static: true }]
1852
- }], isOpen: [{
1853
- type: Input
1854
- }], trigger: [{
1855
- type: Input
1856
- }], size: [{
1857
- type: Input
1858
- }], scrollDisabled: [{
1859
- type: Input
1860
- }], canDismiss: [{
1861
- type: Input
1862
- }], collapseTitle: [{
1863
- type: Input
1864
- }], customHeight: [{
1865
- type: Input
1866
- }], flavor: [{
1867
- type: Input
1868
- }], drawerSupplementaryAction: [{
1869
- type: Input
1870
- }], interactWithBackground: [{
1871
- type: Input
1872
- }], willPresent: [{
1873
- type: Output
1874
- }], didPresent: [{
1875
- type: Output
1876
- }], didDismiss: [{
1877
- type: Output
1878
- }], willDismiss: [{
1879
- type: Output
1880
- }] } });
1881
-
1882
- class ModalFooterComponent extends ModalElementComponent {
1883
- get _cssClass() {
1884
- return [this.themeColor, this.type].filter((cssClass) => !!cssClass);
1885
- }
1886
- constructor(elementRef, modalElementsAdvertiser) {
1887
- super(ModalElementType.FOOTER, elementRef, modalElementsAdvertiser);
1888
- this.snapToKeyboard = false;
1889
- this.type = 'fixed';
1890
- this.themeColor = 'white';
1891
- }
1892
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ModalFooterComponent, deps: [{ token: i0.ElementRef }, { token: ModalElementsAdvertiser, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
1893
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.18", type: ModalFooterComponent, isStandalone: true, selector: "kirby-modal-footer", inputs: { snapToKeyboard: "snapToKeyboard", type: "type", themeColor: "themeColor" }, host: { properties: { "class.snap-to-keyboard": "this.snapToKeyboard", "class": "this._cssClass" } }, usesInheritance: true, ngImport: i0, template: "<ion-footer role=\"presentation\">\n <ng-content></ng-content>\n</ion-footer>\n", styles: [".kirby-line-clamp{display:-webkit-box;-webkit-line-clamp:var(--line-clamp, none);-webkit-box-orient:vertical;overflow:hidden}ion-item-option.primary{background-color:var(--kirby-primary);color:var(--kirby-primary-contrast)}ion-item-option.secondary{background-color:var(--kirby-secondary);color:var(--kirby-secondary-contrast)}ion-item-option.tertiary{background-color:var(--kirby-tertiary);color:var(--kirby-tertiary-contrast)}ion-item-option.success{background-color:var(--kirby-success);color:var(--kirby-success-contrast)}ion-item-option.warning{background-color:var(--kirby-warning);color:var(--kirby-warning-contrast)}ion-item-option.danger{background-color:var(--kirby-danger);color:var(--kirby-danger-contrast)}ion-item-option.white-overlay{background-color:var(--kirby-white-overlay);color:var(--kirby-white-overlay-contrast)}ion-item-option.light{background-color:var(--kirby-light);color:var(--kirby-light-contrast)}ion-item-option.medium{background-color:var(--kirby-medium);color:var(--kirby-medium-contrast)}ion-item-option.dark{background-color:var(--kirby-dark);color:var(--kirby-dark-contrast)}ion-item-option.dark-overlay{background-color:var(--kirby-dark-overlay);color:var(--kirby-dark-overlay-contrast)}ion-footer{--kirby-inputs-background-color: var(--kirby-dark-overlay);--kirby-inputs-background-color-hover: var(--kirby-dark-overlay-10);--kirby-inputs-background-color-active: var(--kirby-dark-overlay-20);--kirby-inputs-color: var(--kirby-black);--kirby-inputs-indicator-background-color: var(--kirby-black);--kirby-inputs-indicator-color: var(--kirby-white);--kirby-inputs-placeholder-color: var(--kirby-semi-dark);--kirby-inputs-color-hover: var(--kirby-semi-dark);--kirby-inputs-elevation: none;--kirby-divider-color: var(--kirby-background-color);box-shadow:0 20px 30px -15px #1c1c1c4d,0 0 5px #1c1c1c14;box-sizing:inherit;display:flex;justify-content:var(--kirby-modal-footer-justify-content, center);align-items:center;background-color:var(--kirby-modal-footer-background, var(--kirby-white));color:var(--kirby-modal-footer-color, var(--kirby-white-contrast));padding:16px;padding-bottom:calc(12px + var(--kirby-modal-safe-area-bottom))}@media(min-width:768px){ion-footer{padding:24px}}:host{box-sizing:border-box;display:block}:host(.snap-to-keyboard) ion-footer{transition:transform .15s ease-out}:host(.light) ion-footer{--kirby-inputs-background-color: var(--kirby-white);--kirby-inputs-background-color-hover: var(--kirby-dark-overlay-10);--kirby-inputs-background-color-active: var(--kirby-dark-overlay-20);--kirby-inputs-color: var(--kirby-black);--kirby-inputs-indicator-background-color: var(--kirby-black);--kirby-inputs-indicator-color: var(--kirby-white);--kirby-inputs-placeholder-color: var(--kirby-semi-dark);--kirby-inputs-color-hover: var(--kirby-semi-dark);--kirby-divider-color: var(--kirby-medium);--kirby-inputs-elevation: var(--kirby-elevation-2);background-color:var(--kirby-background-color)}:host(.inline) ion-footer{--kirby-inputs-background-color: var(--kirby-white);--kirby-inputs-background-color-hover: var(--kirby-dark-overlay-10);--kirby-inputs-background-color-active: var(--kirby-dark-overlay-20);--kirby-inputs-color: var(--kirby-black);--kirby-inputs-indicator-background-color: var(--kirby-black);--kirby-inputs-indicator-color: var(--kirby-white);--kirby-inputs-placeholder-color: var(--kirby-semi-dark);--kirby-inputs-color-hover: var(--kirby-semi-dark);--kirby-divider-color: var(--kirby-medium);--kirby-inputs-elevation: var(--kirby-elevation-2);background:transparent;box-shadow:none}:host-context(.keyboard-visible).snap-to-keyboard ion-footer{transition:transform .25s ease-out 1ms;transform:translateY(calc((var(--keyboard-offset, 0px) - var(--kirby-modal-safe-area-bottom)) * -1))}\n"], dependencies: [{ kind: "component", type: IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1894
- }
1895
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ModalFooterComponent, decorators: [{
1896
- type: Component,
1897
- args: [{ imports: [IonFooter], selector: 'kirby-modal-footer', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-footer role=\"presentation\">\n <ng-content></ng-content>\n</ion-footer>\n", styles: [".kirby-line-clamp{display:-webkit-box;-webkit-line-clamp:var(--line-clamp, none);-webkit-box-orient:vertical;overflow:hidden}ion-item-option.primary{background-color:var(--kirby-primary);color:var(--kirby-primary-contrast)}ion-item-option.secondary{background-color:var(--kirby-secondary);color:var(--kirby-secondary-contrast)}ion-item-option.tertiary{background-color:var(--kirby-tertiary);color:var(--kirby-tertiary-contrast)}ion-item-option.success{background-color:var(--kirby-success);color:var(--kirby-success-contrast)}ion-item-option.warning{background-color:var(--kirby-warning);color:var(--kirby-warning-contrast)}ion-item-option.danger{background-color:var(--kirby-danger);color:var(--kirby-danger-contrast)}ion-item-option.white-overlay{background-color:var(--kirby-white-overlay);color:var(--kirby-white-overlay-contrast)}ion-item-option.light{background-color:var(--kirby-light);color:var(--kirby-light-contrast)}ion-item-option.medium{background-color:var(--kirby-medium);color:var(--kirby-medium-contrast)}ion-item-option.dark{background-color:var(--kirby-dark);color:var(--kirby-dark-contrast)}ion-item-option.dark-overlay{background-color:var(--kirby-dark-overlay);color:var(--kirby-dark-overlay-contrast)}ion-footer{--kirby-inputs-background-color: var(--kirby-dark-overlay);--kirby-inputs-background-color-hover: var(--kirby-dark-overlay-10);--kirby-inputs-background-color-active: var(--kirby-dark-overlay-20);--kirby-inputs-color: var(--kirby-black);--kirby-inputs-indicator-background-color: var(--kirby-black);--kirby-inputs-indicator-color: var(--kirby-white);--kirby-inputs-placeholder-color: var(--kirby-semi-dark);--kirby-inputs-color-hover: var(--kirby-semi-dark);--kirby-inputs-elevation: none;--kirby-divider-color: var(--kirby-background-color);box-shadow:0 20px 30px -15px #1c1c1c4d,0 0 5px #1c1c1c14;box-sizing:inherit;display:flex;justify-content:var(--kirby-modal-footer-justify-content, center);align-items:center;background-color:var(--kirby-modal-footer-background, var(--kirby-white));color:var(--kirby-modal-footer-color, var(--kirby-white-contrast));padding:16px;padding-bottom:calc(12px + var(--kirby-modal-safe-area-bottom))}@media(min-width:768px){ion-footer{padding:24px}}:host{box-sizing:border-box;display:block}:host(.snap-to-keyboard) ion-footer{transition:transform .15s ease-out}:host(.light) ion-footer{--kirby-inputs-background-color: var(--kirby-white);--kirby-inputs-background-color-hover: var(--kirby-dark-overlay-10);--kirby-inputs-background-color-active: var(--kirby-dark-overlay-20);--kirby-inputs-color: var(--kirby-black);--kirby-inputs-indicator-background-color: var(--kirby-black);--kirby-inputs-indicator-color: var(--kirby-white);--kirby-inputs-placeholder-color: var(--kirby-semi-dark);--kirby-inputs-color-hover: var(--kirby-semi-dark);--kirby-divider-color: var(--kirby-medium);--kirby-inputs-elevation: var(--kirby-elevation-2);background-color:var(--kirby-background-color)}:host(.inline) ion-footer{--kirby-inputs-background-color: var(--kirby-white);--kirby-inputs-background-color-hover: var(--kirby-dark-overlay-10);--kirby-inputs-background-color-active: var(--kirby-dark-overlay-20);--kirby-inputs-color: var(--kirby-black);--kirby-inputs-indicator-background-color: var(--kirby-black);--kirby-inputs-indicator-color: var(--kirby-white);--kirby-inputs-placeholder-color: var(--kirby-semi-dark);--kirby-inputs-color-hover: var(--kirby-semi-dark);--kirby-divider-color: var(--kirby-medium);--kirby-inputs-elevation: var(--kirby-elevation-2);background:transparent;box-shadow:none}:host-context(.keyboard-visible).snap-to-keyboard ion-footer{transition:transform .25s ease-out 1ms;transform:translateY(calc((var(--keyboard-offset, 0px) - var(--kirby-modal-safe-area-bottom)) * -1))}\n"] }]
1898
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: ModalElementsAdvertiser, decorators: [{
1899
- type: Optional
1900
- }] }], propDecorators: { snapToKeyboard: [{
1901
- type: HostBinding,
1902
- args: ['class.snap-to-keyboard']
1903
- }, {
1904
- type: Input
1905
- }], type: [{
1906
- type: Input
1907
- }], themeColor: [{
1908
- type: Input
1909
- }], _cssClass: [{
1910
- type: HostBinding,
1911
- args: ['class']
1912
- }] } });
1913
-
1914
- /**
1915
- * Generated bundle index. Do not edit.
1916
- */
1917
-
2161
+ var ModalComponent = class ModalComponent {
2162
+ set canDismiss(canDismiss) {
2163
+ typeof canDismiss === "boolean" ? this._canDismiss = canDismiss : this._canDismiss = this.canDismissHelper.getCanDismissCallback(canDismiss);
2164
+ }
2165
+ constructor(canDismissHelper, modalNavigationService, windowRef, elementRef) {
2166
+ this.canDismissHelper = canDismissHelper;
2167
+ this.modalNavigationService = modalNavigationService;
2168
+ this.windowRef = windowRef;
2169
+ this.elementRef = elementRef;
2170
+ this.isOpen = false;
2171
+ this.size = "medium";
2172
+ this.scrollDisabled = false;
2173
+ this.collapseTitle = false;
2174
+ this.customHeight = void 0;
2175
+ this.flavor = "modal";
2176
+ this.drawerSupplementaryAction = void 0;
2177
+ this.interactWithBackground = false;
2178
+ this.willPresent = new EventEmitter();
2179
+ this.didPresent = new EventEmitter();
2180
+ this.didDismiss = new EventEmitter();
2181
+ this.willDismiss = new EventEmitter();
2182
+ this._config = {
2183
+ collapseTitle: this.collapseTitle,
2184
+ customHeight: this.customHeight,
2185
+ flavor: this.flavor,
2186
+ drawerSupplementaryAction: this.drawerSupplementaryAction,
2187
+ interactWithBackground: this.interactWithBackground
2188
+ };
2189
+ this._canDismiss = true;
2190
+ }
2191
+ ngOnInit() {
2192
+ this.forwardAriaLabel();
2193
+ }
2194
+ ngOnChanges(changes) {
2195
+ this.updateModalConfigOnChange(changes);
2196
+ }
2197
+ scrollToTop(scrollDuration) {
2198
+ this.ionContent.scrollToTop(scrollDuration);
2199
+ }
2200
+ scrollToBottom(scrollDuration) {
2201
+ this.ionContent.scrollToBottom(scrollDuration);
2202
+ }
2203
+ _onWillPresent(event) {
2204
+ this.willPresent.emit(event);
2205
+ if (this.interactWithBackground) this.windowRef.nativeWindow.document.body.classList.add("allow-background-scroll");
2206
+ }
2207
+ _onDidPresent(event) {
2208
+ this.modalNavigationService.handleBrowserBackButton(this.modalElement.nativeElement);
2209
+ this.didPresent.emit(event);
2210
+ }
2211
+ _onWillDismiss(event) {
2212
+ if (this.interactWithBackground) this.windowRef.nativeWindow.document.body.classList.remove("allow-background-scroll");
2213
+ this.willDismiss.emit(event);
2214
+ }
2215
+ _onDidDismiss(event) {
2216
+ this.didDismiss.emit(event);
2217
+ }
2218
+ updateModalConfigOnChange(changes) {
2219
+ Object.entries(changes).forEach(([key]) => {
2220
+ if (key in this._config) this._config[key] = changes[key].currentValue;
2221
+ });
2222
+ }
2223
+ forwardAriaLabel() {
2224
+ this._config.htmlAttributes = { "aria-label": inheritAriaLabelText(this.elementRef.nativeElement) };
2225
+ }
2226
+ static {
2227
+ this.ɵfac = i0.ɵɵngDeclareFactory({
2228
+ minVersion: "12.0.0",
2229
+ version: "22.2.3",
2230
+ ngImport: i0,
2231
+ type: ModalComponent,
2232
+ deps: [
2233
+ { token: CanDismissHelper },
2234
+ { token: ModalNavigationService },
2235
+ { token: i1$2.WindowRef },
2236
+ { token: i0.ElementRef }
2237
+ ],
2238
+ target: i0.ɵɵFactoryTarget.Component
2239
+ });
2240
+ }
2241
+ static {
2242
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
2243
+ minVersion: "17.0.0",
2244
+ version: "22.2.3",
2245
+ type: ModalComponent,
2246
+ isStandalone: true,
2247
+ selector: "kirby-modal",
2248
+ inputs: {
2249
+ isOpen: "isOpen",
2250
+ trigger: "trigger",
2251
+ size: "size",
2252
+ scrollDisabled: "scrollDisabled",
2253
+ canDismiss: "canDismiss",
2254
+ collapseTitle: "collapseTitle",
2255
+ customHeight: "customHeight",
2256
+ flavor: "flavor",
2257
+ drawerSupplementaryAction: "drawerSupplementaryAction",
2258
+ interactWithBackground: "interactWithBackground"
2259
+ },
2260
+ outputs: {
2261
+ willPresent: "willPresent",
2262
+ didPresent: "didPresent",
2263
+ didDismiss: "didDismiss",
2264
+ willDismiss: "willDismiss"
2265
+ },
2266
+ queries: [{
2267
+ propertyName: "template",
2268
+ first: true,
2269
+ predicate: TemplateRef,
2270
+ descendants: true,
2271
+ static: true
2272
+ }],
2273
+ viewQueries: [{
2274
+ propertyName: "modalElement",
2275
+ first: true,
2276
+ predicate: IonModal,
2277
+ descendants: true,
2278
+ read: ElementRef,
2279
+ static: true
2280
+ }, {
2281
+ propertyName: "ionContent",
2282
+ first: true,
2283
+ predicate: IonContent,
2284
+ descendants: true
2285
+ }],
2286
+ usesOnChanges: true,
2287
+ ngImport: i0,
2288
+ template: "<ion-modal\n class=\"kirby-modal kirby-overlay kirby-modal-{{ size }}\"\n [ngClass]=\"[\n flavor === 'compact' ? 'kirby-modal-compact' : 'kirby-' + flavor,\n interactWithBackground ? 'interact-with-background' : '',\n ]\"\n [isOpen]=\"isOpen\"\n [trigger]=\"trigger\"\n [canDismiss]=\"_canDismiss\"\n [showBackdrop]=\"!interactWithBackground\"\n [style.--kirby-modal-height]=\"customHeight\"\n (willPresent)=\"_onWillPresent($event)\"\n (didPresent)=\"_onDidPresent($event)\"\n (willDismiss)=\"_onWillDismiss($event)\"\n (didDismiss)=\"_onDidDismiss($event)\"\n>\n <ng-template>\n @if (flavor === 'compact') {\n <kirby-modal-compact-wrapper\n [config]=\"_config\"\n [content]=\"template\"\n ></kirby-modal-compact-wrapper>\n } @else {\n <kirby-modal-wrapper\n class=\"ion-page\"\n [config]=\"_config\"\n [content]=\"template\"\n [scrollDisabled]=\"scrollDisabled\"\n ></kirby-modal-wrapper>\n }\n </ng-template>\n</ion-modal>\n",
2289
+ dependencies: [
2290
+ {
2291
+ kind: "ngmodule",
2292
+ type: CommonModule
2293
+ },
2294
+ {
2295
+ kind: "directive",
2296
+ type: i2.NgClass,
2297
+ selector: "[ngClass]",
2298
+ inputs: ["class", "ngClass"]
2299
+ },
2300
+ {
2301
+ kind: "component",
2302
+ type: IonModal,
2303
+ selector: "ion-modal"
2304
+ },
2305
+ {
2306
+ kind: "component",
2307
+ type: ModalWrapperComponent,
2308
+ selector: "kirby-modal-wrapper",
2309
+ inputs: [
2310
+ "scrollDisabled",
2311
+ "config",
2312
+ "content"
2313
+ ]
2314
+ },
2315
+ {
2316
+ kind: "component",
2317
+ type: ModalCompactWrapperComponent,
2318
+ selector: "kirby-modal-compact-wrapper",
2319
+ inputs: ["config", "content"]
2320
+ }
2321
+ ],
2322
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
2323
+ });
2324
+ }
2325
+ };
2326
+ i0.ɵɵngDeclareClassMetadata({
2327
+ minVersion: "12.0.0",
2328
+ version: "22.2.3",
2329
+ ngImport: i0,
2330
+ type: ModalComponent,
2331
+ decorators: [{
2332
+ type: Component,
2333
+ args: [{
2334
+ selector: "kirby-modal",
2335
+ imports: [
2336
+ CommonModule,
2337
+ IconComponent,
2338
+ IonModal,
2339
+ ModalWrapperComponent,
2340
+ ModalCompactWrapperComponent
2341
+ ],
2342
+ changeDetection: ChangeDetectionStrategy.OnPush,
2343
+ template: "<ion-modal\n class=\"kirby-modal kirby-overlay kirby-modal-{{ size }}\"\n [ngClass]=\"[\n flavor === 'compact' ? 'kirby-modal-compact' : 'kirby-' + flavor,\n interactWithBackground ? 'interact-with-background' : '',\n ]\"\n [isOpen]=\"isOpen\"\n [trigger]=\"trigger\"\n [canDismiss]=\"_canDismiss\"\n [showBackdrop]=\"!interactWithBackground\"\n [style.--kirby-modal-height]=\"customHeight\"\n (willPresent)=\"_onWillPresent($event)\"\n (didPresent)=\"_onDidPresent($event)\"\n (willDismiss)=\"_onWillDismiss($event)\"\n (didDismiss)=\"_onDidDismiss($event)\"\n>\n <ng-template>\n @if (flavor === 'compact') {\n <kirby-modal-compact-wrapper\n [config]=\"_config\"\n [content]=\"template\"\n ></kirby-modal-compact-wrapper>\n } @else {\n <kirby-modal-wrapper\n class=\"ion-page\"\n [config]=\"_config\"\n [content]=\"template\"\n [scrollDisabled]=\"scrollDisabled\"\n ></kirby-modal-wrapper>\n }\n </ng-template>\n</ion-modal>\n"
2344
+ }]
2345
+ }],
2346
+ ctorParameters: () => [
2347
+ { type: CanDismissHelper },
2348
+ { type: ModalNavigationService },
2349
+ { type: i1$2.WindowRef },
2350
+ { type: i0.ElementRef }
2351
+ ],
2352
+ propDecorators: {
2353
+ modalElement: [{
2354
+ type: ViewChild,
2355
+ args: [IonModal, {
2356
+ static: true,
2357
+ read: ElementRef
2358
+ }]
2359
+ }],
2360
+ ionContent: [{
2361
+ type: ViewChild,
2362
+ args: [IonContent]
2363
+ }],
2364
+ template: [{
2365
+ type: ContentChild,
2366
+ args: [TemplateRef, { static: true }]
2367
+ }],
2368
+ isOpen: [{ type: Input }],
2369
+ trigger: [{ type: Input }],
2370
+ size: [{ type: Input }],
2371
+ scrollDisabled: [{ type: Input }],
2372
+ canDismiss: [{ type: Input }],
2373
+ collapseTitle: [{ type: Input }],
2374
+ customHeight: [{ type: Input }],
2375
+ flavor: [{ type: Input }],
2376
+ drawerSupplementaryAction: [{ type: Input }],
2377
+ interactWithBackground: [{ type: Input }],
2378
+ willPresent: [{ type: Output }],
2379
+ didPresent: [{ type: Output }],
2380
+ didDismiss: [{ type: Output }],
2381
+ willDismiss: [{ type: Output }]
2382
+ }
2383
+ });
2384
+ var ModalFooterComponent = class ModalFooterComponent extends ModalElementComponent {
2385
+ get _cssClass() {
2386
+ return [
2387
+ this.themeColor,
2388
+ this.type,
2389
+ this.surface
2390
+ ].filter((cssClass) => !!cssClass);
2391
+ }
2392
+ get surface() {
2393
+ if (this.type === "inline") return null;
2394
+ return this.themeColor === "light" ? "kirby-surface-base" : "kirby-surface-raised";
2395
+ }
2396
+ constructor(elementRef, modalElementsAdvertiser) {
2397
+ super(ModalElementType.FOOTER, elementRef, modalElementsAdvertiser);
2398
+ this.snapToKeyboard = false;
2399
+ this.type = "fixed";
2400
+ this.themeColor = "white";
2401
+ }
2402
+ static {
2403
+ this.ɵfac = i0.ɵɵngDeclareFactory({
2404
+ minVersion: "12.0.0",
2405
+ version: "22.2.3",
2406
+ ngImport: i0,
2407
+ type: ModalFooterComponent,
2408
+ deps: [{ token: i0.ElementRef }, {
2409
+ token: ModalElementsAdvertiser,
2410
+ optional: true
2411
+ }],
2412
+ target: i0.ɵɵFactoryTarget.Component
2413
+ });
2414
+ }
2415
+ static {
2416
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
2417
+ minVersion: "14.0.0",
2418
+ version: "22.2.3",
2419
+ type: ModalFooterComponent,
2420
+ isStandalone: true,
2421
+ selector: "kirby-modal-footer",
2422
+ inputs: {
2423
+ snapToKeyboard: "snapToKeyboard",
2424
+ type: "type",
2425
+ themeColor: "themeColor"
2426
+ },
2427
+ host: { properties: {
2428
+ "class.snap-to-keyboard": "this.snapToKeyboard",
2429
+ "class": "this._cssClass"
2430
+ } },
2431
+ usesInheritance: true,
2432
+ ngImport: i0,
2433
+ template: "<ion-footer role=\"presentation\">\n <ng-content></ng-content>\n</ion-footer>\n",
2434
+ styles: [".kirby-line-clamp{display:-webkit-box;-webkit-line-clamp:var(--line-clamp, none);-webkit-box-orient:vertical;overflow:hidden}ion-item-option.success{background-color:var(--kirby-color-fill-success);color:var(--kirby-color-content-success)}@media(hover:hover){ion-item-option.success:hover{background-color:var(--kirby-color-fill-success-hover);color:var(--kirby-color-content-success-hover)}}ion-item-option.success:active{background-color:var(--kirby-color-fill-success-active);color:var(--kirby-color-content-success-active)}ion-item-option.warning{background-color:var(--kirby-color-fill-warning);color:var(--kirby-color-content-warning)}@media(hover:hover){ion-item-option.warning:hover{background-color:var(--kirby-color-fill-warning-hover);color:var(--kirby-color-content-warning-hover)}}ion-item-option.warning:active{background-color:var(--kirby-color-fill-warning-active);color:var(--kirby-color-content-warning-active)}ion-item-option.danger{background-color:var(--kirby-color-fill-danger);color:var(--kirby-color-content-danger)}@media(hover:hover){ion-item-option.danger:hover{background-color:var(--kirby-color-fill-danger-hover);color:var(--kirby-color-content-danger-hover)}}ion-item-option.danger:active{background-color:var(--kirby-color-fill-danger-active);color:var(--kirby-color-content-danger-active)}ion-footer{--kirby-inputs-background-color: var(--kirby-dark-overlay);--kirby-inputs-background-color-hover: var(--kirby-dark-overlay-10);--kirby-inputs-background-color-active: var(--kirby-dark-overlay-20);--kirby-inputs-color: var(--kirby-black);--kirby-inputs-indicator-background-color: var(--kirby-black);--kirby-inputs-indicator-color: var(--kirby-white);--kirby-inputs-placeholder-color: var(--kirby-semi-dark);--kirby-inputs-color-hover: var(--kirby-semi-dark);--kirby-inputs-elevation: none;--kirby-divider-color: var(--kirby-background-color);box-shadow:var(--kirby-elevation-8);box-sizing:inherit;display:flex;justify-content:var(--kirby-modal-footer-justify-content, center);align-items:center;background-color:var(--kirby-modal-footer-background, var(--kirby-color-fill-base));color:var(--kirby-modal-footer-color, var(--kirby-color-content-base));padding:var(--kirby-spacing-s);padding-bottom:calc(var(--kirby-spacing-xs) + var(--kirby-modal-safe-area-bottom))}@media(min-width:768px){ion-footer{padding:var(--kirby-spacing-m)}}:host{box-sizing:border-box;display:block}:host(.snap-to-keyboard) ion-footer{transition:transform var(--kirby-transition-soft-keyboard-leave)}:host(.light) ion-footer{--kirby-inputs-background-color: var(--kirby-white);--kirby-inputs-background-color-hover: var(--kirby-dark-overlay-10);--kirby-inputs-background-color-active: var(--kirby-dark-overlay-20);--kirby-inputs-color: var(--kirby-black);--kirby-inputs-indicator-background-color: var(--kirby-black);--kirby-inputs-indicator-color: var(--kirby-white);--kirby-inputs-placeholder-color: var(--kirby-semi-dark);--kirby-inputs-color-hover: var(--kirby-semi-dark);--kirby-divider-color: var(--kirby-medium);--kirby-inputs-elevation: var(--kirby-elevation-2)}:host(.inline) ion-footer{--kirby-inputs-background-color: var(--kirby-white);--kirby-inputs-background-color-hover: var(--kirby-dark-overlay-10);--kirby-inputs-background-color-active: var(--kirby-dark-overlay-20);--kirby-inputs-color: var(--kirby-black);--kirby-inputs-indicator-background-color: var(--kirby-black);--kirby-inputs-indicator-color: var(--kirby-white);--kirby-inputs-placeholder-color: var(--kirby-semi-dark);--kirby-inputs-color-hover: var(--kirby-semi-dark);--kirby-divider-color: var(--kirby-medium);--kirby-inputs-elevation: var(--kirby-elevation-2);background:transparent;box-shadow:none}:host-context(.keyboard-visible).snap-to-keyboard ion-footer{transition:transform var(--kirby-transition-soft-keyboard-enter);transform:translateY(calc((var(--keyboard-offset, 0px) - var(--kirby-modal-safe-area-bottom)) * -1))}\n"],
2435
+ dependencies: [{
2436
+ kind: "component",
2437
+ type: IonFooter,
2438
+ selector: "ion-footer",
2439
+ inputs: [
2440
+ "collapse",
2441
+ "mode",
2442
+ "translucent"
2443
+ ]
2444
+ }],
2445
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
2446
+ });
2447
+ }
2448
+ };
2449
+ i0.ɵɵngDeclareClassMetadata({
2450
+ minVersion: "12.0.0",
2451
+ version: "22.2.3",
2452
+ ngImport: i0,
2453
+ type: ModalFooterComponent,
2454
+ decorators: [{
2455
+ type: Component,
2456
+ args: [{
2457
+ imports: [IonFooter],
2458
+ selector: "kirby-modal-footer",
2459
+ changeDetection: ChangeDetectionStrategy.OnPush,
2460
+ template: "<ion-footer role=\"presentation\">\n <ng-content></ng-content>\n</ion-footer>\n",
2461
+ styles: [".kirby-line-clamp{display:-webkit-box;-webkit-line-clamp:var(--line-clamp, none);-webkit-box-orient:vertical;overflow:hidden}ion-item-option.success{background-color:var(--kirby-color-fill-success);color:var(--kirby-color-content-success)}@media(hover:hover){ion-item-option.success:hover{background-color:var(--kirby-color-fill-success-hover);color:var(--kirby-color-content-success-hover)}}ion-item-option.success:active{background-color:var(--kirby-color-fill-success-active);color:var(--kirby-color-content-success-active)}ion-item-option.warning{background-color:var(--kirby-color-fill-warning);color:var(--kirby-color-content-warning)}@media(hover:hover){ion-item-option.warning:hover{background-color:var(--kirby-color-fill-warning-hover);color:var(--kirby-color-content-warning-hover)}}ion-item-option.warning:active{background-color:var(--kirby-color-fill-warning-active);color:var(--kirby-color-content-warning-active)}ion-item-option.danger{background-color:var(--kirby-color-fill-danger);color:var(--kirby-color-content-danger)}@media(hover:hover){ion-item-option.danger:hover{background-color:var(--kirby-color-fill-danger-hover);color:var(--kirby-color-content-danger-hover)}}ion-item-option.danger:active{background-color:var(--kirby-color-fill-danger-active);color:var(--kirby-color-content-danger-active)}ion-footer{--kirby-inputs-background-color: var(--kirby-dark-overlay);--kirby-inputs-background-color-hover: var(--kirby-dark-overlay-10);--kirby-inputs-background-color-active: var(--kirby-dark-overlay-20);--kirby-inputs-color: var(--kirby-black);--kirby-inputs-indicator-background-color: var(--kirby-black);--kirby-inputs-indicator-color: var(--kirby-white);--kirby-inputs-placeholder-color: var(--kirby-semi-dark);--kirby-inputs-color-hover: var(--kirby-semi-dark);--kirby-inputs-elevation: none;--kirby-divider-color: var(--kirby-background-color);box-shadow:var(--kirby-elevation-8);box-sizing:inherit;display:flex;justify-content:var(--kirby-modal-footer-justify-content, center);align-items:center;background-color:var(--kirby-modal-footer-background, var(--kirby-color-fill-base));color:var(--kirby-modal-footer-color, var(--kirby-color-content-base));padding:var(--kirby-spacing-s);padding-bottom:calc(var(--kirby-spacing-xs) + var(--kirby-modal-safe-area-bottom))}@media(min-width:768px){ion-footer{padding:var(--kirby-spacing-m)}}:host{box-sizing:border-box;display:block}:host(.snap-to-keyboard) ion-footer{transition:transform var(--kirby-transition-soft-keyboard-leave)}:host(.light) ion-footer{--kirby-inputs-background-color: var(--kirby-white);--kirby-inputs-background-color-hover: var(--kirby-dark-overlay-10);--kirby-inputs-background-color-active: var(--kirby-dark-overlay-20);--kirby-inputs-color: var(--kirby-black);--kirby-inputs-indicator-background-color: var(--kirby-black);--kirby-inputs-indicator-color: var(--kirby-white);--kirby-inputs-placeholder-color: var(--kirby-semi-dark);--kirby-inputs-color-hover: var(--kirby-semi-dark);--kirby-divider-color: var(--kirby-medium);--kirby-inputs-elevation: var(--kirby-elevation-2)}:host(.inline) ion-footer{--kirby-inputs-background-color: var(--kirby-white);--kirby-inputs-background-color-hover: var(--kirby-dark-overlay-10);--kirby-inputs-background-color-active: var(--kirby-dark-overlay-20);--kirby-inputs-color: var(--kirby-black);--kirby-inputs-indicator-background-color: var(--kirby-black);--kirby-inputs-indicator-color: var(--kirby-white);--kirby-inputs-placeholder-color: var(--kirby-semi-dark);--kirby-inputs-color-hover: var(--kirby-semi-dark);--kirby-divider-color: var(--kirby-medium);--kirby-inputs-elevation: var(--kirby-elevation-2);background:transparent;box-shadow:none}:host-context(.keyboard-visible).snap-to-keyboard ion-footer{transition:transform var(--kirby-transition-soft-keyboard-enter);transform:translateY(calc((var(--keyboard-offset, 0px) - var(--kirby-modal-safe-area-bottom)) * -1))}\n"]
2462
+ }]
2463
+ }],
2464
+ ctorParameters: () => [{ type: i0.ElementRef }, {
2465
+ type: ModalElementsAdvertiser,
2466
+ decorators: [{ type: Optional }]
2467
+ }],
2468
+ propDecorators: {
2469
+ snapToKeyboard: [{
2470
+ type: HostBinding,
2471
+ args: ["class.snap-to-keyboard"]
2472
+ }, { type: Input }],
2473
+ type: [{ type: Input }],
2474
+ themeColor: [{ type: Input }],
2475
+ _cssClass: [{
2476
+ type: HostBinding,
2477
+ args: ["class"]
2478
+ }]
2479
+ }
2480
+ });
1918
2481
  export { ActionSheetComponent, ActionSheetHelper, AlertComponent, AlertHelper, COMPONENT_PROPS, CanDismissHelper, CanDismissModalGuard, DrawerSupplementaryAction, Modal, ModalCompactWrapperComponent, ModalComponent, ModalController, ModalElementComponent, ModalElementType, ModalElementsAdvertiser, ModalFooterComponent, ModalHelper, ModalNavigationService, ModalWrapperComponent };
1919
- //# sourceMappingURL=kirbydesign-designsystem-modal.mjs.map
2482
+
2483
+ //# sourceMappingURL=kirbydesign-designsystem-modal.mjs.map