@kirbydesign/designsystem 11.11.3-dev-e7cb27f → 12.0.0-dev-67d5287

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