@rdlabo/ionic-theme-ios27 1.2.1-beta.pr275.shad339e7688db7 → 2.0.0-1

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 (248) hide show
  1. package/README.md +24 -280
  2. package/dist/css/components/ion-toolbar.css +1 -1
  3. package/dist/css/ionic-theme-ios27.css +1 -1
  4. package/dist/css/vertical-bars.css +1 -1
  5. package/dist/index.d.ts +3 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +3 -2
  8. package/dist/index.js.map +1 -1
  9. package/dist/layout/index.d.ts +18 -0
  10. package/dist/layout/index.d.ts.map +1 -0
  11. package/dist/layout/index.js +26 -0
  12. package/dist/layout/index.js.map +1 -0
  13. package/dist/segment/index.js +3 -3
  14. package/dist/segment/index.js.map +1 -1
  15. package/dist/sheets-of-glass/index.js +7 -7
  16. package/dist/sheets-of-glass/index.js.map +1 -1
  17. package/dist/tab-bar-searchable/dismiss-button.js +53 -3
  18. package/dist/tab-bar-searchable/dismiss-button.js.map +1 -1
  19. package/dist/tab-bar-searchable/index.js +18 -3
  20. package/dist/tab-bar-searchable/index.js.map +1 -1
  21. package/dist/transition/ios.transition.d.ts.map +1 -1
  22. package/dist/transition/ios.transition.js +7 -4
  23. package/dist/transition/ios.transition.js.map +1 -1
  24. package/dist/transition/native-ui.d.ts +6 -0
  25. package/dist/transition/native-ui.d.ts.map +1 -0
  26. package/dist/{native-integration/index.js → transition/native-ui.js} +16 -30
  27. package/dist/transition/native-ui.js.map +1 -0
  28. package/docs/adaptive-themes.md +161 -0
  29. package/docs/add-native-ui.md +53 -0
  30. package/docs/animation.md +19 -3
  31. package/docs/eslint.md +3 -1
  32. package/docs/features.md +9 -5
  33. package/docs/iphone-duo.md +62 -35
  34. package/docs/migration.md +17 -26
  35. package/docs/setup.md +92 -0
  36. package/docs/special-markup.md +41 -10
  37. package/docs/using-ion-item-group.md +2 -2
  38. package/docs/vertical-bars-layout.md +67 -0
  39. package/package.json +12 -42
  40. package/src/index.ts +3 -1
  41. package/src/layout/index.ts +29 -0
  42. package/src/segment/index.ts +3 -3
  43. package/src/sheets-of-glass/index.ts +7 -7
  44. package/src/styles/components/ion-toolbar.scss +1 -1
  45. package/src/styles/vertical-bars.scss +15 -18
  46. package/src/tab-bar-searchable/dismiss-button.ts +73 -4
  47. package/src/tab-bar-searchable/index.ts +20 -3
  48. package/src/transition/ios.transition.ts +7 -4
  49. package/src/{native-integration/index.ts → transition/native-ui.ts} +17 -46
  50. package/Package.swift +0 -21
  51. package/dist/_virtual/_rolldown/runtime.js +0 -13
  52. package/dist/native/components/index.d.ts +0 -19
  53. package/dist/native/components/index.d.ts.map +0 -1
  54. package/dist/native/components/index.js +0 -40
  55. package/dist/native/components/index.js.map +0 -1
  56. package/dist/native/components/ion-back-button.d.ts +0 -9
  57. package/dist/native/components/ion-back-button.d.ts.map +0 -1
  58. package/dist/native/components/ion-back-button.js +0 -20
  59. package/dist/native/components/ion-back-button.js.map +0 -1
  60. package/dist/native/components/ion-button.d.ts +0 -10
  61. package/dist/native/components/ion-button.d.ts.map +0 -1
  62. package/dist/native/components/ion-button.js +0 -23
  63. package/dist/native/components/ion-button.js.map +0 -1
  64. package/dist/native/components/ion-buttons.d.ts +0 -11
  65. package/dist/native/components/ion-buttons.d.ts.map +0 -1
  66. package/dist/native/components/ion-buttons.js +0 -30
  67. package/dist/native/components/ion-buttons.js.map +0 -1
  68. package/dist/native/components/ion-fab.d.ts +0 -10
  69. package/dist/native/components/ion-fab.d.ts.map +0 -1
  70. package/dist/native/components/ion-fab.js +0 -132
  71. package/dist/native/components/ion-fab.js.map +0 -1
  72. package/dist/native/components/ion-menu-button.d.ts +0 -13
  73. package/dist/native/components/ion-menu-button.d.ts.map +0 -1
  74. package/dist/native/components/ion-menu-button.js +0 -31
  75. package/dist/native/components/ion-menu-button.js.map +0 -1
  76. package/dist/native/components/ion-segment.d.ts +0 -11
  77. package/dist/native/components/ion-segment.d.ts.map +0 -1
  78. package/dist/native/components/ion-segment.js +0 -30
  79. package/dist/native/components/ion-segment.js.map +0 -1
  80. package/dist/native/components/ion-tab-bar.d.ts +0 -11
  81. package/dist/native/components/ion-tab-bar.d.ts.map +0 -1
  82. package/dist/native/components/ion-tab-bar.js +0 -50
  83. package/dist/native/components/ion-tab-bar.js.map +0 -1
  84. package/dist/native/components/searchable-tabs.d.ts +0 -20
  85. package/dist/native/components/searchable-tabs.d.ts.map +0 -1
  86. package/dist/native/components/searchable-tabs.js +0 -383
  87. package/dist/native/components/searchable-tabs.js.map +0 -1
  88. package/dist/native/definitions.d.ts +0 -191
  89. package/dist/native/definitions.d.ts.map +0 -1
  90. package/dist/native/definitions.js +0 -0
  91. package/dist/native/foldable/fold-state.d.ts +0 -5
  92. package/dist/native/foldable/fold-state.d.ts.map +0 -1
  93. package/dist/native/foldable/fold-state.js +0 -14
  94. package/dist/native/foldable/fold-state.js.map +0 -1
  95. package/dist/native/foldable/types.d.ts +0 -12
  96. package/dist/native/foldable/types.d.ts.map +0 -1
  97. package/dist/native/foldable/types.js +0 -0
  98. package/dist/native/index.d.ts +0 -11
  99. package/dist/native/index.d.ts.map +0 -1
  100. package/dist/native/index.js +0 -267
  101. package/dist/native/index.js.map +0 -1
  102. package/dist/native/overlays/content.d.ts +0 -4
  103. package/dist/native/overlays/content.d.ts.map +0 -1
  104. package/dist/native/overlays/content.js +0 -51
  105. package/dist/native/overlays/content.js.map +0 -1
  106. package/dist/native/overlays/controller.d.ts +0 -8
  107. package/dist/native/overlays/controller.d.ts.map +0 -1
  108. package/dist/native/overlays/controller.js +0 -285
  109. package/dist/native/overlays/controller.js.map +0 -1
  110. package/dist/native/overlays/dialog-animation.d.ts +0 -9
  111. package/dist/native/overlays/dialog-animation.d.ts.map +0 -1
  112. package/dist/native/overlays/dialog-animation.js +0 -53
  113. package/dist/native/overlays/dialog-animation.js.map +0 -1
  114. package/dist/native/overlays/dismiss-animation.d.ts +0 -4
  115. package/dist/native/overlays/dismiss-animation.d.ts.map +0 -1
  116. package/dist/native/overlays/dismiss-animation.js +0 -18
  117. package/dist/native/overlays/dismiss-animation.js.map +0 -1
  118. package/dist/native/overlays/focus.d.ts +0 -5
  119. package/dist/native/overlays/focus.d.ts.map +0 -1
  120. package/dist/native/overlays/focus.js +0 -59
  121. package/dist/native/overlays/focus.js.map +0 -1
  122. package/dist/native/overlays/popover.d.ts +0 -12
  123. package/dist/native/overlays/popover.d.ts.map +0 -1
  124. package/dist/native/overlays/popover.js +0 -110
  125. package/dist/native/overlays/popover.js.map +0 -1
  126. package/dist/native/overlays/styles.d.ts +0 -11
  127. package/dist/native/overlays/styles.d.ts.map +0 -1
  128. package/dist/native/overlays/styles.js +0 -167
  129. package/dist/native/overlays/styles.js.map +0 -1
  130. package/dist/native/prehide.d.ts +0 -7
  131. package/dist/native/prehide.d.ts.map +0 -1
  132. package/dist/native/prehide.js +0 -230
  133. package/dist/native/prehide.js.map +0 -1
  134. package/dist/native/runtime.d.ts +0 -7
  135. package/dist/native/runtime.d.ts.map +0 -1
  136. package/dist/native/runtime.js +0 -710
  137. package/dist/native/runtime.js.map +0 -1
  138. package/dist/native/shared/bridge.d.ts +0 -6
  139. package/dist/native/shared/bridge.d.ts.map +0 -1
  140. package/dist/native/shared/bridge.js +0 -18
  141. package/dist/native/shared/bridge.js.map +0 -1
  142. package/dist/native/shared/candidate.d.ts +0 -21
  143. package/dist/native/shared/candidate.d.ts.map +0 -1
  144. package/dist/native/shared/candidate.js +0 -98
  145. package/dist/native/shared/candidate.js.map +0 -1
  146. package/dist/native/shared/crossfade.d.ts +0 -12
  147. package/dist/native/shared/crossfade.d.ts.map +0 -1
  148. package/dist/native/shared/crossfade.js +0 -67
  149. package/dist/native/shared/crossfade.js.map +0 -1
  150. package/dist/native/shared/dom.d.ts +0 -46
  151. package/dist/native/shared/dom.d.ts.map +0 -1
  152. package/dist/native/shared/dom.js +0 -172
  153. package/dist/native/shared/dom.js.map +0 -1
  154. package/dist/native/shared/events.d.ts +0 -11
  155. package/dist/native/shared/events.d.ts.map +0 -1
  156. package/dist/native/shared/events.js +0 -13
  157. package/dist/native/shared/events.js.map +0 -1
  158. package/dist/native/shared/icons.d.ts +0 -8
  159. package/dist/native/shared/icons.d.ts.map +0 -1
  160. package/dist/native/shared/icons.js +0 -61
  161. package/dist/native/shared/icons.js.map +0 -1
  162. package/dist/native/shared/modal.d.ts +0 -10
  163. package/dist/native/shared/modal.d.ts.map +0 -1
  164. package/dist/native/shared/modal.js +0 -160
  165. package/dist/native/shared/modal.js.map +0 -1
  166. package/dist/native/shared/projection-id.d.ts +0 -4
  167. package/dist/native/shared/projection-id.d.ts.map +0 -1
  168. package/dist/native/shared/projection-id.js +0 -7
  169. package/dist/native/shared/projection-id.js.map +0 -1
  170. package/dist/native/shared/vertical-bars-geometry.d.ts +0 -10
  171. package/dist/native/shared/vertical-bars-geometry.d.ts.map +0 -1
  172. package/dist/native/shared/vertical-bars-geometry.js +0 -85
  173. package/dist/native/shared/vertical-bars-geometry.js.map +0 -1
  174. package/dist/native/vertical-bars-web-search.d.ts +0 -10
  175. package/dist/native/vertical-bars-web-search.d.ts.map +0 -1
  176. package/dist/native/vertical-bars-web-search.js +0 -90
  177. package/dist/native/vertical-bars-web-search.js.map +0 -1
  178. package/dist/native/vertical-bars-web.d.ts +0 -5
  179. package/dist/native/vertical-bars-web.d.ts.map +0 -1
  180. package/dist/native/vertical-bars-web.js +0 -411
  181. package/dist/native/vertical-bars-web.js.map +0 -1
  182. package/dist/native-integration/index.d.ts +0 -23
  183. package/dist/native-integration/index.d.ts.map +0 -1
  184. package/dist/native-integration/index.js.map +0 -1
  185. package/dist/native-integration/transition.d.ts +0 -5
  186. package/dist/native-integration/transition.d.ts.map +0 -1
  187. package/dist/native-integration/transition.js +0 -16
  188. package/dist/native-integration/transition.js.map +0 -1
  189. package/dist/vertical-bars.d.ts +0 -5
  190. package/dist/vertical-bars.js +0 -4
  191. package/docs/e2e-testing.md +0 -51
  192. package/docs/feedback.md +0 -65
  193. package/docs/iphone-duo-with-original-theme.md +0 -158
  194. package/docs/native-ui-shell.md +0 -325
  195. package/docs/vertical-bars.md +0 -300
  196. package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellButton.swift +0 -71
  197. package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellButtons.swift +0 -24
  198. package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellComponents.swift +0 -18
  199. package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellFab.swift +0 -80
  200. package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellSearchController.swift +0 -432
  201. package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellSegment.swift +0 -91
  202. package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellTabBar.swift +0 -218
  203. package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellVerticalBars.swift +0 -565
  204. package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellVerticalSearch.swift +0 -118
  205. package/ios/Sources/IonicNativeUIShellPlugin/IonicNativeUIShellPlugin.swift +0 -502
  206. package/ios/Sources/IonicNativeUIShellPlugin/Overlays/ShellOverlayController.swift +0 -119
  207. package/ios/Sources/IonicNativeUIShellPlugin/Overlays/ShellOverlayHost.swift +0 -75
  208. package/ios/Sources/IonicNativeUIShellPlugin/Shared/ShellCrossfade.swift +0 -35
  209. package/ios/Sources/IonicNativeUIShellPlugin/Shared/ShellHost.swift +0 -8
  210. package/ios/Sources/IonicNativeUIShellPlugin/Shared/ShellRendering.swift +0 -27
  211. package/ios/Sources/IonicNativeUIShellPlugin/Shared/ShellSnapshot.swift +0 -135
  212. package/ios/Sources/IonicNativeUIShellPlugin/Shared/ShellVerticalBarsGeometry.swift +0 -52
  213. package/ios/Tests/IonicNativeUIShellPluginTests/ShellSnapshotTests.swift +0 -788
  214. package/src/native/components/index.ts +0 -53
  215. package/src/native/components/ion-back-button.ts +0 -19
  216. package/src/native/components/ion-button.ts +0 -24
  217. package/src/native/components/ion-buttons.ts +0 -38
  218. package/src/native/components/ion-fab.ts +0 -151
  219. package/src/native/components/ion-menu-button.ts +0 -24
  220. package/src/native/components/ion-segment.ts +0 -27
  221. package/src/native/components/ion-tab-bar.ts +0 -50
  222. package/src/native/components/searchable-tabs.ts +0 -459
  223. package/src/native/definitions.ts +0 -218
  224. package/src/native/foldable/fold-state.ts +0 -9
  225. package/src/native/foldable/types.ts +0 -4
  226. package/src/native/index.ts +0 -315
  227. package/src/native/overlays/content.ts +0 -51
  228. package/src/native/overlays/controller.ts +0 -349
  229. package/src/native/overlays/dialog-animation.ts +0 -53
  230. package/src/native/overlays/dismiss-animation.ts +0 -15
  231. package/src/native/overlays/focus.ts +0 -64
  232. package/src/native/overlays/popover.ts +0 -120
  233. package/src/native/overlays/styles.ts +0 -181
  234. package/src/native/prehide.ts +0 -265
  235. package/src/native/runtime.ts +0 -885
  236. package/src/native/shared/bridge.ts +0 -18
  237. package/src/native/shared/candidate.ts +0 -150
  238. package/src/native/shared/crossfade.ts +0 -67
  239. package/src/native/shared/dom.ts +0 -286
  240. package/src/native/shared/events.ts +0 -8
  241. package/src/native/shared/icons.ts +0 -57
  242. package/src/native/shared/modal.ts +0 -157
  243. package/src/native/shared/projection-id.ts +0 -2
  244. package/src/native/shared/vertical-bars-geometry.ts +0 -80
  245. package/src/native/vertical-bars-web-search.ts +0 -86
  246. package/src/native/vertical-bars-web.ts +0 -485
  247. package/src/native-integration/transition.ts +0 -15
  248. package/src/vertical-bars.ts +0 -11
