@rdlabo/ionic-theme-ios27 1.2.1 → 2.0.0-beta.pr303.shaf4f5ca16816f

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 (195) 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 +151 -0
  29. package/docs/add-native-ui.md +53 -0
  30. package/docs/animation.md +1 -1
  31. package/docs/eslint.md +1 -1
  32. package/docs/features.md +3 -3
  33. package/docs/iphone-duo-with-original-theme.md +40 -28
  34. package/docs/iphone-duo.md +29 -32
  35. package/docs/migration.md +12 -24
  36. package/docs/setup.md +82 -0
  37. package/docs/special-markup.md +5 -5
  38. package/docs/using-ion-item-group.md +2 -2
  39. package/docs/vertical-bars-layout.md +47 -0
  40. package/package.json +12 -42
  41. package/src/index.ts +3 -1
  42. package/src/layout/index.ts +29 -0
  43. package/src/segment/index.ts +3 -3
  44. package/src/sheets-of-glass/index.ts +7 -7
  45. package/src/styles/components/ion-toolbar.scss +1 -1
  46. package/src/styles/vertical-bars.scss +15 -18
  47. package/src/tab-bar-searchable/dismiss-button.ts +73 -4
  48. package/src/tab-bar-searchable/index.ts +20 -3
  49. package/src/transition/ios.transition.ts +7 -4
  50. package/src/{native-integration/index.ts → transition/native-ui.ts} +17 -46
  51. package/Package.swift +0 -21
  52. package/dist/_virtual/_rolldown/runtime.js +0 -13
  53. package/dist/native/components/index.d.ts +0 -19
  54. package/dist/native/components/index.d.ts.map +0 -1
  55. package/dist/native/components/index.js +0 -40
  56. package/dist/native/components/index.js.map +0 -1
  57. package/dist/native/components/ion-back-button.d.ts +0 -9
  58. package/dist/native/components/ion-back-button.d.ts.map +0 -1
  59. package/dist/native/components/ion-back-button.js +0 -20
  60. package/dist/native/components/ion-back-button.js.map +0 -1
  61. package/dist/native/components/ion-button.d.ts +0 -10
  62. package/dist/native/components/ion-button.d.ts.map +0 -1
  63. package/dist/native/components/ion-button.js +0 -23
  64. package/dist/native/components/ion-button.js.map +0 -1
  65. package/dist/native/components/ion-buttons.d.ts +0 -11
  66. package/dist/native/components/ion-buttons.d.ts.map +0 -1
  67. package/dist/native/components/ion-buttons.js +0 -30
  68. package/dist/native/components/ion-buttons.js.map +0 -1
  69. package/dist/native/components/ion-fab.d.ts +0 -10
  70. package/dist/native/components/ion-fab.d.ts.map +0 -1
  71. package/dist/native/components/ion-fab.js +0 -132
  72. package/dist/native/components/ion-fab.js.map +0 -1
  73. package/dist/native/components/ion-menu-button.d.ts +0 -13
  74. package/dist/native/components/ion-menu-button.d.ts.map +0 -1
  75. package/dist/native/components/ion-menu-button.js +0 -31
  76. package/dist/native/components/ion-menu-button.js.map +0 -1
  77. package/dist/native/components/ion-segment.d.ts +0 -11
  78. package/dist/native/components/ion-segment.d.ts.map +0 -1
  79. package/dist/native/components/ion-segment.js +0 -30
  80. package/dist/native/components/ion-segment.js.map +0 -1
  81. package/dist/native/components/ion-tab-bar.d.ts +0 -11
  82. package/dist/native/components/ion-tab-bar.d.ts.map +0 -1
  83. package/dist/native/components/ion-tab-bar.js +0 -50
  84. package/dist/native/components/ion-tab-bar.js.map +0 -1
  85. package/dist/native/components/searchable-tabs.d.ts +0 -20
  86. package/dist/native/components/searchable-tabs.d.ts.map +0 -1
  87. package/dist/native/components/searchable-tabs.js +0 -383
  88. package/dist/native/components/searchable-tabs.js.map +0 -1
  89. package/dist/native/definitions.d.ts +0 -152
  90. package/dist/native/definitions.d.ts.map +0 -1
  91. package/dist/native/definitions.js +0 -0
  92. package/dist/native/foldable/fold-state.d.ts +0 -5
  93. package/dist/native/foldable/fold-state.d.ts.map +0 -1
  94. package/dist/native/foldable/fold-state.js +0 -14
  95. package/dist/native/foldable/fold-state.js.map +0 -1
  96. package/dist/native/foldable/types.d.ts +0 -12
  97. package/dist/native/foldable/types.d.ts.map +0 -1
  98. package/dist/native/foldable/types.js +0 -0
  99. package/dist/native/index.d.ts +0 -11
  100. package/dist/native/index.d.ts.map +0 -1
  101. package/dist/native/index.js +0 -242
  102. package/dist/native/index.js.map +0 -1
  103. package/dist/native/prehide.d.ts +0 -7
  104. package/dist/native/prehide.d.ts.map +0 -1
  105. package/dist/native/prehide.js +0 -230
  106. package/dist/native/prehide.js.map +0 -1
  107. package/dist/native/runtime.d.ts +0 -5
  108. package/dist/native/runtime.d.ts.map +0 -1
  109. package/dist/native/runtime.js +0 -640
  110. package/dist/native/runtime.js.map +0 -1
  111. package/dist/native/shared/candidate.d.ts +0 -21
  112. package/dist/native/shared/candidate.d.ts.map +0 -1
  113. package/dist/native/shared/candidate.js +0 -98
  114. package/dist/native/shared/candidate.js.map +0 -1
  115. package/dist/native/shared/crossfade.d.ts +0 -10
  116. package/dist/native/shared/crossfade.d.ts.map +0 -1
  117. package/dist/native/shared/crossfade.js +0 -50
  118. package/dist/native/shared/crossfade.js.map +0 -1
  119. package/dist/native/shared/dom.d.ts +0 -46
  120. package/dist/native/shared/dom.d.ts.map +0 -1
  121. package/dist/native/shared/dom.js +0 -172
  122. package/dist/native/shared/dom.js.map +0 -1
  123. package/dist/native/shared/events.d.ts +0 -11
  124. package/dist/native/shared/events.d.ts.map +0 -1
  125. package/dist/native/shared/events.js +0 -13
  126. package/dist/native/shared/events.js.map +0 -1
  127. package/dist/native/shared/icons.d.ts +0 -8
  128. package/dist/native/shared/icons.d.ts.map +0 -1
  129. package/dist/native/shared/icons.js +0 -61
  130. package/dist/native/shared/icons.js.map +0 -1
  131. package/dist/native/shared/modal.d.ts +0 -10
  132. package/dist/native/shared/modal.d.ts.map +0 -1
  133. package/dist/native/shared/modal.js +0 -160
  134. package/dist/native/shared/modal.js.map +0 -1
  135. package/dist/native/vertical-bars-web-search.d.ts +0 -9
  136. package/dist/native/vertical-bars-web-search.d.ts.map +0 -1
  137. package/dist/native/vertical-bars-web-search.js +0 -84
  138. package/dist/native/vertical-bars-web-search.js.map +0 -1
  139. package/dist/native/vertical-bars-web.d.ts +0 -5
  140. package/dist/native/vertical-bars-web.d.ts.map +0 -1
  141. package/dist/native/vertical-bars-web.js +0 -341
  142. package/dist/native/vertical-bars-web.js.map +0 -1
  143. package/dist/native-integration/index.d.ts +0 -23
  144. package/dist/native-integration/index.d.ts.map +0 -1
  145. package/dist/native-integration/index.js.map +0 -1
  146. package/dist/native-integration/transition.d.ts +0 -5
  147. package/dist/native-integration/transition.d.ts.map +0 -1
  148. package/dist/native-integration/transition.js +0 -16
  149. package/dist/native-integration/transition.js.map +0 -1
  150. package/dist/vertical-bars.d.ts +0 -5
  151. package/dist/vertical-bars.js +0 -4
  152. package/docs/e2e-testing.md +0 -51
  153. package/docs/feedback.md +0 -65
  154. package/docs/native-ui-shell.md +0 -285
  155. package/docs/vertical-bars.md +0 -285
  156. package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellButton.swift +0 -71
  157. package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellButtons.swift +0 -24
  158. package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellComponents.swift +0 -18
  159. package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellFab.swift +0 -83
  160. package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellSearchController.swift +0 -432
  161. package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellSegment.swift +0 -91
  162. package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellTabBar.swift +0 -221
  163. package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellVerticalBars.swift +0 -437
  164. package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellVerticalSearch.swift +0 -118
  165. package/ios/Sources/IonicNativeUIShellPlugin/IonicNativeUIShellPlugin.swift +0 -396
  166. package/ios/Sources/IonicNativeUIShellPlugin/Shared/ShellCrossfade.swift +0 -35
  167. package/ios/Sources/IonicNativeUIShellPlugin/Shared/ShellHost.swift +0 -8
  168. package/ios/Sources/IonicNativeUIShellPlugin/Shared/ShellRendering.swift +0 -27
  169. package/ios/Sources/IonicNativeUIShellPlugin/Shared/ShellSnapshot.swift +0 -135
  170. package/ios/Tests/IonicNativeUIShellPluginTests/ShellSnapshotTests.swift +0 -650
  171. package/src/native/components/index.ts +0 -53
  172. package/src/native/components/ion-back-button.ts +0 -19
  173. package/src/native/components/ion-button.ts +0 -24
  174. package/src/native/components/ion-buttons.ts +0 -38
  175. package/src/native/components/ion-fab.ts +0 -151
  176. package/src/native/components/ion-menu-button.ts +0 -24
  177. package/src/native/components/ion-segment.ts +0 -27
  178. package/src/native/components/ion-tab-bar.ts +0 -50
  179. package/src/native/components/searchable-tabs.ts +0 -459
  180. package/src/native/definitions.ts +0 -191
  181. package/src/native/foldable/fold-state.ts +0 -9
  182. package/src/native/foldable/types.ts +0 -4
  183. package/src/native/index.ts +0 -281
  184. package/src/native/prehide.ts +0 -265
  185. package/src/native/runtime.ts +0 -781
  186. package/src/native/shared/candidate.ts +0 -150
  187. package/src/native/shared/crossfade.ts +0 -50
  188. package/src/native/shared/dom.ts +0 -286
  189. package/src/native/shared/events.ts +0 -8
  190. package/src/native/shared/icons.ts +0 -57
  191. package/src/native/shared/modal.ts +0 -157
  192. package/src/native/vertical-bars-web-search.ts +0 -80
  193. package/src/native/vertical-bars-web.ts +0 -411
  194. package/src/native-integration/transition.ts +0 -15
  195. package/src/vertical-bars.ts +0 -11
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rdlabo/ionic-theme-ios27",
3
3
  "private": false,
