@webview-native-ui/engine 1.0.1 → 1.0.2

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 (230) hide show
  1. package/README.md +14 -0
  2. package/WebViewNativeUIControls.podspec +17 -0
  3. package/dist/controls/activation.d.ts +15 -0
  4. package/dist/controls/activation.js +370 -0
  5. package/dist/controls/components/index.d.ts +16 -0
  6. package/dist/controls/components/index.js +38 -0
  7. package/dist/controls/components/ion-back-button.d.ts +4 -0
  8. package/dist/controls/components/ion-back-button.js +16 -0
  9. package/dist/controls/components/ion-button.d.ts +4 -0
  10. package/dist/controls/components/ion-button.js +26 -0
  11. package/dist/controls/components/ion-buttons.d.ts +5 -0
  12. package/dist/controls/components/ion-buttons.js +34 -0
  13. package/dist/controls/components/ion-fab.d.ts +4 -0
  14. package/dist/controls/components/ion-fab.js +164 -0
  15. package/dist/controls/components/ion-menu-button.d.ts +7 -0
  16. package/dist/controls/components/ion-menu-button.js +41 -0
  17. package/dist/controls/components/ion-segment.d.ts +5 -0
  18. package/dist/controls/components/ion-segment.js +24 -0
  19. package/dist/controls/components/ion-tab-bar.d.ts +5 -0
  20. package/dist/controls/components/ion-tab-bar.js +49 -0
  21. package/dist/controls/components/searchable-tabs.d.ts +20 -0
  22. package/dist/controls/components/searchable-tabs.js +525 -0
  23. package/dist/controls/definitions.d.ts +360 -0
  24. package/dist/controls/definitions.js +1 -0
  25. package/dist/controls/extensions.d.ts +44 -0
  26. package/dist/controls/extensions.js +164 -0
  27. package/dist/controls/foldable/fold-state.d.ts +4 -0
  28. package/dist/controls/foldable/fold-state.js +8 -0
  29. package/dist/controls/foldable/types.d.ts +9 -0
  30. package/dist/controls/foldable/types.js +1 -0
  31. package/dist/controls/html.d.ts +8 -0
  32. package/dist/controls/html.js +260 -0
  33. package/dist/controls/index.d.ts +7 -0
  34. package/dist/controls/index.js +4 -0
  35. package/dist/controls/ionic.d.ts +1 -0
  36. package/dist/controls/ionic.js +1 -0
  37. package/dist/controls/legacy-layout.d.ts +7 -0
  38. package/dist/controls/legacy-layout.js +23 -0
  39. package/dist/controls/overlays/content.d.ts +2 -0
  40. package/dist/controls/overlays/content.js +55 -0
  41. package/dist/controls/overlays/controller.d.ts +7 -0
  42. package/dist/controls/overlays/controller.js +369 -0
  43. package/dist/controls/overlays/covered-overlay.d.ts +4 -0
  44. package/dist/controls/overlays/covered-overlay.js +9 -0
  45. package/dist/controls/overlays/dialog-animation.d.ts +7 -0
  46. package/dist/controls/overlays/dialog-animation.js +49 -0
  47. package/dist/controls/overlays/dismiss-animation.d.ts +2 -0
  48. package/dist/controls/overlays/dismiss-animation.js +14 -0
  49. package/dist/controls/overlays/focus.d.ts +2 -0
  50. package/dist/controls/overlays/focus.js +67 -0
  51. package/dist/controls/overlays/popover.d.ts +10 -0
  52. package/dist/controls/overlays/popover.js +117 -0
  53. package/dist/controls/overlays/styles.d.ts +9 -0
  54. package/dist/controls/overlays/styles.js +194 -0
  55. package/dist/controls/prehide.d.ts +6 -0
  56. package/dist/controls/prehide.js +280 -0
  57. package/dist/controls/runtime.d.ts +5 -0
  58. package/dist/controls/runtime.js +1685 -0
  59. package/dist/controls/shared/bridge.d.ts +4 -0
  60. package/dist/controls/shared/bridge.js +15 -0
  61. package/dist/controls/shared/candidate.d.ts +23 -0
  62. package/dist/controls/shared/candidate.js +128 -0
  63. package/dist/controls/shared/clipping.d.ts +1 -0
  64. package/dist/controls/shared/clipping.js +1 -0
  65. package/dist/controls/shared/connection.d.ts +21 -0
  66. package/dist/controls/shared/connection.js +112 -0
  67. package/dist/controls/shared/control-options.d.ts +4 -0
  68. package/dist/controls/shared/control-options.js +14 -0
  69. package/dist/controls/shared/covered-snapshot.d.ts +35 -0
  70. package/dist/controls/shared/covered-snapshot.js +41 -0
  71. package/dist/controls/shared/covered-source.d.ts +22 -0
  72. package/dist/controls/shared/covered-source.js +72 -0
  73. package/dist/controls/shared/crossfade.d.ts +11 -0
  74. package/dist/controls/shared/crossfade.js +71 -0
  75. package/dist/controls/shared/diagnostics.d.ts +2 -0
  76. package/dist/controls/shared/diagnostics.js +16 -0
  77. package/dist/controls/shared/dom.d.ts +45 -0
  78. package/dist/controls/shared/dom.js +258 -0
  79. package/dist/controls/shared/events.d.ts +12 -0
  80. package/dist/controls/shared/events.js +13 -0
  81. package/dist/controls/shared/horizontal-navigation.d.ts +36 -0
  82. package/dist/controls/shared/horizontal-navigation.js +90 -0
  83. package/dist/controls/shared/icons.d.ts +5 -0
  84. package/dist/controls/shared/icons.js +66 -0
  85. package/dist/controls/shared/modal-animation.d.ts +21 -0
  86. package/dist/controls/shared/modal-animation.js +97 -0
  87. package/dist/controls/shared/modal.d.ts +26 -0
  88. package/dist/controls/shared/modal.js +261 -0
  89. package/dist/controls/shared/projection-id.d.ts +2 -0
  90. package/dist/controls/shared/projection-id.js +2 -0
  91. package/dist/controls/shared/scroll-placement.d.ts +1 -0
  92. package/dist/controls/shared/scroll-placement.js +1 -0
  93. package/dist/controls/shared/tab-bar-width.d.ts +7 -0
  94. package/dist/controls/shared/tab-bar-width.js +72 -0
  95. package/dist/controls/shared/toolbar-options.d.ts +10 -0
  96. package/dist/controls/shared/toolbar-options.js +38 -0
  97. package/dist/controls/shared/transition-identity.d.ts +3 -0
  98. package/dist/controls/shared/transition-identity.js +64 -0
  99. package/dist/controls/shared/vertical-bars-geometry.d.ts +8 -0
  100. package/dist/controls/shared/vertical-bars-geometry.js +82 -0
  101. package/dist/controls/shared/vertical-navigation.d.ts +5 -0
  102. package/dist/controls/shared/vertical-navigation.js +39 -0
  103. package/dist/controls/startup.d.ts +7 -0
  104. package/dist/controls/startup.js +72 -0
  105. package/dist/controls/transport.d.ts +10 -0
  106. package/dist/controls/transport.js +1 -0
  107. package/dist/controls/vertical-bars-web-search.d.ts +8 -0
  108. package/dist/controls/vertical-bars-web-search.js +83 -0
  109. package/dist/controls/vertical-bars-web.d.ts +2 -0
  110. package/dist/controls/vertical-bars-web.js +609 -0
  111. package/dist/index.d.ts +1 -0
  112. package/dist/index.js +1 -0
  113. package/dist/integration/index.d.ts +36 -0
  114. package/dist/integration/index.js +25 -0
  115. package/dist/native/session.js +14 -8
  116. package/dist/projection/pause.d.ts +10 -0
  117. package/dist/projection/pause.js +58 -0
  118. package/dist/projection/styles.d.ts +1 -1
  119. package/dist/projection/styles.js +0 -1
  120. package/dist/projection/surfaces.js +2 -1
  121. package/dist/projection/web.js +39 -5
  122. package/dist/types.d.ts +5 -1
  123. package/docs/README.md +1 -0
  124. package/docs/configuration/README.md +3 -1
  125. package/docs/configuration/ionic-overlays.md +36 -2
  126. package/docs/configuration/pause-resume.md +51 -0
  127. package/docs/controls.md +39 -0
  128. package/ios/Sources/WebViewNativeUIControls/Components/NativeUIButton.swift +98 -0
  129. package/ios/Sources/WebViewNativeUIControls/Components/NativeUIButtons.swift +24 -0
  130. package/ios/Sources/WebViewNativeUIControls/Components/NativeUIComponents.swift +19 -0
  131. package/ios/Sources/WebViewNativeUIControls/Components/NativeUIFab.swift +80 -0
  132. package/ios/Sources/WebViewNativeUIControls/Components/NativeUISearchController.swift +449 -0
  133. package/ios/Sources/WebViewNativeUIControls/Components/NativeUISegment.swift +91 -0
  134. package/ios/Sources/WebViewNativeUIControls/Components/NativeUITabBar.swift +213 -0
  135. package/ios/Sources/WebViewNativeUIControls/Components/NativeUIToolbarTransition.swift +186 -0
  136. package/ios/Sources/WebViewNativeUIControls/Components/NativeUIVerticalBars.swift +696 -0
  137. package/ios/Sources/WebViewNativeUIControls/Components/NativeUIVerticalSearch.swift +117 -0
  138. package/ios/Sources/WebViewNativeUIControls/Extensions/NativeUI.swift +180 -0
  139. package/ios/Sources/WebViewNativeUIControls/Extensions/NativeUIRendering.swift +38 -0
  140. package/ios/Sources/WebViewNativeUIControls/NativeUIController.swift +801 -0
  141. package/ios/Sources/WebViewNativeUIControls/Overlays/NativeUIOverlayController.swift +131 -0
  142. package/ios/Sources/WebViewNativeUIControls/Overlays/NativeUIOverlayHost.swift +85 -0
  143. package/ios/Sources/WebViewNativeUIControls/Shared/NativeUIControlRendering.swift +21 -0
  144. package/ios/Sources/WebViewNativeUIControls/Shared/NativeUICoveredSnapshots.swift +14 -0
  145. package/ios/Sources/WebViewNativeUIControls/Shared/NativeUICrossfade.swift +35 -0
  146. package/ios/Sources/WebViewNativeUIControls/Shared/NativeUIHost.swift +8 -0
  147. package/ios/Sources/WebViewNativeUIControls/Shared/NativeUIScrollTracker.swift +2 -0
  148. package/ios/Sources/WebViewNativeUIControls/Shared/NativeUISnapshot.swift +206 -0
  149. package/ios/Sources/WebViewNativeUIControls/Shared/NativeUIVerticalBarsGeometry.swift +93 -0
  150. package/ios/Sources/WebViewNativeUIEngine/CoveredSnapshots.swift +2 -2
  151. package/ios/Sources/WebViewNativeUIEngine/NativeUIProjection.swift +1 -1
  152. package/ios/Sources/WebViewNativeUIEngine/Resources/native-ui-engine.js +3 -4
  153. package/package.json +30 -5
  154. package/src/controls/activation.ts +427 -0
  155. package/src/controls/components/index.ts +45 -0
  156. package/src/controls/components/ion-back-button.ts +22 -0
  157. package/src/controls/components/ion-button.ts +28 -0
  158. package/src/controls/components/ion-buttons.ts +37 -0
  159. package/src/controls/components/ion-fab.ts +151 -0
  160. package/src/controls/components/ion-menu-button.ts +37 -0
  161. package/src/controls/components/ion-segment.ts +27 -0
  162. package/src/controls/components/ion-tab-bar.ts +55 -0
  163. package/src/controls/components/searchable-tabs.ts +534 -0
  164. package/src/controls/definitions.ts +338 -0
  165. package/src/controls/extensions.ts +198 -0
  166. package/src/controls/foldable/fold-state.ts +10 -0
  167. package/src/controls/foldable/types.ts +4 -0
  168. package/src/controls/html.ts +239 -0
  169. package/src/controls/index.ts +7 -0
  170. package/src/controls/ionic.ts +1 -0
  171. package/src/controls/legacy-layout.ts +21 -0
  172. package/src/controls/overlays/content.ts +51 -0
  173. package/src/controls/overlays/controller.ts +394 -0
  174. package/src/controls/overlays/covered-overlay.ts +11 -0
  175. package/src/controls/overlays/dialog-animation.ts +53 -0
  176. package/src/controls/overlays/dismiss-animation.ts +15 -0
  177. package/src/controls/overlays/focus.ts +64 -0
  178. package/src/controls/overlays/popover.ts +116 -0
  179. package/src/controls/overlays/styles.ts +195 -0
  180. package/src/controls/prehide.ts +285 -0
  181. package/src/controls/runtime.ts +1731 -0
  182. package/src/controls/shared/bridge.ts +18 -0
  183. package/src/controls/shared/candidate.ts +163 -0
  184. package/src/controls/shared/clipping.ts +1 -0
  185. package/src/controls/shared/connection.ts +105 -0
  186. package/src/controls/shared/control-options.ts +20 -0
  187. package/src/controls/shared/covered-snapshot.ts +52 -0
  188. package/src/controls/shared/covered-source.ts +78 -0
  189. package/src/controls/shared/crossfade.ts +70 -0
  190. package/src/controls/shared/diagnostics.ts +13 -0
  191. package/src/controls/shared/dom.ts +310 -0
  192. package/src/controls/shared/events.ts +14 -0
  193. package/src/controls/shared/horizontal-navigation.ts +106 -0
  194. package/src/controls/shared/icons.ts +64 -0
  195. package/src/controls/shared/modal-animation.ts +109 -0
  196. package/src/controls/shared/modal.ts +286 -0
  197. package/src/controls/shared/projection-id.ts +2 -0
  198. package/src/controls/shared/scroll-placement.ts +1 -0
  199. package/src/controls/shared/tab-bar-width.ts +66 -0
  200. package/src/controls/shared/toolbar-options.ts +51 -0
  201. package/src/controls/shared/transition-identity.ts +67 -0
  202. package/src/controls/shared/vertical-bars-geometry.ts +92 -0
  203. package/src/controls/shared/vertical-navigation.ts +34 -0
  204. package/src/controls/startup.ts +74 -0
  205. package/src/controls/transport.ts +11 -0
  206. package/src/controls/vertical-bars-web-search.ts +86 -0
  207. package/src/controls/vertical-bars-web.ts +674 -0
  208. package/src/dom/geometry.ts +24 -0
  209. package/src/dom/overlays.ts +196 -0
  210. package/src/dom/scroll-bindings.ts +66 -0
  211. package/src/dom/scroll-placement.ts +92 -0
  212. package/src/dom/visibility.ts +29 -0
  213. package/src/index.ts +19 -0
  214. package/src/integration/index.ts +64 -0
  215. package/src/ionic.ts +34 -0
  216. package/src/native/bootstrap.ts +132 -0
  217. package/src/native/bridge.ts +18 -0
  218. package/src/native/resource-url.ts +11 -0
  219. package/src/native/session.ts +708 -0
  220. package/src/native/updates.ts +103 -0
  221. package/src/native/values.ts +29 -0
  222. package/src/projection/events.ts +58 -0
  223. package/src/projection/pause.ts +58 -0
  224. package/src/projection/placement.ts +34 -0
  225. package/src/projection/scope.ts +13 -0
  226. package/src/projection/styles.ts +26 -0
  227. package/src/projection/surface.ts +88 -0
  228. package/src/projection/surfaces.ts +119 -0
  229. package/src/projection/web.ts +1013 -0
  230. package/src/types.ts +58 -0
