refactor(api): ✨ add reactive API change notifications
- introduced MTB_API_CHANGED_EVENT custom event for triggering panel updates - added notifyAPIChanged() function dispatched on API modifications - setup event listener in APIPanel constructor to debounce updates via requestAnimationFrame - improved boolean value handling to recognize numeric 1/'1' as true - ensures UI stays in sync when API properties change across extension, widget manager, and panel
This commit is contained in:
@@ -59,17 +59,18 @@
|
||||
/>
|
||||
{/if}
|
||||
{:else if item.type === 'BOOLEAN'}
|
||||
{@const isChecked = value === true || value === 'true' || value === 1 || value === '1'}
|
||||
<label class="mtb-toggle">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={value === true || value === 'true'}
|
||||
checked={isChecked}
|
||||
onchange={(e) => {
|
||||
value = e.currentTarget.checked
|
||||
onInput(e)
|
||||
}}
|
||||
/>
|
||||
<span class="mtb-toggle-slider"></span>
|
||||
<span class="mtb-toggle-label">{value ? 'On' : 'Off'}</span>
|
||||
<span class="mtb-toggle-label">{isChecked ? 'On' : 'Off'}</span>
|
||||
</label>
|
||||
{:else if item.type === 'COLOR'}
|
||||
<ColorPicker
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { app } from '@/scripts/app'
|
||||
import * as shared from '@mtb/shared'
|
||||
import { apiSettingsWidgetManager } from './widget-manager'
|
||||
import { getAPIPanel } from './panel.svelte'
|
||||
import { getAPIPanel, notifyAPIChanged } from './panel.svelte'
|
||||
import type { MTBNode } from './types'
|
||||
|
||||
interface ContextMenuItem {
|
||||
@@ -79,6 +79,7 @@ export function registerMtbApiExtension(): void {
|
||||
} else {
|
||||
node.setProperty('useAPI', true)
|
||||
}
|
||||
notifyAPIChanged()
|
||||
},
|
||||
}
|
||||
options.push(markApiItem)
|
||||
@@ -97,6 +98,7 @@ export function registerMtbApiExtension(): void {
|
||||
apiSettingsWidgetManager.applySettings(node, { isAPIOutput: true })
|
||||
node.setProperty('useAPI', true)
|
||||
}
|
||||
notifyAPIChanged()
|
||||
},
|
||||
}
|
||||
options.push(markOutputItem)
|
||||
|
||||
@@ -19,5 +19,5 @@ export { API_COLOR, OUTPUT_COLOR } from './constants'
|
||||
// Re-export core modules
|
||||
export { graphToPrompt } from './graph-to-prompt'
|
||||
export { APISettingsWidgetManager, apiSettingsWidgetManager } from './widget-manager'
|
||||
export { APIPanel, getAPIPanel } from './panel.svelte'
|
||||
export { APIPanel, getAPIPanel, notifyAPIChanged, MTB_API_CHANGED_EVENT } from './panel.svelte'
|
||||
export { registerMtbApiExtension } from './extension'
|
||||
|
||||
@@ -30,6 +30,14 @@ function createPanelProps() {
|
||||
return props
|
||||
}
|
||||
|
||||
/** Custom event for API changes */
|
||||
export const MTB_API_CHANGED_EVENT = 'mtb:api:changed'
|
||||
|
||||
/** Dispatch event to notify panel of changes */
|
||||
export function notifyAPIChanged(): void {
|
||||
window.dispatchEvent(new CustomEvent(MTB_API_CHANGED_EVENT))
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls the API panel UI for managing exposed workflow inputs
|
||||
*/
|
||||
@@ -37,9 +45,26 @@ export class APIPanel {
|
||||
private component: ReturnType<typeof mount> | null = null
|
||||
private props = createPanelProps()
|
||||
private sidebarMode = false
|
||||
private listening = false
|
||||
|
||||
constructor() {
|
||||
// Don't mount automatically - wait for renderInto or show
|
||||
this.setupChangeListener()
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen for API changes and update panel reactively
|
||||
*/
|
||||
private setupChangeListener(): void {
|
||||
if (this.listening) return
|
||||
this.listening = true
|
||||
|
||||
window.addEventListener(MTB_API_CHANGED_EVENT, () => {
|
||||
// Debounce updates slightly
|
||||
requestAnimationFrame(() => {
|
||||
this.updateContent()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,6 +8,7 @@ import { $el } from '@/scripts/ui'
|
||||
import * as shared from '@mtb/shared'
|
||||
import { API_COLOR, OUTPUT_COLOR } from './constants'
|
||||
import { API_INPUT_TYPES, type APIInputType, type APINodeSettings, type MTBNode } from './types'
|
||||
import { notifyAPIChanged } from './panel.svelte'
|
||||
import CSS from './api_nodes.css?inline'
|
||||
|
||||
declare const LiteGraph: {
|
||||
@@ -199,6 +200,7 @@ export class APISettingsWidgetManager {
|
||||
})
|
||||
contentContainer.classList.add('mtb_api_disabled')
|
||||
}
|
||||
notifyAPIChanged()
|
||||
})
|
||||
|
||||
const title = document.createElement('span')
|
||||
@@ -236,6 +238,7 @@ export class APISettingsWidgetManager {
|
||||
this.applySettings(node, {
|
||||
inputs: { [widget.name]: { type: typeSelect.value as APIInputType } },
|
||||
})
|
||||
notifyAPIChanged()
|
||||
})
|
||||
|
||||
// Name input
|
||||
@@ -252,6 +255,7 @@ export class APISettingsWidgetManager {
|
||||
this.applySettings(node, {
|
||||
inputs: { [widget.name]: { name: nameInput.value } },
|
||||
})
|
||||
notifyAPIChanged()
|
||||
})
|
||||
|
||||
const separator = document.createElement('hr')
|
||||
|
||||
Reference in New Issue
Block a user