@rdlabo/ionic-theme-ios27 1.2.0 → 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/dist/css/components/ion-button.css +1 -1
- package/dist/css/components/ion-toolbar.css +1 -1
- package/dist/css/ionic-theme-ios27.css +1 -1
- package/dist/css/vertical-bars.css +1 -1
- package/dist/native/components/index.js +2 -2
- package/dist/native/components/index.js.map +1 -1
- package/dist/native/prehide.d.ts.map +1 -1
- package/dist/native/prehide.js +6 -2
- package/dist/native/prehide.js.map +1 -1
- package/dist/native/runtime.d.ts.map +1 -1
- package/dist/native/runtime.js +4 -3
- package/dist/native/runtime.js.map +1 -1
- package/dist/native/shared/dom.d.ts +2 -0
- package/dist/native/shared/dom.d.ts.map +1 -1
- package/dist/native/shared/dom.js +5 -1
- package/dist/native/shared/dom.js.map +1 -1
- package/dist/native/vertical-bars-web.d.ts.map +1 -1
- package/dist/native/vertical-bars-web.js +4 -2
- package/dist/native/vertical-bars-web.js.map +1 -1
- package/dist/native-integration/index.d.ts +1 -1
- package/dist/native-integration/index.js.map +1 -1
- package/dist/native-integration/transition.d.ts +1 -1
- package/dist/native-integration/transition.js.map +1 -1
- package/dist/sheets-of-glass/animations.d.ts +1 -1
- package/dist/sheets-of-glass/animations.js +1 -1
- package/dist/sheets-of-glass/animations.js.map +1 -1
- package/dist/sheets-of-glass/index.js +1 -1
- package/dist/sheets-of-glass/index.js.map +1 -1
- package/dist/tab-bar-searchable/animations/enter.d.ts +1 -1
- package/dist/tab-bar-searchable/animations/enter.d.ts.map +1 -1
- package/dist/tab-bar-searchable/animations/enter.js +1 -1
- package/dist/tab-bar-searchable/animations/enter.js.map +1 -1
- package/dist/tab-bar-searchable/animations/leave.d.ts +1 -1
- package/dist/tab-bar-searchable/animations/leave.d.ts.map +1 -1
- package/dist/tab-bar-searchable/animations/leave.js +1 -1
- package/dist/tab-bar-searchable/animations/leave.js.map +1 -1
- package/dist/tab-bar-searchable/index.js +1 -1
- package/dist/tab-bar-searchable/index.js.map +1 -1
- package/dist/transition/index.d.ts +1 -1
- package/dist/transition/index.js +1 -1
- package/dist/transition/index.js.map +1 -1
- package/dist/transition/ios.transition.d.ts +1 -1
- package/dist/transition/ios.transition.js.map +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js.map +1 -1
- package/docs/native-ui-shell.md +2 -2
- package/docs/vertical-bars.md +3 -1
- package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellSearchController.swift +65 -91
- package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellTabBar.swift +9 -3
- package/ios/Sources/IonicNativeUIShellPlugin/Components/ShellVerticalBars.swift +4 -2
- package/package.json +1 -1
- package/src/native/components/index.ts +3 -2
- package/src/native/prehide.ts +6 -1
- package/src/native/runtime.ts +5 -1
- package/src/native/shared/dom.ts +14 -0
- package/src/native/vertical-bars-web.ts +11 -1
- package/src/native-integration/index.ts +1 -1
- package/src/native-integration/transition.ts +1 -1
- package/src/sheets-of-glass/animations.ts +2 -2
- package/src/sheets-of-glass/index.ts +2 -2
- package/src/styles/components/ion-button.scss +47 -0
- package/src/styles/components/ion-toolbar.scss +62 -7
- package/src/styles/vertical-bars.scss +23 -0
- package/src/tab-bar-searchable/animations/enter.ts +2 -1
- package/src/tab-bar-searchable/animations/leave.ts +2 -1
- package/src/tab-bar-searchable/index.ts +1 -1
- package/src/transition/index.ts +3 -3
- package/src/transition/ios.transition.ts +1 -1
- package/src/utils.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","names":[],"sources":["../../src/native/runtime.ts"],"sourcesContent":["import { inVerticalBarsSurface, topModal, modalUsesVerticalBars, modalVerticalBarFrame } from './shared/modal';\nimport type { PluginListenerHandle } from '@capacitor/core';\nimport { LIFECYCLE_WILL_ENTER, LIFECYCLE_WILL_LEAVE, LIFECYCLE_DID_ENTER, LIFECYCLE_DID_LEAVE } from '@ionic/core';\nimport { VERTICAL_BARS_TRANSITION_CANCELED, getNativeSearchBindings, setNativeUIShellIntegration } from '../native-integration';\nimport { createSearchSupport } from './components/searchable-tabs';\nimport type {\n ShellActivation,\n ShellSnapshot,\n NativeUIShellHandle,\n NativeUIShellOptions,\n NativeUIShellPlugin,\n NativeUIShellStatus,\n} from './definitions';\nimport { readCandidate, selector, shadowSelector, motionSelector, isVerticalBarsCandidate } from './components';\nimport {\n activateProjectedElement,\n createVerticalBarsPageState,\n isVerticalBarsSource,\n preferredVerticalBarsBack,\n marker,\n prehideOnlyMutation,\n rejectedClass,\n unprojected,\n} from './shared/dom';\nimport { createIconRenderer } from './shared/icons';\nimport type { Candidate } from './shared/candidate';\nimport { CSS_MOTION_EVENTS } from './shared/events';\nimport { createCrossfade, fadeMarker } from './shared/crossfade';\n\nconst overlays = 'ion-modal, ion-popover, ion-alert, ion-action-sheet, ion-loading, ion-picker, ion-toast, ion-menu';\nconst overlayNames = ['Modal', 'Popover', 'Alert', 'ActionSheet', 'Loading', 'Picker', 'Toast'];\nconst verticalBarsMarker = 'data-native-ui-shell-vertical-bars';\nconst verticalBarsMemberMarker = 'data-native-ui-shell-vertical-bars-member';\n\n// A failed bridge must not leave the source inaccessible indefinitely.\nconst bounded = <T>(promise: Promise<T>): Promise<T> =>\n new Promise((resolve, reject) => {\n const timer = setTimeout(() => reject(new Error('Native UI Shell bridge timed out')), 5000);\n promise.then(resolve, reject).finally(() => clearTimeout(timer));\n });\n\nexport const createRuntime = async (\n doc: Document,\n plugin: NativeUIShellPlugin,\n options: NativeUIShellOptions = {},\n nativeVerticalBars: () => boolean = () => true,\n verticalBarsOnly = false,\n): Promise<NativeUIShellHandle> => {\n const win = doc.defaultView!;\n const icons = createIconRenderer();\n const crossfade = createCrossfade(win);\n const ids = new WeakMap<Element, string>();\n let rejected = new WeakMap<HTMLElement, string>();\n const sources = new Map<HTMLElement, string | null>();\n const verticalBarsOwners = new Set<HTMLElement>();\n const verticalBarsMembers = new Set<HTMLElement>();\n const suspended = new Set<HTMLElement[]>();\n const pages = new Set<HTMLElement>();\n const verticalBarsPages = createVerticalBarsPageState();\n const presented = new Set<HTMLElement>();\n const manualSuspensions = new Set<symbol>();\n const moving = new Map<HTMLElement, Set<string>>();\n const observed = new Set<Element | ShadowRoot>();\n const listeners = new AbortController();\n let actions = new Map<string, HTMLElement>();\n let nextId = 0;\n let revision = 0;\n let acceptedRevision = 0;\n let updatingRevision: number | undefined;\n let pendingActivations: ShellActivation[] = [];\n let lastSequence = 0;\n let lastSnapshot = '';\n let viewport = `${win.innerWidth}:${win.innerHeight}`;\n let forceRefresh = false;\n let dirty = false;\n let pending = false;\n let stopped = false;\n /** True while a tab-switch handoff should skip crossfade. */\n let tabSwitchHandoff = false;\n /** Keep instant updates until this time — DidLeave often precedes the retire sync. */\n let handoffUntil = 0;\n /** Tab switch armed while a sync was already in flight; extend instant past that sync. */\n let handoffAcrossPending = false;\n /** Captured at the start of each sync so an in-flight update keeps a stable duration. */\n let handoffInstant = false;\n /** Retire native controls immediately as a modal starts covering the page. */\n let modalPresentHandoff = false;\n let frame = 0;\n let updates = 0;\n let reason: string | undefined;\n let listener: PluginListenerHandle | undefined;\n let searchListener: PluginListenerHandle | undefined;\n let waiters: (() => void)[] = [];\n const control = (kind: Candidate['control']['kind']): keyof NonNullable<NativeUIShellOptions['controls']> => {\n if (kind === 'ion-tab-bar') return 'tabs';\n if (kind === 'ion-segment') return 'segment';\n if (kind === 'ion-fab') return 'fab';\n return 'toolbar';\n };\n const controlEnabled = (candidate: Candidate) => {\n const controls = options.controls;\n return controls === undefined || controls[control(candidate.control.kind)] === true;\n };\n const id = (element: Element) => {\n let value = ids.get(element);\n if (!value) {\n value = `shell-${++nextId}`;\n ids.set(element, value);\n }\n return value;\n };\n const style = doc.createElement('style');\n const hidden = `[${marker}]:not([${fadeMarker}])`;\n style.textContent = `${hidden}, ${hidden} *, ${hidden}::before, ${hidden}::after, ${hidden}::part(native) { visibility: hidden !important; }\n [${marker}], [${marker}] * { pointer-events: none !important; }\n /* Ionic disables the covered page while a menu is open. VerticalBars rail\n controls remain outside that page; zero specificity preserves any\n pointer-events rule supplied by the application itself. */\n :where(.menu-content-open) :where([${verticalBarsMarker}]) {\n pointer-events: auto;\n }\n :where(.menu-content-open) :where([${verticalBarsMarker}]) > :where(:not([${verticalBarsMemberMarker}])) {\n pointer-events: none;\n }`;\n\n const restore = (element: HTMLElement) => {\n lastSnapshot = '';\n search.release(element);\n element.removeAttribute(marker);\n if (!stopped) crossfade.play(element, false, isVerticalBarsSource(element) ? !element.matches('ion-tab-bar') : handoffInstant);\n if (element.getAttribute('aria-hidden') === 'true') {\n const previous = sources.get(element);\n if (previous == null) element.removeAttribute('aria-hidden');\n else element.setAttribute('aria-hidden', previous);\n }\n sources.delete(element);\n element.dispatchEvent(new CustomEvent('nativeUIShellChange'));\n };\n const restoreAll = () => {\n Array.from(sources.keys()).forEach(restore);\n verticalBarsOwners.forEach((element) => element.removeAttribute(verticalBarsMarker));\n verticalBarsOwners.clear();\n verticalBarsMembers.forEach((element) => element.removeAttribute(verticalBarsMemberMarker));\n verticalBarsMembers.clear();\n };\n const finishWaiters = () => {\n const current = waiters;\n waiters = [];\n current.forEach((resolve) => resolve());\n };\n const schedule = () => {\n if (stopped) return;\n dirty = true;\n if (!pending && !frame) frame = win.requestAnimationFrame(() => void sync());\n };\n const search = createSearchSupport(doc, id, schedule);\n const candidateSources = (candidate: Candidate) => candidate.sources ?? [candidate.element];\n const setRejected = (element: HTMLElement, value: boolean) => {\n element.classList.toggle(rejectedClass, value);\n };\n const measuringPointerPages = new WeakSet<HTMLElement>();\n const readEnabledCandidate = (element: HTMLElement): Candidate | undefined => {\n if (element.matches('ion-back-button') && element.closest('ion-app.ios-theme-vertical-bars') && !isVerticalBarsCandidate(element))\n return;\n if (verticalBarsOnly && !isVerticalBarsCandidate(element)) return;\n const pointerPage = isVerticalBarsCandidate(element) ? element.closest<HTMLElement>('.ion-page') : undefined;\n let candidate: Candidate | undefined;\n if (pointerPage && getComputedStyle(pointerPage).pointerEvents === 'none') {\n const previous = pointerPage.style.getPropertyValue('pointer-events');\n const priority = pointerPage.style.getPropertyPriority('pointer-events');\n const hadStyle = pointerPage.hasAttribute('style');\n measuringPointerPages.add(pointerPage);\n pointerPage.style.setProperty('pointer-events', 'auto', 'important');\n try {\n candidate = readCandidate(element, id, options);\n } finally {\n if (previous) pointerPage.style.setProperty('pointer-events', previous, priority);\n else pointerPage.style.removeProperty('pointer-events');\n if (!hadStyle && !pointerPage.style.length) pointerPage.removeAttribute('style');\n win.setTimeout(() => measuringPointerPages.delete(pointerPage), 0);\n }\n } else candidate = readCandidate(element, id, options);\n if (candidate && isVerticalBarsCandidate(element)) {\n if (!nativeVerticalBars()) return undefined;\n candidate.control.placement = 'vertical-bars';\n if (['ion-button', 'ion-buttons', 'ion-menu-button'].includes(candidate.control.kind)) {\n const slot = (element.matches('ion-buttons') ? element : (element.closest('ion-buttons') ?? element)).getAttribute('slot');\n if (slot === 'start' || slot === 'end') candidate.control.toolbarSlot = slot;\n }\n }\n return candidate && controlEnabled(candidate) ? candidate : undefined;\n };\n const flush = async () => {\n if (stopped) return;\n schedule();\n try {\n await bounded(new Promise<void>((resolve) => waiters.push(resolve)));\n } catch (error) {\n await fail(error);\n }\n };\n const blocked = (element: HTMLElement) =>\n verticalBarsPages.isDeparted(element) ||\n (!isVerticalBarsSource(element) &&\n (Array.from(suspended).some((scopes) => scopes.some((scope) => scope.contains(element))) ||\n Array.from(pages).some((scope) => scope.contains(element)) ||\n Array.from(moving.keys()).some((surface) => surface.contains(element))));\n const painted = () => new Promise<void>((resolve) => win.requestAnimationFrame(() => win.requestAnimationFrame(() => resolve())));\n const overlayOpen = (includeMenu = true, allowModal = false) => {\n const modal = topModal(doc);\n const ignored = (element: Element) => allowModal && !!modal && modalUsesVerticalBars(modal) && element.matches('ion-modal');\n for (const element of presented) if (!element.isConnected) presented.delete(element);\n const presentedOverlayOpen = Array.from(presented).some(\n (element) => !ignored(element) && (includeMenu || !element.matches('ion-menu')),\n );\n return (\n manualSuspensions.size > 0 ||\n presentedOverlayOpen ||\n Array.from(doc.querySelectorAll(overlays)).some(\n (element) =>\n !ignored(element) &&\n (includeMenu || !element.matches('ion-menu')) &&\n ((element as Element & { presented?: boolean }).presented || element.classList.contains('show-menu')),\n )\n );\n };\n // Compare source data before PNG rendering mutates each item's payload.\n const signature = (candidate: Candidate) =>\n JSON.stringify({ control: candidate.control, icons: candidate.icons.map(({ source }) => source) });\n const read = (): Candidate[] => {\n search.keepSearchTabsVisible();\n for (const page of pages) if (!page.isConnected) pages.delete(page);\n for (const surface of moving.keys()) if (!surface.isConnected) moving.delete(surface);\n if (doc.hidden || overlayOpen(false, true)) return [];\n if (win.visualViewport && (win.visualViewport.scale !== 1 || win.visualViewport.offsetTop !== 0) && !search.hasActive()) return [];\n const menuOpen = overlayOpen();\n const candidates = unprojected(sources.keys(), () =>\n search\n .decorate(\n Array.from(doc.querySelectorAll<HTMLElement>(selector))\n .filter(\n (element) =>\n inVerticalBarsSurface(element) &&\n !verticalBarsPages.isDeparted(element) &&\n (!blocked(element) || (menuOpen && isVerticalBarsSource(element))),\n )\n .map(readEnabledCandidate)\n .filter((candidate): candidate is Candidate => !!candidate),\n blocked,\n )\n .filter((candidate) => !rejected.has(candidate.element) || rejected.get(candidate.element) !== signature(candidate)),\n );\n const back = preferredVerticalBarsBack(\n candidates\n .filter((candidate) => candidate.control.kind === 'ion-back-button' && isVerticalBarsCandidate(candidate.element))\n .map((candidate) => candidate.element),\n doc,\n );\n const selected = candidates.filter(\n (candidate) =>\n candidate.control.kind !== 'ion-back-button' || !isVerticalBarsCandidate(candidate.element) || candidate.element === back,\n );\n return menuOpen ? selected.filter((candidate) => isVerticalBarsCandidate(candidate.element)) : selected;\n };\n const observe = () => {\n const wanted = new Set<Element | ShadowRoot>();\n for (const element of Array.from(doc.querySelectorAll<HTMLElement>(selector))) {\n wanted.add(element);\n if (element.parentElement) wanted.add(element.parentElement);\n const inspectShadow = (node: Element) => {\n if (node.shadowRoot) {\n wanted.add(node.shadowRoot);\n node.shadowRoot.querySelectorAll('ion-icon').forEach(inspectShadow);\n }\n };\n inspectShadow(element);\n element.querySelectorAll(shadowSelector).forEach(inspectShadow);\n }\n // Reconnect only when the set changes; no per-frame observer allocation.\n if (wanted.size === observed.size && Array.from(wanted).every((element) => observed.has(element))) return;\n observer.disconnect();\n resize.disconnect();\n observed.clear();\n observer.observe(doc.documentElement, observation);\n for (const element of wanted) {\n observed.add(element);\n if (element instanceof ShadowRoot) observer.observe(element, observation);\n else resize.observe(element);\n }\n };\n const fail = async (error: unknown) => {\n reason = error instanceof Error ? error.message : String(error);\n console.warn('[Native UI Shell] Returning to Web:', reason);\n await handle.destroy();\n // The Web fallback re-evaluates eligibility once native projection is stopped.\n win.dispatchEvent(new Event('nativeUIShellRefresh'));\n };\n const sync = async () => {\n frame = 0;\n dirty = false;\n pending = true;\n handoffInstant = tabSwitchHandoff || handoffAcrossPending || modalPresentHandoff || win.performance.now() < handoffUntil;\n modalPresentHandoff = false;\n try {\n const size = `${win.innerWidth}:${win.innerHeight}`;\n // WebKit can resize before Ionic's fixed DOM positions catch up.\n // Measure on the next frame instead of retiring a valid native search.\n if (viewport !== size) {\n viewport = size;\n dirty = true;\n return;\n }\n observe();\n const candidates = read();\n const signatures = new Map(candidates.map((candidate) => [candidate.element, signature(candidate)]));\n for (const candidate of candidates) {\n for (const icon of candidate.icons) {\n const field = icon.field ?? 'icon';\n icon.item[field] = await icons.render(\n icon.source,\n field === 'icon' ? icon.item.iconWidth! : icon.item.closeIconWidth!,\n field === 'icon' ? icon.item.iconHeight! : icon.item.closeIconHeight!,\n );\n }\n }\n if (stopped || dirty) return;\n const retained = new Set(candidates.flatMap(candidateSources));\n const removed = Array.from(sources.keys()).filter((element) => !retained.has(element));\n if (removed.length) {\n // Restore the source and let WebKit paint before removing its native cover.\n removed.forEach(restore);\n // The outgoing tab is no longer visible, so waiting two frames only leaves its\n // native snapshot over the destination. Stack transitions still need the paint.\n if (!handoffInstant && removed.some((element) => !isVerticalBarsSource(element))) {\n await painted();\n if (stopped || dirty) return;\n }\n }\n const root = doc.querySelector('ion-app.ios-theme-vertical-bars');\n const verticalBarEdge: 'left' | 'right' | undefined = root\n ? root.classList.contains('ios-theme-vertical-bars-left')\n ? 'left'\n : 'right'\n : undefined;\n const modal = topModal(doc);\n const verticalBarFrame = modal && modalUsesVerticalBars(modal) ? modalVerticalBarFrame(modal) : undefined;\n const data = {\n verticalBarFrame,\n viewportWidth: win.innerWidth,\n verticalBarEdge,\n controls: candidates.map((candidate) => candidate.control),\n };\n const serialized = JSON.stringify(data);\n if (serialized === lastSnapshot && !forceRefresh) return;\n const snapshot: ShellSnapshot = { ...data, revision: ++revision, transitionDuration: crossfade.duration(handoffInstant) };\n // A native visibility notification during this update must survive its ack.\n forceRefresh = false;\n updates++;\n updatingRevision = snapshot.revision;\n const result = await bounded(plugin.update(snapshot));\n if (stopped) return;\n if (result.revision !== snapshot.revision) throw new Error('Native UI Shell revision mismatch');\n if (`${win.innerWidth}:${win.innerHeight}` !== size) {\n lastSnapshot = '';\n dirty = true;\n return;\n }\n if (result.rejectedSearches?.length) {\n search.reject(result.rejectedSearches);\n lastSnapshot = '';\n dirty = true;\n }\n for (const candidate of candidates) {\n if (result.rejectedControls?.includes(candidate.control.id)) {\n rejected.set(candidate.element, signatures.get(candidate.element)!);\n setRejected(candidate.element, true);\n dirty = true;\n }\n }\n // A page mutation must not tear down unchanged shared controls such as tabs.\n const currentCandidates = dirty ? read() : candidates;\n const current = dirty ? new Map(currentCandidates.map((candidate) => [candidate.element, signature(candidate)])) : signatures;\n const currentSources = new Set(currentCandidates.flatMap(candidateSources));\n const accepted = candidates.filter((candidate) => current.get(candidate.element) === signatures.get(candidate.element));\n accepted.forEach((candidate) => setRejected(candidate.element, false));\n const acceptedVerticalBarsOwners = new Set(\n accepted.filter((candidate) => candidate.control.placement === 'vertical-bars').map((candidate) => candidate.element),\n );\n const acceptedVerticalBarsMembers = new Set(\n accepted\n .filter((candidate) => candidate.control.placement === 'vertical-bars')\n .flatMap((candidate) => Array.from(candidate.actions.values())),\n );\n const invalidated = candidates.length !== accepted.length;\n acceptedRevision = result.revision;\n lastSnapshot = invalidated ? '' : serialized;\n actions = new Map(\n candidates.filter((candidate) => current.has(candidate.element)).flatMap((candidate) => Array.from(candidate.actions)),\n );\n // Keep an existing cover while its content catches up. Only an ineligible\n // source needs to return to Web; new sources still require an exact ack.\n for (const element of sources.keys()) if (!currentSources.has(element)) restore(element);\n for (const element of verticalBarsOwners) {\n if (acceptedVerticalBarsOwners.has(element)) continue;\n element.removeAttribute(verticalBarsMarker);\n verticalBarsOwners.delete(element);\n }\n for (const element of acceptedVerticalBarsOwners) {\n element.setAttribute(verticalBarsMarker, '');\n verticalBarsOwners.add(element);\n }\n for (const element of verticalBarsMembers) {\n if (acceptedVerticalBarsMembers.has(element)) continue;\n element.removeAttribute(verticalBarsMemberMarker);\n verticalBarsMembers.delete(element);\n }\n for (const element of acceptedVerticalBarsMembers) {\n element.setAttribute(verticalBarsMemberMarker, '');\n verticalBarsMembers.add(element);\n }\n for (const element of accepted.flatMap(candidateSources)) {\n const newlyProjected = !sources.has(element) || !element.hasAttribute(marker);\n if (!sources.has(element)) {\n sources.set(element, element.getAttribute('aria-hidden'));\n crossfade.play(element, true, handoffInstant || isVerticalBarsSource(element));\n }\n element.setAttribute(marker, '');\n element.setAttribute('aria-hidden', 'true');\n if (newlyProjected) element.dispatchEvent(new CustomEvent('nativeUIShellChange'));\n }\n const received = pendingActivations;\n pendingActivations = [];\n received.forEach(activate);\n await crossfade.settled();\n if (invalidated) {\n dirty = true;\n // Sources that became ineligible must paint before their cover is removed.\n await painted();\n }\n } catch (error) {\n await fail(error);\n } finally {\n updatingRevision = undefined;\n pendingActivations = [];\n // A refresh received before the ack must also invalidate that ack's rejects.\n if (forceRefresh) rejected = new WeakMap();\n // A tab switch mid-update (or a dirty follow-up) must keep instant through the retire sync.\n if (!stopped && (handoffAcrossPending || (handoffInstant && dirty))) {\n handoffUntil = Math.max(handoffUntil, win.performance.now() + 400);\n }\n handoffAcrossPending = false;\n pending = false;\n if (dirty && !stopped) schedule();\n else finishWaiters();\n }\n };\n const observation: MutationObserverInit = {\n subtree: true,\n childList: true,\n characterData: true,\n attributes: true,\n attributeOldValue: true,\n };\n const observer = new MutationObserver((records) => {\n if (\n records.some(\n (record) =>\n record.attributeName !== marker &&\n record.attributeName !== fadeMarker &&\n !prehideOnlyMutation(record) &&\n !(record.attributeName === 'style' && measuringPointerPages.has(record.target as HTMLElement)) &&\n !(\n record.attributeName === 'aria-hidden' &&\n sources.has(record.target as HTMLElement) &&\n (record.target as Element).getAttribute('aria-hidden') === 'true'\n ),\n )\n )\n schedule();\n });\n const resize = new ResizeObserver(schedule);\n const on = (target: EventTarget, name: string, callback: EventListener = schedule) =>\n target.addEventListener(name, callback, { capture: true, signal: listeners.signal });\n const pageWill: EventListener = (event) => {\n const page = event.target as HTMLElement;\n verticalBarsPages.lifecycle(event);\n getNativeSearchBindings(doc)\n .filter((binding) => page.contains(binding.footer))\n .forEach((binding) => search.retire(binding));\n // Angular updates the URL before willLeave, but keeps ion-tab-bar.selectedTab on the\n // leaving tab until DidChange. A mismatch means this leave is a tab switch, not a stack push.\n if (event.type === LIFECYCLE_WILL_LEAVE) beginTabSwitchHandoffIfNeeded(page);\n pages.add(page);\n schedule();\n };\n const pageDid: EventListener = (event) => {\n const page = event.target as HTMLElement;\n verticalBarsPages.lifecycle(event);\n pages.delete(page);\n schedule();\n if (tabSwitchHandoff && pages.size === 0) endTabSwitchHandoff();\n };\n const tabOfPath = (tabs: Element, pathname: string) => {\n let best: { tab: string; length: number } | undefined;\n for (const button of Array.from(tabs.querySelectorAll('ion-tab-button'))) {\n const tab = button.getAttribute('tab');\n const href = button.getAttribute('href')?.split(/[?#]/)[0];\n if (!tab || !href) continue;\n if (pathname === href || pathname.startsWith(`${href}/`)) {\n if (!best || href.length > best.length) best = { tab, length: href.length };\n }\n }\n return best?.tab;\n };\n const armTabSwitchHandoff = () => {\n tabSwitchHandoff = true;\n // Retiring outgoing controls often lands in a later async sync than WillLeave/DidChange.\n handoffUntil = Math.max(handoffUntil, win.performance.now() + 400);\n // The in-flight sync already captured handoffInstant=false; hold instant for the next one.\n if (pending) handoffAcrossPending = true;\n };\n const beginTabSwitchHandoffIfNeeded = (page: HTMLElement) => {\n const tabs = page.closest('ion-tabs');\n if (!tabs) return;\n const bar = tabs.querySelector('ion-tab-bar');\n const selected =\n (bar && 'selectedTab' in bar ? String((bar as HTMLElement & { selectedTab?: string }).selectedTab ?? '') : '') ||\n tabs.querySelector('ion-tab-button.tab-selected')?.getAttribute('tab') ||\n undefined;\n const destination = tabOfPath(tabs, win.location.pathname);\n if (selected && destination && selected !== destination) armTabSwitchHandoff();\n };\n // DidChange / pageDid can land in the same turn as WillLeave. Clear the sticky flag on the\n // next frame; handoffUntil / handoffAcrossPending still cover the async retire sync.\n const endTabSwitchHandoff = () => {\n win.requestAnimationFrame(() => {\n if (stopped || !tabSwitchHandoff) return;\n tabSwitchHandoff = false;\n schedule();\n });\n };\n const motion: EventListener = (event) => {\n const target = event.target as HTMLElement;\n if (!target.matches?.(motionSelector)) return;\n const key = (event as TransitionEvent).propertyName ?? (event as AnimationEvent).animationName;\n if (event.type === CSS_MOTION_EVENTS.transitionRun || event.type === CSS_MOTION_EVENTS.animationStart) {\n const keys = moving.get(target) ?? new Set<string>();\n keys.add(key);\n moving.set(target, keys);\n } else {\n moving.get(target)?.delete(key);\n if (!moving.get(target)?.size) moving.delete(target);\n }\n schedule();\n };\n for (const name of Object.values(CSS_MOTION_EVENTS)) on(doc, name, motion);\n for (const name of [LIFECYCLE_WILL_ENTER, LIFECYCLE_WILL_LEAVE]) on(doc, name, pageWill);\n for (const name of [LIFECYCLE_DID_ENTER, LIFECYCLE_DID_LEAVE]) on(doc, name, pageDid);\n on(doc, VERTICAL_BARS_TRANSITION_CANCELED, (event) => {\n const leaving = event.target as HTMLElement;\n const entering = (event as CustomEvent<{ entering?: HTMLElement }>).detail?.entering;\n verticalBarsPages.cancel(entering, leaving);\n pages.delete(leaving);\n if (entering) pages.delete(entering);\n schedule();\n });\n on(doc, 'ionTabsWillChange', () => {\n // Vanilla ion-tabs dispatches DOM events; @ionic/angular uses EventEmitters instead.\n armTabSwitchHandoff();\n schedule();\n });\n on(doc, 'ionTabsDidChange', endTabSwitchHandoff);\n for (const name of overlayNames) {\n on(doc, `ion${name}WillPresent`, (event) => {\n presented.add(event.target as HTMLElement);\n if (name === 'Modal') {\n modalPresentHandoff = true;\n // WillPresent may arrive while another bridge update is awaiting its ack.\n // Make that retirement instant too instead of racing the modal animation.\n if (pending) handoffInstant = true;\n }\n schedule();\n });\n on(doc, `ion${name}DidDismiss`, (event) => {\n presented.delete(event.target as HTMLElement);\n schedule();\n });\n }\n const eventMenu = (event: Event) =>\n event.composedPath().find((target): target is HTMLElement => target instanceof HTMLElement && target.matches('ion-menu'));\n on(doc, 'ionWillOpen', (event) => {\n const menu = eventMenu(event);\n if (menu) presented.add(menu);\n schedule();\n });\n on(doc, 'ionDidClose', (event) => {\n const menu = eventMenu(event);\n if (menu) presented.delete(menu);\n schedule();\n });\n for (const name of [\n 'ionChange',\n 'ionSelect',\n 'ionImgDidLoad',\n CSS_MOTION_EVENTS.transitionEnd,\n CSS_MOTION_EVENTS.animationEnd,\n 'focusin',\n 'focusout',\n ])\n on(doc, name);\n const refreshLayout = () => {\n rejected = new WeakMap();\n forceRefresh = true;\n schedule();\n };\n on(doc, 'visibilitychange', () => {\n if (doc.hidden) {\n getNativeSearchBindings(doc).forEach((binding) => search.retire(binding));\n schedule();\n } else refreshLayout();\n });\n on(win, 'resize', refreshLayout);\n on(win, 'keyboardWillShow', () => search.keyboard(true));\n on(win, 'keyboardWillHide', () => search.keyboard(false));\n on(win, 'scroll');\n on(win.matchMedia('(prefers-color-scheme: dark)'), 'change');\n on(win, 'nativeUIShellRefresh', (event) => {\n if ((event as Event & { retireSearch?: boolean }).retireSearch)\n getNativeSearchBindings(doc).forEach((binding) => search.retire(binding));\n refreshLayout();\n });\n if (win.visualViewport) {\n on(win.visualViewport, 'resize', refreshLayout);\n on(win.visualViewport, 'scroll');\n }\n const handle: NativeUIShellHandle = {\n getStatus: (): NativeUIShellStatus => ({\n state: stopped ? 'stopped' : sources.size ? 'native' : 'web',\n projected: sources.size,\n updates,\n reason,\n }),\n async suspend() {\n const token = Symbol();\n let resumed = false;\n if (!stopped) {\n manualSuspensions.add(token);\n getNativeSearchBindings(doc).forEach((binding) => search.retire(binding));\n await flush();\n }\n return {\n async resume() {\n if (resumed) return;\n resumed = true;\n if (stopped || !manualSuspensions.delete(token)) return;\n await flush();\n },\n };\n },\n async destroy() {\n if (stopped) return;\n stopped = true;\n setNativeUIShellIntegration(doc);\n win.cancelAnimationFrame(frame);\n listeners.abort();\n observer.disconnect();\n resize.disconnect();\n observed.clear();\n actions.clear();\n pendingActivations = [];\n search.destroy();\n crossfade.destroy();\n restoreAll();\n if (!doc.hidden) await painted();\n try {\n await bounded(plugin.clear({ revision: ++revision }));\n } catch {\n /* Always restore the Web, even after bridge loss. */\n }\n style.remove();\n doc.querySelectorAll<HTMLElement>(`.${rejectedClass}`).forEach((element) => setRejected(element, false));\n icons.clear();\n pages.clear();\n presented.clear();\n manualSuspensions.clear();\n moving.clear();\n suspended.clear();\n await listener?.remove().catch(() => {});\n await searchListener?.remove().catch(() => {});\n finishWaiters();\n },\n };\n const activate = (event: ShellActivation) => {\n if (\n stopped ||\n doc.hidden ||\n event.revision < acceptedRevision ||\n event.revision > revision ||\n event.sequence <= lastSequence ||\n overlayOpen(false, true)\n )\n return;\n // Native may send input before update() resolves on the JS bridge.\n // Revalidate it after ownership is accepted, using the same action path.\n if (event.revision > acceptedRevision && event.revision === updatingRevision) {\n pendingActivations.push(event);\n return;\n }\n lastSequence = event.sequence;\n const element = actions.get(event.id);\n if (!element) return;\n const owner = Array.from(sources.keys()).find((source) => source === element || source.contains(element));\n if (!owner || !inVerticalBarsSurface(owner)) return;\n const direct = !blocked(owner) && unprojected(sources.keys(), () => readEnabledCandidate(owner));\n const candidate = direct || read().find((candidate) => candidate.actions.has(event.id));\n const item = candidate?.control.items.find((item) => item.id === event.id);\n const searchAction =\n candidate?.control.search && [candidate.control.search.trigger.id, candidate.control.search.closeId].includes(event.id);\n if (!searchAction && (!item || item.disabled || item.visible === false)) return;\n // The original Ionic host owns form submission, routerLink and selection events.\n activateProjectedElement(element);\n lastSnapshot = ''; // Reconcile even if Ionic rejects the proposed native selection.\n schedule();\n };\n try {\n listener = await bounded(plugin.addListener('activate', activate));\n searchListener = await bounded(\n plugin.addListener('search', (event) => {\n if (stopped || doc.hidden || event.revision < acceptedRevision || event.revision > revision || overlayOpen()) return;\n search.event(event);\n }),\n );\n doc.head.append(style);\n observer.observe(doc.documentElement, observation);\n setNativeUIShellIntegration(doc, {\n async search(binding, active, focus) {\n if (!getNativeSearchBindings(doc).includes(binding) || !search.projected(binding)) return false;\n if (!active) {\n search.setStatus(binding, false);\n } else {\n const entering = !binding.active;\n if (entering) search.begin(binding, revision + 1);\n const nextFocused = focus === true ? true : focus === false ? false : entering ? false : binding.focused;\n search.setStatus(binding, true, nextFocused);\n }\n await flush();\n return !stopped && search.projected(binding);\n },\n async suspend(scopes) {\n getNativeSearchBindings(doc)\n .filter((binding) => scopes.some((scope) => scope.contains(binding.footer) || scope.contains(binding.tabBar)))\n .forEach((binding) => search.retire(binding));\n suspended.add(scopes);\n await flush();\n // Source DOM has been restored before Ionic starts moving it.\n await new Promise<void>((resolve) => win.requestAnimationFrame(() => resolve()));\n return (canceled = false) => {\n suspended.delete(scopes);\n if (canceled || !scopes.some((scope) => scope.closest('ion-app.ios-theme-vertical-bars'))) {\n scopes.forEach((scope) => pages.delete(scope)); // Preserve ordinary iPhone handoff; cancellation has no DidLeave.\n if (canceled) {\n verticalBarsPages.cancel(scopes[0], scopes[1]); // The entering page is abandoned; the leaving page stays active.\n }\n }\n schedule();\n };\n },\n });\n on(win, 'pagehide', () => {\n void handle.destroy();\n });\n schedule();\n } catch (error) {\n await fail(error);\n }\n return handle;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"runtime.js","names":[],"sources":["../../src/native/runtime.ts"],"sourcesContent":["import { inVerticalBarsSurface, topModal, modalUsesVerticalBars, modalVerticalBarFrame } from './shared/modal';\nimport type { PluginListenerHandle } from '@capacitor/core';\nimport { LIFECYCLE_WILL_ENTER, LIFECYCLE_WILL_LEAVE, LIFECYCLE_DID_ENTER, LIFECYCLE_DID_LEAVE } from '@ionic/core/components/index.js';\nimport { VERTICAL_BARS_TRANSITION_CANCELED, getNativeSearchBindings, setNativeUIShellIntegration } from '../native-integration';\nimport { createSearchSupport } from './components/searchable-tabs';\nimport type {\n ShellActivation,\n ShellSnapshot,\n NativeUIShellHandle,\n NativeUIShellOptions,\n NativeUIShellPlugin,\n NativeUIShellStatus,\n} from './definitions';\nimport { readCandidate, selector, shadowSelector, motionSelector, isVerticalBarsCandidate } from './components';\nimport {\n activateProjectedElement,\n createVerticalBarsPageState,\n isVerticalBarsSource,\n preferredVerticalBarsBack,\n marker,\n syncToolbarText,\n toolbarTextMarker,\n prehideOnlyMutation,\n rejectedClass,\n unprojected,\n} from './shared/dom';\nimport { createIconRenderer } from './shared/icons';\nimport type { Candidate } from './shared/candidate';\nimport { CSS_MOTION_EVENTS } from './shared/events';\nimport { createCrossfade, fadeMarker } from './shared/crossfade';\n\nconst overlays = 'ion-modal, ion-popover, ion-alert, ion-action-sheet, ion-loading, ion-picker, ion-toast, ion-menu';\nconst overlayNames = ['Modal', 'Popover', 'Alert', 'ActionSheet', 'Loading', 'Picker', 'Toast'];\nconst verticalBarsMarker = 'data-native-ui-shell-vertical-bars';\nconst verticalBarsMemberMarker = 'data-native-ui-shell-vertical-bars-member';\n\n// A failed bridge must not leave the source inaccessible indefinitely.\nconst bounded = <T>(promise: Promise<T>): Promise<T> =>\n new Promise((resolve, reject) => {\n const timer = setTimeout(() => reject(new Error('Native UI Shell bridge timed out')), 5000);\n promise.then(resolve, reject).finally(() => clearTimeout(timer));\n });\n\nexport const createRuntime = async (\n doc: Document,\n plugin: NativeUIShellPlugin,\n options: NativeUIShellOptions = {},\n nativeVerticalBars: () => boolean = () => true,\n verticalBarsOnly = false,\n): Promise<NativeUIShellHandle> => {\n const win = doc.defaultView!;\n const icons = createIconRenderer();\n const crossfade = createCrossfade(win);\n const ids = new WeakMap<Element, string>();\n let rejected = new WeakMap<HTMLElement, string>();\n const sources = new Map<HTMLElement, string | null>();\n const verticalBarsOwners = new Set<HTMLElement>();\n const verticalBarsMembers = new Set<HTMLElement>();\n const suspended = new Set<HTMLElement[]>();\n const pages = new Set<HTMLElement>();\n const verticalBarsPages = createVerticalBarsPageState();\n const presented = new Set<HTMLElement>();\n const manualSuspensions = new Set<symbol>();\n const moving = new Map<HTMLElement, Set<string>>();\n const observed = new Set<Element | ShadowRoot>();\n const listeners = new AbortController();\n let actions = new Map<string, HTMLElement>();\n let nextId = 0;\n let revision = 0;\n let acceptedRevision = 0;\n let updatingRevision: number | undefined;\n let pendingActivations: ShellActivation[] = [];\n let lastSequence = 0;\n let lastSnapshot = '';\n let viewport = `${win.innerWidth}:${win.innerHeight}`;\n let forceRefresh = false;\n let dirty = false;\n let pending = false;\n let stopped = false;\n /** True while a tab-switch handoff should skip crossfade. */\n let tabSwitchHandoff = false;\n /** Keep instant updates until this time — DidLeave often precedes the retire sync. */\n let handoffUntil = 0;\n /** Tab switch armed while a sync was already in flight; extend instant past that sync. */\n let handoffAcrossPending = false;\n /** Captured at the start of each sync so an in-flight update keeps a stable duration. */\n let handoffInstant = false;\n /** Retire native controls immediately as a modal starts covering the page. */\n let modalPresentHandoff = false;\n let frame = 0;\n let updates = 0;\n let reason: string | undefined;\n let listener: PluginListenerHandle | undefined;\n let searchListener: PluginListenerHandle | undefined;\n let waiters: (() => void)[] = [];\n const control = (kind: Candidate['control']['kind']): keyof NonNullable<NativeUIShellOptions['controls']> => {\n if (kind === 'ion-tab-bar') return 'tabs';\n if (kind === 'ion-segment') return 'segment';\n if (kind === 'ion-fab') return 'fab';\n return 'toolbar';\n };\n const controlEnabled = (candidate: Candidate) => {\n const controls = options.controls;\n return controls === undefined || controls[control(candidate.control.kind)] === true;\n };\n const id = (element: Element) => {\n let value = ids.get(element);\n if (!value) {\n value = `shell-${++nextId}`;\n ids.set(element, value);\n }\n return value;\n };\n const style = doc.createElement('style');\n const hidden = `[${marker}]:not([${fadeMarker}])`;\n style.textContent = `${hidden}, ${hidden} *, ${hidden}::before, ${hidden}::after, ${hidden}::part(native) { visibility: hidden !important; }\n [${marker}], [${marker}] * { pointer-events: none !important; }\n /* Ionic disables the covered page while a menu is open. VerticalBars rail\n controls remain outside that page; zero specificity preserves any\n pointer-events rule supplied by the application itself. */\n :where(.menu-content-open) :where([${verticalBarsMarker}]) {\n pointer-events: auto;\n }\n :where(.menu-content-open) :where([${verticalBarsMarker}]) > :where(:not([${verticalBarsMemberMarker}])) {\n pointer-events: none;\n }`;\n\n const restore = (element: HTMLElement) => {\n lastSnapshot = '';\n search.release(element);\n element.removeAttribute(marker);\n if (!stopped) crossfade.play(element, false, isVerticalBarsSource(element) ? !element.matches('ion-tab-bar') : handoffInstant);\n if (element.getAttribute('aria-hidden') === 'true') {\n const previous = sources.get(element);\n if (previous == null) element.removeAttribute('aria-hidden');\n else element.setAttribute('aria-hidden', previous);\n }\n sources.delete(element);\n element.dispatchEvent(new CustomEvent('nativeUIShellChange'));\n };\n const restoreAll = () => {\n Array.from(sources.keys()).forEach(restore);\n verticalBarsOwners.forEach((element) => element.removeAttribute(verticalBarsMarker));\n verticalBarsOwners.clear();\n verticalBarsMembers.forEach((element) => element.removeAttribute(verticalBarsMemberMarker));\n verticalBarsMembers.clear();\n };\n const finishWaiters = () => {\n const current = waiters;\n waiters = [];\n current.forEach((resolve) => resolve());\n };\n const schedule = () => {\n if (stopped) return;\n dirty = true;\n if (!pending && !frame) frame = win.requestAnimationFrame(() => void sync());\n };\n const search = createSearchSupport(doc, id, schedule);\n const candidateSources = (candidate: Candidate) => candidate.sources ?? [candidate.element];\n const setRejected = (element: HTMLElement, value: boolean) => {\n element.classList.toggle(rejectedClass, value);\n };\n const measuringPointerPages = new WeakSet<HTMLElement>();\n const readEnabledCandidate = (element: HTMLElement): Candidate | undefined => {\n if (element.matches('ion-back-button') && element.closest('ion-app.ios-theme-vertical-bars') && !isVerticalBarsCandidate(element))\n return;\n if (verticalBarsOnly && !isVerticalBarsCandidate(element)) return;\n const pointerPage = isVerticalBarsCandidate(element) ? element.closest<HTMLElement>('.ion-page') : undefined;\n let candidate: Candidate | undefined;\n if (pointerPage && getComputedStyle(pointerPage).pointerEvents === 'none') {\n const previous = pointerPage.style.getPropertyValue('pointer-events');\n const priority = pointerPage.style.getPropertyPriority('pointer-events');\n const hadStyle = pointerPage.hasAttribute('style');\n measuringPointerPages.add(pointerPage);\n pointerPage.style.setProperty('pointer-events', 'auto', 'important');\n try {\n candidate = readCandidate(element, id, options);\n } finally {\n if (previous) pointerPage.style.setProperty('pointer-events', previous, priority);\n else pointerPage.style.removeProperty('pointer-events');\n if (!hadStyle && !pointerPage.style.length) pointerPage.removeAttribute('style');\n win.setTimeout(() => measuringPointerPages.delete(pointerPage), 0);\n }\n } else candidate = readCandidate(element, id, options);\n if (candidate && isVerticalBarsCandidate(element)) {\n if (!nativeVerticalBars()) return undefined;\n candidate.control.placement = 'vertical-bars';\n if (['ion-button', 'ion-buttons', 'ion-menu-button'].includes(candidate.control.kind)) {\n const slot = (element.matches('ion-buttons') ? element : (element.closest('ion-buttons') ?? element)).getAttribute('slot');\n if (slot === 'start' || slot === 'end') candidate.control.toolbarSlot = slot;\n }\n }\n return candidate && controlEnabled(candidate) ? candidate : undefined;\n };\n const flush = async () => {\n if (stopped) return;\n schedule();\n try {\n await bounded(new Promise<void>((resolve) => waiters.push(resolve)));\n } catch (error) {\n await fail(error);\n }\n };\n const blocked = (element: HTMLElement) =>\n verticalBarsPages.isDeparted(element) ||\n (!isVerticalBarsSource(element) &&\n (Array.from(suspended).some((scopes) => scopes.some((scope) => scope.contains(element))) ||\n Array.from(pages).some((scope) => scope.contains(element)) ||\n Array.from(moving.keys()).some((surface) => surface.contains(element))));\n const painted = () => new Promise<void>((resolve) => win.requestAnimationFrame(() => win.requestAnimationFrame(() => resolve())));\n const overlayOpen = (includeMenu = true, allowModal = false) => {\n const modal = topModal(doc);\n const ignored = (element: Element) => allowModal && !!modal && modalUsesVerticalBars(modal) && element.matches('ion-modal');\n for (const element of presented) if (!element.isConnected) presented.delete(element);\n const presentedOverlayOpen = Array.from(presented).some(\n (element) => !ignored(element) && (includeMenu || !element.matches('ion-menu')),\n );\n return (\n manualSuspensions.size > 0 ||\n presentedOverlayOpen ||\n Array.from(doc.querySelectorAll(overlays)).some(\n (element) =>\n !ignored(element) &&\n (includeMenu || !element.matches('ion-menu')) &&\n ((element as Element & { presented?: boolean }).presented || element.classList.contains('show-menu')),\n )\n );\n };\n // Compare source data before PNG rendering mutates each item's payload.\n const signature = (candidate: Candidate) =>\n JSON.stringify({ control: candidate.control, icons: candidate.icons.map(({ source }) => source) });\n const read = (): Candidate[] => {\n search.keepSearchTabsVisible();\n for (const page of pages) if (!page.isConnected) pages.delete(page);\n for (const surface of moving.keys()) if (!surface.isConnected) moving.delete(surface);\n if (doc.hidden || overlayOpen(false, true)) return [];\n if (win.visualViewport && (win.visualViewport.scale !== 1 || win.visualViewport.offsetTop !== 0) && !search.hasActive()) return [];\n const menuOpen = overlayOpen();\n const candidates = unprojected(sources.keys(), () =>\n search\n .decorate(\n Array.from(doc.querySelectorAll<HTMLElement>(selector))\n .filter(\n (element) =>\n inVerticalBarsSurface(element) &&\n !verticalBarsPages.isDeparted(element) &&\n (!blocked(element) || (menuOpen && isVerticalBarsSource(element))),\n )\n .map(readEnabledCandidate)\n .filter((candidate): candidate is Candidate => !!candidate),\n blocked,\n )\n .filter((candidate) => !rejected.has(candidate.element) || rejected.get(candidate.element) !== signature(candidate)),\n );\n const back = preferredVerticalBarsBack(\n candidates\n .filter((candidate) => candidate.control.kind === 'ion-back-button' && isVerticalBarsCandidate(candidate.element))\n .map((candidate) => candidate.element),\n doc,\n );\n const selected = candidates.filter(\n (candidate) =>\n candidate.control.kind !== 'ion-back-button' || !isVerticalBarsCandidate(candidate.element) || candidate.element === back,\n );\n return menuOpen ? selected.filter((candidate) => isVerticalBarsCandidate(candidate.element)) : selected;\n };\n const observe = () => {\n const wanted = new Set<Element | ShadowRoot>();\n for (const element of Array.from(doc.querySelectorAll<HTMLElement>(selector))) {\n wanted.add(element);\n if (element.parentElement) wanted.add(element.parentElement);\n const inspectShadow = (node: Element) => {\n if (node.shadowRoot) {\n wanted.add(node.shadowRoot);\n node.shadowRoot.querySelectorAll('ion-icon').forEach(inspectShadow);\n }\n };\n inspectShadow(element);\n element.querySelectorAll(shadowSelector).forEach(inspectShadow);\n }\n // Reconnect only when the set changes; no per-frame observer allocation.\n if (wanted.size === observed.size && Array.from(wanted).every((element) => observed.has(element))) return;\n observer.disconnect();\n resize.disconnect();\n observed.clear();\n observer.observe(doc.documentElement, observation);\n for (const element of wanted) {\n observed.add(element);\n if (element instanceof ShadowRoot) observer.observe(element, observation);\n else resize.observe(element);\n }\n };\n const fail = async (error: unknown) => {\n reason = error instanceof Error ? error.message : String(error);\n console.warn('[Native UI Shell] Returning to Web:', reason);\n await handle.destroy();\n // The Web fallback re-evaluates eligibility once native projection is stopped.\n win.dispatchEvent(new Event('nativeUIShellRefresh'));\n };\n const sync = async () => {\n frame = 0;\n dirty = false;\n pending = true;\n syncToolbarText(doc);\n handoffInstant = tabSwitchHandoff || handoffAcrossPending || modalPresentHandoff || win.performance.now() < handoffUntil;\n modalPresentHandoff = false;\n try {\n const size = `${win.innerWidth}:${win.innerHeight}`;\n // WebKit can resize before Ionic's fixed DOM positions catch up.\n // Measure on the next frame instead of retiring a valid native search.\n if (viewport !== size) {\n viewport = size;\n dirty = true;\n return;\n }\n observe();\n const candidates = read();\n const signatures = new Map(candidates.map((candidate) => [candidate.element, signature(candidate)]));\n for (const candidate of candidates) {\n for (const icon of candidate.icons) {\n const field = icon.field ?? 'icon';\n icon.item[field] = await icons.render(\n icon.source,\n field === 'icon' ? icon.item.iconWidth! : icon.item.closeIconWidth!,\n field === 'icon' ? icon.item.iconHeight! : icon.item.closeIconHeight!,\n );\n }\n }\n if (stopped || dirty) return;\n const retained = new Set(candidates.flatMap(candidateSources));\n const removed = Array.from(sources.keys()).filter((element) => !retained.has(element));\n if (removed.length) {\n // Restore the source and let WebKit paint before removing its native cover.\n removed.forEach(restore);\n // The outgoing tab is no longer visible, so waiting two frames only leaves its\n // native snapshot over the destination. Stack transitions still need the paint.\n if (!handoffInstant && removed.some((element) => !isVerticalBarsSource(element))) {\n await painted();\n if (stopped || dirty) return;\n }\n }\n const root = doc.querySelector('ion-app.ios-theme-vertical-bars');\n const verticalBarEdge: 'left' | 'right' | undefined = root\n ? root.classList.contains('ios-theme-vertical-bars-left')\n ? 'left'\n : 'right'\n : undefined;\n const modal = topModal(doc);\n const verticalBarFrame = modal && modalUsesVerticalBars(modal) ? modalVerticalBarFrame(modal) : undefined;\n const data = {\n verticalBarFrame,\n viewportWidth: win.innerWidth,\n verticalBarEdge,\n controls: candidates.map((candidate) => candidate.control),\n };\n const serialized = JSON.stringify(data);\n if (serialized === lastSnapshot && !forceRefresh) return;\n const snapshot: ShellSnapshot = { ...data, revision: ++revision, transitionDuration: crossfade.duration(handoffInstant) };\n // A native visibility notification during this update must survive its ack.\n forceRefresh = false;\n updates++;\n updatingRevision = snapshot.revision;\n const result = await bounded(plugin.update(snapshot));\n if (stopped) return;\n if (result.revision !== snapshot.revision) throw new Error('Native UI Shell revision mismatch');\n if (`${win.innerWidth}:${win.innerHeight}` !== size) {\n lastSnapshot = '';\n dirty = true;\n return;\n }\n if (result.rejectedSearches?.length) {\n search.reject(result.rejectedSearches);\n lastSnapshot = '';\n dirty = true;\n }\n for (const candidate of candidates) {\n if (result.rejectedControls?.includes(candidate.control.id)) {\n rejected.set(candidate.element, signatures.get(candidate.element)!);\n setRejected(candidate.element, true);\n dirty = true;\n }\n }\n // A page mutation must not tear down unchanged shared controls such as tabs.\n const currentCandidates = dirty ? read() : candidates;\n const current = dirty ? new Map(currentCandidates.map((candidate) => [candidate.element, signature(candidate)])) : signatures;\n const currentSources = new Set(currentCandidates.flatMap(candidateSources));\n const accepted = candidates.filter((candidate) => current.get(candidate.element) === signatures.get(candidate.element));\n accepted.forEach((candidate) => setRejected(candidate.element, false));\n const acceptedVerticalBarsOwners = new Set(\n accepted.filter((candidate) => candidate.control.placement === 'vertical-bars').map((candidate) => candidate.element),\n );\n const acceptedVerticalBarsMembers = new Set(\n accepted\n .filter((candidate) => candidate.control.placement === 'vertical-bars')\n .flatMap((candidate) => Array.from(candidate.actions.values())),\n );\n const invalidated = candidates.length !== accepted.length;\n acceptedRevision = result.revision;\n lastSnapshot = invalidated ? '' : serialized;\n actions = new Map(\n candidates.filter((candidate) => current.has(candidate.element)).flatMap((candidate) => Array.from(candidate.actions)),\n );\n // Keep an existing cover while its content catches up. Only an ineligible\n // source needs to return to Web; new sources still require an exact ack.\n for (const element of sources.keys()) if (!currentSources.has(element)) restore(element);\n for (const element of verticalBarsOwners) {\n if (acceptedVerticalBarsOwners.has(element)) continue;\n element.removeAttribute(verticalBarsMarker);\n verticalBarsOwners.delete(element);\n }\n for (const element of acceptedVerticalBarsOwners) {\n element.setAttribute(verticalBarsMarker, '');\n verticalBarsOwners.add(element);\n }\n for (const element of verticalBarsMembers) {\n if (acceptedVerticalBarsMembers.has(element)) continue;\n element.removeAttribute(verticalBarsMemberMarker);\n verticalBarsMembers.delete(element);\n }\n for (const element of acceptedVerticalBarsMembers) {\n element.setAttribute(verticalBarsMemberMarker, '');\n verticalBarsMembers.add(element);\n }\n for (const element of accepted.flatMap(candidateSources)) {\n const newlyProjected = !sources.has(element) || !element.hasAttribute(marker);\n if (!sources.has(element)) {\n sources.set(element, element.getAttribute('aria-hidden'));\n crossfade.play(element, true, handoffInstant || isVerticalBarsSource(element));\n }\n element.setAttribute(marker, '');\n element.setAttribute('aria-hidden', 'true');\n if (newlyProjected) element.dispatchEvent(new CustomEvent('nativeUIShellChange'));\n }\n const received = pendingActivations;\n pendingActivations = [];\n received.forEach(activate);\n await crossfade.settled();\n if (invalidated) {\n dirty = true;\n // Sources that became ineligible must paint before their cover is removed.\n await painted();\n }\n } catch (error) {\n await fail(error);\n } finally {\n updatingRevision = undefined;\n pendingActivations = [];\n // A refresh received before the ack must also invalidate that ack's rejects.\n if (forceRefresh) rejected = new WeakMap();\n // A tab switch mid-update (or a dirty follow-up) must keep instant through the retire sync.\n if (!stopped && (handoffAcrossPending || (handoffInstant && dirty))) {\n handoffUntil = Math.max(handoffUntil, win.performance.now() + 400);\n }\n handoffAcrossPending = false;\n pending = false;\n if (dirty && !stopped) schedule();\n else finishWaiters();\n }\n };\n const observation: MutationObserverInit = {\n subtree: true,\n childList: true,\n characterData: true,\n attributes: true,\n attributeOldValue: true,\n };\n const observer = new MutationObserver((records) => {\n if (\n records.some(\n (record) =>\n record.attributeName !== marker &&\n record.attributeName !== toolbarTextMarker &&\n record.attributeName !== fadeMarker &&\n !prehideOnlyMutation(record) &&\n !(record.attributeName === 'style' && measuringPointerPages.has(record.target as HTMLElement)) &&\n !(\n record.attributeName === 'aria-hidden' &&\n sources.has(record.target as HTMLElement) &&\n (record.target as Element).getAttribute('aria-hidden') === 'true'\n ),\n )\n )\n schedule();\n });\n const resize = new ResizeObserver(schedule);\n const on = (target: EventTarget, name: string, callback: EventListener = schedule) =>\n target.addEventListener(name, callback, { capture: true, signal: listeners.signal });\n const pageWill: EventListener = (event) => {\n const page = event.target as HTMLElement;\n verticalBarsPages.lifecycle(event);\n getNativeSearchBindings(doc)\n .filter((binding) => page.contains(binding.footer))\n .forEach((binding) => search.retire(binding));\n // Angular updates the URL before willLeave, but keeps ion-tab-bar.selectedTab on the\n // leaving tab until DidChange. A mismatch means this leave is a tab switch, not a stack push.\n if (event.type === LIFECYCLE_WILL_LEAVE) beginTabSwitchHandoffIfNeeded(page);\n pages.add(page);\n schedule();\n };\n const pageDid: EventListener = (event) => {\n const page = event.target as HTMLElement;\n verticalBarsPages.lifecycle(event);\n pages.delete(page);\n schedule();\n if (tabSwitchHandoff && pages.size === 0) endTabSwitchHandoff();\n };\n const tabOfPath = (tabs: Element, pathname: string) => {\n let best: { tab: string; length: number } | undefined;\n for (const button of Array.from(tabs.querySelectorAll('ion-tab-button'))) {\n const tab = button.getAttribute('tab');\n const href = button.getAttribute('href')?.split(/[?#]/)[0];\n if (!tab || !href) continue;\n if (pathname === href || pathname.startsWith(`${href}/`)) {\n if (!best || href.length > best.length) best = { tab, length: href.length };\n }\n }\n return best?.tab;\n };\n const armTabSwitchHandoff = () => {\n tabSwitchHandoff = true;\n // Retiring outgoing controls often lands in a later async sync than WillLeave/DidChange.\n handoffUntil = Math.max(handoffUntil, win.performance.now() + 400);\n // The in-flight sync already captured handoffInstant=false; hold instant for the next one.\n if (pending) handoffAcrossPending = true;\n };\n const beginTabSwitchHandoffIfNeeded = (page: HTMLElement) => {\n const tabs = page.closest('ion-tabs');\n if (!tabs) return;\n const bar = tabs.querySelector('ion-tab-bar');\n const selected =\n (bar && 'selectedTab' in bar ? String((bar as HTMLElement & { selectedTab?: string }).selectedTab ?? '') : '') ||\n tabs.querySelector('ion-tab-button.tab-selected')?.getAttribute('tab') ||\n undefined;\n const destination = tabOfPath(tabs, win.location.pathname);\n if (selected && destination && selected !== destination) armTabSwitchHandoff();\n };\n // DidChange / pageDid can land in the same turn as WillLeave. Clear the sticky flag on the\n // next frame; handoffUntil / handoffAcrossPending still cover the async retire sync.\n const endTabSwitchHandoff = () => {\n win.requestAnimationFrame(() => {\n if (stopped || !tabSwitchHandoff) return;\n tabSwitchHandoff = false;\n schedule();\n });\n };\n const motion: EventListener = (event) => {\n const target = event.target as HTMLElement;\n if (!target.matches?.(motionSelector)) return;\n const key = (event as TransitionEvent).propertyName ?? (event as AnimationEvent).animationName;\n if (event.type === CSS_MOTION_EVENTS.transitionRun || event.type === CSS_MOTION_EVENTS.animationStart) {\n const keys = moving.get(target) ?? new Set<string>();\n keys.add(key);\n moving.set(target, keys);\n } else {\n moving.get(target)?.delete(key);\n if (!moving.get(target)?.size) moving.delete(target);\n }\n schedule();\n };\n for (const name of Object.values(CSS_MOTION_EVENTS)) on(doc, name, motion);\n for (const name of [LIFECYCLE_WILL_ENTER, LIFECYCLE_WILL_LEAVE]) on(doc, name, pageWill);\n for (const name of [LIFECYCLE_DID_ENTER, LIFECYCLE_DID_LEAVE]) on(doc, name, pageDid);\n on(doc, VERTICAL_BARS_TRANSITION_CANCELED, (event) => {\n const leaving = event.target as HTMLElement;\n const entering = (event as CustomEvent<{ entering?: HTMLElement }>).detail?.entering;\n verticalBarsPages.cancel(entering, leaving);\n pages.delete(leaving);\n if (entering) pages.delete(entering);\n schedule();\n });\n on(doc, 'ionTabsWillChange', () => {\n // Vanilla ion-tabs dispatches DOM events; @ionic/angular uses EventEmitters instead.\n armTabSwitchHandoff();\n schedule();\n });\n on(doc, 'ionTabsDidChange', endTabSwitchHandoff);\n for (const name of overlayNames) {\n on(doc, `ion${name}WillPresent`, (event) => {\n presented.add(event.target as HTMLElement);\n if (name === 'Modal') {\n modalPresentHandoff = true;\n // WillPresent may arrive while another bridge update is awaiting its ack.\n // Make that retirement instant too instead of racing the modal animation.\n if (pending) handoffInstant = true;\n }\n schedule();\n });\n on(doc, `ion${name}DidDismiss`, (event) => {\n presented.delete(event.target as HTMLElement);\n schedule();\n });\n }\n const eventMenu = (event: Event) =>\n event.composedPath().find((target): target is HTMLElement => target instanceof HTMLElement && target.matches('ion-menu'));\n on(doc, 'ionWillOpen', (event) => {\n const menu = eventMenu(event);\n if (menu) presented.add(menu);\n schedule();\n });\n on(doc, 'ionDidClose', (event) => {\n const menu = eventMenu(event);\n if (menu) presented.delete(menu);\n schedule();\n });\n for (const name of [\n 'ionChange',\n 'ionSelect',\n 'ionImgDidLoad',\n CSS_MOTION_EVENTS.transitionEnd,\n CSS_MOTION_EVENTS.animationEnd,\n 'focusin',\n 'focusout',\n ])\n on(doc, name);\n const refreshLayout = () => {\n rejected = new WeakMap();\n forceRefresh = true;\n schedule();\n };\n on(doc, 'visibilitychange', () => {\n if (doc.hidden) {\n getNativeSearchBindings(doc).forEach((binding) => search.retire(binding));\n schedule();\n } else refreshLayout();\n });\n on(win, 'resize', refreshLayout);\n on(win, 'keyboardWillShow', () => search.keyboard(true));\n on(win, 'keyboardWillHide', () => search.keyboard(false));\n on(win, 'scroll');\n on(win.matchMedia('(prefers-color-scheme: dark)'), 'change');\n on(win, 'nativeUIShellRefresh', (event) => {\n if ((event as Event & { retireSearch?: boolean }).retireSearch)\n getNativeSearchBindings(doc).forEach((binding) => search.retire(binding));\n refreshLayout();\n });\n if (win.visualViewport) {\n on(win.visualViewport, 'resize', refreshLayout);\n on(win.visualViewport, 'scroll');\n }\n const handle: NativeUIShellHandle = {\n getStatus: (): NativeUIShellStatus => ({\n state: stopped ? 'stopped' : sources.size ? 'native' : 'web',\n projected: sources.size,\n updates,\n reason,\n }),\n async suspend() {\n const token = Symbol();\n let resumed = false;\n if (!stopped) {\n manualSuspensions.add(token);\n getNativeSearchBindings(doc).forEach((binding) => search.retire(binding));\n await flush();\n }\n return {\n async resume() {\n if (resumed) return;\n resumed = true;\n if (stopped || !manualSuspensions.delete(token)) return;\n await flush();\n },\n };\n },\n async destroy() {\n if (stopped) return;\n stopped = true;\n setNativeUIShellIntegration(doc);\n win.cancelAnimationFrame(frame);\n listeners.abort();\n observer.disconnect();\n resize.disconnect();\n observed.clear();\n actions.clear();\n pendingActivations = [];\n search.destroy();\n crossfade.destroy();\n restoreAll();\n if (!doc.hidden) await painted();\n try {\n await bounded(plugin.clear({ revision: ++revision }));\n } catch {\n /* Always restore the Web, even after bridge loss. */\n }\n style.remove();\n doc.querySelectorAll<HTMLElement>(`.${rejectedClass}`).forEach((element) => setRejected(element, false));\n icons.clear();\n pages.clear();\n presented.clear();\n manualSuspensions.clear();\n moving.clear();\n suspended.clear();\n await listener?.remove().catch(() => {});\n await searchListener?.remove().catch(() => {});\n finishWaiters();\n },\n };\n const activate = (event: ShellActivation) => {\n if (\n stopped ||\n doc.hidden ||\n event.revision < acceptedRevision ||\n event.revision > revision ||\n event.sequence <= lastSequence ||\n overlayOpen(false, true)\n )\n return;\n // Native may send input before update() resolves on the JS bridge.\n // Revalidate it after ownership is accepted, using the same action path.\n if (event.revision > acceptedRevision && event.revision === updatingRevision) {\n pendingActivations.push(event);\n return;\n }\n lastSequence = event.sequence;\n const element = actions.get(event.id);\n if (!element) return;\n const owner = Array.from(sources.keys()).find((source) => source === element || source.contains(element));\n if (!owner || !inVerticalBarsSurface(owner)) return;\n const direct = !blocked(owner) && unprojected(sources.keys(), () => readEnabledCandidate(owner));\n const candidate = direct || read().find((candidate) => candidate.actions.has(event.id));\n const item = candidate?.control.items.find((item) => item.id === event.id);\n const searchAction =\n candidate?.control.search && [candidate.control.search.trigger.id, candidate.control.search.closeId].includes(event.id);\n if (!searchAction && (!item || item.disabled || item.visible === false)) return;\n // The original Ionic host owns form submission, routerLink and selection events.\n activateProjectedElement(element);\n lastSnapshot = ''; // Reconcile even if Ionic rejects the proposed native selection.\n schedule();\n };\n try {\n listener = await bounded(plugin.addListener('activate', activate));\n searchListener = await bounded(\n plugin.addListener('search', (event) => {\n if (stopped || doc.hidden || event.revision < acceptedRevision || event.revision > revision || overlayOpen()) return;\n search.event(event);\n }),\n );\n doc.head.append(style);\n observer.observe(doc.documentElement, observation);\n setNativeUIShellIntegration(doc, {\n async search(binding, active, focus) {\n if (!getNativeSearchBindings(doc).includes(binding) || !search.projected(binding)) return false;\n if (!active) {\n search.setStatus(binding, false);\n } else {\n const entering = !binding.active;\n if (entering) search.begin(binding, revision + 1);\n const nextFocused = focus === true ? true : focus === false ? false : entering ? false : binding.focused;\n search.setStatus(binding, true, nextFocused);\n }\n await flush();\n return !stopped && search.projected(binding);\n },\n async suspend(scopes) {\n getNativeSearchBindings(doc)\n .filter((binding) => scopes.some((scope) => scope.contains(binding.footer) || scope.contains(binding.tabBar)))\n .forEach((binding) => search.retire(binding));\n suspended.add(scopes);\n await flush();\n // Source DOM has been restored before Ionic starts moving it.\n await new Promise<void>((resolve) => win.requestAnimationFrame(() => resolve()));\n return (canceled = false) => {\n suspended.delete(scopes);\n if (canceled || !scopes.some((scope) => scope.closest('ion-app.ios-theme-vertical-bars'))) {\n scopes.forEach((scope) => pages.delete(scope)); // Preserve ordinary iPhone handoff; cancellation has no DidLeave.\n if (canceled) {\n verticalBarsPages.cancel(scopes[0], scopes[1]); // The entering page is abandoned; the leaving page stays active.\n }\n }\n schedule();\n };\n },\n });\n on(win, 'pagehide', () => {\n void handle.destroy();\n });\n schedule();\n } catch (error) {\n await fail(error);\n }\n return handle;\n};\n"],"mappings":"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"}
|
|
@@ -34,6 +34,8 @@ export declare const verticalBarsActionCandidate: (element: HTMLElement) => bool
|
|
|
34
34
|
export declare const verticalBarsBackCandidate: (element: HTMLElement) => boolean;
|
|
35
35
|
export declare const verticalBarsToolbarActions: (element: HTMLElement) => HTMLElement[];
|
|
36
36
|
export declare const isVerticalBarsToolbarGroup: (element: HTMLElement) => boolean;
|
|
37
|
+
export declare const toolbarTextMarker = "data-native-ui-shell-toolbar-text";
|
|
38
|
+
export declare const syncToolbarText: (doc: Document) => void;
|
|
37
39
|
export declare const activateProjectedElement: (element: HTMLElement) => void;
|
|
38
40
|
export declare const unprojected: <T>(elements: Iterable<HTMLElement>, read: () => T) => T;
|
|
39
41
|
export declare const visible: (element: HTMLElement, allowOutsideViewport?: boolean) => boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom.d.ts","names":[],"sources":["../../../src/native/shared/dom.ts"],"mappings":";;qBAKa;qBAKA,eAAgB,SAAS,YAAU;qBAEnC,gBAAiB,SAAS,YAAU;qBAEpC;qBACA;qBACA;qBACA;qBAEA,sBAAuB,QAAQ;qBAU/B,iBAAkB,GAAG,SAAS,aAAa,YAAY,MAAI;qBAmB3D,SAAU,OAAO;qBAOjB;qBAEA,8BAA+B,MAAM,aAAa;qBAIlD,2BAA4B,SAAS,gBAAc;qBAInD;EAGW,WAAA,SAAA;EAIH,UAAA,OAAA;EASC,OAAA,WAAA,aAAW,UAAY;;qBAYhC,6BAA8B,SAAS;qBAKvC,uBAAwB,SAAS;qBAOjC,6BAA8B,SAAS;qBAoBvC,4BAA6B,UAAU,aAAa,UAAU,KAAK,KAAK,aAAW;qBAWnF,wBAAyB,SAAS;qBAClC,aAAc,SAAS,aAAa,eAAe;qBAInD,kBAAmB,SAAS;qBAG5B,mCAAoC,SAAS;qBAO7C,2BAA4B,SAAS,aAAa;qBAGlD,6BAA8B,SAAS;qBAGvC,oBAAqB,SAAS;qBAE9B,8BAA+B,SAAS;qBAMxC,8BAA+B,SAAS;qBASxC,4BAA6B,SAAS;qBAQtC,6BAA8B,SAAS,gBAAc;qBAIrD,6BAA8B,SAAS;qBASvC,2BAA4B,SAAS;qBAOrC,cAAe,GAAG,UAAU,SAAS,cAAc,YAAY,MAAI;qBAyCnE,UAAW,SAAS,aAAa;qBAGjC,QAAS,MAAM,SAAS,SAAS,YAAU;qBAO3C,OAAQ,SAAS;qBASjB,iBAAkB,SAAS"}
|
|
1
|
+
{"version":3,"file":"dom.d.ts","names":[],"sources":["../../../src/native/shared/dom.ts"],"mappings":";;qBAKa;qBAKA,eAAgB,SAAS,YAAU;qBAEnC,gBAAiB,SAAS,YAAU;qBAEpC;qBACA;qBACA;qBACA;qBAEA,sBAAuB,QAAQ;qBAU/B,iBAAkB,GAAG,SAAS,aAAa,YAAY,MAAI;qBAmB3D,SAAU,OAAO;qBAOjB;qBAEA,8BAA+B,MAAM,aAAa;qBAIlD,2BAA4B,SAAS,gBAAc;qBAInD;EAGW,WAAA,SAAA;EAIH,UAAA,OAAA;EASC,OAAA,WAAA,aAAW,UAAY;;qBAYhC,6BAA8B,SAAS;qBAKvC,uBAAwB,SAAS;qBAOjC,6BAA8B,SAAS;qBAoBvC,4BAA6B,UAAU,aAAa,UAAU,KAAK,KAAK,aAAW;qBAWnF,wBAAyB,SAAS;qBAClC,aAAc,SAAS,aAAa,eAAe;qBAInD,kBAAmB,SAAS;qBAG5B,mCAAoC,SAAS;qBAO7C,2BAA4B,SAAS,aAAa;qBAGlD,6BAA8B,SAAS;qBAGvC,oBAAqB,SAAS;qBAE9B,8BAA+B,SAAS;qBAMxC,8BAA+B,SAAS;qBASxC,4BAA6B,SAAS;qBAQtC,6BAA8B,SAAS,gBAAc;qBAIrD,6BAA8B,SAAS;qBASvC;qBAEA,kBAAmB,KAAK;qBAYxB,2BAA4B,SAAS;qBAOrC,cAAe,GAAG,UAAU,SAAS,cAAc,YAAY,MAAI;qBAyCnE,UAAW,SAAS,aAAa;qBAGjC,QAAS,MAAM,SAAS,SAAS,YAAU;qBAO3C,OAAQ,SAAS;qBASjB,iBAAkB,SAAS"}
|
|
@@ -123,6 +123,10 @@ const verticalBarsToolbarActions = (element) => childElements(element).filter((c
|
|
|
123
123
|
const isVerticalBarsToolbarGroup = (element) => {
|
|
124
124
|
return element.matches("ion-buttons") && verticalBarsOwned(element) && !element.matches(".ios-theme-disabled, .ios26-disabled") && !isShellDisabled(element);
|
|
125
125
|
};
|
|
126
|
+
const toolbarTextMarker = "data-native-ui-shell-toolbar-text";
|
|
127
|
+
const syncToolbarText = (doc) => {
|
|
128
|
+
for (const toolbar of Array.from(doc.querySelectorAll(`ion-app.ios-theme-vertical-bars ion-toolbar, ion-toolbar[${toolbarTextMarker}]`))) toolbar.toggleAttribute(toolbarTextMarker, !!toolbar.closest("ion-app.ios-theme-vertical-bars") && childNodesOf(toolbar).some((node) => node.nodeType === Node.TEXT_NODE && !!node.textContent?.trim()));
|
|
129
|
+
};
|
|
126
130
|
const activateProjectedElement = (element) => {
|
|
127
131
|
((element.matches("ion-button, ion-back-button, ion-menu-button") ? element.shadowRoot?.querySelector("[part~=\"native\"]") : void 0) ?? element).click();
|
|
128
132
|
};
|
|
@@ -163,6 +167,6 @@ const inFixedToolbar = (element) => {
|
|
|
163
167
|
return !!edge?.matches("ion-header, ion-footer") && !element.closest("ion-content") && !edge.hasAttribute("collapse") && (verticalBars || !edge.matches(".header-collapse-main, .header-collapse-condense"));
|
|
164
168
|
};
|
|
165
169
|
//#endregion
|
|
166
|
-
export { activateProjectedElement, childElements, childNodesOf, clearVerticalBarsPlacement, createVerticalBarsPageState, excluded, frame, inFixedToolbar, isDark, isDisabledButtonGroupChild, isExcluded, isPermanentlyExcluded, isShellDisabled, isVerticalBarsBackPosition, isVerticalBarsSource, isVerticalBarsToolbarAction, isVerticalBarsToolbarActionShape, isVerticalBarsToolbarGroup, marker, preferredVerticalBarsBack, prehiddenClass, prehideOnlyMutation, prehideRootClass, rejectedClass, setVerticalBarsEnteringPage, setVerticalBarsPlacement, text, unprojected, verticalBarsActionCandidate, verticalBarsBackCandidate, verticalBarsBackWebClass, verticalBarsEnteringPage, verticalBarsOwned, verticalBarsToolbarActions, visible, withoutPrehide };
|
|
170
|
+
export { activateProjectedElement, childElements, childNodesOf, clearVerticalBarsPlacement, createVerticalBarsPageState, excluded, frame, inFixedToolbar, isDark, isDisabledButtonGroupChild, isExcluded, isPermanentlyExcluded, isShellDisabled, isVerticalBarsBackPosition, isVerticalBarsSource, isVerticalBarsToolbarAction, isVerticalBarsToolbarActionShape, isVerticalBarsToolbarGroup, marker, preferredVerticalBarsBack, prehiddenClass, prehideOnlyMutation, prehideRootClass, rejectedClass, setVerticalBarsEnteringPage, setVerticalBarsPlacement, syncToolbarText, text, toolbarTextMarker, unprojected, verticalBarsActionCandidate, verticalBarsBackCandidate, verticalBarsBackWebClass, verticalBarsEnteringPage, verticalBarsOwned, verticalBarsToolbarActions, visible, withoutPrehide };
|
|
167
171
|
|
|
168
172
|
//# sourceMappingURL=dom.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom.js","names":[],"sources":["../../../src/native/shared/dom.ts"],"sourcesContent":["import { fadeMarker } from './crossfade';\nimport { modalUsesVerticalBars } from './modal';\n\nimport type { Frame } from '../definitions';\n\nexport const marker = 'data-native-ui-shell';\n// Scoped runtimes (Stencil slot emulation) patch child accessors on upgraded\n// elements and may report none before hydration; the prototype getter still\n// reports the real light DOM.\nconst childNodesGet = typeof Node === 'undefined' ? undefined : Object.getOwnPropertyDescriptor(Node.prototype, 'childNodes')?.get;\nexport const childNodesOf = (element: Element): Node[] =>\n childNodesGet ? Array.from(childNodesGet.call(element)) : Array.from(element.childNodes);\nexport const childElements = (element: Element): HTMLElement[] =>\n childNodesOf(element).filter((node) => node.nodeType === 1) as HTMLElement[];\nexport const prehiddenClass = 'ios-theme-native-ui-shell-prehidden';\nexport const prehideRootClass = 'ios-theme-native-ui-shell-prehide';\nexport const rejectedClass = 'ios-theme-native-ui-shell-rejected';\nexport const verticalBarsBackWebClass = 'ios-theme-vertical-bars-back-web-owned';\nconst prehideClasses = new Set([prehiddenClass, prehideRootClass]);\nexport const prehideOnlyMutation = (record: MutationRecord): boolean => {\n if (record.attributeName !== 'class' || record.oldValue === null) return false;\n const withoutPrehide = (value: string) =>\n value\n .split(/\\s+/)\n .filter((name) => name && !prehideClasses.has(name))\n .join(' ');\n return withoutPrehide(record.oldValue) === withoutPrehide((record.target as Element).getAttribute('class') ?? '');\n};\n\nexport const withoutPrehide = <T>(element: HTMLElement, read: () => T): T => {\n const changed: HTMLElement[] = [];\n for (let current: HTMLElement | null = element; current; current = current.parentElement) {\n if (current.classList.contains(prehiddenClass)) {\n current.classList.remove(prehiddenClass);\n changed.push(current);\n }\n }\n const root = element.ownerDocument.documentElement;\n if (element.matches('ion-back-button') && root.classList.contains(prehideRootClass)) {\n root.classList.remove(prehideRootClass);\n changed.push(root);\n }\n try {\n return read();\n } finally {\n changed.forEach((current) => current.classList.add(current === root ? prehideRootClass : prehiddenClass));\n }\n};\nexport const isDark = (style: CSSStyleDeclaration): boolean => {\n const themeScheme = style.getPropertyValue('--ios27-color-scheme').trim();\n if (themeScheme) return themeScheme === 'dark';\n const background = style.getPropertyValue('--ion-background-color-rgb').match(/\\d+/g)?.slice(0, 3).map(Number);\n return !!background && background.length === 3 && background[0] * 0.2126 + background[1] * 0.7152 + background[2] * 0.0722 < 128;\n};\nconst permanentlyExcluded = '.ios-theme-disabled, .ios26-disabled, .ion-cloned-element, [hidden], [inert]';\nexport const excluded = `${permanentlyExcluded}, .ion-page-hidden, .ion-page-invisible`;\nconst enteringPages = new WeakSet<HTMLElement>();\nexport const setVerticalBarsEnteringPage = (page: HTMLElement, entering: boolean): void => {\n if (entering) enteringPages.add(page);\n else enteringPages.delete(page);\n};\nexport const verticalBarsEnteringPage = (element: HTMLElement): HTMLElement | undefined => {\n const page = element.closest<HTMLElement>('.ion-page-invisible');\n return page && enteringPages.has(page) && page.closest('ion-app.ios-theme-vertical-bars') ? page : undefined;\n};\nexport const createVerticalBarsPageState = () => {\n const departed = new WeakSet<HTMLElement>();\n return {\n isDeparted(element: HTMLElement): boolean {\n const page = element.closest<HTMLElement>('.ion-page');\n return !!page && departed.has(page) && !!element.closest('ion-app.ios-theme-vertical-bars');\n },\n lifecycle(event: Event): void {\n // Avoid instanceof so stale listeners stay safe after global teardown.\n const page = event.target && (event.target as Node).nodeType === 1 ? (event.target as HTMLElement) : undefined;\n if (!page?.matches('.ion-page')) return;\n const entering = event.type === 'ionViewWillEnter';\n if (entering || event.type === 'ionViewDidEnter') departed.delete(page);\n else if (event.type === 'ionViewWillLeave' || event.type === 'ionViewDidLeave') departed.add(page);\n setVerticalBarsEnteringPage(page, entering);\n },\n cancel(entering?: HTMLElement, leaving?: HTMLElement): void {\n if (entering) {\n departed.add(entering);\n setVerticalBarsEnteringPage(entering, false);\n }\n if (leaving) departed.delete(leaving);\n },\n };\n};\nconst disabledButtonGroup = 'ion-buttons:is(.ios-theme-disabled, .ios26-disabled)';\nconst shellDisabledSelector = '.ios-theme-shell-disabled, [data-shell=\"disabled\"]';\n\nexport const isDisabledButtonGroupChild = (element: HTMLElement): boolean =>\n element.matches('ion-button') && element.parentElement?.matches(disabledButtonGroup) === true;\n\nconst verticalBarsTags = new Set(['ion-button', 'ion-back-button', 'ion-buttons', 'ion-menu-button', 'ion-tab-bar']);\n\nexport const isVerticalBarsSource = (element: HTMLElement): boolean =>\n verticalBarsTags.has(element.localName) &&\n (element.matches('ion-tab-bar') || verticalBarsOwned(element)) &&\n !element.closest('ion-menu, ion-popover') &&\n modalUsesVerticalBars(element) &&\n !!element.closest('ion-app.ios-theme-vertical-bars');\n\nexport const isVerticalBarsBackPosition = (element: HTMLElement): boolean => {\n if (element.closest('ion-header[collapse], ion-footer[collapse]')) return false;\n const page = element.closest('.ion-page');\n if (!page) return true;\n const candidates = Array.from(page.querySelectorAll<HTMLElement>('ion-back-button')).filter(\n (back) =>\n back.closest('.ion-page') === page &&\n !back.matches('.ion-cloned-element') &&\n !back.closest('ion-header[collapse], ion-footer[collapse], ion-menu, ion-popover') &&\n modalUsesVerticalBars(back),\n );\n const rank = (back: HTMLElement) =>\n inFixedToolbar(back) ? 0 : back.closest('ion-header ion-toolbar, ion-footer ion-toolbar') ? 1 : back.closest('ion-toolbar') ? 3 : 2;\n const best = candidates.reduce<HTMLElement | undefined>(\n (winner, back) => (!winner || rank(back) < rank(winner) ? back : winner),\n undefined,\n );\n return best === element;\n};\n\nexport const preferredVerticalBarsBack = <T extends HTMLElement>(elements: T[], doc: Document): T | undefined => {\n const pages = Array.from(doc.querySelectorAll('.ion-page'));\n const pageOrder = (element: Element) => pages.indexOf(element.closest('.ion-page')!);\n return elements.sort((a, b) => pageOrder(b) - pageOrder(a) || Number(!!b.closest('ion-header')) - Number(!!a.closest('ion-header')))[0];\n};\n\nconst excludedBy = (element: HTMLElement, selector: string): boolean => {\n const owner = element.closest<HTMLElement>(selector);\n return !!owner && !(element.parentElement === owner && isDisabledButtonGroupChild(element));\n};\n\nexport const isPermanentlyExcluded = (element: HTMLElement): boolean => excludedBy(element, permanentlyExcluded);\nexport const isExcluded = (element: HTMLElement, enteringPage?: HTMLElement): boolean =>\n excludedBy(element, `${permanentlyExcluded}, .ion-page-hidden`) || (!!element.closest('.ion-page-invisible') && !enteringPage);\n\n// A shared native surface must not cover an opted-out descendant either.\nexport const isShellDisabled = (element: Element): boolean =>\n !!element.closest(shellDisabledSelector) || !!element.querySelector(shellDisabledSelector);\n\nexport const isVerticalBarsToolbarActionShape = (element: HTMLElement): boolean =>\n element.matches('ion-menu-button') ||\n (element.matches('ion-button') && !!element.querySelector('ion-icon[slot=\"icon-only\"], svg[slot=\"icon-only\"]'));\n\n// Placement belongs to the DOM identity for one routed-page epoch. Changes to\n// content/disabled state affect rendering, never its chosen surface.\nconst verticalBarsPlacement = new WeakMap<HTMLElement, boolean>();\nexport const setVerticalBarsPlacement = (element: HTMLElement, rail: boolean): void => {\n verticalBarsPlacement.set(element, rail);\n};\nexport const clearVerticalBarsPlacement = (element: HTMLElement): void => {\n verticalBarsPlacement.delete(element);\n};\nexport const verticalBarsOwned = (element: HTMLElement): boolean => verticalBarsPlacement.get(element) === true;\n\nexport const isVerticalBarsToolbarAction = (element: HTMLElement): boolean =>\n verticalBarsOwned(element) && !isExcluded(element, verticalBarsEnteringPage(element)) && !isShellDisabled(element);\n\nconst overlays = 'ion-menu, ion-popover';\n\n/** Shared eligibility for a toolbar action candidate, before placement is decided (prehide) or consumed (projection). */\nexport const verticalBarsActionCandidate = (element: HTMLElement): boolean =>\n inFixedToolbar(element) &&\n !element.closest('ion-buttons.ios-theme-horizontal-only, ion-button.ios-theme-horizontal-only') &&\n !isPermanentlyExcluded(element) &&\n !isShellDisabled(element) &&\n !element.closest(overlays) &&\n modalUsesVerticalBars(element);\n\n/** Shared eligibility for a back-button candidate; the back button may sit outside a fixed toolbar. */\nexport const verticalBarsBackCandidate = (element: HTMLElement): boolean =>\n isVerticalBarsBackPosition(element) &&\n !element.closest('ion-buttons.ios-theme-horizontal-only') &&\n !isPermanentlyExcluded(element) &&\n !isShellDisabled(element) &&\n !element.closest(overlays) &&\n modalUsesVerticalBars(element);\n\nexport const verticalBarsToolbarActions = (element: HTMLElement): HTMLElement[] =>\n // Back buttons use the dedicated rail slot; they are never toolbar actions.\n childElements(element).filter((child) => !child.matches('ion-back-button') && isVerticalBarsToolbarAction(child));\n\nexport const isVerticalBarsToolbarGroup = (element: HTMLElement): boolean => {\n return (\n element.matches('ion-buttons') &&\n verticalBarsOwned(element) &&\n !element.matches('.ios-theme-disabled, .ios26-disabled') &&\n !isShellDisabled(element)\n );\n};\n\nexport const activateProjectedElement = (element: HTMLElement): void => {\n const target = element.matches('ion-button, ion-back-button, ion-menu-button')\n ? element.shadowRoot?.querySelector<HTMLElement>('[part~=\"native\"]')\n : undefined;\n (target ?? element).click();\n};\n\nexport const unprojected = <T>(elements: Iterable<HTMLElement>, read: () => T): T => {\n const hidden = Array.from(elements).filter((element) => element.hasAttribute(marker));\n hidden.forEach((element) => element.removeAttribute(marker));\n try {\n return read();\n } finally {\n hidden.forEach((element) => element.setAttribute(marker, ''));\n }\n};\n\nconst readVisible = (element: HTMLElement, allowOutsideViewport: boolean): boolean => {\n const enteringPage = isVerticalBarsSource(element) ? verticalBarsEnteringPage(element) : undefined;\n if (!element.isConnected || isExcluded(element, enteringPage) || isShellDisabled(element)) return false;\n for (let current: HTMLElement | null = element; current; current = current.parentElement) {\n const style = getComputedStyle(current);\n if (\n style.display === 'none' ||\n style.visibility !== 'visible' ||\n (Number(style.opacity) === 0 && !current.hasAttribute(fadeMarker) && current !== enteringPage)\n )\n return false;\n // Ordinary controls on moving/collapsing/custom transformed surfaces stay in Web coordinates.\n // VerticalBars rail controls are placed independently of their Web coordinates and must remain\n // owned while Ionic transforms the content behind an open menu.\n if (\n !allowOutsideViewport &&\n style.transform !== 'none' &&\n !new DOMMatrixReadOnly(style.transform).isIdentity &&\n current !== element &&\n !current.matches('ion-tab-bar')\n )\n return false;\n }\n const rect = element.getBoundingClientRect();\n return (\n rect.width > 0 &&\n rect.height > 0 &&\n (allowOutsideViewport || (rect.left >= -1 && rect.top >= -1 && rect.right <= innerWidth + 1 && rect.bottom <= innerHeight + 1))\n );\n};\n\nexport const visible = (element: HTMLElement, allowOutsideViewport = false): boolean =>\n withoutPrehide(element, () => readVisible(element, allowOutsideViewport));\n\nexport const frame = (rect: DOMRect, origin?: DOMRect): Frame => ({\n x: rect.x - (origin?.x ?? 0),\n y: rect.y - (origin?.y ?? 0),\n width: rect.width,\n height: rect.height,\n});\n\nexport const text = (element: Element): string => {\n if (element.matches('ion-icon, svg, ion-badge, .ios27-segment-lens, .ion-cloned-element')) return '';\n return childNodesOf(element)\n .map((node) => (node.nodeType === 3 ? node.textContent : node.nodeType === 1 ? text(node as Element) : ''))\n .join('')\n .replace(/\\s+/g, ' ')\n .trim();\n};\n\nexport const inFixedToolbar = (element: Element): boolean => {\n const edge = element.closest('ion-toolbar')?.parentElement;\n const verticalBars = !!element.closest('ion-app.ios-theme-vertical-bars');\n return (\n !!edge?.matches('ion-header, ion-footer') &&\n !element.closest('ion-content') &&\n !edge.hasAttribute('collapse') &&\n (verticalBars || !edge.matches('.header-collapse-main, .header-collapse-condense'))\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dom.js","names":[],"sources":["../../../src/native/shared/dom.ts"],"sourcesContent":["import { fadeMarker } from './crossfade';\nimport { modalUsesVerticalBars } from './modal';\n\nimport type { Frame } from '../definitions';\n\nexport const marker = 'data-native-ui-shell';\n// Scoped runtimes (Stencil slot emulation) patch child accessors on upgraded\n// elements and may report none before hydration; the prototype getter still\n// reports the real light DOM.\nconst childNodesGet = typeof Node === 'undefined' ? undefined : Object.getOwnPropertyDescriptor(Node.prototype, 'childNodes')?.get;\nexport const childNodesOf = (element: Element): Node[] =>\n childNodesGet ? Array.from(childNodesGet.call(element)) : Array.from(element.childNodes);\nexport const childElements = (element: Element): HTMLElement[] =>\n childNodesOf(element).filter((node) => node.nodeType === 1) as HTMLElement[];\nexport const prehiddenClass = 'ios-theme-native-ui-shell-prehidden';\nexport const prehideRootClass = 'ios-theme-native-ui-shell-prehide';\nexport const rejectedClass = 'ios-theme-native-ui-shell-rejected';\nexport const verticalBarsBackWebClass = 'ios-theme-vertical-bars-back-web-owned';\nconst prehideClasses = new Set([prehiddenClass, prehideRootClass]);\nexport const prehideOnlyMutation = (record: MutationRecord): boolean => {\n if (record.attributeName !== 'class' || record.oldValue === null) return false;\n const withoutPrehide = (value: string) =>\n value\n .split(/\\s+/)\n .filter((name) => name && !prehideClasses.has(name))\n .join(' ');\n return withoutPrehide(record.oldValue) === withoutPrehide((record.target as Element).getAttribute('class') ?? '');\n};\n\nexport const withoutPrehide = <T>(element: HTMLElement, read: () => T): T => {\n const changed: HTMLElement[] = [];\n for (let current: HTMLElement | null = element; current; current = current.parentElement) {\n if (current.classList.contains(prehiddenClass)) {\n current.classList.remove(prehiddenClass);\n changed.push(current);\n }\n }\n const root = element.ownerDocument.documentElement;\n if (element.matches('ion-back-button') && root.classList.contains(prehideRootClass)) {\n root.classList.remove(prehideRootClass);\n changed.push(root);\n }\n try {\n return read();\n } finally {\n changed.forEach((current) => current.classList.add(current === root ? prehideRootClass : prehiddenClass));\n }\n};\nexport const isDark = (style: CSSStyleDeclaration): boolean => {\n const themeScheme = style.getPropertyValue('--ios27-color-scheme').trim();\n if (themeScheme) return themeScheme === 'dark';\n const background = style.getPropertyValue('--ion-background-color-rgb').match(/\\d+/g)?.slice(0, 3).map(Number);\n return !!background && background.length === 3 && background[0] * 0.2126 + background[1] * 0.7152 + background[2] * 0.0722 < 128;\n};\nconst permanentlyExcluded = '.ios-theme-disabled, .ios26-disabled, .ion-cloned-element, [hidden], [inert]';\nexport const excluded = `${permanentlyExcluded}, .ion-page-hidden, .ion-page-invisible`;\nconst enteringPages = new WeakSet<HTMLElement>();\nexport const setVerticalBarsEnteringPage = (page: HTMLElement, entering: boolean): void => {\n if (entering) enteringPages.add(page);\n else enteringPages.delete(page);\n};\nexport const verticalBarsEnteringPage = (element: HTMLElement): HTMLElement | undefined => {\n const page = element.closest<HTMLElement>('.ion-page-invisible');\n return page && enteringPages.has(page) && page.closest('ion-app.ios-theme-vertical-bars') ? page : undefined;\n};\nexport const createVerticalBarsPageState = () => {\n const departed = new WeakSet<HTMLElement>();\n return {\n isDeparted(element: HTMLElement): boolean {\n const page = element.closest<HTMLElement>('.ion-page');\n return !!page && departed.has(page) && !!element.closest('ion-app.ios-theme-vertical-bars');\n },\n lifecycle(event: Event): void {\n // Avoid instanceof so stale listeners stay safe after global teardown.\n const page = event.target && (event.target as Node).nodeType === 1 ? (event.target as HTMLElement) : undefined;\n if (!page?.matches('.ion-page')) return;\n const entering = event.type === 'ionViewWillEnter';\n if (entering || event.type === 'ionViewDidEnter') departed.delete(page);\n else if (event.type === 'ionViewWillLeave' || event.type === 'ionViewDidLeave') departed.add(page);\n setVerticalBarsEnteringPage(page, entering);\n },\n cancel(entering?: HTMLElement, leaving?: HTMLElement): void {\n if (entering) {\n departed.add(entering);\n setVerticalBarsEnteringPage(entering, false);\n }\n if (leaving) departed.delete(leaving);\n },\n };\n};\nconst disabledButtonGroup = 'ion-buttons:is(.ios-theme-disabled, .ios26-disabled)';\nconst shellDisabledSelector = '.ios-theme-shell-disabled, [data-shell=\"disabled\"]';\n\nexport const isDisabledButtonGroupChild = (element: HTMLElement): boolean =>\n element.matches('ion-button') && element.parentElement?.matches(disabledButtonGroup) === true;\n\nconst verticalBarsTags = new Set(['ion-button', 'ion-back-button', 'ion-buttons', 'ion-menu-button', 'ion-tab-bar']);\n\nexport const isVerticalBarsSource = (element: HTMLElement): boolean =>\n verticalBarsTags.has(element.localName) &&\n (element.matches('ion-tab-bar') || verticalBarsOwned(element)) &&\n !element.closest('ion-menu, ion-popover') &&\n modalUsesVerticalBars(element) &&\n !!element.closest('ion-app.ios-theme-vertical-bars');\n\nexport const isVerticalBarsBackPosition = (element: HTMLElement): boolean => {\n if (element.closest('ion-header[collapse], ion-footer[collapse]')) return false;\n const page = element.closest('.ion-page');\n if (!page) return true;\n const candidates = Array.from(page.querySelectorAll<HTMLElement>('ion-back-button')).filter(\n (back) =>\n back.closest('.ion-page') === page &&\n !back.matches('.ion-cloned-element') &&\n !back.closest('ion-header[collapse], ion-footer[collapse], ion-menu, ion-popover') &&\n modalUsesVerticalBars(back),\n );\n const rank = (back: HTMLElement) =>\n inFixedToolbar(back) ? 0 : back.closest('ion-header ion-toolbar, ion-footer ion-toolbar') ? 1 : back.closest('ion-toolbar') ? 3 : 2;\n const best = candidates.reduce<HTMLElement | undefined>(\n (winner, back) => (!winner || rank(back) < rank(winner) ? back : winner),\n undefined,\n );\n return best === element;\n};\n\nexport const preferredVerticalBarsBack = <T extends HTMLElement>(elements: T[], doc: Document): T | undefined => {\n const pages = Array.from(doc.querySelectorAll('.ion-page'));\n const pageOrder = (element: Element) => pages.indexOf(element.closest('.ion-page')!);\n return elements.sort((a, b) => pageOrder(b) - pageOrder(a) || Number(!!b.closest('ion-header')) - Number(!!a.closest('ion-header')))[0];\n};\n\nconst excludedBy = (element: HTMLElement, selector: string): boolean => {\n const owner = element.closest<HTMLElement>(selector);\n return !!owner && !(element.parentElement === owner && isDisabledButtonGroupChild(element));\n};\n\nexport const isPermanentlyExcluded = (element: HTMLElement): boolean => excludedBy(element, permanentlyExcluded);\nexport const isExcluded = (element: HTMLElement, enteringPage?: HTMLElement): boolean =>\n excludedBy(element, `${permanentlyExcluded}, .ion-page-hidden`) || (!!element.closest('.ion-page-invisible') && !enteringPage);\n\n// A shared native surface must not cover an opted-out descendant either.\nexport const isShellDisabled = (element: Element): boolean =>\n !!element.closest(shellDisabledSelector) || !!element.querySelector(shellDisabledSelector);\n\nexport const isVerticalBarsToolbarActionShape = (element: HTMLElement): boolean =>\n element.matches('ion-menu-button') ||\n (element.matches('ion-button') && !!element.querySelector('ion-icon[slot=\"icon-only\"], svg[slot=\"icon-only\"]'));\n\n// Placement belongs to the DOM identity for one routed-page epoch. Changes to\n// content/disabled state affect rendering, never its chosen surface.\nconst verticalBarsPlacement = new WeakMap<HTMLElement, boolean>();\nexport const setVerticalBarsPlacement = (element: HTMLElement, rail: boolean): void => {\n verticalBarsPlacement.set(element, rail);\n};\nexport const clearVerticalBarsPlacement = (element: HTMLElement): void => {\n verticalBarsPlacement.delete(element);\n};\nexport const verticalBarsOwned = (element: HTMLElement): boolean => verticalBarsPlacement.get(element) === true;\n\nexport const isVerticalBarsToolbarAction = (element: HTMLElement): boolean =>\n verticalBarsOwned(element) && !isExcluded(element, verticalBarsEnteringPage(element)) && !isShellDisabled(element);\n\nconst overlays = 'ion-menu, ion-popover';\n\n/** Shared eligibility for a toolbar action candidate, before placement is decided (prehide) or consumed (projection). */\nexport const verticalBarsActionCandidate = (element: HTMLElement): boolean =>\n inFixedToolbar(element) &&\n !element.closest('ion-buttons.ios-theme-horizontal-only, ion-button.ios-theme-horizontal-only') &&\n !isPermanentlyExcluded(element) &&\n !isShellDisabled(element) &&\n !element.closest(overlays) &&\n modalUsesVerticalBars(element);\n\n/** Shared eligibility for a back-button candidate; the back button may sit outside a fixed toolbar. */\nexport const verticalBarsBackCandidate = (element: HTMLElement): boolean =>\n isVerticalBarsBackPosition(element) &&\n !element.closest('ion-buttons.ios-theme-horizontal-only') &&\n !isPermanentlyExcluded(element) &&\n !isShellDisabled(element) &&\n !element.closest(overlays) &&\n modalUsesVerticalBars(element);\n\nexport const verticalBarsToolbarActions = (element: HTMLElement): HTMLElement[] =>\n // Back buttons use the dedicated rail slot; they are never toolbar actions.\n childElements(element).filter((child) => !child.matches('ion-back-button') && isVerticalBarsToolbarAction(child));\n\nexport const isVerticalBarsToolbarGroup = (element: HTMLElement): boolean => {\n return (\n element.matches('ion-buttons') &&\n verticalBarsOwned(element) &&\n !element.matches('.ios-theme-disabled, .ios26-disabled') &&\n !isShellDisabled(element)\n );\n};\n\nexport const toolbarTextMarker = 'data-native-ui-shell-toolbar-text';\n\nexport const syncToolbarText = (doc: Document): void => {\n for (const toolbar of Array.from(\n doc.querySelectorAll<HTMLElement>(`ion-app.ios-theme-vertical-bars ion-toolbar, ion-toolbar[${toolbarTextMarker}]`),\n )) {\n toolbar.toggleAttribute(\n toolbarTextMarker,\n !!toolbar.closest('ion-app.ios-theme-vertical-bars') &&\n childNodesOf(toolbar).some((node) => node.nodeType === Node.TEXT_NODE && !!node.textContent?.trim()),\n );\n }\n};\n\nexport const activateProjectedElement = (element: HTMLElement): void => {\n const target = element.matches('ion-button, ion-back-button, ion-menu-button')\n ? element.shadowRoot?.querySelector<HTMLElement>('[part~=\"native\"]')\n : undefined;\n (target ?? element).click();\n};\n\nexport const unprojected = <T>(elements: Iterable<HTMLElement>, read: () => T): T => {\n const hidden = Array.from(elements).filter((element) => element.hasAttribute(marker));\n hidden.forEach((element) => element.removeAttribute(marker));\n try {\n return read();\n } finally {\n hidden.forEach((element) => element.setAttribute(marker, ''));\n }\n};\n\nconst readVisible = (element: HTMLElement, allowOutsideViewport: boolean): boolean => {\n const enteringPage = isVerticalBarsSource(element) ? verticalBarsEnteringPage(element) : undefined;\n if (!element.isConnected || isExcluded(element, enteringPage) || isShellDisabled(element)) return false;\n for (let current: HTMLElement | null = element; current; current = current.parentElement) {\n const style = getComputedStyle(current);\n if (\n style.display === 'none' ||\n style.visibility !== 'visible' ||\n (Number(style.opacity) === 0 && !current.hasAttribute(fadeMarker) && current !== enteringPage)\n )\n return false;\n // Ordinary controls on moving/collapsing/custom transformed surfaces stay in Web coordinates.\n // VerticalBars rail controls are placed independently of their Web coordinates and must remain\n // owned while Ionic transforms the content behind an open menu.\n if (\n !allowOutsideViewport &&\n style.transform !== 'none' &&\n !new DOMMatrixReadOnly(style.transform).isIdentity &&\n current !== element &&\n !current.matches('ion-tab-bar')\n )\n return false;\n }\n const rect = element.getBoundingClientRect();\n return (\n rect.width > 0 &&\n rect.height > 0 &&\n (allowOutsideViewport || (rect.left >= -1 && rect.top >= -1 && rect.right <= innerWidth + 1 && rect.bottom <= innerHeight + 1))\n );\n};\n\nexport const visible = (element: HTMLElement, allowOutsideViewport = false): boolean =>\n withoutPrehide(element, () => readVisible(element, allowOutsideViewport));\n\nexport const frame = (rect: DOMRect, origin?: DOMRect): Frame => ({\n x: rect.x - (origin?.x ?? 0),\n y: rect.y - (origin?.y ?? 0),\n width: rect.width,\n height: rect.height,\n});\n\nexport const text = (element: Element): string => {\n if (element.matches('ion-icon, svg, ion-badge, .ios27-segment-lens, .ion-cloned-element')) return '';\n return childNodesOf(element)\n .map((node) => (node.nodeType === 3 ? node.textContent : node.nodeType === 1 ? text(node as Element) : ''))\n .join('')\n .replace(/\\s+/g, ' ')\n .trim();\n};\n\nexport const inFixedToolbar = (element: Element): boolean => {\n const edge = element.closest('ion-toolbar')?.parentElement;\n const verticalBars = !!element.closest('ion-app.ios-theme-vertical-bars');\n return (\n !!edge?.matches('ion-header, ion-footer') &&\n !element.closest('ion-content') &&\n !edge.hasAttribute('collapse') &&\n (verticalBars || !edge.matches('.header-collapse-main, .header-collapse-condense'))\n );\n};\n"],"mappings":";;;AAKA,MAAa,SAAS;AAItB,MAAM,gBAAgB,OAAO,SAAS,cAAc,KAAA,IAAY,OAAO,yBAAyB,KAAK,WAAW,YAAY,CAAC,EAAE;AAC/H,MAAa,gBAAgB,YAC3B,gBAAgB,MAAM,KAAK,cAAc,KAAK,OAAO,CAAC,IAAI,MAAM,KAAK,QAAQ,UAAU;AACzF,MAAa,iBAAiB,YAC5B,aAAa,OAAO,CAAC,CAAC,QAAQ,SAAS,KAAK,aAAa,CAAC;AAC5D,MAAa,iBAAiB;AAC9B,MAAa,mBAAmB;AAChC,MAAa,gBAAgB;AAC7B,MAAa,2BAA2B;AACxC,MAAM,iCAAiB,IAAI,IAAI,CAAC,gBAAgB,gBAAgB,CAAC;AACjE,MAAa,uBAAuB,WAAoC;CACtE,IAAI,OAAO,kBAAkB,WAAW,OAAO,aAAa,MAAM,OAAO;CACzE,MAAM,kBAAkB,UACtB,MACG,MAAM,KAAK,CAAC,CACZ,QAAQ,SAAS,QAAQ,CAAC,eAAe,IAAI,IAAI,CAAC,CAAC,CACnD,KAAK,GAAG;CACb,OAAO,eAAe,OAAO,QAAQ,MAAM,eAAgB,OAAO,OAAmB,aAAa,OAAO,KAAK,EAAE;AAClH;AAEA,MAAa,kBAAqB,SAAsB,SAAqB;CAC3E,MAAM,UAAyB,CAAC;CAChC,KAAK,IAAI,UAA8B,SAAS,SAAS,UAAU,QAAQ,eACzE,IAAI,QAAQ,UAAU,SAAA,qCAAuB,GAAG;EAC9C,QAAQ,UAAU,OAAO,cAAc;EACvC,QAAQ,KAAK,OAAO;CACtB;CAEF,MAAM,OAAO,QAAQ,cAAc;CACnC,IAAI,QAAQ,QAAQ,iBAAiB,KAAK,KAAK,UAAU,SAAA,mCAAyB,GAAG;EACnF,KAAK,UAAU,OAAO,gBAAgB;EACtC,QAAQ,KAAK,IAAI;CACnB;CACA,IAAI;EACF,OAAO,KAAK;CACd,UAAU;EACR,QAAQ,SAAS,YAAY,QAAQ,UAAU,IAAI,YAAY,OAAO,mBAAmB,cAAc,CAAC;CAC1G;AACF;AACA,MAAa,UAAU,UAAwC;CAC7D,MAAM,cAAc,MAAM,iBAAiB,sBAAsB,CAAC,CAAC,KAAK;CACxE,IAAI,aAAa,OAAO,gBAAgB;CACxC,MAAM,aAAa,MAAM,iBAAiB,4BAA4B,CAAC,CAAC,MAAM,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,MAAM;CAC7G,OAAO,CAAC,CAAC,cAAc,WAAW,WAAW,KAAK,WAAW,KAAK,QAAS,WAAW,KAAK,QAAS,WAAW,KAAK,QAAS;AAC/H;AACA,MAAM,sBAAsB;AAC5B,MAAa,WAAW,GAAG,oBAAoB;AAC/C,MAAM,gCAAgB,IAAI,QAAqB;AAC/C,MAAa,+BAA+B,MAAmB,aAA4B;CACzF,IAAI,UAAU,cAAc,IAAI,IAAI;MAC/B,cAAc,OAAO,IAAI;AAChC;AACA,MAAa,4BAA4B,YAAkD;CACzF,MAAM,OAAO,QAAQ,QAAqB,qBAAqB;CAC/D,OAAO,QAAQ,cAAc,IAAI,IAAI,KAAK,KAAK,QAAQ,iCAAiC,IAAI,OAAO,KAAA;AACrG;AACA,MAAa,oCAAoC;CAC/C,MAAM,2BAAW,IAAI,QAAqB;CAC1C,OAAO;EACL,WAAW,SAA+B;GACxC,MAAM,OAAO,QAAQ,QAAqB,WAAW;GACrD,OAAO,CAAC,CAAC,QAAQ,SAAS,IAAI,IAAI,KAAK,CAAC,CAAC,QAAQ,QAAQ,iCAAiC;EAC5F;EACA,UAAU,OAAoB;GAE5B,MAAM,OAAO,MAAM,UAAW,MAAM,OAAgB,aAAa,IAAK,MAAM,SAAyB,KAAA;GACrG,IAAI,CAAC,MAAM,QAAQ,WAAW,GAAG;GACjC,MAAM,WAAW,MAAM,SAAS;GAChC,IAAI,YAAY,MAAM,SAAS,mBAAmB,SAAS,OAAO,IAAI;QACjE,IAAI,MAAM,SAAS,sBAAsB,MAAM,SAAS,mBAAmB,SAAS,IAAI,IAAI;GACjG,4BAA4B,MAAM,QAAQ;EAC5C;EACA,OAAO,UAAwB,SAA6B;GAC1D,IAAI,UAAU;IACZ,SAAS,IAAI,QAAQ;IACrB,4BAA4B,UAAU,KAAK;GAC7C;GACA,IAAI,SAAS,SAAS,OAAO,OAAO;EACtC;CACF;AACF;AACA,MAAM,sBAAsB;AAC5B,MAAM,wBAAwB;AAE9B,MAAa,8BAA8B,YACzC,QAAQ,QAAQ,YAAY,KAAK,QAAQ,eAAe,QAAQ,mBAAmB,MAAM;AAE3F,MAAM,mCAAmB,IAAI,IAAI;CAAC;CAAc;CAAmB;CAAe;CAAmB;AAAa,CAAC;AAEnH,MAAa,wBAAwB,YACnC,iBAAiB,IAAI,QAAQ,SAAS,MACrC,QAAQ,QAAQ,aAAa,KAAK,kBAAkB,OAAO,MAC5D,CAAC,QAAQ,QAAQ,uBAAuB,KACxC,sBAAsB,OAAO,KAC7B,CAAC,CAAC,QAAQ,QAAQ,iCAAiC;AAErD,MAAa,8BAA8B,YAAkC;CAC3E,IAAI,QAAQ,QAAQ,4CAA4C,GAAG,OAAO;CAC1E,MAAM,OAAO,QAAQ,QAAQ,WAAW;CACxC,IAAI,CAAC,MAAM,OAAO;CAClB,MAAM,aAAa,MAAM,KAAK,KAAK,iBAA8B,iBAAiB,CAAC,CAAC,CAAC,QAClF,SACC,KAAK,QAAQ,WAAW,MAAM,QAC9B,CAAC,KAAK,QAAQ,qBAAqB,KACnC,CAAC,KAAK,QAAQ,mEAAmE,KACjF,sBAAsB,IAAI,CAC9B;CACA,MAAM,QAAQ,SACZ,eAAe,IAAI,IAAI,IAAI,KAAK,QAAQ,gDAAgD,IAAI,IAAI,KAAK,QAAQ,aAAa,IAAI,IAAI;CAKpI,OAJa,WAAW,QACrB,QAAQ,SAAU,CAAC,UAAU,KAAK,IAAI,IAAI,KAAK,MAAM,IAAI,OAAO,QACjE,KAAA,CAEQ,MAAM;AAClB;AAEA,MAAa,6BAAoD,UAAe,QAAiC;CAC/G,MAAM,QAAQ,MAAM,KAAK,IAAI,iBAAiB,WAAW,CAAC;CAC1D,MAAM,aAAa,YAAqB,MAAM,QAAQ,QAAQ,QAAQ,WAAW,CAAE;CACnF,OAAO,SAAS,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,UAAU,CAAC,KAAK,OAAO,CAAC,CAAC,EAAE,QAAQ,YAAY,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,QAAQ,YAAY,CAAC,CAAC,CAAC,CAAC;AACvI;AAEA,MAAM,cAAc,SAAsB,aAA8B;CACtE,MAAM,QAAQ,QAAQ,QAAqB,QAAQ;CACnD,OAAO,CAAC,CAAC,SAAS,EAAE,QAAQ,kBAAkB,SAAS,2BAA2B,OAAO;AAC3F;AAEA,MAAa,yBAAyB,YAAkC,WAAW,SAAS,mBAAmB;AAC/G,MAAa,cAAc,SAAsB,iBAC/C,WAAW,SAAS,GAAG,oBAAoB,mBAAmB,KAAM,CAAC,CAAC,QAAQ,QAAQ,qBAAqB,KAAK,CAAC;AAGnH,MAAa,mBAAmB,YAC9B,CAAC,CAAC,QAAQ,QAAQ,qBAAqB,KAAK,CAAC,CAAC,QAAQ,cAAc,qBAAqB;AAE3F,MAAa,oCAAoC,YAC/C,QAAQ,QAAQ,iBAAiB,KAChC,QAAQ,QAAQ,YAAY,KAAK,CAAC,CAAC,QAAQ,cAAc,uDAAmD;AAI/G,MAAM,wCAAwB,IAAI,QAA8B;AAChE,MAAa,4BAA4B,SAAsB,SAAwB;CACrF,sBAAsB,IAAI,SAAS,IAAI;AACzC;AACA,MAAa,8BAA8B,YAA+B;CACxE,sBAAsB,OAAO,OAAO;AACtC;AACA,MAAa,qBAAqB,YAAkC,sBAAsB,IAAI,OAAO,MAAM;AAE3G,MAAa,+BAA+B,YAC1C,kBAAkB,OAAO,KAAK,CAAC,WAAW,SAAS,yBAAyB,OAAO,CAAC,KAAK,CAAC,gBAAgB,OAAO;AAEnH,MAAM,WAAW;;AAGjB,MAAa,+BAA+B,YAC1C,eAAe,OAAO,KACtB,CAAC,QAAQ,QAAQ,6EAA6E,KAC9F,CAAC,sBAAsB,OAAO,KAC9B,CAAC,gBAAgB,OAAO,KACxB,CAAC,QAAQ,QAAQ,QAAQ,KACzB,sBAAsB,OAAO;;AAG/B,MAAa,6BAA6B,YACxC,2BAA2B,OAAO,KAClC,CAAC,QAAQ,QAAQ,uCAAuC,KACxD,CAAC,sBAAsB,OAAO,KAC9B,CAAC,gBAAgB,OAAO,KACxB,CAAC,QAAQ,QAAQ,QAAQ,KACzB,sBAAsB,OAAO;AAE/B,MAAa,8BAA8B,YAEzC,cAAc,OAAO,CAAC,CAAC,QAAQ,UAAU,CAAC,MAAM,QAAQ,iBAAiB,KAAK,4BAA4B,KAAK,CAAC;AAElH,MAAa,8BAA8B,YAAkC;CAC3E,OACE,QAAQ,QAAQ,aAAa,KAC7B,kBAAkB,OAAO,KACzB,CAAC,QAAQ,QAAQ,sCAAsC,KACvD,CAAC,gBAAgB,OAAO;AAE5B;AAEA,MAAa,oBAAoB;AAEjC,MAAa,mBAAmB,QAAwB;CACtD,KAAK,MAAM,WAAW,MAAM,KAC1B,IAAI,iBAA8B,4DAA4D,kBAAkB,EAAE,CACpH,GACE,QAAQ,gBACN,mBACA,CAAC,CAAC,QAAQ,QAAQ,iCAAiC,KACjD,aAAa,OAAO,CAAC,CAAC,MAAM,SAAS,KAAK,aAAa,KAAK,aAAa,CAAC,CAAC,KAAK,aAAa,KAAK,CAAC,CACvG;AAEJ;AAEA,MAAa,4BAA4B,YAA+B;CAItE,EAHe,QAAQ,QAAQ,8CAA8C,IACzE,QAAQ,YAAY,cAA2B,oBAAkB,IACjE,KAAA,MACO,QAAA,CAAS,MAAM;AAC5B;AAEA,MAAa,eAAkB,UAAiC,SAAqB;CACnF,MAAM,SAAS,MAAM,KAAK,QAAQ,CAAC,CAAC,QAAQ,YAAY,QAAQ,aAAa,MAAM,CAAC;CACpF,OAAO,SAAS,YAAY,QAAQ,gBAAgB,MAAM,CAAC;CAC3D,IAAI;EACF,OAAO,KAAK;CACd,UAAU;EACR,OAAO,SAAS,YAAY,QAAQ,aAAa,QAAQ,EAAE,CAAC;CAC9D;AACF;AAEA,MAAM,eAAe,SAAsB,yBAA2C;CACpF,MAAM,eAAe,qBAAqB,OAAO,IAAI,yBAAyB,OAAO,IAAI,KAAA;CACzF,IAAI,CAAC,QAAQ,eAAe,WAAW,SAAS,YAAY,KAAK,gBAAgB,OAAO,GAAG,OAAO;CAClG,KAAK,IAAI,UAA8B,SAAS,SAAS,UAAU,QAAQ,eAAe;EACxF,MAAM,QAAQ,iBAAiB,OAAO;EACtC,IACE,MAAM,YAAY,UAClB,MAAM,eAAe,aACpB,OAAO,MAAM,OAAO,MAAM,KAAK,CAAC,QAAQ,aAAA,6BAAuB,KAAK,YAAY,cAEjF,OAAO;EAIT,IACE,CAAC,wBACD,MAAM,cAAc,UACpB,CAAC,IAAI,kBAAkB,MAAM,SAAS,CAAC,CAAC,cACxC,YAAY,WACZ,CAAC,QAAQ,QAAQ,aAAa,GAE9B,OAAO;CACX;CACA,MAAM,OAAO,QAAQ,sBAAsB;CAC3C,OACE,KAAK,QAAQ,KACb,KAAK,SAAS,MACb,wBAAyB,KAAK,QAAQ,MAAM,KAAK,OAAO,MAAM,KAAK,SAAS,aAAa,KAAK,KAAK,UAAU,cAAc;AAEhI;AAEA,MAAa,WAAW,SAAsB,uBAAuB,UACnE,eAAe,eAAe,YAAY,SAAS,oBAAoB,CAAC;AAE1E,MAAa,SAAS,MAAe,YAA6B;CAChE,GAAG,KAAK,KAAK,QAAQ,KAAK;CAC1B,GAAG,KAAK,KAAK,QAAQ,KAAK;CAC1B,OAAO,KAAK;CACZ,QAAQ,KAAK;AACf;AAEA,MAAa,QAAQ,YAA6B;CAChD,IAAI,QAAQ,QAAQ,oEAAoE,GAAG,OAAO;CAClG,OAAO,aAAa,OAAO,CAAC,CACzB,KAAK,SAAU,KAAK,aAAa,IAAI,KAAK,cAAc,KAAK,aAAa,IAAI,KAAK,IAAe,IAAI,EAAG,CAAC,CAC1G,KAAK,EAAE,CAAC,CACR,QAAQ,QAAQ,GAAG,CAAC,CACpB,KAAK;AACV;AAEA,MAAa,kBAAkB,YAA8B;CAC3D,MAAM,OAAO,QAAQ,QAAQ,aAAa,CAAC,EAAE;CAC7C,MAAM,eAAe,CAAC,CAAC,QAAQ,QAAQ,iCAAiC;CACxE,OACE,CAAC,CAAC,MAAM,QAAQ,wBAAwB,KACxC,CAAC,QAAQ,QAAQ,aAAa,KAC9B,CAAC,KAAK,aAAa,UAAU,MAC5B,gBAAgB,CAAC,KAAK,QAAQ,kDAAkD;AAErF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vertical-bars-web.d.ts","names":[],"sources":["../../src/native/vertical-bars-web.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"vertical-bars-web.d.ts","names":[],"sources":["../../src/native/vertical-bars-web.ts"],"mappings":";;qBA0Ca,kCACX,KAAK,UACL,SAAS,sBACT,4BACC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { VERTICAL_BARS_TRANSITION_CANCELED } from "../native-integration/index.js";
|
|
2
2
|
import { inVerticalBarsSurface, topModal } from "./shared/modal.js";
|
|
3
|
-
import { activateProjectedElement, createVerticalBarsPageState, isExcluded, isShellDisabled, isVerticalBarsToolbarGroup, marker, preferredVerticalBarsBack, prehiddenClass, prehideOnlyMutation, unprojected, verticalBarsActionCandidate, verticalBarsBackCandidate, verticalBarsEnteringPage, verticalBarsOwned, verticalBarsToolbarActions, withoutPrehide } from "./shared/dom.js";
|
|
3
|
+
import { activateProjectedElement, createVerticalBarsPageState, isExcluded, isShellDisabled, isVerticalBarsToolbarGroup, marker, preferredVerticalBarsBack, prehiddenClass, prehideOnlyMutation, syncToolbarText, unprojected, verticalBarsActionCandidate, verticalBarsBackCandidate, verticalBarsEnteringPage, verticalBarsOwned, verticalBarsToolbarActions, withoutPrehide } from "./shared/dom.js";
|
|
4
4
|
import { createVerticalBarsWebSearch, searchProjectionClass } from "./vertical-bars-web-search.js";
|
|
5
5
|
//#region src/native/vertical-bars-web.ts
|
|
6
6
|
const backProjectionClass = "ios-theme-vertical-bars-back-button-projection";
|
|
@@ -215,6 +215,7 @@ const createVerticalBarsWebProjection = (doc, options, enabled = () => true) =>
|
|
|
215
215
|
};
|
|
216
216
|
const performUpdate = () => {
|
|
217
217
|
frame = 0;
|
|
218
|
+
syncToolbarText(doc);
|
|
218
219
|
const currentRoot = verticalBarsRoot();
|
|
219
220
|
if (observingVerticalBars !== !!currentRoot) {
|
|
220
221
|
observingVerticalBars = !!currentRoot;
|
|
@@ -222,6 +223,7 @@ const createVerticalBarsWebProjection = (doc, options, enabled = () => true) =>
|
|
|
222
223
|
observer.observe(doc.documentElement, {
|
|
223
224
|
subtree: true,
|
|
224
225
|
childList: true,
|
|
226
|
+
characterData: observingVerticalBars,
|
|
225
227
|
attributes: true,
|
|
226
228
|
attributeOldValue: true,
|
|
227
229
|
attributeFilter: observingVerticalBars ? void 0 : ["class"]
|
|
@@ -264,7 +266,7 @@ const createVerticalBarsWebProjection = (doc, options, enabled = () => true) =>
|
|
|
264
266
|
return !![element, rootNode instanceof ShadowRoot ? rootNode.host : void 0].some((candidate) => candidate?.closest(`.${backProjectionClass}, .${toolbarProjectionClass}, .${searchProjectionClass}`));
|
|
265
267
|
};
|
|
266
268
|
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"))));
|
|
267
|
-
if (observingVerticalBars && records.some((record) => record.attributeName !== "data-native-ui-shell" && !prehideOnlyMutation(record) && !insideProjection(record.target)) || !observingVerticalBars && verticalBarsChanged && records.some((record) => !prehideOnlyMutation(record))) schedule();
|
|
269
|
+
if (observingVerticalBars && records.some((record) => record.attributeName !== "data-native-ui-shell" && record.attributeName !== "data-native-ui-shell-toolbar-text" && !prehideOnlyMutation(record) && !insideProjection(record.target)) || !observingVerticalBars && verticalBarsChanged && records.some((record) => !prehideOnlyMutation(record))) schedule();
|
|
268
270
|
});
|
|
269
271
|
observer.observe(doc.documentElement, {
|
|
270
272
|
subtree: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vertical-bars-web.js","names":[],"sources":["../../src/native/vertical-bars-web.ts"],"sourcesContent":["import { createVerticalBarsWebSearch, searchProjectionClass } from './vertical-bars-web-search';\nimport { inVerticalBarsSurface, topModal } from './shared/modal';\nimport type { NativeUIShellHandle, NativeUIShellOptions, NativeUIShellStatus } 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 isShellDisabled,\n isVerticalBarsToolbarGroup,\n preferredVerticalBarsBack,\n verticalBarsOwned,\n marker,\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: HTMLIonButtonsElement;\n projection: HTMLElement;\n actions: { source: HTMLElement; projection: HTMLElement; previousAriaHidden: string | null }[];\n}\n\ninterface ToolbarSource {\n group: HTMLIonButtonsElement;\n actions: HTMLElement[];\n}\n\nexport const createVerticalBarsWebProjection = (\n doc: Document,\n options: NativeUIShellOptions,\n enabled: () => boolean = () => true,\n): NativeUIShellHandle => {\n const win = doc.defaultView!;\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 inVerticalBarsSurface(element) &&\n !isExcluded(element, verticalBarsEnteringPage(element)) &&\n !isShellDisabled(element) &&\n !verticalBarsPages.isDeparted(element) &&\n isRendered(element),\n () => {\n void schedule();\n },\n );\n const inEligibleToolbar = (element: HTMLElement) =>\n !!verticalBarsRoot()?.contains(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 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 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 = () => {\n search.restore();\n backProjection?.remove();\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('nativeUIShellChange'));\n }\n backSource = undefined;\n previousBackAriaHidden = null;\n for (const { projection, actions } of toolbarProjections) {\n 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('nativeUIShellChange'));\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].includes(attribute.name) && !original.hasAttribute(attribute.name)) 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 };\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] : []));\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 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('nativeUIShellChange'));\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('nativeUIShellChange'));\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 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 performUpdate = () => {\n frame = 0;\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 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)) return syncExisting();\n restore();\n project(nextBack, groups);\n search.update(projectionRoot);\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((record) => record.attributeName !== marker && !prehideOnlyMutation(record) && !insideProjection(record.target))) ||\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('resize', schedule, { signal: listeners.signal });\n win.addEventListener('nativeUIShellRefresh', schedule, { signal: listeners.signal });\n schedule();\n\n return {\n getStatus: (): NativeUIShellStatus => ({\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 restore();\n },\n };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"vertical-bars-web.js","names":[],"sources":["../../src/native/vertical-bars-web.ts"],"sourcesContent":["import { createVerticalBarsWebSearch, searchProjectionClass } from './vertical-bars-web-search';\nimport { inVerticalBarsSurface, topModal } from './shared/modal';\nimport type { NativeUIShellHandle, NativeUIShellOptions, NativeUIShellStatus } 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 isShellDisabled,\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: HTMLIonButtonsElement;\n projection: HTMLElement;\n actions: { source: HTMLElement; projection: HTMLElement; previousAriaHidden: string | null }[];\n}\n\ninterface ToolbarSource {\n group: HTMLIonButtonsElement;\n actions: HTMLElement[];\n}\n\nexport const createVerticalBarsWebProjection = (\n doc: Document,\n options: NativeUIShellOptions,\n enabled: () => boolean = () => true,\n): NativeUIShellHandle => {\n const win = doc.defaultView!;\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 inVerticalBarsSurface(element) &&\n !isExcluded(element, verticalBarsEnteringPage(element)) &&\n !isShellDisabled(element) &&\n !verticalBarsPages.isDeparted(element) &&\n isRendered(element),\n () => {\n void schedule();\n },\n );\n const inEligibleToolbar = (element: HTMLElement) =>\n !!verticalBarsRoot()?.contains(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 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 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 = () => {\n search.restore();\n backProjection?.remove();\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('nativeUIShellChange'));\n }\n backSource = undefined;\n previousBackAriaHidden = null;\n for (const { projection, actions } of toolbarProjections) {\n 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('nativeUIShellChange'));\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].includes(attribute.name) && !original.hasAttribute(attribute.name)) 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 };\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] : []));\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 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('nativeUIShellChange'));\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('nativeUIShellChange'));\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 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 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)) return syncExisting();\n restore();\n project(nextBack, groups);\n search.update(projectionRoot);\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('resize', schedule, { signal: listeners.signal });\n win.addEventListener('nativeUIShellRefresh', schedule, { signal: listeners.signal });\n schedule();\n\n return {\n getStatus: (): NativeUIShellStatus => ({\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 restore();\n },\n };\n};\n"],"mappings":";;;;;AAyBA,MAAM,sBAAsB;AAC5B,MAAM,yBAAyB;AAC/B,MAAM,aAAa;AACnB,MAAM,qBAAqB;AAC3B,MAAM,oBAAoB;AAa1B,MAAa,mCACX,KACA,SACA,gBAA+B,SACP;CACxB,MAAM,MAAM,IAAI;CAChB,MAAM,iBAAiB,QAAQ,aAAa,KAAA,KAAa,QAAQ,SAAS,YAAY;CACtF,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI,yBAAwC;CAC5C,IAAI,qBAA0C,CAAC;CAC/C,IAAI,YAAY;CAChB,IAAI,UAAU;CACd,IAAI,QAAQ;CACZ,IAAI,UAAU;CACd,IAAI,wBAAwB;CAC5B,MAAM,oBAAoB,4BAA4B;CACtD,IAAI;CACJ,IAAI,UAA0B,CAAC;CAC/B,MAAM,YAAY,IAAI,gBAAgB;CACtC,MAAM,yBAAyB,IAAI,cAA2B,iCAAiC;CAC/F,MAAM,yBACJ;EAAC;EAAY,OAAO;EAAQ,GAAG,mBAAmB,SAAS,EAAE,cAAc,QAAQ,KAAK,EAAE,aAAa,MAAM,CAAC;CAAC,CAAC,CAAC,QAC9G,WAAkC,CAAC,CAAC,MACvC;CACF,MAAM,cAAc,YAClB,eAAe,eAAe;EAC5B,MAAM,QAAQ,iBAAiB,OAAO;EACtC,MAAM,OAAO,QAAQ,sBAAsB;EAC3C,OAAO,QAAQ,eAAe,MAAM,YAAY,UAAU,MAAM,eAAe,aAAa,KAAK,QAAQ,KAAK,KAAK,SAAS;CAC9H,CAAC;CACH,MAAM,SAAS,4BACb,MACC,aACE,QAAQ,aAAa,KAAA,KAAa,QAAQ,SAAS,SAAS,SAC7D,CAAC,CAAC,iBAAiB,CAAC,EAAE,SAAS,OAAO,KACtC,sBAAsB,OAAO,KAC7B,CAAC,WAAW,SAAS,yBAAyB,OAAO,CAAC,KACtD,CAAC,gBAAgB,OAAO,KACxB,CAAC,kBAAkB,WAAW,OAAO,KACrC,WAAW,OAAO,SACd;EACJ,SAAc;CAChB,CACF;CACA,MAAM,qBAAqB,YACzB,CAAC,CAAC,iBAAiB,CAAC,EAAE,SAAS,OAAO,KACtC,sBAAsB,OAAO,KAC7B,4BAA4B,OAAO,KACnC,CAAC,WAAW,SAAS,yBAAyB,OAAO,CAAC,KACtD,CAAC,kBAAkB,WAAW,OAAO;CACvC,MAAM,kBAAkB,YACtB,CAAC,CAAC,iBAAiB,CAAC,EAAE,SAAS,OAAO,KACtC,sBAAsB,OAAO,KAC7B,kBAAkB,OAAO,KACzB,0BAA0B,OAAO,KACjC,CAAC,WAAW,SAAS,yBAAyB,OAAO,CAAC,KACtD,CAAC,kBAAkB,WAAW,OAAO,KACrC,YAAY,iBAAiB,SAAS,WAAW,OAAO,CAAC;CAC3D,MAAM,aAAa,YAAqB,MAAM,KAAK,IAAI,iBAAiB,WAAW,CAAC,CAAC,CAAC,QAAQ,QAAQ,QAAQ,WAAW,CAAE;CAC3H,MAAM,iBAAiB;EACrB,MAAM,aAAa,MAAM,KAAK,IAAI,iBAA2C,wBAAwB,oBAAoB,EAAE,CAAC,CAAC,CAAC,OAC5H,cACF;EACA,OAAO,0BAA0B,YAAY,GAAG;CAClD;CACA,MAAM,0BAA0B;EAC9B,MAAM,aAAa,MAAM,KAAK,IAAI,iBAAwC,oBAAoB,uBAAuB,EAAE,CAAC,CAAC,CAAC,SACvH,UAA2B;GAC1B,MAAM,UAAU,2BAA2B,KAAK,CAAC,CAAC,QAAQ,WAAW,YAAY,iBAAiB,SAAS,WAAW,MAAM,CAAC,CAAC;GAC9H,IAAI,CAAC,QAAQ,QAAQ,OAAO,CAAC;GAC7B,IAAI,CAAC,2BAA2B,KAAK,GAAG,OAAO,QAAQ,OAAO,iBAAiB,CAAC,CAAC,KAAK,YAAY;IAAE;IAAO,SAAS,CAAC,MAAM;GAAE,EAAE;GAC/H,OAAO,kBAAkB,KAAK,KAAK,YAAY,iBAAiB,SAAS,WAAW,KAAK,CAAC,IAAI,CAAC;IAAE;IAAO;GAAQ,CAAC,IAAI,CAAC;EACxH,CACF;EACA,MAAM,cAAc,KAAK,IAAI,GAAG,WAAW,KAAK,EAAE,YAAY,UAAU,KAAK,CAAC,CAAC;EAC/E,OAAO,WAAW,QAAQ,EAAE,YAAY,UAAU,KAAK,MAAM,WAAW;CAC1E;CACA,MAAM,0BAA0B,WAAwB,kBAAkB,CAAC,CAAC,MAAM,EAAE,cAAc,QAAQ,SAAS,MAAM,CAAC;CAC1H,MAAM,gBAAgB;EACpB,OAAO,QAAQ;EACf,gBAAgB,OAAO;EACvB,iBAAiB,KAAA;EACjB,IAAI,YAAY;GACd,WAAW,gBAAgB,MAAM;GACjC,IAAI,2BAA2B,MAAM,WAAW,gBAAgB,aAAa;QACxE,WAAW,aAAa,eAAe,sBAAsB;GAClE,WAAW,cAAc,IAAI,YAAY,qBAAqB,CAAC;EACjE;EACA,aAAa,KAAA;EACb,yBAAyB;EACzB,KAAK,MAAM,EAAE,YAAY,aAAa,oBAAoB;GACxD,WAAW,OAAO;GAClB,KAAK,MAAM,EAAE,QAAQ,wBAAwB,SAAS;IACpD,OAAO,gBAAgB,MAAM;IAC7B,IAAI,uBAAuB,MAAM,OAAO,gBAAgB,aAAa;SAChE,OAAO,aAAa,eAAe,kBAAkB;IAC1D,OAAO,cAAc,IAAI,YAAY,qBAAqB,CAAC;GAC7D;EACF;EACA,qBAAqB,CAAC;EACtB,gBAAgB,WAAW;EAC3B,iBAAiB,KAAA;EACjB,MAAM,UAAU,OAAO,UAAU;EACjC,OAAO,KAAA;CACT;CACA,MAAM,kBAAkB,QAAqB,aAA0B;EACrE,KAAK,MAAM,QAAQ;GAAC;GAAM;GAAQ;GAAQ;EAAa,GAAG,OAAO,gBAAgB,IAAI;EACrF,KAAK,MAAM,aAAa,MAAM,KAAK,OAAO,UAAU,GAClD,IAAI,CAAC,CAAC,SAAA,sBAAe,CAAC,CAAC,SAAS,UAAU,IAAI,KAAK,CAAC,SAAS,aAAa,UAAU,IAAI,GAAG,OAAO,gBAAgB,UAAU,IAAI;EAClI,KAAK,MAAM,aAAa,MAAM,KAAK,SAAS,UAAU,GACpD,IAAI,CAAC;GAAC;GAAM;;GAAgB;EAAa,CAAC,CAAC,SAAS,UAAU,IAAI,GAAG,OAAO,aAAa,UAAU,MAAM,UAAU,KAAK;EAC1H,OAAO,UAAU,OAAO,cAAc;CACxC;CACA,MAAM,YAAY,QAAkC,aAAuC;EACzF,eAAe,QAAQ,QAAQ;EAC/B,OAAO,UAAU,IAAI,qBAAqB,oBAAoB;EAC9D,OAAO,WAAW,SAAS;EAC3B,OAAO,cAAc,SAAS;EAC9B,OAAO,OAAO,SAAS;EACvB,OAAO,QAAQ,SAAS;EACxB,OAAO,OAAO,SAAS;EACvB,OAAO,OAAO;CAChB;CACA,MAAM,cAAc,QAAqB,aAA0B;EACjE,eAAe,QAAQ,QAAQ;EAC/B,OAAO,UAAU,IAAI,0CAA0C,oBAAoB;EACnF,MAAM,QACJ,SAAS,aAAa,YAAY,KAClC,SAAS,YAAY,cAAc,gBAAgB,CAAC,EAAE,aAAa,YAAY,KAC/E,SAAS,aAAa,KAAK;EAC7B,IAAI,OAAO,OAAO,aAAa,cAAc,KAAK;EAClD,IAAI,cAAc,UAAU,OAAiC,WAAY,SAAkC;EAC3G,IAAI,SAAS,QAAQ,YAAY,GAAG;GAElC,MAAM,aADO,SAAS,cAA2B,eAC3B,CAAC,EAAE,UAAU,IAAI;GACvC,YAAY,aAAa,QAAQ,WAAW;GAC5C,OAAO,gBAAgB,GAAI,aAAa,CAAC,UAAU,IAAI,CAAC,CAAE;EAC5D;CACF;CACA,MAAM,eAAe,MAA4C,WAC/D,SAAS,cACT,OAAO,WAAW,mBAAmB,UACrC,OAAO,OAAO,EAAE,OAAO,WAAW,UAAU;EAC1C,MAAM,UAAU,mBAAmB;EACnC,OACE,UAAU,QAAQ,UAClB,QAAQ,WAAW,QAAQ,QAAQ,UACnC,QAAQ,OAAO,QAAQ,gBAAgB,WAAW,QAAQ,QAAQ,YAAY,CAAC,MAAM;CAEzF,CAAC;CACH,MAAM,qBAAqB;EACzB,IAAI,cAAc,gBAAgB,SAAS,gBAAgB,UAAU;EACrE,IAAI,YAAY,aAAa,KAAyC;EACtE,KAAK,MAAM,EAAE,YAAY,QAAQ,aAAa,oBAAoB;GAChE,IAAI,QAAQ,WAAW,KAAK,CAAC,WAAW,QAAQ,aAAa,GAAG,WAAW,YAAY,QAAQ,EAAE,CAAC,MAAM;QACnG,eAAe,YAAY,MAAM;GACtC,WAAW,UAAU,IAAI,wBAAwB,oBAAoB;GACrE,WAAW,MAAM,YAAY,4CAA4C,GAAG,UAAU,GAAG;GACzF,IAAI,WAAW,QAAQ,aAAa,GAAG,QAAQ,SAAS,EAAE,QAAQ,QAAQ,YAAY,YAAY,WAAW,OAAO,MAAM,CAAC;GAC3H,aAAa,QAAQ,SAAS,qBAAqB;EACrD;CACF;CACA,MAAM,WAAW,UAAgD,WAA4B;EAC3F,OAAO,SAAS,GAAG,KAAK,iBAAiB;EACzC,IAAI,YAAY;EAChB,IAAI,UAAU;GACZ,aAAa;GACb,yBAAyB,SAAS,aAAa,aAAa;GAC5D,iBAAiB,SAAS,UAAU,KAAK;GACzC,SAAS,gBAAgB,QAAQ;GACjC,eAAe,iBACb,UACC,UAAU;IACT,MAAM,eAAe;IACrB,MAAM,yBAAyB;IAC/B,IAAI,cAAc,eAAe,SAAS,GAAG,yBAAyB,UAAU;GAClF,GACA,EAAE,SAAS,KAAK,CAClB;GACA,KAAK,OAAO,cAAc;GAC1B,SAAS,aAAa,QAAQ,EAAE;GAChC,SAAS,aAAa,eAAe,MAAM;GAC3C,SAAS,cAAc,IAAI,YAAY,qBAAqB,CAAC;GAC7D,YAAY;EACd;EACA,KAAK,MAAM,EAAE,OAAO,SAAS,aAAa,QAAQ;GAChD,MAAM,cAAc,QAAQ,WAAW,IAAI,QAAQ,KAAK,MAAA,CAAO,UAAU,KAAK;GAC9E,IAAI,QAAQ,WAAW,GAAG,WAAW,YAAY,QAAQ,EAAE;QACtD,eAAe,YAAY,KAAK;GACrC,WAAW,UAAU,IAAI,wBAAwB,oBAAoB;GACrE,WAAW,MAAM,YAAY,4CAA4C,GAAG,UAAU,GAAG;GACzF,MAAM,UAAU,QAAQ,KAAK,WAAW;IACtC,MAAM,QAAQ,QAAQ,WAAW,IAAI,aAAc,OAAO,UAAU,KAAK;IACzE,IAAI,QAAQ,SAAS,GAAG,WAAW,OAAO,MAAM;IAChD,MAAM,iBACJ,UACC,UAAU;KACT,MAAM,eAAe;KACrB,MAAM,yBAAyB;KAC/B,IAAI,uBAAuB,MAAM,GAAG,yBAAyB,MAAM;IACrE,GACA,EAAE,SAAS,KAAK,CAClB;IACA,IAAI,QAAQ,SAAS,GAAG,WAAW,OAAO,KAAK;IAC/C,MAAM,qBAAqB,OAAO,aAAa,aAAa;IAC5D,OAAO,aAAa,QAAQ,EAAE;IAC9B,OAAO,aAAa,eAAe,MAAM;IACzC,OAAO,cAAc,IAAI,YAAY,qBAAqB,CAAC;IAC3D,OAAO;KAAE;KAAQ,YAAY;KAAO;IAAmB;GACzD,CAAC;GACD,KAAK,OAAO,UAAU;GACtB,mBAAmB,KAAK;IAAE,QAAQ;IAAO;IAAY;GAAQ,CAAC;GAC9D,aAAa,QAAQ,SAAS,qBAAqB;EACrD;EACA,IAAI,YAAY,mBAAmB,QAAQ,KAAK,UAAU,IAAI,UAAU;EACxE,iBAAiB,IAAI,kBAAkB,YAAY;GACjD,IACE,QAAQ,MACL,WACC,OAAO,SAAS,gBAAiB,CAAC,CAAA,wBAAS,aAAa,CAAC,CAAC,SAAS,OAAO,iBAAiB,EAAE,KAAK,CAAC,oBAAoB,MAAM,CACjI,GAEA,SAAS;EACb,CAAC;EACD,IAAI,UAAU,YACZ,eAAe,QAAQ,SAAS,YAAY;GAAE,SAAS;GAAM,WAAW;GAAM,YAAY;GAAM,mBAAmB;EAAK,CAAC;EAC3H,KAAK,MAAM,EAAE,WAAW,QACtB,eAAe,QAAQ,OAAO;GAAE,SAAS;GAAM,WAAW;GAAM,YAAY;GAAM,mBAAmB;EAAK,CAAC;CAC/G;CACA,MAAM,sBAAsB;EAC1B,QAAQ;EACR,gBAAgB,GAAG;EACnB,MAAM,cAAc,iBAAiB;EACrC,IAAI,0BAA0B,CAAC,CAAC,aAAa;GAC3C,wBAAwB,CAAC,CAAC;GAC1B,SAAS,WAAW;GACpB,SAAS,QAAQ,IAAI,iBAAiB;IACpC,SAAS;IACT,WAAW;IACX,eAAe;IACf,YAAY;IACZ,mBAAmB;IACnB,iBAAiB,wBAAwB,KAAA,IAAY,CAAC,OAAO;GAC/D,CAAC;EACH;EACA,IAAI,WAAW,aAAa,CAAC,eAAe,CAAC,QAAQ,GAAG,OAAO,QAAQ;EACvE,MAAM,WAAW,iBAAiB,SAAS,IAAI,KAAA;EAC/C,MAAM,SAAS,iBAAiB,kBAAkB,IAAI,CAAC;EACvD,MAAM,iBAAiB,SAAS,GAAG,KAAK;EACxC,OAAO,OAAO,cAAc;EAC5B,IAAI,CAAC,YAAY,CAAC,OAAO,UAAU,CAAC,OAAO,QAAQ,OAAO,QAAQ;EAClE,IAAI,UAAU,SAAS,GAAG,KAAK,gBAAgB,YAAY,UAAU,MAAM,GAAG,OAAO,aAAa;EAClG,QAAQ;EACR,QAAQ,UAAU,MAAM;EACxB,OAAO,OAAO,cAAc;EAC5B;CACF;CACA,MAAM,eAAe;EACnB,IAAI;GACF,cAAc;EAChB,QAAQ;GACN,QAAQ;EACV,UAAU;GACR,MAAM,UAAU;GAChB,UAAU,CAAC;GACX,QAAQ,SAAS,YAAY,QAAQ,CAAC;EACxC;CACF;CACA,MAAM,iBAAgC;EACpC,IAAI,SAAS,OAAO,QAAQ,QAAQ;EAEpC,IAAI,CAAC,QAAQ,GAAG,QAAQ;EACxB,MAAM,OAAO,IAAI,SAAe,YAAY,QAAQ,KAAK,OAAO,CAAC;EACjE,IAAI,CAAC,OAAO,QAAQ,IAAI,sBAAsB,MAAM;EACpD,OAAO;CACT;CACA,MAAM,WAAW,IAAI,kBAAkB,YAAY;EACjD,MAAM,oBAAoB,WAAiB;GACzC,MAAM,UAAU,kBAAkB,UAAU,SAAS,OAAO,sBAAsB,UAAU,OAAO,aAAa,KAAA;GAChH,MAAM,WAAW,OAAO,YAAY;GAEpC,OAAO,CAAC,CAAC,CAAC,SADS,oBAAoB,aAAa,SAAS,OAAO,KAAA,CACvC,CAAC,CAAC,MAAM,cACnC,WAAW,QAAQ,IAAI,oBAAoB,KAAK,uBAAuB,KAAK,uBAAuB,CACrG;EACF;EACA,MAAM,sBAAsB,QAAQ,MACjC,WACE,OAAO,SAAS,gBAAiB,OAAO,OAAmB,QAAQ,SAAS,KAC5E,OAAO,SAAS,eACf,MAAM,KAAK,OAAO,UAAU,CAAC,CAAC,MAC3B,SACC,gBAAgB,YACf,KAAK,QAAQ,iCAAiC,KAAK,CAAC,CAAC,KAAK,cAAc,iCAAiC,EAC9G,CACN;EACA,IACG,yBACC,QAAQ,MACL,WACC,OAAO,kBAAA,0BACP,OAAO,kBAAA,uCACP,CAAC,oBAAoB,MAAM,KAC3B,CAAC,iBAAiB,OAAO,MAAM,CACnC,KACD,CAAC,yBAAyB,uBAAuB,QAAQ,MAAM,WAAW,CAAC,oBAAoB,MAAM,CAAC,GAEvG,SAAS;CACb,CAAC;CACD,SAAS,QAAQ,IAAI,iBAAiB;EACpC,SAAS;EACT,WAAW;EACX,YAAY;EACZ,mBAAmB;EACnB,iBAAiB,CAAC,OAAO;CAC3B,CAAC;CACD,MAAM,iBAAiB,UAAiB;EACtC,MAAM,OAAO,MAAM;EACnB,IAAI,EAAE,gBAAgB,gBAAgB,CAAC,KAAK,QAAQ,WAAW,GAAG;EAClE,IAAI,MAAM,SAAA,0CAA4C;GACpD,MAAM,WAAY,MAAkD,QAAQ;GAC5E,kBAAkB,OAAO,UAAU,IAAI;EACzC,OAAO,kBAAkB,UAAU,KAAK;EACxC,IAAI,iBAAiB,GAAG,SAAS;CACnC;CACA,KAAK,MAAM,QAAQ;EAAC;EAAoB;EAAoB;EAAmB;CAAiB,GAC9F,IAAI,iBAAiB,MAAM,eAAe;EAAE,SAAS;EAAM,QAAQ,UAAU;CAAO,CAAC;CACvF,IAAI,iBAAiB,mCAAmC,eAAe;EAAE,SAAS;EAAM,QAAQ,UAAU;CAAO,CAAC;CAClH,KAAK,MAAM,QAAQ,CAAC,uBAAuB,oBAAoB,GAC7D,IAAI,iBAAiB,MAAM,UAAU;EAAE,SAAS;EAAM,QAAQ,UAAU;CAAO,CAAC;CAClF,IAAI,iBAAiB,UAAU,UAAU,EAAE,QAAQ,UAAU,OAAO,CAAC;CACrE,IAAI,iBAAiB,wBAAwB,UAAU,EAAE,QAAQ,UAAU,OAAO,CAAC;CACnF,SAAS;CAET,OAAO;EACL,kBAAuC;GACrC,OAAO,UAAU,YAAY;GAC7B,WACE,OAAO,CAAC,CAAC,UAAU,IAAI,OAAO,CAAC,CAAC,OAAO,MAAM,IAAI,mBAAmB,QAAQ,OAAO,UAAU,QAAQ,MAAM,QAAQ,QAAQ,CAAC;GAC9H;EACF;EACA,MAAM,UAAU;GACd;GACA,QAAQ;GACR,IAAI,UAAU;GACd,OAAO,EACL,MAAM,SAAS;IACb,IAAI,SAAS;IACb,UAAU;IACV,YAAY,KAAK,IAAI,GAAG,YAAY,CAAC;IACrC,IAAI,CAAC,WAAW,MAAM,SAAS;GACjC,EACF;EACF;EACA,MAAM,UAAU;GACd,IAAI,SAAS;GACb,UAAU;GACV,IAAI,qBAAqB,KAAK;GAC9B,QAAQ;GACR,QAAQ,SAAS,YAAY,QAAQ,CAAC;GACtC,UAAU,CAAC;GACX,SAAS,WAAW;GACpB,gBAAgB,WAAW;GAC3B,UAAU,MAAM;GAChB,QAAQ;EACV;CACF;AACF"}
|