fix switcher initially not adding its child

This commit is contained in:
Aran-Fey
2024-07-06 19:32:04 +02:00
parent ed76baf5a1
commit 7ff791647e
6 changed files with 51 additions and 26 deletions

View File

@@ -32,7 +32,7 @@ export class DropdownComponent extends ComponentBase {
element.classList.add('rio-dropdown');
// The dropdown is styled as an input box. Use the InputBox abstraction
this.inputBox = new InputBox({ labelIsAlwaysSmall: true });
this.inputBox = new InputBox(this.id, { labelIsAlwaysSmall: true });
element.appendChild(this.inputBox.outerElement);
// In order to ensure the dropdown can actually fit its options, add a

View File

@@ -23,6 +23,7 @@ export class ImageComponent extends ComponentBase {
createElement(): HTMLElement {
let element = document.createElement('div');
element.classList.add('rio-image');
element.role = 'img';
this.imageElement = document.createElement('img');
element.appendChild(this.imageElement);

View File

@@ -17,7 +17,7 @@ export class MultiLineTextInputComponent extends ComponentBase {
createElement(): HTMLElement {
let textarea = document.createElement('textarea');
this.inputBox = new InputBox({ inputElement: textarea });
this.inputBox = new InputBox(this.id, { inputElement: textarea });
let element = this.inputBox.outerElement;
element.classList.add('rio-multi-line-text-input');

View File

@@ -15,6 +15,7 @@ export class SwitcherComponent extends ComponentBase {
private activeChildContainer: HTMLElement | null = null;
private resizerElement: HTMLElement | null = null;
private idOfCurrentAnimation: number = 0;
private isInitialized: boolean = false;
createElement(): HTMLElement {
let element = document.createElement('div');
@@ -38,16 +39,30 @@ export class SwitcherComponent extends ComponentBase {
}
// Update the child
if (
deltaState.content !== undefined &&
deltaState.content !== this.state.content
) {
this.replaceContent(
deltaState.content,
latentComponents,
deltaState.transition_time ?? this.state.transition_time
);
if (deltaState.content !== undefined) {
if (!this.isInitialized) {
// When it's the first time, don't animate
this.activeChildContainer = document.createElement('div');
this.activeChildContainer.classList.add(
'rio-switcher-active-child'
);
this.element.appendChild(this.activeChildContainer);
this.replaceOnlyChild(
latentComponents,
deltaState.content,
this.activeChildContainer
);
} else if (deltaState.content !== this.state.content) {
this.replaceContent(
deltaState.content,
latentComponents,
deltaState.transition_time ?? this.state.transition_time
);
}
}
this.isInitialized = true;
}
private async replaceContent(
@@ -104,8 +119,6 @@ export class SwitcherComponent extends ComponentBase {
if (content !== null) {
// Add the child into a helper container
newChildContainer = document.createElement('div');
newChildContainer.classList.add('rio-switcher-active-child');
this.replaceOnlyChild(latentComponents, content, newChildContainer);
// Make it `absolute` so it isn't influenced by the Switcher's
@@ -128,6 +141,10 @@ export class SwitcherComponent extends ComponentBase {
newChildContainer.style.removeProperty('position');
newChildContainer.style.removeProperty('width');
commitCss(newChildContainer);
newChildContainer.classList.add('rio-switcher-active-child');
}
this.activeChildContainer = newChildContainer;
@@ -157,8 +174,8 @@ export class SwitcherComponent extends ComponentBase {
resizerElement.style.minHeight = `${newHeight}px`;
// Step 4: Clean up
let idOfCurrentAnimation = Math.random();
this.idOfCurrentAnimation = idOfCurrentAnimation;
let idOfCurrentAnimation = this.idOfCurrentAnimation;
this.idOfCurrentAnimation++;
// Clean up once the animation is finished
setTimeout(() => {

View File

@@ -21,7 +21,7 @@ export class TextInputComponent extends ComponentBase {
private onChangeLimiter: Debouncer;
createElement(): HTMLElement {
this.inputBox = new InputBox();
this.inputBox = new InputBox(this.id);
let element = this.inputBox.outerElement;

View File

@@ -13,20 +13,23 @@ export class InputBox {
private suffixTextElement: HTMLElement;
private labelWidthReserverElement: HTMLElement; // Ensures enough width for the label
private labelElement: HTMLElement;
private labelElement: HTMLLabelElement;
// NOTE: The input element can also be a textarea, but for some reason the
// typing gets really wonky if this is a union. I don't like it, but I think
// lying about the type is our best option.
private _inputElement: HTMLInputElement;
constructor({
inputElement,
labelIsAlwaysSmall,
}: {
inputElement?: HTMLInputElement | HTMLTextAreaElement;
labelIsAlwaysSmall?: boolean;
} = {}) {
constructor(
id: string | number,
{
inputElement,
labelIsAlwaysSmall,
}: {
inputElement?: HTMLInputElement | HTMLTextAreaElement;
labelIsAlwaysSmall?: boolean;
} = {}
) {
this.outerElement = document.createElement('div');
this.outerElement.classList.add('rio-input-box');
@@ -35,7 +38,7 @@ export class InputBox {
<div class="rio-input-box-hint-text rio-input-box-prefix-text"></div>
<div class="rio-input-box-column">
<div class="rio-input-box-label-width-reserver"></div>
<div class="rio-input-box-label"></div>
<label class="rio-input-box-label"></label>
<input type="text">
</div>
<div class="rio-input-box-suffix-element">
@@ -62,7 +65,7 @@ export class InputBox {
) as HTMLElement;
this.labelElement = this.outerElement.querySelector(
'.rio-input-box-label'
) as HTMLElement;
) as HTMLLabelElement;
this._inputElement = this.outerElement.querySelector(
'input'
) as HTMLInputElement;
@@ -80,6 +83,10 @@ export class InputBox {
this.outerElement.classList.add('label-is-always-small');
}
// Associate the <label> with the <input>
this._inputElement.id = `rio-input-${id}`;
this.labelElement.htmlFor = this._inputElement.id;
// Detect clicks on any part of the component and focus the input
//
// The `mousedown` are needed to prevent any potential drag events from