feat(ui): add trigger word highlighting for selected LoRAs

- Import applySelectionHighlight in lora_loader and lora_stacker
- Pass onSelectionChange callback to loras_widget to handle selection changes
- Implement selection tracking and payload building in loras_widget
- Emit selection changes when LoRA selection is modified
- Update tags_widget to support highlighted tag styling

This provides visual feedback when LoRAs are selected by highlighting associated trigger words in the interface.
This commit is contained in:
Will Miao
2025-11-07 16:08:56 +08:00
parent f76343f389
commit 388ff7f5b4
6 changed files with 350 additions and 22 deletions

View File

@@ -33,6 +33,66 @@ app.registerExtension({
node.tagWidget = result.widget;
const normalizeTagText = (text) =>
(typeof text === 'string' ? text.trim().toLowerCase() : '');
const collectHighlightTokens = (wordsArray) => {
const tokens = new Set();
const addToken = (text) => {
const normalized = normalizeTagText(text);
if (normalized) {
tokens.add(normalized);
}
};
wordsArray.forEach((rawWord) => {
if (typeof rawWord !== 'string') {
return;
}
addToken(rawWord);
const groupParts = rawWord.split(/,{2,}/);
groupParts.forEach((groupPart) => {
addToken(groupPart);
groupPart.split(',').forEach(addToken);
});
rawWord.split(',').forEach(addToken);
});
return tokens;
};
const applyHighlightState = () => {
if (!node.tagWidget) return;
const highlightSet = node._highlightedTriggerWords || new Set();
const updatedTags = (node.tagWidget.value || []).map(tag => ({
...tag,
highlighted: highlightSet.size > 0 && highlightSet.has(normalizeTagText(tag.text))
}));
node.tagWidget.value = updatedTags;
};
node.highlightTriggerWords = (triggerWords) => {
const wordsArray = Array.isArray(triggerWords)
? triggerWords
: triggerWords
? [triggerWords]
: [];
node._highlightedTriggerWords = collectHighlightTokens(wordsArray);
applyHighlightState();
};
if (node.__pendingHighlightWords !== undefined) {
const pending = node.__pendingHighlightWords;
delete node.__pendingHighlightWords;
node.highlightTriggerWords(pending);
}
node.applyTriggerHighlightState = applyHighlightState;
// Add hidden widget to store original message
const hiddenWidget = node.addWidget('text', 'orinalMessage', '');
hiddenWidget.type = CONVERTED_TYPE;
@@ -52,6 +112,8 @@ app.registerExtension({
}
}
requestAnimationFrame(() => node.applyTriggerHighlightState?.());
const groupModeWidget = node.widgets[0];
groupModeWidget.callback = (value) => {
if (node.widgets[3].value) {
@@ -69,6 +131,7 @@ app.registerExtension({
active: value
}));
node.tagWidget.value = updatedTags;
node.applyTriggerHighlightState?.();
}
}
});
@@ -147,5 +210,6 @@ app.registerExtension({
}
node.tagWidget.value = tagArray;
node.applyTriggerHighlightState?.();
}
});