From 93108a27fe716452eb5c1692c6736e0994c474d4 Mon Sep 17 00:00:00 2001 From: ImBenji Date: Tue, 1 Sep 2026 20:20:27 +0100 Subject: [PATCH] fix: convert style strings for react in the ops console htm passes props through untouched and react rejects a style string with error #62, so every view rendered an empty page. Converting once in the createElement wrapper keeps plain css in the templates instead of style objects everywhere. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01WnNxwxfXSbeNtjvtz5gayb --- public/admin/assets/js/ops/core.js | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/public/admin/assets/js/ops/core.js b/public/admin/assets/js/ops/core.js index 9ef9321..3f4611a 100644 --- a/public/admin/assets/js/ops/core.js +++ b/public/admin/assets/js/ops/core.js @@ -1,6 +1,31 @@ // Shared plumbing: htm binding, hash router, polling fetch, formatters. const { createElement, useState, useEffect, useRef, useCallback } = React; -export const html = htm.bind(createElement); + +// htm hands props straight through, and React refuses a style string (error #62). +// Writing style objects everywhere in tagged templates is miserable, so convert +// once here instead and let the views keep using plain css. +function cssToObject(css) { + const style = {}; + for (const declaration of String(css).split(';')) { + const split = declaration.indexOf(':'); + if (split === -1) continue; + const property = declaration.slice(0, split).trim(); + const value = declaration.slice(split + 1).trim(); + if (!property || !value) continue; + // custom properties have to stay verbatim, the rest camelCase + style[property.startsWith('--') ? property : property.replace(/-([a-z])/g, (_, c) => c.toUpperCase())] = value; + } + return style; +} + +function h(type, props, ...children) { + if (props && typeof props.style === 'string') { + return createElement(type, { ...props, style: cssToObject(props.style) }, ...children); + } + return createElement(type, props, ...children); +} + +export const html = htm.bind(h); export { useState, useEffect, useRef, useCallback }; export async function api(path, options = {}) {