@ionic/core 8.8.16-dev.11784841344.1aa1a41c → 8.8.16-dev.11784914346.10d0804c

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 (205) hide show
  1. package/components/ion-accordion.js +1 -1
  2. package/components/ion-action-sheet.js +1 -1
  3. package/components/ion-alert.js +1 -1
  4. package/components/ion-avatar.js +1 -1
  5. package/components/ion-back-button.js +1 -1
  6. package/components/ion-badge.js +1 -1
  7. package/components/ion-breadcrumb.js +1 -1
  8. package/components/ion-button.js +1 -1
  9. package/components/ion-buttons.js +1 -1
  10. package/components/ion-content.js +1 -1
  11. package/components/ion-datetime.js +1 -1
  12. package/components/ion-fab-button.js +1 -1
  13. package/components/ion-footer.js +1 -1
  14. package/components/ion-header.js +1 -1
  15. package/components/ion-icon.js +1 -1
  16. package/components/ion-input-password-toggle.js +1 -1
  17. package/components/ion-input.js +1 -1
  18. package/components/ion-item-option.js +1 -1
  19. package/components/ion-item.js +1 -1
  20. package/components/ion-menu-button.js +1 -1
  21. package/components/ion-refresher-content.js +1 -1
  22. package/components/ion-reorder.js +1 -1
  23. package/components/ion-searchbar.js +1 -1
  24. package/components/ion-segment-button.js +1 -1
  25. package/components/ion-select-modal.js +1 -1
  26. package/components/ion-select-popover.js +1 -1
  27. package/components/ion-select.js +1 -1
  28. package/components/ion-tab-bar.js +1 -1
  29. package/components/ion-tab-button.js +1 -1
  30. package/components/ion-title.js +1 -1
  31. package/components/ion-toast.js +1 -1
  32. package/components/ion-toggle.js +1 -1
  33. package/components/{p-DiKh2eQw.js → p-4u9RNymb.js} +1 -1
  34. package/components/{p-B8KYxaMx.js → p-B8xhFBOE.js} +1 -1
  35. package/components/p-BAnNwWMA.js +4 -0
  36. package/components/p-BYZR_5L4.js +4 -0
  37. package/components/p-B_zaqq5F.js +4 -0
  38. package/components/p-CO9VfZyc.js +4 -0
  39. package/components/p-Cjx0xPoU.js +4 -0
  40. package/components/p-CyWeCU8e.js +4 -0
  41. package/components/p-DRnK3A-V.js +4 -0
  42. package/components/p-DcVqGRkT.js +4 -0
  43. package/components/p-Dght1fh7.js +4 -0
  44. package/components/p-GpxJMpJu.js +4 -0
  45. package/dist/cjs/{index-Cu9JNpPi.js → index-CgAbCW6L.js} +1 -1
  46. package/dist/cjs/ion-accordion_2.cjs.entry.js +1 -1
  47. package/dist/cjs/ion-action-sheet.cjs.entry.js +3 -3
  48. package/dist/cjs/ion-alert.cjs.entry.js +3 -3
  49. package/dist/cjs/ion-app_8.cjs.entry.js +194 -65
  50. package/dist/cjs/ion-avatar_3.cjs.entry.js +4 -4
  51. package/dist/cjs/ion-back-button.cjs.entry.js +1 -1
  52. package/dist/cjs/ion-breadcrumb_2.cjs.entry.js +1 -1
  53. package/dist/cjs/ion-button_2.cjs.entry.js +3 -3
  54. package/dist/cjs/ion-datetime_3.cjs.entry.js +1 -1
  55. package/dist/cjs/ion-fab_3.cjs.entry.js +1 -1
  56. package/dist/cjs/ion-input-password-toggle.cjs.entry.js +1 -1
  57. package/dist/cjs/ion-input.cjs.entry.js +4 -4
  58. package/dist/cjs/ion-item-option_3.cjs.entry.js +1 -1
  59. package/dist/cjs/ion-item_8.cjs.entry.js +1 -1
  60. package/dist/cjs/ion-menu_3.cjs.entry.js +1 -1
  61. package/dist/cjs/ion-refresher_2.cjs.entry.js +1 -1
  62. package/dist/cjs/ion-reorder_2.cjs.entry.js +1 -1
  63. package/dist/cjs/ion-searchbar.cjs.entry.js +2 -2
  64. package/dist/cjs/ion-segment_2.cjs.entry.js +1 -1
  65. package/dist/cjs/ion-select-modal.cjs.entry.js +4 -4
  66. package/dist/cjs/ion-select_3.cjs.entry.js +5 -5
  67. package/dist/cjs/ion-tab-bar_2.cjs.entry.js +78 -80
  68. package/dist/cjs/ion-toggle.cjs.entry.js +1 -1
  69. package/dist/cjs/ionic.cjs.js +1 -1
  70. package/dist/cjs/loader.cjs.js +1 -1
  71. package/dist/cjs/scroll-hide-controller-G9HOmmhN.js +345 -0
  72. package/dist/collection/components/action-sheet/action-sheet.ionic.css +2 -5
  73. package/dist/collection/components/action-sheet/action-sheet.ios.css +2 -1
  74. package/dist/collection/components/action-sheet/action-sheet.md.css +2 -1
  75. package/dist/collection/components/alert/alert.ionic.css +2 -5
  76. package/dist/collection/components/alert/alert.ios.css +2 -1
  77. package/dist/collection/components/alert/alert.md.css +2 -1
  78. package/dist/collection/components/avatar/avatar.ionic.css +12 -6
  79. package/dist/collection/components/badge/badge.ionic.css +6 -3
  80. package/dist/collection/components/badge/badge.ios.css +4 -2
  81. package/dist/collection/components/badge/badge.md.css +2 -1
  82. package/dist/collection/components/button/button.ionic.css +4 -2
  83. package/dist/collection/components/buttons/buttons.ionic.css +1 -1
  84. package/dist/collection/components/content/content.css +39 -0
  85. package/dist/collection/components/footer/footer-interface.js +1 -0
  86. package/dist/collection/components/footer/footer.ios.css +19 -4
  87. package/dist/collection/components/footer/footer.js +102 -15
  88. package/dist/collection/components/footer/footer.md.css +28 -0
  89. package/dist/collection/components/header/header-interface.js +1 -0
  90. package/dist/collection/components/header/header.ionic.css +153 -0
  91. package/dist/collection/components/header/header.ios.css +153 -123
  92. package/dist/collection/components/header/header.js +139 -28
  93. package/dist/collection/components/header/header.md.css +176 -1
  94. package/dist/collection/components/header/header.utils.js +6 -13
  95. package/dist/collection/components/input/input.ionic.css +2 -1
  96. package/dist/collection/components/input/input.ios.css +2 -1
  97. package/dist/collection/components/input/input.md.css +2 -1
  98. package/dist/collection/components/item-option/item-option.ionic.css +2 -1
  99. package/dist/collection/components/searchbar/searchbar.ionic.css +6 -2
  100. package/dist/collection/components/segment-button/segment-button.ionic.css +2 -1
  101. package/dist/collection/components/select/select.ionic.css +2 -1
  102. package/dist/collection/components/select-modal/select-modal.ionic.css +2 -5
  103. package/dist/collection/components/select-modal/select-modal.ios.css +2 -1
  104. package/dist/collection/components/select-modal/select-modal.md.css +2 -1
  105. package/dist/collection/components/select-popover/select-popover.ionic.css +2 -5
  106. package/dist/collection/components/select-popover/select-popover.ios.css +2 -1
  107. package/dist/collection/components/select-popover/select-popover.md.css +2 -1
  108. package/dist/collection/components/tab-bar/tab-bar.ionic.css +25 -3
  109. package/dist/collection/components/tab-bar/tab-bar.ios.css +15 -0
  110. package/dist/collection/components/tab-bar/tab-bar.js +94 -88
  111. package/dist/collection/components/tab-bar/tab-bar.md.css +15 -0
  112. package/dist/collection/components/tab-button/tab-button.ionic.css +2 -1
  113. package/dist/collection/components/title/title.md.css +7 -0
  114. package/dist/collection/utils/scroll-hide-controller.js +178 -0
  115. package/dist/docs.json +144 -32
  116. package/dist/esm/{index-1y3VhUSy.js → index-D2tu5BUg.js} +1 -1
  117. package/dist/esm/ion-accordion_2.entry.js +1 -1
  118. package/dist/esm/ion-action-sheet.entry.js +3 -3
  119. package/dist/esm/ion-alert.entry.js +3 -3
  120. package/dist/esm/ion-app_8.entry.js +194 -65
  121. package/dist/esm/ion-avatar_3.entry.js +4 -4
  122. package/dist/esm/ion-back-button.entry.js +1 -1
  123. package/dist/esm/ion-breadcrumb_2.entry.js +1 -1
  124. package/dist/esm/ion-button_2.entry.js +3 -3
  125. package/dist/esm/ion-datetime_3.entry.js +1 -1
  126. package/dist/esm/ion-fab_3.entry.js +1 -1
  127. package/dist/esm/ion-input-password-toggle.entry.js +1 -1
  128. package/dist/esm/ion-input.entry.js +4 -4
  129. package/dist/esm/ion-item-option_3.entry.js +1 -1
  130. package/dist/esm/ion-item_8.entry.js +1 -1
  131. package/dist/esm/ion-menu_3.entry.js +1 -1
  132. package/dist/esm/ion-refresher_2.entry.js +1 -1
  133. package/dist/esm/ion-reorder_2.entry.js +1 -1
  134. package/dist/esm/ion-searchbar.entry.js +2 -2
  135. package/dist/esm/ion-segment_2.entry.js +1 -1
  136. package/dist/esm/ion-select-modal.entry.js +4 -4
  137. package/dist/esm/ion-select_3.entry.js +5 -5
  138. package/dist/esm/ion-tab-bar_2.entry.js +79 -81
  139. package/dist/esm/ion-toggle.entry.js +1 -1
  140. package/dist/esm/ionic.js +1 -1
  141. package/dist/esm/loader.js +1 -1
  142. package/dist/esm/scroll-hide-controller-CUNW7EpD.js +342 -0
  143. package/dist/html.html-data.json +36 -4
  144. package/dist/ionic/ionic.esm.js +1 -1
  145. package/dist/ionic/p-07bd8446.entry.js +4 -0
  146. package/dist/ionic/p-103e1d9f.entry.js +4 -0
  147. package/dist/ionic/{p-eeb7b373.entry.js → p-18bc4f2d.entry.js} +1 -1
  148. package/dist/ionic/p-248265c2.entry.js +4 -0
  149. package/dist/ionic/{p-fb457fdd.entry.js → p-3bc5b5e9.entry.js} +1 -1
  150. package/dist/ionic/{p-42a882b7.entry.js → p-43b00c5b.entry.js} +1 -1
  151. package/dist/ionic/{p-d0f253fc.entry.js → p-56224b93.entry.js} +1 -1
  152. package/dist/ionic/p-5732396e.entry.js +4 -0
  153. package/dist/ionic/{p-b3d04a86.entry.js → p-58d8877d.entry.js} +1 -1
  154. package/dist/ionic/{p-9e9be378.entry.js → p-5d079dc1.entry.js} +1 -1
  155. package/dist/ionic/{p-d0dfc9a3.entry.js → p-5e9665dd.entry.js} +1 -1
  156. package/dist/ionic/{p-7b2fe639.entry.js → p-5fee5cc1.entry.js} +1 -1
  157. package/dist/ionic/p-64734604.entry.js +4 -0
  158. package/dist/ionic/p-69feeff9.entry.js +4 -0
  159. package/dist/ionic/p-83acfa2d.entry.js +4 -0
  160. package/dist/ionic/{p-f692219d.entry.js → p-849b1759.entry.js} +1 -1
  161. package/dist/ionic/{p-a09c7a4c.entry.js → p-86f040e0.entry.js} +1 -1
  162. package/dist/ionic/p-8cb23f27.entry.js +4 -0
  163. package/dist/ionic/p-C1I_d964.js +4 -0
  164. package/dist/ionic/p-b97778f5.entry.js +4 -0
  165. package/dist/ionic/p-be9db7e8.entry.js +4 -0
  166. package/dist/ionic/{p-2fba8f15.entry.js → p-c04429f2.entry.js} +1 -1
  167. package/dist/ionic/p-c25a2a9b.entry.js +4 -0
  168. package/dist/ionic/{p-a797625e.entry.js → p-d272ff4f.entry.js} +1 -1
  169. package/dist/types/components/footer/footer-interface.d.ts +1 -0
  170. package/dist/types/components/footer/footer.d.ts +16 -0
  171. package/dist/types/components/header/header-interface.d.ts +1 -0
  172. package/dist/types/components/header/header.d.ts +17 -0
  173. package/dist/types/components/header/header.utils.d.ts +4 -5
  174. package/dist/types/components/tab-bar/tab-bar-interface.d.ts +1 -0
  175. package/dist/types/components/tab-bar/tab-bar.d.ts +17 -14
  176. package/dist/types/components.d.ts +37 -13
  177. package/dist/types/utils/scroll-hide-controller.d.ts +56 -0
  178. package/hydrate/index.js +477 -175
  179. package/hydrate/index.mjs +477 -175
  180. package/package.json +2 -2
  181. package/components/p-BZwQa9ey.js +0 -4
  182. package/components/p-CJCMdFb9.js +0 -4
  183. package/components/p-Ck_9SoHZ.js +0 -4
  184. package/components/p-CmnPD02Z.js +0 -4
  185. package/components/p-D-Xa9lMG.js +0 -4
  186. package/components/p-DFSqPtzD.js +0 -4
  187. package/components/p-NPsFR8Ng.js +0 -4
  188. package/components/p-U2gyA6Z0.js +0 -4
  189. package/components/p-q8wGOPJB.js +0 -4
  190. package/dist/cjs/keyboard-controller-CefyW9lm.js +0 -169
  191. package/dist/esm/keyboard-controller-BFwRdk2T.js +0 -167
  192. package/dist/ionic/p-0c4d9d7c.entry.js +0 -4
  193. package/dist/ionic/p-40dc9dbd.entry.js +0 -4
  194. package/dist/ionic/p-54419365.entry.js +0 -4
  195. package/dist/ionic/p-6293e9f1.entry.js +0 -4
  196. package/dist/ionic/p-7de397c7.entry.js +0 -4
  197. package/dist/ionic/p-8cf82b85.entry.js +0 -4
  198. package/dist/ionic/p-MqqcZQSB.js +0 -4
  199. package/dist/ionic/p-a6e04ca3.entry.js +0 -4
  200. package/dist/ionic/p-a6fe63f0.entry.js +0 -4
  201. package/dist/ionic/p-b275f17e.entry.js +0 -4
  202. package/dist/ionic/p-c5635175.entry.js +0 -4
  203. package/dist/ionic/p-dc8e0b91.entry.js +0 -4
  204. /package/components/{p-J03hHbbL.js → p-BaPtaYEC.js} +0 -0
  205. /package/dist/ionic/{p-1y3VhUSy.js → p-D2tu5BUg.js} +0 -0
