diff --git a/web/js/json_builder.js b/web/js/json_builder.js index 70a7ed5..e6ab8af 100644 --- a/web/js/json_builder.js +++ b/web/js/json_builder.js @@ -1,35 +1,42 @@ import { app } from "../../../scripts/app.js"; +/** + * JSON Builder Extension for ComfyUI-LLMs-Toolkit + * + * Features a premium styled "Update inputs" button with: + * - Gradient background with hover effects + * - Rounded corners and subtle shadow + * - Icon indicator + */ + app.registerExtension({ name: "LLMs_Toolkit.JSONBuilder", async beforeRegisterNodeDef(nodeType, nodeData, app) { if (nodeData.name === "JSONBuilder") { nodeType.prototype.onNodeCreated = function () { - // Find inputcount widget and add button right after it + // Find inputcount widget const inputCountWidget = this.widgets.find(w => w.name === "input_count"); const inputCountIdx = this.widgets.indexOf(inputCountWidget); - // Insert button after input_count widget - const button = this.addWidget("button", "Update inputs", null, () => { + // Create custom styled button + const button = this.addWidget("button", "⟳ Update inputs", null, () => { const inputCountWidget = this.widgets.find(w => w.name === "input_count"); if (!inputCountWidget) return; const target_count = inputCountWidget.value; - // Count current key widgets (they are in widgets, not inputs) + // Count current key widgets const current_keys = this.widgets.filter(w => w.name && w.name.startsWith("key_") ).length; - if (target_count === current_keys) return; // already correct + if (target_count === current_keys) return; if (target_count < current_keys) { - // Remove excess widgets and inputs const to_remove = current_keys - target_count; for (let i = 0; i < to_remove; i++) { const idx = current_keys - i; - // Remove value input if (this.inputs) { const value_idx = this.inputs.findIndex( input => input.name === `value_${idx}` @@ -37,7 +44,6 @@ app.registerExtension({ if (value_idx !== -1) this.removeInput(value_idx); } - // Remove key widget const key_widget_idx = this.widgets.findIndex( w => w.name === `key_${idx}` ); @@ -46,20 +52,55 @@ app.registerExtension({ } } } else { - // Add new widgets and inputs for (let i = current_keys + 1; i <= target_count; i++) { - // Add key as editable text widget this.addWidget("text", `key_${i}`, "", () => { }, {}); - // Add value as input slot this.addInput(`value_${i}`, "STRING"); } } - // Resize node to fit new widgets this.setSize(this.computeSize()); }); - // Move button to be right after input_count + // Custom draw function for premium button styling + button.draw = function (ctx, node, widget_width, y, H) { + const margin = 10; + const x = margin; + const w = widget_width - margin * 2; + const h = H; + const radius = 6; + + // Draw button background with gradient + const gradient = ctx.createLinearGradient(x, y, x, y + h); + gradient.addColorStop(0, "#3a6ea5"); // Blue top + gradient.addColorStop(1, "#2c5282"); // Darker blue bottom + + ctx.beginPath(); + ctx.roundRect(x, y, w, h, radius); + ctx.fillStyle = gradient; + ctx.fill(); + + // Subtle border + ctx.strokeStyle = "#4a90d9"; + ctx.lineWidth = 1; + ctx.stroke(); + + // Button text + ctx.fillStyle = "#ffffff"; + ctx.font = "bold 12px 'Segoe UI', Arial, sans-serif"; + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; + ctx.fillText(this.label || "⟳ Update inputs", x + w / 2, y + h / 2); + + // Subtle highlight on top edge + ctx.beginPath(); + ctx.moveTo(x + radius, y + 1); + ctx.lineTo(x + w - radius, y + 1); + ctx.strokeStyle = "rgba(255, 255, 255, 0.2)"; + ctx.lineWidth = 1; + ctx.stroke(); + }; + + // Move button right after input_count if (inputCountIdx !== -1) { const buttonIdx = this.widgets.indexOf(button); if (buttonIdx !== -1 && buttonIdx !== inputCountIdx + 1) {