@@ -1,85 +0,0 @@
1
- //#region src/native/shared/vertical-bars-geometry.ts
2
- const measurements = /* @__PURE__ */ new WeakMap();
3
- const viewport = (element) => {
4
- const win = element.ownerDocument.defaultView;
5
- const classes = element.closest("ion-app")?.classList;
6
- return `${win.innerWidth}:${win.innerHeight}:${classes?.contains("ios-theme-vertical-bars")}:${classes?.contains("ios-theme-vertical-bars-left")}`;
7
- };
8
- const validVerticalBarFrame = (frame) => [
9
- frame.x,
10
- frame.y,
11
- frame.width,
12
- frame.height
13
- ].every(Number.isFinite) && frame.width > 0 && frame.height > 0;
14
- const forgetVerticalBarFrame = (element) => measurements.delete(element);
15
- const rememberVerticalBarFrame = (element, frame) => {
16
- if (validVerticalBarFrame(frame)) measurements.set(element, {
17
- frame,
18
- viewport: viewport(element)
19
- });
20
- };
21
- const verticalBarFrame = (element) => {
22
- const saved = measurements.get(element);
23
- return saved?.viewport === viewport(element) ? saved.frame : void 0;
24
- };
25
- /** Convert the native viewport rectangle into the clone's positioning container. */
26
- const alignVerticalBarClone = (clone, source, parent) => {
27
- const frame = verticalBarFrame(source);
28
- if (!frame) return;
29
- const origin = parent.getBoundingClientRect();
30
- Object.assign(clone.style, {
31
- position: "absolute",
32
- left: `${frame.x - origin.left}px`,
33
- top: `${frame.y - origin.top}px`,
34
- right: "auto",
35
- bottom: "auto",
36
- width: `${frame.width}px`,
37
- height: `${frame.height}px`,
38
- minWidth: `${frame.width}px`,
39
- maxWidth: `${frame.width}px`,
40
- minHeight: `${frame.height}px`,
41
- maxHeight: `${frame.height}px`,
42
- margin: "0",
43
- boxSizing: "border-box"
44
- });
45
- };
46
- const alignVerticalTabBar = (tabBar, frame, items) => {
47
- const doc = tabBar.ownerDocument;
48
- const style = doc.createElement("style");
49
- const token = `rail-${Math.random().toString(36).slice(2)}`;
50
- const selector = `[data-native-rail-geometry="${token}"]`;
51
- const origin = tabBar.offsetParent?.getBoundingClientRect() ?? {
52
- left: 0,
53
- top: 0
54
- };
55
- tabBar.setAttribute("data-native-rail-geometry", token);
56
- const box = (rect, x, y) => `position:absolute!important;left:${rect.x - x}px!important;top:${rect.y - y}px!important;right:auto!important;bottom:auto!important;width:${rect.width}px!important;min-width:${rect.width}px!important;max-width:${rect.width}px!important;height:${rect.height}px!important;min-height:${rect.height}px!important;max-height:${rect.height}px!important;margin:0!important;padding:0!important;box-sizing:border-box!important;`;
57
- style.textContent = `${selector}{${box(frame, origin.left, origin.top)}}` + [...items].map(([element, rect]) => {
58
- const index = Array.from(tabBar.children).indexOf(element) + 1;
59
- return `${selector}>:nth-child(${index}){${box(rect, frame.x, frame.y)}}${selector}>:nth-child(${index})::part(native){min-height:0!important}`;
60
- }).join("");
61
- doc.head.append(style);
62
- const win = doc.defaultView;
63
- const measuredViewport = viewport(tabBar);
64
- const stop = () => {
65
- observer.disconnect();
66
- win.removeEventListener("resize", stop);
67
- style.remove();
68
- if (tabBar.getAttribute("data-native-rail-geometry") === token) tabBar.removeAttribute("data-native-rail-geometry");
69
- };
70
- const observer = new MutationObserver((records) => {
71
- if (viewport(tabBar) !== measuredViewport || records.some((record) => record.type === "childList")) stop();
72
- });
73
- observer.observe(tabBar, { childList: true });
74
- const app = tabBar.closest("ion-app");
75
- if (app) observer.observe(app, {
76
- attributes: true,
77
- attributeFilter: ["class"]
78
- });
79
- win.addEventListener("resize", stop);
80
- return stop;
81
- };
82
- //#endregion
83
- export { alignVerticalBarClone, alignVerticalTabBar, forgetVerticalBarFrame, rememberVerticalBarFrame, validVerticalBarFrame, verticalBarFrame };
84
-
85
- //# sourceMappingURL=vertical-bars-geometry.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"vertical-bars-geometry.js","names":[],"sources":["../../../src/native/shared/vertical-bars-geometry.ts"],"sourcesContent":["import type { Frame } from '../definitions';\n\nconst measurements = new WeakMap<Element, { frame: Frame; viewport: string }>();\nconst viewport = (element: Element) => {\n const win = element.ownerDocument.defaultView!;\n const classes = element.closest('ion-app')?.classList;\n return `${win.innerWidth}:${win.innerHeight}:${classes?.contains('ios-theme-vertical-bars')}:${classes?.contains('ios-theme-vertical-bars-left')}`;\n};\n\nexport const validVerticalBarFrame = (frame: Frame) =>\n [frame.x, frame.y, frame.width, frame.height].every(Number.isFinite) && frame.width > 0 && frame.height > 0;\n\nexport const forgetVerticalBarFrame = (element: Element) => measurements.delete(element);\n\nexport const rememberVerticalBarFrame = (element: Element, frame: Frame) => {\n if (validVerticalBarFrame(frame)) measurements.set(element, { frame, viewport: viewport(element) });\n};\n\nexport const verticalBarFrame = (element: Element): Frame | undefined => {\n const saved = measurements.get(element);\n return saved?.viewport === viewport(element) ? saved.frame : undefined;\n};\n\n/** Convert the native viewport rectangle into the clone's positioning container. */\nexport const alignVerticalBarClone = (clone: HTMLElement, source: Element, parent: HTMLElement) => {\n const frame = verticalBarFrame(source);\n if (!frame) return;\n const origin = parent.getBoundingClientRect();\n Object.assign(clone.style, {\n position: 'absolute',\n left: `${frame.x - origin.left}px`,\n top: `${frame.y - origin.top}px`,\n right: 'auto',\n bottom: 'auto',\n width: `${frame.width}px`,\n height: `${frame.height}px`,\n minWidth: `${frame.width}px`,\n maxWidth: `${frame.width}px`,\n minHeight: `${frame.height}px`,\n maxHeight: `${frame.height}px`,\n margin: '0',\n boxSizing: 'border-box',\n });\n};\n\nexport const alignVerticalTabBar = (tabBar: HTMLElement, frame: Frame, items: Map<HTMLElement, Frame>): (() => void) => {\n const doc = tabBar.ownerDocument;\n const style = doc.createElement('style');\n const token = `rail-${Math.random().toString(36).slice(2)}`;\n const selector = `[data-native-rail-geometry=\"${token}\"]`;\n const origin = (tabBar.offsetParent as HTMLElement | null)?.getBoundingClientRect() ?? { left: 0, top: 0 };\n tabBar.setAttribute('data-native-rail-geometry', token);\n const box = (rect: Frame, x: number, y: number) =>\n `position:absolute!important;left:${rect.x - x}px!important;top:${rect.y - y}px!important;right:auto!important;bottom:auto!important;width:${rect.width}px!important;min-width:${rect.width}px!important;max-width:${rect.width}px!important;height:${rect.height}px!important;min-height:${rect.height}px!important;max-height:${rect.height}px!important;margin:0!important;padding:0!important;box-sizing:border-box!important;`;\n style.textContent =\n `${selector}{${box(frame, origin.left, origin.top)}}` +\n [...items]\n .map(([element, rect]) => {\n const index = Array.from(tabBar.children).indexOf(element) + 1;\n return `${selector}>:nth-child(${index}){${box(rect, frame.x, frame.y)}}${selector}>:nth-child(${index})::part(native){min-height:0!important}`;\n })\n .join('');\n doc.head.append(style);\n const win = doc.defaultView!;\n const measuredViewport = viewport(tabBar);\n const stop = () => {\n observer.disconnect();\n win.removeEventListener('resize', stop);\n style.remove();\n if (tabBar.getAttribute('data-native-rail-geometry') === token) tabBar.removeAttribute('data-native-rail-geometry');\n };\n const observer = new MutationObserver((records) => {\n if (viewport(tabBar) !== measuredViewport || records.some((record) => record.type === 'childList')) stop();\n });\n observer.observe(tabBar, { childList: true });\n const app = tabBar.closest('ion-app');\n if (app) observer.observe(app, { attributes: true, attributeFilter: ['class'] });\n win.addEventListener('resize', stop);\n return stop;\n};\n"],"mappings":"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"}
@@ -1,10 +0,0 @@
1
- //#region src/native/vertical-bars-web-search.d.ts
2
- export declare const searchProjectionClass = "ios-theme-vertical-bars-search-projection";
3
- export declare const createVerticalBarsWebSearch: (doc: Document, eligible: (element: HTMLElement) => boolean, refresh: () => void) => {
4
- restore: (retire?: (surface: HTMLElement) => void) => void;
5
- readonly surface: HTMLIonFabElement | undefined;
6
- readonly source: HTMLElement | undefined;
7
- update(root: HTMLElement): void;
8
- };
9
- //#endregion
10
- //# sourceMappingURL=vertical-bars-web-search.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"vertical-bars-web-search.d.ts","names":[],"sources":["../../src/native/vertical-bars-web-search.ts"],"mappings":";qBAGa;qBAGA,8BAA+B,KAAK,UAAU,WAAW,SAAS,yBAAyB;EAM5E,UAAA,UAAC,SAAS;;;EAuBrB,OAAA,MAAA"}
@@ -1,90 +0,0 @@
1
- import { getNativeSearchBindings } from "../native-integration/index.js";
2
- import { activateProjectedElement, marker, unprojected } from "./shared/dom.js";
3
- //#region src/native/vertical-bars-web-search.ts
4
- const searchProjectionClass = "ios-theme-vertical-bars-search-projection";
5
- /** Web counterpart of the system search button above the vertical tabs, or at the rail bottom without visible tabs. */
6
- const createVerticalBarsWebSearch = (doc, eligible, refresh) => {
7
- let binding;
8
- let projection;
9
- let container;
10
- const iconObserver = new MutationObserver(refresh);
11
- let previousAriaHidden = null;
12
- const restore = (retire) => {
13
- iconObserver.disconnect();
14
- if (container) {
15
- if (retire) retire(container);
16
- else container.remove();
17
- }
18
- container = void 0;
19
- projection = void 0;
20
- if (binding) {
21
- binding.trigger.removeAttribute(marker);
22
- if (previousAriaHidden === null) binding.trigger.removeAttribute("aria-hidden");
23
- else binding.trigger.setAttribute("aria-hidden", previousAriaHidden);
24
- }
25
- binding = void 0;
26
- };
27
- return {
28
- restore,
29
- get surface() {
30
- return container;
31
- },
32
- get source() {
33
- return binding?.trigger;
34
- },
35
- update(root) {
36
- const next = unprojected(binding ? [binding.trigger] : [], () => getNativeSearchBindings(doc).find(({ trigger, footer }) => eligible(trigger) && eligible(footer)));
37
- if (next !== binding || container?.parentElement !== root) restore();
38
- if (!next) return;
39
- if (!projection) {
40
- binding = next;
41
- previousAriaHidden = next.trigger.getAttribute("aria-hidden");
42
- projection = next.trigger.cloneNode(true);
43
- for (const name of [
44
- "id",
45
- "slot",
46
- marker,
47
- "aria-hidden",
48
- "style"
49
- ]) projection.removeAttribute(name);
50
- container = doc.createElement("ion-fab");
51
- container.setAttribute("mode", next.trigger.mode ?? "ios");
52
- container.classList.add(searchProjectionClass, "ion-cloned-element");
53
- projection.addEventListener("click", (event) => {
54
- event.preventDefault();
55
- event.stopImmediatePropagation();
56
- activateProjectedElement(next.trigger);
57
- }, { capture: true });
58
- container.append(projection);
59
- root.append(container);
60
- next.trigger.setAttribute(marker, "");
61
- next.trigger.setAttribute("aria-hidden", "true");
62
- }
63
- projection.setAttribute("aria-label", next.trigger.getAttribute("aria-label") ?? next.footer.querySelector("ion-searchbar")?.getAttribute("aria-label") ?? "Search");
64
- const sourceIcon = next.trigger.querySelector("ion-icon");
65
- const icon = projection.querySelector("ion-icon");
66
- if (sourceIcon?.shadowRoot) iconObserver.observe(sourceIcon.shadowRoot, {
67
- subtree: true,
68
- childList: true,
69
- attributes: true
70
- });
71
- if (sourceIcon && icon) {
72
- icon.icon = sourceIcon.icon;
73
- icon.name = sourceIcon.name;
74
- icon.src = sourceIcon.src;
75
- }
76
- container.hidden = next.trigger.style.pointerEvents === "none";
77
- projection.disabled = next.trigger.disabled;
78
- const bounds = next.tabBar.getBoundingClientRect();
79
- const tabs = bounds.width > 0 && bounds.height > 0 && getComputedStyle(next.tabBar).visibility === "visible" ? bounds : void 0;
80
- container.style.left = tabs ? `${tabs.left + (tabs.width - 46) / 2}px` : "";
81
- container.style.top = tabs ? `${tabs.top - 56}px` : "";
82
- container.style.right = tabs ? "auto" : "";
83
- container.style.bottom = tabs ? "auto" : "";
84
- }
85
- };
86
- };
87
- //#endregion
88
- export { createVerticalBarsWebSearch, searchProjectionClass };
89
-
90
- //# sourceMappingURL=vertical-bars-web-search.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"vertical-bars-web-search.js","names":[],"sources":["../../src/native/vertical-bars-web-search.ts"],"sourcesContent":["import { getNativeSearchBindings, type NativeSearchBinding } from '../native-integration';\nimport { activateProjectedElement, marker, unprojected } from './shared/dom';\n\nexport const searchProjectionClass = 'ios-theme-vertical-bars-search-projection';\n\n/** Web counterpart of the system search button above the vertical tabs, or at the rail bottom without visible tabs. */\nexport const createVerticalBarsWebSearch = (doc: Document, eligible: (element: HTMLElement) => boolean, refresh: () => void) => {\n let binding: NativeSearchBinding | undefined;\n let projection: HTMLIonFabButtonElement | undefined;\n let container: HTMLIonFabElement | undefined;\n const iconObserver = new MutationObserver(refresh);\n let previousAriaHidden: string | null = null;\n const restore = (retire?: (surface: HTMLElement) => void) => {\n iconObserver.disconnect();\n if (container) {\n if (retire) retire(container);\n else container.remove();\n }\n container = undefined;\n projection = undefined;\n if (binding) {\n binding.trigger.removeAttribute(marker);\n if (previousAriaHidden === null) binding.trigger.removeAttribute('aria-hidden');\n else binding.trigger.setAttribute('aria-hidden', previousAriaHidden);\n }\n binding = undefined;\n };\n return {\n restore,\n get surface() {\n return container;\n },\n get source() {\n return binding?.trigger;\n },\n update(root: HTMLElement) {\n const next = unprojected(binding ? [binding.trigger] : [], () =>\n getNativeSearchBindings(doc).find(({ trigger, footer }) => eligible(trigger) && eligible(footer)),\n );\n if (next !== binding || container?.parentElement !== root) restore();\n if (!next) return;\n if (!projection) {\n binding = next;\n previousAriaHidden = next.trigger.getAttribute('aria-hidden');\n projection = next.trigger.cloneNode(true) as HTMLIonFabButtonElement;\n for (const name of ['id', 'slot', marker, 'aria-hidden', 'style']) projection.removeAttribute(name);\n container = doc.createElement('ion-fab');\n container.setAttribute('mode', (next.trigger as HTMLIonFabButtonElement).mode ?? 'ios');\n container.classList.add(searchProjectionClass, 'ion-cloned-element');\n projection.addEventListener(\n 'click',\n (event) => {\n event.preventDefault();\n event.stopImmediatePropagation();\n activateProjectedElement(next.trigger);\n },\n { capture: true },\n );\n container.append(projection);\n root.append(container);\n next.trigger.setAttribute(marker, '');\n next.trigger.setAttribute('aria-hidden', 'true');\n }\n projection.setAttribute(\n 'aria-label',\n next.trigger.getAttribute('aria-label') ?? next.footer.querySelector('ion-searchbar')?.getAttribute('aria-label') ?? 'Search',\n );\n const sourceIcon = next.trigger.querySelector('ion-icon');\n const icon = projection.querySelector('ion-icon');\n if (sourceIcon?.shadowRoot) iconObserver.observe(sourceIcon.shadowRoot, { subtree: true, childList: true, attributes: true });\n if (sourceIcon && icon) {\n icon.icon = sourceIcon.icon;\n icon.name = sourceIcon.name;\n icon.src = sourceIcon.src;\n }\n container!.hidden = next.trigger.style.pointerEvents === 'none';\n projection.disabled = (next.trigger as HTMLIonFabButtonElement).disabled;\n const bounds = next.tabBar.getBoundingClientRect();\n const tabs = bounds.width > 0 && bounds.height > 0 && getComputedStyle(next.tabBar).visibility === 'visible' ? bounds : undefined;\n container!.style.left = tabs ? `${tabs.left + (tabs.width - 46) / 2}px` : '';\n container!.style.top = tabs ? `${tabs.top - 56}px` : '';\n container!.style.right = tabs ? 'auto' : '';\n container!.style.bottom = tabs ? 'auto' : '';\n },\n };\n};\n"],"mappings":";;;AAGA,MAAa,wBAAwB;;AAGrC,MAAa,+BAA+B,KAAe,UAA6C,YAAwB;CAC9H,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,MAAM,eAAe,IAAI,iBAAiB,OAAO;CACjD,IAAI,qBAAoC;CACxC,MAAM,WAAW,WAA4C;EAC3D,aAAa,WAAW;EACxB,IAAI,WAAW;GACb,IAAI,QAAQ,OAAO,SAAS;QACvB,UAAU,OAAO;EACxB;EACA,YAAY,KAAA;EACZ,aAAa,KAAA;EACb,IAAI,SAAS;GACX,QAAQ,QAAQ,gBAAgB,MAAM;GACtC,IAAI,uBAAuB,MAAM,QAAQ,QAAQ,gBAAgB,aAAa;QACzE,QAAQ,QAAQ,aAAa,eAAe,kBAAkB;EACrE;EACA,UAAU,KAAA;CACZ;CACA,OAAO;EACL;EACA,IAAI,UAAU;GACZ,OAAO;EACT;EACA,IAAI,SAAS;GACX,OAAO,SAAS;EAClB;EACA,OAAO,MAAmB;GACxB,MAAM,OAAO,YAAY,UAAU,CAAC,QAAQ,OAAO,IAAI,CAAC,SACtD,wBAAwB,GAAG,CAAC,CAAC,MAAM,EAAE,SAAS,aAAa,SAAS,OAAO,KAAK,SAAS,MAAM,CAAC,CAClG;GACA,IAAI,SAAS,WAAW,WAAW,kBAAkB,MAAM,QAAQ;GACnE,IAAI,CAAC,MAAM;GACX,IAAI,CAAC,YAAY;IACf,UAAU;IACV,qBAAqB,KAAK,QAAQ,aAAa,aAAa;IAC5D,aAAa,KAAK,QAAQ,UAAU,IAAI;IACxC,KAAK,MAAM,QAAQ;KAAC;KAAM;KAAQ;KAAQ;KAAe;IAAO,GAAG,WAAW,gBAAgB,IAAI;IAClG,YAAY,IAAI,cAAc,SAAS;IACvC,UAAU,aAAa,QAAS,KAAK,QAAoC,QAAQ,KAAK;IACtF,UAAU,UAAU,IAAI,uBAAuB,oBAAoB;IACnE,WAAW,iBACT,UACC,UAAU;KACT,MAAM,eAAe;KACrB,MAAM,yBAAyB;KAC/B,yBAAyB,KAAK,OAAO;IACvC,GACA,EAAE,SAAS,KAAK,CAClB;IACA,UAAU,OAAO,UAAU;IAC3B,KAAK,OAAO,SAAS;IACrB,KAAK,QAAQ,aAAa,QAAQ,EAAE;IACpC,KAAK,QAAQ,aAAa,eAAe,MAAM;GACjD;GACA,WAAW,aACT,cACA,KAAK,QAAQ,aAAa,YAAY,KAAK,KAAK,OAAO,cAAc,eAAe,CAAC,EAAE,aAAa,YAAY,KAAK,QACvH;GACA,MAAM,aAAa,KAAK,QAAQ,cAAc,UAAU;GACxD,MAAM,OAAO,WAAW,cAAc,UAAU;GAChD,IAAI,YAAY,YAAY,aAAa,QAAQ,WAAW,YAAY;IAAE,SAAS;IAAM,WAAW;IAAM,YAAY;GAAK,CAAC;GAC5H,IAAI,cAAc,MAAM;IACtB,KAAK,OAAO,WAAW;IACvB,KAAK,OAAO,WAAW;IACvB,KAAK,MAAM,WAAW;GACxB;GACA,UAAW,SAAS,KAAK,QAAQ,MAAM,kBAAkB;GACzD,WAAW,WAAY,KAAK,QAAoC;GAChE,MAAM,SAAS,KAAK,OAAO,sBAAsB;GACjD,MAAM,OAAO,OAAO,QAAQ,KAAK,OAAO,SAAS,KAAK,iBAAiB,KAAK,MAAM,CAAC,CAAC,eAAe,YAAY,SAAS,KAAA;GACxH,UAAW,MAAM,OAAO,OAAO,GAAG,KAAK,QAAQ,KAAK,QAAQ,MAAM,EAAE,MAAM;GAC1E,UAAW,MAAM,MAAM,OAAO,GAAG,KAAK,MAAM,GAAG,MAAM;GACrD,UAAW,MAAM,QAAQ,OAAO,SAAS;GACzC,UAAW,MAAM,SAAS,OAAO,SAAS;EAC5C;CACF;AACF"}
@@ -1,5 +0,0 @@
1
- import { NativeUIShellHandle, NativeUIShellOptions } from "./definitions.js";
2
- //#region src/native/vertical-bars-web.d.ts
3
- export declare const createVerticalBarsWebProjection: (doc: Document, options: NativeUIShellOptions, enabled?: () => boolean) => NativeUIShellHandle;
4
- //#endregion
5
- //# sourceMappingURL=vertical-bars-web.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"vertical-bars-web.d.ts","names":[],"sources":["../../src/native/vertical-bars-web.ts"],"mappings":";;qBA4Ca,kCACX,KAAK,UACL,SAAS,sBACT,4BACC"}
@@ -1,411 +0,0 @@
1
- import { VERTICAL_BARS_TRANSITION_CANCELED } from "../native-integration/index.js";
2
- import { createCrossfade } from "./shared/crossfade.js";
3
- import { inVerticalBarsSurface, topModal } from "./shared/modal.js";
4
- import { activateProjectedElement, createVerticalBarsPageState, isExcluded, isShellDisabled, isVerticalBarsToolbarGroup, marker, preferredVerticalBarsBack, prehiddenClass, prehideOnlyMutation, syncToolbarText, unprojected, verticalBarsActionCandidate, verticalBarsBackCandidate, verticalBarsEnteringPage, verticalBarsOwned, verticalBarsToolbarActions, withoutPrehide } from "./shared/dom.js";
5
- import { alignVerticalBarClone, verticalBarFrame } from "./shared/vertical-bars-geometry.js";
6
- import { createVerticalBarsWebSearch, searchProjectionClass } from "./vertical-bars-web-search.js";
7
- //#region src/native/vertical-bars-web.ts
8
- const backProjectionClass = "ios-theme-vertical-bars-back-button-projection";
9
- const toolbarProjectionClass = "ios-theme-vertical-bars-toolbar-projection";
10
- const readyClass = "ios-theme-vertical-bars-toolbar-ready";
11
- const toolbarControlSize = 46;
12
- const toolbarControlGap = 10;
13
- const createVerticalBarsWebProjection = (doc, options, enabled = () => true) => {
14
- const win = doc.defaultView;
15
- const crossfade = createCrossfade(win);
16
- let incomingInstant;
17
- const toolbarEnabled = options.controls === void 0 || options.controls.toolbar === true;
18
- let root;
19
- let backSource;
20
- let backProjection;
21
- let previousBackAriaHidden = null;
22
- let toolbarProjections = [];
23
- let suspended = 0;
24
- let stopped = false;
25
- let frame = 0;
26
- let updates = 0;
27
- let observingVerticalBars = false;
28
- const verticalBarsPages = createVerticalBarsPageState();
29
- let sourceObserver;
30
- let waiters = [];
31
- const listeners = new AbortController();
32
- const verticalBarsRoot = () => doc.querySelector("ion-app.ios-theme-vertical-bars");
33
- const projectedSources = () => [
34
- backSource,
35
- search.source,
36
- ...toolbarProjections.flatMap(({ actions }) => actions.map(({ source }) => source))
37
- ].filter((source) => !!source);
38
- const isRendered = (element) => withoutPrehide(element, () => {
39
- const style = getComputedStyle(element);
40
- const rect = element.getBoundingClientRect();
41
- return element.isConnected && style.display !== "none" && style.visibility === "visible" && rect.width > 0 && rect.height > 0;
42
- });
43
- const search = createVerticalBarsWebSearch(doc, (element) => (options.controls === void 0 || options.controls.tabs === true) && !!verticalBarsRoot()?.contains(element) && inVerticalBarsSurface(element) && !isExcluded(element, verticalBarsEnteringPage(element)) && !isShellDisabled(element) && !verticalBarsPages.isDeparted(element) && isRendered(element), () => {
44
- schedule();
45
- });
46
- const inEligibleToolbar = (element) => !!verticalBarsRoot()?.contains(element) && inVerticalBarsSurface(element) && verticalBarsActionCandidate(element) && !isExcluded(element, verticalBarsEnteringPage(element)) && !verticalBarsPages.isDeparted(element);
47
- const isEligibleBack = (element) => !!verticalBarsRoot()?.contains(element) && inVerticalBarsSurface(element) && verticalBarsOwned(element) && verticalBarsBackCandidate(element) && !isExcluded(element, verticalBarsEnteringPage(element)) && !verticalBarsPages.isDeparted(element) && unprojected(projectedSources(), () => isRendered(element));
48
- const pageOrder = (element) => Array.from(doc.querySelectorAll(".ion-page")).indexOf(element.closest(".ion-page"));
49
- const findBack = () => {
50
- const candidates = Array.from(doc.querySelectorAll(`ion-back-button:not(.${backProjectionClass})`)).filter(isEligibleBack);
51
- return preferredVerticalBarsBack(candidates, doc);
52
- };
53
- const findToolbarGroups = () => {
54
- const candidates = Array.from(doc.querySelectorAll(`ion-buttons:not(.${toolbarProjectionClass})`)).flatMap((group) => {
55
- const actions = verticalBarsToolbarActions(group).filter((action) => unprojected(projectedSources(), () => isRendered(action)));
56
- if (!actions.length) return [];
57
- if (!isVerticalBarsToolbarGroup(group)) return actions.filter(inEligibleToolbar).map((action) => ({
58
- group,
59
- actions: [action]
60
- }));
61
- return inEligibleToolbar(group) && unprojected(projectedSources(), () => isRendered(group)) ? [{
62
- group,
63
- actions
64
- }] : [];
65
- });
66
- const highestPage = Math.max(...candidates.map(({ group }) => pageOrder(group)));
67
- return candidates.filter(({ group }) => pageOrder(group) === highestPage);
68
- };
69
- const isCurrentToolbarAction = (source) => findToolbarGroups().some(({ actions }) => actions.includes(source));
70
- const restore = (retire) => {
71
- search.restore(retire);
72
- if (backProjection) {
73
- if (retire) retire(backProjection);
74
- else backProjection.remove();
75
- }
76
- backProjection = void 0;
77
- if (backSource) {
78
- backSource.removeAttribute(marker);
79
- if (previousBackAriaHidden === null) backSource.removeAttribute("aria-hidden");
80
- else backSource.setAttribute("aria-hidden", previousBackAriaHidden);
81
- backSource.dispatchEvent(new CustomEvent("nativeUIShellChange"));
82
- }
83
- backSource = void 0;
84
- previousBackAriaHidden = null;
85
- for (const { projection, actions } of toolbarProjections) {
86
- if (retire) retire(projection);
87
- else projection.remove();
88
- for (const { source, previousAriaHidden } of actions) {
89
- source.removeAttribute(marker);
90
- if (previousAriaHidden === null) source.removeAttribute("aria-hidden");
91
- else source.setAttribute("aria-hidden", previousAriaHidden);
92
- source.dispatchEvent(new CustomEvent("nativeUIShellChange"));
93
- }
94
- }
95
- toolbarProjections = [];
96
- sourceObserver?.disconnect();
97
- sourceObserver = void 0;
98
- root?.classList.remove(readyClass);
99
- root = void 0;
100
- };
101
- const copyAttributes = (target, original) => {
102
- for (const name of [
103
- "id",
104
- "slot",
105
- marker,
106
- "aria-hidden"
107
- ]) target.removeAttribute(name);
108
- for (const attribute of Array.from(target.attributes)) if (![
109
- "class",
110
- "data-native-ui-shell",
111
- "data-native-ui-shell-fading"
112
- ].includes(attribute.name) && !original.hasAttribute(attribute.name)) target.removeAttribute(attribute.name);
113
- for (const attribute of Array.from(original.attributes)) if (![
114
- "id",
115
- "slot",
116
- "data-native-ui-shell",
117
- "aria-hidden"
118
- ].includes(attribute.name)) target.setAttribute(attribute.name, attribute.value);
119
- target.classList.remove(prehiddenClass);
120
- };
121
- const syncBack = (target, original) => {
122
- copyAttributes(target, original);
123
- target.classList.add(backProjectionClass, "ion-cloned-element");
124
- target.disabled = original.disabled;
125
- target.defaultHref = original.defaultHref;
126
- target.icon = original.icon;
127
- target.color = original.color;
128
- target.mode = original.mode;
129
- target.text = "";
130
- if (root) alignVerticalBarClone(target, original, root);
131
- };
132
- const syncAction = (target, original) => {
133
- copyAttributes(target, original);
134
- target.classList.add("ios-theme-vertical-bars-toolbar-action", "ion-cloned-element");
135
- const label = original.getAttribute("aria-label") ?? original.shadowRoot?.querySelector("[part~=native]")?.getAttribute("aria-label") ?? original.textContent?.trim();
136
- if (label) target.setAttribute("aria-label", label);
137
- if ("disabled" in original) target.disabled = original.disabled;
138
- if (original.matches("ion-button")) {
139
- const clonedIcon = original.querySelector("ion-icon, svg")?.cloneNode(true);
140
- clonedIcon?.setAttribute("slot", "icon-only");
141
- target.replaceChildren(...clonedIcon ? [clonedIcon] : []);
142
- }
143
- };
144
- const sameSources = (back, groups) => back === backSource && groups.length === toolbarProjections.length && groups.every(({ group, actions }, index) => {
145
- const current = toolbarProjections[index];
146
- return group === current.source && actions.length === current.actions.length && actions.every((action, actionIndex) => action === current.actions[actionIndex].source);
147
- });
148
- const syncExisting = () => {
149
- if (backSource && backProjection) syncBack(backProjection, backSource);
150
- let topOffset = backSource ? 56 : 0;
151
- for (const { projection, source, actions } of toolbarProjections) {
152
- if (actions.length === 1 && !projection.matches("ion-buttons")) syncAction(projection, actions[0].source);
153
- else copyAttributes(projection, source);
154
- projection.classList.add(toolbarProjectionClass, "ion-cloned-element");
155
- projection.style.setProperty("--ios-theme-vertical-bars-toolbar-offset", `${topOffset}px`);
156
- if (projection.matches("ion-buttons")) actions.forEach(({ source: action, projection: clone }) => syncAction(clone, action));
157
- const frames = actions.map(({ source }) => verticalBarFrame(source));
158
- if (root && frames.every((frame) => !!frame)) {
159
- if (actions.length === 1) alignVerticalBarClone(projection, actions[0].source, root);
160
- else {
161
- const left = Math.min(...frames.map((frame) => frame.x));
162
- const top = Math.min(...frames.map((frame) => frame.y));
163
- const right = Math.max(...frames.map((frame) => frame.x + frame.width));
164
- const bottom = Math.max(...frames.map((frame) => frame.y + frame.height));
165
- const origin = root.getBoundingClientRect();
166
- Object.assign(projection.style, {
167
- left: `${left - origin.left}px`,
168
- top: `${top - origin.top}px`,
169
- right: "auto",
170
- bottom: "auto",
171
- width: `${right - left}px`,
172
- height: `${bottom - top}px`,
173
- padding: "0"
174
- });
175
- actions.forEach(({ source, projection: clone }) => alignVerticalBarClone(clone, source, projection));
176
- }
177
- }
178
- topOffset += actions.length * toolbarControlSize + toolbarControlGap;
179
- }
180
- };
181
- const project = (nextBack, groups) => {
182
- root = topModal(doc) ?? verticalBarsRoot();
183
- let topOffset = 0;
184
- if (nextBack) {
185
- backSource = nextBack;
186
- previousBackAriaHidden = nextBack.getAttribute("aria-hidden");
187
- backProjection = nextBack.cloneNode(false);
188
- syncBack(backProjection, nextBack);
189
- backProjection.addEventListener("click", (event) => {
190
- event.preventDefault();
191
- event.stopImmediatePropagation();
192
- if (backSource && backSource === findBack()) activateProjectedElement(backSource);
193
- }, { capture: true });
194
- root.append(backProjection);
195
- nextBack.setAttribute(marker, "");
196
- nextBack.setAttribute("aria-hidden", "true");
197
- nextBack.dispatchEvent(new CustomEvent("nativeUIShellChange"));
198
- topOffset = 56;
199
- }
200
- for (const { group, actions: sources } of groups) {
201
- const projection = (sources.length === 1 ? sources[0] : group).cloneNode(false);
202
- if (sources.length === 1) syncAction(projection, sources[0]);
203
- else copyAttributes(projection, group);
204
- projection.classList.add(toolbarProjectionClass, "ion-cloned-element");
205
- projection.style.setProperty("--ios-theme-vertical-bars-toolbar-offset", `${topOffset}px`);
206
- const actions = sources.map((source) => {
207
- const clone = sources.length === 1 ? projection : source.cloneNode(false);
208
- if (sources.length > 1) syncAction(clone, source);
209
- clone.addEventListener("click", (event) => {
210
- event.preventDefault();
211
- event.stopImmediatePropagation();
212
- if (isCurrentToolbarAction(source)) activateProjectedElement(source);
213
- }, { capture: true });
214
- if (sources.length > 1) projection.append(clone);
215
- const previousAriaHidden = source.getAttribute("aria-hidden");
216
- source.setAttribute(marker, "");
217
- source.setAttribute("aria-hidden", "true");
218
- source.dispatchEvent(new CustomEvent("nativeUIShellChange"));
219
- return {
220
- source,
221
- projection: clone,
222
- previousAriaHidden
223
- };
224
- });
225
- root.append(projection);
226
- toolbarProjections.push({
227
- source: group,
228
- projection,
229
- actions
230
- });
231
- topOffset += actions.length * toolbarControlSize + toolbarControlGap;
232
- }
233
- syncExisting();
234
- if (nextBack || toolbarProjections.length) root.classList.add(readyClass);
235
- sourceObserver = new MutationObserver((records) => {
236
- if (records.some((record) => record.type !== "attributes" || !["data-native-ui-shell", "aria-hidden"].includes(record.attributeName ?? "") && !prehideOnlyMutation(record))) schedule();
237
- });
238
- if (nextBack?.shadowRoot) sourceObserver.observe(nextBack.shadowRoot, {
239
- subtree: true,
240
- childList: true,
241
- attributes: true,
242
- attributeOldValue: true
243
- });
244
- for (const { group } of groups) sourceObserver.observe(group, {
245
- subtree: true,
246
- childList: true,
247
- attributes: true,
248
- attributeOldValue: true
249
- });
250
- };
251
- const reveal = () => {
252
- if (incomingInstant === void 0) return;
253
- for (const surface of [
254
- backProjection,
255
- ...toolbarProjections.map(({ projection }) => projection),
256
- search.surface
257
- ]) if (surface) crossfade.play(surface, false, incomingInstant);
258
- incomingInstant = void 0;
259
- };
260
- const performUpdate = () => {
261
- frame = 0;
262
- syncToolbarText(doc);
263
- const currentRoot = verticalBarsRoot();
264
- if (observingVerticalBars !== !!currentRoot) {
265
- observingVerticalBars = !!currentRoot;
266
- observer.disconnect();
267
- observer.observe(doc.documentElement, {
268
- subtree: true,
269
- childList: true,
270
- characterData: observingVerticalBars,
271
- attributes: true,
272
- attributeOldValue: true,
273
- attributeFilter: observingVerticalBars ? void 0 : ["class"]
274
- });
275
- }
276
- if (stopped || suspended || !currentRoot || !enabled()) return restore();
277
- const nextBack = toolbarEnabled ? findBack() : void 0;
278
- const groups = toolbarEnabled ? findToolbarGroups() : [];
279
- const projectionRoot = topModal(doc) ?? currentRoot;
280
- search.update(projectionRoot);
281
- if (!nextBack && !groups.length && !search.source) return restore();
282
- if (root === (topModal(doc) ?? currentRoot) && sameSources(nextBack, groups)) {
283
- syncExisting();
284
- reveal();
285
- return;
286
- }
287
- restore();
288
- project(nextBack, groups);
289
- search.update(projectionRoot);
290
- reveal();
291
- updates++;
292
- };
293
- const update = () => {
294
- try {
295
- performUpdate();
296
- } catch {
297
- restore();
298
- } finally {
299
- const pending = waiters;
300
- waiters = [];
301
- pending.forEach((resolve) => resolve());
302
- }
303
- };
304
- const schedule = () => {
305
- if (stopped) return Promise.resolve();
306
- if (!enabled()) restore();
307
- const done = new Promise((resolve) => waiters.push(resolve));
308
- if (!frame) frame = win.requestAnimationFrame(update);
309
- return done;
310
- };
311
- const observer = new MutationObserver((records) => {
312
- const insideProjection = (target) => {
313
- const element = target instanceof Element ? target : target.parentNode instanceof Element ? target.parentNode : void 0;
314
- const rootNode = target.getRootNode();
315
- return !![element, rootNode instanceof ShadowRoot ? rootNode.host : void 0].some((candidate) => candidate?.closest(`.${backProjectionClass}, .${toolbarProjectionClass}, .${searchProjectionClass}`));
316
- };
317
- const verticalBarsChanged = records.some((record) => record.type === "attributes" && record.target.matches("ion-app") || record.type === "childList" && Array.from(record.addedNodes).some((node) => node instanceof Element && (node.matches("ion-app.ios-theme-vertical-bars") || !!node.querySelector("ion-app.ios-theme-vertical-bars"))));
318
- if (observingVerticalBars && records.some((record) => record.attributeName !== "data-native-ui-shell" && record.attributeName !== "data-native-ui-shell-toolbar-text" && !prehideOnlyMutation(record) && !insideProjection(record.target)) || !observingVerticalBars && verticalBarsChanged && records.some((record) => !prehideOnlyMutation(record))) schedule();
319
- });
320
- observer.observe(doc.documentElement, {
321
- subtree: true,
322
- childList: true,
323
- attributes: true,
324
- attributeOldValue: true,
325
- attributeFilter: ["class"]
326
- });
327
- const pageLifecycle = (event) => {
328
- const page = event.target;
329
- if (!(page instanceof HTMLElement) || !page.matches(".ion-page")) return;
330
- if (event.type === "iosThemeVerticalBarsTransitionCanceled") {
331
- const entering = event.detail?.entering;
332
- verticalBarsPages.cancel(entering, page);
333
- } else verticalBarsPages.lifecycle(event);
334
- if (verticalBarsRoot()) schedule();
335
- };
336
- for (const name of [
337
- "ionViewWillEnter",
338
- "ionViewWillLeave",
339
- "ionViewDidEnter",
340
- "ionViewDidLeave"
341
- ]) doc.addEventListener(name, pageLifecycle, {
342
- capture: true,
343
- signal: listeners.signal
344
- });
345
- doc.addEventListener(VERTICAL_BARS_TRANSITION_CANCELED, pageLifecycle, {
346
- capture: true,
347
- signal: listeners.signal
348
- });
349
- for (const name of ["ionModalWillPresent", "ionModalDidDismiss"]) doc.addEventListener(name, schedule, {
350
- capture: true,
351
- signal: listeners.signal
352
- });
353
- win.addEventListener("nativeUIShellVerticalBarsAcquire", (event) => {
354
- const instant = event.detail?.instant ?? true;
355
- incomingInstant = void 0;
356
- restore((surface) => {
357
- const box = surface.getBoundingClientRect();
358
- surface.style.setProperty("position", "fixed", "important");
359
- surface.style.setProperty("display", "block", "important");
360
- surface.style.setProperty("left", `${box.left}px`, "important");
361
- surface.style.setProperty("top", `${box.top}px`, "important");
362
- surface.style.setProperty("right", "auto", "important");
363
- surface.style.setProperty("bottom", "auto", "important");
364
- surface.style.setProperty("width", `${box.width}px`, "important");
365
- surface.style.setProperty("height", `${box.height}px`, "important");
366
- crossfade.retire(surface, instant);
367
- });
368
- }, { signal: listeners.signal });
369
- win.addEventListener("nativeUIShellVerticalBarsRelease", (event) => {
370
- incomingInstant = event.detail.instant;
371
- schedule();
372
- }, { signal: listeners.signal });
373
- win.addEventListener("resize", schedule, { signal: listeners.signal });
374
- win.addEventListener("nativeUIShellRefresh", schedule, { signal: listeners.signal });
375
- schedule();
376
- return {
377
- getStatus: () => ({
378
- state: stopped ? "stopped" : "web",
379
- projected: Number(!!backSource) + Number(!!search.source) + toolbarProjections.reduce((count, group) => count + group.actions.length, 0),
380
- updates
381
- }),
382
- async suspend() {
383
- suspended++;
384
- restore();
385
- let resumed = false;
386
- return { async resume() {
387
- if (resumed) return;
388
- resumed = true;
389
- suspended = Math.max(0, suspended - 1);
390
- if (!suspended) await schedule();
391
- } };
392
- },
393
- async destroy() {
394
- if (stopped) return;
395
- stopped = true;
396
- win.cancelAnimationFrame(frame);
397
- frame = 0;
398
- waiters.forEach((resolve) => resolve());
399
- waiters = [];
400
- observer.disconnect();
401
- sourceObserver?.disconnect();
402
- listeners.abort();
403
- crossfade.destroy();
404
- restore();
405
- }
406
- };
407
- };
408
- //#endregion
409
- export { createVerticalBarsWebProjection };
410
-
411
- //# sourceMappingURL=vertical-bars-web.js.map