157 lines
3.4 KiB
TypeScript
157 lines
3.4 KiB
TypeScript
|
|
import {
|
||
|
|
DeesElement,
|
||
|
|
css,
|
||
|
|
cssManager,
|
||
|
|
customElement,
|
||
|
|
html,
|
||
|
|
property,
|
||
|
|
type TemplateResult,
|
||
|
|
} from '@design.estate/dees-element';
|
||
|
|
|
||
|
|
import { mobileComponentStyles } from '../../00componentstyles.js';
|
||
|
|
|
||
|
|
declare global {
|
||
|
|
interface HTMLElementTagNameMap {
|
||
|
|
'dees-mobile-view': DeesMobileView;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* A view container component that works with dees-mobile-viewstack.
|
||
|
|
* Each view has a unique ID and is shown/hidden based on the viewstack's current state.
|
||
|
|
*/
|
||
|
|
@customElement('dees-mobile-view')
|
||
|
|
export class DeesMobileView extends DeesElement {
|
||
|
|
@property({ type: String, attribute: 'view-id' })
|
||
|
|
accessor viewId: string = '';
|
||
|
|
|
||
|
|
@property({ type: Boolean, reflect: true })
|
||
|
|
accessor active: boolean = false;
|
||
|
|
|
||
|
|
@property({ type: String })
|
||
|
|
accessor animationState: 'none' | 'entering' | 'leaving' = 'none';
|
||
|
|
|
||
|
|
@property({ type: String })
|
||
|
|
accessor animationDirection: 'forward' | 'back' = 'forward';
|
||
|
|
|
||
|
|
public static styles = [
|
||
|
|
cssManager.defaultStyles,
|
||
|
|
mobileComponentStyles,
|
||
|
|
css`
|
||
|
|
:host {
|
||
|
|
display: none;
|
||
|
|
position: absolute;
|
||
|
|
top: 0;
|
||
|
|
left: 0;
|
||
|
|
right: 0;
|
||
|
|
bottom: 0;
|
||
|
|
overflow: hidden;
|
||
|
|
background: ${cssManager.bdTheme('#ffffff', '#09090b')};
|
||
|
|
}
|
||
|
|
|
||
|
|
:host([active]) {
|
||
|
|
display: block;
|
||
|
|
}
|
||
|
|
|
||
|
|
.view-content {
|
||
|
|
width: 100%;
|
||
|
|
height: 100%;
|
||
|
|
overflow-y: auto;
|
||
|
|
-webkit-overflow-scrolling: touch;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Forward animations (new view slides in from right) */
|
||
|
|
:host(.entering-forward) {
|
||
|
|
display: block;
|
||
|
|
animation: slideInFromRight 300ms ease-out forwards;
|
||
|
|
}
|
||
|
|
|
||
|
|
:host(.leaving-forward) {
|
||
|
|
display: block;
|
||
|
|
animation: slideOutToLeft 300ms ease-out forwards;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Back animations (returning to previous view) */
|
||
|
|
:host(.entering-back) {
|
||
|
|
display: block;
|
||
|
|
animation: slideInFromLeft 300ms ease-out forwards;
|
||
|
|
}
|
||
|
|
|
||
|
|
:host(.leaving-back) {
|
||
|
|
display: block;
|
||
|
|
animation: slideOutToRight 300ms ease-out forwards;
|
||
|
|
}
|
||
|
|
|
||
|
|
@keyframes slideInFromRight {
|
||
|
|
from {
|
||
|
|
transform: translateX(100%);
|
||
|
|
}
|
||
|
|
to {
|
||
|
|
transform: translateX(0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@keyframes slideOutToLeft {
|
||
|
|
from {
|
||
|
|
transform: translateX(0);
|
||
|
|
opacity: 1;
|
||
|
|
}
|
||
|
|
to {
|
||
|
|
transform: translateX(-30%);
|
||
|
|
opacity: 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@keyframes slideInFromLeft {
|
||
|
|
from {
|
||
|
|
transform: translateX(-30%);
|
||
|
|
opacity: 0;
|
||
|
|
}
|
||
|
|
to {
|
||
|
|
transform: translateX(0);
|
||
|
|
opacity: 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@keyframes slideOutToRight {
|
||
|
|
from {
|
||
|
|
transform: translateX(0);
|
||
|
|
}
|
||
|
|
to {
|
||
|
|
transform: translateX(100%);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
`,
|
||
|
|
];
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Start an animation on this view
|
||
|
|
*/
|
||
|
|
public startAnimation(type: 'entering' | 'leaving', direction: 'forward' | 'back'): void {
|
||
|
|
this.animationState = type;
|
||
|
|
this.animationDirection = direction;
|
||
|
|
this.classList.add(`${type}-${direction}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* End the current animation
|
||
|
|
*/
|
||
|
|
public endAnimation(): void {
|
||
|
|
this.classList.remove(
|
||
|
|
'entering-forward',
|
||
|
|
'leaving-forward',
|
||
|
|
'entering-back',
|
||
|
|
'leaving-back'
|
||
|
|
);
|
||
|
|
this.animationState = 'none';
|
||
|
|
}
|
||
|
|
|
||
|
|
public render(): TemplateResult {
|
||
|
|
return html`
|
||
|
|
<div class="view-content">
|
||
|
|
<slot></slot>
|
||
|
|
</div>
|
||
|
|
`;
|
||
|
|
}
|
||
|
|
}
|