@rdlabo/ionic-theme-ios27 1.2.0-beta.pr243.shae972a0e49191 → 1.2.0-beta.pr246.sha237333ceac21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/dist/css/ionic-theme-ios27.css +1 -1
- package/dist/css/vertical-bars.css +1 -1
- package/dist/native/definitions.d.ts.map +1 -1
- package/dist/native/prehide.js +2 -0
- package/dist/native/prehide.js.map +1 -1
- package/dist/native/shared/candidate.js +3 -2
- package/dist/native/shared/candidate.js.map +1 -1
- package/dist/native/shared/dom.d.ts +1 -1
- package/dist/native/shared/dom.js +4 -4
- package/dist/native/shared/dom.js.map +1 -1
- package/docs/features.md +2 -2
- package/docs/iphone-duo-with-original-theme.md +7 -9
- package/docs/iphone-duo.md +3 -3
- package/docs/native-ui-shell.md +11 -9
- package/docs/special-markup.md +2 -2
- package/docs/vertical-bars.md +20 -13
- package/package.json +1 -1
- package/src/native/definitions.ts +4 -3
- package/src/native/prehide.ts +3 -1
- package/src/native/shared/candidate.ts +10 -6
- package/src/native/shared/dom.ts +4 -4
- package/src/styles/vertical-bars.scss +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
@property --ios-theme-split-pane-width{syntax:"<length>";inherits:false;initial-value:320px}ion-app.ios-theme-fold-half-opened ion-split-pane.split-pane-fold-layout,ion-split-pane.ios-theme-split-pane-half-open{--ios-theme-split-pane-width: 50vw}ion-app.ios-theme-vertical-bars{--ios-theme-vertical-bars-safe-area-left-resolved: var(--ios-theme-vertical-bars-safe-area-left, 0px);--ios-theme-vertical-bars-safe-area-right-resolved: var( --ios-theme-vertical-bars-safe-area-right, var(--ios-theme-vertical-bars-native-inset, max(80px, env(safe-area-inset-right, 0px))) )}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left{--ios-theme-vertical-bars-safe-area-left-resolved: var( --ios-theme-vertical-bars-safe-area-left, var(--ios-theme-vertical-bars-native-inset, max(80px, env(safe-area-inset-left, 0px))) );--ios-theme-vertical-bars-safe-area-right-resolved: var(--ios-theme-vertical-bars-safe-area-right, 0px)}ion-app.ios-theme-vertical-bars ion-modal:not(.ios-theme-vertical-bars-modal){--ios-theme-vertical-bars-safe-area-left-resolved: 0px;--ios-theme-vertical-bars-safe-area-right-resolved: 0px}ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal{--ios-theme-vertical-bars-modal-toolbar-top: max( 24px, calc(var(--ios-theme-vertical-bars-toolbar-top, 220px) - var(--ios-theme-vertical-bars-modal-offset-top, 0px)) )}:is(ion-app.ios-theme-vertical-bars,ion-modal.ios-theme-vertical-bars-modal).ios-theme-vertical-bars-toolbar-ready>:is(ion-menu-button,ion-button).ios-theme-vertical-bars-toolbar-projection{--ios26-glass-background-rgb: var(--ion-background-color-rgb, 255, 255, 255);--ios26-glass-border-color-rgb: var(--ion-background-color-rgb, 255, 255, 255);--ios26-glass-box-shadow-color-rgb: var(--ion-text-color-rgb, 0, 0, 0)}ion-app.ios-theme-vertical-bars .ios-transition-shade{clip-path:inset(0 var(--ios-theme-vertical-bars-safe-area-right-resolved) 0 var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-header.ios:not(.header-collapse-condense,.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)){--ion-safe-area-top: max(24px, env(safe-area-inset-top, 0px))}ion-app.ios-theme-vertical-bars ion-content:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)){--ion-safe-area-left: 0px;--ion-safe-area-right: 0px}ion-app.ios-theme-vertical-bars ion-content:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *))::part(scroll){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-content:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)):dir(rtl)::part(scroll){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)){--ion-safe-area-left: 0px;--ion-safe-area-right: 0px}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)):not(:where(ion-header.header-collapse-condense *,ion-footer.footer-collapse-fade *))::part(container){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)):not(:where(ion-header.header-collapse-condense *,ion-footer.footer-collapse-fade *)):dir(rtl)::part(container){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)){--ion-safe-area-left: 0px;--ion-safe-area-right: 0px;--ios-theme-vertical-bars-fab-edge-gap: 16px;--ios-theme-vertical-bars-fab-start-offset: var(--ios-theme-menu-width, var(--ios26-menu-width, 0px))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)).fab-horizontal-start{inset-inline-start:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-fab-start-offset) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)).fab-horizontal-end{inset-inline-end:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):dir(rtl).fab-horizontal-start{inset-inline-start:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-fab-start-offset) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):dir(rtl).fab-horizontal-end{inset-inline-end:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):has(.fab-button-small){--ios-theme-vertical-bars-fab-edge-gap: 10px}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:dir(rtl):not(.ios-theme-disabled,.ios26-disabled){--ion-safe-area-right: 0px}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled)::part(container),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:dir(rtl):not(.ios-theme-disabled,.ios26-disabled)::part(container){margin-right:var(--ios-theme-vertical-bars-safe-area-right-resolved)}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:dir(rtl):not(.ios-theme-disabled,.ios26-disabled){--ion-safe-area-left: 0px}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled)::part(container),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:dir(rtl):not(.ios-theme-disabled,.ios26-disabled)::part(container){margin-left:var(--ios-theme-vertical-bars-safe-area-left-resolved)}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled){--ios-theme-side-tab-bar-width: 48px;--ios-theme-side-tab-content-width: 44px;--ios-theme-side-tab-bar-gap: 24px;contain:layout style;position:absolute;z-index:2;display:flex;flex-direction:column;width:44px;min-width:44px;max-width:44px;height:fit-content;min-height:0;padding:2px;border-radius:24px;left:auto;right:calc(24px + (48px - var(--ios-theme-side-tab-bar-width))/2);margin:0;top:auto;bottom:var(--ios-theme-side-tab-bar-gap)}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled).ios27-enable-gesture{touch-action:pan-x pinch-zoom}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element){display:block;flex:none;width:44px;min-width:44px;height:58px;min-height:58px;border-radius:22px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element)::part(native){justify-content:center;min-height:58px;padding:0}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element) ion-label{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element) ion-icon{margin:0;font-size:28px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button.ion-activated{transform:scale(1.16)}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element)~ion-tab-button:not(.ion-cloned-element){margin-block-start:-8px;margin-inline-start:0}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):is(.ios27-animated,:has(>ion-tab-button:is(.ion-activated,:active))){--ios-theme-side-tab-bar-width: 72px;--ios-theme-side-tab-content-width: 64px;--ios-theme-side-tab-bar-gap: 20px;width:64px;min-width:64px;max-width:64px;padding:4px;border-radius:36px;transform:none;-webkit-transform:none}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):is(.ios27-animated,:has(>ion-tab-button:is(.ion-activated,:active)))>ion-tab-button:not(.ion-cloned-element){width:64px;min-width:64px;height:64px;min-height:64px;border-radius:32px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):is(.ios27-animated,:has(>ion-tab-button:is(.ion-activated,:active)))>ion-tab-button:not(.ion-cloned-element)::part(native){flex-direction:column;min-height:64px;padding-block:11px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):is(.ios27-animated,:has(>ion-tab-button:is(.ion-activated,:active)))>ion-tab-button:not(.ion-cloned-element) ion-label{position:static;width:auto;height:auto;max-width:64px;padding:0;margin:1px 0 0;overflow:hidden;clip:auto;font-size:10px;line-height:12px;text-overflow:ellipsis;white-space:nowrap}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):is(.ios27-animated,:has(>ion-tab-button:is(.ion-activated,:active)))>ion-tab-button:not(.ion-cloned-element) ion-icon{margin:0;font-size:28px}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled){right:auto;left:calc(24px + (48px - var(--ios-theme-side-tab-bar-width))/2)}.ios-theme-native-ui-shell-prehidden{position:absolute !important;visibility:hidden !important}html.ios-theme-native-ui-shell-prehide ion-app.ios-theme-vertical-bars ion-back-button:not([icon],[color],.ios-theme-vertical-bars-back-web-owned,.ionic-theme-disabled,.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-back-button-projection):not(:where(ion-menu *,ion-modal *,ion-popover *,ion-header[collapse] *,ion-footer[collapse] *,ion-buttons.ios-theme-horizontal-only *,.ios-theme-shell-disabled *,.ionic-theme-disabled *,.ios-theme-disabled *,.ios26-disabled *)){position:absolute !important;visibility:hidden !important}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-back-button:is(.ios,.md)[data-native-ui-shell]:not(.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-back-button-projection),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-back-button:is(.ios,.md)[data-native-ui-shell]:not(.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-back-button-projection){display:none}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-buttons:is(.ios,.md)>:is(ion-button,ion-menu-button):is(.ios,.md)[data-native-ui-shell]:not(.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-toolbar-action),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-buttons:is(.ios,.md)>:is(ion-button,ion-menu-button):is(.ios,.md)[data-native-ui-shell]:not(.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-toolbar-action){display:none}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-buttons:is(.ios,.md):has(>:is(ion-back-button,ion-button,ion-menu-button)[data-native-ui-shell]):not(:has(>:is(ion-back-button,ion-button,ion-menu-button):not([data-native-ui-shell]))),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-buttons:is(.ios,.md):has(>:is(ion-back-button,ion-button,ion-menu-button)[data-native-ui-shell]):not(:has(>:is(ion-back-button,ion-button,ion-menu-button):not([data-native-ui-shell]))){display:none}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-back-button.ios-theme-vertical-bars-back-button-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-back-button.ios-theme-vertical-bars-back-button-projection{position:fixed;z-index:1001;top:var(--ios-theme-vertical-bars-modal-toolbar-top, var(--ios-theme-vertical-bars-toolbar-top, 220px));right:max(4px,(var(--ios-theme-vertical-bars-safe-area-right-resolved) - 46px)/2);display:block;width:46px;height:46px;margin:0}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{position:fixed;z-index:1001;top:calc(var(--ios-theme-vertical-bars-modal-toolbar-top, var(--ios-theme-vertical-bars-toolbar-top, 220px)) + var(--ios-theme-vertical-bars-toolbar-offset, 0px));right:max(4px,(var(--ios-theme-vertical-bars-safe-area-right-resolved) - 46px)/2);width:46px;min-width:46px;height:46px;min-height:46px;margin:0}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection :is(ion-icon,svg),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection :is(ion-icon,svg){width:22px;height:22px;margin:0;font-size:22px}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{backdrop-filter:blur(2px) saturate(360%);transform:translateZ(0);-webkit-transform:translateZ(0);-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:rgba(var(--ios-theme-glass-background-rgb, var(--ios26-glass-background-rgb)), 0.72);box-shadow:inset 0 1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.25),inset 0 -1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.3),0 -0.5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 .5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 0 0 .5px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.22),0 .5px 1px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.08);border:.5px solid rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)));background-image:linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%);background-origin:padding-box;background-clip:border-box;border-inline-color:rgba(0,0,0,0)}@supports(background-clip: border-area){ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{border-color:rgba(0,0,0,0);background-image:linear-gradient(180deg, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb))), transparent 50%, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)))),linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%),linear-gradient(transparent, transparent);background-origin:border-box,padding-box,border-box;background-clip:border-area,padding-box,border-box}}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{border-radius:50%}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-solid):not(.button-outline),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-solid):not(.button-outline){--background: rgba(var(--ios-theme-glass-background-rgb, var(--ios26-glass-background-rgb)), 0.72)}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{--border-radius: 50%;--box-shadow:inset 0 1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.25),inset 0 -1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.3),0 -0.5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 .5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 0 0 .5px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.22),0 .5px 1px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.08)}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-outline)::part(native),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-outline)::part(native){backdrop-filter:blur(2px) saturate(360%);transform:translateZ(0);-webkit-transform:translateZ(0);-webkit-backface-visibility:hidden;backface-visibility:hidden;box-shadow:var(--box-shadow);border:.5px solid rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)));background-image:linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%);background-origin:padding-box;background-clip:border-box;border-inline-color:rgba(0,0,0,0)}@supports(background-clip: border-area){ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-outline)::part(native),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-outline)::part(native){border-color:rgba(0,0,0,0);background-image:linear-gradient(180deg, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb))), transparent 50%, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)))),linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%),linear-gradient(transparent, transparent);background-origin:border-box,padding-box,border-box;background-clip:border-area,padding-box,border-box}}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{display:flex;flex-direction:column;height:auto;min-height:0}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection>:is(ion-button,ion-menu-button):is(.ios,.md).ios-theme-vertical-bars-toolbar-action,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection>:is(ion-button,ion-menu-button):is(.ios,.md).ios-theme-vertical-bars-toolbar-action{display:block;width:44px;min-width:44px;height:46px;min-height:46px;margin:0 1px}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection>:is(ion-button,ion-menu-button):is(.ios,.md).ios-theme-vertical-bars-toolbar-action::part(native),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection>:is(ion-button,ion-menu-button):is(.ios,.md).ios-theme-vertical-bars-toolbar-action::part(native){margin-inline:auto}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left>ion-back-button.ios-theme-vertical-bars-back-button-projection,ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left ion-modal.ios-theme-vertical-bars-modal>ion-back-button.ios-theme-vertical-bars-back-button-projection,ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left ion-modal.ios-theme-vertical-bars-modal>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{right:auto;left:max(4px,(var(--ios-theme-vertical-bars-safe-area-left-resolved) - 46px)/2)}ion-tab-button.ios.ion-cloned-element.ios27-vertical-tab-effect{border-radius:32px}ion-tab-button.ios.ion-cloned-element.ios27-vertical-tab-effect::part(native){min-height:0;height:100%}
|
|
1
|
+
@property --ios-theme-split-pane-width{syntax:"<length>";inherits:false;initial-value:320px}ion-app.ios-theme-fold-half-opened ion-split-pane.split-pane-fold-layout,ion-split-pane.ios-theme-split-pane-half-open{--ios-theme-split-pane-width: 50vw}ion-app.ios-theme-vertical-bars{--ios-theme-vertical-bars-safe-area-left-resolved: var(--ios-theme-vertical-bars-safe-area-left, 0px);--ios-theme-vertical-bars-safe-area-right-resolved: var( --ios-theme-vertical-bars-safe-area-right, var(--ios-theme-vertical-bars-native-inset, max(80px, env(safe-area-inset-right, 0px))) )}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left{--ios-theme-vertical-bars-safe-area-left-resolved: var( --ios-theme-vertical-bars-safe-area-left, var(--ios-theme-vertical-bars-native-inset, max(80px, env(safe-area-inset-left, 0px))) );--ios-theme-vertical-bars-safe-area-right-resolved: var(--ios-theme-vertical-bars-safe-area-right, 0px)}ion-app.ios-theme-vertical-bars ion-modal:not(.ios-theme-vertical-bars-modal){--ios-theme-vertical-bars-safe-area-left-resolved: 0px;--ios-theme-vertical-bars-safe-area-right-resolved: 0px}ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal{--ios-theme-vertical-bars-modal-toolbar-top: max( 24px, calc(var(--ios-theme-vertical-bars-toolbar-top, 220px) - var(--ios-theme-vertical-bars-modal-offset-top, 0px)) )}:is(ion-app.ios-theme-vertical-bars,ion-modal.ios-theme-vertical-bars-modal).ios-theme-vertical-bars-toolbar-ready>:is(ion-menu-button,ion-button).ios-theme-vertical-bars-toolbar-projection{--ios26-glass-background-rgb: var(--ion-background-color-rgb, 255, 255, 255);--ios26-glass-border-color-rgb: var(--ion-background-color-rgb, 255, 255, 255);--ios26-glass-box-shadow-color-rgb: var(--ion-text-color-rgb, 0, 0, 0)}ion-app.ios-theme-vertical-bars .ios-transition-shade{clip-path:inset(0 var(--ios-theme-vertical-bars-safe-area-right-resolved) 0 var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-header.ios:not(.header-collapse-condense,.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)){--ion-safe-area-top: max(24px, env(safe-area-inset-top, 0px))}ion-app.ios-theme-vertical-bars ion-content:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)){--ion-safe-area-left: 0px;--ion-safe-area-right: 0px}ion-app.ios-theme-vertical-bars ion-content:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *))::part(scroll){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-content:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)):dir(rtl)::part(scroll){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)){--ion-safe-area-left: 0px;--ion-safe-area-right: 0px}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)):not(:where(ion-header.header-collapse-condense *,ion-footer.footer-collapse-fade *))::part(container){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)):not(:where(ion-header.header-collapse-condense *,ion-footer.footer-collapse-fade *)):dir(rtl)::part(container){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)){--ion-safe-area-left: 0px;--ion-safe-area-right: 0px;--ios-theme-vertical-bars-fab-edge-gap: 16px;--ios-theme-vertical-bars-fab-start-offset: var(--ios-theme-menu-width, var(--ios26-menu-width, 0px))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)).fab-horizontal-start{inset-inline-start:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-fab-start-offset) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)).fab-horizontal-end{inset-inline-end:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):dir(rtl).fab-horizontal-start{inset-inline-start:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-fab-start-offset) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):dir(rtl).fab-horizontal-end{inset-inline-end:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):has(.fab-button-small){--ios-theme-vertical-bars-fab-edge-gap: 10px}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:dir(rtl):not(.ios-theme-disabled,.ios26-disabled){--ion-safe-area-right: 0px}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled)::part(container),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:dir(rtl):not(.ios-theme-disabled,.ios26-disabled)::part(container){margin-right:var(--ios-theme-vertical-bars-safe-area-right-resolved)}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:dir(rtl):not(.ios-theme-disabled,.ios26-disabled){--ion-safe-area-left: 0px}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled)::part(container),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:dir(rtl):not(.ios-theme-disabled,.ios26-disabled)::part(container){margin-left:var(--ios-theme-vertical-bars-safe-area-left-resolved)}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled){--ios-theme-side-tab-bar-width: 48px;--ios-theme-side-tab-content-width: 44px;--ios-theme-side-tab-bar-gap: 24px;contain:layout style;position:absolute;z-index:2;display:flex;flex-direction:column;width:44px;min-width:44px;max-width:44px;height:fit-content;min-height:0;padding:2px;border-radius:24px;left:auto;right:calc(24px + (48px - var(--ios-theme-side-tab-bar-width))/2);margin:0;top:auto;bottom:var(--ios-theme-side-tab-bar-gap)}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled).ios27-enable-gesture{touch-action:pan-x pinch-zoom}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element){display:block;flex:none;width:44px;min-width:44px;height:58px;min-height:58px;border-radius:22px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element)::part(native){justify-content:center;min-height:58px;padding:0}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element) ion-label{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element) ion-icon{margin:0;font-size:28px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button.ion-activated{transform:scale(1.16)}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element)~ion-tab-button:not(.ion-cloned-element){margin-block-start:-8px;margin-inline-start:0}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):is(.ios27-animated,:has(>ion-tab-button:is(.ion-activated,:active))){--ios-theme-side-tab-bar-width: 72px;--ios-theme-side-tab-content-width: 64px;--ios-theme-side-tab-bar-gap: 20px;width:64px;min-width:64px;max-width:64px;padding:4px;border-radius:36px;transform:none;-webkit-transform:none}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):is(.ios27-animated,:has(>ion-tab-button:is(.ion-activated,:active)))>ion-tab-button:not(.ion-cloned-element){width:64px;min-width:64px;height:64px;min-height:64px;border-radius:32px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):is(.ios27-animated,:has(>ion-tab-button:is(.ion-activated,:active)))>ion-tab-button:not(.ion-cloned-element)::part(native){flex-direction:column;min-height:64px;padding-block:11px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):is(.ios27-animated,:has(>ion-tab-button:is(.ion-activated,:active)))>ion-tab-button:not(.ion-cloned-element) ion-label{position:static;width:auto;height:auto;max-width:64px;padding:0;margin:1px 0 0;overflow:hidden;clip:auto;font-size:10px;line-height:12px;text-overflow:ellipsis;white-space:nowrap}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):is(.ios27-animated,:has(>ion-tab-button:is(.ion-activated,:active)))>ion-tab-button:not(.ion-cloned-element) ion-icon{margin:0;font-size:28px}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled){right:auto;left:calc(24px + (48px - var(--ios-theme-side-tab-bar-width))/2)}.ios-theme-native-ui-shell-prehidden{position:absolute !important;visibility:hidden !important}html.ios-theme-native-ui-shell-prehide ion-app.ios-theme-vertical-bars ion-back-button:not([icon],[color],.ios-theme-vertical-bars-back-web-owned,.ios-theme-shell-disabled,[data-shell=disabled],.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-back-button-projection):not(:where(ion-menu *,ion-modal *,ion-popover *,ion-header[collapse] *,ion-footer[collapse] *,ion-buttons.ios-theme-horizontal-only *,.ios-theme-shell-disabled *,[data-shell=disabled] *,.ios-theme-disabled *,.ios26-disabled *)){position:absolute !important;visibility:hidden !important}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-back-button:is(.ios,.md)[data-native-ui-shell]:not(.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-back-button-projection),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-back-button:is(.ios,.md)[data-native-ui-shell]:not(.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-back-button-projection){display:none}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-buttons:is(.ios,.md)>:is(ion-button,ion-menu-button):is(.ios,.md)[data-native-ui-shell]:not(.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-toolbar-action),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-buttons:is(.ios,.md)>:is(ion-button,ion-menu-button):is(.ios,.md)[data-native-ui-shell]:not(.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-toolbar-action){display:none}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-buttons:is(.ios,.md):has(>:is(ion-back-button,ion-button,ion-menu-button)[data-native-ui-shell]):not(:has(>:is(ion-back-button,ion-button,ion-menu-button):not([data-native-ui-shell]))),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal:not(.ios-theme-vertical-bars-modal) *,ion-popover *)) ion-buttons:is(.ios,.md):has(>:is(ion-back-button,ion-button,ion-menu-button)[data-native-ui-shell]):not(:has(>:is(ion-back-button,ion-button,ion-menu-button):not([data-native-ui-shell]))){display:none}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-back-button.ios-theme-vertical-bars-back-button-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-back-button.ios-theme-vertical-bars-back-button-projection{position:fixed;z-index:1001;top:var(--ios-theme-vertical-bars-modal-toolbar-top, var(--ios-theme-vertical-bars-toolbar-top, 220px));right:max(4px,(var(--ios-theme-vertical-bars-safe-area-right-resolved) - 46px)/2);display:block;width:46px;height:46px;margin:0}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{position:fixed;z-index:1001;top:calc(var(--ios-theme-vertical-bars-modal-toolbar-top, var(--ios-theme-vertical-bars-toolbar-top, 220px)) + var(--ios-theme-vertical-bars-toolbar-offset, 0px));right:max(4px,(var(--ios-theme-vertical-bars-safe-area-right-resolved) - 46px)/2);width:46px;min-width:46px;height:46px;min-height:46px;margin:0}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection :is(ion-icon,svg),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection :is(ion-icon,svg){width:22px;height:22px;margin:0;font-size:22px}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{backdrop-filter:blur(2px) saturate(360%);transform:translateZ(0);-webkit-transform:translateZ(0);-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:rgba(var(--ios-theme-glass-background-rgb, var(--ios26-glass-background-rgb)), 0.72);box-shadow:inset 0 1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.25),inset 0 -1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.3),0 -0.5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 .5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 0 0 .5px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.22),0 .5px 1px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.08);border:.5px solid rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)));background-image:linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%);background-origin:padding-box;background-clip:border-box;border-inline-color:rgba(0,0,0,0)}@supports(background-clip: border-area){ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{border-color:rgba(0,0,0,0);background-image:linear-gradient(180deg, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb))), transparent 50%, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)))),linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%),linear-gradient(transparent, transparent);background-origin:border-box,padding-box,border-box;background-clip:border-area,padding-box,border-box}}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{border-radius:50%}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-solid):not(.button-outline),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-solid):not(.button-outline){--background: rgba(var(--ios-theme-glass-background-rgb, var(--ios26-glass-background-rgb)), 0.72)}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{--border-radius: 50%;--box-shadow:inset 0 1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.25),inset 0 -1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.3),0 -0.5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 .5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 0 0 .5px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.22),0 .5px 1px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.08)}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-outline)::part(native),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-outline)::part(native){backdrop-filter:blur(2px) saturate(360%);transform:translateZ(0);-webkit-transform:translateZ(0);-webkit-backface-visibility:hidden;backface-visibility:hidden;box-shadow:var(--box-shadow);border:.5px solid rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)));background-image:linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%);background-origin:padding-box;background-clip:border-box;border-inline-color:rgba(0,0,0,0)}@supports(background-clip: border-area){ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-outline)::part(native),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection:not(.button-outline)::part(native){border-color:rgba(0,0,0,0);background-image:linear-gradient(180deg, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb))), transparent 50%, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)))),linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%),linear-gradient(transparent, transparent);background-origin:border-box,padding-box,border-box;background-clip:border-area,padding-box,border-box}}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{display:flex;flex-direction:column;height:auto;min-height:0}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection>:is(ion-button,ion-menu-button):is(.ios,.md).ios-theme-vertical-bars-toolbar-action,ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection>:is(ion-button,ion-menu-button):is(.ios,.md).ios-theme-vertical-bars-toolbar-action{display:block;width:44px;min-width:44px;height:46px;min-height:46px;margin:0 1px}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection>:is(ion-button,ion-menu-button):is(.ios,.md).ios-theme-vertical-bars-toolbar-action::part(native),ion-app.ios-theme-vertical-bars ion-modal.ios-theme-vertical-bars-modal.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection>:is(ion-button,ion-menu-button):is(.ios,.md).ios-theme-vertical-bars-toolbar-action::part(native){margin-inline:auto}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left>ion-back-button.ios-theme-vertical-bars-back-button-projection,ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection,ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left ion-modal.ios-theme-vertical-bars-modal>ion-back-button.ios-theme-vertical-bars-back-button-projection,ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left ion-modal.ios-theme-vertical-bars-modal>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{right:auto;left:max(4px,(var(--ios-theme-vertical-bars-safe-area-left-resolved) - 46px)/2)}ion-tab-button.ios.ion-cloned-element.ios27-vertical-tab-effect{border-radius:32px}ion-tab-button.ios.ion-cloned-element.ios27-vertical-tab-effect::part(native){min-height:0;height:100%}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.d.ts","names":[],"sources":["../../src/native/definitions.ts"],"mappings":";;;iBAKiB;EACf;EACA;EACA;EACA;;iBAGe;
|
|
1
|
+
{"version":3,"file":"definitions.d.ts","names":[],"sources":["../../src/native/definitions.ts"],"mappings":";;;iBAKiB;EACf;EACA;EACA;EACA;;iBAGe;EASf;EAOA;;iBAGe,6BAA6B;EAE5C;EAEA,WAAW;EAEX;;iBAGe;EAEf;EAEA;EAEA;EAEA;;iBAGe;EAEf,aAAa;EAEb,WAAW,QAAQ;EAEnB,WAAW;;YAID;iBAEK;EACf,MAAM;EAEN;EAEA,aAAa;;iBAGE,kCAAkC;EAEjD,aAAa,WAAW,kBAAkB,sBAAsB;;iBAGjD;EAEf,UAAU;;iBAGK;EACf;EACA;EACA;EACA;;iBAGe;EACf;EACA;EACA;;iBAGe,kBAAkB;EACjC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA,QAAQ;EACR;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;iBAGe,qBAAqB;EACpC;EACA,MAAM;EAEN;EAEA;EACA,OAAO;EACP;EACA;EACA;IAAiB;IAAgB;;EACjC,SAAS;;iBAGM;EACf;EACA,OAAO;EACP,SAAS;EACT;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;iBAGe,yBAAyB;EACxC;EACA;EACA;EACA;;iBAGe;EACf;EACA;EACA;EAEA;EAEA,mBAAmB;EACnB,UAAU;;iBAGK;EACf;EACA;EACA;;iBAGe;EAEf;;iBAGe;EACf,UAAU;IAAY;MAA+B;IAAU;;EAC/D,qBAAqB,QAAQ;EAC7B,OAAO,UAAU,gBAAgB;IAAU;IAAkB;IAA6B;;EAC1F,MAAM;IAAW;MAAqB;EACtC,YAAY,kBAAkB,WAAW,OAAO,2BAA2B,QAAQ;EACnF,YAAY,gBAAgB,WAAW,OAAO,4BAA4B,QAAQ;EAClF,YAAY,8BAA8B,WAAW,OAAO,0BAA0B,QAAQ"}
|
package/dist/native/prehide.js
CHANGED
|
@@ -55,6 +55,7 @@ const prehideVerticalBarsToolbarSources = (doc) => {
|
|
|
55
55
|
owned.add(element);
|
|
56
56
|
};
|
|
57
57
|
(scope.matches("ion-back-button") ? [scope] : Array.from(scope.querySelectorAll(sourceSelector))).forEach((element) => {
|
|
58
|
+
if (isShellDisabled(element)) return;
|
|
58
59
|
if (!modalUsesVerticalBars(element) || element.closest(overlays) || scope.matches(".ion-page") && routedPage(element) !== scope) return;
|
|
59
60
|
if (element.matches("ion-buttons")) {
|
|
60
61
|
const children = childElements(element);
|
|
@@ -186,6 +187,7 @@ const prehideVerticalBarsToolbarSources = (doc) => {
|
|
|
186
187
|
attributeOldValue: true,
|
|
187
188
|
attributeFilter: [
|
|
188
189
|
"class",
|
|
190
|
+
"data-shell",
|
|
189
191
|
"hidden",
|
|
190
192
|
"inert",
|
|
191
193
|
"icon",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prehide.js","names":[],"sources":["../../src/native/prehide.ts"],"sourcesContent":["import { modalUsesVerticalBars } from './shared/modal';\nimport { LIFECYCLE_DID_ENTER, LIFECYCLE_DID_LEAVE, LIFECYCLE_WILL_ENTER, LIFECYCLE_WILL_LEAVE } from '@ionic/core';\nimport { VERTICAL_BARS_TRANSITION_CANCELED } from '../native-integration';\nimport {\n childElements,\n clearVerticalBarsPlacement,\n createVerticalBarsPageState,\n verticalBarsActionCandidate,\n verticalBarsBackCandidate,\n verticalBarsBackWebClass,\n verticalBarsOwned,\n isVerticalBarsToolbarActionShape,\n isPermanentlyExcluded,\n isShellDisabled,\n prehiddenClass,\n prehideRootClass,\n rejectedClass,\n setVerticalBarsPlacement,\n} from './shared/dom';\n\nconst overlays = 'ion-menu, ion-popover';\nconst sourceSelector = 'ion-back-button, ion-menu-button, ion-buttons, ion-button';\n// Realm- and teardown-safe: globals such as Element/HTMLElement may be gone\n// when a queued mutation microtask or a stale listener still runs.\nconst isHtmlElement = (node: unknown): node is HTMLElement => !!node && (node as Node).nodeType === 1;\nconst asElement = (node: Node | EventTarget | null): HTMLElement | undefined => (isHtmlElement(node) ? node : undefined);\nconst backSupported = (element: HTMLElement): boolean => {\n const back = element as HTMLIonBackButtonElement;\n return back.icon === undefined && back.color === undefined && !!back.shadowRoot;\n};\nconst eligibleBack = verticalBarsBackCandidate;\nconst eligible = verticalBarsActionCandidate;\n\n/** Capture toolbar placement once per routed-page epoch, before Ionic paints its transition. */\nexport const prehideVerticalBarsToolbarSources = (doc: Document): { suspend: () => () => void; stop: () => void } => {\n doc.documentElement.classList.add(prehideRootClass);\n const scopes = new Map<HTMLElement, Set<HTMLElement>>();\n const owner = new WeakMap<HTMLElement, HTMLElement>();\n const pendingBacks = new Map<HTMLElement, { scope: HTMLElement; timer: ReturnType<typeof setTimeout> }>();\n const verticalBarsPages = createVerticalBarsPageState();\n const listeners = new AbortController();\n const root = () => doc.querySelector<HTMLElement>('ion-app.ios-theme-vertical-bars');\n let suspended = 0;\n let stopped = false;\n const routedPage = (element: HTMLElement) => element.closest<HTMLElement>('.ion-page:not(ion-app, body)');\n const release = (scope: HTMLElement) => {\n for (const [element, pending] of pendingBacks) {\n if (pending.scope !== scope) continue;\n clearTimeout(pending.timer);\n pendingBacks.delete(element);\n }\n const owned = scopes.get(scope);\n if (!owned) return;\n owned.forEach((element) => {\n if (owner.get(element) !== scope) return;\n owner.delete(element);\n element.classList.remove(prehiddenClass);\n element.classList.remove(verticalBarsBackWebClass);\n clearVerticalBarsPlacement(element);\n });\n scopes.delete(scope);\n };\n const capture = (scope: HTMLElement) => {\n if (!root()?.contains(scope) || scope.closest(overlays) || !modalUsesVerticalBars(scope) || verticalBarsPages.isDeparted(scope)) return;\n const owned = scopes.get(scope) ?? new Set<HTMLElement>();\n const place = (element: HTMLElement, rail: boolean) => {\n if (owned.has(element)) return;\n const previousScope = owner.get(element);\n if (previousScope) scopes.get(previousScope)?.delete(element);\n owner.set(element, scope);\n setVerticalBarsPlacement(element, rail);\n if (element.matches('ion-back-button')) element.classList.toggle(verticalBarsBackWebClass, !rail);\n owned.add(element);\n };\n const sources = scope.matches('ion-back-button') ? [scope] : Array.from(scope.querySelectorAll<HTMLElement>(sourceSelector));\n sources.forEach((element) => {\n if (!modalUsesVerticalBars(element) || element.closest(overlays) || (scope.matches('.ion-page') && routedPage(element) !== scope))\n return;\n if (element.matches('ion-buttons')) {\n const children = childElements(element);\n const actions = children.filter((child) => eligible(child) && isVerticalBarsToolbarActionShape(child));\n const group =\n eligible(element) &&\n actions.length === children.length &&\n (actions.length > 1 || (actions.length === 1 && actions[0].matches('ion-menu-button')));\n const freshGroup = !owned.has(element);\n place(element, group);\n children.forEach((child) => {\n if (!child.matches('ion-back-button')) place(child, freshGroup && actions.includes(child));\n });\n } else if (element.matches('ion-back-button') || !element.parentElement?.matches('ion-buttons')) {\n if (owned.has(element)) return;\n if (\n element.matches('ion-back-button') &&\n eligibleBack(element) &&\n (element as HTMLIonBackButtonElement).icon === undefined &&\n (element as HTMLIonBackButtonElement).color === undefined &&\n !element.shadowRoot &&\n !element.classList.contains('hydrated')\n ) {\n const previousPending = pendingBacks.get(element);\n if (previousPending && previousPending.scope !== scope) {\n clearTimeout(previousPending.timer);\n pendingBacks.delete(element);\n }\n if (!pendingBacks.has(element)) {\n const timer = setTimeout(() => {\n if (pendingBacks.get(element)?.scope !== scope) return;\n pendingBacks.delete(element);\n // A custom element that never hydrates must remain usable on Web.\n place(element, false);\n reconcile();\n }, 1500);\n pendingBacks.set(element, { scope, timer });\n }\n return;\n }\n const pending = pendingBacks.get(element);\n if (pending) {\n clearTimeout(pending.timer);\n pendingBacks.delete(element);\n }\n place(\n element,\n element.matches('ion-back-button')\n ? eligibleBack(element) && backSupported(element)\n : eligible(element) && isVerticalBarsToolbarActionShape(element),\n );\n }\n });\n scopes.set(scope, owned);\n };\n const reconcile = () => {\n const verticalBars = root();\n if (!verticalBars) {\n Array.from(scopes.keys()).forEach(release);\n return;\n }\n for (const scope of scopes.keys()) if (!scope.isConnected || !modalUsesVerticalBars(scope)) release(scope);\n for (const [element, pending] of pendingBacks) if (element.shadowRoot || element.classList.contains('hydrated')) capture(pending.scope);\n // Ionic inserts the destination as invisible before WillEnter. Hide its\n // sources in that same mutation microtask; capture new DOM identities on active pages too.\n verticalBars.querySelectorAll<HTMLElement>('.ion-page:not(ion-app, body, .ion-page-hidden)').forEach(capture);\n // Root toolbars can mount after startup; each new DOM identity is captured once.\n verticalBars.querySelectorAll<HTMLElement>(sourceSelector).forEach((element) => {\n if (routedPage(element) || element.closest(overlays)) return;\n const scope = element.closest<HTMLElement>('ion-toolbar') ?? (element.matches('ion-back-button') ? element : null);\n if (scope) capture(scope);\n });\n for (const owned of scopes.values()) {\n for (const element of owned) {\n const groupOwnsChildren =\n element.parentElement?.matches('ion-buttons') &&\n verticalBarsOwned(element.parentElement) &&\n childElements(element.parentElement).every((child) => verticalBarsOwned(child));\n const hide =\n !suspended &&\n verticalBarsOwned(element) &&\n !groupOwnsChildren &&\n element.isConnected &&\n !element.closest(`.${rejectedClass}`) &&\n !isPermanentlyExcluded(element) &&\n !isShellDisabled(element) &&\n (!element.matches('ion-back-button') || backSupported(element) || !element.classList.contains('hydrated')) &&\n (!element.matches('ion-buttons') || childElements(element).every((child) => verticalBarsOwned(child)));\n element.classList.toggle(prehiddenClass, hide);\n if (element.matches('ion-back-button')) element.classList.toggle(verticalBarsBackWebClass, !hide);\n }\n }\n };\n const onWillEnter = (event: Event) => {\n const page = asElement(event.target);\n if (page?.matches('.ion-page')) {\n verticalBarsPages.lifecycle(event);\n release(page); // Cached pages begin a new placement epoch.\n capture(page);\n reconcile();\n }\n };\n const onPageLifecycle: EventListener = (event) => {\n verticalBarsPages.lifecycle(event);\n if (event.type !== LIFECYCLE_DID_LEAVE) return;\n const page = asElement(event.target);\n if (page) release(page);\n };\n // A canceled transition keeps the leaving page active and abandons the entering one.\n const onTransitionCanceled: EventListener = (event) => {\n const leaving = asElement(event.target);\n if (!leaving) return;\n const entering = (event as CustomEvent<{ entering?: HTMLElement }>).detail?.entering;\n verticalBarsPages.cancel(entering, leaving);\n reconcile();\n };\n doc.addEventListener(LIFECYCLE_WILL_ENTER, onWillEnter, { capture: true, signal: listeners.signal });\n for (const name of [LIFECYCLE_WILL_LEAVE, LIFECYCLE_DID_ENTER, LIFECYCLE_DID_LEAVE])\n doc.addEventListener(name, onPageLifecycle, { capture: true, signal: listeners.signal });\n doc.addEventListener(VERTICAL_BARS_TRANSITION_CANCELED, onTransitionCanceled, { capture: true, signal: listeners.signal });\n doc.defaultView?.addEventListener('nativeUIShellRefresh', reconcile, { signal: listeners.signal });\n reconcile();\n const mutationRelevant = (record: MutationRecord) => {\n if (record.type === 'childList')\n return [...Array.from(record.addedNodes), ...Array.from(record.removedNodes)].some(\n (node) =>\n isHtmlElement(node) &&\n (node.matches(`${sourceSelector}, .ion-page, ion-toolbar`) || !!node.querySelector(`${sourceSelector}, .ion-page, ion-toolbar`)),\n );\n if (record.attributeName !== 'class') return true;\n const current = (record.target as Element).className;\n const previous = record.oldValue ?? '';\n const withoutOwned = (value: string) =>\n value\n .split(/\\s+/)\n .filter((name) => name && ![prehiddenClass, prehideRootClass, verticalBarsBackWebClass].includes(name))\n .join(' ');\n return typeof current !== 'string' || withoutOwned(previous) !== withoutOwned(current);\n };\n let scheduled = false;\n const observer = new (doc.defaultView?.MutationObserver ?? MutationObserver)((records) => {\n if (scheduled || stopped || !records.some(mutationRelevant)) return;\n scheduled = true;\n queueMicrotask(() => {\n scheduled = false;\n if (!stopped) reconcile();\n });\n });\n observer.observe(doc.documentElement, {\n subtree: true,\n childList: true,\n attributes: true,\n attributeOldValue: true,\n attributeFilter: ['class', 'hidden', 'inert', 'icon', 'color'],\n });\n return {\n suspend: () => {\n if (stopped) return () => {};\n suspended++;\n doc.documentElement.classList.remove(prehideRootClass);\n reconcile();\n let resumed = false;\n return () => {\n if (resumed || stopped) return;\n resumed = true;\n if (--suspended === 0) {\n doc.documentElement.classList.add(prehideRootClass);\n reconcile();\n }\n };\n },\n stop: () => {\n if (stopped) return;\n stopped = true;\n observer.disconnect();\n listeners.abort();\n doc.documentElement.classList.remove(prehideRootClass);\n Array.from(scopes.keys()).forEach(release);\n },\n };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"prehide.js","names":[],"sources":["../../src/native/prehide.ts"],"sourcesContent":["import { modalUsesVerticalBars } from './shared/modal';\nimport { LIFECYCLE_DID_ENTER, LIFECYCLE_DID_LEAVE, LIFECYCLE_WILL_ENTER, LIFECYCLE_WILL_LEAVE } from '@ionic/core';\nimport { VERTICAL_BARS_TRANSITION_CANCELED } from '../native-integration';\nimport {\n childElements,\n clearVerticalBarsPlacement,\n createVerticalBarsPageState,\n verticalBarsActionCandidate,\n verticalBarsBackCandidate,\n verticalBarsBackWebClass,\n verticalBarsOwned,\n isVerticalBarsToolbarActionShape,\n isPermanentlyExcluded,\n isShellDisabled,\n prehiddenClass,\n prehideRootClass,\n rejectedClass,\n setVerticalBarsPlacement,\n} from './shared/dom';\n\nconst overlays = 'ion-menu, ion-popover';\nconst sourceSelector = 'ion-back-button, ion-menu-button, ion-buttons, ion-button';\n// Realm- and teardown-safe: globals such as Element/HTMLElement may be gone\n// when a queued mutation microtask or a stale listener still runs.\nconst isHtmlElement = (node: unknown): node is HTMLElement => !!node && (node as Node).nodeType === 1;\nconst asElement = (node: Node | EventTarget | null): HTMLElement | undefined => (isHtmlElement(node) ? node : undefined);\nconst backSupported = (element: HTMLElement): boolean => {\n const back = element as HTMLIonBackButtonElement;\n return back.icon === undefined && back.color === undefined && !!back.shadowRoot;\n};\nconst eligibleBack = verticalBarsBackCandidate;\nconst eligible = verticalBarsActionCandidate;\n\n/** Capture toolbar placement once per routed-page epoch, before Ionic paints its transition. */\nexport const prehideVerticalBarsToolbarSources = (doc: Document): { suspend: () => () => void; stop: () => void } => {\n doc.documentElement.classList.add(prehideRootClass);\n const scopes = new Map<HTMLElement, Set<HTMLElement>>();\n const owner = new WeakMap<HTMLElement, HTMLElement>();\n const pendingBacks = new Map<HTMLElement, { scope: HTMLElement; timer: ReturnType<typeof setTimeout> }>();\n const verticalBarsPages = createVerticalBarsPageState();\n const listeners = new AbortController();\n const root = () => doc.querySelector<HTMLElement>('ion-app.ios-theme-vertical-bars');\n let suspended = 0;\n let stopped = false;\n const routedPage = (element: HTMLElement) => element.closest<HTMLElement>('.ion-page:not(ion-app, body)');\n const release = (scope: HTMLElement) => {\n for (const [element, pending] of pendingBacks) {\n if (pending.scope !== scope) continue;\n clearTimeout(pending.timer);\n pendingBacks.delete(element);\n }\n const owned = scopes.get(scope);\n if (!owned) return;\n owned.forEach((element) => {\n if (owner.get(element) !== scope) return;\n owner.delete(element);\n element.classList.remove(prehiddenClass);\n element.classList.remove(verticalBarsBackWebClass);\n clearVerticalBarsPlacement(element);\n });\n scopes.delete(scope);\n };\n const capture = (scope: HTMLElement) => {\n if (!root()?.contains(scope) || scope.closest(overlays) || !modalUsesVerticalBars(scope) || verticalBarsPages.isDeparted(scope)) return;\n const owned = scopes.get(scope) ?? new Set<HTMLElement>();\n const place = (element: HTMLElement, rail: boolean) => {\n if (owned.has(element)) return;\n const previousScope = owner.get(element);\n if (previousScope) scopes.get(previousScope)?.delete(element);\n owner.set(element, scope);\n setVerticalBarsPlacement(element, rail);\n if (element.matches('ion-back-button')) element.classList.toggle(verticalBarsBackWebClass, !rail);\n owned.add(element);\n };\n const sources = scope.matches('ion-back-button') ? [scope] : Array.from(scope.querySelectorAll<HTMLElement>(sourceSelector));\n sources.forEach((element) => {\n // Shell opt-out is temporary; decide initial placement once it is lifted.\n if (isShellDisabled(element)) return;\n if (!modalUsesVerticalBars(element) || element.closest(overlays) || (scope.matches('.ion-page') && routedPage(element) !== scope))\n return;\n if (element.matches('ion-buttons')) {\n const children = childElements(element);\n const actions = children.filter((child) => eligible(child) && isVerticalBarsToolbarActionShape(child));\n const group =\n eligible(element) &&\n actions.length === children.length &&\n (actions.length > 1 || (actions.length === 1 && actions[0].matches('ion-menu-button')));\n const freshGroup = !owned.has(element);\n place(element, group);\n children.forEach((child) => {\n if (!child.matches('ion-back-button')) place(child, freshGroup && actions.includes(child));\n });\n } else if (element.matches('ion-back-button') || !element.parentElement?.matches('ion-buttons')) {\n if (owned.has(element)) return;\n if (\n element.matches('ion-back-button') &&\n eligibleBack(element) &&\n (element as HTMLIonBackButtonElement).icon === undefined &&\n (element as HTMLIonBackButtonElement).color === undefined &&\n !element.shadowRoot &&\n !element.classList.contains('hydrated')\n ) {\n const previousPending = pendingBacks.get(element);\n if (previousPending && previousPending.scope !== scope) {\n clearTimeout(previousPending.timer);\n pendingBacks.delete(element);\n }\n if (!pendingBacks.has(element)) {\n const timer = setTimeout(() => {\n if (pendingBacks.get(element)?.scope !== scope) return;\n pendingBacks.delete(element);\n // A custom element that never hydrates must remain usable on Web.\n place(element, false);\n reconcile();\n }, 1500);\n pendingBacks.set(element, { scope, timer });\n }\n return;\n }\n const pending = pendingBacks.get(element);\n if (pending) {\n clearTimeout(pending.timer);\n pendingBacks.delete(element);\n }\n place(\n element,\n element.matches('ion-back-button')\n ? eligibleBack(element) && backSupported(element)\n : eligible(element) && isVerticalBarsToolbarActionShape(element),\n );\n }\n });\n scopes.set(scope, owned);\n };\n const reconcile = () => {\n const verticalBars = root();\n if (!verticalBars) {\n Array.from(scopes.keys()).forEach(release);\n return;\n }\n for (const scope of scopes.keys()) if (!scope.isConnected || !modalUsesVerticalBars(scope)) release(scope);\n for (const [element, pending] of pendingBacks) if (element.shadowRoot || element.classList.contains('hydrated')) capture(pending.scope);\n // Ionic inserts the destination as invisible before WillEnter. Hide its\n // sources in that same mutation microtask; capture new DOM identities on active pages too.\n verticalBars.querySelectorAll<HTMLElement>('.ion-page:not(ion-app, body, .ion-page-hidden)').forEach(capture);\n // Root toolbars can mount after startup; each new DOM identity is captured once.\n verticalBars.querySelectorAll<HTMLElement>(sourceSelector).forEach((element) => {\n if (routedPage(element) || element.closest(overlays)) return;\n const scope = element.closest<HTMLElement>('ion-toolbar') ?? (element.matches('ion-back-button') ? element : null);\n if (scope) capture(scope);\n });\n for (const owned of scopes.values()) {\n for (const element of owned) {\n const groupOwnsChildren =\n element.parentElement?.matches('ion-buttons') &&\n verticalBarsOwned(element.parentElement) &&\n childElements(element.parentElement).every((child) => verticalBarsOwned(child));\n const hide =\n !suspended &&\n verticalBarsOwned(element) &&\n !groupOwnsChildren &&\n element.isConnected &&\n !element.closest(`.${rejectedClass}`) &&\n !isPermanentlyExcluded(element) &&\n !isShellDisabled(element) &&\n (!element.matches('ion-back-button') || backSupported(element) || !element.classList.contains('hydrated')) &&\n (!element.matches('ion-buttons') || childElements(element).every((child) => verticalBarsOwned(child)));\n element.classList.toggle(prehiddenClass, hide);\n if (element.matches('ion-back-button')) element.classList.toggle(verticalBarsBackWebClass, !hide);\n }\n }\n };\n const onWillEnter = (event: Event) => {\n const page = asElement(event.target);\n if (page?.matches('.ion-page')) {\n verticalBarsPages.lifecycle(event);\n release(page); // Cached pages begin a new placement epoch.\n capture(page);\n reconcile();\n }\n };\n const onPageLifecycle: EventListener = (event) => {\n verticalBarsPages.lifecycle(event);\n if (event.type !== LIFECYCLE_DID_LEAVE) return;\n const page = asElement(event.target);\n if (page) release(page);\n };\n // A canceled transition keeps the leaving page active and abandons the entering one.\n const onTransitionCanceled: EventListener = (event) => {\n const leaving = asElement(event.target);\n if (!leaving) return;\n const entering = (event as CustomEvent<{ entering?: HTMLElement }>).detail?.entering;\n verticalBarsPages.cancel(entering, leaving);\n reconcile();\n };\n doc.addEventListener(LIFECYCLE_WILL_ENTER, onWillEnter, { capture: true, signal: listeners.signal });\n for (const name of [LIFECYCLE_WILL_LEAVE, LIFECYCLE_DID_ENTER, LIFECYCLE_DID_LEAVE])\n doc.addEventListener(name, onPageLifecycle, { capture: true, signal: listeners.signal });\n doc.addEventListener(VERTICAL_BARS_TRANSITION_CANCELED, onTransitionCanceled, { capture: true, signal: listeners.signal });\n doc.defaultView?.addEventListener('nativeUIShellRefresh', reconcile, { signal: listeners.signal });\n reconcile();\n const mutationRelevant = (record: MutationRecord) => {\n if (record.type === 'childList')\n return [...Array.from(record.addedNodes), ...Array.from(record.removedNodes)].some(\n (node) =>\n isHtmlElement(node) &&\n (node.matches(`${sourceSelector}, .ion-page, ion-toolbar`) || !!node.querySelector(`${sourceSelector}, .ion-page, ion-toolbar`)),\n );\n if (record.attributeName !== 'class') return true;\n const current = (record.target as Element).className;\n const previous = record.oldValue ?? '';\n const withoutOwned = (value: string) =>\n value\n .split(/\\s+/)\n .filter((name) => name && ![prehiddenClass, prehideRootClass, verticalBarsBackWebClass].includes(name))\n .join(' ');\n return typeof current !== 'string' || withoutOwned(previous) !== withoutOwned(current);\n };\n let scheduled = false;\n const observer = new (doc.defaultView?.MutationObserver ?? MutationObserver)((records) => {\n if (scheduled || stopped || !records.some(mutationRelevant)) return;\n scheduled = true;\n queueMicrotask(() => {\n scheduled = false;\n if (!stopped) reconcile();\n });\n });\n observer.observe(doc.documentElement, {\n subtree: true,\n childList: true,\n attributes: true,\n attributeOldValue: true,\n attributeFilter: ['class', 'data-shell', 'hidden', 'inert', 'icon', 'color'],\n });\n return {\n suspend: () => {\n if (stopped) return () => {};\n suspended++;\n doc.documentElement.classList.remove(prehideRootClass);\n reconcile();\n let resumed = false;\n return () => {\n if (resumed || stopped) return;\n resumed = true;\n if (--suspended === 0) {\n doc.documentElement.classList.add(prehideRootClass);\n reconcile();\n }\n };\n },\n stop: () => {\n if (stopped) return;\n stopped = true;\n observer.disconnect();\n listeners.abort();\n doc.documentElement.classList.remove(prehideRootClass);\n Array.from(scopes.keys()).forEach(release);\n },\n };\n};\n"],"mappings":"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"}
|
|
@@ -33,8 +33,9 @@ const appendItem = (candidate, child, id, content = child, label = text(child))
|
|
|
33
33
|
const badge = child.querySelector("ion-badge");
|
|
34
34
|
const badgeStyle = badge && visible(badge) ? getComputedStyle(badge) : void 0;
|
|
35
35
|
const sourceFill = child.fill;
|
|
36
|
-
const projectionOwner = [child, child.closest("ion-buttons")].find((element) => element?.matches(".ios-theme-projection-source, .ios-theme-projection-system"));
|
|
37
|
-
const
|
|
36
|
+
const projectionOwner = [child, child.closest("ion-buttons")].find((element) => element?.matches("[data-projection=\"source\"], [data-projection=\"system\"], .ios-theme-projection-source, .ios-theme-projection-system"));
|
|
37
|
+
const attributeProjection = projectionOwner?.getAttribute("data-projection");
|
|
38
|
+
const systemButton = (attributeProjection === "source" || attributeProjection === "system" ? attributeProjection : projectionOwner ? projectionOwner.classList.contains("ios-theme-projection-system") ? "system" : "source" : candidate.buttonProjection) !== "source" && isVerticalBarsSource(child) && child.matches("ion-button, ion-menu-button");
|
|
38
39
|
const defaultFill = child.closest("ion-buttons") ? "clear" : candidate.buttonDefaultFill;
|
|
39
40
|
const fill = !sourceFill || sourceFill === "default" ? defaultFill : sourceFill;
|
|
40
41
|
const buttonFill = !systemButton && isVerticalBarsSource(child) && child.matches("ion-button") && (fill === "clear" || fill === "solid" || fill === "outline") ? fill : void 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"candidate.js","names":[],"sources":["../../../src/native/shared/candidate.ts"],"sourcesContent":["import type { ShellControl, ShellItem, NativeUIShellComponent, VerticalControlAreaOptions } from '../definitions';\nimport { frame, isDark, isVerticalBarsSource, text, visible } from './dom';\nimport { iconSource } from './icons';\n\nexport interface Candidate {\n buttonProjection?: VerticalControlAreaOptions['buttonProjection'];\n buttonDefaultFill?: VerticalControlAreaOptions['buttonDefaultFill'];\n element: HTMLElement;\n sources?: HTMLElement[];\n control: ShellControl;\n actions: Map<string, HTMLElement>;\n icons: { item: ShellItem; source: string; field?: 'closeIcon' }[];\n}\n\nexport type Identify = (element: HTMLElement) => string;\ntype ItemElement = HTMLElement & { disabled?: boolean; selected?: boolean };\n\nexport const createCandidate = (\n element: HTMLElement,\n kind: NativeUIShellComponent,\n id: Identify,\n options: VerticalControlAreaOptions = {},\n): Candidate => {\n const rect = element.getBoundingClientRect();\n const style = getComputedStyle(element);\n return {\n element,\n buttonProjection: options.buttonProjection,\n buttonDefaultFill: options.buttonDefaultFill,\n control: {\n id: id(element),\n kind,\n ...frame(rect),\n items: [],\n dark: isDark(style),\n rtl: style.direction === 'rtl',\n },\n actions: new Map(),\n icons: [],\n };\n};\n\n// Shared text, artwork, geometry and action data; component rules stay with their readers.\nexport const appendItem = (\n candidate: Candidate,\n child: HTMLElement,\n id: Identify,\n content: ParentNode = child,\n label = text(child),\n): ShellItem | undefined => {\n if (\n !visible(child, isVerticalBarsSource(candidate.element)) ||\n child.querySelector('input, button, a, img, canvas, video, ion-spinner, ion-avatar')\n )\n return;\n const icons = Array.from(content.querySelectorAll<HTMLElement>('ion-icon'));\n const directSVGs = Array.from(content.querySelectorAll<SVGElement>('svg'));\n if (icons.length + directSVGs.length > 1) return undefined;\n const svg = directSVGs[0] ?? icons[0]?.shadowRoot?.querySelector<SVGElement>('svg');\n if (icons.length && !svg) return undefined; // ion-icon has not finished loading.\n const labelElement = content.querySelector('[part=\"text\"], ion-label') ?? child;\n const native = child.shadowRoot?.querySelector('[part=\"native\"]');\n const labelStyle = getComputedStyle(labelElement);\n const badge = child.querySelector<HTMLElement>('ion-badge');\n const badgeStyle = badge && visible(badge) ? getComputedStyle(badge) : undefined;\n const sourceFill = (child as HTMLIonButtonElement).fill;\n const projectionOwner = [child, child.closest('ion-buttons')].find((element) =>\n element?.matches('.ios-theme-projection-source, .ios-theme-projection-system'),\n );\n const projection = projectionOwner\n ? projectionOwner.classList.contains('ios-theme-projection-system')\n ? 'system'\n : 'source'\n : candidate.buttonProjection;\n const systemButton = projection !== 'source' && isVerticalBarsSource(child) && child.matches('ion-button, ion-menu-button');\n // Ionic defaults buttons inside ion-buttons to clear, even when the app defaults to solid.\n const defaultFill = child.closest('ion-buttons') ? 'clear' : candidate.buttonDefaultFill;\n const fill = !sourceFill || sourceFill === 'default' ? defaultFill : sourceFill;\n const buttonFill =\n !systemButton &&\n isVerticalBarsSource(child) &&\n child.matches('ion-button') &&\n (fill === 'clear' || fill === 'solid' || fill === 'outline')\n ? fill\n : undefined;\n const outline = buttonFill === 'outline' ? getComputedStyle(native ?? child) : undefined;\n const item: ShellItem = {\n id: id(child),\n ...frame(child.getBoundingClientRect(), candidate.element.getBoundingClientRect()),\n label,\n accessibilityLabel:\n child.getAttribute('aria-label') ??\n native?.getAttribute('aria-label') ??\n (icons[0]?.getAttribute('aria-hidden') === 'true' ? null : icons[0]?.getAttribute('aria-label')) ??\n label,\n disabled:\n !!(child as ItemElement).disabled ||\n !!(candidate.element as ItemElement).disabled ||\n getComputedStyle(child).pointerEvents === 'none',\n selected: !!(child as ItemElement).selected,\n fontSize: parseFloat(labelStyle.fontSize),\n fontWeight: parseInt(labelStyle.fontWeight, 10) || 400,\n color: systemButton ? 'currentColor' : getComputedStyle(native ?? child).color,\n iconTemplate: systemButton ? true : undefined,\n buttonFill,\n backgroundColor: buttonFill === 'solid' ? getComputedStyle(native ?? child).backgroundColor : undefined,\n borderColor: outline?.borderTopColor,\n borderWidth: outline ? parseFloat(outline.borderTopWidth) : undefined,\n badge: badgeStyle\n ? { value: badge!.textContent?.trim() ?? '', color: badgeStyle.backgroundColor, textColor: badgeStyle.color }\n : undefined,\n };\n if (svg) {\n const source = iconSource(svg);\n if (!source) return undefined;\n const size = (icons[0] ?? svg).getBoundingClientRect();\n item.iconWidth = size.width;\n item.iconHeight = size.height;\n if (!size.width || !size.height) return undefined;\n item.iconPosition = (icons[0] ?? svg).getAttribute('slot') === 'end' ? 'trailing' : 'leading';\n candidate.icons.push({ item, source });\n }\n if (native && child.matches('ion-button, ion-back-button')) {\n const style = getComputedStyle(native);\n const icon = icons[0] ?? svg;\n const iconStyle = icon && getComputedStyle(icon);\n const leadingMargin = parseFloat(iconStyle?.marginInlineStart ?? '') || 0;\n const trailingMargin = parseFloat(iconStyle?.marginInlineEnd ?? '') || 0;\n const trailing = item.iconPosition === 'trailing';\n const inner = native.querySelector('.button-inner');\n const gap = inner ? parseFloat(getComputedStyle(inner).columnGap) || 0 : 0;\n // UIKit centers the title/image pair using its insets. Include Ionic's\n // border and negative outer icon margin instead of applying a fixed offset.\n item.contentInsetLeading =\n (parseFloat(style.paddingInlineStart) || 0) +\n (parseFloat(style.borderInlineStartWidth) || 0) +\n (!trailing || !label ? leadingMargin : 0);\n item.contentInsetTrailing =\n (parseFloat(style.paddingInlineEnd) || 0) + (parseFloat(style.borderInlineEndWidth) || 0) + (trailing || !label ? trailingMargin : 0);\n item.imagePadding = label && icon ? gap + (trailing ? leadingMargin : trailingMargin) : 0;\n }\n if (!label && !svg) return undefined;\n candidate.control.items.push(item);\n candidate.actions.set(item.id, child);\n return item;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"candidate.js","names":[],"sources":["../../../src/native/shared/candidate.ts"],"sourcesContent":["import type { ShellControl, ShellItem, NativeUIShellComponent, VerticalControlAreaOptions } from '../definitions';\nimport { frame, isDark, isVerticalBarsSource, text, visible } from './dom';\nimport { iconSource } from './icons';\n\nexport interface Candidate {\n buttonProjection?: VerticalControlAreaOptions['buttonProjection'];\n buttonDefaultFill?: VerticalControlAreaOptions['buttonDefaultFill'];\n element: HTMLElement;\n sources?: HTMLElement[];\n control: ShellControl;\n actions: Map<string, HTMLElement>;\n icons: { item: ShellItem; source: string; field?: 'closeIcon' }[];\n}\n\nexport type Identify = (element: HTMLElement) => string;\ntype ItemElement = HTMLElement & { disabled?: boolean; selected?: boolean };\n\nexport const createCandidate = (\n element: HTMLElement,\n kind: NativeUIShellComponent,\n id: Identify,\n options: VerticalControlAreaOptions = {},\n): Candidate => {\n const rect = element.getBoundingClientRect();\n const style = getComputedStyle(element);\n return {\n element,\n buttonProjection: options.buttonProjection,\n buttonDefaultFill: options.buttonDefaultFill,\n control: {\n id: id(element),\n kind,\n ...frame(rect),\n items: [],\n dark: isDark(style),\n rtl: style.direction === 'rtl',\n },\n actions: new Map(),\n icons: [],\n };\n};\n\n// Shared text, artwork, geometry and action data; component rules stay with their readers.\nexport const appendItem = (\n candidate: Candidate,\n child: HTMLElement,\n id: Identify,\n content: ParentNode = child,\n label = text(child),\n): ShellItem | undefined => {\n if (\n !visible(child, isVerticalBarsSource(candidate.element)) ||\n child.querySelector('input, button, a, img, canvas, video, ion-spinner, ion-avatar')\n )\n return;\n const icons = Array.from(content.querySelectorAll<HTMLElement>('ion-icon'));\n const directSVGs = Array.from(content.querySelectorAll<SVGElement>('svg'));\n if (icons.length + directSVGs.length > 1) return undefined;\n const svg = directSVGs[0] ?? icons[0]?.shadowRoot?.querySelector<SVGElement>('svg');\n if (icons.length && !svg) return undefined; // ion-icon has not finished loading.\n const labelElement = content.querySelector('[part=\"text\"], ion-label') ?? child;\n const native = child.shadowRoot?.querySelector('[part=\"native\"]');\n const labelStyle = getComputedStyle(labelElement);\n const badge = child.querySelector<HTMLElement>('ion-badge');\n const badgeStyle = badge && visible(badge) ? getComputedStyle(badge) : undefined;\n const sourceFill = (child as HTMLIonButtonElement).fill;\n const projectionOwner = [child, child.closest('ion-buttons')].find((element) =>\n element?.matches('[data-projection=\"source\"], [data-projection=\"system\"], .ios-theme-projection-source, .ios-theme-projection-system'),\n );\n const attributeProjection = projectionOwner?.getAttribute('data-projection');\n const projection =\n attributeProjection === 'source' || attributeProjection === 'system'\n ? attributeProjection\n : projectionOwner\n ? projectionOwner.classList.contains('ios-theme-projection-system')\n ? 'system'\n : 'source'\n : candidate.buttonProjection;\n const systemButton = projection !== 'source' && isVerticalBarsSource(child) && child.matches('ion-button, ion-menu-button');\n // Ionic defaults buttons inside ion-buttons to clear, even when the app defaults to solid.\n const defaultFill = child.closest('ion-buttons') ? 'clear' : candidate.buttonDefaultFill;\n const fill = !sourceFill || sourceFill === 'default' ? defaultFill : sourceFill;\n const buttonFill =\n !systemButton &&\n isVerticalBarsSource(child) &&\n child.matches('ion-button') &&\n (fill === 'clear' || fill === 'solid' || fill === 'outline')\n ? fill\n : undefined;\n const outline = buttonFill === 'outline' ? getComputedStyle(native ?? child) : undefined;\n const item: ShellItem = {\n id: id(child),\n ...frame(child.getBoundingClientRect(), candidate.element.getBoundingClientRect()),\n label,\n accessibilityLabel:\n child.getAttribute('aria-label') ??\n native?.getAttribute('aria-label') ??\n (icons[0]?.getAttribute('aria-hidden') === 'true' ? null : icons[0]?.getAttribute('aria-label')) ??\n label,\n disabled:\n !!(child as ItemElement).disabled ||\n !!(candidate.element as ItemElement).disabled ||\n getComputedStyle(child).pointerEvents === 'none',\n selected: !!(child as ItemElement).selected,\n fontSize: parseFloat(labelStyle.fontSize),\n fontWeight: parseInt(labelStyle.fontWeight, 10) || 400,\n color: systemButton ? 'currentColor' : getComputedStyle(native ?? child).color,\n iconTemplate: systemButton ? true : undefined,\n buttonFill,\n backgroundColor: buttonFill === 'solid' ? getComputedStyle(native ?? child).backgroundColor : undefined,\n borderColor: outline?.borderTopColor,\n borderWidth: outline ? parseFloat(outline.borderTopWidth) : undefined,\n badge: badgeStyle\n ? { value: badge!.textContent?.trim() ?? '', color: badgeStyle.backgroundColor, textColor: badgeStyle.color }\n : undefined,\n };\n if (svg) {\n const source = iconSource(svg);\n if (!source) return undefined;\n const size = (icons[0] ?? svg).getBoundingClientRect();\n item.iconWidth = size.width;\n item.iconHeight = size.height;\n if (!size.width || !size.height) return undefined;\n item.iconPosition = (icons[0] ?? svg).getAttribute('slot') === 'end' ? 'trailing' : 'leading';\n candidate.icons.push({ item, source });\n }\n if (native && child.matches('ion-button, ion-back-button')) {\n const style = getComputedStyle(native);\n const icon = icons[0] ?? svg;\n const iconStyle = icon && getComputedStyle(icon);\n const leadingMargin = parseFloat(iconStyle?.marginInlineStart ?? '') || 0;\n const trailingMargin = parseFloat(iconStyle?.marginInlineEnd ?? '') || 0;\n const trailing = item.iconPosition === 'trailing';\n const inner = native.querySelector('.button-inner');\n const gap = inner ? parseFloat(getComputedStyle(inner).columnGap) || 0 : 0;\n // UIKit centers the title/image pair using its insets. Include Ionic's\n // border and negative outer icon margin instead of applying a fixed offset.\n item.contentInsetLeading =\n (parseFloat(style.paddingInlineStart) || 0) +\n (parseFloat(style.borderInlineStartWidth) || 0) +\n (!trailing || !label ? leadingMargin : 0);\n item.contentInsetTrailing =\n (parseFloat(style.paddingInlineEnd) || 0) + (parseFloat(style.borderInlineEndWidth) || 0) + (trailing || !label ? trailingMargin : 0);\n item.imagePadding = label && icon ? gap + (trailing ? leadingMargin : trailingMargin) : 0;\n }\n if (!label && !svg) return undefined;\n candidate.control.items.push(item);\n candidate.actions.set(item.id, child);\n return item;\n};\n"],"mappings":"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"}
|
|
@@ -10,7 +10,7 @@ export declare const verticalBarsBackWebClass = "ios-theme-vertical-bars-back-we
|
|
|
10
10
|
export declare const prehideOnlyMutation: (record: MutationRecord) => boolean;
|
|
11
11
|
export declare const withoutPrehide: <T>(element: HTMLElement, read: () => T) => T;
|
|
12
12
|
export declare const isDark: (style: CSSStyleDeclaration) => boolean;
|
|
13
|
-
export declare const excluded = ".
|
|
13
|
+
export declare const excluded = ".ios-theme-disabled, .ios26-disabled, .ion-cloned-element, [hidden], [inert], .ion-page-hidden, .ion-page-invisible";
|
|
14
14
|
export declare const setVerticalBarsEnteringPage: (page: HTMLElement, entering: boolean) => void;
|
|
15
15
|
export declare const verticalBarsEnteringPage: (element: HTMLElement) => HTMLElement | undefined;
|
|
16
16
|
export declare const createVerticalBarsPageState: () => {
|
|
@@ -38,7 +38,7 @@ const isDark = (style) => {
|
|
|
38
38
|
const background = style.getPropertyValue("--ion-background-color-rgb").match(/\d+/g)?.slice(0, 3).map(Number);
|
|
39
39
|
return !!background && background.length === 3 && background[0] * .2126 + background[1] * .7152 + background[2] * .0722 < 128;
|
|
40
40
|
};
|
|
41
|
-
const permanentlyExcluded = ".
|
|
41
|
+
const permanentlyExcluded = ".ios-theme-disabled, .ios26-disabled, .ion-cloned-element, [hidden], [inert]";
|
|
42
42
|
const excluded = `${permanentlyExcluded}, .ion-page-hidden, .ion-page-invisible`;
|
|
43
43
|
const enteringPages = /* @__PURE__ */ new WeakSet();
|
|
44
44
|
const setVerticalBarsEnteringPage = (page, entering) => {
|
|
@@ -73,8 +73,8 @@ const createVerticalBarsPageState = () => {
|
|
|
73
73
|
}
|
|
74
74
|
};
|
|
75
75
|
};
|
|
76
|
-
const disabledButtonGroup = "ion-buttons:is(.
|
|
77
|
-
const shellDisabledSelector = ".ios-theme-shell-disabled";
|
|
76
|
+
const disabledButtonGroup = "ion-buttons:is(.ios-theme-disabled, .ios26-disabled)";
|
|
77
|
+
const shellDisabledSelector = ".ios-theme-shell-disabled, [data-shell=\"disabled\"]";
|
|
78
78
|
const isDisabledButtonGroupChild = (element) => element.matches("ion-button") && element.parentElement?.matches(disabledButtonGroup) === true;
|
|
79
79
|
const verticalBarsTags = /* @__PURE__ */ new Set([
|
|
80
80
|
"ion-button",
|
|
@@ -121,7 +121,7 @@ const verticalBarsActionCandidate = (element) => inFixedToolbar(element) && !ele
|
|
|
121
121
|
const verticalBarsBackCandidate = (element) => isVerticalBarsBackPosition(element) && !element.closest("ion-buttons.ios-theme-horizontal-only") && !isPermanentlyExcluded(element) && !isShellDisabled(element) && !element.closest(overlays) && modalUsesVerticalBars(element);
|
|
122
122
|
const verticalBarsToolbarActions = (element) => childElements(element).filter((child) => !child.matches("ion-back-button") && isVerticalBarsToolbarAction(child));
|
|
123
123
|
const isVerticalBarsToolbarGroup = (element) => {
|
|
124
|
-
return element.matches("ion-buttons") && verticalBarsOwned(element) && !element.matches(".
|
|
124
|
+
return element.matches("ion-buttons") && verticalBarsOwned(element) && !element.matches(".ios-theme-disabled, .ios26-disabled") && !isShellDisabled(element);
|
|
125
125
|
};
|
|
126
126
|
const activateProjectedElement = (element) => {
|
|
127
127
|
((element.matches("ion-button, ion-back-button, ion-menu-button") ? element.shadowRoot?.querySelector("[part~=\"native\"]") : void 0) ?? element).click();
|
|
@@ -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 = '.ionic-theme-disabled, .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(.ionic-theme-disabled, .ios-theme-disabled, .ios26-disabled)';\nconst shellDisabledSelector = '.ios-theme-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('.ionic-theme-disabled, .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 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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"}
|
package/docs/features.md
CHANGED
|
@@ -27,9 +27,9 @@ ion-textarea label.textarea-wrapper {
|
|
|
27
27
|
}
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
## Native UI Shell (
|
|
30
|
+
## Native UI Shell (Preview)
|
|
31
31
|
|
|
32
|
-
Capacitor iOS apps can use the optional
|
|
32
|
+
Capacitor iOS apps can use the optional [Native UI Shell](https://docs.rdlabo.dev/projects/ionic-theme-ios27/docs/native-ui-shell) to render supported fixed Ionic controls with UIKit and system Liquid Glass. It is available as a preview in `1.2.0`. Content and application logic stay in the WebView, with Ionic owning routing and page transitions. The guide explains the hybrid approach's origins in Basecamp and Capacitor, setup, supported controls and Web fallback behavior.
|
|
33
33
|
|
|
34
34
|
## Selective component imports
|
|
35
35
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: iPhone Duo with your existing theme (
|
|
2
|
+
title: iPhone Duo with your existing theme (preview)
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
# iPhone Duo with your existing theme (
|
|
5
|
+
# iPhone Duo with your existing theme (preview)
|
|
6
6
|
|
|
7
7
|
Add a vertical navigation area to your Ionic app while keeping its existing theme. Tabs and supported toolbar actions move to the side of the screen; your content and horizontal controls keep their current appearance. Both Ionic `ios` and `md` modes are supported.
|
|
8
8
|
|
|
9
9
|
**Try it in Chrome first.** You can preview the layout with Web controls before setting up an iPhone Duo or an iOS build. On supported Capacitor iOS, the same Ionic markup supplies native SwiftUI controls in the system rail.
|
|
10
10
|
|
|
11
|
-
Available in `1.2.0
|
|
11
|
+
Available in `1.2.0` as a **preview** feature. APIs and supported behavior may change.
|
|
12
12
|
|
|
13
13
|
## Try it in your existing Ionic app
|
|
14
14
|
|
|
@@ -17,7 +17,7 @@ Available in `1.2.0-0` as an **experimental** feature. APIs and supported behavi
|
|
|
17
17
|
This guide assumes an existing Ionic app with Ionic `>=8.8.1 <10` and Capacitor Core `>=8 <9`. Keep your existing Capacitor 8 installation. If your app uses another Capacitor major, migrate its Core, CLI, and platform packages together before following this guide. For a Web-only app without Capacitor, also install `@capacitor/core@^8`; the JavaScript entry point needs it even in Chrome.
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
npm install @rdlabo/ionic-theme-ios27@1.2.0
|
|
20
|
+
npm install @rdlabo/ionic-theme-ios27@1.2.0
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
Keep your existing theme imports. Add this to your global Sass file:
|
|
@@ -94,8 +94,6 @@ The adapter returns the original `Animation`, preserving its effects, duration,
|
|
|
94
94
|
|
|
95
95
|
The adapter keeps the builder's animation targets, including any horizontal back-button effect. If you need the iOS 27 transition with that effect excluded in vertical layouts, use `iosTransitionAnimation` from `@rdlabo/ionic-theme-ios27` as your `navAnimation` instead. It already includes the adapter, so no wrapper is needed.
|
|
96
96
|
|
|
97
|
-
`withNativeUIShellTransition()` is available in `1.2.0-1` and later.
|
|
98
|
-
|
|
99
97
|
### 4. Start the controls after the app root is mounted
|
|
100
98
|
|
|
101
99
|
Call this once from your application startup after `ion-app` exists in the DOM:
|
|
@@ -112,9 +110,9 @@ Use your existing Ionic click handlers, routing, and form associations. All butt
|
|
|
112
110
|
|
|
113
111
|
When the application owner is disposed, call `await rail.destroy()` to restore the original controls and release the runtime. If you already use `enableNativeUIShell()`, keep that runtime and follow the [shared placement guide](https://docs.rdlabo.dev/projects/ionic-theme-ios27/docs/iphone-duo#project-controls-into-the-rail).
|
|
114
112
|
|
|
115
|
-
### Optional: choose native button appearance
|
|
113
|
+
### Optional: choose native button appearance
|
|
116
114
|
|
|
117
|
-
|
|
115
|
+
`buttonProjection` and local projection settings are available in `1.2.0`. See [Choose button appearance](https://docs.rdlabo.dev/projects/ionic-theme-ios27/docs/vertical-bars#choose-button-appearance) for availability and migration details.
|
|
118
116
|
|
|
119
117
|
The new default is `system`: SwiftUI styles vertical buttons and tints their icons. If your existing theme should supply their fill and colors, use:
|
|
120
118
|
|
|
@@ -122,7 +120,7 @@ The new default is `system`: SwiftUI styles vertical buttons and tints their ico
|
|
|
122
120
|
const rail = await enableVerticalControlArea({ buttonProjection: 'source', buttonDefaultFill: 'solid' });
|
|
123
121
|
```
|
|
124
122
|
|
|
125
|
-
The `solid` default suits ordinary Ionic buttons. Buttons inside `ion-buttons` still default to clear; set `fill="solid"` explicitly to project their background. For one-off exceptions, use the [local projection
|
|
123
|
+
The `solid` default suits ordinary Ionic buttons. Buttons inside `ion-buttons` still default to clear; set `fill="solid"` explicitly to project their background. For one-off exceptions, use the [local projection settings](https://docs.rdlabo.dev/projects/ionic-theme-ios27/docs/vertical-bars#override-individual-buttons-or-groups). These settings affect native vertical buttons only; Web clones keep their existing appearance.
|
|
126
124
|
|
|
127
125
|
### If the preview does not appear
|
|
128
126
|
|
package/docs/iphone-duo.md
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: iPhone Duo support (
|
|
2
|
+
title: iPhone Duo support (preview)
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
# iPhone Duo support (
|
|
5
|
+
# iPhone Duo support (preview)
|
|
6
6
|
|
|
7
7
|
Adapt your Ionic app to iPhone Duo: place navigation and actions in its vertical system rail, and adjust your split pane as the device opens and closes. Existing Ionic markup remains the source of labels, icons, routing, and click handlers.
|
|
8
8
|
|
|
9
9
|
**New here?** Start with [iPhone Duo with your existing theme](https://docs.rdlabo.dev/projects/ionic-theme-ios27/docs/iphone-duo-with-original-theme) to preview the side layout in Chrome. This page explains device events, placement and split panes. [Vertical Bars](https://docs.rdlabo.dev/projects/ionic-theme-ios27/docs/vertical-bars) documents control projection and the runtime API.
|
|
10
10
|
|
|
11
|
-
Available in `1.2.0
|
|
11
|
+
Available in `1.2.0` as a **preview** feature alongside [Native UI Shell](https://docs.rdlabo.dev/projects/ionic-theme-ios27/docs/native-ui-shell). APIs and supported behavior may change before stable status. Stable status is planned after the official release of Xcode 27.1. The real system rail and hinge reporting require iOS 27.1 or later and an app built with Xcode 27.1 or newer.
|
|
12
12
|
|
|
13
13
|
This package provides two independent pieces for that hardware. Each works **without the iOS 27 theme stylesheets** and **without the full Native UI Shell**:
|
|
14
14
|
|