@rdlabo/ionic-theme-ios27 1.1.0-beta.pr224.shac63de393e27b → 1.2.0-0
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 +8 -1
- package/dist/css/components/ion-menu.css +1 -1
- package/dist/css/ionic-theme-ios27.css +1 -1
- package/dist/css/vertical-bars.css +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -8
- package/dist/native/components/index.d.ts +1 -0
- package/dist/native/components/index.d.ts.map +1 -1
- package/dist/native/components/index.js +8 -3
- package/dist/native/components/ion-back-button.d.ts.map +1 -1
- package/dist/native/components/ion-back-button.js +5 -2
- package/dist/native/components/ion-button.d.ts.map +1 -1
- package/dist/native/components/ion-button.js +10 -2
- package/dist/native/components/ion-buttons.d.ts.map +1 -1
- package/dist/native/components/ion-buttons.js +12 -4
- package/dist/native/components/ion-fab.js +4 -4
- package/dist/native/components/ion-menu-button.d.ts.map +1 -1
- package/dist/native/components/ion-menu-button.js +5 -4
- package/dist/native/components/searchable-tabs.d.ts.map +1 -1
- package/dist/native/components/searchable-tabs.js +4 -1
- package/dist/native/definitions.d.ts +29 -3
- package/dist/native/definitions.d.ts.map +1 -1
- package/dist/native/definitions.js +6 -1
- package/dist/native/index.d.ts +6 -2
- package/dist/native/index.d.ts.map +1 -1
- package/dist/native/index.js +154 -17
- package/dist/native/prehide.d.ts +5 -0
- package/dist/native/prehide.d.ts.map +1 -0
- package/dist/native/prehide.js +246 -0
- package/dist/native/runtime.d.ts +1 -1
- package/dist/native/runtime.d.ts.map +1 -1
- package/dist/native/runtime.js +162 -28
- package/dist/native/shared/candidate.d.ts.map +1 -1
- package/dist/native/shared/candidate.js +7 -3
- package/dist/native/shared/dom.d.ts +33 -2
- package/dist/native/shared/dom.d.ts.map +1 -1
- package/dist/native/shared/dom.js +171 -10
- package/dist/native/vertical-bars-web.d.ts +3 -0
- package/dist/native/vertical-bars-web.d.ts.map +1 -0
- package/dist/native/vertical-bars-web.js +341 -0
- package/dist/native-integration/index.d.ts +3 -2
- package/dist/native-integration/index.d.ts.map +1 -1
- package/dist/native-integration/index.js +11 -5
- package/dist/transition/index.d.ts +2 -2
- package/dist/transition/index.d.ts.map +1 -1
- package/dist/transition/index.js +1 -1
- package/dist/transition/ios.transition.d.ts.map +1 -1
- package/dist/transition/ios.transition.js +1 -0
- package/dist/utils.d.ts +3 -3
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +1 -1
- package/dist/vertical-bars.d.ts +4 -0
- package/dist/vertical-bars.d.ts.map +1 -0
- package/dist/vertical-bars.js +2 -0
- package/docs/iphone-duo.md +255 -0
- package/docs/migration.md +2 -2
- package/docs/native-ui-shell.md +15 -3
- package/docs/special-markup.md +6 -0
- package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellSearchController.swift +15 -1
- package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellVerticalBars.swift +358 -0
- package/ios/Sources/IonicNativeUIShellPlugin/IonicNativeUIShellPlugin.swift +215 -35
- package/ios/Sources/IonicNativeUIShellPlugin/Shared/ShellSnapshot.swift +10 -1
- package/ios/Tests/IonicNativeUIShellPluginTests/ShellSnapshotTests.swift +29 -0
- package/package.json +6 -2
- package/src/index.ts +15 -8
- package/src/native/components/index.ts +12 -3
- package/src/native/components/ion-back-button.ts +8 -2
- package/src/native/components/ion-button.ts +12 -2
- package/src/native/components/ion-buttons.ts +9 -4
- package/src/native/components/ion-fab.ts +4 -4
- package/src/native/components/ion-menu-button.ts +5 -4
- package/src/native/components/searchable-tabs.ts +9 -1
- package/src/native/definitions.ts +40 -3
- package/src/native/index.ts +188 -20
- package/src/native/prehide.ts +255 -0
- package/src/native/runtime.ts +173 -27
- package/src/native/shared/candidate.ts +11 -3
- package/src/native/shared/dom.ts +212 -11
- package/src/native/vertical-bars-web.ts +374 -0
- package/src/native-integration/index.ts +13 -8
- package/src/styles/components/ion-menu.scss +2 -2
- package/src/styles/ionic-theme-ios27.scss +1 -0
- package/src/styles/vertical-bars.scss +342 -0
- package/src/transition/index.ts +11 -6
- package/src/transition/ios.transition.ts +1 -0
- package/src/utils.ts +8 -8
- package/src/vertical-bars.ts +3 -0
- package/dist/native/lifecycle.d.ts +0 -4
- package/dist/native/lifecycle.d.ts.map +0 -1
- package/dist/native/lifecycle.js +0 -34
- package/src/native/lifecycle.ts +0 -38
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prehide.d.ts","sourceRoot":"","sources":["../../src/native/prehide.ts"],"names":[],"mappings":"AAiCA,eAAO,MAAM,iCAAiC,GAAI,KAAK,QAAQ,KAAG;IAAE,OAAO,EAAE,MAAM,MAAM,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,IAAI,CAAA;CA6N9G,CAAC"}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { LIFECYCLE_DID_ENTER, LIFECYCLE_DID_LEAVE, LIFECYCLE_WILL_ENTER, LIFECYCLE_WILL_LEAVE } from '@ionic/core';
|
|
2
|
+
import { VERTICAL_BARS_TRANSITION_CANCELED } from '../native-integration';
|
|
3
|
+
import { childElements, clearVerticalBarsPlacement, createVerticalBarsPageState, verticalBarsActionCandidate, verticalBarsBackCandidate, verticalBarsBackWebClass, verticalBarsOwned, isVerticalBarsToolbarActionShape, isPermanentlyExcluded, isShellDisabled, prehiddenClass, prehideRootClass, rejectedClass, setVerticalBarsPlacement, } from './shared/dom';
|
|
4
|
+
const overlays = 'ion-menu, ion-modal, ion-popover';
|
|
5
|
+
const sourceSelector = 'ion-back-button, ion-menu-button, ion-buttons, ion-button';
|
|
6
|
+
const isHtmlElement = (node) => !!node && node.nodeType === 1;
|
|
7
|
+
const asElement = (node) => (isHtmlElement(node) ? node : undefined);
|
|
8
|
+
const backSupported = (element) => {
|
|
9
|
+
const back = element;
|
|
10
|
+
return back.icon === undefined && back.color === undefined && !!back.shadowRoot;
|
|
11
|
+
};
|
|
12
|
+
const eligibleBack = verticalBarsBackCandidate;
|
|
13
|
+
const eligible = verticalBarsActionCandidate;
|
|
14
|
+
export const prehideVerticalBarsToolbarSources = (doc) => {
|
|
15
|
+
doc.documentElement.classList.add(prehideRootClass);
|
|
16
|
+
const scopes = new Map();
|
|
17
|
+
const owner = new WeakMap();
|
|
18
|
+
const pendingBacks = new Map();
|
|
19
|
+
const verticalBarsPages = createVerticalBarsPageState();
|
|
20
|
+
const listeners = new AbortController();
|
|
21
|
+
const root = () => doc.querySelector('ion-app.ios-theme-vertical-bars');
|
|
22
|
+
let suspended = 0;
|
|
23
|
+
let stopped = false;
|
|
24
|
+
const routedPage = (element) => element.closest('.ion-page:not(ion-app, body)');
|
|
25
|
+
const release = (scope) => {
|
|
26
|
+
for (const [element, pending] of pendingBacks) {
|
|
27
|
+
if (pending.scope !== scope)
|
|
28
|
+
continue;
|
|
29
|
+
clearTimeout(pending.timer);
|
|
30
|
+
pendingBacks.delete(element);
|
|
31
|
+
}
|
|
32
|
+
const owned = scopes.get(scope);
|
|
33
|
+
if (!owned)
|
|
34
|
+
return;
|
|
35
|
+
owned.forEach((element) => {
|
|
36
|
+
if (owner.get(element) !== scope)
|
|
37
|
+
return;
|
|
38
|
+
owner.delete(element);
|
|
39
|
+
element.classList.remove(prehiddenClass);
|
|
40
|
+
element.classList.remove(verticalBarsBackWebClass);
|
|
41
|
+
clearVerticalBarsPlacement(element);
|
|
42
|
+
});
|
|
43
|
+
scopes.delete(scope);
|
|
44
|
+
};
|
|
45
|
+
const capture = (scope) => {
|
|
46
|
+
if (!root()?.contains(scope) || scope.closest(overlays) || verticalBarsPages.isDeparted(scope))
|
|
47
|
+
return;
|
|
48
|
+
const owned = scopes.get(scope) ?? new Set();
|
|
49
|
+
const place = (element, rail) => {
|
|
50
|
+
if (owned.has(element))
|
|
51
|
+
return;
|
|
52
|
+
const previousScope = owner.get(element);
|
|
53
|
+
if (previousScope)
|
|
54
|
+
scopes.get(previousScope)?.delete(element);
|
|
55
|
+
owner.set(element, scope);
|
|
56
|
+
setVerticalBarsPlacement(element, rail);
|
|
57
|
+
if (element.matches('ion-back-button'))
|
|
58
|
+
element.classList.toggle(verticalBarsBackWebClass, !rail);
|
|
59
|
+
owned.add(element);
|
|
60
|
+
};
|
|
61
|
+
const sources = scope.matches('ion-back-button') ? [scope] : Array.from(scope.querySelectorAll(sourceSelector));
|
|
62
|
+
sources.forEach((element) => {
|
|
63
|
+
if (element.closest(overlays) || (scope.matches('.ion-page') && routedPage(element) !== scope))
|
|
64
|
+
return;
|
|
65
|
+
if (element.matches('ion-buttons')) {
|
|
66
|
+
const children = childElements(element);
|
|
67
|
+
const actions = children.filter((child) => eligible(child) && isVerticalBarsToolbarActionShape(child));
|
|
68
|
+
const group = eligible(element) &&
|
|
69
|
+
actions.length === children.length &&
|
|
70
|
+
(actions.length > 1 || (actions.length === 1 && actions[0].matches('ion-menu-button')));
|
|
71
|
+
const freshGroup = !owned.has(element);
|
|
72
|
+
place(element, group);
|
|
73
|
+
children.forEach((child) => {
|
|
74
|
+
if (!child.matches('ion-back-button'))
|
|
75
|
+
place(child, freshGroup && actions.includes(child));
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
else if (element.matches('ion-back-button') || !element.parentElement?.matches('ion-buttons')) {
|
|
79
|
+
if (owned.has(element))
|
|
80
|
+
return;
|
|
81
|
+
if (element.matches('ion-back-button') &&
|
|
82
|
+
eligibleBack(element) &&
|
|
83
|
+
element.icon === undefined &&
|
|
84
|
+
element.color === undefined &&
|
|
85
|
+
!element.shadowRoot &&
|
|
86
|
+
!element.classList.contains('hydrated')) {
|
|
87
|
+
const previousPending = pendingBacks.get(element);
|
|
88
|
+
if (previousPending && previousPending.scope !== scope) {
|
|
89
|
+
clearTimeout(previousPending.timer);
|
|
90
|
+
pendingBacks.delete(element);
|
|
91
|
+
}
|
|
92
|
+
if (!pendingBacks.has(element)) {
|
|
93
|
+
const timer = setTimeout(() => {
|
|
94
|
+
if (pendingBacks.get(element)?.scope !== scope)
|
|
95
|
+
return;
|
|
96
|
+
pendingBacks.delete(element);
|
|
97
|
+
place(element, false);
|
|
98
|
+
reconcile();
|
|
99
|
+
}, 1500);
|
|
100
|
+
pendingBacks.set(element, { scope, timer });
|
|
101
|
+
}
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const pending = pendingBacks.get(element);
|
|
105
|
+
if (pending) {
|
|
106
|
+
clearTimeout(pending.timer);
|
|
107
|
+
pendingBacks.delete(element);
|
|
108
|
+
}
|
|
109
|
+
place(element, element.matches('ion-back-button')
|
|
110
|
+
? eligibleBack(element) && backSupported(element)
|
|
111
|
+
: eligible(element) && isVerticalBarsToolbarActionShape(element));
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
scopes.set(scope, owned);
|
|
115
|
+
};
|
|
116
|
+
const reconcile = () => {
|
|
117
|
+
const verticalBars = root();
|
|
118
|
+
if (!verticalBars) {
|
|
119
|
+
Array.from(scopes.keys()).forEach(release);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
for (const scope of scopes.keys())
|
|
123
|
+
if (!scope.isConnected)
|
|
124
|
+
release(scope);
|
|
125
|
+
for (const [element, pending] of pendingBacks)
|
|
126
|
+
if (element.shadowRoot || element.classList.contains('hydrated'))
|
|
127
|
+
capture(pending.scope);
|
|
128
|
+
verticalBars.querySelectorAll('.ion-page:not(ion-app, body, .ion-page-hidden)').forEach(capture);
|
|
129
|
+
verticalBars.querySelectorAll(sourceSelector).forEach((element) => {
|
|
130
|
+
if (routedPage(element) || element.closest(overlays))
|
|
131
|
+
return;
|
|
132
|
+
const scope = element.closest('ion-toolbar') ?? (element.matches('ion-back-button') ? element : null);
|
|
133
|
+
if (scope)
|
|
134
|
+
capture(scope);
|
|
135
|
+
});
|
|
136
|
+
for (const owned of scopes.values()) {
|
|
137
|
+
for (const element of owned) {
|
|
138
|
+
const groupOwnsChildren = element.parentElement?.matches('ion-buttons') &&
|
|
139
|
+
verticalBarsOwned(element.parentElement) &&
|
|
140
|
+
childElements(element.parentElement).every((child) => verticalBarsOwned(child));
|
|
141
|
+
const hide = !suspended &&
|
|
142
|
+
verticalBarsOwned(element) &&
|
|
143
|
+
!groupOwnsChildren &&
|
|
144
|
+
element.isConnected &&
|
|
145
|
+
!element.closest(`.${rejectedClass}`) &&
|
|
146
|
+
!isPermanentlyExcluded(element) &&
|
|
147
|
+
!isShellDisabled(element) &&
|
|
148
|
+
(!element.matches('ion-back-button') || backSupported(element) || !element.classList.contains('hydrated')) &&
|
|
149
|
+
(!element.matches('ion-buttons') || childElements(element).every((child) => verticalBarsOwned(child)));
|
|
150
|
+
element.classList.toggle(prehiddenClass, hide);
|
|
151
|
+
if (element.matches('ion-back-button'))
|
|
152
|
+
element.classList.toggle(verticalBarsBackWebClass, !hide);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
const onWillEnter = (event) => {
|
|
157
|
+
const page = asElement(event.target);
|
|
158
|
+
if (page?.matches('.ion-page')) {
|
|
159
|
+
verticalBarsPages.lifecycle(event);
|
|
160
|
+
release(page);
|
|
161
|
+
capture(page);
|
|
162
|
+
reconcile();
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
const onPageLifecycle = (event) => {
|
|
166
|
+
verticalBarsPages.lifecycle(event);
|
|
167
|
+
if (event.type !== LIFECYCLE_DID_LEAVE)
|
|
168
|
+
return;
|
|
169
|
+
const page = asElement(event.target);
|
|
170
|
+
if (page)
|
|
171
|
+
release(page);
|
|
172
|
+
};
|
|
173
|
+
const onTransitionCanceled = (event) => {
|
|
174
|
+
const leaving = asElement(event.target);
|
|
175
|
+
if (!leaving)
|
|
176
|
+
return;
|
|
177
|
+
const entering = event.detail?.entering;
|
|
178
|
+
verticalBarsPages.cancel(entering, leaving);
|
|
179
|
+
reconcile();
|
|
180
|
+
};
|
|
181
|
+
doc.addEventListener(LIFECYCLE_WILL_ENTER, onWillEnter, { capture: true, signal: listeners.signal });
|
|
182
|
+
for (const name of [LIFECYCLE_WILL_LEAVE, LIFECYCLE_DID_ENTER, LIFECYCLE_DID_LEAVE])
|
|
183
|
+
doc.addEventListener(name, onPageLifecycle, { capture: true, signal: listeners.signal });
|
|
184
|
+
doc.addEventListener(VERTICAL_BARS_TRANSITION_CANCELED, onTransitionCanceled, { capture: true, signal: listeners.signal });
|
|
185
|
+
reconcile();
|
|
186
|
+
const mutationRelevant = (record) => {
|
|
187
|
+
if (record.type === 'childList')
|
|
188
|
+
return [...Array.from(record.addedNodes), ...Array.from(record.removedNodes)].some((node) => isHtmlElement(node) &&
|
|
189
|
+
(node.matches(`${sourceSelector}, .ion-page, ion-toolbar`) || !!node.querySelector(`${sourceSelector}, .ion-page, ion-toolbar`)));
|
|
190
|
+
if (record.attributeName !== 'class')
|
|
191
|
+
return true;
|
|
192
|
+
const current = record.target.className;
|
|
193
|
+
const previous = record.oldValue ?? '';
|
|
194
|
+
const withoutOwned = (value) => value
|
|
195
|
+
.split(/\s+/)
|
|
196
|
+
.filter((name) => name && ![prehiddenClass, prehideRootClass, verticalBarsBackWebClass].includes(name))
|
|
197
|
+
.join(' ');
|
|
198
|
+
return typeof current !== 'string' || withoutOwned(previous) !== withoutOwned(current);
|
|
199
|
+
};
|
|
200
|
+
let scheduled = false;
|
|
201
|
+
const observer = new (doc.defaultView?.MutationObserver ?? MutationObserver)((records) => {
|
|
202
|
+
if (scheduled || stopped || !records.some(mutationRelevant))
|
|
203
|
+
return;
|
|
204
|
+
scheduled = true;
|
|
205
|
+
queueMicrotask(() => {
|
|
206
|
+
scheduled = false;
|
|
207
|
+
if (!stopped)
|
|
208
|
+
reconcile();
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
observer.observe(doc.documentElement, {
|
|
212
|
+
subtree: true,
|
|
213
|
+
childList: true,
|
|
214
|
+
attributes: true,
|
|
215
|
+
attributeOldValue: true,
|
|
216
|
+
attributeFilter: ['class', 'hidden', 'inert', 'icon', 'color'],
|
|
217
|
+
});
|
|
218
|
+
return {
|
|
219
|
+
suspend: () => {
|
|
220
|
+
if (stopped)
|
|
221
|
+
return () => { };
|
|
222
|
+
suspended++;
|
|
223
|
+
doc.documentElement.classList.remove(prehideRootClass);
|
|
224
|
+
reconcile();
|
|
225
|
+
let resumed = false;
|
|
226
|
+
return () => {
|
|
227
|
+
if (resumed || stopped)
|
|
228
|
+
return;
|
|
229
|
+
resumed = true;
|
|
230
|
+
if (--suspended === 0) {
|
|
231
|
+
doc.documentElement.classList.add(prehideRootClass);
|
|
232
|
+
reconcile();
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
},
|
|
236
|
+
stop: () => {
|
|
237
|
+
if (stopped)
|
|
238
|
+
return;
|
|
239
|
+
stopped = true;
|
|
240
|
+
observer.disconnect();
|
|
241
|
+
listeners.abort();
|
|
242
|
+
doc.documentElement.classList.remove(prehideRootClass);
|
|
243
|
+
Array.from(scopes.keys()).forEach(release);
|
|
244
|
+
},
|
|
245
|
+
};
|
|
246
|
+
};
|
package/dist/native/runtime.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { NativeUIShellHandle, NativeUIShellOptions, NativeUIShellPlugin } from './definitions';
|
|
2
|
-
export declare const createRuntime: (doc: Document, plugin: NativeUIShellPlugin, options?: NativeUIShellOptions) => Promise<NativeUIShellHandle>;
|
|
2
|
+
export declare const createRuntime: (doc: Document, plugin: NativeUIShellPlugin, options?: NativeUIShellOptions, nativeVerticalBars?: () => boolean, verticalBarsOnly?: boolean) => Promise<NativeUIShellHandle>;
|
|
3
3
|
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/native/runtime.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAGV,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EAEpB,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/native/runtime.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAGV,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EAEpB,MAAM,eAAe,CAAC;AA6BvB,eAAO,MAAM,aAAa,GACxB,KAAK,QAAQ,EACb,QAAQ,mBAAmB,EAC3B,UAAS,oBAAyB,EAClC,qBAAoB,MAAM,OAAoB,EAC9C,0BAAwB,KACvB,OAAO,CAAC,mBAAmB,CAosB7B,CAAC"}
|
package/dist/native/runtime.js
CHANGED
|
@@ -1,26 +1,31 @@
|
|
|
1
1
|
import { LIFECYCLE_WILL_ENTER, LIFECYCLE_WILL_LEAVE, LIFECYCLE_DID_ENTER, LIFECYCLE_DID_LEAVE } from '@ionic/core';
|
|
2
|
-
import { getNativeSearchBindings, setNativeUIShellIntegration } from '../native-integration';
|
|
2
|
+
import { VERTICAL_BARS_TRANSITION_CANCELED, getNativeSearchBindings, setNativeUIShellIntegration } from '../native-integration';
|
|
3
3
|
import { createSearchSupport } from './components/searchable-tabs';
|
|
4
|
-
import { readCandidate, selector, shadowSelector, motionSelector } from './components';
|
|
5
|
-
import { marker, unprojected } from './shared/dom';
|
|
4
|
+
import { readCandidate, selector, shadowSelector, motionSelector, isVerticalBarsCandidate } from './components';
|
|
5
|
+
import { activateProjectedElement, createVerticalBarsPageState, isVerticalBarsSource, preferredVerticalBarsBack, marker, prehideOnlyMutation, rejectedClass, unprojected, } from './shared/dom';
|
|
6
6
|
import { createIconRenderer } from './shared/icons';
|
|
7
7
|
import { CSS_MOTION_EVENTS } from './shared/events';
|
|
8
8
|
import { createCrossfade, fadeMarker } from './shared/crossfade';
|
|
9
9
|
const overlays = 'ion-modal, ion-popover, ion-alert, ion-action-sheet, ion-loading, ion-picker, ion-toast, ion-menu';
|
|
10
10
|
const overlayNames = ['Modal', 'Popover', 'Alert', 'ActionSheet', 'Loading', 'Picker', 'Toast'];
|
|
11
|
+
const verticalBarsMarker = 'data-native-ui-shell-vertical-bars';
|
|
12
|
+
const verticalBarsMemberMarker = 'data-native-ui-shell-vertical-bars-member';
|
|
11
13
|
const bounded = (promise) => new Promise((resolve, reject) => {
|
|
12
14
|
const timer = setTimeout(() => reject(new Error('Native UI Shell bridge timed out')), 5000);
|
|
13
15
|
promise.then(resolve, reject).finally(() => clearTimeout(timer));
|
|
14
16
|
});
|
|
15
|
-
export const createRuntime = async (doc, plugin, options = {}) => {
|
|
17
|
+
export const createRuntime = async (doc, plugin, options = {}, nativeVerticalBars = () => true, verticalBarsOnly = false) => {
|
|
16
18
|
const win = doc.defaultView;
|
|
17
19
|
const icons = createIconRenderer();
|
|
18
20
|
const crossfade = createCrossfade(win);
|
|
19
21
|
const ids = new WeakMap();
|
|
20
22
|
let rejected = new WeakMap();
|
|
21
23
|
const sources = new Map();
|
|
24
|
+
const verticalBarsOwners = new Set();
|
|
25
|
+
const verticalBarsMembers = new Set();
|
|
22
26
|
const suspended = new Set();
|
|
23
27
|
const pages = new Set();
|
|
28
|
+
const verticalBarsPages = createVerticalBarsPageState();
|
|
24
29
|
const presented = new Set();
|
|
25
30
|
const manualSuspensions = new Set();
|
|
26
31
|
const moving = new Map();
|
|
@@ -74,13 +79,22 @@ export const createRuntime = async (doc, plugin, options = {}) => {
|
|
|
74
79
|
const style = doc.createElement('style');
|
|
75
80
|
const hidden = `[${marker}]:not([${fadeMarker}])`;
|
|
76
81
|
style.textContent = `${hidden}, ${hidden} *, ${hidden}::before, ${hidden}::after, ${hidden}::part(native) { visibility: hidden !important; }
|
|
77
|
-
[${marker}], [${marker}] * { pointer-events: none !important; }
|
|
82
|
+
[${marker}], [${marker}] * { pointer-events: none !important; }
|
|
83
|
+
/* Ionic disables the covered page while a menu is open. VerticalBars rail
|
|
84
|
+
controls remain outside that page; zero specificity preserves any
|
|
85
|
+
pointer-events rule supplied by the application itself. */
|
|
86
|
+
:where(.menu-content-open) :where([${verticalBarsMarker}]) {
|
|
87
|
+
pointer-events: auto;
|
|
88
|
+
}
|
|
89
|
+
:where(.menu-content-open) :where([${verticalBarsMarker}]) > :where(:not([${verticalBarsMemberMarker}])) {
|
|
90
|
+
pointer-events: none;
|
|
91
|
+
}`;
|
|
78
92
|
const restore = (element) => {
|
|
79
93
|
lastSnapshot = '';
|
|
80
94
|
search.release(element);
|
|
81
95
|
element.removeAttribute(marker);
|
|
82
96
|
if (!stopped)
|
|
83
|
-
crossfade.play(element, false, handoffInstant);
|
|
97
|
+
crossfade.play(element, false, handoffInstant || isVerticalBarsSource(element));
|
|
84
98
|
if (element.getAttribute('aria-hidden') === 'true') {
|
|
85
99
|
const previous = sources.get(element);
|
|
86
100
|
if (previous == null)
|
|
@@ -91,7 +105,13 @@ export const createRuntime = async (doc, plugin, options = {}) => {
|
|
|
91
105
|
sources.delete(element);
|
|
92
106
|
element.dispatchEvent(new CustomEvent('nativeUIShellChange'));
|
|
93
107
|
};
|
|
94
|
-
const restoreAll = () =>
|
|
108
|
+
const restoreAll = () => {
|
|
109
|
+
Array.from(sources.keys()).forEach(restore);
|
|
110
|
+
verticalBarsOwners.forEach((element) => element.removeAttribute(verticalBarsMarker));
|
|
111
|
+
verticalBarsOwners.clear();
|
|
112
|
+
verticalBarsMembers.forEach((element) => element.removeAttribute(verticalBarsMemberMarker));
|
|
113
|
+
verticalBarsMembers.clear();
|
|
114
|
+
};
|
|
95
115
|
const finishWaiters = () => {
|
|
96
116
|
const current = waiters;
|
|
97
117
|
waiters = [];
|
|
@@ -106,8 +126,48 @@ export const createRuntime = async (doc, plugin, options = {}) => {
|
|
|
106
126
|
};
|
|
107
127
|
const search = createSearchSupport(doc, id, schedule);
|
|
108
128
|
const candidateSources = (candidate) => candidate.sources ?? [candidate.element];
|
|
129
|
+
const setRejected = (element, value) => {
|
|
130
|
+
element.classList.toggle(rejectedClass, value);
|
|
131
|
+
};
|
|
132
|
+
const measuringPointerPages = new WeakSet();
|
|
109
133
|
const readEnabledCandidate = (element) => {
|
|
110
|
-
|
|
134
|
+
if (element.matches('ion-back-button') && element.closest('ion-app.ios-theme-vertical-bars') && !isVerticalBarsCandidate(element))
|
|
135
|
+
return;
|
|
136
|
+
if (verticalBarsOnly && !isVerticalBarsCandidate(element))
|
|
137
|
+
return;
|
|
138
|
+
const pointerPage = isVerticalBarsCandidate(element) ? element.closest('.ion-page') : undefined;
|
|
139
|
+
let candidate;
|
|
140
|
+
if (pointerPage && getComputedStyle(pointerPage).pointerEvents === 'none') {
|
|
141
|
+
const previous = pointerPage.style.getPropertyValue('pointer-events');
|
|
142
|
+
const priority = pointerPage.style.getPropertyPriority('pointer-events');
|
|
143
|
+
const hadStyle = pointerPage.hasAttribute('style');
|
|
144
|
+
measuringPointerPages.add(pointerPage);
|
|
145
|
+
pointerPage.style.setProperty('pointer-events', 'auto', 'important');
|
|
146
|
+
try {
|
|
147
|
+
candidate = readCandidate(element, id);
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
if (previous)
|
|
151
|
+
pointerPage.style.setProperty('pointer-events', previous, priority);
|
|
152
|
+
else
|
|
153
|
+
pointerPage.style.removeProperty('pointer-events');
|
|
154
|
+
if (!hadStyle && !pointerPage.style.length)
|
|
155
|
+
pointerPage.removeAttribute('style');
|
|
156
|
+
win.setTimeout(() => measuringPointerPages.delete(pointerPage), 0);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
else
|
|
160
|
+
candidate = readCandidate(element, id);
|
|
161
|
+
if (candidate && isVerticalBarsCandidate(element)) {
|
|
162
|
+
if (!nativeVerticalBars())
|
|
163
|
+
return undefined;
|
|
164
|
+
candidate.control.placement = 'vertical-bars';
|
|
165
|
+
if (['ion-button', 'ion-buttons', 'ion-menu-button'].includes(candidate.control.kind)) {
|
|
166
|
+
const slot = (element.matches('ion-buttons') ? element : (element.closest('ion-buttons') ?? element)).getAttribute('slot');
|
|
167
|
+
if (slot === 'start' || slot === 'end')
|
|
168
|
+
candidate.control.toolbarSlot = slot;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
111
171
|
return candidate && controlEnabled(candidate) ? candidate : undefined;
|
|
112
172
|
};
|
|
113
173
|
const flush = async () => {
|
|
@@ -121,17 +181,21 @@ export const createRuntime = async (doc, plugin, options = {}) => {
|
|
|
121
181
|
await fail(error);
|
|
122
182
|
}
|
|
123
183
|
};
|
|
124
|
-
const blocked = (element) =>
|
|
125
|
-
|
|
126
|
-
|
|
184
|
+
const blocked = (element) => verticalBarsPages.isDeparted(element) ||
|
|
185
|
+
(!isVerticalBarsSource(element) &&
|
|
186
|
+
(Array.from(suspended).some((scopes) => scopes.some((scope) => scope.contains(element))) ||
|
|
187
|
+
Array.from(pages).some((scope) => scope.contains(element)) ||
|
|
188
|
+
Array.from(moving.keys()).some((surface) => surface.contains(element))));
|
|
127
189
|
const painted = () => new Promise((resolve) => win.requestAnimationFrame(() => win.requestAnimationFrame(() => resolve())));
|
|
128
|
-
const overlayOpen = () => {
|
|
190
|
+
const overlayOpen = (includeMenu = true) => {
|
|
129
191
|
for (const element of presented)
|
|
130
192
|
if (!element.isConnected)
|
|
131
193
|
presented.delete(element);
|
|
194
|
+
const presentedOverlayOpen = Array.from(presented).some((element) => includeMenu || !element.matches('ion-menu'));
|
|
132
195
|
return (manualSuspensions.size > 0 ||
|
|
133
|
-
|
|
134
|
-
Array.from(doc.querySelectorAll(overlays)).some((element) =>
|
|
196
|
+
presentedOverlayOpen ||
|
|
197
|
+
Array.from(doc.querySelectorAll(overlays)).some((element) => (includeMenu || !element.matches('ion-menu')) &&
|
|
198
|
+
(element.presented || element.classList.contains('show-menu'))));
|
|
135
199
|
};
|
|
136
200
|
const signature = (candidate) => JSON.stringify({ control: candidate.control, icons: candidate.icons.map(({ source }) => source) });
|
|
137
201
|
const read = () => {
|
|
@@ -142,16 +206,22 @@ export const createRuntime = async (doc, plugin, options = {}) => {
|
|
|
142
206
|
for (const surface of moving.keys())
|
|
143
207
|
if (!surface.isConnected)
|
|
144
208
|
moving.delete(surface);
|
|
145
|
-
if (doc.hidden || overlayOpen())
|
|
209
|
+
if (doc.hidden || overlayOpen(false))
|
|
146
210
|
return [];
|
|
147
211
|
if (win.visualViewport && (win.visualViewport.scale !== 1 || win.visualViewport.offsetTop !== 0) && !search.hasActive())
|
|
148
212
|
return [];
|
|
149
|
-
|
|
213
|
+
const menuOpen = overlayOpen();
|
|
214
|
+
const candidates = unprojected(sources.keys(), () => search
|
|
150
215
|
.decorate(Array.from(doc.querySelectorAll(selector))
|
|
151
|
-
.filter((element) => !blocked(element))
|
|
216
|
+
.filter((element) => !verticalBarsPages.isDeparted(element) && (!blocked(element) || (menuOpen && isVerticalBarsSource(element))))
|
|
152
217
|
.map(readEnabledCandidate)
|
|
153
218
|
.filter((candidate) => !!candidate), blocked)
|
|
154
219
|
.filter((candidate) => !rejected.has(candidate.element) || rejected.get(candidate.element) !== signature(candidate)));
|
|
220
|
+
const back = preferredVerticalBarsBack(candidates
|
|
221
|
+
.filter((candidate) => candidate.control.kind === 'ion-back-button' && isVerticalBarsCandidate(candidate.element))
|
|
222
|
+
.map((candidate) => candidate.element), doc);
|
|
223
|
+
const selected = candidates.filter((candidate) => candidate.control.kind !== 'ion-back-button' || !isVerticalBarsCandidate(candidate.element) || candidate.element === back);
|
|
224
|
+
return menuOpen ? selected.filter((candidate) => isVerticalBarsCandidate(candidate.element)) : selected;
|
|
155
225
|
};
|
|
156
226
|
const observe = () => {
|
|
157
227
|
const wanted = new Set();
|
|
@@ -186,6 +256,7 @@ export const createRuntime = async (doc, plugin, options = {}) => {
|
|
|
186
256
|
reason = error instanceof Error ? error.message : String(error);
|
|
187
257
|
console.warn('[Native UI Shell] Returning to Web:', reason);
|
|
188
258
|
await handle.destroy();
|
|
259
|
+
win.dispatchEvent(new Event('nativeUIShellRefresh'));
|
|
189
260
|
};
|
|
190
261
|
const sync = async () => {
|
|
191
262
|
frame = 0;
|
|
@@ -215,13 +286,19 @@ export const createRuntime = async (doc, plugin, options = {}) => {
|
|
|
215
286
|
const removed = Array.from(sources.keys()).filter((element) => !retained.has(element));
|
|
216
287
|
if (removed.length) {
|
|
217
288
|
removed.forEach(restore);
|
|
218
|
-
if (!handoffInstant) {
|
|
289
|
+
if (!handoffInstant && removed.some((element) => !isVerticalBarsSource(element))) {
|
|
219
290
|
await painted();
|
|
220
291
|
if (stopped || dirty)
|
|
221
292
|
return;
|
|
222
293
|
}
|
|
223
294
|
}
|
|
224
|
-
const
|
|
295
|
+
const root = doc.querySelector('ion-app.ios-theme-vertical-bars');
|
|
296
|
+
const verticalBarEdge = root
|
|
297
|
+
? root.classList.contains('ios-theme-vertical-bars-left')
|
|
298
|
+
? 'left'
|
|
299
|
+
: 'right'
|
|
300
|
+
: undefined;
|
|
301
|
+
const data = { viewportWidth: win.innerWidth, verticalBarEdge, controls: candidates.map((candidate) => candidate.control) };
|
|
225
302
|
const serialized = JSON.stringify(data);
|
|
226
303
|
if (serialized === lastSnapshot && !forceRefresh)
|
|
227
304
|
return;
|
|
@@ -247,6 +324,7 @@ export const createRuntime = async (doc, plugin, options = {}) => {
|
|
|
247
324
|
for (const candidate of candidates) {
|
|
248
325
|
if (result.rejectedControls?.includes(candidate.control.id)) {
|
|
249
326
|
rejected.set(candidate.element, signatures.get(candidate.element));
|
|
327
|
+
setRejected(candidate.element, true);
|
|
250
328
|
dirty = true;
|
|
251
329
|
}
|
|
252
330
|
}
|
|
@@ -254,6 +332,11 @@ export const createRuntime = async (doc, plugin, options = {}) => {
|
|
|
254
332
|
const current = dirty ? new Map(currentCandidates.map((candidate) => [candidate.element, signature(candidate)])) : signatures;
|
|
255
333
|
const currentSources = new Set(currentCandidates.flatMap(candidateSources));
|
|
256
334
|
const accepted = candidates.filter((candidate) => current.get(candidate.element) === signatures.get(candidate.element));
|
|
335
|
+
accepted.forEach((candidate) => setRejected(candidate.element, false));
|
|
336
|
+
const acceptedVerticalBarsOwners = new Set(accepted.filter((candidate) => candidate.control.placement === 'vertical-bars').map((candidate) => candidate.element));
|
|
337
|
+
const acceptedVerticalBarsMembers = new Set(accepted
|
|
338
|
+
.filter((candidate) => candidate.control.placement === 'vertical-bars')
|
|
339
|
+
.flatMap((candidate) => Array.from(candidate.actions.values())));
|
|
257
340
|
const invalidated = candidates.length !== accepted.length;
|
|
258
341
|
acceptedRevision = result.revision;
|
|
259
342
|
lastSnapshot = invalidated ? '' : serialized;
|
|
@@ -261,10 +344,30 @@ export const createRuntime = async (doc, plugin, options = {}) => {
|
|
|
261
344
|
for (const element of sources.keys())
|
|
262
345
|
if (!currentSources.has(element))
|
|
263
346
|
restore(element);
|
|
347
|
+
for (const element of verticalBarsOwners) {
|
|
348
|
+
if (acceptedVerticalBarsOwners.has(element))
|
|
349
|
+
continue;
|
|
350
|
+
element.removeAttribute(verticalBarsMarker);
|
|
351
|
+
verticalBarsOwners.delete(element);
|
|
352
|
+
}
|
|
353
|
+
for (const element of acceptedVerticalBarsOwners) {
|
|
354
|
+
element.setAttribute(verticalBarsMarker, '');
|
|
355
|
+
verticalBarsOwners.add(element);
|
|
356
|
+
}
|
|
357
|
+
for (const element of verticalBarsMembers) {
|
|
358
|
+
if (acceptedVerticalBarsMembers.has(element))
|
|
359
|
+
continue;
|
|
360
|
+
element.removeAttribute(verticalBarsMemberMarker);
|
|
361
|
+
verticalBarsMembers.delete(element);
|
|
362
|
+
}
|
|
363
|
+
for (const element of acceptedVerticalBarsMembers) {
|
|
364
|
+
element.setAttribute(verticalBarsMemberMarker, '');
|
|
365
|
+
verticalBarsMembers.add(element);
|
|
366
|
+
}
|
|
264
367
|
for (const element of accepted.flatMap(candidateSources)) {
|
|
265
368
|
if (!sources.has(element)) {
|
|
266
369
|
sources.set(element, element.getAttribute('aria-hidden'));
|
|
267
|
-
crossfade.play(element, true, handoffInstant);
|
|
370
|
+
crossfade.play(element, true, handoffInstant || isVerticalBarsSource(element));
|
|
268
371
|
element.setAttribute(marker, '');
|
|
269
372
|
element.setAttribute('aria-hidden', 'true');
|
|
270
373
|
element.dispatchEvent(new CustomEvent('nativeUIShellChange'));
|
|
@@ -298,10 +401,18 @@ export const createRuntime = async (doc, plugin, options = {}) => {
|
|
|
298
401
|
finishWaiters();
|
|
299
402
|
}
|
|
300
403
|
};
|
|
301
|
-
const observation = {
|
|
404
|
+
const observation = {
|
|
405
|
+
subtree: true,
|
|
406
|
+
childList: true,
|
|
407
|
+
characterData: true,
|
|
408
|
+
attributes: true,
|
|
409
|
+
attributeOldValue: true,
|
|
410
|
+
};
|
|
302
411
|
const observer = new MutationObserver((records) => {
|
|
303
412
|
if (records.some((record) => record.attributeName !== marker &&
|
|
304
413
|
record.attributeName !== fadeMarker &&
|
|
414
|
+
!prehideOnlyMutation(record) &&
|
|
415
|
+
!(record.attributeName === 'style' && measuringPointerPages.has(record.target)) &&
|
|
305
416
|
!(record.attributeName === 'aria-hidden' &&
|
|
306
417
|
sources.has(record.target) &&
|
|
307
418
|
record.target.getAttribute('aria-hidden') === 'true')))
|
|
@@ -311,6 +422,7 @@ export const createRuntime = async (doc, plugin, options = {}) => {
|
|
|
311
422
|
const on = (target, name, callback = schedule) => target.addEventListener(name, callback, { capture: true, signal: listeners.signal });
|
|
312
423
|
const pageWill = (event) => {
|
|
313
424
|
const page = event.target;
|
|
425
|
+
verticalBarsPages.lifecycle(event);
|
|
314
426
|
getNativeSearchBindings(doc)
|
|
315
427
|
.filter((binding) => page.contains(binding.footer))
|
|
316
428
|
.forEach((binding) => search.retire(binding));
|
|
@@ -320,7 +432,9 @@ export const createRuntime = async (doc, plugin, options = {}) => {
|
|
|
320
432
|
schedule();
|
|
321
433
|
};
|
|
322
434
|
const pageDid = (event) => {
|
|
323
|
-
|
|
435
|
+
const page = event.target;
|
|
436
|
+
verticalBarsPages.lifecycle(event);
|
|
437
|
+
pages.delete(page);
|
|
324
438
|
schedule();
|
|
325
439
|
if (tabSwitchHandoff && pages.size === 0)
|
|
326
440
|
endTabSwitchHandoff();
|
|
@@ -388,6 +502,15 @@ export const createRuntime = async (doc, plugin, options = {}) => {
|
|
|
388
502
|
on(doc, name, pageWill);
|
|
389
503
|
for (const name of [LIFECYCLE_DID_ENTER, LIFECYCLE_DID_LEAVE])
|
|
390
504
|
on(doc, name, pageDid);
|
|
505
|
+
on(doc, VERTICAL_BARS_TRANSITION_CANCELED, (event) => {
|
|
506
|
+
const leaving = event.target;
|
|
507
|
+
const entering = event.detail?.entering;
|
|
508
|
+
verticalBarsPages.cancel(entering, leaving);
|
|
509
|
+
pages.delete(leaving);
|
|
510
|
+
if (entering)
|
|
511
|
+
pages.delete(entering);
|
|
512
|
+
schedule();
|
|
513
|
+
});
|
|
391
514
|
on(doc, 'ionTabsWillChange', () => {
|
|
392
515
|
armTabSwitchHandoff();
|
|
393
516
|
schedule();
|
|
@@ -408,12 +531,17 @@ export const createRuntime = async (doc, plugin, options = {}) => {
|
|
|
408
531
|
schedule();
|
|
409
532
|
});
|
|
410
533
|
}
|
|
534
|
+
const eventMenu = (event) => event.composedPath().find((target) => target instanceof HTMLElement && target.matches('ion-menu'));
|
|
411
535
|
on(doc, 'ionWillOpen', (event) => {
|
|
412
|
-
|
|
536
|
+
const menu = eventMenu(event);
|
|
537
|
+
if (menu)
|
|
538
|
+
presented.add(menu);
|
|
413
539
|
schedule();
|
|
414
540
|
});
|
|
415
541
|
on(doc, 'ionDidClose', (event) => {
|
|
416
|
-
|
|
542
|
+
const menu = eventMenu(event);
|
|
543
|
+
if (menu)
|
|
544
|
+
presented.delete(menu);
|
|
417
545
|
schedule();
|
|
418
546
|
});
|
|
419
547
|
for (const name of [
|
|
@@ -496,6 +624,7 @@ export const createRuntime = async (doc, plugin, options = {}) => {
|
|
|
496
624
|
catch {
|
|
497
625
|
}
|
|
498
626
|
style.remove();
|
|
627
|
+
doc.querySelectorAll(`.${rejectedClass}`).forEach((element) => setRejected(element, false));
|
|
499
628
|
icons.clear();
|
|
500
629
|
pages.clear();
|
|
501
630
|
presented.clear();
|
|
@@ -513,7 +642,7 @@ export const createRuntime = async (doc, plugin, options = {}) => {
|
|
|
513
642
|
event.revision < acceptedRevision ||
|
|
514
643
|
event.revision > revision ||
|
|
515
644
|
event.sequence <= lastSequence ||
|
|
516
|
-
overlayOpen())
|
|
645
|
+
overlayOpen(false))
|
|
517
646
|
return;
|
|
518
647
|
if (event.revision > acceptedRevision && event.revision === updatingRevision) {
|
|
519
648
|
pendingActivations.push(event);
|
|
@@ -532,7 +661,7 @@ export const createRuntime = async (doc, plugin, options = {}) => {
|
|
|
532
661
|
const searchAction = candidate?.control.search && [candidate.control.search.trigger.id, candidate.control.search.closeId].includes(event.id);
|
|
533
662
|
if (!searchAction && (!item || item.disabled || item.visible === false))
|
|
534
663
|
return;
|
|
535
|
-
element
|
|
664
|
+
activateProjectedElement(element);
|
|
536
665
|
lastSnapshot = '';
|
|
537
666
|
schedule();
|
|
538
667
|
};
|
|
@@ -569,9 +698,14 @@ export const createRuntime = async (doc, plugin, options = {}) => {
|
|
|
569
698
|
suspended.add(scopes);
|
|
570
699
|
await flush();
|
|
571
700
|
await new Promise((resolve) => win.requestAnimationFrame(() => resolve()));
|
|
572
|
-
return () => {
|
|
701
|
+
return (canceled = false) => {
|
|
573
702
|
suspended.delete(scopes);
|
|
574
|
-
scopes.
|
|
703
|
+
if (canceled || !scopes.some((scope) => scope.closest('ion-app.ios-theme-vertical-bars'))) {
|
|
704
|
+
scopes.forEach((scope) => pages.delete(scope));
|
|
705
|
+
if (canceled) {
|
|
706
|
+
verticalBarsPages.cancel(scopes[0], scopes[1]);
|
|
707
|
+
}
|
|
708
|
+
}
|
|
575
709
|
schedule();
|
|
576
710
|
};
|
|
577
711
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"candidate.d.ts","sourceRoot":"","sources":["../../../src/native/shared/candidate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAItF,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAClC,KAAK,EAAE;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,WAAW,CAAA;KAAE,EAAE,CAAC;CACnE;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,EAAE,WAAW,KAAK,MAAM,CAAC;AAGxD,eAAO,MAAM,eAAe,GAAI,SAAS,WAAW,EAAE,MAAM,sBAAsB,EAAE,IAAI,QAAQ,KAAG,SAgBlG,CAAC;AAGF,eAAO,MAAM,UAAU,GACrB,WAAW,SAAS,EACpB,OAAO,WAAW,EAClB,IAAI,QAAQ,EACZ,UAAS,UAAkB,EAC3B,cAAmB,KAClB,SAAS,GAAG,
|
|
1
|
+
{"version":3,"file":"candidate.d.ts","sourceRoot":"","sources":["../../../src/native/shared/candidate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAItF,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAClC,KAAK,EAAE;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,WAAW,CAAA;KAAE,EAAE,CAAC;CACnE;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,EAAE,WAAW,KAAK,MAAM,CAAC;AAGxD,eAAO,MAAM,eAAe,GAAI,SAAS,WAAW,EAAE,MAAM,sBAAsB,EAAE,IAAI,QAAQ,KAAG,SAgBlG,CAAC;AAGF,eAAO,MAAM,UAAU,GACrB,WAAW,SAAS,EACpB,OAAO,WAAW,EAClB,IAAI,QAAQ,EACZ,UAAS,UAAkB,EAC3B,cAAmB,KAClB,SAAS,GAAG,SAsEd,CAAC"}
|