Release Healer Man 0.1.43

This commit is contained in:
phenom committed 2026-09-14 13:20:20 -04:00
1 parent c7e8163790
commit ccc01396cd
86 files changed
+2951 -198

No files matched your search

+12 -5
View File
@@ -1,6 +1,8 @@
import { useLayoutEffect, useRef, useState, type CSSProperties, type ReactNode } from "react";
import { createPortal } from "react-dom";
import { HUD_ELEMENTS, type HudElementId, type HudElementLayout } from "../game/uiLayout";
import { HUD_ELEMENTS, resolveHudScreen, type HudElementId, type HudElementLayout } from "../game/uiLayout";
import { currentDisplayLayout } from "../platform/displayLayout";
import { useHudSurface } from "./HudSurface";
import { currentUiDevice, useUiLayoutStore } from "../game/uiLayoutStore";
import { useGameStore } from "../game/store";
import "./uiLayout.css";
@@ -22,23 +24,26 @@ export function EditableHudElement({ id, children, intrinsicWidth, bottomAnchor,
onChange?: (update: Partial<HudElementLayout>) => void;
}) {
const overlay = useGameStore((state) => state.overlay);
const surface = useHudSurface();
const dualScreen = currentDisplayLayout() !== "single";
const editing = editingOverride ?? overlay === "ui-layout";
const state = useUiLayoutStore();
const layout = state.draft ?? state.preferences.current[currentUiDevice()];
const element = elementLayout ?? layout.elements[id];
const screen = resolveHudScreen(id, layout, dualScreen);
const [origin, setOrigin] = useState<{ x: number; y: number; width: number } | null>(null);
const ref = useRef<HTMLDivElement>(null);
const [host, setHost] = useState<Element | null>(null);
const drag = useRef<{ pointerId: number; dx: number; dy: number } | null>(null);
const [bounds, setBounds] = useState({ width: 0, height: 0, panelWidth: 0, panelHeight: 0 });
const positioned = editing || element.position !== null;
const positioned = editing || element.position !== null || (dualScreen && surface.surface === "bottom" && !["player", "actions", "cast", "experience", "dps"].includes(id));
const fallback = FALLBACKS[id] ?? [.5, .35, 250];
const position = element.position ?? (bottomAnchor !== undefined
? { x: .5, y: 1 - bottomAnchor / Math.max(1, bounds.height) }
: origin ?? { x: fallback[0], y: fallback[1] });
const width = intrinsicWidth ?? element.width ?? origin?.width ?? fallback[2];
useLayoutEffect(() => { if (ref.current) setHost(ref.current.closest(hostSelector)); }, [hostSelector]);
useLayoutEffect(() => { if (ref.current) setHost(ref.current.closest(hostSelector)); }, [hostSelector, screen]);
useLayoutEffect(() => {
if (positioned || !ref.current) return;
@@ -66,18 +71,19 @@ export function EditableHudElement({ id, children, intrinsicWidth, bottomAnchor,
const observer = new ResizeObserver(measure);
observer.observe(node); observer.observe(host); measure();
return () => observer.disconnect();
}, [positioned, host, hostSelector]);
}, [positioned, host, hostSelector, screen]);
const updatePosition = (x: number, y: number) => {
const update = { position: { x: Math.max(0, Math.min(1, x)), y: Math.max(0, Math.min(1, y)) }, width };
if (onChange) onChange(update);
else if (surface.onChange) surface.onChange(id, update);
else state.updateDraft((draft) => ({ ...draft, elements: { ...draft.elements, [id]: { ...draft.elements[id], ...update } } }));
};
const left = Math.max(6, Math.min(Math.max(6, bounds.width - bounds.panelWidth - 6), position.x * bounds.width - bounds.panelWidth / 2));
const top = Math.max(6, Math.min(Math.max(6, bounds.height - bounds.panelHeight - 6), position.y * bounds.height - bounds.panelHeight / 2));
const style = positioned ? { left, top, width: `min(${width}px, calc(100% - 12px))` } as CSSProperties : undefined;
const content = <div ref={ref} data-hud-element={id} style={style}
className={`editable-hud ${positioned ? "editable-hud--positioned" : "editable-hud--default"} ${editing ? "editable-hud--editing" : ""} ${!element.visible ? editing ? "editable-hud--ghost" : "editable-hud--hidden" : ""}`}
className={`editable-hud ${positioned ? "editable-hud--positioned" : "editable-hud--default"} ${editing ? "editable-hud--editing" : ""} ${state.selectedElement === id ? "editable-hud--selected" : ""} ${!element.visible ? editing ? "editable-hud--ghost" : "editable-hud--hidden" : ""}`}
onClickCapture={(event) => { if (editing && !id.startsWith("bar-")) { event.preventDefault(); event.stopPropagation(); useUiLayoutStore.setState({ selectedElement: id }); } }}>
{children}
{editing && <button type="button" className="editable-hud__handle" aria-label={`Move ${HUD_ELEMENTS[id]}`} title="Drag to move; arrow keys nudge"
@@ -102,5 +108,6 @@ export function EditableHudElement({ id, children, intrinsicWidth, bottomAnchor,
updatePosition(position.x + delta[0] * .01, position.y + delta[1] * .01);
}}>{HUD_ELEMENTS[id]}{!element.visible ? " · Hidden" : ""}</button>}
</div>;
if (dualScreen && screen !== surface.surface) return null;
return positioned && host ? createPortal(content, host) : content;
}