@rdlabo/ionic-theme-ios27 1.2.1 → 2.0.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.
- package/README.md +24 -279
- package/dist/css/components/ion-toolbar.css +1 -1
- package/dist/css/ionic-theme-ios27.css +1 -1
- package/dist/css/vertical-bars.css +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/layout/index.d.ts +18 -0
- package/dist/layout/index.d.ts.map +1 -0
- package/dist/layout/index.js +26 -0
- package/dist/layout/index.js.map +1 -0
- package/dist/segment/index.js +3 -3
- package/dist/segment/index.js.map +1 -1
- package/dist/sheets-of-glass/index.js +7 -7
- package/dist/sheets-of-glass/index.js.map +1 -1
- package/dist/tab-bar-searchable/dismiss-button.js +53 -3
- package/dist/tab-bar-searchable/dismiss-button.js.map +1 -1
- package/dist/tab-bar-searchable/index.js +18 -3
- package/dist/tab-bar-searchable/index.js.map +1 -1
- package/dist/transition/ios.transition.d.ts.map +1 -1
- package/dist/transition/ios.transition.js +7 -4
- package/dist/transition/ios.transition.js.map +1 -1
- package/dist/transition/native-ui.d.ts +6 -0
- package/dist/transition/native-ui.d.ts.map +1 -0
- package/dist/{native-integration/index.js → transition/native-ui.js} +16 -30
- package/dist/transition/native-ui.js.map +1 -0
- package/docs/adaptive-themes.md +161 -0
- package/docs/add-native-ui.md +53 -0
- package/docs/animation.md +19 -3
- package/docs/eslint.md +3 -1
- package/docs/features.md +9 -5
- package/docs/migration.md +33 -22
- package/docs/setup.md +94 -0
- package/docs/special-markup.md +41 -10
- package/docs/using-ion-item-group.md +2 -2
- package/docs/vertical-bars-layout.md +137 -0
- package/package.json +12 -42
- package/src/index.ts +3 -1
- package/src/layout/index.ts +29 -0
- package/src/segment/index.ts +3 -3
- package/src/sheets-of-glass/index.ts +7 -7
- package/src/styles/components/ion-toolbar.scss +1 -1
- package/src/styles/vertical-bars.scss +15 -18
- package/src/tab-bar-searchable/dismiss-button.ts +73 -4
- package/src/tab-bar-searchable/index.ts +20 -3
- package/src/transition/ios.transition.ts +7 -4
- package/src/{native-integration/index.ts → transition/native-ui.ts} +17 -46
- package/Package.swift +0 -21
- package/dist/_virtual/_rolldown/runtime.js +0 -13
- package/dist/native/components/index.d.ts +0 -19
- package/dist/native/components/index.d.ts.map +0 -1
- package/dist/native/components/index.js +0 -40
- package/dist/native/components/index.js.map +0 -1
- package/dist/native/components/ion-back-button.d.ts +0 -9
- package/dist/native/components/ion-back-button.d.ts.map +0 -1
- package/dist/native/components/ion-back-button.js +0 -20
- package/dist/native/components/ion-back-button.js.map +0 -1
- package/dist/native/components/ion-button.d.ts +0 -10
- package/dist/native/components/ion-button.d.ts.map +0 -1
- package/dist/native/components/ion-button.js +0 -23
- package/dist/native/components/ion-button.js.map +0 -1
- package/dist/native/components/ion-buttons.d.ts +0 -11
- package/dist/native/components/ion-buttons.d.ts.map +0 -1
- package/dist/native/components/ion-buttons.js +0 -30
- package/dist/native/components/ion-buttons.js.map +0 -1
- package/dist/native/components/ion-fab.d.ts +0 -10
- package/dist/native/components/ion-fab.d.ts.map +0 -1
- package/dist/native/components/ion-fab.js +0 -132
- package/dist/native/components/ion-fab.js.map +0 -1
- package/dist/native/components/ion-menu-button.d.ts +0 -13
- package/dist/native/components/ion-menu-button.d.ts.map +0 -1
- package/dist/native/components/ion-menu-button.js +0 -31
- package/dist/native/components/ion-menu-button.js.map +0 -1
- package/dist/native/components/ion-segment.d.ts +0 -11
- package/dist/native/components/ion-segment.d.ts.map +0 -1
- package/dist/native/components/ion-segment.js +0 -30
- package/dist/native/components/ion-segment.js.map +0 -1
- package/dist/native/components/ion-tab-bar.d.ts +0 -11
- package/dist/native/components/ion-tab-bar.d.ts.map +0 -1
- package/dist/native/components/ion-tab-bar.js +0 -50
- package/dist/native/components/ion-tab-bar.js.map +0 -1
- package/dist/native/components/searchable-tabs.d.ts +0 -20
- package/dist/native/components/searchable-tabs.d.ts.map +0 -1
- package/dist/native/components/searchable-tabs.js +0 -383
- package/dist/native/components/searchable-tabs.js.map +0 -1
- package/dist/native/definitions.d.ts +0 -152
- package/dist/native/definitions.d.ts.map +0 -1
- package/dist/native/definitions.js +0 -0
- package/dist/native/foldable/fold-state.d.ts +0 -5
- package/dist/native/foldable/fold-state.d.ts.map +0 -1
- package/dist/native/foldable/fold-state.js +0 -14
- package/dist/native/foldable/fold-state.js.map +0 -1
- package/dist/native/foldable/types.d.ts +0 -12
- package/dist/native/foldable/types.d.ts.map +0 -1
- package/dist/native/foldable/types.js +0 -0
- package/dist/native/index.d.ts +0 -11
- package/dist/native/index.d.ts.map +0 -1
- package/dist/native/index.js +0 -242
- package/dist/native/index.js.map +0 -1
- package/dist/native/prehide.d.ts +0 -7
- package/dist/native/prehide.d.ts.map +0 -1
- package/dist/native/prehide.js +0 -230
- package/dist/native/prehide.js.map +0 -1
- package/dist/native/runtime.d.ts +0 -5
- package/dist/native/runtime.d.ts.map +0 -1
- package/dist/native/runtime.js +0 -640
- package/dist/native/runtime.js.map +0 -1
- package/dist/native/shared/candidate.d.ts +0 -21
- package/dist/native/shared/candidate.d.ts.map +0 -1
- package/dist/native/shared/candidate.js +0 -98
- package/dist/native/shared/candidate.js.map +0 -1
- package/dist/native/shared/crossfade.d.ts +0 -10
- package/dist/native/shared/crossfade.d.ts.map +0 -1
- package/dist/native/shared/crossfade.js +0 -50
- package/dist/native/shared/crossfade.js.map +0 -1
- package/dist/native/shared/dom.d.ts +0 -46
- package/dist/native/shared/dom.d.ts.map +0 -1
- package/dist/native/shared/dom.js +0 -172
- package/dist/native/shared/dom.js.map +0 -1
- package/dist/native/shared/events.d.ts +0 -11
- package/dist/native/shared/events.d.ts.map +0 -1
- package/dist/native/shared/events.js +0 -13
- package/dist/native/shared/events.js.map +0 -1
- package/dist/native/shared/icons.d.ts +0 -8
- package/dist/native/shared/icons.d.ts.map +0 -1
- package/dist/native/shared/icons.js +0 -61
- package/dist/native/shared/icons.js.map +0 -1
- package/dist/native/shared/modal.d.ts +0 -10
- package/dist/native/shared/modal.d.ts.map +0 -1
- package/dist/native/shared/modal.js +0 -160
- package/dist/native/shared/modal.js.map +0 -1
- package/dist/native/vertical-bars-web-search.d.ts +0 -9
- package/dist/native/vertical-bars-web-search.d.ts.map +0 -1
- package/dist/native/vertical-bars-web-search.js +0 -84
- package/dist/native/vertical-bars-web-search.js.map +0 -1
- package/dist/native/vertical-bars-web.d.ts +0 -5
- package/dist/native/vertical-bars-web.d.ts.map +0 -1
- package/dist/native/vertical-bars-web.js +0 -341
- package/dist/native/vertical-bars-web.js.map +0 -1
- package/dist/native-integration/index.d.ts +0 -23
- package/dist/native-integration/index.d.ts.map +0 -1
- package/dist/native-integration/index.js.map +0 -1
- package/dist/native-integration/transition.d.ts +0 -5
- package/dist/native-integration/transition.d.ts.map +0 -1
- package/dist/native-integration/transition.js +0 -16
- package/dist/native-integration/transition.js.map +0 -1
- package/dist/vertical-bars.d.ts +0 -5
- package/dist/vertical-bars.js +0 -4
- package/docs/e2e-testing.md +0 -51
- package/docs/feedback.md +0 -65
- package/docs/iphone-duo-with-original-theme.md +0 -158
- package/docs/iphone-duo.md +0 -150
- package/docs/native-ui-shell.md +0 -285
- package/docs/vertical-bars.md +0 -285
- package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellButton.swift +0 -71
- package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellButtons.swift +0 -24
- package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellComponents.swift +0 -18
- package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellFab.swift +0 -83
- package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellSearchController.swift +0 -432
- package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellSegment.swift +0 -91
- package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellTabBar.swift +0 -221
- package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellVerticalBars.swift +0 -437
- package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellVerticalSearch.swift +0 -118
- package/ios/Sources/IonicNativeUIShellPlugin/IonicNativeUIShellPlugin.swift +0 -396
- package/ios/Sources/IonicNativeUIShellPlugin/Shared/ShellCrossfade.swift +0 -35
- package/ios/Sources/IonicNativeUIShellPlugin/Shared/ShellHost.swift +0 -8
- package/ios/Sources/IonicNativeUIShellPlugin/Shared/ShellRendering.swift +0 -27
- package/ios/Sources/IonicNativeUIShellPlugin/Shared/ShellSnapshot.swift +0 -135
- package/ios/Tests/IonicNativeUIShellPluginTests/ShellSnapshotTests.swift +0 -650
- package/src/native/components/index.ts +0 -53
- package/src/native/components/ion-back-button.ts +0 -19
- package/src/native/components/ion-button.ts +0 -24
- package/src/native/components/ion-buttons.ts +0 -38
- package/src/native/components/ion-fab.ts +0 -151
- package/src/native/components/ion-menu-button.ts +0 -24
- package/src/native/components/ion-segment.ts +0 -27
- package/src/native/components/ion-tab-bar.ts +0 -50
- package/src/native/components/searchable-tabs.ts +0 -459
- package/src/native/definitions.ts +0 -191
- package/src/native/foldable/fold-state.ts +0 -9
- package/src/native/foldable/types.ts +0 -4
- package/src/native/index.ts +0 -281
- package/src/native/prehide.ts +0 -265
- package/src/native/runtime.ts +0 -781
- package/src/native/shared/candidate.ts +0 -150
- package/src/native/shared/crossfade.ts +0 -50
- package/src/native/shared/dom.ts +0 -286
- package/src/native/shared/events.ts +0 -8
- package/src/native/shared/icons.ts +0 -57
- package/src/native/shared/modal.ts +0 -157
- package/src/native/vertical-bars-web-search.ts +0 -80
- package/src/native/vertical-bars-web.ts +0 -411
- package/src/native-integration/transition.ts +0 -15
- package/src/vertical-bars.ts +0 -11
|
@@ -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
|
+
}
|
package/src/segment/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { registeredEffect } from '../sheets-of-glass/interfaces';
|
|
2
|
-
import {
|
|
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 ||
|
|
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('
|
|
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 {
|
|
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 (
|
|
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 (
|
|
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(!
|
|
403
|
+
gesture.enable(!isNativeUI(targetElement));
|
|
404
404
|
cancelActiveGesture();
|
|
405
405
|
};
|
|
406
|
-
targetElement.addEventListener('
|
|
407
|
-
if (
|
|
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('
|
|
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], .
|
|
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-
|
|
99
|
-
> .
|
|
100
|
-
|
|
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
|
-
.
|
|
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.
|
|
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
|
-
.
|
|
310
|
-
[data-
|
|
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
|
-
.
|
|
323
|
-
[data-
|
|
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-
|
|
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-
|
|
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-
|
|
359
|
-
:has(> :is(ion-back-button, ion-button, ion-menu-button):not([data-native-ui-
|
|
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
|
|
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-
|
|
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
|
-
//
|
|
18
|
-
|
|
19
|
-
|
|
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))
|
|
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 {
|
|
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 ||=
|
|
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
|
|
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 {
|
|
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
|
|
18
|
+
get radius() {
|
|
19
|
+
return nativeWebViewMetrics.radius;
|
|
20
|
+
},
|
|
18
21
|
};
|
|
19
22
|
|
|
20
23
|
export const setConfig = (config: Partial<IosTransitionConfig>): void => {
|
|
21
|
-
|
|
24
|
+
if (config.radius !== undefined) nativeWebViewMetrics.radius = config.radius;
|
|
22
25
|
};
|
|
23
26
|
|
|
24
|
-
export const iosTransitionAnimation: (navEl: HTMLElement, opts: TransitionOptions) => Animation =
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
|
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) || !
|
|
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 ??=
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":["button","buttons","backButton","menuButton","tabBar","segment","fab"],"sources":["../../../src/native/components/index.ts"],"mappings":";;;;;;;;;;qBAYa,6BAAUA,6BAAAC,8BAAAC,kCAAAC,kCAAAC,8BAAAC,8BAAAC;YACX,iCAAiC;qBAChC;qBAIA;qBAIA;qBAQA,0BAAuB,SAAA;qBAEvB,gBAAiB,SAAS,aAAa,IAAI,UAAU,UAAS,+BAAkC"}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { isDisabledButtonGroupChild, isVerticalBarsSource, visible, withoutPrehide } from "../shared/dom.js";
|
|
2
|
-
import { ion_button_exports } from "./ion-button.js";
|
|
3
|
-
import { ion_menu_button_exports } from "./ion-menu-button.js";
|
|
4
|
-
import { ion_buttons_exports } from "./ion-buttons.js";
|
|
5
|
-
import { ion_back_button_exports } from "./ion-back-button.js";
|
|
6
|
-
import { ion_tab_bar_exports } from "./ion-tab-bar.js";
|
|
7
|
-
import { ion_segment_exports } from "./ion-segment.js";
|
|
8
|
-
import { ion_fab_exports } from "./ion-fab.js";
|
|
9
|
-
//#region src/native/components/index.ts
|
|
10
|
-
const components = [
|
|
11
|
-
ion_button_exports,
|
|
12
|
-
ion_buttons_exports,
|
|
13
|
-
ion_back_button_exports,
|
|
14
|
-
ion_menu_button_exports,
|
|
15
|
-
ion_tab_bar_exports,
|
|
16
|
-
ion_segment_exports,
|
|
17
|
-
ion_fab_exports
|
|
18
|
-
];
|
|
19
|
-
const selector = components.map((component) => "selector" in component ? component.selector : component.tag).filter(Boolean).join(", ");
|
|
20
|
-
const shadowSelector = ["ion-icon", ...components.flatMap((component) => "shadowSelector" in component ? [component.shadowSelector] : [])].join(", ");
|
|
21
|
-
const motionSelector = [
|
|
22
|
-
".ion-page",
|
|
23
|
-
"ion-header",
|
|
24
|
-
"ion-footer",
|
|
25
|
-
"ion-toolbar",
|
|
26
|
-
...components.filter((component) => "tracksMotion" in component && component.tracksMotion).map((component) => component.tag)
|
|
27
|
-
].join(", ");
|
|
28
|
-
const isVerticalBarsCandidate = isVerticalBarsSource;
|
|
29
|
-
const readCandidate = (element, id, options = {}) => {
|
|
30
|
-
const verticalBars = isVerticalBarsCandidate(element);
|
|
31
|
-
if (!element.classList.contains("ios") && !verticalBars || !visible(element, verticalBars) || element.closest("ion-popover") || element.closest("ion-modal") && !verticalBars) return;
|
|
32
|
-
const style = getComputedStyle(element);
|
|
33
|
-
if (!isDisabledButtonGroupChild(element) && !style.getPropertyValue("--ios-theme-glass-background-rgb").trim() && !style.getPropertyValue("--ios26-glass-background-rgb").trim() && !verticalBars) return;
|
|
34
|
-
if (element.contains(element.ownerDocument.activeElement)) return;
|
|
35
|
-
return withoutPrehide(element, () => components.find((component) => component.tag === element.localName)?.read(element, id, options));
|
|
36
|
-
};
|
|
37
|
-
//#endregion
|
|
38
|
-
export { components, isVerticalBarsCandidate, motionSelector, readCandidate, selector, shadowSelector };
|
|
39
|
-
|
|
40
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["button","buttons","backButton","menuButton","tabBar","segment","fab"],"sources":["../../../src/native/components/index.ts"],"sourcesContent":["import type { VerticalControlAreaOptions } from '../definitions';\nimport * as button from './ion-button';\nimport * as buttons from './ion-buttons';\nimport * as backButton from './ion-back-button';\nimport * as menuButton from './ion-menu-button';\nimport * as tabBar from './ion-tab-bar';\nimport * as segment from './ion-segment';\nimport * as fab from './ion-fab';\nimport { isDisabledButtonGroupChild, isVerticalBarsSource, visible, withoutPrehide } from '../shared/dom';\nimport type { Candidate, Identify } from '../shared/candidate';\n\n// Static composition only. Each component declares its own tag, discovery and reader.\nexport const components = [button, buttons, backButton, menuButton, tabBar, segment, fab] as const;\nexport type NativeUIShellComponent = (typeof components)[number]['tag'];\nexport const selector = components\n .map((component) => ('selector' in component ? component.selector : component.tag))\n .filter(Boolean)\n .join(', ');\nexport const shadowSelector = [\n 'ion-icon',\n ...components.flatMap((component) => ('shadowSelector' in component ? [component.shadowSelector] : [])),\n].join(', ');\nexport const motionSelector = [\n '.ion-page',\n 'ion-header',\n 'ion-footer',\n 'ion-toolbar',\n ...components.filter((component) => 'tracksMotion' in component && component.tracksMotion).map((component) => component.tag),\n].join(', ');\n\nexport const isVerticalBarsCandidate = isVerticalBarsSource;\n\nexport const readCandidate = (element: HTMLElement, id: Identify, options: VerticalControlAreaOptions = {}): Candidate | undefined => {\n const verticalBars = isVerticalBarsCandidate(element);\n if (\n (!element.classList.contains('ios') && !verticalBars) ||\n !visible(element, verticalBars) ||\n element.closest('ion-popover') ||\n (element.closest('ion-modal') && !verticalBars)\n )\n return;\n const style = getComputedStyle(element);\n if (\n !isDisabledButtonGroupChild(element) &&\n !style.getPropertyValue('--ios-theme-glass-background-rgb').trim() &&\n !style.getPropertyValue('--ios26-glass-background-rgb').trim() &&\n !verticalBars\n )\n return;\n if (element.contains(element.ownerDocument.activeElement)) return;\n // Read icon and control geometry before restoring prehide, which can collapse the toolbar.\n return withoutPrehide(element, () => components.find((component) => component.tag === element.localName)?.read(element, id, options));\n};\n"],"mappings":";;;;;;;;;AAYA,MAAa,aAAa;CAACA;CAAQC;CAASC;CAAYC;CAAYC;CAAQC;CAASC;AAAG;AAExF,MAAa,WAAW,WACrB,KAAK,cAAe,cAAc,YAAY,UAAU,WAAW,UAAU,GAAI,CAAC,CAClF,OAAO,OAAO,CAAC,CACf,KAAK,IAAI;AACZ,MAAa,iBAAiB,CAC5B,YACA,GAAG,WAAW,SAAS,cAAe,oBAAoB,YAAY,CAAC,UAAU,cAAc,IAAI,CAAC,CAAE,CACxG,CAAC,CAAC,KAAK,IAAI;AACX,MAAa,iBAAiB;CAC5B;CACA;CACA;CACA;CACA,GAAG,WAAW,QAAQ,cAAc,kBAAkB,aAAa,UAAU,YAAY,CAAC,CAAC,KAAK,cAAc,UAAU,GAAG;AAC7H,CAAC,CAAC,KAAK,IAAI;AAEX,MAAa,0BAA0B;AAEvC,MAAa,iBAAiB,SAAsB,IAAc,UAAsC,CAAC,MAA6B;CACpI,MAAM,eAAe,wBAAwB,OAAO;CACpD,IACG,CAAC,QAAQ,UAAU,SAAS,KAAK,KAAK,CAAC,gBACxC,CAAC,QAAQ,SAAS,YAAY,KAC9B,QAAQ,QAAQ,aAAa,KAC5B,QAAQ,QAAQ,WAAW,KAAK,CAAC,cAElC;CACF,MAAM,QAAQ,iBAAiB,OAAO;CACtC,IACE,CAAC,2BAA2B,OAAO,KACnC,CAAC,MAAM,iBAAiB,kCAAkC,CAAC,CAAC,KAAK,KACjE,CAAC,MAAM,iBAAiB,8BAA8B,CAAC,CAAC,KAAK,KAC7D,CAAC,cAED;CACF,IAAI,QAAQ,SAAS,QAAQ,cAAc,aAAa,GAAG;CAE3D,OAAO,eAAe,eAAe,WAAW,MAAM,cAAc,UAAU,QAAQ,QAAQ,SAAS,CAAC,EAAE,KAAK,SAAS,IAAI,OAAO,CAAC;AACtI"}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { Candidate, Identify } from "../shared/candidate.js";
|
|
2
|
-
declare namespace ion_back_button_d_exports {
|
|
3
|
-
export { read, tag };
|
|
4
|
-
}
|
|
5
|
-
export declare const tag = "ion-back-button";
|
|
6
|
-
export declare const read: (element: HTMLElement, id: Identify) => Candidate | undefined;
|
|
7
|
-
//#endregion
|
|
8
|
-
export { ion_back_button_d_exports };
|
|
9
|
-
//# sourceMappingURL=ion-back-button.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ion-back-button.d.ts","names":[],"sources":["../../../src/native/components/ion-back-button.ts"],"mappings":";;;;qBAIa;qBAEA,OAAQ,SAAS,aAAa,IAAI,aAAW"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { __exportAll } from "../../_virtual/_rolldown/runtime.js";
|
|
2
|
-
import { inFixedToolbar, isVerticalBarsSource } from "../shared/dom.js";
|
|
3
|
-
import { appendItem, createCandidate } from "../shared/candidate.js";
|
|
4
|
-
//#region src/native/components/ion-back-button.ts
|
|
5
|
-
var ion_back_button_exports = /* @__PURE__ */ __exportAll({
|
|
6
|
-
read: () => read,
|
|
7
|
-
tag: () => tag
|
|
8
|
-
});
|
|
9
|
-
const tag = "ion-back-button";
|
|
10
|
-
const read = (element, id) => {
|
|
11
|
-
const button = element;
|
|
12
|
-
if (!button.shadowRoot || button.icon !== void 0 || button.color !== void 0 || !isVerticalBarsSource(element) && !inFixedToolbar(element)) return;
|
|
13
|
-
const candidate = createCandidate(element, tag, id);
|
|
14
|
-
const label = button.shadowRoot.querySelector("[part=\"text\"]")?.textContent?.trim() ?? "";
|
|
15
|
-
return appendItem(candidate, element, id, button.shadowRoot, label) ? candidate : void 0;
|
|
16
|
-
};
|
|
17
|
-
//#endregion
|
|
18
|
-
export { ion_back_button_exports, read, tag };
|
|
19
|
-
|
|
20
|
-
//# sourceMappingURL=ion-back-button.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ion-back-button.js","names":[],"sources":["../../../src/native/components/ion-back-button.ts"],"sourcesContent":["import { createCandidate, appendItem } from '../shared/candidate';\nimport type { Candidate, Identify } from '../shared/candidate';\nimport { inFixedToolbar, isVerticalBarsSource } from '../shared/dom';\n\nexport const tag = 'ion-back-button';\n\nexport const read = (element: HTMLElement, id: Identify): Candidate | undefined => {\n const button = element as HTMLIonBackButtonElement;\n if (\n !button.shadowRoot ||\n button.icon !== undefined ||\n button.color !== undefined ||\n (!isVerticalBarsSource(element) && !inFixedToolbar(element))\n )\n return;\n const candidate = createCandidate(element, tag, id);\n const label = button.shadowRoot.querySelector('[part=\"text\"]')?.textContent?.trim() ?? '';\n return appendItem(candidate, element, id, button.shadowRoot, label) ? candidate : undefined;\n};\n"],"mappings":";;;;;;;;AAIA,MAAa,MAAM;AAEnB,MAAa,QAAQ,SAAsB,OAAwC;CACjF,MAAM,SAAS;CACf,IACE,CAAC,OAAO,cACR,OAAO,SAAS,KAAA,KAChB,OAAO,UAAU,KAAA,KAChB,CAAC,qBAAqB,OAAO,KAAK,CAAC,eAAe,OAAO,GAE1D;CACF,MAAM,YAAY,gBAAgB,SAAS,KAAK,EAAE;CAClD,MAAM,QAAQ,OAAO,WAAW,cAAc,iBAAe,CAAC,EAAE,aAAa,KAAK,KAAK;CACvF,OAAO,WAAW,WAAW,SAAS,IAAI,OAAO,YAAY,KAAK,IAAI,YAAY,KAAA;AACpF"}
|