Files
ueblueprint/js/template/pin/IInputPinTemplate.js
BarsDev 6ba2705386 Large refactoring and new nodes
* Fix node reference when changing elements

* Fix ScriptVariables parsing

* Fix invariant text and niagara types

* Niagara convert nodes

* Move node tests to own files

* More Niagara tests

* Niagara float and smaller fixes

* More Decoding

* More decoding

* WIP

* Float is real

* WIP

* More types and colors

* Test case and small polish

* WIP

* WIP

* Fix niagara script variables merging

* Fix Niagara variables

* Fixing mirrored ExportPath

* Fix Export paths name adjustments

* Simplify arc calculation

* Simplify a bit arc calculation

* source / destionation => origin / target

* Minor refactoring

* Fix switched link position

* Rename some properties for uniformity

* Fix input escape

* Simplify test

* About window

* Dialog backdrop style

* About dialog touches

* Remove dependency and minot improvement

* Light mode

* Fix link location and css small improvement

* Link direction and minor fixes

* Some minor fixes and refactoring

* Refactoring WIP

* Shorting repetitive bits

* More tests

* Simplify linking tests
2025-02-07 00:36:03 +02:00

138 lines
5.2 KiB
JavaScript
Executable File

import { html } from "lit"
import Configuration from "../../Configuration.js"
import Utility from "../../Utility.js"
import PinTemplate from "./PinTemplate.js"
/**
* @template {IEntity} T
* @extends PinTemplate<T>
*/
export default class IInputPinTemplate extends PinTemplate {
static singleLineInput = false
static selectOnFocus = true
static saveEachInputChange = false // Otherwise save only on focus out
/** @type {HTMLElement} */
#inputWrapper
get inputWrapper() {
return this.#inputWrapper
}
/** @type {HTMLElement[]} */
#inputContentElements
/** @param {String} value */
static stringFromInputToUE(value) {
return value
.replace(/(?=\n\s*)\n$/, "") // Remove trailing double newline
}
/** @param {String} value */
static stringFromUEToInput(value) {
return value
.replaceAll(/(?:\r|(?<=(?:^|[^\\])(?:\\\\)*)\\r)(?=\n)/g, "") // Remove \r leftover from \r\n
.replace(/(?<=\n\s*)$/, "\n") // Put back trailing double newline
}
#setInput = () => this.setInputs(this.getInputs(), true)
/** @param {Event} event */
#checkWrapHandler = event => this.#updateWrapClass(/** @type {HTMLElement} */(event.target))
/** @param {HTMLElement} inputElement*/
#updateWrapClass(inputElement) {
if (this.element.querySelector(".ueb-pin-name")?.getBoundingClientRect().width < 20) {
// Do not wrap if the pin name is just a letter (like A, B, V, ...)
return
}
const width = this.blueprint.scaleCorrect(this.#inputWrapper.getBoundingClientRect().width) + this.nameWidth
const inputWrapped = this.element.classList.contains("ueb-pin-input-wrap")
if (!inputWrapped && width > Configuration.pinInputWrapWidth) {
this.element.classList.add("ueb-pin-input-wrap")
} else if (inputWrapped && width <= Configuration.pinInputWrapWidth) {
this.element.classList.remove("ueb-pin-input-wrap")
}
}
/** @param {PropertyValues} changedProperties */
firstUpdated(changedProperties) {
super.firstUpdated(changedProperties)
const Self = /** @type {typeof IInputPinTemplate} */(this.constructor)
if (Self.canWrapInput && this.isInputRendered()) {
this.element.addEventListener("input", this.#checkWrapHandler)
this.nameWidth = this.blueprint.scaleCorrect(
this.element.querySelector(".ueb-pin-name")?.getBoundingClientRect().width ?? 0
)
}
this.#inputWrapper = this.element.querySelector(".ueb-pin-input-wrapper")
this.#inputContentElements = /** @type {HTMLElement[]} */([...this.element.querySelectorAll("ueb-input")])
}
setup() {
super.setup()
const Self = /** @type {typeof IInputPinTemplate} */(this.constructor)
if (Self.saveEachInputChange) {
this.element.addEventListener("input", this.#setInput)
} else {
this.element.addEventListener("focusout", this.#setInput)
}
if (Self.canWrapInput && this.isInputRendered()) {
this.element.addEventListener("input", this.#checkWrapHandler)
this.element.nodeElement.addEventListener(Configuration.nodeUpdateEventName, this.#checkWrapHandler)
}
}
cleanup() {
super.cleanup()
this.element.nodeElement.removeEventListener(Configuration.nodeUpdateEventName, this.#checkWrapHandler)
this.element.removeEventListener("input", this.#checkWrapHandler)
this.element.removeEventListener("input", this.#setInput)
this.element.removeEventListener("focusout", this.#setInput)
}
getInput() {
return this.getInputs().reduce((acc, cur) => acc + cur, "")
}
getInputs() {
return this.#inputContentElements.map(element =>
// Faster than innerText which causes reflow
Utility.clearHTMLWhitespace(element.innerHTML)
)
}
/** @param {String[]} values */
setInputs(values = [], updateDefaultValue = true) {
this.#inputContentElements.forEach(/** @type {typeof IInputPinTemplate } */(this.constructor).singleLineInput
? (elem, i) => elem.innerText = values[i]
: (elem, i) => elem.innerText = values[i].replaceAll("\n", "")
)
if (updateDefaultValue) {
this.setDefaultValue(values.map(v => IInputPinTemplate.stringFromInputToUE(v)), values)
}
this.element.requestUpdate()
this.element.updateComplete.then(() => this.element.nodeElement.acknowledgeUpdate())
}
setDefaultValue(values = [], rawValues = values) {
this.element.setDefaultValue(
// @ts-expect-error
values.join("")
)
}
renderInput() {
const Self = /** @type {typeof IInputPinTemplate} */(this.constructor)
const singleLine = Self.singleLineInput
const selectOnFocus = Self.selectOnFocus
return html`
<div class="ueb-pin-input-wrapper ueb-pin-input">
<ueb-input .singleLine="${singleLine}" .selectOnFocus="${selectOnFocus}"
.innerText="${IInputPinTemplate.stringFromUEToInput(this.element.getDefaultValue()?.toString() ?? "")}">
</ueb-input>
</div>
`
}
}