@@ -0,0 +1,164 @@
1
+ import { childElements, excluded, isDark, text } from '../shared/dom.js';
2
+ import { iconSource } from '../shared/icons.js';
3
+ export const tag = 'ion-fab';
4
+ export const shadowSelector = 'ion-fab-button, ion-fab-list';
5
+ const hasHostMotion = (style) => style.animationName !== 'none' || style.transitionDuration.split(',').some((value) => parseFloat(value) > 0);
6
+ // FAB owns the batch; only its buttons draw glass. Closed lists keep their IDs
7
+ // and resolved artwork, without inventing layout for display:none descendants.
8
+ export const read = (fab, id) => {
9
+ if (fab.slot !== 'fixed' || !fab.parentElement?.matches('ion-content') || fab.contains(fab.ownerDocument.activeElement))
10
+ return;
11
+ const children = childElements(fab);
12
+ const main = children.filter((child) => child.matches('ion-fab-button'));
13
+ const lists = children.filter((child) => child.matches('ion-fab-list'));
14
+ if (main.length !== 1 || main.length + lists.length !== children.length)
15
+ return;
16
+ if (lists.some((list) => list.closest(excluded) || childElements(list).some((child) => !child.matches('ion-fab-button'))))
17
+ return;
18
+ const buttons = [main[0], ...lists.flatMap((list) => childElements(list))];
19
+ const style = getComputedStyle(fab);
20
+ if (hasHostMotion(style))
21
+ return;
22
+ const transform = new DOMMatrixReadOnly(style.transform);
23
+ if (!transform.is2D || transform.a !== 1 || transform.d !== 1 || transform.b || transform.c)
24
+ return;
25
+ const candidate = {
26
+ element: fab,
27
+ control: {
28
+ id: id(fab),
29
+ kind: 'floating-action-button',
30
+ x: 0,
31
+ y: 0,
32
+ width: innerWidth,
33
+ height: innerHeight,
34
+ dark: isDark(style),
35
+ rtl: style.direction === 'rtl',
36
+ items: [],
37
+ },
38
+ actions: new Map(),
39
+ icons: [],
40
+ };
41
+ for (const button of buttons) {
42
+ if (!button.classList.contains('ios') || button.closest(excluded) || button.color || button.type !== 'button' || button.href)
43
+ return;
44
+ if (button.querySelector('input, button, a, img, canvas, video, ion-spinner, ion-avatar, ion-badge'))
45
+ return;
46
+ const native = button.shadowRoot?.querySelector('[part=native]');
47
+ if (!native)
48
+ return;
49
+ const s = getComputedStyle(button), n = getComputedStyle(native);
50
+ // An opaque custom host/background or custom shape cannot be discarded.
51
+ const alpha = n.backgroundColor.startsWith('rgba(') ? Number(n.backgroundColor.slice(5, -1).split(',')[3]) : 1;
52
+ if (s.backgroundColor !== 'rgba(0, 0, 0, 0)' ||
53
+ s.backgroundImage !== 'none' ||
54
+ n.backgroundImage.includes('url(') ||
55
+ !n.backdropFilter.includes('blur') ||
56
+ !(alpha > 0 && alpha < 1))
57
+ return;
58
+ const width = parseFloat(s.width), height = parseFloat(s.height);
59
+ if (!(width > 0 && height > 0) || Math.abs(width - height) > 0.5 || !n.borderRadius.includes('50%'))
60
+ return;
61
+ const list = button.parentElement?.matches('ion-fab-list') ? button.parentElement : undefined;
62
+ const listStyle = list && getComputedStyle(list);
63
+ const laidOut = s.display !== 'none' && (!listStyle || listStyle.display !== 'none');
64
+ const visible = laidOut &&
65
+ (!list || (list.activated && button.show && listStyle.visibility === 'visible' && Number(listStyle.opacity) > 0)) &&
66
+ s.visibility === 'visible' &&
67
+ Number(s.opacity) > 0;
68
+ // Standard scale is centered: even scale(0) retains its actual layout center.
69
+ // Static list translation is already included in the DOM rect (including RTL).
70
+ const matrix = new DOMMatrixReadOnly(s.transform);
71
+ if (!matrix.is2D || matrix.b || matrix.c || matrix.e || matrix.f || matrix.a !== matrix.d || matrix.a < 0)
72
+ return;
73
+ // Only Ionic's hidden list child may use scale(0). Custom static scaling
74
+ // changes the actual glass/hit area and must retain its Web rendering.
75
+ // Stencil updates show before rendering its host class. Judge the rendered
76
+ // scale against that class so this normal one-frame gap keeps its cover.
77
+ if (matrix.a !== 1 && (matrix.a !== 0 || !list || button.classList.contains('fab-button-show')))
78
+ return;
79
+ if (laidOut && !matrix.isIdentity) {
80
+ const origin = s.transformOrigin.split(' ').map(parseFloat);
81
+ if (Math.abs(origin[0] - width / 2) > 0.5 || Math.abs(origin[1] - height / 2) > 0.5)
82
+ return;
83
+ }
84
+ // Ionic's list appearance is staggered show changes, without a host CSS
85
+ // transition. Custom host animations keep their complete Web rendering.
86
+ if (hasHostMotion(s))
87
+ return;
88
+ if (listStyle) {
89
+ if (hasHostMotion(listStyle))
90
+ return;
91
+ const transform = new DOMMatrixReadOnly(listStyle.transform);
92
+ if (!transform.is2D || transform.a !== 1 || transform.d !== 1 || transform.b || transform.c)
93
+ return;
94
+ }
95
+ const rect = button.getBoundingClientRect();
96
+ const x = laidOut ? rect.x + rect.width / 2 - width / 2 : 0;
97
+ const y = laidOut ? rect.y + rect.height / 2 - height / 2 : 0;
98
+ if (visible && (x < -1 || y < -1 || x + width > innerWidth + 1 || y + height > innerHeight + 1))
99
+ return;
100
+ const label = text(button);
101
+ const item = {
102
+ id: id(button),
103
+ x,
104
+ y,
105
+ width,
106
+ height,
107
+ label,
108
+ accessibilityLabel: button.getAttribute('aria-label') ?? native.getAttribute('aria-label') ?? label,
109
+ disabled: button.disabled || s.pointerEvents === 'none',
110
+ selected: button.activated,
111
+ visible,
112
+ fontSize: parseFloat(s.fontSize),
113
+ fontWeight: parseInt(s.fontWeight, 10) || 400,
114
+ color: n.color,
115
+ };
116
+ const normal = Array.from(button.querySelectorAll('ion-icon, svg'));
117
+ if (normal.length > 1)
118
+ return;
119
+ const close = button.shadowRoot?.querySelector('ion-icon[part=close-icon]');
120
+ for (const [index, icon] of [normal[0], close].entries()) {
121
+ if (!icon) {
122
+ if (index === 1 || !label)
123
+ return;
124
+ else
125
+ continue;
126
+ }
127
+ const svg = icon.matches('svg') ? icon : icon.shadowRoot?.querySelector('svg');
128
+ if (!svg)
129
+ return;
130
+ const iconStyle = getComputedStyle(icon);
131
+ const inner = icon.shadowRoot?.querySelector('.icon-inner');
132
+ if (index === 0 && inner && !new DOMMatrixReadOnly(iconStyle.transform).isIdentity)
133
+ return;
134
+ const transform = new DOMMatrixReadOnly(inner ? getComputedStyle(inner).transform : iconStyle.transform);
135
+ const mirrored = transform.is2D && transform.a === -1 && transform.d === 1 && !transform.b && !transform.c && !transform.e && !transform.f;
136
+ if (index === 0 && !transform.isIdentity && !mirrored)
137
+ return;
138
+ const source = iconSource(svg, index === 0 && mirrored);
139
+ const iconWidth = parseFloat(iconStyle.width), iconHeight = parseFloat(iconStyle.height);
140
+ // The internal close-icon fills the button vertically; its glyph uses font-size.
141
+ const size = index === 1 ? parseFloat(iconStyle.fontSize) : iconWidth;
142
+ const h = index === 1 ? size : iconHeight;
143
+ if (!source || !(size > 0 && h > 0))
144
+ return;
145
+ if (index === 0) {
146
+ item.iconWidth = size;
147
+ item.iconHeight = h;
148
+ }
149
+ else {
150
+ item.closeIconWidth = size;
151
+ item.closeIconHeight = h;
152
+ item.iconTransition =
153
+ parseFloat(iconStyle.transitionDuration) * (iconStyle.transitionDuration.split(',')[0].trim().endsWith('ms') ? 0.001 : 1);
154
+ }
155
+ candidate.icons.push({ item, source, ...(index === 1 ? { field: 'closeIcon' } : {}) });
156
+ }
157
+ if (!visible && !list)
158
+ return;
159
+ candidate.control.items.push(item);
160
+ if (visible)
161
+ candidate.actions.set(item.id, button);
162
+ }
163
+ return candidate;
164
+ };
@@ -0,0 +1,7 @@
1
+ import type { Candidate, Identify } from '../shared/candidate.js';
2
+ import type { VerticalControlAreaOptions } from '../definitions.js';
3
+ export declare const tag = "ion-menu-button";
4
+ export declare const selector = "ion-menu-button";
5
+ export declare const shadowSelector = "ion-menu-button";
6
+ export declare const append: (candidate: Candidate, button: HTMLIonMenuButtonElement, id: Identify) => boolean;
7
+ export declare const read: (group: HTMLElement, id: Identify, options?: VerticalControlAreaOptions) => Candidate | undefined;
@@ -0,0 +1,41 @@
1
+ import { horizontalSelected, horizontalToolbarGroup, inVerticalToolbarLayout } from '../shared/toolbar-options.js';
2
+ import { createCandidate, appendItem } from '../shared/candidate.js';
3
+ import { childElements, inFixedToolbar, isVerticalBarsToolbarAction, isVerticalBarsToolbarGroup } from '../shared/dom.js';
4
+ export const tag = 'ion-menu-button';
5
+ // Horizontal menu buttons belong to ion-buttons; vertical actions can opt out of grouping.
6
+ export const selector = tag;
7
+ export const shadowSelector = tag;
8
+ export const append = (candidate, button, id) => {
9
+ if (button.type !== 'button')
10
+ return false;
11
+ const content = !button.shadowRoot?.querySelector('slot')?.assignedNodes().length ? button.shadowRoot : button;
12
+ return !!content && !!appendItem(candidate, button, id, content);
13
+ };
14
+ export const read = (group, id, options = {}) => {
15
+ if (group.matches(tag)) {
16
+ if (!inFixedToolbar(group))
17
+ return;
18
+ if (inVerticalToolbarLayout(group)) {
19
+ if (!isVerticalBarsToolbarAction(group))
20
+ return;
21
+ if (group.parentElement && isVerticalBarsToolbarGroup(group.parentElement))
22
+ return;
23
+ }
24
+ else {
25
+ if (!horizontalSelected(group, options) || !group.parentElement?.matches('ion-buttons'))
26
+ return;
27
+ if (horizontalToolbarGroup(group.parentElement, options))
28
+ return;
29
+ }
30
+ const candidate = createCandidate(group, tag, id, options);
31
+ return append(candidate, group, id) ? candidate : undefined;
32
+ }
33
+ const children = group.matches('ion-buttons') ? childElements(group) : [];
34
+ if (!inFixedToolbar(group) || children.length !== 1)
35
+ return;
36
+ const button = children[0];
37
+ if (!button?.matches(`${tag}${group.closest('ion-app.ios-theme-vertical-bars') ? '' : '.ios'}`))
38
+ return;
39
+ const candidate = createCandidate(group, tag, id, options);
40
+ return append(candidate, button, id) ? candidate : undefined;
41
+ };
@@ -0,0 +1,5 @@
1
+ import type { Candidate, Identify } from '../shared/candidate.js';
2
+ export declare const tag = "ion-segment";
3
+ export declare const shadowSelector = "ion-segment-button";
4
+ export declare const tracksMotion = true;
5
+ export declare const read: (element: HTMLElement, id: Identify) => Candidate | undefined;
@@ -0,0 +1,24 @@
1
+ import { createCandidate, appendItem } from '../shared/candidate.js';
2
+ import { inFixedToolbar } from '../shared/dom.js';
3
+ export const tag = 'ion-segment';
4
+ export const shadowSelector = 'ion-segment-button';
5
+ export const tracksMotion = true;
6
+ export const read = (element, id) => {
7
+ const segment = element;
8
+ if (!inFixedToolbar(element) ||
9
+ segment.scrollable ||
10
+ element.classList.contains('segment-expand') ||
11
+ element.querySelector('ion-segment-button[content-id]'))
12
+ return;
13
+ const children = Array.from(element.querySelectorAll(':scope > ion-segment-button'));
14
+ if (!children.length)
15
+ return;
16
+ const candidate = createCandidate(element, tag, id);
17
+ for (const child of children) {
18
+ const item = appendItem(candidate, child, id);
19
+ if (!item || (item.label && item.iconWidth))
20
+ return;
21
+ item.selected = segment.value === child.value;
22
+ }
23
+ return candidate;
24
+ };
@@ -0,0 +1,5 @@
1
+ import type { Candidate, Identify } from '../shared/candidate.js';
2
+ export declare const tag = "ion-tab-bar";
3
+ export declare const shadowSelector = "ion-tab-button";
4
+ export declare const tracksMotion = true;
5
+ export declare const read: (element: HTMLElement, id: Identify) => Candidate | undefined;
@@ -0,0 +1,49 @@
1
+ import { createCandidate, appendItem } from '../shared/candidate.js';
2
+ export const tag = 'ion-tab-bar';
3
+ export const shadowSelector = 'ion-tab-button';
4
+ export const tracksMotion = true;
5
+ export const read = (element, id) => {
6
+ if (element.closest('ion-content'))
7
+ return;
8
+ const children = Array.from(element.querySelectorAll(':scope > ion-tab-button:not(.ion-cloned-element)'));
9
+ if (!children.length)
10
+ return;
11
+ // Only equal items with Ionic's default layout map to UIKit's adaptive tabs.
12
+ const width = children[0].getBoundingClientRect().width;
13
+ if (children.some((child) => (child.layout ?? 'icon-top') !== 'icon-top' ||
14
+ Math.abs(child.getBoundingClientRect().width - width) > 1))
15
+ return undefined;
16
+ const candidate = createCandidate(element, tag, id);
17
+ const style = getComputedStyle(element);
18
+ // Palette contrast colors assume a colored Web background; keep native tint there.
19
+ const projectSelectionColor = !element.classList.contains('ion-color');
20
+ const rtl = style.direction === 'rtl';
21
+ const position = ['start', 'center', 'end'].find((value) => element.classList.contains(`tab-bar-position-${value}`));
22
+ candidate.control.tabBarAnchor = {
23
+ x: position === 'center' ? 0.5 : position ? ((position === 'start') !== rtl ? 0 : 1) : style.left !== 'auto' ? 0 : 1,
24
+ y: element.slot === 'bottom' ? 1 : 0,
25
+ };
26
+ for (const child of children) {
27
+ const item = appendItem(candidate, child, id);
28
+ if (!item)
29
+ return;
30
+ // Read Ionic's applied selection color, after CSS inheritance and theme
31
+ // resolution, rather than requiring a particular palette token or format.
32
+ if (projectSelectionColor && item.selected && /^rgba?\(/.test(item.color))
33
+ candidate.control.tabTint = item.color;
34
+ const svg = child.querySelector('svg') ?? child.querySelector('ion-icon')?.shadowRoot?.querySelector('svg');
35
+ if (svg) {
36
+ item.iconPosition = 'top';
37
+ const color = getComputedStyle(svg).color;
38
+ const shapes = Array.from(svg.querySelectorAll('path, rect, circle, ellipse, line, polygon, polyline'));
39
+ // Only text-colored SVGs follow UIKit selection tint; preserve explicit artwork colors.
40
+ item.iconTemplate =
41
+ shapes.length > 0 &&
42
+ shapes.every((shape) => {
43
+ const paint = getComputedStyle(shape);
44
+ return [paint.fill, paint.stroke].every((value) => value === 'none' || value === color);
45
+ });
46
+ }
47
+ }
48
+ return candidate;
49
+ };
@@ -0,0 +1,20 @@
1
+ import type { NativeSearchBinding } from '../../integration/index.js';
2
+ import type { Candidate } from '../shared/candidate.js';
3
+ import type { NativeUISearchEvent } from '../definitions.js';
4
+ export declare const createSearchSupport: (doc: Document, id: (element: Element) => string, schedule: () => void) => {
5
+ keyboard(visible: boolean): void;
6
+ prepare(scope?: ParentNode): void;
7
+ settle(transitioning: (element: HTMLElement) => boolean): void;
8
+ keepSearchTabsVisible(): void;
9
+ decorate(candidates: Candidate[], blocked: (element: HTMLElement) => boolean): Candidate[];
10
+ projected: (binding: NativeSearchBinding) => boolean;
11
+ hasActive(): boolean;
12
+ begin(binding: NativeSearchBinding, revision: number): void;
13
+ /** Enter / focus / leave. `focused` is ignored when leaving. */
14
+ setStatus(binding: NativeSearchBinding, active: boolean, focused?: boolean): void;
15
+ release(element: HTMLElement): void;
16
+ reject(ids: string[]): void;
17
+ event(event: NativeUISearchEvent): void;
18
+ retire(binding: NativeSearchBinding, unavailable?: boolean): void;
19
+ destroy(): void;
20
+ };