WIP: AspectRatioContainer

This commit is contained in:
Jakob Pinterits
2024-07-04 00:33:12 +02:00
parent ad5b451ce1
commit 704f354c7b
5 changed files with 139 additions and 4 deletions

View File

@@ -1,3 +1,4 @@
import { AspectRatioContainerComponent } from './components/aspectRatioContainer';
import { BuildFailedComponent } from './components/buildFailed';
import { ButtonComponent, IconButtonComponent } from './components/buttons';
import { CalendarComponent } from './components/calendar';
@@ -10,8 +11,10 @@ import { ColorPickerComponent } from './components/colorPicker';
import { ColumnComponent, RowComponent } from './components/linearContainers';
import { ComponentBase, ComponentState } from './components/componentBase';
import { ComponentId } from './dataModels';
import { ComponentPickerComponent } from './components/componentPicker';
import { ComponentTreeComponent } from './components/componentTree';
import { CustomListItemComponent } from './components/customListItem';
import { devToolsConnector } from './app';
import { DevToolsConnectorComponent } from './components/devToolsConnector';
import { DrawerComponent } from './components/drawer';
import { DropdownComponent } from './components/dropdown';
@@ -19,6 +22,7 @@ import { FlowComponent as FlowContainerComponent } from './components/flowContai
import { FundamentalRootComponent } from './components/fundamentalRootComponent';
import { GridComponent } from './components/grid';
import { HeadingListItemComponent } from './components/headingListItem';
import { HighLevelComponent as HighLevelComponent } from './components/highLevelComponent';
import { HtmlComponent } from './components/html';
import { IconComponent } from './components/icon';
import { ImageComponent } from './components/image';
@@ -33,7 +37,6 @@ import { MultiLineTextInputComponent } from './components/multiLineTextInput';
import { NodeInputComponent } from './components/nodeInput';
import { NodeOutputComponent } from './components/nodeOutput';
import { OverlayComponent } from './components/overlay';
import { HighLevelComponent as HighLevelComponent } from './components/highLevelComponent';
import { PlotComponent } from './components/plot';
import { PopupComponent } from './components/popup';
import { ProgressBarComponent } from './components/progressBar';
@@ -41,6 +44,7 @@ import { ProgressCircleComponent } from './components/progressCircle';
import { RectangleComponent } from './components/rectangle';
import { reprElement, scrollToUrlFragment } from './utils';
import { RevealerComponent } from './components/revealer';
import { ScrollContainerComponent } from './components/scrollContainer';
import { ScrollTargetComponent } from './components/scrollTarget';
import { SeparatorComponent } from './components/separator';
import { SeparatorListItemComponent } from './components/separatorListItem';
@@ -55,11 +59,9 @@ import { TextComponent } from './components/text';
import { TextInputComponent } from './components/textInput';
import { ThemeContextSwitcherComponent } from './components/themeContextSwitcher';
import { TooltipComponent } from './components/tooltip';
import { devToolsConnector } from './app';
import { ComponentPickerComponent } from './components/componentPicker';
import { ScrollContainerComponent } from './components/scrollContainer';
const COMPONENT_CLASSES = {
'AspectRatioContainer-builtin': AspectRatioContainerComponent,
'BuildFailed-builtin': BuildFailedComponent,
'Button-builtin': ButtonComponent,
'Calendar-builtin': CalendarComponent,

View File

@@ -0,0 +1,103 @@
import { ComponentBase, ComponentState } from './componentBase';
import { ComponentId } from '../dataModels';
import { getNaturalSizeInPixels } from '../utils';
export type AspectRatioContainerState = ComponentState & {
_type_: 'AspectRatioContainer-builtin';
content?: ComponentId;
aspect_ratio: number;
};
export class AspectRatioContainerComponent extends ComponentBase {
state: Required<AspectRatioContainerState>;
private innerElement: HTMLElement;
private childContainer: HTMLElement;
private parentResizeObserver: ResizeObserver;
private childResizeObserver: ResizeObserver;
createElement(): HTMLElement {
let element = document.createElement('div');
element.classList.add('rio-aspect-ratio-container');
// Add a second element to apply the child's size to
this.innerElement = document.createElement('div');
element.appendChild(this.innerElement);
// Add a child container
this.childContainer = document.createElement('div');
this.childContainer.classList.add(
'rio-aspect-ratio-container-child-container'
);
this.innerElement.appendChild(this.childContainer);
// Listen for changes
this.parentResizeObserver = new ResizeObserver(
this.onParentResize.bind(this)
);
this.parentResizeObserver.observe(element);
this.childResizeObserver = new ResizeObserver(
this.onParentResize.bind(this)
);
this.childResizeObserver.observe(this.childContainer);
return element;
}
onDestruction(): void {
this.parentResizeObserver.disconnect();
this.childResizeObserver.disconnect();
}
updateElement(
deltaState: AspectRatioContainerState,
latentComponents: Set<ComponentBase>
): void {
super.updateElement(deltaState, latentComponents);
if (deltaState.content !== undefined) {
this.replaceOnlyChild(
latentComponents,
deltaState.content,
this.childContainer
);
}
if (deltaState.aspect_ratio !== undefined) {
this.childContainer.style.aspectRatio =
deltaState.aspect_ratio.toString();
}
}
onParentResize(): void {
// Get the parent's and child's dimensions
let parentRect = this.element.getBoundingClientRect();
let parentAspectRatio = parentRect.width / parentRect.height;
// Update the child's dimensions
if (parentAspectRatio > this.state.aspect_ratio) {
this.childContainer.style.width = 'auto';
this.childContainer.style.height = '100%';
this.childContainer.style.left = '50%';
this.childContainer.style.top = '0';
this.childContainer.style.transform = 'translateX(-50%)';
} else {
this.childContainer.style.width = '100%';
this.childContainer.style.height = 'auto';
this.childContainer.style.left = '0';
this.childContainer.style.top = '50%';
this.childContainer.style.transform = 'translateY(-50%)';
}
}
onChildResize(): void {
let childElement = this.innerElement.firstElementChild as HTMLElement;
let childNaturalSize = getNaturalSizeInPixels(childElement);
this.innerElement.style.minWidth = `${childNaturalSize[0]}px`;
this.innerElement.style.minHeight = `${childNaturalSize[1]}px`;
}
}

View File

@@ -3628,3 +3628,13 @@ html.picking-component * {
.rio-checkbox.is-on .rio-checkbox-check {
transform: scale(1);
}
// Aspect Ratio Container
.rio-aspect-ratio-container {
@include single-container();
& > div > .rio-aspect-ratio-container-child-container {
position: absolute;
@include single-container();
}
}

View File

@@ -1,3 +1,4 @@
from .aspect_ratio_container import *
from .auto_form import *
from .banner import *
from .button import *

View File

@@ -0,0 +1,19 @@
from __future__ import annotations
import rio
from .fundamental_component import FundamentalComponent
__all__ = [
"AspectRatioContainer",
]
class AspectRatioContainer(FundamentalComponent):
# TODO
content: rio.Component
aspect_ratio: float
AspectRatioContainer._unique_id = "AspectRatioContainer-builtin"