Files
2025-12-22 10:53:15 +00:00

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>
`;
}
}