diff --git a/Assets/Plugins/Preactor/Runtime/DomStyle.cs b/Assets/Plugins/Preactor/Runtime/DomStyle.cs index 0dc12a2..4869343 100644 --- a/Assets/Plugins/Preactor/Runtime/DomStyle.cs +++ b/Assets/Plugins/Preactor/Runtime/DomStyle.cs @@ -2078,21 +2078,11 @@ static bool TryParseStyleInt(object value, out StyleInt styleInt) { static bool GetLength(object value, out Length lengthValue) { switch (value) { - // Attempt to parse the string for length values (e.g., "100px", "50%") - case string s when s.EndsWith("px"): { - if (float.TryParse(s.Substring(0, s.Length - 2), out var pixelValue)) { - lengthValue = new(pixelValue); - return true; - } - - break; - } case string s: { - if (s.EndsWith("%")) { - if (float.TryParse(s.Substring(0, s.Length - 1), out var percentValue)) { - lengthValue = new(percentValue, LengthUnit.Percent); - return true; - } + var str = s.EndsWith("px") ? s[..^2] : s.EndsWith("%") ? s[..^1] : s; + if (float.TryParse(str, out var percentValue)) { + lengthValue = new(percentValue, s.EndsWith("%") ? LengthUnit.Percent : LengthUnit.Pixel); + return true; } break; diff --git a/Preactor/core/@types/jsx.d.ts b/Preactor/core/@types/jsx.d.ts index a6d5320..ec906c0 100644 --- a/Preactor/core/@types/jsx.d.ts +++ b/Preactor/core/@types/jsx.d.ts @@ -59,6 +59,7 @@ type ScrollViewMode = CS.UnityEngine.UIElements.ScrollViewMode; type ScrollerVisibility = CS.UnityEngine.UIElements.ScrollerVisibility; type TouchScrollBehavior = CS.UnityEngine.UIElements.ScrollView.TouchScrollBehavior; type TooltipEvent = CS.UnityEngine.UIElements.TooltipEvent; +type TouchScreenKeyboardType = CS.UnityEngine; type TransitionCancelEvent = CS.UnityEngine.UIElements.TransitionCancelEvent; type TransitionEndEvent = CS.UnityEngine.UIElements.TransitionEndEvent; type TransitionRunEvent = CS.UnityEngine.UIElements.TransitionRunEvent; @@ -71,6 +72,7 @@ declare global { export namespace JSX { interface IntrinsicAttributes { id?: string; + key?: string | number; } interface BaseElement {} @@ -243,9 +245,7 @@ declare global { interface RadioButton extends BaseBoolField {} - interface RadioButtonGroup extends BindableElement { - label?: string; - } + interface RadioButtonGroup extends BaseField {} interface RepeatButton extends TextElement { delay?: number; @@ -309,6 +309,10 @@ declare global { 'is-password-field'?: boolean; 'mask-char'?: string; 'is-read-only'?: boolean; + 'select-all-on-focus'?: boolean; + 'select-all-on-mouse-up'?: boolean; + 'vertical-scroller-visibility'?: ScrollerVisibility; + keyboardType?: TouchScreenKeyboardType; } interface TextField extends TextInputBaseField { diff --git a/Preactor/core/dom/dom.ts b/Preactor/core/dom/dom.ts index b2a4264..80b2e96 100644 --- a/Preactor/core/dom/dom.ts +++ b/Preactor/core/dom/dom.ts @@ -5,6 +5,9 @@ export class DomWrapper { #dom: CS.Preactor.Dom; #domStyleWrapper: DomStyleWrapper; + #cachedChildren: DomWrapper[] | null = null; + #boundListeners = new WeakMap(); + public get _dom(): CS.Preactor.Dom { return this.#dom; } @@ -14,7 +17,15 @@ export class DomWrapper { } public get childNodes(): DomWrapper[] { - return (this.#dom.ChildNodes as unknown as CS.Preactor.Dom[]).map(x => new DomWrapper(x)); + if (!this.#cachedChildren) { + this.#cachedChildren = new Array(this.#dom.ChildNodes.Length) as DomWrapper[]; + + for (let i = 0; i < this.#dom.ChildNodes.Length; i++) { + this.#cachedChildren[i] = new DomWrapper(this.#dom.ChildNodes.get_Item(i)); + } + } + + return this.#cachedChildren; } public get firstChild(): DomWrapper | null { @@ -73,19 +84,27 @@ export class DomWrapper { } appendChild(child: DomWrapper) { - this.#dom.AppendChild(child.#dom); + if (child) { + this.#dom.AppendChild(child.#dom); + this.#cachedChildren = null; + } } removeChild(child: DomWrapper) { - this.#dom.RemoveChild(child.#dom); + if (child) { + this.#dom.RemoveChild(child.#dom); + this.#cachedChildren = null; + } } insertBefore(a: DomWrapper, b: DomWrapper) { this.#dom.InsertBefore(a?._dom, b?._dom); + this.#cachedChildren = null; } clearChildren() { this.#dom.ClearChildren(); + this.#cachedChildren = null; } focus() { @@ -93,17 +112,31 @@ export class DomWrapper { } contains(element: DomWrapper) { + if (!element) { + return false; + } + return this.#dom.Contains(element.#dom); } addEventListener(type: string, listener: (event: EventBase) => void, useCapture?: boolean) { - // @ts-ignore + let boundListener = this.#boundListeners.get(listener); + + if (!boundListener) { + boundListener = listener.bind(this); + this.#boundListeners.set(listener, boundListener); + } + this.#dom.AddEventListener(type, listener.bind(this), useCapture); } removeEventListener(type: string, listener: (event: EventBase) => void, useCapture?: boolean) { - // @ts-ignore - this.#dom.RemoveEventListener(type, listener.bind(this), useCapture); + const boundListener = this.#boundListeners.get(listener); + + if (boundListener) { + this.#dom.RemoveEventListener(type, listener.bind(this), useCapture); + this.#boundListeners.delete(listener); + } } setAttribute(name: string, value: any) { diff --git a/Preactor/core/package.json b/Preactor/core/package.json index 232ed15..e127201 100644 --- a/Preactor/core/package.json +++ b/Preactor/core/package.json @@ -6,7 +6,7 @@ "type": "git", "url": "git+https://github.com/rikarin/preactor.git" }, - "version": "0.0.12", + "version": "0.0.14", "main": "./dist/index.js", "types": "./typings.d.ts", "scripts": { diff --git a/Preactor/core/preact/diff/props.js b/Preactor/core/preact/diff/props.js index c46f0ee..9586d83 100644 --- a/Preactor/core/preact/diff/props.js +++ b/Preactor/core/preact/diff/props.js @@ -6,10 +6,8 @@ function setStyle(style, key, value) { style.setProperty(key, value == null ? '' : value); } else if (value == null) { style[key] = ''; - } else if (typeof value != 'number' || IS_NON_DIMENSIONAL.test(key)) { - style[key] = value; } else { - style[key] = value + 'px'; + style[key] = value; } } @@ -68,10 +66,7 @@ export function setProperty(dom, name, value, oldValue, namespace) { // Benchmark for comparison: https://esbench.com/bench/574c954bdb965b9a00965ac6 else if (name[0] === 'o' && name[1] === 'n') { useCapture = name !== (name = name.replace(/(PointerCapture)$|Capture$/i, '$1')); - - // Infer correct casing for DOM built-in events: - if (name.toLowerCase() in dom || name === 'onFocusOut' || name === 'onFocusIn') name = name.toLowerCase().slice(2); - else name = name.slice(2); + name = name.slice(2); if (!dom._listeners) dom._listeners = {}; dom._listeners[name + useCapture] = value; @@ -124,7 +119,8 @@ export function setProperty(dom, name, value, oldValue, namespace) { if (typeof value == 'function') { // never serialize functions as attribute values - } else if (value != null && (value !== false || name[4] === '-')) { + // } else if (value != null && (value !== false || name[4] === '-')) { + } else if (value != null && typeof value !== 'undefined') { dom.setAttribute(name, name == 'popover' && value == true ? '' : value); } else { dom.removeAttribute(name); diff --git a/Preactor/core/preact/style.d.ts b/Preactor/core/preact/style.d.ts index 1346187..a26247b 100644 --- a/Preactor/core/preact/style.d.ts +++ b/Preactor/core/preact/style.d.ts @@ -33,7 +33,7 @@ declare module 'preact/jsx' { backgroundImage?: Sprite | Texture | string; // StyleBackground backgroundSize?: BackgroundSize | string; // StyleBackgroundSize backgroundRepeat?: BackgroundRepeat | string; // StyleBackgroundRepeat - backgroundPosition?: string; // StyleBackgroundPosition + backgroundPosition?: string; // StyleBackgroundPosition backgroundPositionX?: BackgroundPosition | string; // StyleBackgroundPosition backgroundPositionY?: BackgroundPosition | string; // StyleBackgroundPosition diff --git a/Preactor/core/scripts/tailwind-config.cjs b/Preactor/core/scripts/tailwind-config.cjs index 8c8cdf3..86f0367 100644 --- a/Preactor/core/scripts/tailwind-config.cjs +++ b/Preactor/core/scripts/tailwind-config.cjs @@ -161,6 +161,8 @@ exports.corePlugins = [ 'padding', 'opacity', 'overflow', + 'display', + 'visibility', 'position', 'textOverflow', 'inset' diff --git a/Preactor/core/scripts/uss-transform-plugin.cjs b/Preactor/core/scripts/uss-transform-plugin.cjs index 527d7e1..9c42ee2 100644 --- a/Preactor/core/scripts/uss-transform-plugin.cjs +++ b/Preactor/core/scripts/uss-transform-plugin.cjs @@ -53,12 +53,12 @@ module.exports = () => { // Handle hexadecimal colors with alpha value to RGBA conversion root.walkDecls(decl => { - decl.value = decl.value.replace(/: #([A-Fa-f0-9]{8})/g, (match, hex) => { + decl.value = decl.value.replace(/#([A-Fa-f0-9]{8})/g, (match, hex) => { const r = parseInt(hex.slice(0, 2), 16); const g = parseInt(hex.slice(2, 4), 16); const b = parseInt(hex.slice(4, 6), 16); const a = parseInt(hex.slice(6, 8), 16) / 255; - return `: rgba(${r}, ${g}, ${b}, ${a})`; + return `rgba(${r}, ${g}, ${b}, ${a})`; }); });