4
- "version": "1.2.1",
4
+ "version": "2.0.0-beta.pr303.shaf4f5ca16816f",
5
5
  "description": "iOS27 Theme for Ionic Framework",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.js",
@@ -12,40 +12,25 @@
12
12
  "import": "./dist/index.js"
13
13
  },
14
14
  "./dist/css/*": "./dist/css/*",
15
- "./src/styles/*": "./src/styles/*",
16
- "./native": {
17
- "types": "./dist/native/index.d.ts",
18
- "import": "./dist/native/index.js"
19
- },
20
- "./vertical-bars": {
21
- "types": "./dist/vertical-bars.d.ts",
22
- "import": "./dist/vertical-bars.js"
23
- }
15
+ "./src/styles/*": "./src/styles/*"
24
16
  },
25
17
  "files": [
26
18
  "dist",
27
19
  "src",
28
- "package.json",
29
- "docs",
30
- "ios",
31
- "Package.swift"
20
+ "LICENSE",
21
+ "README.md",
22
+ "docs"
32
23
  ],
33
24
  "scripts": {
34
- "build": "npm run docgen && npm run build:css && npm run build:ts",
35
25
  "prebuild:css": "rdlabo-copy-structured-list src/styles/utils/structured-list.scss",
36
26
  "build:css": "rm -rf dist/css && sass src/styles:dist/css --style=compressed --no-source-map",
37
27
  "build:ts": "tsc --noEmit && rdlabo-build-theme",
38
- "docgen": "docgen --project tsconfig.docgen.json --api NativeUIShellHandle --output-readme docs/native-ui-shell.md && docgen --project tsconfig.docgen.json --api VerticalControlAreaHandle --output-readme docs/vertical-bars.md",
39
- "build:demo": "npm run build && cd demo && npm install && npm run build -- --configuration=production",
40
- "lint": "prettier --check \"./**/*.{scss,ts}\" && prettier --parser angular --check \"./**/*.html\"",
41
- "fmt": "prettier --write \"./**/*.{scss,ts}\" && prettier --parser angular --write \"./**/*.html\"",
42
- "release": "np --no-tests --no-publish",
43
- "prepublishOnly": "npm run build",
44
- "test:esm": "rdlabo-check-esm"
28
+ "build": "rm -rf dist && npm run build:css && npm run build:ts"
45
29
  },