@@ -9,6 +9,159 @@ ion-header ion-toolbar:first-of-type {
9
9
  padding-top: var(--ion-safe-area-top, 0);
10
10
  }
11
11
 
12
+ .header-collapse-fade ion-toolbar {
13
+ --opacity-scale: inherit;
14
+ }
15
+
16
+ /**
17
+ * Override styles applied during the page transition to prevent
18
+ * header flickering.
19
+ */
20
+ .header-collapse-fade.header-transitioning ion-toolbar {
21
+ --background: transparent;
22
+ --border-style: none;
23
+ }
24
+
25
+ .header-collapse-condense {
26
+ z-index: 9;
27
+ }
28
+
29
+ .header-collapse-condense ion-toolbar {
30
+ position: sticky;
31
+ top: 0;
32
+ }
33
+
34
+ .header-collapse-condense ion-toolbar:first-of-type {
35
+ /**
36
+ * The toolbar that contains the collapsible
37
+ * large title should not have safe area padding applied.
38
+ */
39
+ padding-top: 0px;
40
+ z-index: 1;
41
+ }
42
+
43
+ /**
44
+ * Large title toolbar should just use the content background
45
+ * since it needs to blend in with the header above it.
46
+ */
47
+ .header-collapse-condense ion-toolbar {
48
+ z-index: 0;
49
+ }
50
+
51
+ .header-collapse-condense ion-toolbar:last-of-type {
52
+ --border-width: 0px;
53
+ }
54
+
55
+ .header-collapse-condense ion-toolbar ion-searchbar {
56
+ padding-top: 0px;
57
+ padding-bottom: 13px;
58
+ }
59
+
60
+ .header-collapse-main {
61
+ --opacity-scale: 1;
62
+ }
63
+
64
+ .header-collapse-main ion-toolbar {
65
+ --opacity-scale: inherit;
66
+ }
67
+
68
+ .header-collapse-main ion-toolbar.in-toolbar ion-title,
69
+ .header-collapse-main ion-toolbar.in-toolbar ion-buttons {
70
+ transition: all 0.2s ease-in-out;
71
+ }
72
+
73
+ /**
74
+ * Large title toolbar should just use the content background
75
+ * since it needs to blend in with the header above it.
76
+ */
77
+ .header-collapse-condense ion-toolbar,
78
+ .header-collapse-condense-inactive.header-transitioning:not(.header-collapse-condense) ion-toolbar {
79
+ --background: var(--ion-background-color, #fff);
80
+ }
81
+
82
+ /**
83
+ * Override styles applied during the page transition to prevent
84
+ * header flickering.
85
+ */
86
+ .header-collapse-condense-inactive.header-transitioning:not(.header-collapse-condense) ion-toolbar {
87
+ --border-style: none;
88
+ --opacity-scale: 1;
89
+ }
90
+
91
+ .header-collapse-condense-inactive:not(.header-collapse-condense) ion-toolbar.in-toolbar ion-title,
92
+ .header-collapse-condense-inactive:not(.header-collapse-condense) ion-toolbar.in-toolbar ion-buttons.buttons-collapse {
93
+ opacity: 0;
94
+ pointer-events: none;
95
+ }
96
+
97
+ /**
98
+ * There is a bug in Safari where changing
99
+ * the opacity of an element in a scrollable container
100
+ * while rubber-banding causes the scroll position
101
+ * to jump to the top
102
+ */
103
+ .header-collapse-condense-inactive.header-collapse-condense ion-toolbar.in-toolbar ion-title,
104
+ .header-collapse-condense-inactive.header-collapse-condense ion-toolbar.in-toolbar ion-buttons.buttons-collapse {
105
+ visibility: hidden;
106
+ }
107
+
108
+ /**
109
+ * The main header is only hidden once the collapsible large
110
+ * title is configured. As a result, if the main header loads
111
+ * before the collapsible large title is configured then the
112
+ * main header will be visible briefly before being hidden
113
+ * by the collapsible large title.
114
+ *
115
+ * The following selector ensures that any main header
116
+ * on a page with a collapsible large title is hidden
117
+ * before the collapsible large title is configured.
118
+ * Once the collapsible large title is configured the main
119
+ * header will have the ".header-collapse-main" class, and
120
+ * this selector will no longer apply.
121
+ *
122
+ * The :has(...) part of the selector ensures a couple things:
123
+ * 1. This will only apply within a page view since the content
124
+ * must be a subsequent-sibling of the header (~ ion-content).
125
+ * 2. This will only apply when that content has an active condense
126
+ * header (the .header-collapse-condense class).
127
+ *
128
+ * We use opacity: 0 to avoid a layout shift.
129
+ * We use the class (not the attribute) because the class is only
130
+ * added when the condense effect is valid (large title present).
131
+ * The attribute alone is not sufficient since it would match even
132
+ * when the effect is guarded (e.g. no large title).
133
+ */
134
+ ion-header:not(.header-collapse-main):has(~ ion-content ion-header.header-collapse-condense) {
135
+ opacity: 0;
136
+ }
137
+
138
+ /**
139
+ * The deprecated collapse="condense" prop is iOS-only.
140
+ * On non-iOS themes, the condense header should be hidden since
141
+ * the JS won't activate it. Uses a class instead of an attribute
142
+ * selector because collapse is not a reflected prop, and framework
143
+ * proxies (Angular/Vue) bind it as a property.
144
+ */
145
+ .header-collapse-condense-hidden {
146
+ display: none;
147
+ }
148
+
149
+ ion-header.header-scroll-effect-hide {
150
+ transition: transform 300ms cubic-bezier(0, 0, 0.2, 1), opacity 300ms cubic-bezier(0, 0, 0.2, 1);
151
+ }
152
+
153
+ ion-header.header-scroll-effect-hide.header-scroll-hidden {
154
+ transform: translateY(-100%);
155
+ transition: transform 200ms cubic-bezier(0.4, 0, 1, 1), opacity 300ms cubic-bezier(0.4, 0, 1, 1);
156
+ opacity: 0;
157
+ }
158
+
159
+ @media (prefers-reduced-motion: reduce) {
160
+ ion-header.header-scroll-effect-hide,
161
+ ion-header.header-scroll-effect-hide.header-scroll-hidden {
162
+ transition: none;
163
+ }
164
+ }
12
165
  /**
13
166
  * Convert a pixels given value into rem
14
167
  *
@@ -163,129 +316,6 @@ ion-header {
163
316
  --border-width: 0;
164
317
  }
165
318
 
166
- .header-collapse-fade ion-toolbar {
167
- --opacity-scale: inherit;
168
- }
169
-
170
- /**
171
- * Override styles applied during the page transition to prevent
172
- * header flickering.
173
- */
174
- .header-collapse-fade.header-transitioning ion-toolbar {
175
- --background: transparent;
176
- --border-style: none;
177
- }
178
-
179
- .header-collapse-condense {
180
- z-index: 9;
181
- }
182
-
183
- .header-collapse-condense ion-toolbar {
184
- position: sticky;
185
- top: 0;
186
- }
187
-
188
- .header-collapse-condense ion-toolbar:first-of-type {
189
- /**
190
- * The toolbar that contains the collapsible
191
- * large title should not have safe area padding applied.
192
- */
193
- padding-top: 0px;
194
- z-index: 1;
195
- }
196
-
197
- /**
198
- * Large title toolbar should just use the content background
199
- * since it needs to blend in with the header above it.
200
- */
201
- .header-collapse-condense ion-toolbar {
202
- z-index: 0;
203
- }
204
-
205
319
  .header-collapse-condense ion-toolbar:last-of-type {
206
320
  --border-width: 0px;
207
- }
208
-
209
- .header-collapse-condense ion-toolbar ion-searchbar {
210
- padding-top: 0px;
211
- padding-bottom: 13px;
212
- }
213
-
214
- .header-collapse-main {
215
- --opacity-scale: 1;
216
- }
217
-
218
- .header-collapse-main ion-toolbar {
219
- --opacity-scale: inherit;
220
- }
221
-
222
- .header-collapse-main ion-toolbar.in-toolbar ion-title,
223
- .header-collapse-main ion-toolbar.in-toolbar ion-buttons {
224
- transition: all 0.2s ease-in-out;
225
- }
226
-
227
- /**
228
- * Large title toolbar should just use the content background
229
- * since it needs to blend in with the header above it.
230
- */
231
- .header-collapse-condense ion-toolbar,
232
- .header-collapse-condense-inactive.header-transitioning:not(.header-collapse-condense) ion-toolbar {
233
- --background: var(--ion-background-color, #fff);
234
- }
235
-
236
- /**
237
- * Override styles applied during the page transition to prevent
238
- * header flickering.
239
- */
240
- .header-collapse-condense-inactive.header-transitioning:not(.header-collapse-condense) ion-toolbar {
241
- --border-style: none;
242
- --opacity-scale: 1;
243
- }
244
-
245
- .header-collapse-condense-inactive:not(.header-collapse-condense) ion-toolbar.in-toolbar ion-title,
246
- .header-collapse-condense-inactive:not(.header-collapse-condense) ion-toolbar.in-toolbar ion-buttons.buttons-collapse {
247
- opacity: 0;
248
- pointer-events: none;
249
- }
250
-
251
- /**
252
- * There is a bug in Safari where changing
253
- * the opacity of an element in a scrollable container
254
- * while rubber-banding causes the scroll position
255
- * to jump to the top
256
- */
257
- .header-collapse-condense-inactive.header-collapse-condense ion-toolbar.in-toolbar ion-title,
258
- .header-collapse-condense-inactive.header-collapse-condense ion-toolbar.in-toolbar ion-buttons.buttons-collapse {
259
- visibility: hidden;
260
- }
261
-
262
- /**
263
- * The main header is only hidden once the collapsible large
264
- * title is configured. As a result, if the main header loads
265
- * before the collapsible large title is configured then the
266
- * main header will be visible briefly before being hidden
267
- * by the collapsible large title.
268
- *
269
- * The following selector ensures that any main header
270
- * on a page with a collapsible large title is hidden
271
- * before the collapsible large title is configured.
272
- * Once the collapsible large title is configured the main
273
- * header will have the ".header-collapse-main" class, and
274
- * this selector will no longer apply.
275
- *
276
- * The :has(...) part of the selector ensures a couple things:
277
- * 1. This will only apply within a page view since the content
278
- * must be a subsequent-sibling of the header (~ ion-content).
279
- * 2. This will only apply when that content has a collapse header (ion-header[collapse="condense"])
280
- *
281
- * We use opacity: 0 to avoid a layout shift.
282
- * We target both the attribute and the class in the event that the attribute
283
- * is not reflected on the host in some frameworks.
284
- *
285
- * Both headers should be scoped to iOS mode otherwise an MD app that uses an
286
- * iOS header may cause other MD headers to be unexpectedly hidden.
287
- */
288
- ion-header.header-ios:not(.header-collapse-main):has(~ ion-content ion-header.header-ios[collapse=condense],
289
- ~ ion-content ion-header.header-ios.header-collapse-condense) {
290
- opacity: 0;
291
321
  }
@@ -4,6 +4,8 @@
4
4
  import { Host, h, writeTask } from "@stencil/core";
5
5
  import { findIonContent, getScrollElement, printIonContentErrorMsg } from "../../utils/content/index";
6
6
  import { inheritAriaAttributes } from "../../utils/helpers";
7
+ import { printIonWarning } from "../../utils/logging/index";
8
+ import { createScrollHideController } from "../../utils/scroll-hide-controller";
7
9
  import { hostContext } from "../../utils/theme";
8
10
  import { config } from "../../global/config";
9
11
  import { getIonTheme } from "../../global/ionic-global";
@@ -15,6 +17,9 @@ import { cloneElement, createHeaderIndex, handleContentScroll, handleHeaderFade,
15
17
  export class Header {
16
18
  constructor() {
17
19
  this.inheritedAttributes = {};
20
+ this.scrollHideCtrlPromise = null;
21
+ this.hasWarnedCollapse = false;
22
+ this.fadeCondenseSetupId = 0;
18
23
  /**
19
24
  * If `true`, the header will have a line at the bottom.
20
25
  * TODO(ROU-10855): add support for this prop on ios/md themes
@@ -29,8 +34,29 @@ export class Header {
29
34
  * attribute needs to be set on the content.
30
35
  */
31
36
  this.translucent = false;
37
+ this.setupScrollEffectHide = async (contentEl) => {
38
+ const setupPromise = createScrollHideController(contentEl, {
39
+ el: this.el,
40
+ cssVar: '--internal-header-hide-height',
41
+ hiddenClass: 'header-scroll-hidden',
42
+ contentPartnerClass: 'content-header-hide-scroll-partner',
43
+ contentHiddenClass: 'content-header-hide-scroll-hidden',
44
+ });
45
+ this.scrollHideCtrlPromise = setupPromise;
46
+ const controller = await setupPromise;
47
+ if (this.scrollHideCtrlPromise === setupPromise) {
48
+ this.scrollHideCtrlPromise = null;
49
+ controller.init();
50
+ this.scrollHideCtrl = controller;
51
+ }
52
+ };
32
53
  this.setupFadeHeader = async (contentEl, condenseHeader) => {
33
- const scrollEl = (this.scrollEl = await getScrollElement(contentEl));
54
+ const setupId = ++this.fadeCondenseSetupId;
55
+ const scrollEl = await getScrollElement(contentEl);
56
+ if (this.fadeCondenseSetupId !== setupId) {
57
+ return;
58
+ }
59
+ this.scrollEl = scrollEl;
34
60
  /**
35
61
  * Handle fading of toolbars on scroll
36
62
  */
@@ -54,38 +80,63 @@ export class Header {
54
80
  this.destroyCollapsibleHeader();
55
81
  }
56
82
  async checkCollapsibleHeader() {
57
- const theme = getIonTheme(this);
58
- if (theme !== 'ios') {
83
+ const { scrollEffect, collapse } = this;
84
+ if (collapse !== undefined && scrollEffect === undefined && !this.hasWarnedCollapse) {
85
+ this.hasWarnedCollapse = true;
86
+ printIonWarning(`[ion-header] - The \`collapse\` property is deprecated. Use \`scrollEffect\` instead.\nExample: <ion-header scroll-effect="${collapse}">`, this.el);
87
+ }
88
+ const effect = scrollEffect !== null && scrollEffect !== void 0 ? scrollEffect : collapse;
89
+ // Skip teardown/rebuild if the effect hasn't changed.
90
+ // This prevents re-renders from destroying the scroll controller
91
+ // and resetting isHidden.
92
+ if (effect === this.activeEffect) {
59
93
  return;
60
94
  }
61
- const { collapse } = this;
62
- const hasCondense = collapse === 'condense';
63
- const hasFade = collapse === 'fade';
95
+ const hasHide = effect === 'hide';
96
+ const hasCondense = effect === 'condense';
97
+ const hasFade = effect === 'fade';
64
98
  this.destroyCollapsibleHeader();
65
99
  const appRootSelector = config.get('appRootSelector', 'ion-app');
66
- if (hasCondense) {
67
- const pageEl = this.el.closest(`${appRootSelector},ion-page,.ion-page,page-inner`);
68
- const contentEl = pageEl ? findIonContent(pageEl) : null;
100
+ const pageEl = this.el.closest(`${appRootSelector}, ion-page, .ion-page, page-inner`);
101
+ const contentEl = pageEl ? findIonContent(pageEl) : null;
102
+ if (hasHide && contentEl) {
103
+ this.activeEffect = effect;
104
+ await this.setupScrollEffectHide(contentEl);
105
+ return;
106
+ }
107
+ // condense/fade via the deprecated `collapse` prop are iOS-only.
108
+ // condense/fade via the new `scrollEffect` prop work in all themes.
109
+ const isModeRestricted = scrollEffect === undefined && getIonTheme(this) !== 'ios';
110
+ if (hasCondense && !isModeRestricted) {
69
111
  // Cloned elements are always needed in iOS transition
70
112
  writeTask(() => {
71
113
  const title = cloneElement('ion-title');
72
114
  title.size = 'large';
73
115
  cloneElement('ion-back-button');
74
116
  });
75
- await this.setupCondenseHeader(contentEl, pageEl);
117
+ const didSetup = await this.setupCondenseHeader(contentEl, pageEl);
118
+ if (didSetup) {
119
+ this.activeEffect = effect;
120
+ }
76
121
  }
77
- else if (hasFade) {
78
- const pageEl = this.el.closest(`${appRootSelector},ion-page,.ion-page,page-inner`);
79
- const contentEl = pageEl ? findIonContent(pageEl) : null;
122
+ else if (hasFade && !isModeRestricted) {
80
123
  if (!contentEl) {
81
124
  printIonContentErrorMsg(this.el);
82
125
  return;
83
126
  }
84
- const condenseHeader = contentEl.querySelector('ion-header[collapse="condense"]');
127
+ const condenseHeader = contentEl.querySelector('ion-header[collapse="condense"],ion-header[scroll-effect="condense"]');
128
+ this.activeEffect = effect;
85
129
  await this.setupFadeHeader(contentEl, condenseHeader);
86
130
  }
87
131
  }
88
132
  destroyCollapsibleHeader() {
133
+ this.activeEffect = undefined;
134
+ this.fadeCondenseSetupId++;
135
+ this.scrollHideCtrlPromise = null;
136
+ if (this.scrollHideCtrl) {
137
+ this.scrollHideCtrl.destroy();
138
+ this.scrollHideCtrl = undefined;
139
+ }
89
140
  if (this.intersectionObserver) {
90
141
  this.intersectionObserver.disconnect();
91
142
  this.intersectionObserver = undefined;
@@ -102,21 +153,40 @@ export class Header {
102
153
  async setupCondenseHeader(contentEl, pageEl) {
103
154
  if (!contentEl || !pageEl) {
104
155
  printIonContentErrorMsg(this.el);
105
- return;
156
+ return false;
106
157
  }
107
158
  if (typeof IntersectionObserver === 'undefined') {
108
- return;
159
+ return false;
160
+ }
161
+ const setupId = ++this.fadeCondenseSetupId;
162
+ const scrollEl = await getScrollElement(contentEl);
163
+ if (this.fadeCondenseSetupId !== setupId) {
164
+ return false;
165
+ }
166
+ this.scrollEl = scrollEl;
167
+ /**
168
+ * The condense effect requires an ion-title with size="large"
169
+ * in the condense header. Without it, there is nothing to
170
+ * collapse into the main header toolbar.
171
+ */
172
+ const hasLargeTitle = this.el.querySelector('ion-title[size="large"]') !== null;
173
+ if (!hasLargeTitle) {
174
+ printIonWarning('[ion-header] - The condense scroll effect requires an <ion-title size="large"> in the condense header.', this.el);
175
+ return false;
109
176
  }
110
- this.scrollEl = await getScrollElement(contentEl);
111
177
  const headers = pageEl.querySelectorAll('ion-header');
112
- this.collapsibleMainHeader = Array.from(headers).find((header) => header.collapse !== 'condense');
178
+ this.collapsibleMainHeader = Array.from(headers).find((header) => {
179
+ var _a;
180
+ const effect = (_a = header.scrollEffect) !== null && _a !== void 0 ? _a : header.collapse;
181
+ return effect !== 'condense';
182
+ });
113
183
  if (!this.collapsibleMainHeader) {
114
- return;
184
+ return false;
115
185
  }
116
186
  const mainHeaderIndex = createHeaderIndex(this.collapsibleMainHeader);
117
187
  const scrollHeaderIndex = createHeaderIndex(this.el);
118
188
  if (!mainHeaderIndex || !scrollHeaderIndex) {
119
- return;
189
+ return false;
120
190
  }
121
191
  setHeaderActive(mainHeaderIndex, false);
122
192
  setToolbarBackgroundOpacity(mainHeaderIndex.el, 0);
@@ -148,23 +218,35 @@ export class Header {
148
218
  this.collapsibleMainHeader.classList.add('header-collapse-main');
149
219
  }
150
220
  });
221
+ return true;
151
222
  }
152
223
  render() {
153
- const { translucent, inheritedAttributes, divider } = this;
224
+ const { translucent, inheritedAttributes, divider, scrollEffect, collapse } = this;
154
225
  const theme = getIonTheme(this);
155
- const collapse = this.collapse || 'none';
156
- const isCondensed = collapse === 'condense';
226
+ const effect = scrollEffect !== null && scrollEffect !== void 0 ? scrollEffect : collapse;
227
+ // condense/fade via the deprecated `collapse` prop are iOS-only.
228
+ const isModeRestricted = scrollEffect === undefined && theme !== 'ios';
229
+ const hasHide = effect === 'hide';
230
+ const hasCondense = effect === 'condense' && !isModeRestricted && this.el.querySelector('ion-title[size="large"]') !== null;
231
+ const hasFade = effect === 'fade' && !isModeRestricted;
232
+ // The condense header should be hidden when
233
+ // - deprecated collapse prop is used on non-iOS (mode restricted), or
234
+ // - scrollEffect="condense" is set but no ion-title[size="large"] is present
235
+ const isHiddenCondense = effect === 'condense' && !hasCondense;
157
236
  // banner role must be at top level, so remove role if inside a menu
158
- const roleType = getRoleType(hostContext('ion-menu', this.el), isCondensed, theme);
159
- return (h(Host, Object.assign({ key: '3395dedfd5165ba6e9f3ad1a25f0bb5b3678704a', role: roleType, class: {
237
+ const roleType = isHiddenCondense ? 'none' : getRoleType(hostContext('ion-menu', this.el));
238
+ return (h(Host, Object.assign({ key: '09f60ca014bb7b3a85d3c0a94e7989d5dbc43f46', role: roleType, class: {
160
239
  [theme]: true,
161
240
  // Used internally for styling
162
241
  [`header-${theme}`]: true,
163
242
  [`header-translucent`]: this.translucent,
164
- [`header-collapse-${collapse}`]: true,
243
+ ['header-collapse-condense']: hasCondense,
244
+ ['header-collapse-condense-hidden']: isHiddenCondense,
245
+ ['header-collapse-fade']: hasFade,
165
246
  [`header-translucent-${theme}`]: this.translucent,
166
247
  ['header-divider']: divider,
167
- } }, inheritedAttributes), theme !== 'md' && translucent && h("div", { key: 'cafeb88b6e73d64b264514ea46590fd3477b3052', class: "header-background" }), h("slot", { key: 'ad681aaf866d7e7a5e5e731c0b5d6f5cc9fe94d2' })));
248
+ 'header-scroll-effect-hide': hasHide,
249
+ } }, inheritedAttributes), theme !== 'md' && translucent && h("div", { key: 'fd5ff245ae0166e5e1d50936cacc98c90625db48', class: "header-background" }), h("slot", { key: '1baa31af87b9eb6406a21073ec65afa191dfbb3d' })));
168
250
  }
169
251
  static get is() { return "ion-header"; }
170
252
  static get originalStyleUrls() {
@@ -183,6 +265,32 @@ export class Header {
183
265
  }
184
266
  static get properties() {
185
267
  return {
268
+ "scrollEffect": {
269
+ "type": "string",
270
+ "mutable": false,
271
+ "complexType": {
272
+ "original": "HeaderScrollEffect",
273
+ "resolved": "\"condense\" | \"fade\" | \"hide\" | undefined",
274
+ "references": {
275
+ "HeaderScrollEffect": {
276
+ "location": "import",
277
+ "path": "./header-interface",
278
+ "id": "src/components/header/header-interface.ts::HeaderScrollEffect",
279
+ "referenceLocation": "HeaderScrollEffect"
280
+ }
281
+ }
282
+ },
283
+ "required": false,
284
+ "optional": true,
285
+ "docs": {
286
+ "tags": [],
287
+ "text": "Describes the scroll effect that will be applied to the header.\n`\"hide\"` slides the header out of view when scrolling down and back in\nwhen scrolling up.\n`\"condense\"` collapses the large title into the main toolbar on scroll.\n`\"fade\"` fades the toolbar background on scroll."
288
+ },
289
+ "getter": false,
290
+ "setter": false,
291
+ "reflect": true,
292
+ "attribute": "scroll-effect"
293
+ },
186
294
  "collapse": {
187
295
  "type": "string",
188
296
  "mutable": false,
@@ -194,7 +302,10 @@ export class Header {
194
302
  "required": false,
195
303
  "optional": true,
196
304
  "docs": {
197
- "tags": [],
305
+ "tags": [{
306
+ "name": "deprecated",
307
+ "text": "Use `scrollEffect` instead."
308
+ }],
198
309
  "text": "Describes the scroll effect that will be applied to the header.\nOnly applies when the theme is `\"ios\"`.\n\nTypically used for [Collapsible Large Titles](https://ionicframework.com/docs/api/title#collapsible-large-titles)"
199
310
  },
200
311
  "getter": false,