@rdlabo/ionic-theme-ios27 1.2.0-1 → 1.2.0-beta.pr226.shaa2e125f11160
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/css/ionic-theme-ios27.css +1 -1
- package/dist/css/vertical-bars.css +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +31 -12
- package/dist/sheets-of-glass/animations.d.ts +13 -4
- package/dist/sheets-of-glass/animations.d.ts.map +1 -1
- package/dist/sheets-of-glass/animations.js +45 -32
- package/dist/sheets-of-glass/index.d.ts +1 -1
- package/dist/sheets-of-glass/index.d.ts.map +1 -1
- package/dist/sheets-of-glass/index.js +40 -19
- package/docs/iphone-duo-with-original-theme.md +17 -3
- package/docs/migration.md +3 -3
- package/docs/native-ui-shell.md +1 -1
- package/package.json +1 -1
- package/src/index.ts +40 -9
- package/src/sheets-of-glass/animations.ts +54 -33
- package/src/sheets-of-glass/index.ts +54 -15
- package/src/styles/vertical-bars.scss +14 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
@property --ios-theme-split-pane-width{syntax:"<length>";inherits:false;initial-value:320px}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.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-content: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}ion-app.ios-theme-vertical-bars ion-content:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-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 *,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 *,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 *,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 *,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: 50px;--ios-theme-side-tab-bar-gap: 8px;--ios-theme-side-safe-area: var(--ios-theme-vertical-bars-safe-area-right-resolved);contain:layout style;position:absolute;z-index:2;display:flex;flex-direction:column;width:46px;min-width:46px;max-width:46px;height:fit-content;min-height:0;padding:2px;border-radius:25px;left:auto;right:max(4px,(var(--ios-theme-side-safe-area) - var(--ios-theme-side-tab-bar-width))/2);margin:0;top:auto;bottom:calc(var(--ion-safe-area-bottom, 0px) + 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)>ion-tab-button:not(.ion-cloned-element){display:block;flex:none;width:46px;min-width:46px;height:52px;min-height:52px;border-radius:23px}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}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:not(.ion-cloned-element)~ion-tab-button:not(.ion-cloned-element){margin-block-start:0;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):has(>ion-tab-button:is(.ion-activated,:active))>ion-tab-button:not(.ion-cloned-element)::part(native){flex-direction:column;padding-block:4px}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):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:44px;padding:0;margin:1px 0 0;overflow:hidden;clip:auto;font-size:.5rem;line-height:1;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):has(>ion-tab-button:is(.ion-activated,:active))>ion-tab-button:not(.ion-cloned-element) ion-icon{margin:0;font-size:22px}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){--ios-theme-side-safe-area: var(--ios-theme-vertical-bars-safe-area-left-resolved);right:auto;left:max(4px,(var(--ios-theme-side-safe-area) - 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 *,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 *,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 *,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{position:fixed;z-index:1001;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{position:fixed;z-index:1001;top:calc(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){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{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{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{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{--background: rgba(var(--ios-theme-glass-background-rgb, var(--ios26-glass-background-rgb)), 0.72);--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::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::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{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{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){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{right:auto;left:max(4px,(var(--ios-theme-vertical-bars-safe-area-left-resolved) - 46px)/2)}
|
|
1
|
+
@property --ios-theme-split-pane-width{syntax:"<length>";inherits:false;initial-value:320px}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.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-content: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}ion-app.ios-theme-vertical-bars ion-content:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-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 *,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 *,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 *,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 *,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: 50px;--ios-theme-side-tab-bar-gap: 8px;--ios-theme-side-safe-area: var(--ios-theme-vertical-bars-safe-area-right-resolved);contain:layout style;position:absolute;z-index:2;display:flex;flex-direction:column;width:46px;min-width:46px;max-width:46px;height:fit-content;min-height:0;padding:2px;border-radius:25px;left:auto;right:max(4px,(var(--ios-theme-side-safe-area) - var(--ios-theme-side-tab-bar-width))/2);margin:0;top:auto;bottom:calc(var(--ion-safe-area-bottom, 0px) + 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:46px;min-width:46px;height:52px;min-height:52px;border-radius:23px}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:52px}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:not(.ion-cloned-element)~ion-tab-button:not(.ion-cloned-element){margin-block-start:0;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):has(>ion-tab-button:is(.ion-activated,:active))>ion-tab-button:not(.ion-cloned-element)::part(native){flex-direction:column;padding-block:4px}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):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:44px;padding:0;margin:1px 0 0;overflow:hidden;clip:auto;font-size:.5rem;line-height:1;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):has(>ion-tab-button:is(.ion-activated,:active))>ion-tab-button:not(.ion-cloned-element) ion-icon{margin:0;font-size:22px}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){--ios-theme-side-safe-area: var(--ios-theme-vertical-bars-safe-area-left-resolved);right:auto;left:max(4px,(var(--ios-theme-side-safe-area) - 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 *,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 *,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 *,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{position:fixed;z-index:1001;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{position:fixed;z-index:1001;top:calc(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){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{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{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{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{--background: rgba(var(--ios-theme-glass-background-rgb, var(--ios26-glass-background-rgb)), 0.72);--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::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::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{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{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){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{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:23px}ion-tab-button.ios.ion-cloned-element.ios27-vertical-tab-effect::part(native){min-height:0;height:100%}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEhE,cAAc,8BAA8B,CAAC;AAC7C,OAAO,EACL,wBAAwB,IAAI,qBAAqB,EACjD,wBAAwB,IAAI,qBAAqB,GAClD,MAAM,2BAA2B,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,aAAa,CAAC;AAC5B,cAAc,6BAA6B,CAAC;AAC5C,OAAO,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAElD,eAAO,MAAM,oBAAoB,GAAI,eAAe,WAAW,KAAG,gBAAgB,GAAG,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEhE,cAAc,8BAA8B,CAAC;AAC7C,OAAO,EACL,wBAAwB,IAAI,qBAAqB,EACjD,wBAAwB,IAAI,qBAAqB,GAClD,MAAM,2BAA2B,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,aAAa,CAAC;AAC5B,cAAc,6BAA6B,CAAC;AAC5C,OAAO,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAElD,eAAO,MAAM,oBAAoB,GAAI,eAAe,WAAW,KAAG,gBAAgB,GAAG,SA+DpF,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -13,24 +13,43 @@ export const registerTabBarEffect = (targetElement) => {
|
|
|
13
13
|
const reducedMotion = win.matchMedia('(prefers-reduced-motion: reduce)');
|
|
14
14
|
const verticalBarsRoot = targetElement.closest('ion-app');
|
|
15
15
|
let effect;
|
|
16
|
+
let placement;
|
|
16
17
|
const update = () => {
|
|
18
|
+
const isVertical = !!verticalBarsRoot?.classList.contains('ios-theme-vertical-bars') &&
|
|
19
|
+
targetElement.matches('ion-tabs > ion-tab-bar:not(.ios-theme-disabled, .ios26-disabled)') &&
|
|
20
|
+
!targetElement.closest('ion-menu, ion-modal, ion-popover');
|
|
21
|
+
const disabled = reducedMotion.matches || !targetElement.matches('.ios:not(.ios-theme-disabled, .ios26-disabled)');
|
|
22
|
+
const nextPlacement = disabled
|
|
23
|
+
? 'disabled'
|
|
24
|
+
: isVertical
|
|
25
|
+
? verticalBarsRoot?.classList.contains('ios-theme-vertical-bars-left')
|
|
26
|
+
? 'left'
|
|
27
|
+
: 'right'
|
|
28
|
+
: 'horizontal';
|
|
29
|
+
if (placement === nextPlacement)
|
|
30
|
+
return;
|
|
31
|
+
placement = nextPlacement;
|
|
17
32
|
effect?.destroy();
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
:
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
xlarge: 'scale(1.3)',
|
|
27
|
-
});
|
|
33
|
+
effect = disabled
|
|
34
|
+
? undefined
|
|
35
|
+
: registerEffect(targetElement, 'ion-tab-button', 'tab-selected', {
|
|
36
|
+
small: 'scale(1.1, 1)',
|
|
37
|
+
medium: 'scale(1.2)',
|
|
38
|
+
large: 'scale(1.15, 1.4)',
|
|
39
|
+
xlarge: 'scale(1.3)',
|
|
40
|
+
}, isVertical);
|
|
28
41
|
};
|
|
29
42
|
update();
|
|
30
43
|
reducedMotion.addEventListener('change', update);
|
|
31
|
-
const placementObserver = new win.MutationObserver(
|
|
44
|
+
const placementObserver = new win.MutationObserver((records) => {
|
|
45
|
+
if (records.some((record) => record.type === 'attributes'
|
|
46
|
+
? record.target === targetElement || record.target === verticalBarsRoot
|
|
47
|
+
: [...Array.from(record.addedNodes), ...Array.from(record.removedNodes)].some((node) => node.contains(targetElement))))
|
|
48
|
+
update();
|
|
49
|
+
});
|
|
32
50
|
if (verticalBarsRoot)
|
|
33
|
-
placementObserver.observe(verticalBarsRoot, { attributes: true, attributeFilter: ['class'] });
|
|
51
|
+
placementObserver.observe(verticalBarsRoot, { attributes: true, attributeFilter: ['class'], childList: true, subtree: true });
|
|
52
|
+
placementObserver.observe(targetElement, { attributes: true, attributeFilter: ['class'] });
|
|
34
53
|
return {
|
|
35
54
|
destroy: () => {
|
|
36
55
|
reducedMotion.removeEventListener('change', update);
|
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
import type { Animation, AnimationKeyFrames } from '@ionic/core';
|
|
2
2
|
import { AnimationPosition, EffectScales } from './interfaces';
|
|
3
3
|
import { GestureDetail } from '@ionic/core';
|
|
4
|
+
export declare const animationRect: (element: Element, vertical?: boolean) => DOMRect | {
|
|
5
|
+
left: number;
|
|
6
|
+
top: number;
|
|
7
|
+
right: number;
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
x: number;
|
|
11
|
+
y: number;
|
|
12
|
+
};
|
|
4
13
|
export declare const getScaleAnimation: (effectElement: Element) => Animation;
|
|
5
|
-
export declare const createTabBarPressAnimation: (effect: HTMLElement, from: HTMLElement, to: HTMLElement, bar: HTMLElement) => Animation;
|
|
6
|
-
export declare const createTabBarDragAnimation: (effect: HTMLElement, bar: HTMLElement, velocity: number) => Animation;
|
|
14
|
+
export declare const createTabBarPressAnimation: (effect: HTMLElement, from: HTMLElement, to: HTMLElement, bar: HTMLElement, vertical?: boolean) => Animation;
|
|
15
|
+
export declare const createTabBarDragAnimation: (effect: HTMLElement, bar: HTMLElement, velocity: number, vertical?: boolean) => Animation;
|
|
7
16
|
export declare const createTabBarReleaseAnimation: (effectElement: Element, target: HTMLElement, tap?: {
|
|
8
17
|
elapsed: number;
|
|
9
18
|
distance: number;
|
|
10
|
-
}) => Animation;
|
|
19
|
+
}, vertical?: boolean) => Animation;
|
|
11
20
|
export declare const createPreMoveAnimation: (effectElement: Element, tabSelectedElement: Element, currentTouchedElement: Element, animationPosition: AnimationPosition) => Animation;
|
|
12
|
-
export declare const createMoveAnimation: (effectElement: Element, detail: GestureDetail, tabSelectedElement: Element, animationPosition: AnimationPosition) => Animation;
|
|
21
|
+
export declare const createMoveAnimation: (effectElement: Element, detail: GestureDetail, tabSelectedElement: Element, animationPosition: AnimationPosition, vertical?: boolean) => Animation;
|
|
13
22
|
export declare const getMoveAnimationKeyframe: (type: "moveRight" | "moveLeft" | "slowly", scales: EffectScales) => AnimationKeyFrames;
|
|
14
23
|
//# sourceMappingURL=animations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"animations.d.ts","sourceRoot":"","sources":["../../src/sheets-of-glass/animations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"animations.d.ts","sourceRoot":"","sources":["../../src/sheets-of-glass/animations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AAI7D,eAAO,MAAM,aAAa,GAAI,SAAS,OAAO,EAAE,kBAAgB;;;;;;;;CAK/D,CAAC;AASF,eAAO,MAAM,iBAAiB,GAAI,eAAe,OAAO,KAAG,SAE1D,CAAC;AAyCF,eAAO,MAAM,0BAA0B,GACrC,QAAQ,WAAW,EACnB,MAAM,WAAW,EACjB,IAAI,WAAW,EACf,KAAK,WAAW,EAChB,kBAAgB,KACf,SAqCF,CAAC;AAGF,eAAO,MAAM,yBAAyB,GAAI,QAAQ,WAAW,EAAE,KAAK,WAAW,EAAE,UAAU,MAAM,EAAE,kBAAgB,KAAG,SAmBrH,CAAC;AAGF,eAAO,MAAM,4BAA4B,GACvC,eAAe,OAAO,EACtB,QAAQ,WAAW,EACnB,MAAM;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EAC3C,kBAAgB,KACf,SAgIF,CAAC;AAEF,eAAO,MAAM,sBAAsB,GACjC,eAAe,OAAO,EACtB,oBAAoB,OAAO,EAC3B,uBAAuB,OAAO,EAC9B,mBAAmB,iBAAiB,KACnC,SA0BF,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,eAAe,OAAO,EACtB,QAAQ,aAAa,EACrB,oBAAoB,OAAO,EAC3B,mBAAmB,iBAAiB,EACpC,kBAAgB,KACf,SAiBF,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAI,MAAM,WAAW,GAAG,UAAU,GAAG,QAAQ,EAAE,QAAQ,YAAY,KAAG,kBAqD1G,CAAC"}
|
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import { createAnimation } from '@ionic/core';
|
|
2
2
|
import { getStep } from '../utils';
|
|
3
|
+
export const animationRect = (element, vertical = false) => {
|
|
4
|
+
const rect = element.getBoundingClientRect();
|
|
5
|
+
return vertical
|
|
6
|
+
? { left: rect.top, top: rect.left, right: rect.bottom, width: rect.height, height: rect.width, x: rect.y, y: rect.x }
|
|
7
|
+
: rect;
|
|
8
|
+
};
|
|
9
|
+
const translate = (x, y, vertical) => `translate3d(${vertical ? y : x}px, ${vertical ? x : y}px, 0)`;
|
|
10
|
+
const stretchTransform = (x, y, vertical) => `scale(${vertical ? y : x}, ${vertical ? x : y})`;
|
|
11
|
+
const mainSize = (element, vertical) => (vertical ? element.offsetHeight : element.offsetWidth);
|
|
12
|
+
const axisScale = (transform, vertical) => {
|
|
13
|
+
const matrix = new DOMMatrixReadOnly(transform);
|
|
14
|
+
return vertical ? { a: matrix.d, d: matrix.a } : matrix;
|
|
15
|
+
};
|
|
3
16
|
export const getScaleAnimation = (effectElement) => {
|
|
4
17
|
return createAnimation().addElement(effectElement.shadowRoot.querySelector('[part="native"]')).easing('ease-out');
|
|
5
18
|
};
|
|
@@ -37,21 +50,21 @@ const tabBarTapFrames = [
|
|
|
37
50
|
[0.7, 1.003, -0.74, 0.59],
|
|
38
51
|
[0.8, 1, 0, 0],
|
|
39
52
|
];
|
|
40
|
-
export const createTabBarPressAnimation = (effect, from, to, bar) => {
|
|
41
|
-
const box = bar
|
|
53
|
+
export const createTabBarPressAnimation = (effect, from, to, bar, vertical = false) => {
|
|
54
|
+
const box = animationRect(bar, vertical);
|
|
42
55
|
const center = box.left + box.width / 2;
|
|
43
|
-
const left = center - bar
|
|
44
|
-
const fromBox = from
|
|
45
|
-
const toBox = to
|
|
46
|
-
const parentScale = box.width / bar
|
|
47
|
-
const buttonScale =
|
|
56
|
+
const left = center - mainSize(bar, vertical) / 2;
|
|
57
|
+
const fromBox = animationRect(from, vertical);
|
|
58
|
+
const toBox = animationRect(to, vertical);
|
|
59
|
+
const parentScale = box.width / mainSize(bar, vertical);
|
|
60
|
+
const buttonScale = axisScale(getComputedStyle(from).transform, vertical);
|
|
48
61
|
const width = fromBox.width / parentScale / buttonScale.a;
|
|
49
62
|
const height = fromBox.height / parentScale / buttonScale.d;
|
|
50
63
|
const start = (fromBox.left + fromBox.width / 2 - box.left) / parentScale;
|
|
51
64
|
const end = (toBox.left + toBox.width / 2 - box.left) / parentScale;
|
|
52
65
|
const selected = from === to;
|
|
53
66
|
const frames = tabBarPressFrames.map(([time, position, extraWidth, extraHeight, expansion]) => {
|
|
54
|
-
const scale = 1 + (14.14 / bar
|
|
67
|
+
const scale = 1 + (14.14 / mainSize(bar, vertical)) * expansion;
|
|
55
68
|
const press = 1 - Math.exp(-18 * time) * (1 + 18 * time);
|
|
56
69
|
return {
|
|
57
70
|
offset: time / 0.9,
|
|
@@ -63,22 +76,22 @@ export const createTabBarPressAnimation = (effect, from, to, bar) => {
|
|
|
63
76
|
const move = createAnimation()
|
|
64
77
|
.addElement(effect)
|
|
65
78
|
.beforeStyles({
|
|
66
|
-
width: `${width}px`,
|
|
67
|
-
height: `${height}px`,
|
|
79
|
+
width: `${vertical ? height : width}px`,
|
|
80
|
+
height: `${vertical ? width : height}px`,
|
|
68
81
|
display: 'block',
|
|
69
82
|
opacity: '1',
|
|
70
83
|
})
|
|
71
|
-
.keyframes(frames.map(({ offset, x }) => ({ offset, transform:
|
|
84
|
+
.keyframes(frames.map(({ offset, x }) => ({ offset, transform: translate(x, box.top + box.height / 2 - height / 2, vertical) })));
|
|
72
85
|
const stretch = getScaleAnimation(effect)
|
|
73
86
|
.easing('linear')
|
|
74
|
-
.keyframes(frames.map(({ offset, sx, sy }) => ({ offset, transform:
|
|
87
|
+
.keyframes(frames.map(({ offset, sx, sy }) => ({ offset, transform: stretchTransform(sx, sy, vertical) })));
|
|
75
88
|
return createAnimation().duration(900).easing('linear').addAnimation([move, stretch]);
|
|
76
89
|
};
|
|
77
|
-
export const createTabBarDragAnimation = (effect, bar, velocity) => {
|
|
90
|
+
export const createTabBarDragAnimation = (effect, bar, velocity, vertical = false) => {
|
|
78
91
|
const native = effect.shadowRoot.querySelector('[part="native"]');
|
|
79
|
-
const current =
|
|
80
|
-
const { width, height } = effect
|
|
81
|
-
const scale = 1 + 14.14 / bar
|
|
92
|
+
const current = axisScale(native.style.transform || getComputedStyle(native).transform, vertical);
|
|
93
|
+
const { width, height } = animationRect(effect, vertical);
|
|
94
|
+
const scale = 1 + 14.14 / mainSize(bar, vertical);
|
|
82
95
|
const restX = ((width + 16) * scale) / width;
|
|
83
96
|
const restY = ((height + 16) * scale) / height;
|
|
84
97
|
const stretch = Math.min(16, 32 * velocity * velocity) * scale;
|
|
@@ -87,16 +100,16 @@ export const createTabBarDragAnimation = (effect, bar, velocity) => {
|
|
|
87
100
|
.duration(500)
|
|
88
101
|
.easing('linear')
|
|
89
102
|
.keyframes([
|
|
90
|
-
{ offset: 0, transform:
|
|
91
|
-
{ offset: 0.2, transform:
|
|
92
|
-
{ offset: 0.44, transform:
|
|
93
|
-
{ offset: 1, transform:
|
|
103
|
+
{ offset: 0, transform: stretchTransform(current.a, current.d, vertical) },
|
|
104
|
+
{ offset: 0.2, transform: stretchTransform(restX + stretch / width, restY - stretch / height, vertical) },
|
|
105
|
+
{ offset: 0.44, transform: stretchTransform(restX - rebound / width, restY + rebound / height, vertical) },
|
|
106
|
+
{ offset: 1, transform: stretchTransform(restX, restY, vertical) },
|
|
94
107
|
]);
|
|
95
108
|
};
|
|
96
|
-
export const createTabBarReleaseAnimation = (effectElement, target, tap) => {
|
|
109
|
+
export const createTabBarReleaseAnimation = (effectElement, target, tap, vertical = false) => {
|
|
97
110
|
const tapElapsed = tap?.elapsed;
|
|
98
111
|
const native = effectElement.shadowRoot.querySelector('[part="native"]');
|
|
99
|
-
const scale =
|
|
112
|
+
const scale = axisScale(native.style.transform || getComputedStyle(native).transform, vertical);
|
|
100
113
|
const samples = [
|
|
101
114
|
[0, 1],
|
|
102
115
|
[0.033, 0.85],
|
|
@@ -110,11 +123,11 @@ export const createTabBarReleaseAnimation = (effectElement, target, tap) => {
|
|
|
110
123
|
[0.45, 0],
|
|
111
124
|
];
|
|
112
125
|
const bar = target.parentElement;
|
|
113
|
-
const box = bar
|
|
114
|
-
const current = effectElement
|
|
115
|
-
const targetBox = target
|
|
126
|
+
const box = animationRect(bar, vertical);
|
|
127
|
+
const current = animationRect(effectElement, vertical);
|
|
128
|
+
const targetBox = animationRect(target, vertical);
|
|
116
129
|
const center = box.left + box.width / 2;
|
|
117
|
-
const x = center + (targetBox.left + targetBox.width / 2 - center) / (box.width / bar
|
|
130
|
+
const x = center + (targetBox.left + targetBox.width / 2 - center) / (box.width / mainSize(bar, vertical)) - current.width / 2;
|
|
118
131
|
const y = box.top + box.height / 2 - current.height / 2;
|
|
119
132
|
const elapsed = (tapElapsed ?? 0) / 1000;
|
|
120
133
|
const duration = tapElapsed === undefined ? 450 : 800 - tapElapsed;
|
|
@@ -136,7 +149,7 @@ export const createTabBarReleaseAnimation = (effectElement, target, tap) => {
|
|
|
136
149
|
...tabBarTapFrames.slice(nextIndex).map(([time, position, width, height]) => ({
|
|
137
150
|
offset: (time - elapsed) / (0.8 - elapsed),
|
|
138
151
|
x: x + ((current.x - x) * (1 - position)) / Math.max(0.1, 1 - progress),
|
|
139
|
-
y,
|
|
152
|
+
y: y + ((current.y - y) * (1 - position)) / Math.max(0.1, 1 - progress),
|
|
140
153
|
sx: 1 + (width * (time >= 0.367 ? 1 + 0.75 * extraDistance : 1)) / current.width,
|
|
141
154
|
sy: 1 + (height * (time >= 0.367 ? 1 + 0.5 * extraDistance : 1)) / current.height,
|
|
142
155
|
})),
|
|
@@ -146,14 +159,14 @@ export const createTabBarReleaseAnimation = (effectElement, target, tap) => {
|
|
|
146
159
|
.addElement(native)
|
|
147
160
|
.duration(duration)
|
|
148
161
|
.easing('linear')
|
|
149
|
-
.keyframes(frames.map(({ offset, sx, sy }) => ({ offset, transform:
|
|
162
|
+
.keyframes(frames.map(({ offset, sx, sy }) => ({ offset, transform: stretchTransform(sx, sy, vertical) })));
|
|
150
163
|
const move = createAnimation()
|
|
151
164
|
.addElement(effectElement)
|
|
152
165
|
.duration(duration)
|
|
153
166
|
.easing('linear')
|
|
154
167
|
.keyframes(frames.map(({ offset, x, y }) => ({
|
|
155
168
|
offset,
|
|
156
|
-
transform:
|
|
169
|
+
transform: translate(x, y, vertical),
|
|
157
170
|
})));
|
|
158
171
|
const offset = 1 - 200 / duration;
|
|
159
172
|
const selectedBackground = 'var(--ios27-tab-selected-background, rgba(var(--ios-theme-button-color-selected-rgb, var(--ios26-button-color-selected-rgb, var(--ios27-button-color-selected-default-rgb))), 0.095))';
|
|
@@ -175,7 +188,7 @@ export const createTabBarReleaseAnimation = (effectElement, target, tap) => {
|
|
|
175
188
|
]);
|
|
176
189
|
const release = createAnimation().duration(duration).addAnimation([stretch, move, glass, selected]);
|
|
177
190
|
if (tapElapsed !== undefined) {
|
|
178
|
-
const width = bar
|
|
191
|
+
const width = mainSize(bar, vertical);
|
|
179
192
|
const expansion = box.width - width;
|
|
180
193
|
const peak = Math.max(8.65, expansion);
|
|
181
194
|
const platter = createAnimation()
|
|
@@ -236,7 +249,7 @@ export const createPreMoveAnimation = (effectElement, tabSelectedElement, curren
|
|
|
236
249
|
},
|
|
237
250
|
]);
|
|
238
251
|
};
|
|
239
|
-
export const createMoveAnimation = (effectElement, detail, tabSelectedElement, animationPosition) => {
|
|
252
|
+
export const createMoveAnimation = (effectElement, detail, tabSelectedElement, animationPosition, vertical = false) => {
|
|
240
253
|
return createAnimation()
|
|
241
254
|
.duration(500)
|
|
242
255
|
.addElement(effectElement)
|
|
@@ -247,7 +260,7 @@ export const createMoveAnimation = (effectElement, detail, tabSelectedElement, a
|
|
|
247
260
|
opacity: '1',
|
|
248
261
|
transform: 'none',
|
|
249
262
|
})
|
|
250
|
-
.fromTo('transform',
|
|
263
|
+
.fromTo('transform', translate(animationPosition.minPositionX, animationPosition.positionY, vertical), translate(animationPosition.maxPositionX, animationPosition.positionY, vertical))
|
|
251
264
|
.progressStep(getStep(detail.currentX, animationPosition));
|
|
252
265
|
};
|
|
253
266
|
export const getMoveAnimationKeyframe = (type, scales) => {
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { EffectScales, registeredEffect } from './interfaces';
|
|
2
|
-
export declare const registerEffect: (targetElement: HTMLElement, effectTagName: string, selectedClassName: string, scales: EffectScales) => registeredEffect | undefined;
|
|
2
|
+
export declare const registerEffect: (targetElement: HTMLElement, effectTagName: string, selectedClassName: string, scales: EffectScales, vertical?: boolean) => registeredEffect | undefined;
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sheets-of-glass/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sheets-of-glass/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAmBjF,eAAO,MAAM,cAAc,GACzB,eAAe,WAAW,EAC1B,eAAe,MAAM,EACrB,mBAAmB,MAAM,EACzB,QAAQ,YAAY,EACpB,kBAAgB,KACf,gBAAgB,GAAG,SA0XrB,CAAC"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { createGesture } from '@ionic/core';
|
|
2
2
|
import { changeSelectedElement, cloneElement, getStep } from '../utils';
|
|
3
3
|
import { isNativeUIShell } from '../native-integration';
|
|
4
|
-
import { createMoveAnimation, createPreMoveAnimation, createTabBarDragAnimation, createTabBarPressAnimation, createTabBarReleaseAnimation, getMoveAnimationKeyframe, getScaleAnimation, } from './animations';
|
|
4
|
+
import { animationRect, createMoveAnimation, createPreMoveAnimation, createTabBarDragAnimation, createTabBarPressAnimation, createTabBarReleaseAnimation, getMoveAnimationKeyframe, getScaleAnimation, } from './animations';
|
|
5
5
|
const GESTURE_NAME = 'ios27-enable-gesture';
|
|
6
6
|
const ANIMATED_NAME = 'ios27-animated';
|
|
7
|
-
export const registerEffect = (targetElement, effectTagName, selectedClassName, scales) => {
|
|
7
|
+
export const registerEffect = (targetElement, effectTagName, selectedClassName, scales, vertical = false) => {
|
|
8
8
|
if (!targetElement.classList.contains('ios')) {
|
|
9
9
|
return undefined;
|
|
10
10
|
}
|
|
@@ -24,6 +24,8 @@ export const registerEffect = (targetElement, effectTagName, selectedClassName,
|
|
|
24
24
|
let destroyed = false;
|
|
25
25
|
const originalTabBarScale = targetElement.style.getPropertyValue('--ios27-tab-bar-scale');
|
|
26
26
|
const effectElement = cloneElement(effectTagName, false);
|
|
27
|
+
if (vertical)
|
|
28
|
+
effectElement.classList.add('ios27-vertical-tab-effect');
|
|
27
29
|
const stopTabPress = () => {
|
|
28
30
|
if (!tabPressAnimation)
|
|
29
31
|
return;
|
|
@@ -98,17 +100,29 @@ export const registerEffect = (targetElement, effectTagName, selectedClassName,
|
|
|
98
100
|
document.addEventListener('pointercancel', onPointerCancel);
|
|
99
101
|
};
|
|
100
102
|
targetElement.addEventListener('pointerdown', onPointerDown);
|
|
103
|
+
const axisDetail = (detail) => vertical
|
|
104
|
+
? {
|
|
105
|
+
...detail,
|
|
106
|
+
currentX: detail.currentY,
|
|
107
|
+
currentY: detail.currentX,
|
|
108
|
+
startX: detail.startY,
|
|
109
|
+
startY: detail.startX,
|
|
110
|
+
velocityX: detail.velocityY,
|
|
111
|
+
velocityY: detail.velocityX,
|
|
112
|
+
}
|
|
113
|
+
: detail;
|
|
101
114
|
const createAnimationGesture = () => {
|
|
102
115
|
targetElement.classList.add(GESTURE_NAME);
|
|
103
116
|
gesture = createGesture({
|
|
104
117
|
el: targetElement,
|
|
105
118
|
threshold: 0,
|
|
119
|
+
direction: vertical ? 'y' : 'x',
|
|
106
120
|
gestureName: `${GESTURE_NAME}_${effectTagName}_${crypto.randomUUID()}`,
|
|
107
|
-
onStart: (event) => onStartGesture(event),
|
|
108
|
-
onMove: (event) => onMoveGesture(event),
|
|
121
|
+
onStart: (event) => onStartGesture(axisDetail(event)),
|
|
122
|
+
onMove: (event) => onMoveGesture(axisDetail(event)),
|
|
109
123
|
onEnd: (detail) => {
|
|
110
124
|
if (effectTagName === 'ion-tab-button' && tabDragging)
|
|
111
|
-
onMoveGesture(detail);
|
|
125
|
+
onMoveGesture(axisDetail(detail));
|
|
112
126
|
onEndGesture().then();
|
|
113
127
|
},
|
|
114
128
|
});
|
|
@@ -135,25 +149,29 @@ export const registerEffect = (targetElement, effectTagName, selectedClassName,
|
|
|
135
149
|
return false;
|
|
136
150
|
currentTouchedElement = detail.event.target.closest(effectTagName) || undefined;
|
|
137
151
|
const tabSelectedElement = targetElement.querySelector(`${effectTagName}.${selectedClassName}`);
|
|
138
|
-
if (currentTouchedElement === undefined ||
|
|
152
|
+
if (currentTouchedElement === undefined ||
|
|
153
|
+
currentTouchedElement.parentElement !== targetElement ||
|
|
154
|
+
currentTouchedElement.disabled ||
|
|
155
|
+
tabSelectedElement === null) {
|
|
156
|
+
currentTouchedElement = undefined;
|
|
139
157
|
return false;
|
|
140
158
|
}
|
|
141
159
|
selectedElementBeforeGesture = tabSelectedElement;
|
|
142
160
|
if (effectTagName === 'ion-tab-button') {
|
|
143
|
-
targetElement.style.setProperty('--ios27-tab-bar-scale', String(1 + 14.14 / targetElement.offsetWidth));
|
|
161
|
+
targetElement.style.setProperty('--ios27-tab-bar-scale', String(1 + 14.14 / (vertical ? targetElement.offsetHeight : targetElement.offsetWidth)));
|
|
144
162
|
}
|
|
145
163
|
animationPosition = {
|
|
146
|
-
minPositionX: targetElement
|
|
147
|
-
maxPositionX: targetElement
|
|
148
|
-
width: tabSelectedElement.clientWidth,
|
|
149
|
-
positionY: tabSelectedElement
|
|
164
|
+
minPositionX: animationRect(targetElement, vertical).left,
|
|
165
|
+
maxPositionX: animationRect(targetElement, vertical).right - (vertical ? tabSelectedElement.clientHeight : tabSelectedElement.clientWidth),
|
|
166
|
+
width: vertical ? tabSelectedElement.clientHeight : tabSelectedElement.clientWidth,
|
|
167
|
+
positionY: animationRect(tabSelectedElement, vertical).top,
|
|
150
168
|
};
|
|
151
169
|
targetElement.classList.add(ANIMATED_NAME);
|
|
152
170
|
changeSelectedElement(targetElement, currentTouchedElement, effectTagName, selectedClassName);
|
|
153
171
|
if (effectTagName === 'ion-tab-button') {
|
|
154
|
-
moveAnimation = createMoveAnimation(effectElement, detail, tabSelectedElement, animationPosition);
|
|
155
|
-
moveAnimation.progressStart(true, getStep(tabSelectedElement
|
|
156
|
-
tabPressAnimation = createTabBarPressAnimation(effectElement, tabSelectedElement, currentTouchedElement, targetElement);
|
|
172
|
+
moveAnimation = createMoveAnimation(effectElement, detail, tabSelectedElement, animationPosition, vertical);
|
|
173
|
+
moveAnimation.progressStart(true, getStep(animationRect(tabSelectedElement, vertical).left + animationRect(tabSelectedElement, vertical).width / 2, animationPosition));
|
|
174
|
+
tabPressAnimation = createTabBarPressAnimation(effectElement, tabSelectedElement, currentTouchedElement, targetElement, vertical);
|
|
157
175
|
tabPressStartedAt = performance.now();
|
|
158
176
|
void tabPressAnimation.play();
|
|
159
177
|
return true;
|
|
@@ -187,7 +205,7 @@ export const registerEffect = (targetElement, effectTagName, selectedClassName,
|
|
|
187
205
|
return;
|
|
188
206
|
tabDragging = true;
|
|
189
207
|
stopTabPress();
|
|
190
|
-
tabPressAnimation = createTabBarDragAnimation(effectElement, targetElement, detail.velocityX);
|
|
208
|
+
tabPressAnimation = createTabBarDragAnimation(effectElement, targetElement, detail.velocityX, vertical);
|
|
191
209
|
void tabPressAnimation.play();
|
|
192
210
|
}
|
|
193
211
|
else if (scaleAnimationPromise === undefined) {
|
|
@@ -211,10 +229,13 @@ export const registerEffect = (targetElement, effectTagName, selectedClassName,
|
|
|
211
229
|
}
|
|
212
230
|
}
|
|
213
231
|
const currentX = detail.currentX;
|
|
214
|
-
const previousY = targetElement
|
|
215
|
-
const nextEl = targetElement.getRootNode().elementFromPoint(currentX, previousY);
|
|
232
|
+
const previousY = animationRect(targetElement, vertical).top + animationRect(targetElement, vertical).height / 2;
|
|
233
|
+
const nextEl = targetElement.getRootNode().elementFromPoint(vertical ? previousY : currentX, vertical ? currentX : previousY);
|
|
216
234
|
const latestTouchedElement = nextEl?.closest(effectTagName) || undefined;
|
|
217
|
-
if (latestTouchedElement &&
|
|
235
|
+
if (latestTouchedElement &&
|
|
236
|
+
latestTouchedElement.parentElement === targetElement &&
|
|
237
|
+
!latestTouchedElement.disabled &&
|
|
238
|
+
currentTouchedElement !== latestTouchedElement) {
|
|
218
239
|
currentTouchedElement = latestTouchedElement;
|
|
219
240
|
changeSelectedElement(targetElement, currentTouchedElement, effectTagName, selectedClassName);
|
|
220
241
|
}
|
|
@@ -268,7 +289,7 @@ export const registerEffect = (targetElement, effectTagName, selectedClassName,
|
|
|
268
289
|
elapsed: tapElapsed,
|
|
269
290
|
distance: Math.abs(tabs.indexOf(currentTouchedElement) - tabs.indexOf(selectedElementBeforeGesture)),
|
|
270
291
|
}
|
|
271
|
-
: undefined);
|
|
292
|
+
: undefined, vertical);
|
|
272
293
|
currentTouchedElement.classList.remove('ion-activated');
|
|
273
294
|
releaseAnimation = releasing;
|
|
274
295
|
await releasing.play();
|
|
@@ -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-1
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
Keep your existing theme imports. Add this to your global Sass file:
|
|
@@ -62,9 +62,23 @@ const ionicConfig = {
|
|
|
62
62
|
|
|
63
63
|
Merge this option into your existing Ionic configuration before initialization: pass it to Angular's `provideIonicAngular()`, React's `setupIonicReact()`, or Vue's `IonicVue` plugin options. Keep your existing theme stylesheet imports. No iOS 27 theme stylesheet is required.
|
|
64
64
|
|
|
65
|
+
#### Use this package's iOS animation
|
|
66
|
+
|
|
67
|
+
If you already use the iOS 27 transition, keep this configuration. It includes the native adapter and excludes the horizontal back-button effect in vertical layouts; no additional wrapper is needed. Importing this JavaScript entry point does not load the theme stylesheets.
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import { iosTransitionAnimation } from '@rdlabo/ionic-theme-ios27';
|
|
71
|
+
|
|
72
|
+
const ionicConfig = {
|
|
73
|
+
navAnimation: iosTransitionAnimation,
|
|
74
|
+
};
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Apply this option to your existing iOS-mode configuration and keep your MD configuration.
|
|
78
|
+
|
|
65
79
|
#### Keep your custom animation
|
|
66
80
|
|
|
67
|
-
If your app
|
|
81
|
+
If your app uses another builder for `navAnimation`, wrap it:
|
|
68
82
|
|
|
69
83
|
```ts
|
|
70
84
|
import type { AnimationBuilder } from '@ionic/core';
|
|
@@ -80,7 +94,7 @@ The adapter returns the original `Animation`, preserving its effects, duration,
|
|
|
80
94
|
|
|
81
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.
|
|
82
96
|
|
|
83
|
-
|
|
97
|
+
`withNativeUIShellTransition()` is available in `1.2.0-1` and later.
|
|
84
98
|
|
|
85
99
|
### 4. Start the controls after the app root is mounted
|
|
86
100
|
|
package/docs/migration.md
CHANGED
|
@@ -8,8 +8,8 @@ title: Migration
|
|
|
8
8
|
|
|
9
9
|
Use `withNativeUIShellTransition()` to keep your existing Ionic navigation animation while coordinating Native UI Shell controls.
|
|
10
10
|
|
|
11
|
-
- If you already
|
|
12
|
-
- If you use Ionic's default animation without a `navAnimation` option, follow [Keep Ionic's default animation](./iphone-duo-with-original-theme.md#keep-
|
|
11
|
+
- If you already import `iosTransitionAnimation` from `@rdlabo/ionic-theme-ios27`, keep the [package animation setup](./iphone-duo-with-original-theme.md#use-this-package%27s-ios-animation); no configuration change is needed. It now uses the shared adapter internally; do not add another wrapper.
|
|
12
|
+
- If you use Ionic's default animation without a `navAnimation` option, follow [Keep Ionic's default animation](./iphone-duo-with-original-theme.md#keep-ionic%27s-default-animation). The example selects Ionic's standard iOS or MD builder from the transition mode.
|
|
13
13
|
- If you use a custom navigation animation with Native UI Shell or the standalone Vertical Control Area, wrap your existing builder when configuring Ionic:
|
|
14
14
|
|
|
15
15
|
```diff
|
|
@@ -25,7 +25,7 @@ Merge this option into your existing Ionic configuration before initialization.
|
|
|
25
25
|
|
|
26
26
|
Use the adapter only for navigation; leave modal and popover animations unchanged. Your builder must create a fresh `Animation` for each navigation because Ionic destroys it afterward. Keep lifecycle events for control registration and transitions without animation. If the custom builder animates a horizontal back button separately, exclude that effect while `.ios-theme-vertical-bars` is active.
|
|
27
27
|
|
|
28
|
-
See [Connect your navigation animation](./iphone-duo-with-original-theme.md#3
|
|
28
|
+
See [Connect your navigation animation](./iphone-duo-with-original-theme.md#3.-connect-your-navigation-animation) for the setup and supported scope.
|
|
29
29
|
|
|
30
30
|
## From the iOS 26 theme
|
|
31
31
|
|
package/docs/native-ui-shell.md
CHANGED
|
@@ -116,7 +116,7 @@ FAB support covers the standard circular glass appearance, text and resolved sta
|
|
|
116
116
|
|
|
117
117
|
Custom host animation or transition declarations on the FAB, list or button keep the group on the Web until removed. Button transforms support the standard identity and hidden-child scale(0), not custom scaling. For children inside a `display:none` list, browsers can report a computed transform of `none` even when a custom transform is declared. Such transforms are checked when layout becomes available; the whole FAB then returns to Web if needed. The plugin does not parse application stylesheets or temporarily open lists to predict hidden layout.
|
|
118
118
|
|
|
119
|
-
The built-in `iosTransitionAnimation` waits for native retirement before starting the Web animation. Interactive progress and completion/cancellation are queued while that retirement is in progress. Stationary shared tabs are retained. First render and transitions without an animation builder are covered by the startup runtime and Ionic lifecycle events. Default Ionic and custom navigation builders can use the same integration through `withNativeUIShellTransition()`, exported from both the package root and `/vertical-bars`. See [Connect your navigation animation](./iphone-duo-with-original-theme.md#3
|
|
119
|
+
The built-in `iosTransitionAnimation` waits for native retirement before starting the Web animation. Interactive progress and completion/cancellation are queued while that retirement is in progress. Stationary shared tabs are retained. First render and transitions without an animation builder are covered by the startup runtime and Ionic lifecycle events. Default Ionic and custom navigation builders can use the same integration through `withNativeUIShellTransition()`, exported from both the package root and `/vertical-bars`. See [Connect your navigation animation](./iphone-duo-with-original-theme.md#3.-connect-your-navigation-animation) for the setup.
|
|
120
120
|
|
|
121
121
|
Tab switches skip the Web/native crossfade so a retiring UIKit snapshot cannot linger over the next tab. Detection uses the router URL versus the still-selected tab on `ionViewWillLeave` (and vanilla `ionTabsWillChange` / `ionTabsDidChange` DOM events). Stack pushes and pops keep the normal 180ms handoff.
|
|
122
122
|
|
package/package.json
CHANGED