46
30
  "repository": {
47
31
  "type": "git",
48
- "url": "git+ssh://git@github.com/rdlabo-dev/ionic-theme-ios27.git"
32
+ "url": "git+ssh://git@github.com/rdlabo-dev/ionic-theme-ios27.git",
33
+ "directory": "packages/theme-ios27"
49
34
  },
50
35
  "keywords": [
51
36
  "ionic",
@@ -61,20 +46,10 @@
61
46
  },
62
47
  "homepage": "https://docs.rdlabo.dev/projects/ionic-theme-ios27",
63
48
  "dependencies": {
64
- "@rdlabo/ionic-theme-utils": "0.1.2"
65
- },
66
- "devDependencies": {
67
- "@capacitor/core": "^8.5.2",
68
- "@ionic/angular": "^9.0.0",
69
- "@rdlabo/capacitor-docgen": "^0.4.1",
70
- "husky": "^9.1.7",
71
- "lint-staged": "^16.2.1",
72
- "np": "^10.2.0",
73
- "prettier": "^3.6.2",
74
- "sass": "^1.93.2",
75
- "tsdown": "^0.23.0",
76
- "typescript": "^5.9.3",
77
- "wrangler": "^4.125.0"
49
+ "@rdlabo/capacitor-native-ui": "2.0.0-beta.pr303.shaf4f5ca16816f",
50
+ "@rdlabo/ionic-theme-utils": "0.1.4",
51
+ "@stencil/core": "^4.43.5",
52
+ "ionicons": "^8.1.0"
78
53
  },
79
54
  "peerDependencies": {
80
55
  "@capacitor/core": ">=8.0.0 <9",
@@ -85,10 +60,5 @@
85
60
  "optional": true
86
61
  }
87
62
  },
88
- "capacitor": {
89
- "ios": {
90
- "src": "ios"
91
- }
92
- },
93
63
  "type": "module"
94
64
  }
package/src/index.ts CHANGED
@@ -8,7 +8,7 @@ export {
8
8
  export * from './tab-bar-searchable';
9
9
  export * from './searchbar';
10
10
  export * from './transition/ios.transition';
11
- export { withNativeUIShellTransition } from './native-integration/transition';
11
+ export { withNativeUITransition } from './transition/native-ui';
12
12
  export { registerSegmentEffect } from './segment';
13
13
 
14
14
  export const registerTabBarEffect = (targetElement: HTMLElement): registeredEffect | undefined => {
@@ -75,3 +75,5 @@ export const registerTabBarEffect = (targetElement: HTMLElement): registeredEffe
75
75
  },
76
76
  };
77
77
  };
78
+
79
+ export { setVerticalBarsLayout, applyFoldStateClasses, type VerticalBarsLayout, type FoldState } from './layout';
@@ -0,0 +1,29 @@
1
+ /** Web layout inputs. Device capabilities belong to the application or native plugin. */
2
+ export interface VerticalBarsLayout {
3
+ edge: 'leading' | 'trailing' | null;
4
+ inset?: number;
5
+ }
6
+
7
+ /** Applies only Web layout. Does not enable Native UI or report native availability. */
8
+ export const setVerticalBarsLayout = (layout: VerticalBarsLayout, root?: HTMLElement, rtl?: boolean): void => {
9
+ const app = root ?? (typeof document === 'undefined' ? undefined : document.querySelector<HTMLElement>('ion-app'));
10
+ if (!app) return;
11
+ const { edge, inset = 0 } = layout;
12
+ const direction = rtl ?? app.closest('[dir]')?.getAttribute('dir') === 'rtl';
13
+ app.classList.toggle('ios-theme-vertical-bars', edge !== null);
14
+ app.classList.toggle('ios-theme-vertical-bars-left', edge !== null && (edge === 'leading') !== direction);
15
+ if (edge && Number.isFinite(inset) && inset > 0) app.style.setProperty('--ios-theme-vertical-bars-native-inset', `${inset}px`);
16
+ else app.style.removeProperty('--ios-theme-vertical-bars-native-inset');
17
+ app.ownerDocument.defaultView?.dispatchEvent(new Event('nativeUIRefresh'));
18
+ };
19
+
20
+ export interface FoldState {
21
+ state: 'flat' | 'half-opened' | 'closed';
22
+ hingeBounds?: { x: number; y: number; width: number; height: number };
23
+ }
24
+
25
+ /** Maps application-supplied posture to theme CSS, without subscribing to a device plugin. */
26
+ export function applyFoldStateClasses(root: HTMLElement, fold: FoldState): void {
27
+ for (const state of ['flat', 'half-opened', 'closed']) root.classList.toggle(`ios-theme-fold-${state}`, fold.state === state);
28
+ root.classList.toggle('ios-theme-fold-expanded', fold.state === 'half-opened' || (fold.state === 'flat' && !!fold.hingeBounds));
29
+ }
@@ -1,5 +1,5 @@
1
1
  import type { registeredEffect } from '../sheets-of-glass/interfaces';
