@rdlabo/capacitor-native-ui 0.0.0-stage → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/Package.swift +23 -0
- package/README.md +53 -2
- package/RdlaboCapacitorNativeUi.podspec +17 -0
- package/android/build.gradle +69 -0
- package/android/proguard-rules.pro +0 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/java/dev/rdlabo/capacitor/nativeui/NativeUI.kt +51 -0
- package/android/src/main/java/dev/rdlabo/capacitor/nativeui/NativeUIPlugin.kt +192 -0
- package/android/src/main/java/dev/rdlabo/capacitor/nativeui/NativeUISnapshot.kt +57 -0
- package/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/core.d.ts +4 -0
- package/dist/core.js +3 -0
- package/dist/native/activation.d.ts +14 -0
- package/dist/native/activation.d.ts.map +1 -0
- package/dist/native/activation.js +305 -0
- package/dist/native/activation.js.map +1 -0
- package/dist/native/components/index.d.ts +19 -0
- package/dist/native/components/index.d.ts.map +1 -0
- package/dist/native/components/index.js +38 -0
- package/dist/native/components/index.js.map +1 -0
- package/dist/native/components/ion-back-button.d.ts +10 -0
- package/dist/native/components/ion-back-button.d.ts.map +1 -0
- package/dist/native/components/ion-back-button.js +21 -0
- package/dist/native/components/ion-back-button.js.map +1 -0
- package/dist/native/components/ion-button.d.ts +10 -0
- package/dist/native/components/ion-button.d.ts.map +1 -0
- package/dist/native/components/ion-button.js +25 -0
- package/dist/native/components/ion-button.js.map +1 -0
- package/dist/native/components/ion-buttons.d.ts +11 -0
- package/dist/native/components/ion-buttons.d.ts.map +1 -0
- package/dist/native/components/ion-buttons.js +30 -0
- package/dist/native/components/ion-buttons.js.map +1 -0
- package/dist/native/components/ion-fab.d.ts +10 -0
- package/dist/native/components/ion-fab.d.ts.map +1 -0
- package/dist/native/components/ion-fab.js +132 -0
- package/dist/native/components/ion-fab.js.map +1 -0
- package/dist/native/components/ion-menu-button.d.ts +13 -0
- package/dist/native/components/ion-menu-button.d.ts.map +1 -0
- package/dist/native/components/ion-menu-button.js +44 -0
- package/dist/native/components/ion-menu-button.js.map +1 -0
- package/dist/native/components/ion-segment.d.ts +11 -0
- package/dist/native/components/ion-segment.d.ts.map +1 -0
- package/dist/native/components/ion-segment.js +30 -0
- package/dist/native/components/ion-segment.js.map +1 -0
- package/dist/native/components/ion-tab-bar.d.ts +11 -0
- package/dist/native/components/ion-tab-bar.d.ts.map +1 -0
- package/dist/native/components/ion-tab-bar.js +50 -0
- package/dist/native/components/ion-tab-bar.js.map +1 -0
- package/dist/native/components/searchable-tabs.d.ts +20 -0
- package/dist/native/components/searchable-tabs.d.ts.map +1 -0
- package/dist/native/components/searchable-tabs.js +413 -0
- package/dist/native/components/searchable-tabs.js.map +1 -0
- package/dist/native/definitions.d.ts +255 -0
- package/dist/native/definitions.d.ts.map +1 -0
- package/dist/native/definitions.js +0 -0
- package/dist/native/extensions.d.ts +31 -0
- package/dist/native/extensions.d.ts.map +1 -0
- package/dist/native/extensions.js +122 -0
- package/dist/native/extensions.js.map +1 -0
- package/dist/native/foldable/fold-state.d.ts +5 -0
- package/dist/native/foldable/fold-state.d.ts.map +1 -0
- package/dist/native/foldable/fold-state.js +15 -0
- package/dist/native/foldable/fold-state.js.map +1 -0
- package/dist/native/foldable/types.d.ts +12 -0
- package/dist/native/foldable/types.d.ts.map +1 -0
- package/dist/native/foldable/types.js +0 -0
- package/dist/native/html.d.ts +9 -0
- package/dist/native/html.d.ts.map +1 -0
- package/dist/native/html.js +188 -0
- package/dist/native/html.js.map +1 -0
- package/dist/native/index.d.ts +10 -0
- package/dist/native/index.d.ts.map +1 -0
- package/dist/native/index.js +28 -0
- package/dist/native/index.js.map +1 -0
- package/dist/native/legacy-layout.d.ts +5 -0
- package/dist/native/legacy-layout.d.ts.map +1 -0
- package/dist/native/legacy-layout.js +27 -0
- package/dist/native/legacy-layout.js.map +1 -0
- package/dist/native/overlays/content.d.ts +4 -0
- package/dist/native/overlays/content.d.ts.map +1 -0
- package/dist/native/overlays/content.js +51 -0
- package/dist/native/overlays/content.js.map +1 -0
- package/dist/native/overlays/controller.d.ts +8 -0
- package/dist/native/overlays/controller.d.ts.map +1 -0
- package/dist/native/overlays/controller.js +285 -0
- package/dist/native/overlays/controller.js.map +1 -0
- package/dist/native/overlays/dialog-animation.d.ts +9 -0
- package/dist/native/overlays/dialog-animation.d.ts.map +1 -0
- package/dist/native/overlays/dialog-animation.js +53 -0
- package/dist/native/overlays/dialog-animation.js.map +1 -0
- package/dist/native/overlays/dismiss-animation.d.ts +4 -0
- package/dist/native/overlays/dismiss-animation.d.ts.map +1 -0
- package/dist/native/overlays/dismiss-animation.js +18 -0
- package/dist/native/overlays/dismiss-animation.js.map +1 -0
- package/dist/native/overlays/focus.d.ts +5 -0
- package/dist/native/overlays/focus.d.ts.map +1 -0
- package/dist/native/overlays/focus.js +59 -0
- package/dist/native/overlays/focus.js.map +1 -0
- package/dist/native/overlays/popover.d.ts +12 -0
- package/dist/native/overlays/popover.d.ts.map +1 -0
- package/dist/native/overlays/popover.js +110 -0
- package/dist/native/overlays/popover.js.map +1 -0
- package/dist/native/overlays/styles.d.ts +11 -0
- package/dist/native/overlays/styles.d.ts.map +1 -0
- package/dist/native/overlays/styles.js +167 -0
- package/dist/native/overlays/styles.js.map +1 -0
- package/dist/native/prehide.d.ts +8 -0
- package/dist/native/prehide.d.ts.map +1 -0
- package/dist/native/prehide.js +238 -0
- package/dist/native/prehide.js.map +1 -0
- package/dist/native/runtime.d.ts +7 -0
- package/dist/native/runtime.d.ts.map +1 -0
- package/dist/native/runtime.js +788 -0
- package/dist/native/runtime.js.map +1 -0
- package/dist/native/shared/bridge.d.ts +6 -0
- package/dist/native/shared/bridge.d.ts.map +1 -0
- package/dist/native/shared/bridge.js +18 -0
- package/dist/native/shared/bridge.js.map +1 -0
- package/dist/native/shared/candidate.d.ts +25 -0
- package/dist/native/shared/candidate.d.ts.map +1 -0
- package/dist/native/shared/candidate.js +106 -0
- package/dist/native/shared/candidate.js.map +1 -0
- package/dist/native/shared/clipping.d.ts +5 -0
- package/dist/native/shared/clipping.d.ts.map +1 -0
- package/dist/native/shared/clipping.js +26 -0
- package/dist/native/shared/clipping.js.map +1 -0
- package/dist/native/shared/crossfade.d.ts +12 -0
- package/dist/native/shared/crossfade.d.ts.map +1 -0
- package/dist/native/shared/crossfade.js +67 -0
- package/dist/native/shared/crossfade.js.map +1 -0
- package/dist/native/shared/diagnostics.d.ts +4 -0
- package/dist/native/shared/diagnostics.d.ts.map +1 -0
- package/dist/native/shared/diagnostics.js +18 -0
- package/dist/native/shared/diagnostics.js.map +1 -0
- package/dist/native/shared/dom.d.ts +46 -0
- package/dist/native/shared/dom.d.ts.map +1 -0
- package/dist/native/shared/dom.js +180 -0
- package/dist/native/shared/dom.js.map +1 -0
- package/dist/native/shared/events.d.ts +15 -0
- package/dist/native/shared/events.d.ts.map +1 -0
- package/dist/native/shared/events.js +17 -0
- package/dist/native/shared/events.js.map +1 -0
- package/dist/native/shared/icons.d.ts +8 -0
- package/dist/native/shared/icons.d.ts.map +1 -0
- package/dist/native/shared/icons.js +61 -0
- package/dist/native/shared/icons.js.map +1 -0
- package/dist/native/shared/modal.d.ts +10 -0
- package/dist/native/shared/modal.d.ts.map +1 -0
- package/dist/native/shared/modal.js +160 -0
- package/dist/native/shared/modal.js.map +1 -0
- package/dist/native/shared/projection-id.d.ts +4 -0
- package/dist/native/shared/projection-id.d.ts.map +1 -0
- package/dist/native/shared/projection-id.js +7 -0
- package/dist/native/shared/projection-id.js.map +1 -0
- package/dist/native/shared/toolbar-options.d.ts +9 -0
- package/dist/native/shared/toolbar-options.d.ts.map +1 -0
- package/dist/native/shared/toolbar-options.js +36 -0
- package/dist/native/shared/toolbar-options.js.map +1 -0
- package/dist/native/shared/vertical-bars-geometry.d.ts +10 -0
- package/dist/native/shared/vertical-bars-geometry.d.ts.map +1 -0
- package/dist/native/shared/vertical-bars-geometry.js +85 -0
- package/dist/native/shared/vertical-bars-geometry.js.map +1 -0
- package/dist/native/startup.d.ts +8 -0
- package/dist/native/startup.d.ts.map +1 -0
- package/dist/native/startup.js +86 -0
- package/dist/native/startup.js.map +1 -0
- package/dist/native/vertical-bars-web-search.d.ts +10 -0
- package/dist/native/vertical-bars-web-search.d.ts.map +1 -0
- package/dist/native/vertical-bars-web-search.js +90 -0
- package/dist/native/vertical-bars-web-search.js.map +1 -0
- package/dist/native/vertical-bars-web.d.ts +5 -0
- package/dist/native/vertical-bars-web.d.ts.map +1 -0
- package/dist/native/vertical-bars-web.js +421 -0
- package/dist/native/vertical-bars-web.js.map +1 -0
- package/dist/native-integration/index.d.ts +25 -0
- package/dist/native-integration/index.d.ts.map +1 -0
- package/dist/native-integration/index.js +33 -0
- package/dist/native-integration/index.js.map +1 -0
- package/dist/vertical-bars.d.ts +6 -0
- package/dist/vertical-bars.js +5 -0
- package/docs/configuration.md +187 -0
- package/docs/framework-independent.md +82 -0
- package/docs/migration.md +206 -0
- package/docs/native-mini-player.md +47 -0
- package/docs/native-ui-extensions.md +365 -0
- package/docs/native-ui.md +409 -0
- package/docs/setup.md +205 -0
- package/docs/vertical-bars.md +379 -0
- package/ios/Sources/NativeUIPlugin/Components/NativeUIButton.swift +71 -0
- package/ios/Sources/NativeUIPlugin/Components/NativeUIButtons.swift +24 -0
- package/ios/Sources/NativeUIPlugin/Components/NativeUIComponents.swift +19 -0
- package/ios/Sources/NativeUIPlugin/Components/NativeUIFab.swift +80 -0
- package/ios/Sources/NativeUIPlugin/Components/NativeUISearchController.swift +439 -0
- package/ios/Sources/NativeUIPlugin/Components/NativeUISegment.swift +91 -0
- package/ios/Sources/NativeUIPlugin/Components/NativeUITabBar.swift +218 -0
- package/ios/Sources/NativeUIPlugin/Components/NativeUIVerticalBars.swift +590 -0
- package/ios/Sources/NativeUIPlugin/Components/NativeUIVerticalSearch.swift +118 -0
- package/ios/Sources/NativeUIPlugin/Extensions/NativeUI.swift +178 -0
- package/ios/Sources/NativeUIPlugin/Extensions/NativeUIRendering.swift +38 -0
- package/ios/Sources/NativeUIPlugin/NativeUIPlugin.swift +615 -0
- package/ios/Sources/NativeUIPlugin/Overlays/NativeUIOverlayController.swift +119 -0
- package/ios/Sources/NativeUIPlugin/Overlays/NativeUIOverlayHost.swift +75 -0
- package/ios/Sources/NativeUIPlugin/Shared/NativeUIControlRendering.swift +21 -0
- package/ios/Sources/NativeUIPlugin/Shared/NativeUICrossfade.swift +35 -0
- package/ios/Sources/NativeUIPlugin/Shared/NativeUIHost.swift +8 -0
- package/ios/Sources/NativeUIPlugin/Shared/NativeUISnapshot.swift +161 -0
- package/ios/Sources/NativeUIPlugin/Shared/NativeUIVerticalBarsGeometry.swift +52 -0
- package/ios/Tests/NativeUIPluginTests/NativeUIExtensionTests.swift +165 -0
- package/ios/Tests/NativeUIPluginTests/NativeUISnapshotTests.swift +805 -0
- package/package.json +89 -4
- package/src/core.ts +15 -0
- package/src/native/activation.ts +394 -0
- package/src/native/components/index.ts +45 -0
- package/src/native/components/ion-back-button.ts +22 -0
- package/src/native/components/ion-button.ts +25 -0
- package/src/native/components/ion-buttons.ts +37 -0
- package/src/native/components/ion-fab.ts +151 -0
- package/src/native/components/ion-menu-button.ts +37 -0
- package/src/native/components/ion-segment.ts +27 -0
- package/src/native/components/ion-tab-bar.ts +50 -0
- package/src/native/components/searchable-tabs.ts +499 -0
- package/src/native/definitions.ts +324 -0
- package/src/native/extensions.ts +176 -0
- package/src/native/foldable/fold-state.ts +10 -0
- package/src/native/foldable/types.ts +4 -0
- package/src/native/html.ts +193 -0
- package/src/native/index.ts +41 -0
- package/src/native/legacy-layout.ts +21 -0
- package/src/native/overlays/content.ts +51 -0
- package/src/native/overlays/controller.ts +349 -0
- package/src/native/overlays/dialog-animation.ts +53 -0
- package/src/native/overlays/dismiss-animation.ts +15 -0
- package/src/native/overlays/focus.ts +64 -0
- package/src/native/overlays/popover.ts +120 -0
- package/src/native/overlays/styles.ts +181 -0
- package/src/native/prehide.ts +285 -0
- package/src/native/runtime.ts +988 -0
- package/src/native/shared/bridge.ts +18 -0
- package/src/native/shared/candidate.ts +162 -0
- package/src/native/shared/clipping.ts +24 -0
- package/src/native/shared/crossfade.ts +67 -0
- package/src/native/shared/diagnostics.ts +13 -0
- package/src/native/shared/dom.ts +304 -0
- package/src/native/shared/events.ts +14 -0
- package/src/native/shared/icons.ts +57 -0
- package/src/native/shared/modal.ts +157 -0
- package/src/native/shared/projection-id.ts +2 -0
- package/src/native/shared/toolbar-options.ts +53 -0
- package/src/native/shared/vertical-bars-geometry.ts +80 -0
- package/src/native/startup.ts +84 -0
- package/src/native/vertical-bars-web-search.ts +86 -0
- package/src/native/vertical-bars-web.ts +498 -0
- package/src/native-integration/index.ts +49 -0
- package/src/vertical-bars.ts +11 -0
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
import { inVerticalBarsSurface, topModal } from "./shared/modal.js";
|
|
2
|
+
import { createCrossfade } from "./shared/crossfade.js";
|
|
3
|
+
import { activateProjectedElement, createVerticalBarsPageState, isExcluded, isNativeUIDisabled, isVerticalBarsToolbarGroup, marker, preferredVerticalBarsBack, prehiddenClass, prehideOnlyMutation, syncToolbarText, unprojected, verticalBarsActionCandidate, verticalBarsBackCandidate, verticalBarsEnteringPage, verticalBarsOwned, verticalBarsToolbarActions, withoutPrehide } from "./shared/dom.js";
|
|
4
|
+
import { VERTICAL_BARS_TRANSITION_CANCELED } from "../native-integration/index.js";
|
|
5
|
+
import { alignVerticalBarClone, verticalBarFrame } from "./shared/vertical-bars-geometry.js";
|
|
6
|
+
import { createVerticalBarsWebSearch, searchProjectionClass } from "./vertical-bars-web-search.js";
|
|
7
|
+
//#region src/native/vertical-bars-web.ts
|
|
8
|
+
const backProjectionClass = "ios-theme-vertical-bars-back-button-projection";
|
|
9
|
+
const toolbarProjectionClass = "ios-theme-vertical-bars-toolbar-projection";
|
|
10
|
+
const readyClass = "ios-theme-vertical-bars-toolbar-ready";
|
|
11
|
+
const toolbarControlSize = 46;
|
|
12
|
+
const toolbarControlGap = 10;
|
|
13
|
+
const createVerticalBarsWebProjection = (doc, options, enabled = () => true) => {
|
|
14
|
+
const win = doc.defaultView;
|
|
15
|
+
const crossfade = createCrossfade(win);
|
|
16
|
+
let incomingInstant;
|
|
17
|
+
const toolbarEnabled = options.controls === void 0 || options.controls.toolbar === true;
|
|
18
|
+
let root;
|
|
19
|
+
let backSource;
|
|
20
|
+
let backProjection;
|
|
21
|
+
let previousBackAriaHidden = null;
|
|
22
|
+
let toolbarProjections = [];
|
|
23
|
+
let suspended = 0;
|
|
24
|
+
let stopped = false;
|
|
25
|
+
let frame = 0;
|
|
26
|
+
let updates = 0;
|
|
27
|
+
let observingVerticalBars = false;
|
|
28
|
+
const verticalBarsPages = createVerticalBarsPageState();
|
|
29
|
+
let sourceObserver;
|
|
30
|
+
let waiters = [];
|
|
31
|
+
const listeners = new AbortController();
|
|
32
|
+
const verticalBarsRoot = () => doc.querySelector("ion-app.ios-theme-vertical-bars");
|
|
33
|
+
const projectedSources = () => [
|
|
34
|
+
backSource,
|
|
35
|
+
search.source,
|
|
36
|
+
...toolbarProjections.flatMap(({ actions }) => actions.map(({ source }) => source))
|
|
37
|
+
].filter((source) => !!source);
|
|
38
|
+
const isRendered = (element) => withoutPrehide(element, () => {
|
|
39
|
+
const style = getComputedStyle(element);
|
|
40
|
+
const rect = element.getBoundingClientRect();
|
|
41
|
+
return element.isConnected && style.display !== "none" && style.visibility === "visible" && rect.width > 0 && rect.height > 0;
|
|
42
|
+
});
|
|
43
|
+
const search = createVerticalBarsWebSearch(doc, (element) => (options.controls === void 0 || options.controls.tabs === true) && !!verticalBarsRoot()?.contains(element) && (!options.root || options.root.contains(element)) && !element.closest("[data-native-ui-placement=\"element\"]") && inVerticalBarsSurface(element) && !isExcluded(element, verticalBarsEnteringPage(element)) && !isNativeUIDisabled(element) && !verticalBarsPages.isDeparted(element) && isRendered(element), () => {
|
|
44
|
+
schedule();
|
|
45
|
+
});
|
|
46
|
+
const inEligibleToolbar = (element) => !!verticalBarsRoot()?.contains(element) && (!options.root || options.root.contains(element)) && !element.closest("[data-native-ui-placement=\"element\"]") && inVerticalBarsSurface(element) && verticalBarsActionCandidate(element) && !isExcluded(element, verticalBarsEnteringPage(element)) && !verticalBarsPages.isDeparted(element);
|
|
47
|
+
const isEligibleBack = (element) => !!verticalBarsRoot()?.contains(element) && (!options.root || options.root.contains(element)) && !element.closest("[data-native-ui-placement=\"element\"]") && inVerticalBarsSurface(element) && verticalBarsOwned(element) && verticalBarsBackCandidate(element) && !isExcluded(element, verticalBarsEnteringPage(element)) && !verticalBarsPages.isDeparted(element) && unprojected(projectedSources(), () => isRendered(element));
|
|
48
|
+
const pageOrder = (element) => Array.from(doc.querySelectorAll(".ion-page")).indexOf(element.closest(".ion-page"));
|
|
49
|
+
const findBack = () => {
|
|
50
|
+
const candidates = Array.from(doc.querySelectorAll(`ion-back-button:not(.${backProjectionClass})`)).filter(isEligibleBack);
|
|
51
|
+
return preferredVerticalBarsBack(candidates, doc);
|
|
52
|
+
};
|
|
53
|
+
const findToolbarGroups = () => {
|
|
54
|
+
const candidates = Array.from(doc.querySelectorAll(`ion-buttons:not(.${toolbarProjectionClass})`)).flatMap((group) => {
|
|
55
|
+
const actions = verticalBarsToolbarActions(group).filter((action) => unprojected(projectedSources(), () => isRendered(action)));
|
|
56
|
+
if (!actions.length) return [];
|
|
57
|
+
if (!isVerticalBarsToolbarGroup(group)) return actions.filter(inEligibleToolbar).map((action) => ({
|
|
58
|
+
group,
|
|
59
|
+
actions: [action]
|
|
60
|
+
}));
|
|
61
|
+
return inEligibleToolbar(group) && unprojected(projectedSources(), () => isRendered(group)) ? [{
|
|
62
|
+
group,
|
|
63
|
+
actions
|
|
64
|
+
}] : [];
|
|
65
|
+
});
|
|
66
|
+
for (const action of Array.from(doc.querySelectorAll("ion-button, ion-menu-button"))) {
|
|
67
|
+
if (action.closest("ion-buttons") || !verticalBarsOwned(action) || !inEligibleToolbar(action)) continue;
|
|
68
|
+
if (unprojected(projectedSources(), () => isRendered(action))) candidates.push({
|
|
69
|
+
group: action,
|
|
70
|
+
actions: [action]
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
const highestPage = Math.max(...candidates.map(({ group }) => pageOrder(group)));
|
|
74
|
+
return candidates.filter(({ group }) => pageOrder(group) === highestPage);
|
|
75
|
+
};
|
|
76
|
+
const isCurrentToolbarAction = (source) => findToolbarGroups().some(({ actions }) => actions.includes(source));
|
|
77
|
+
const restore = (retire) => {
|
|
78
|
+
search.restore(retire);
|
|
79
|
+
if (backProjection) {
|
|
80
|
+
if (retire) retire(backProjection);
|
|
81
|
+
else backProjection.remove();
|
|
82
|
+
}
|
|
83
|
+
backProjection = void 0;
|
|
84
|
+
if (backSource) {
|
|
85
|
+
backSource.removeAttribute(marker);
|
|
86
|
+
if (previousBackAriaHidden === null) backSource.removeAttribute("aria-hidden");
|
|
87
|
+
else backSource.setAttribute("aria-hidden", previousBackAriaHidden);
|
|
88
|
+
backSource.dispatchEvent(new CustomEvent("nativeUIChange"));
|
|
89
|
+
}
|
|
90
|
+
backSource = void 0;
|
|
91
|
+
previousBackAriaHidden = null;
|
|
92
|
+
for (const { projection, actions } of toolbarProjections) {
|
|
93
|
+
if (retire) retire(projection);
|
|
94
|
+
else projection.remove();
|
|
95
|
+
for (const { source, previousAriaHidden } of actions) {
|
|
96
|
+
source.removeAttribute(marker);
|
|
97
|
+
if (previousAriaHidden === null) source.removeAttribute("aria-hidden");
|
|
98
|
+
else source.setAttribute("aria-hidden", previousAriaHidden);
|
|
99
|
+
source.dispatchEvent(new CustomEvent("nativeUIChange"));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
toolbarProjections = [];
|
|
103
|
+
sourceObserver?.disconnect();
|
|
104
|
+
sourceObserver = void 0;
|
|
105
|
+
root?.classList.remove(readyClass);
|
|
106
|
+
root = void 0;
|
|
107
|
+
};
|
|
108
|
+
const copyAttributes = (target, original) => {
|
|
109
|
+
for (const name of [
|
|
110
|
+
"id",
|
|
111
|
+
"slot",
|
|
112
|
+
marker,
|
|
113
|
+
"aria-hidden"
|
|
114
|
+
]) target.removeAttribute(name);
|
|
115
|
+
for (const attribute of Array.from(target.attributes)) if (![
|
|
116
|
+
"class",
|
|
117
|
+
"data-native-ui-projected",
|
|
118
|
+
"data-native-ui-fading"
|
|
119
|
+
].includes(attribute.name) && !original.hasAttribute(attribute.name)) target.removeAttribute(attribute.name);
|
|
120
|
+
for (const attribute of Array.from(original.attributes)) if (![
|
|
121
|
+
"id",
|
|
122
|
+
"slot",
|
|
123
|
+
"data-native-ui-projected",
|
|
124
|
+
"aria-hidden"
|
|
125
|
+
].includes(attribute.name)) target.setAttribute(attribute.name, attribute.value);
|
|
126
|
+
target.classList.remove(prehiddenClass);
|
|
127
|
+
};
|
|
128
|
+
const syncBack = (target, original) => {
|
|
129
|
+
copyAttributes(target, original);
|
|
130
|
+
target.classList.add(backProjectionClass, "ion-cloned-element");
|
|
131
|
+
target.disabled = original.disabled;
|
|
132
|
+
target.defaultHref = original.defaultHref;
|
|
133
|
+
target.icon = original.icon;
|
|
134
|
+
target.color = original.color;
|
|
135
|
+
target.mode = original.mode;
|
|
136
|
+
target.text = "";
|
|
137
|
+
if (root) alignVerticalBarClone(target, original, root);
|
|
138
|
+
};
|
|
139
|
+
const syncAction = (target, original) => {
|
|
140
|
+
copyAttributes(target, original);
|
|
141
|
+
target.classList.add("ios-theme-vertical-bars-toolbar-action", "ion-cloned-element");
|
|
142
|
+
const label = original.getAttribute("aria-label") ?? original.shadowRoot?.querySelector("[part~=native]")?.getAttribute("aria-label") ?? original.textContent?.trim();
|
|
143
|
+
if (label) target.setAttribute("aria-label", label);
|
|
144
|
+
if ("disabled" in original) target.disabled = original.disabled;
|
|
145
|
+
if (original.matches("ion-button")) {
|
|
146
|
+
const clonedIcon = original.querySelector("ion-icon, svg")?.cloneNode(true);
|
|
147
|
+
clonedIcon?.setAttribute("slot", "icon-only");
|
|
148
|
+
target.replaceChildren(...clonedIcon ? [clonedIcon] : [document.createTextNode(original.textContent?.trim() || label || "")]);
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
const sameSources = (back, groups) => back === backSource && groups.length === toolbarProjections.length && groups.every(({ group, actions }, index) => {
|
|
152
|
+
const current = toolbarProjections[index];
|
|
153
|
+
return group === current.source && actions.length === current.actions.length && actions.every((action, actionIndex) => action === current.actions[actionIndex].source);
|
|
154
|
+
});
|
|
155
|
+
const syncExisting = () => {
|
|
156
|
+
if (backSource && backProjection) syncBack(backProjection, backSource);
|
|
157
|
+
let topOffset = backSource ? 56 : 0;
|
|
158
|
+
for (const { projection, source, actions } of toolbarProjections) {
|
|
159
|
+
if (actions.length === 1 && !projection.matches("ion-buttons")) syncAction(projection, actions[0].source);
|
|
160
|
+
else copyAttributes(projection, source);
|
|
161
|
+
projection.classList.add(toolbarProjectionClass, "ion-cloned-element");
|
|
162
|
+
projection.style.setProperty("--ios-theme-vertical-bars-toolbar-offset", `${topOffset}px`);
|
|
163
|
+
if (projection.matches("ion-buttons")) actions.forEach(({ source: action, projection: clone }) => syncAction(clone, action));
|
|
164
|
+
const frames = actions.map(({ source }) => verticalBarFrame(source));
|
|
165
|
+
if (root && frames.every((frame) => !!frame)) {
|
|
166
|
+
if (actions.length === 1) alignVerticalBarClone(projection, actions[0].source, root);
|
|
167
|
+
else {
|
|
168
|
+
const left = Math.min(...frames.map((frame) => frame.x));
|
|
169
|
+
const top = Math.min(...frames.map((frame) => frame.y));
|
|
170
|
+
const right = Math.max(...frames.map((frame) => frame.x + frame.width));
|
|
171
|
+
const bottom = Math.max(...frames.map((frame) => frame.y + frame.height));
|
|
172
|
+
const origin = root.getBoundingClientRect();
|
|
173
|
+
Object.assign(projection.style, {
|
|
174
|
+
left: `${left - origin.left}px`,
|
|
175
|
+
top: `${top - origin.top}px`,
|
|
176
|
+
right: "auto",
|
|
177
|
+
bottom: "auto",
|
|
178
|
+
width: `${right - left}px`,
|
|
179
|
+
height: `${bottom - top}px`,
|
|
180
|
+
padding: "0"
|
|
181
|
+
});
|
|
182
|
+
actions.forEach(({ source, projection: clone }) => alignVerticalBarClone(clone, source, projection));
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
topOffset += actions.length * toolbarControlSize + toolbarControlGap;
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
const project = (nextBack, groups) => {
|
|
189
|
+
root = topModal(doc) ?? verticalBarsRoot();
|
|
190
|
+
let topOffset = 0;
|
|
191
|
+
if (nextBack) {
|
|
192
|
+
backSource = nextBack;
|
|
193
|
+
previousBackAriaHidden = nextBack.getAttribute("aria-hidden");
|
|
194
|
+
backProjection = nextBack.cloneNode(false);
|
|
195
|
+
syncBack(backProjection, nextBack);
|
|
196
|
+
backProjection.addEventListener("click", (event) => {
|
|
197
|
+
event.preventDefault();
|
|
198
|
+
event.stopImmediatePropagation();
|
|
199
|
+
if (backSource && backSource === findBack()) activateProjectedElement(backSource);
|
|
200
|
+
}, { capture: true });
|
|
201
|
+
root.append(backProjection);
|
|
202
|
+
nextBack.setAttribute(marker, "");
|
|
203
|
+
nextBack.setAttribute("aria-hidden", "true");
|
|
204
|
+
nextBack.dispatchEvent(new CustomEvent("nativeUIChange"));
|
|
205
|
+
topOffset = 56;
|
|
206
|
+
}
|
|
207
|
+
for (const { group, actions: sources } of groups) {
|
|
208
|
+
const projection = (sources.length === 1 ? sources[0] : group).cloneNode(false);
|
|
209
|
+
if (sources.length === 1) syncAction(projection, sources[0]);
|
|
210
|
+
else copyAttributes(projection, group);
|
|
211
|
+
projection.classList.add(toolbarProjectionClass, "ion-cloned-element");
|
|
212
|
+
projection.style.setProperty("--ios-theme-vertical-bars-toolbar-offset", `${topOffset}px`);
|
|
213
|
+
const actions = sources.map((source) => {
|
|
214
|
+
const clone = sources.length === 1 ? projection : source.cloneNode(false);
|
|
215
|
+
if (sources.length > 1) syncAction(clone, source);
|
|
216
|
+
clone.addEventListener("click", (event) => {
|
|
217
|
+
event.preventDefault();
|
|
218
|
+
event.stopImmediatePropagation();
|
|
219
|
+
if (isCurrentToolbarAction(source)) activateProjectedElement(source);
|
|
220
|
+
}, { capture: true });
|
|
221
|
+
if (sources.length > 1) projection.append(clone);
|
|
222
|
+
const previousAriaHidden = source.getAttribute("aria-hidden");
|
|
223
|
+
source.setAttribute(marker, "");
|
|
224
|
+
source.setAttribute("aria-hidden", "true");
|
|
225
|
+
source.dispatchEvent(new CustomEvent("nativeUIChange"));
|
|
226
|
+
return {
|
|
227
|
+
source,
|
|
228
|
+
projection: clone,
|
|
229
|
+
previousAriaHidden
|
|
230
|
+
};
|
|
231
|
+
});
|
|
232
|
+
root.append(projection);
|
|
233
|
+
toolbarProjections.push({
|
|
234
|
+
source: group,
|
|
235
|
+
projection,
|
|
236
|
+
actions
|
|
237
|
+
});
|
|
238
|
+
topOffset += actions.length * toolbarControlSize + toolbarControlGap;
|
|
239
|
+
}
|
|
240
|
+
syncExisting();
|
|
241
|
+
if (nextBack || toolbarProjections.length) root.classList.add(readyClass);
|
|
242
|
+
sourceObserver = new MutationObserver((records) => {
|
|
243
|
+
if (records.some((record) => record.type !== "attributes" || !["data-native-ui-projected", "aria-hidden"].includes(record.attributeName ?? "") && !prehideOnlyMutation(record))) schedule();
|
|
244
|
+
});
|
|
245
|
+
if (nextBack?.shadowRoot) sourceObserver.observe(nextBack.shadowRoot, {
|
|
246
|
+
subtree: true,
|
|
247
|
+
childList: true,
|
|
248
|
+
attributes: true,
|
|
249
|
+
attributeOldValue: true
|
|
250
|
+
});
|
|
251
|
+
for (const { group } of groups) sourceObserver.observe(group, {
|
|
252
|
+
subtree: true,
|
|
253
|
+
childList: true,
|
|
254
|
+
attributes: true,
|
|
255
|
+
attributeOldValue: true
|
|
256
|
+
});
|
|
257
|
+
};
|
|
258
|
+
const reveal = () => {
|
|
259
|
+
if (incomingInstant === void 0) return;
|
|
260
|
+
for (const surface of [
|
|
261
|
+
backProjection,
|
|
262
|
+
...toolbarProjections.map(({ projection }) => projection),
|
|
263
|
+
search.surface
|
|
264
|
+
]) if (surface) crossfade.play(surface, false, incomingInstant);
|
|
265
|
+
incomingInstant = void 0;
|
|
266
|
+
};
|
|
267
|
+
const performUpdate = () => {
|
|
268
|
+
frame = 0;
|
|
269
|
+
syncToolbarText(doc);
|
|
270
|
+
const currentRoot = verticalBarsRoot();
|
|
271
|
+
if (observingVerticalBars !== !!currentRoot) {
|
|
272
|
+
observingVerticalBars = !!currentRoot;
|
|
273
|
+
observer.disconnect();
|
|
274
|
+
observer.observe(doc.documentElement, {
|
|
275
|
+
subtree: true,
|
|
276
|
+
childList: true,
|
|
277
|
+
characterData: observingVerticalBars,
|
|
278
|
+
attributes: true,
|
|
279
|
+
attributeOldValue: true,
|
|
280
|
+
attributeFilter: observingVerticalBars ? void 0 : ["class"]
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
if (stopped || suspended || !currentRoot || !enabled()) return restore();
|
|
284
|
+
const nextBack = toolbarEnabled ? findBack() : void 0;
|
|
285
|
+
const groups = toolbarEnabled ? findToolbarGroups() : [];
|
|
286
|
+
const projectionRoot = topModal(doc) ?? currentRoot;
|
|
287
|
+
search.update(projectionRoot);
|
|
288
|
+
if (!nextBack && !groups.length && !search.source) return restore();
|
|
289
|
+
if (root === (topModal(doc) ?? currentRoot) && sameSources(nextBack, groups)) {
|
|
290
|
+
syncExisting();
|
|
291
|
+
reveal();
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
restore();
|
|
295
|
+
project(nextBack, groups);
|
|
296
|
+
search.update(projectionRoot);
|
|
297
|
+
reveal();
|
|
298
|
+
updates++;
|
|
299
|
+
};
|
|
300
|
+
const update = () => {
|
|
301
|
+
try {
|
|
302
|
+
performUpdate();
|
|
303
|
+
} catch {
|
|
304
|
+
restore();
|
|
305
|
+
} finally {
|
|
306
|
+
const pending = waiters;
|
|
307
|
+
waiters = [];
|
|
308
|
+
pending.forEach((resolve) => resolve());
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
const schedule = () => {
|
|
312
|
+
if (stopped) return Promise.resolve();
|
|
313
|
+
if (!enabled()) restore();
|
|
314
|
+
const done = new Promise((resolve) => waiters.push(resolve));
|
|
315
|
+
if (!frame) frame = win.requestAnimationFrame(update);
|
|
316
|
+
return done;
|
|
317
|
+
};
|
|
318
|
+
const observer = new MutationObserver((records) => {
|
|
319
|
+
const insideProjection = (target) => {
|
|
320
|
+
const element = target instanceof Element ? target : target.parentNode instanceof Element ? target.parentNode : void 0;
|
|
321
|
+
const rootNode = target.getRootNode();
|
|
322
|
+
return !![element, rootNode instanceof ShadowRoot ? rootNode.host : void 0].some((candidate) => candidate?.closest(`.${backProjectionClass}, .${toolbarProjectionClass}, .${searchProjectionClass}`));
|
|
323
|
+
};
|
|
324
|
+
const verticalBarsChanged = records.some((record) => record.type === "attributes" && record.target.matches("ion-app") || record.type === "childList" && Array.from(record.addedNodes).some((node) => node instanceof Element && (node.matches("ion-app.ios-theme-vertical-bars") || !!node.querySelector("ion-app.ios-theme-vertical-bars"))));
|
|
325
|
+
if (observingVerticalBars && records.some((record) => record.attributeName !== "data-native-ui-projected" && record.attributeName !== "data-native-ui-toolbar-text" && !prehideOnlyMutation(record) && !insideProjection(record.target)) || !observingVerticalBars && verticalBarsChanged && records.some((record) => !prehideOnlyMutation(record))) schedule();
|
|
326
|
+
});
|
|
327
|
+
observer.observe(doc.documentElement, {
|
|
328
|
+
subtree: true,
|
|
329
|
+
childList: true,
|
|
330
|
+
attributes: true,
|
|
331
|
+
attributeOldValue: true,
|
|
332
|
+
attributeFilter: ["class"]
|
|
333
|
+
});
|
|
334
|
+
const pageLifecycle = (event) => {
|
|
335
|
+
const page = event.target;
|
|
336
|
+
if (!(page instanceof HTMLElement) || !page.matches(".ion-page")) return;
|
|
337
|
+
if (event.type === "iosThemeVerticalBarsTransitionCanceled") {
|
|
338
|
+
const entering = event.detail?.entering;
|
|
339
|
+
verticalBarsPages.cancel(entering, page);
|
|
340
|
+
} else verticalBarsPages.lifecycle(event);
|
|
341
|
+
if (verticalBarsRoot()) schedule();
|
|
342
|
+
};
|
|
343
|
+
for (const name of [
|
|
344
|
+
"ionViewWillEnter",
|
|
345
|
+
"ionViewWillLeave",
|
|
346
|
+
"ionViewDidEnter",
|
|
347
|
+
"ionViewDidLeave"
|
|
348
|
+
]) doc.addEventListener(name, pageLifecycle, {
|
|
349
|
+
capture: true,
|
|
350
|
+
signal: listeners.signal
|
|
351
|
+
});
|
|
352
|
+
doc.addEventListener(VERTICAL_BARS_TRANSITION_CANCELED, pageLifecycle, {
|
|
353
|
+
capture: true,
|
|
354
|
+
signal: listeners.signal
|
|
355
|
+
});
|
|
356
|
+
for (const name of ["ionModalWillPresent", "ionModalDidDismiss"]) doc.addEventListener(name, schedule, {
|
|
357
|
+
capture: true,
|
|
358
|
+
signal: listeners.signal
|
|
359
|
+
});
|
|
360
|
+
win.addEventListener("nativeUIVerticalBarsAcquire", (event) => {
|
|
361
|
+
const instant = event.detail?.instant ?? true;
|
|
362
|
+
incomingInstant = void 0;
|
|
363
|
+
restore((surface) => {
|
|
364
|
+
const box = surface.getBoundingClientRect();
|
|
365
|
+
surface.style.setProperty("position", "fixed", "important");
|
|
366
|
+
surface.style.setProperty("display", "block", "important");
|
|
367
|
+
surface.style.setProperty("left", `${box.left}px`, "important");
|
|
368
|
+
surface.style.setProperty("top", `${box.top}px`, "important");
|
|
369
|
+
surface.style.setProperty("right", "auto", "important");
|
|
370
|
+
surface.style.setProperty("bottom", "auto", "important");
|
|
371
|
+
surface.style.setProperty("width", `${box.width}px`, "important");
|
|
372
|
+
surface.style.setProperty("height", `${box.height}px`, "important");
|
|
373
|
+
crossfade.retire(surface, instant);
|
|
374
|
+
});
|
|
375
|
+
}, { signal: listeners.signal });
|
|
376
|
+
win.addEventListener("nativeUIVerticalBarsRelease", (event) => {
|
|
377
|
+
incomingInstant = event.detail.instant;
|
|
378
|
+
schedule();
|
|
379
|
+
}, { signal: listeners.signal });
|
|
380
|
+
win.addEventListener("resize", schedule, { signal: listeners.signal });
|
|
381
|
+
win.addEventListener("nativeUIRefresh", schedule, { signal: listeners.signal });
|
|
382
|
+
schedule();
|
|
383
|
+
return {
|
|
384
|
+
markForCheck: () => {
|
|
385
|
+
schedule();
|
|
386
|
+
},
|
|
387
|
+
getStatus: () => ({
|
|
388
|
+
state: stopped ? "stopped" : "web",
|
|
389
|
+
projected: Number(!!backSource) + Number(!!search.source) + toolbarProjections.reduce((count, group) => count + group.actions.length, 0),
|
|
390
|
+
updates
|
|
391
|
+
}),
|
|
392
|
+
async suspend() {
|
|
393
|
+
suspended++;
|
|
394
|
+
restore();
|
|
395
|
+
let resumed = false;
|
|
396
|
+
return { async resume() {
|
|
397
|
+
if (resumed) return;
|
|
398
|
+
resumed = true;
|
|
399
|
+
suspended = Math.max(0, suspended - 1);
|
|
400
|
+
if (!suspended) await schedule();
|
|
401
|
+
} };
|
|
402
|
+
},
|
|
403
|
+
async destroy() {
|
|
404
|
+
if (stopped) return;
|
|
405
|
+
stopped = true;
|
|
406
|
+
win.cancelAnimationFrame(frame);
|
|
407
|
+
frame = 0;
|
|
408
|
+
waiters.forEach((resolve) => resolve());
|
|
409
|
+
waiters = [];
|
|
410
|
+
observer.disconnect();
|
|
411
|
+
sourceObserver?.disconnect();
|
|
412
|
+
listeners.abort();
|
|
413
|
+
crossfade.destroy();
|
|
414
|
+
restore();
|
|
415
|
+
}
|
|
416
|
+
};
|
|
417
|
+
};
|
|
418
|
+
//#endregion
|
|
419
|
+
export { createVerticalBarsWebProjection };
|
|
420
|
+
|
|
421
|
+
//# sourceMappingURL=vertical-bars-web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vertical-bars-web.js","names":[],"sources":["../../src/native/vertical-bars-web.ts"],"sourcesContent":["import { createCrossfade, fadeMarker } from './shared/crossfade';\nimport { alignVerticalBarClone, verticalBarFrame } from './shared/vertical-bars-geometry';\nimport { createVerticalBarsWebSearch, searchProjectionClass } from './vertical-bars-web-search';\nimport { inVerticalBarsSurface, topModal } from './shared/modal';\nimport type { NativeUIRuntimeHandle, NativeUIOptions, NativeUIStatus } from './definitions';\nimport { VERTICAL_BARS_TRANSITION_CANCELED } from '../native-integration';\nimport {\n activateProjectedElement,\n createVerticalBarsPageState,\n verticalBarsActionCandidate,\n verticalBarsBackCandidate,\n verticalBarsEnteringPage,\n verticalBarsToolbarActions,\n isExcluded,\n isNativeUIDisabled,\n isVerticalBarsToolbarGroup,\n preferredVerticalBarsBack,\n verticalBarsOwned,\n marker,\n syncToolbarText,\n toolbarTextMarker,\n prehideOnlyMutation,\n prehiddenClass,\n unprojected,\n withoutPrehide,\n} from './shared/dom';\n\nconst backProjectionClass = 'ios-theme-vertical-bars-back-button-projection';\nconst toolbarProjectionClass = 'ios-theme-vertical-bars-toolbar-projection';\nconst readyClass = 'ios-theme-vertical-bars-toolbar-ready';\nconst toolbarControlSize = 46;\nconst toolbarControlGap = 10;\n\ninterface ToolbarProjection {\n source: HTMLElement;\n projection: HTMLElement;\n actions: { source: HTMLElement; projection: HTMLElement; previousAriaHidden: string | null }[];\n}\n\ninterface ToolbarSource {\n group: HTMLElement;\n actions: HTMLElement[];\n}\n\nexport const createVerticalBarsWebProjection = (\n doc: Document,\n options: NativeUIOptions,\n enabled: () => boolean = () => true,\n): NativeUIRuntimeHandle => {\n const win = doc.defaultView!;\n const crossfade = createCrossfade(win);\n let incomingInstant: boolean | undefined;\n const toolbarEnabled = options.controls === undefined || options.controls.toolbar === true;\n let root: HTMLElement | undefined;\n let backSource: HTMLIonBackButtonElement | undefined;\n let backProjection: HTMLIonBackButtonElement | undefined;\n let previousBackAriaHidden: string | null = null;\n let toolbarProjections: ToolbarProjection[] = [];\n let suspended = 0;\n let stopped = false;\n let frame = 0;\n let updates = 0;\n let observingVerticalBars = false;\n const verticalBarsPages = createVerticalBarsPageState();\n let sourceObserver: MutationObserver | undefined;\n let waiters: (() => void)[] = [];\n const listeners = new AbortController();\n const verticalBarsRoot = () => doc.querySelector<HTMLElement>('ion-app.ios-theme-vertical-bars');\n const projectedSources = () =>\n [backSource, search.source, ...toolbarProjections.flatMap(({ actions }) => actions.map(({ source }) => source))].filter(\n (source): source is HTMLElement => !!source,\n );\n const isRendered = (element: HTMLElement) =>\n withoutPrehide(element, () => {\n const style = getComputedStyle(element);\n const rect = element.getBoundingClientRect();\n return element.isConnected && style.display !== 'none' && style.visibility === 'visible' && rect.width > 0 && rect.height > 0;\n });\n const search = createVerticalBarsWebSearch(\n doc,\n (element) =>\n (options.controls === undefined || options.controls.tabs === true) &&\n !!verticalBarsRoot()?.contains(element) &&\n (!options.root || options.root.contains(element)) &&\n !element.closest('[data-native-ui-placement=\"element\"]') &&\n inVerticalBarsSurface(element) &&\n !isExcluded(element, verticalBarsEnteringPage(element)) &&\n !isNativeUIDisabled(element) &&\n !verticalBarsPages.isDeparted(element) &&\n isRendered(element),\n () => {\n void schedule();\n },\n );\n const inEligibleToolbar = (element: HTMLElement) =>\n !!verticalBarsRoot()?.contains(element) &&\n (!options.root || options.root.contains(element)) &&\n !element.closest('[data-native-ui-placement=\"element\"]') &&\n inVerticalBarsSurface(element) &&\n verticalBarsActionCandidate(element) &&\n !isExcluded(element, verticalBarsEnteringPage(element)) &&\n !verticalBarsPages.isDeparted(element);\n const isEligibleBack = (element: HTMLIonBackButtonElement) =>\n !!verticalBarsRoot()?.contains(element) &&\n (!options.root || options.root.contains(element)) &&\n !element.closest('[data-native-ui-placement=\"element\"]') &&\n inVerticalBarsSurface(element) &&\n verticalBarsOwned(element) &&\n verticalBarsBackCandidate(element) &&\n !isExcluded(element, verticalBarsEnteringPage(element)) &&\n !verticalBarsPages.isDeparted(element) &&\n unprojected(projectedSources(), () => isRendered(element));\n const pageOrder = (element: Element) => Array.from(doc.querySelectorAll('.ion-page')).indexOf(element.closest('.ion-page')!);\n const findBack = () => {\n const candidates = Array.from(doc.querySelectorAll<HTMLIonBackButtonElement>(`ion-back-button:not(.${backProjectionClass})`)).filter(\n isEligibleBack,\n );\n return preferredVerticalBarsBack(candidates, doc);\n };\n const findToolbarGroups = () => {\n const candidates = Array.from(doc.querySelectorAll<HTMLIonButtonsElement>(`ion-buttons:not(.${toolbarProjectionClass})`)).flatMap(\n (group): ToolbarSource[] => {\n const actions = verticalBarsToolbarActions(group).filter((action) => unprojected(projectedSources(), () => isRendered(action)));\n if (!actions.length) return [];\n if (!isVerticalBarsToolbarGroup(group)) return actions.filter(inEligibleToolbar).map((action) => ({ group, actions: [action] }));\n return inEligibleToolbar(group) && unprojected(projectedSources(), () => isRendered(group)) ? [{ group, actions }] : [];\n },\n );\n for (const action of Array.from(doc.querySelectorAll<HTMLElement>('ion-button, ion-menu-button'))) {\n if (action.closest('ion-buttons') || !verticalBarsOwned(action) || !inEligibleToolbar(action)) continue;\n if (unprojected(projectedSources(), () => isRendered(action))) candidates.push({ group: action, actions: [action] });\n }\n const highestPage = Math.max(...candidates.map(({ group }) => pageOrder(group)));\n return candidates.filter(({ group }) => pageOrder(group) === highestPage);\n };\n const isCurrentToolbarAction = (source: HTMLElement) => findToolbarGroups().some(({ actions }) => actions.includes(source));\n const restore = (retire?: (surface: HTMLElement) => void) => {\n search.restore(retire);\n if (backProjection) {\n if (retire) retire(backProjection);\n else backProjection.remove();\n }\n backProjection = undefined;\n if (backSource) {\n backSource.removeAttribute(marker);\n if (previousBackAriaHidden === null) backSource.removeAttribute('aria-hidden');\n else backSource.setAttribute('aria-hidden', previousBackAriaHidden);\n backSource.dispatchEvent(new CustomEvent('nativeUIChange'));\n }\n backSource = undefined;\n previousBackAriaHidden = null;\n for (const { projection, actions } of toolbarProjections) {\n if (retire) retire(projection);\n else projection.remove();\n for (const { source, previousAriaHidden } of actions) {\n source.removeAttribute(marker);\n if (previousAriaHidden === null) source.removeAttribute('aria-hidden');\n else source.setAttribute('aria-hidden', previousAriaHidden);\n source.dispatchEvent(new CustomEvent('nativeUIChange'));\n }\n }\n toolbarProjections = [];\n sourceObserver?.disconnect();\n sourceObserver = undefined;\n root?.classList.remove(readyClass);\n root = undefined;\n };\n const copyAttributes = (target: HTMLElement, original: HTMLElement) => {\n for (const name of ['id', 'slot', marker, 'aria-hidden']) target.removeAttribute(name);\n for (const attribute of Array.from(target.attributes))\n if (!['class', marker, fadeMarker].includes(attribute.name) && !original.hasAttribute(attribute.name))\n target.removeAttribute(attribute.name);\n for (const attribute of Array.from(original.attributes))\n if (!['id', 'slot', marker, 'aria-hidden'].includes(attribute.name)) target.setAttribute(attribute.name, attribute.value);\n target.classList.remove(prehiddenClass);\n };\n const syncBack = (target: HTMLIonBackButtonElement, original: HTMLIonBackButtonElement) => {\n copyAttributes(target, original);\n target.classList.add(backProjectionClass, 'ion-cloned-element');\n target.disabled = original.disabled;\n target.defaultHref = original.defaultHref;\n target.icon = original.icon;\n target.color = original.color;\n target.mode = original.mode;\n target.text = '';\n if (root) alignVerticalBarClone(target, original, root);\n };\n const syncAction = (target: HTMLElement, original: HTMLElement) => {\n copyAttributes(target, original);\n target.classList.add('ios-theme-vertical-bars-toolbar-action', 'ion-cloned-element');\n const label =\n original.getAttribute('aria-label') ??\n original.shadowRoot?.querySelector('[part~=native]')?.getAttribute('aria-label') ??\n original.textContent?.trim();\n if (label) target.setAttribute('aria-label', label);\n if ('disabled' in original) (target as HTMLIonButtonElement).disabled = (original as HTMLIonButtonElement).disabled;\n if (original.matches('ion-button')) {\n const icon = original.querySelector<HTMLElement>('ion-icon, svg');\n const clonedIcon = icon?.cloneNode(true) as HTMLElement | undefined;\n clonedIcon?.setAttribute('slot', 'icon-only');\n target.replaceChildren(...(clonedIcon ? [clonedIcon] : [document.createTextNode(original.textContent?.trim() || label || '')]));\n }\n };\n const sameSources = (back: HTMLIonBackButtonElement | undefined, groups: ToolbarSource[]) =>\n back === backSource &&\n groups.length === toolbarProjections.length &&\n groups.every(({ group, actions }, index) => {\n const current = toolbarProjections[index];\n return (\n group === current.source &&\n actions.length === current.actions.length &&\n actions.every((action, actionIndex) => action === current.actions[actionIndex].source)\n );\n });\n const syncExisting = () => {\n if (backSource && backProjection) syncBack(backProjection, backSource);\n let topOffset = backSource ? toolbarControlSize + toolbarControlGap : 0;\n for (const { projection, source, actions } of toolbarProjections) {\n if (actions.length === 1 && !projection.matches('ion-buttons')) syncAction(projection, actions[0].source);\n else copyAttributes(projection, source);\n projection.classList.add(toolbarProjectionClass, 'ion-cloned-element');\n projection.style.setProperty('--ios-theme-vertical-bars-toolbar-offset', `${topOffset}px`);\n if (projection.matches('ion-buttons')) actions.forEach(({ source: action, projection: clone }) => syncAction(clone, action));\n const frames = actions.map(({ source }) => verticalBarFrame(source));\n if (root && frames.every((frame) => !!frame)) {\n if (actions.length === 1) alignVerticalBarClone(projection, actions[0].source, root);\n else {\n const left = Math.min(...frames.map((frame) => frame!.x));\n const top = Math.min(...frames.map((frame) => frame!.y));\n const right = Math.max(...frames.map((frame) => frame!.x + frame!.width));\n const bottom = Math.max(...frames.map((frame) => frame!.y + frame!.height));\n const origin = root.getBoundingClientRect();\n Object.assign(projection.style, {\n left: `${left - origin.left}px`,\n top: `${top - origin.top}px`,\n right: 'auto',\n bottom: 'auto',\n width: `${right - left}px`,\n height: `${bottom - top}px`,\n padding: '0',\n });\n actions.forEach(({ source, projection: clone }) => alignVerticalBarClone(clone, source, projection));\n }\n }\n topOffset += actions.length * toolbarControlSize + toolbarControlGap;\n }\n };\n const project = (nextBack: HTMLIonBackButtonElement | undefined, groups: ToolbarSource[]) => {\n root = topModal(doc) ?? verticalBarsRoot()!;\n let topOffset = 0;\n if (nextBack) {\n backSource = nextBack;\n previousBackAriaHidden = nextBack.getAttribute('aria-hidden');\n backProjection = nextBack.cloneNode(false) as HTMLIonBackButtonElement;\n syncBack(backProjection, nextBack);\n backProjection.addEventListener(\n 'click',\n (event) => {\n event.preventDefault();\n event.stopImmediatePropagation();\n if (backSource && backSource === findBack()) activateProjectedElement(backSource);\n },\n { capture: true },\n );\n root.append(backProjection);\n nextBack.setAttribute(marker, '');\n nextBack.setAttribute('aria-hidden', 'true');\n nextBack.dispatchEvent(new CustomEvent('nativeUIChange'));\n topOffset = toolbarControlSize + toolbarControlGap;\n }\n for (const { group, actions: sources } of groups) {\n const projection = (sources.length === 1 ? sources[0] : group).cloneNode(false) as HTMLElement;\n if (sources.length === 1) syncAction(projection, sources[0]);\n else copyAttributes(projection, group);\n projection.classList.add(toolbarProjectionClass, 'ion-cloned-element');\n projection.style.setProperty('--ios-theme-vertical-bars-toolbar-offset', `${topOffset}px`);\n const actions = sources.map((source) => {\n const clone = sources.length === 1 ? projection : (source.cloneNode(false) as HTMLElement);\n if (sources.length > 1) syncAction(clone, source);\n clone.addEventListener(\n 'click',\n (event) => {\n event.preventDefault();\n event.stopImmediatePropagation();\n if (isCurrentToolbarAction(source)) activateProjectedElement(source);\n },\n { capture: true },\n );\n if (sources.length > 1) projection.append(clone);\n const previousAriaHidden = source.getAttribute('aria-hidden');\n source.setAttribute(marker, '');\n source.setAttribute('aria-hidden', 'true');\n source.dispatchEvent(new CustomEvent('nativeUIChange'));\n return { source, projection: clone, previousAriaHidden };\n });\n root.append(projection);\n toolbarProjections.push({ source: group, projection, actions });\n topOffset += actions.length * toolbarControlSize + toolbarControlGap;\n }\n syncExisting();\n if (nextBack || toolbarProjections.length) root.classList.add(readyClass);\n sourceObserver = new MutationObserver((records) => {\n if (\n records.some(\n (record) =>\n record.type !== 'attributes' || (![marker, 'aria-hidden'].includes(record.attributeName ?? '') && !prehideOnlyMutation(record)),\n )\n )\n schedule();\n });\n if (nextBack?.shadowRoot)\n sourceObserver.observe(nextBack.shadowRoot, { subtree: true, childList: true, attributes: true, attributeOldValue: true });\n for (const { group } of groups)\n sourceObserver.observe(group, { subtree: true, childList: true, attributes: true, attributeOldValue: true });\n };\n const reveal = () => {\n if (incomingInstant === undefined) return;\n for (const surface of [backProjection, ...toolbarProjections.map(({ projection }) => projection), search.surface])\n if (surface) crossfade.play(surface, false, incomingInstant);\n incomingInstant = undefined;\n };\n const performUpdate = () => {\n frame = 0;\n syncToolbarText(doc);\n const currentRoot = verticalBarsRoot();\n if (observingVerticalBars !== !!currentRoot) {\n observingVerticalBars = !!currentRoot;\n observer.disconnect();\n observer.observe(doc.documentElement, {\n subtree: true,\n childList: true,\n characterData: observingVerticalBars,\n attributes: true,\n attributeOldValue: true,\n attributeFilter: observingVerticalBars ? undefined : ['class'],\n });\n }\n if (stopped || suspended || !currentRoot || !enabled()) return restore();\n const nextBack = toolbarEnabled ? findBack() : undefined;\n const groups = toolbarEnabled ? findToolbarGroups() : [];\n const projectionRoot = topModal(doc) ?? currentRoot;\n search.update(projectionRoot);\n if (!nextBack && !groups.length && !search.source) return restore();\n if (root === (topModal(doc) ?? currentRoot) && sameSources(nextBack, groups)) {\n syncExisting();\n reveal();\n return;\n }\n restore();\n project(nextBack, groups);\n search.update(projectionRoot);\n reveal();\n updates++;\n };\n const update = () => {\n try {\n performUpdate();\n } catch {\n restore();\n } finally {\n const pending = waiters;\n waiters = [];\n pending.forEach((resolve) => resolve());\n }\n };\n const schedule = (): Promise<void> => {\n if (stopped) return Promise.resolve();\n // Release Web ownership before the native runtime can acknowledge its next frame.\n if (!enabled()) restore();\n const done = new Promise<void>((resolve) => waiters.push(resolve));\n if (!frame) frame = win.requestAnimationFrame(update);\n return done;\n };\n const observer = new MutationObserver((records) => {\n const insideProjection = (target: Node) => {\n const element = target instanceof Element ? target : target.parentNode instanceof Element ? target.parentNode : undefined;\n const rootNode = target.getRootNode();\n const shadowHost = rootNode instanceof ShadowRoot ? rootNode.host : undefined;\n return !![element, shadowHost].some((candidate) =>\n candidate?.closest(`.${backProjectionClass}, .${toolbarProjectionClass}, .${searchProjectionClass}`),\n );\n };\n const verticalBarsChanged = records.some(\n (record) =>\n (record.type === 'attributes' && (record.target as Element).matches('ion-app')) ||\n (record.type === 'childList' &&\n Array.from(record.addedNodes).some(\n (node) =>\n node instanceof Element &&\n (node.matches('ion-app.ios-theme-vertical-bars') || !!node.querySelector('ion-app.ios-theme-vertical-bars')),\n )),\n );\n if (\n (observingVerticalBars &&\n records.some(\n (record) =>\n record.attributeName !== marker &&\n record.attributeName !== toolbarTextMarker &&\n !prehideOnlyMutation(record) &&\n !insideProjection(record.target),\n )) ||\n (!observingVerticalBars && verticalBarsChanged && records.some((record) => !prehideOnlyMutation(record)))\n )\n schedule();\n });\n observer.observe(doc.documentElement, {\n subtree: true,\n childList: true,\n attributes: true,\n attributeOldValue: true,\n attributeFilter: ['class'],\n });\n const pageLifecycle = (event: Event) => {\n const page = event.target;\n if (!(page instanceof HTMLElement) || !page.matches('.ion-page')) return;\n if (event.type === VERTICAL_BARS_TRANSITION_CANCELED) {\n const entering = (event as CustomEvent<{ entering?: HTMLElement }>).detail?.entering;\n verticalBarsPages.cancel(entering, page);\n } else verticalBarsPages.lifecycle(event);\n if (verticalBarsRoot()) schedule();\n };\n for (const name of ['ionViewWillEnter', 'ionViewWillLeave', 'ionViewDidEnter', 'ionViewDidLeave'])\n doc.addEventListener(name, pageLifecycle, { capture: true, signal: listeners.signal });\n doc.addEventListener(VERTICAL_BARS_TRANSITION_CANCELED, pageLifecycle, { capture: true, signal: listeners.signal });\n for (const name of ['ionModalWillPresent', 'ionModalDidDismiss'])\n doc.addEventListener(name, schedule, { capture: true, signal: listeners.signal });\n win.addEventListener(\n 'nativeUIVerticalBarsAcquire',\n (event) => {\n const instant = (event as CustomEvent<{ instant: boolean }>).detail?.instant ?? true;\n incomingInstant = undefined;\n restore((surface) => {\n // Keep only the outgoing visual at its last rectangle after Web ownership\n // is released. The native acknowledgement transfers input exactly once.\n const box = surface.getBoundingClientRect();\n surface.style.setProperty('position', 'fixed', 'important');\n surface.style.setProperty('display', 'block', 'important');\n surface.style.setProperty('left', `${box.left}px`, 'important');\n surface.style.setProperty('top', `${box.top}px`, 'important');\n surface.style.setProperty('right', 'auto', 'important');\n surface.style.setProperty('bottom', 'auto', 'important');\n surface.style.setProperty('width', `${box.width}px`, 'important');\n surface.style.setProperty('height', `${box.height}px`, 'important');\n crossfade.retire(surface, instant);\n });\n },\n { signal: listeners.signal },\n );\n win.addEventListener(\n 'nativeUIVerticalBarsRelease',\n (event) => {\n incomingInstant = (event as CustomEvent<{ instant: boolean }>).detail.instant;\n void schedule();\n },\n { signal: listeners.signal },\n );\n win.addEventListener('resize', schedule, { signal: listeners.signal });\n win.addEventListener('nativeUIRefresh', schedule, { signal: listeners.signal });\n schedule();\n\n return {\n markForCheck: () => {\n void schedule();\n },\n getStatus: (): NativeUIStatus => ({\n state: stopped ? 'stopped' : 'web',\n projected:\n Number(!!backSource) + Number(!!search.source) + toolbarProjections.reduce((count, group) => count + group.actions.length, 0),\n updates,\n }),\n async suspend() {\n suspended++;\n restore();\n let resumed = false;\n return {\n async resume() {\n if (resumed) return;\n resumed = true;\n suspended = Math.max(0, suspended - 1);\n if (!suspended) await schedule();\n },\n };\n },\n async destroy() {\n if (stopped) return;\n stopped = true;\n win.cancelAnimationFrame(frame);\n frame = 0;\n waiters.forEach((resolve) => resolve());\n waiters = [];\n observer.disconnect();\n sourceObserver?.disconnect();\n listeners.abort();\n crossfade.destroy();\n restore();\n },\n };\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region src/native-integration/index.d.ts
|
|
2
|
+
export interface NativeUIIntegration {
|
|
3
|
+
suspend(scopes: HTMLElement[]): Promise<(canceled?: boolean) => void>;
|
|
4
|
+
search?(binding: NativeSearchBinding, active: boolean, focus?: boolean): Promise<boolean>;
|
|
5
|
+
}
|
|
6
|
+
export interface NativeSearchBinding {
|
|
7
|
+
tabBar: HTMLElement;
|
|
8
|
+
trigger: HTMLElement;
|
|
9
|
+
footer: HTMLElement;
|
|
10
|
+
active: boolean;
|
|
11
|
+
focused: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare const registerNativeSearch: (tabBar: HTMLElement, trigger: HTMLElement, footer: HTMLElement) => NativeSearchBinding;
|
|
14
|
+
export declare const getNativeSearchBindings: (doc: Document) => NativeSearchBinding[];
|
|
15
|
+
export declare const requestNativeSearch: (binding: NativeSearchBinding, active: boolean, focus?: boolean) => Promise<boolean>;
|
|
16
|
+
export declare const VERTICAL_BARS_TRANSITION_CANCELED = "iosThemeVerticalBarsTransitionCanceled";
|
|
17
|
+
export declare const setNativeUIIntegration: (doc: Document, runtime?: NativeUIIntegration) => void;
|
|
18
|
+
export declare const hasNativeUIIntegration: (doc: Document) => boolean;
|
|
19
|
+
export declare const isNativeUI: (element: HTMLElement) => boolean;
|
|
20
|
+
export declare const suspendNativeUI: (scopes: HTMLElement[]) => Promise<(canceled?: boolean) => void>;
|
|
21
|
+
export declare const nativeWebViewMetrics: {
|
|
22
|
+
radius: number;
|
|
23
|
+
};
|
|
24
|
+
//#endregion
|
|
25
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/native-integration/index.ts"],"mappings":";iBAEiB;EACf,QAAQ,QAAQ,gBAAgB,SAAS;EACzC,QAAQ,SAAS,qBAAqB,iBAAiB,kBAAkB;;iBAG1D;EACf,QAAQ;EACR,SAAS;EACT,QAAQ;EACR;EACA;;qBAKW,uBAAwB,QAAQ,aAAa,SAAS,aAAa,QAAQ,gBAAc;qBASzF,0BAA2B,KAAK,aAAW;qBAG3C,sBAA6B,SAAS,qBAAqB,iBAAiB,oBAAkB;qBAI9F;qBAEA,yBAA0B,KAAK,UAAU,UAAU;qBAKnD,yBAA0B,KAAK;qBAE/B,aAAc,SAAS;qBAEvB,kBAAyB,QAAQ,kBAAgB,SAAS;qBAI1D;EAAA"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//#region src/native-integration/index.ts
|
|
2
|
+
const searches = /* @__PURE__ */ new WeakMap();
|
|
3
|
+
const registerNativeSearch = (tabBar, trigger, footer) => {
|
|
4
|
+
const binding = {
|
|
5
|
+
tabBar,
|
|
6
|
+
trigger,
|
|
7
|
+
footer,
|
|
8
|
+
active: false,
|
|
9
|
+
focused: false
|
|
10
|
+
};
|
|
11
|
+
const entries = (searches.get(tabBar.ownerDocument) ?? []).filter((entry) => entry.deref() && entry.deref()?.footer !== footer);
|
|
12
|
+
entries.push(new WeakRef(binding));
|
|
13
|
+
searches.set(tabBar.ownerDocument, entries);
|
|
14
|
+
tabBar.ownerDocument.defaultView?.dispatchEvent(new Event("nativeUIRefresh"));
|
|
15
|
+
return binding;
|
|
16
|
+
};
|
|
17
|
+
const getNativeSearchBindings = (doc) => (searches.get(doc) ?? []).flatMap((entry) => entry.deref() ?? []);
|
|
18
|
+
const requestNativeSearch = async (binding, active, focus) => await runtimes.get(binding.tabBar.ownerDocument)?.search?.(binding, active, focus) ?? false;
|
|
19
|
+
const runtimes = /* @__PURE__ */ new WeakMap();
|
|
20
|
+
const VERTICAL_BARS_TRANSITION_CANCELED = "iosThemeVerticalBarsTransitionCanceled";
|
|
21
|
+
const setNativeUIIntegration = (doc, runtime) => {
|
|
22
|
+
if (runtime) runtimes.set(doc, runtime);
|
|
23
|
+
else runtimes.delete(doc);
|
|
24
|
+
};
|
|
25
|
+
const hasNativeUIIntegration = (doc) => runtimes.has(doc);
|
|
26
|
+
const isNativeUI = (element) => element.hasAttribute("data-native-ui-projected");
|
|
27
|
+
const suspendNativeUI = async (scopes) => await runtimes.get(scopes[0]?.ownerDocument)?.suspend(scopes) ?? (() => {});
|
|
28
|
+
/** Shared geometry used by the theme's transition adapter; no theme import in the plugin. */
|
|
29
|
+
const nativeWebViewMetrics = { radius: 0 };
|
|
30
|
+
//#endregion
|
|
31
|
+
export { VERTICAL_BARS_TRANSITION_CANCELED, getNativeSearchBindings, hasNativeUIIntegration, isNativeUI, nativeWebViewMetrics, registerNativeSearch, requestNativeSearch, setNativeUIIntegration, suspendNativeUI };
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/native-integration/index.ts"],"sourcesContent":["/// <reference lib=\"es2021.weakref\" />\n\nexport interface NativeUIIntegration {\n suspend(scopes: HTMLElement[]): Promise<(canceled?: boolean) => void>;\n search?(binding: NativeSearchBinding, active: boolean, focus?: boolean): Promise<boolean>;\n}\n\nexport interface NativeSearchBinding {\n tabBar: HTMLElement;\n trigger: HTMLElement;\n footer: HTMLElement;\n active: boolean;\n focused: boolean;\n}\n\nconst searches = new WeakMap<Document, WeakRef<NativeSearchBinding>[]>();\n\nexport const registerNativeSearch = (tabBar: HTMLElement, trigger: HTMLElement, footer: HTMLElement): NativeSearchBinding => {\n const binding = { tabBar, trigger, footer, active: false, focused: false };\n const entries = (searches.get(tabBar.ownerDocument) ?? []).filter((entry) => entry.deref() && entry.deref()?.footer !== footer);\n entries.push(new WeakRef(binding));\n searches.set(tabBar.ownerDocument, entries);\n tabBar.ownerDocument.defaultView?.dispatchEvent(new Event('nativeUIRefresh'));\n return binding;\n};\n\nexport const getNativeSearchBindings = (doc: Document): NativeSearchBinding[] =>\n (searches.get(doc) ?? []).flatMap((entry) => entry.deref() ?? []);\n\nexport const requestNativeSearch = async (binding: NativeSearchBinding, active: boolean, focus?: boolean): Promise<boolean> =>\n (await runtimes.get(binding.tabBar.ownerDocument)?.search?.(binding, active, focus)) ?? false;\n\nconst runtimes = new WeakMap<Document, NativeUIIntegration>();\nexport const VERTICAL_BARS_TRANSITION_CANCELED = 'iosThemeVerticalBarsTransitionCanceled';\n\nexport const setNativeUIIntegration = (doc: Document, runtime?: NativeUIIntegration) => {\n if (runtime) runtimes.set(doc, runtime);\n else runtimes.delete(doc);\n};\n\nexport const hasNativeUIIntegration = (doc: Document): boolean => runtimes.has(doc);\n\nexport const isNativeUI = (element: HTMLElement) => element.hasAttribute('data-native-ui-projected');\n\nexport const suspendNativeUI = async (scopes: HTMLElement[]): Promise<(canceled?: boolean) => void> =>\n (await runtimes.get(scopes[0]?.ownerDocument)?.suspend(scopes)) ?? (() => {});\n\n/** Shared geometry used by the theme's transition adapter; no theme import in the plugin. */\nexport const nativeWebViewMetrics = { radius: 0 };\n"],"mappings":";AAeA,MAAM,2BAAW,IAAI,QAAkD;AAEvE,MAAa,wBAAwB,QAAqB,SAAsB,WAA6C;CAC3H,MAAM,UAAU;EAAE;EAAQ;EAAS;EAAQ,QAAQ;EAAO,SAAS;CAAM;CACzE,MAAM,WAAW,SAAS,IAAI,OAAO,aAAa,KAAK,CAAC,EAAA,CAAG,QAAQ,UAAU,MAAM,MAAM,KAAK,MAAM,MAAM,CAAC,EAAE,WAAW,MAAM;CAC9H,QAAQ,KAAK,IAAI,QAAQ,OAAO,CAAC;CACjC,SAAS,IAAI,OAAO,eAAe,OAAO;CAC1C,OAAO,cAAc,aAAa,cAAc,IAAI,MAAM,iBAAiB,CAAC;CAC5E,OAAO;AACT;AAEA,MAAa,2BAA2B,SACrC,SAAS,IAAI,GAAG,KAAK,CAAC,EAAA,CAAG,SAAS,UAAU,MAAM,MAAM,KAAK,CAAC,CAAC;AAElE,MAAa,sBAAsB,OAAO,SAA8B,QAAiB,UACtF,MAAM,SAAS,IAAI,QAAQ,OAAO,aAAa,CAAC,EAAE,SAAS,SAAS,QAAQ,KAAK,KAAM;AAE1F,MAAM,2BAAW,IAAI,QAAuC;AAC5D,MAAa,oCAAoC;AAEjD,MAAa,0BAA0B,KAAe,YAAkC;CACtF,IAAI,SAAS,SAAS,IAAI,KAAK,OAAO;MACjC,SAAS,OAAO,GAAG;AAC1B;AAEA,MAAa,0BAA0B,QAA2B,SAAS,IAAI,GAAG;AAElF,MAAa,cAAc,YAAyB,QAAQ,aAAa,0BAA0B;AAEnG,MAAa,kBAAkB,OAAO,WACnC,MAAM,SAAS,IAAI,OAAO,EAAE,EAAE,aAAa,CAAC,EAAE,QAAQ,MAAM,YAAa,CAAC;;AAG7E,MAAa,uBAAuB,EAAE,QAAQ,EAAE"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { NativeUIStatus, NativeUISuspension, ToolbarProjectionOptions, VerticalBarEdge, VerticalControlAreaHandle, VerticalControlAreaOptions } from "./native/definitions.js";
|
|
2
|
+
import { NativeUI } from "./native/activation.js";
|
|
3
|
+
import { applyFoldStateClasses } from "./native/foldable/fold-state.js";
|
|
4
|
+
import { setVerticalControlAreaPlacement } from "./native/legacy-layout.js";
|
|
5
|
+
import { enableVerticalControlArea } from "./native/index.js";
|
|
6
|
+
export { NativeUI, type NativeUIStatus, type NativeUISuspension, type ToolbarProjectionOptions, type VerticalBarEdge, type VerticalControlAreaHandle, type VerticalControlAreaOptions, applyFoldStateClasses, enableVerticalControlArea, setVerticalControlAreaPlacement };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { NativeUI } from "./native/activation.js";
|
|
2
|
+
import { setVerticalControlAreaPlacement } from "./native/legacy-layout.js";
|
|
3
|
+
import { enableVerticalControlArea } from "./native/index.js";
|
|
4
|
+
import { applyFoldStateClasses } from "./native/foldable/fold-state.js";
|
|
5
|
+
export { NativeUI, applyFoldStateClasses, enableVerticalControlArea, setVerticalControlAreaPlacement };
|