From 86a77043d7372e3a2aae359c1204b7c28f1bed12 Mon Sep 17 00:00:00 2001 From: Chris Dumas Date: Wed, 26 Aug 2026 19:42:33 +0000 Subject: [PATCH] Persist H3 beat prompt state across reconfigure --- js/h3_beat_prompt/index.js | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/js/h3_beat_prompt/index.js b/js/h3_beat_prompt/index.js index f452dca..ac54176 100644 --- a/js/h3_beat_prompt/index.js +++ b/js/h3_beat_prompt/index.js @@ -7,6 +7,7 @@ const MIN_W = 420; const DEFAULT_W = 520; const DEFAULT_H = 340; const DEFAULT_BEAT = "Describe this beat."; +const STATE_PROPERTY = "dumas_h3_beat_prompt_state"; const DIRECTIVE_EXAMPLES = [ ["wardrobe", "wardrobe: Maya = grey shorts, red jacket"], ["seconds", "seconds: 8"], @@ -152,7 +153,12 @@ function normalizeState(value) { } function readState(node) { - return normalizeState(node._dh3bpState || findWidget(node, HIDDEN_INPUT_NAME)?.value || ""); + return normalizeState( + node._dh3bpState + || findWidget(node, HIDDEN_INPUT_NAME)?.value + || node.properties?.[STATE_PROPERTY] + || "" + ); } function findWidget(node, name) { @@ -170,10 +176,19 @@ function writeState(node, state) { const normalized = normalizeState(state); const serialized = JSON.stringify(normalized); node._dh3bpState = serialized; + node.properties = node.properties || {}; + node.properties[STATE_PROPERTY] = serialized; const widget = findWidget(node, HIDDEN_INPUT_NAME); if (widget) widget.value = serialized; } +function syncStateFromNode(node) { + const widgetValue = findWidget(node, HIDDEN_INPUT_NAME)?.value; + const propertyValue = node.properties?.[STATE_PROPERTY]; + const source = node._dh3bpState || widgetValue || propertyValue || ""; + writeState(node, source); +} + function updateTextareaHeight(textarea) { textarea.style.height = "auto"; textarea.style.height = `${Math.max(96, textarea.scrollHeight)}px`; @@ -306,7 +321,7 @@ function setupNode(node) { node.size[0] = Math.max(node.size[0] || 0, DEFAULT_W); node.size[1] = Math.max(node.size[1] || 0, DEFAULT_H); - writeState(node, readState(node)); + syncStateFromNode(node); renderUI(node); } @@ -371,7 +386,19 @@ app.registerExtension({ const originalConfigure = nodeType.prototype.onConfigure; nodeType.prototype.onConfigure = function onConfigure() { const result = originalConfigure?.apply(this, arguments); - this._dh3bpState = findWidget(this, HIDDEN_INPUT_NAME)?.value || this._dh3bpState; + syncStateFromNode(this); + queueMicrotask(() => renderUI(this)); + return result; + }; + + const originalSerialize = nodeType.prototype.onSerialize; + nodeType.prototype.onSerialize = function onSerialize(o) { + syncStateFromNode(this); + const result = originalSerialize?.apply(this, arguments); + if (o && this.properties?.[STATE_PROPERTY]) { + o.properties = o.properties || {}; + o.properties[STATE_PROPERTY] = this.properties[STATE_PROPERTY]; + } queueMicrotask(() => renderUI(this)); return result; };