2
- import { isNativeUIShell } from '../native-integration';
2
+ import { isNativeUI } from '@rdlabo/capacitor-native-ui/integration';
3
3
 
4
4
  interface LensRect {
5
5
  x: number;
@@ -216,7 +216,7 @@ export const registerSegmentEffect = (targetElement: HTMLElement): registeredEff
216
216
  );
217
217
  };
218
218
  const down = (event: PointerEvent) => {
219
- if (pointer || event.button !== 0 || segment.disabled || reducedMotion.matches || isNativeUIShell(segment)) return;
219
+ if (pointer || event.button !== 0 || segment.disabled || reducedMotion.matches || isNativeUI(segment)) return;
220
220
  const button = (event.target as Element).closest<HTMLIonSegmentButtonElement>('ion-segment-button');
221
221
  const old = selected();
222
222
  if (!button || button.disabled || !old) return;
@@ -368,7 +368,7 @@ export const registerSegmentEffect = (targetElement: HTMLElement): registeredEff
368
368
  { signal: listeners.signal },
369
369
  );
370
370
  reducedMotion.addEventListener('change', abort, { signal: listeners.signal });
371
- segment.addEventListener('nativeUIShellChange', abort, { signal: listeners.signal });
371
+ segment.addEventListener('nativeUIChange', abort, { signal: listeners.signal });
372
372
  return {
373
373
  destroy: () => {
374
374
  destroyed = true;
@@ -2,7 +2,7 @@ import { AnimationPosition, EffectScales, registeredEffect } from './interfaces'
2
2
  import { createAnimation, createGesture } from '@ionic/core/components/index.js';
3
3
  import type { Animation, Gesture, GestureDetail } from '@ionic/core/components';
4
4
  import { changeSelectedElement, cloneElement, getStep } from '../utils';
5
- import { isNativeUIShell } from '../native-integration';
5
+ import { isNativeUI } from '@rdlabo/capacitor-native-ui/integration';
6
6
  import {
7
7
  animationRect,
8
8
  createMoveAnimation,
@@ -97,7 +97,7 @@ export const registerEffect = (
97
97
  * They terminate the gesture using native events as a fallback.
98
98
  */
99
99
  const onPointerDown = (event: PointerEvent) => {
100
- if (isNativeUIShell(targetElement)) return;
100
+ if (isNativeUI(targetElement)) return;
101
101
  stopTabPress();
102
102
  tabDragging = false;
103
103
  releaseAnimation?.destroy();
@@ -181,7 +181,7 @@ export const registerEffect = (
181
181
  };
182
182
 
183
183
  const onStartGesture = (detail: GestureDetail): boolean | undefined => {
184
- if (isNativeUIShell(targetElement)) return false;
184
+ if (isNativeUI(targetElement)) return false;
185
185
  currentTouchedElement = ((detail.event.target as HTMLElement).closest(effectTagName) as HTMLElement) || undefined;
186
186
  const tabSelectedElement = targetElement.querySelector(`${effectTagName}.${selectedClassName}`);
187
187
  if (
@@ -400,11 +400,11 @@ export const registerEffect = (
400
400
  };
401
401
 
402
402
  const nativeChanged = () => {
403
- gesture.enable(!isNativeUIShell(targetElement));
403
+ gesture.enable(!isNativeUI(targetElement));
404
404
  cancelActiveGesture();
405
405
  };
406
- targetElement.addEventListener('nativeUIShellChange', nativeChanged);
407
- if (isNativeUIShell(targetElement)) nativeChanged();
406
+ targetElement.addEventListener('nativeUIChange', nativeChanged);
407
+ if (isNativeUI(targetElement)) nativeChanged();
408
408
 
409
409
  return {
410
410
  destroy: () => {
@@ -413,7 +413,7 @@ export const registerEffect = (
413
413
  // Remove event listeners
414
414
  targetElement.removeEventListener('pointerdown', onPointerDown);
415
415
  targetElement.removeEventListener('click', onClick, true);
416
- targetElement.removeEventListener('nativeUIShellChange', nativeChanged);
416
+ targetElement.removeEventListener('nativeUIChange', nativeChanged);
417
417
 
418
418
  // Destroy gesture
419
419
  if (gesture) {
@@ -118,7 +118,7 @@ ion-toolbar.ios:not(.ios-theme-disabled, .ios26-disabled) {
118
118
  margin-inline: 12px;
119
119
  }
120
120
  // Rail sources leave toolbar layout; ordinary native projection retains it.
121
- $visible: ':not([hidden], .ios-theme-native-ui-shell-prehidden, [data-native-ui-shell][data-native-ui-shell-vertical-bars], ion-menu-button.menu-button-hidden, ion-back-button:not(.show-back-button))';
121
+ $visible: ':not([hidden], .native-ui-prehidden, [data-native-ui-projected][data-native-ui-vertical-bars], ion-menu-button.menu-button-hidden, ion-back-button:not(.show-back-button))';
122
122
  $button: ':is(ion-button, ion-back-button)#{$visible}';
123
123
  $group: 'ion-buttons#{$visible}';
124
124
  $action: ':is(#{$button}, #{$group}:has(> #{$visible}))';
@@ -95,12 +95,9 @@ ion-app.ios-theme-vertical-bars
95
95
  // Reserve the final layout before a page transition, using the same prehide
96
96
  // decision as its rail controls. Horizontal native projection keeps its space.
97
97
  // Titles, custom content and horizontal-only controls keep the toolbar visible.
98
- &:not([data-native-ui-shell-toolbar-text]):has(
99
- > .ios-theme-native-ui-shell-prehidden,
100
- > ion-buttons > .ios-theme-native-ui-shell-prehidden
101
- ):not(:has(> :not(ion-buttons, .ios-theme-native-ui-shell-prehidden))):not(
102
- :has(> ion-buttons:not(.ios-theme-native-ui-shell-prehidden) > :not(.ios-theme-native-ui-shell-prehidden))
103
- ) {
98
+ &:not([data-native-ui-toolbar-text]):has(> .native-ui-prehidden, > ion-buttons > .native-ui-prehidden):not(
99
+ :has(> :not(ion-buttons, .native-ui-prehidden))
100
+ ):not(:has(> ion-buttons:not(.native-ui-prehidden) > :not(.native-ui-prehidden))) {
104
101
  display: none;
105
102
  }
106
103
 
@@ -294,20 +291,20 @@ ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left
294
291
  left: calc(24px + (48px - var(--ios-theme-side-tab-bar-width)) / 2);
295
292
  }
296
293
 
297
- .ios-theme-native-ui-shell-prehidden {
294
+ .native-ui-prehidden {
298
295
  position: absolute !important;
299
296
  visibility: hidden !important;
300
297
  }
301
298
 
302
299
  // Hide an entering back source until JS decides whether it belongs in the rail.
303
- html.ios-theme-native-ui-shell-prehide
300
+ html.native-ui-prehide
304
301
  ion-app.ios-theme-vertical-bars
305
302
  ion-back-button:not(
306
303
  [icon],
307
304
  [color],
308
305
  .ios-theme-vertical-bars-back-web-owned,
309
- .ios-theme-shell-disabled,
310
- [data-shell='disabled'],
306
+ .native-ui-disabled,
307
+ [data-native-ui='disabled'],
311
308
  .ios-theme-disabled,
312
309
  .ios26-disabled,
313
310
  .ios-theme-vertical-bars-back-button-projection
@@ -319,8 +316,8 @@ html.ios-theme-native-ui-shell-prehide
319
316
  ion-header[collapse] *,
320
317
  ion-footer[collapse] *,
321
318
  ion-buttons.ios-theme-horizontal-only *,
322
- .ios-theme-shell-disabled *,
323
- [data-shell='disabled'] *,
319
+ .native-ui-disabled *,
320
+ [data-native-ui='disabled'] *,
324
321
  .ios-theme-disabled *,
325
322
  .ios26-disabled *
326
323
  )
@@ -334,7 +331,7 @@ ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-them
334
331
  ion-toolbar:is(.ios, .md):not(.ios-theme-disabled, .ios26-disabled):not(
335
332
  :where(ion-menu *, ion-modal:not(.ios-theme-vertical-bars-modal) *, ion-popover *)
336
333
  )
337
- ion-back-button:is(.ios, .md)[data-native-ui-shell]:not(
334
+ ion-back-button:is(.ios, .md)[data-native-ui-projected]:not(
338
335
  .ios-theme-disabled,
339
336
  .ios26-disabled,
340
337
  .ios-theme-vertical-bars-back-button-projection
@@ -345,7 +342,7 @@ ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-them
345
342
  :where(ion-menu *, ion-modal:not(.ios-theme-vertical-bars-modal) *, ion-popover *)
346
343
  )
347
344
  ion-buttons:is(.ios, .md)
348
- > :is(ion-button, ion-menu-button):is(.ios, .md)[data-native-ui-shell]:not(
345
+ > :is(ion-button, ion-menu-button):is(.ios, .md)[data-native-ui-projected]:not(
349
346
  .ios-theme-disabled,
350
347
  .ios26-disabled,
351
348
  .ios-theme-vertical-bars-toolbar-action
@@ -355,8 +352,8 @@ ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-them
355
352
  ion-toolbar:is(.ios, .md):not(.ios-theme-disabled, .ios26-disabled):not(
356
353
  :where(ion-menu *, ion-modal:not(.ios-theme-vertical-bars-modal) *, ion-popover *)
357
354
  )
358
- ion-buttons:is(.ios, .md):has(> :is(ion-back-button, ion-button, ion-menu-button)[data-native-ui-shell]):not(
359
- :has(> :is(ion-back-button, ion-button, ion-menu-button):not([data-native-ui-shell]))
355
+ ion-buttons:is(.ios, .md):has(> :is(ion-back-button, ion-button, ion-menu-button)[data-native-ui-projected]):not(
356
+ :has(> :is(ion-back-button, ion-button, ion-menu-button):not([data-native-ui-projected]))
360
357
  ) {
361
358
  display: none;
362
359
  }
@@ -441,7 +438,7 @@ ion-tab-button.ios.ion-cloned-element.ios27-vertical-tab-effect {
441
438
  }
442
439
  }
443
440
 
444
- // Search shares the Web rail before Native UI Shell takes ownership.
441
+ // Search shares the Web rail before Native UI takes ownership.
445
442
  :is(ion-app.ios-theme-vertical-bars, ion-modal.ios-theme-vertical-bars-modal) > ion-fab.ios-theme-vertical-bars-search-projection {
446
443
  position: fixed;
447
444
  left: auto;
@@ -459,7 +456,7 @@ ion-tab-button.ios.ion-cloned-element.ios27-vertical-tab-effect {
459
456
  }
460
457
  }
461
458
 
462
- ion-app.ios-theme-vertical-bars ion-fab > ion-fab-button[data-native-ui-shell] {
459
+ ion-app.ios-theme-vertical-bars ion-fab > ion-fab-button[data-native-ui-projected] {
463
460
  visibility: hidden !important;
464
461
  }
465
462
 
@@ -14,9 +14,77 @@ export const addSearchDismissButton = (footer: HTMLElement): void => {
14
14
  button.fill = 'default';
15
15
  button.type = 'button';
16
16
  button.setAttribute('aria-label', original.getAttribute('aria-label') ?? 'Close');
17
- // Keep the field focused until click; blur would hide this button before dismissal.
18
- button.addEventListener('pointerdown', (event) => event.preventDefault());
19
- button.addEventListener('click', () => original.click());
17
+ // WebKit can blur the field between pointerup and click despite preventDefault.
18
+ // Complete pointer activation on release before blur can remove the button.
19
+ const doc = footer.ownerDocument;
20
+ let pointer: number | undefined;
21
+ let pointerTarget: HTMLElement | undefined;
22
+ const actionTarget = (event: Event): HTMLElement | undefined => {
23
+ const target = event.target instanceof Element ? event.target : undefined;
24
+ if (target?.closest('ion-button') === button) return button;
25
+ const clear = target?.closest<HTMLElement>('ion-searchbar .searchbar-clear-button');
26
+ return clear && footer.contains(clear) ? clear : undefined;
27
+ };
28
+ const syncEditing = () => {
29
+ if (!footer.contains(doc.activeElement)) footer.classList.remove('ios-theme-searchable-editing');
30
+ };
31
+ const releasePointer = () => {
32
+ pointer = undefined;
33
+ pointerTarget = undefined;
34
+ doc.removeEventListener('pointerup', finishPointer, true);
35
+ doc.removeEventListener('pointercancel', cancelPointer, true);
36
+ doc.defaultView?.removeEventListener('blur', releasePointer);
37
+ syncEditing();
38
+ };
39
+ const finishPointer = (event: PointerEvent) => {
40
+ if (event.pointerId !== pointer || !pointerTarget) return;
41
+ const target = pointerTarget;
42
+ const rect = target.getBoundingClientRect();
43
+ const inside =
44
+ rect.width > 0 &&
45
+ rect.height > 0 &&
46
+ event.clientX >= rect.left &&
47
+ event.clientX <= rect.right &&
48
+ event.clientY >= rect.top &&
49
+ event.clientY <= rect.bottom;
50
+ releasePointer();
51
+ if (inside) (target === button ? original : target).click();
52
+ };
53
+ const cancelPointer = (event: PointerEvent) => {
54
+ if (event.pointerId === pointer) releasePointer();
55
+ };
56
+ footer.addEventListener(
57
+ 'pointerdown',
58
+ (event) => {
59
+ const target = actionTarget(event);
60
+ if (!target || !event.isPrimary || event.button !== 0) return;
61
+ event.preventDefault();
62
+ pointer = event.pointerId;
63
+ pointerTarget = target;
64
+ doc.addEventListener('pointerup', finishPointer, true);
65
+ doc.addEventListener('pointercancel', cancelPointer, true);
66
+ doc.defaultView?.addEventListener('blur', releasePointer);
67
+ },
68
+ true,
69
+ );
70
+ // Capture before Ionic's clear handler. Our programmatic click (detail 0) still
71
+ // invokes its existing ionClear/input/refocus behavior, including after hydration.
72
+ footer.addEventListener(
73
+ 'click',
74
+ (event) => {
75
+ if (event.detail !== 0 && actionTarget(event)) {
76
+ event.preventDefault();
77
+ event.stopPropagation();
78
+ }
79
+ },
80
+ true,
81
+ );
82
+ button.addEventListener('click', (event) => {
83
+ // Pointer release already invoked the action. Keyboard/AT activation has no pointer click count.
84
+ if (event.detail !== 0) return;
85
+ releasePointer();
86
+ original.click();
87
+ });
20
88
  const icon = footer.ownerDocument.createElement('ion-icon');
21
89
  icon.slot = 'icon-only';
22
90
  icon.icon = close;
@@ -27,7 +95,8 @@ export const addSearchDismissButton = (footer: HTMLElement): void => {
27
95
  if ((event.target as HTMLElement).closest('ion-searchbar')) footer.classList.add('ios-theme-searchable-editing');
28
96
  });
29
97
  footer.addEventListener('focusout', (event) => {
30
- if (!footer.contains(event.relatedTarget as Node | null)) footer.classList.remove('ios-theme-searchable-editing');
98
+ if (pointer === undefined && !footer.contains(event.relatedTarget as Node | null))
99
+ footer.classList.remove('ios-theme-searchable-editing');
31
100
  });
32
101
  original.closest('ion-toolbar')?.append(buttons);
33
102
  };
@@ -11,7 +11,7 @@ import {
11
11
  type TabBarSearchableFunction,
12
12
  TabBarSearchableType,
13
13
  } from '@rdlabo/ionic-theme-utils';
14
- import { isNativeUIShell, registerNativeSearch, requestNativeSearch, suspendNativeUIShell } from '../native-integration';
14
+ import { isNativeUI, registerNativeSearch, requestNativeSearch, suspendNativeUI } from '@rdlabo/capacitor-native-ui/integration';
15
15
  import {
16
16
  createCloseButtonsAnimation,
17
17
  createEffectAnimation,
@@ -75,6 +75,7 @@ export const attachTabBarSearchable = (
75
75
  // Saved Params
76
76
  let searchableEventCache: SearchableEventCache | undefined;
77
77
  let resumeNative: (() => void) | undefined;
78
+ let restoreTrigger: (() => void) | undefined;
78
79
  // Leave is valid both while native Enter awaits its ack and after it completes.
79
80
  let nativeEntry = false;
80
81
  let nativeRequest = 0;
@@ -88,7 +89,7 @@ export const attachTabBarSearchable = (
88
89
  throw new Error('TabBarSearchableType.Leave should be run after TabBarSearchableType.Enter');
89
90
  const hadNativeEntry = nativeEntry;
90
91
  const request = ++nativeRequest;
91
- if (type === TabBarSearchableType.Enter) nativeEntry ||= isNativeUIShell(ionFooter);
92
+ if (type === TabBarSearchableType.Enter) nativeEntry ||= isNativeUI(ionFooter);
92
93
  const accepted = await requestNativeSearch(nativeSearch, type === TabBarSearchableType.Enter);
93
94
  if (request !== nativeRequest) return;
94
95
  if (accepted) {
@@ -114,14 +115,28 @@ export const attachTabBarSearchable = (
114
115
  tabVisibilityObserver.observe(ionTabBar, { attributes: true, attributeFilter: ['class'] });
115
116
  keepTabsVisible();
116
117
  }
117
- resumeNative ??= await suspendNativeUIShell([
118
+ resumeNative ??= await suspendNativeUI([
118
119
  ...(verticalSearch ? [] : [ionTabBar]),
119
120
  ionFooter,
120
121
  ionFabButton.closest('ion-fab') ?? ionFabButton,
121
122
  ]);
122
123
  try {
123
124
  searchableEventCache = await enterEvent(event, ionTabBar, ionFabButton, ionFooter, verticalSearch);
125
+ if (!restoreTrigger) {
126
+ // WebKit can hit an opacity-zero FAB above the focused close button.
127
+ // Hide its complete host after the entrance animation; restore before animating out.
128
+ const trigger = ionFabButton.closest('ion-fab') ?? ionFabButton;
129
+ const visibility = trigger.style.getPropertyValue('visibility');
130
+ const priority = trigger.style.getPropertyPriority('visibility');
131
+ restoreTrigger = () => {
132
+ if (visibility) trigger.style.setProperty('visibility', visibility, priority);
133
+ else trigger.style.removeProperty('visibility');
134
+ restoreTrigger = undefined;
135
+ };
136
+ trigger.style.setProperty('visibility', 'hidden', 'important');
137
+ }
124
138
  } catch (error) {
139
+ restoreTrigger?.();
125
140
  tabVisibilityObserver?.disconnect();
126
141
  resumeNative();
127
142
  resumeNative = undefined;
@@ -129,9 +144,11 @@ export const attachTabBarSearchable = (
129
144
  }
130
145
  } else if (searchableEventCache !== undefined) {
131
146
  try {
147
+ restoreTrigger?.();
132
148
  await leaveEvent(event, searchableEventCache, ionTabBar, ionFabButton, ionFooter, verticalSearch);
133
149
  searchableEventCache = undefined;
134
150
  } finally {
151
+ restoreTrigger?.();
135
152
  tabVisibilityObserver?.disconnect();
136
153
  resumeNative?.();
137
154
  resumeNative = undefined;
@@ -2,7 +2,8 @@ import { createIosTransitionAnimation, shadow } from '@rdlabo/ionic-theme-utils'
2
2
  import type { Animation } from '@ionic/core/components';
3
3
  import type { TransitionOptions } from './index';
4
4
  import { getIonPageElement } from './index';
5
- import { withNativeUIShellTransition } from '../native-integration/transition';
5
+ import { nativeWebViewMetrics } from '@rdlabo/capacitor-native-ui/integration';
6
+ import { withNativeUITransition } from './native-ui';
6
7
 
7
8
  export { shadow };
8
9
 
@@ -14,13 +15,15 @@ const transitionConfig = {
14
15
  offLeftPercent: 30,
15
16
  getIonPageElement,
16
17
  shouldAnimateFixedBackButton: (navEl: HTMLElement) => !navEl.closest('ion-app.ios-theme-vertical-bars'),
17
- radius: 0,
18
+ get radius() {
19
+ return nativeWebViewMetrics.radius;
20
+ },
18
21
  };
19
22
 
20
23
  export const setConfig = (config: Partial<IosTransitionConfig>): void => {
21
- Object.assign(transitionConfig, config);
24
+ if (config.radius !== undefined) nativeWebViewMetrics.radius = config.radius;
22
25
  };
23
26
 
24
- export const iosTransitionAnimation: (navEl: HTMLElement, opts: TransitionOptions) => Animation = withNativeUIShellTransition(
27
+ export const iosTransitionAnimation: (navEl: HTMLElement, opts: TransitionOptions) => Animation = withNativeUITransition(
25
28
  createIosTransitionAnimation<TransitionOptions>(transitionConfig),
26
29
  );
@@ -1,61 +1,32 @@
1
- /// <reference lib="es2021.weakref" />
2
1
  import type { Animation } from '@ionic/core/components';
2
+ import { hasNativeUIIntegration, suspendNativeUI, VERTICAL_BARS_TRANSITION_CANCELED } from '@rdlabo/capacitor-native-ui/integration';
3
+ import type { AnimationBuilder } from '@ionic/core/components';
3
4
 
4
- export interface NativeUIShellIntegration {
5
- suspend(scopes: HTMLElement[]): Promise<(canceled?: boolean) => void>;
6
- search?(binding: NativeSearchBinding, active: boolean, focus?: boolean): Promise<boolean>;
7
- }
8
-
9
- export interface NativeSearchBinding {
10
- tabBar: HTMLElement;
11
- trigger: HTMLElement;
12
- footer: HTMLElement;
13
- active: boolean;
14
- focused: boolean;
15
- }
16
-
17
- const searches = new WeakMap<Document, WeakRef<NativeSearchBinding>[]>();
18
-
19
- export const registerNativeSearch = (tabBar: HTMLElement, trigger: HTMLElement, footer: HTMLElement): NativeSearchBinding => {
20
- const binding = { tabBar, trigger, footer, active: false, focused: false };
21
- const entries = (searches.get(tabBar.ownerDocument) ?? []).filter((entry) => entry.deref() && entry.deref()?.footer !== footer);
22
- entries.push(new WeakRef(binding));
23
- searches.set(tabBar.ownerDocument, entries);
24
- tabBar.ownerDocument.defaultView?.dispatchEvent(new Event('nativeUIShellRefresh'));
25
- return binding;
26
- };
27
-
28
- export const getNativeSearchBindings = (doc: Document): NativeSearchBinding[] =>
29
- (searches.get(doc) ?? []).flatMap((entry) => entry.deref() ?? []);
30
-
31
- export const requestNativeSearch = async (binding: NativeSearchBinding, active: boolean, focus?: boolean): Promise<boolean> =>
32
- (await runtimes.get(binding.tabBar.ownerDocument)?.search?.(binding, active, focus)) ?? false;
33
-
34
- const runtimes = new WeakMap<Document, NativeUIShellIntegration>();
35
- export const VERTICAL_BARS_TRANSITION_CANCELED = 'iosThemeVerticalBarsTransitionCanceled';
36
-
37
- export const setNativeUIShellIntegration = (doc: Document, runtime?: NativeUIShellIntegration) => {
38
- if (runtime) runtimes.set(doc, runtime);
39
- else runtimes.delete(doc);
40
- };
41
-
42
- export const isNativeUIShell = (element: HTMLElement) => element.hasAttribute('data-native-ui-shell');
43
-
44
- export const suspendNativeUIShell = async (scopes: HTMLElement[]): Promise<(canceled?: boolean) => void> =>
45
- (await runtimes.get(scopes[0]?.ownerDocument)?.suspend(scopes)) ?? (() => {});
5
+ /**
6
+ * Keeps an existing Ionic navigation animation and coordinates native control handoff.
7
+ * Register the returned builder as navAnimation. Do not use it for overlay animations.
8
+ * The builder must return a fresh Animation for each navigation; Ionic destroys it afterward.
9
+ */
10
+ export const withNativeUITransition =
11
+ (builder: AnimationBuilder): AnimationBuilder =>
12
+ (baseEl, opts) => {
13
+ const animation = builder(baseEl, opts);
14
+ if (opts?.enteringEl) connectNativeUITransition(animation, opts.enteringEl, opts.leavingEl);
15
+ return animation;
16
+ };
46
17
 
47
18
  const connectedTransitions = new WeakSet<Animation>();
48
19
  const cancellationTransitions = new WeakSet<Animation>();
49
20
 
50
21
  /** Ionic write hooks cannot await the bridge. Gate playback, including interactive playback. */
51
- export const connectNativeUIShellTransition = (animation: Animation, entering: HTMLElement, leaving?: HTMLElement) => {
22
+ export const connectNativeUITransition = (animation: Animation, entering: HTMLElement, leaving?: HTMLElement) => {
52
23
  if (leaving && !cancellationTransitions.has(animation)) {
53
24
  cancellationTransitions.add(animation);
54
25
  animation.onFinish((step) => {
55
26
  if (step === 0) leaving.dispatchEvent(new CustomEvent(VERTICAL_BARS_TRANSITION_CANCELED, { bubbles: true, detail: { entering } }));
56
27
  });
57
28
  }
58
- if (connectedTransitions.has(animation) || !runtimes.has(entering.ownerDocument)) return;
29
+ if (connectedTransitions.has(animation) || !hasNativeUIIntegration(entering.ownerDocument)) return;
59
30
  connectedTransitions.add(animation);
60
31
  const scopes = leaving ? [entering, leaving] : [entering];
61
32
  const play = animation.play.bind(animation);
@@ -70,7 +41,7 @@ export const connectNativeUIShellTransition = (animation: Animation, entering: H
70
41
  let step: number | undefined;
71
42
  let end: Parameters<Animation['progressEnd']> | undefined;
72
43
  const prepare = () =>
73
- (preparation ??= suspendNativeUIShell(scopes).then((resume) => {
44
+ (preparation ??= suspendNativeUI(scopes).then((resume) => {
74
45
  if (disposed) resume(true);
75
46
  else release = resume;
76
47
  }));
package/Package.swift DELETED
@@ -1,21 +0,0 @@
1
- // swift-tools-version: 5.9
2
- import PackageDescription
3
-
4
- let package = Package(
5
- name: "RdlaboIonicThemeIos27",
6
- platforms: [.iOS(.v15)],
7
- products: [.library(name: "RdlaboIonicThemeIos27", targets: ["IonicNativeUIShellPlugin"])],
8
- dependencies: [.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0")],
9
- targets: [.target(
10
- name: "IonicNativeUIShellPlugin",
11
- dependencies: [
12
- .product(name: "Capacitor", package: "capacitor-swift-pm"),
13
- .product(name: "Cordova", package: "capacitor-swift-pm")
14
- ],
15
- path: "ios/Sources/IonicNativeUIShellPlugin"
16
- ), .testTarget(
17
- name: "IonicNativeUIShellPluginTests",
18
- dependencies: ["IonicNativeUIShellPlugin"],
19
- path: "ios/Tests/IonicNativeUIShellPluginTests"
20
- )]
21
- )
@@ -1,13 +0,0 @@
1
- //#region \0rolldown/runtime.js
2
- var __defProp = Object.defineProperty;
3
- var __exportAll = (all, no_symbols) => {
4
- let target = {};
5
- for (var name in all) __defProp(target, name, {
6
- get: all[name],
7
- enumerable: true
8
- });
9
- if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
10
- return target;
11
- };
12
- //#endregion
13
- export { __exportAll };
@@ -1,19 +0,0 @@
1
- import { VerticalControlAreaOptions } from "../definitions.js";
2
- import { Candidate, Identify } from "../shared/candidate.js";
3
- import { ion_button_d_exports } from "./ion-button.js";
4
- import { ion_buttons_d_exports } from "./ion-buttons.js";
5
- import { ion_back_button_d_exports } from "./ion-back-button.js";
6
- import { ion_menu_button_d_exports } from "./ion-menu-button.js";
7
- import { ion_tab_bar_d_exports } from "./ion-tab-bar.js";
8
- import { ion_segment_d_exports } from "./ion-segment.js";
9
- import { ion_fab_d_exports } from "./ion-fab.js";
10
- //#region src/native/components/index.d.ts
11
- export declare const components: readonly [typeof ion_button_d_exports, typeof ion_buttons_d_exports, typeof ion_back_button_d_exports, typeof ion_menu_button_d_exports, typeof ion_tab_bar_d_exports, typeof ion_segment_d_exports, typeof ion_fab_d_exports];
12
- export type NativeUIShellComponent = (typeof components)[number]['tag'];
13
- export declare const selector: string;
14
- export declare const shadowSelector: string;
15
- export declare const motionSelector: string;
16
- export declare const isVerticalBarsCandidate: (element: HTMLElement) => boolean;
17
- export declare const readCandidate: (element: HTMLElement, id: Identify, options?: VerticalControlAreaOptions) => Candidate | undefined;
18
- //#endregion
19
- //# sourceMappingURL=index.d.ts.map