Files
rio/frontend/code/components/popup.ts
T
2024-07-27 20:02:37 +02:00

122 lines
3.9 KiB
TypeScript

import { applySwitcheroo } from '../designApplication';
import { ColorSet, ComponentId } from '../dataModels';
import { ComponentBase, ComponentState } from './componentBase';
import { getPositionerByName, PopupManager } from '../popupManager';
export type PopupState = ComponentState & {
_type_: 'Popup-builtin';
anchor?: ComponentId;
content?: ComponentId;
color?: ColorSet | 'none';
corner_radius?: number | [number, number, number, number];
position?:
| 'auto'
| 'left'
| 'top'
| 'right'
| 'bottom'
| 'center'
| 'fullscreen';
alignment?: number;
gap?: number;
is_open?: boolean;
};
export class PopupComponent extends ComponentBase {
state: Required<PopupState>;
private anchorContainer: HTMLElement;
private contentContainer: HTMLElement;
private popupManager: PopupManager;
createElement(): HTMLElement {
let element = document.createElement('div');
element.classList.add('rio-popup');
this.anchorContainer = document.createElement('div');
this.anchorContainer.classList.add('rio-popup-anchor');
element.appendChild(this.anchorContainer);
this.contentContainer = document.createElement('div');
this.contentContainer.classList.add(
'rio-popup-animation-scale',
'rio-popup-content'
);
element.appendChild(this.contentContainer);
// Initialize the popup manager. Many of these values will be
// overwritten by the updateElement method.
this.popupManager = new PopupManager(
this.anchorContainer,
this.contentContainer,
getPositionerByName('center', 0, 0.5)
);
return element;
}
updateElement(
deltaState: PopupState,
latentComponents: Set<ComponentBase>
): void {
super.updateElement(deltaState, latentComponents);
// Update the children
this.replaceOnlyChild(
latentComponents,
deltaState.anchor,
this.anchorContainer
);
this.replaceOnlyChild(
latentComponents,
deltaState.content,
this.contentContainer
);
// Update the popup manager
if (
deltaState.position !== undefined ||
deltaState.alignment !== undefined ||
deltaState.gap !== undefined
) {
this.popupManager.positioner = getPositionerByName(
deltaState.position ?? this.state.position,
deltaState.gap ?? this.state.gap,
deltaState.alignment ?? this.state.alignment
);
}
// Open / Close
if (deltaState.is_open !== undefined) {
this.popupManager.isOpen = deltaState.is_open;
}
// Colorize
if (deltaState.color === 'none') {
applySwitcheroo(this.contentContainer, 'keep');
this.contentContainer.style.removeProperty('background-color');
this.contentContainer.style.removeProperty('box-shadow');
} else if (deltaState.color !== undefined) {
applySwitcheroo(this.contentContainer, deltaState.color);
this.contentContainer.style.backgroundColor = `var(--rio-local-bg)`;
this.contentContainer.style.boxShadow = `0 0 1rem var(--rio-global-shadow-color)`;
}
// Update the corner radius
if (deltaState.corner_radius !== undefined) {
if (typeof deltaState.corner_radius === 'number') {
this.contentContainer.style.borderRadius = `${deltaState.corner_radius}rem`;
} else {
this.contentContainer.style.borderRadius = `${deltaState.corner_radius[0]}rem ${deltaState.corner_radius[1]}rem ${deltaState.corner_radius[2]}rem ${deltaState.corner_radius[3]}rem`;
}
}
}
onDestruction(): void {
super.onDestruction();
this.popupManager.destroy();
}
}