wanvision-studio / components /lora-selector.js
00Boobs00's picture
Give this the grand finale finishing polish for immediate deployment as a reliable and fully operational private and secure personal tool only intended to be used by me.
d595b97 verified
class LoraSelector extends HTMLElement {
connectedCallback() {
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
}
.lora-container {
position: relative;
}
.lora-select {
width: 100%;
background: #374151;
border: 1px solid #4b5563;
border-radius: 0.5rem;
padding: 0.75rem;
color: white;
font-size: 1rem;
cursor: pointer;
appearance: none;
background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239ca3af' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
background-repeat: no-repeat;
background-position: right 0.75rem center;
background-size: 1rem;
}
.lora-select:focus {
outline: none;
border-color: #10b981;
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.3);
}
.loading {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
display: none;
}
.spinner {
width: 20px;
height: 20px;
border: 2px solid rgba(255, 255, 255, 0.3);
border-radius: 50%;
border-top-color: #10b981;
animation: spin 1s ease-in-out infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.error {
color: #ef4444;
font-size: 0.875rem;
margin-top: 0.5rem;
display: none;
}
</style>
<div class="lora-container">
<select class="lora-select" id="loraSelect">
<option value="">Loading LoRA models...</option>
</select>
<div class="loading" id="loadingIndicator">
<div class="spinner"></div>
</div>
</div>
<div class="error" id="errorMessage"></div>
`;
this.loadLoraModels();
}
async loadLoraModels() {
const selectElement = this.shadowRoot.getElementById('loraSelect');
const loadingIndicator = this.shadowRoot.getElementById('loadingIndicator');
const errorMessage = this.shadowRoot.getElementById('errorMessage');
try {
loadingIndicator.style.display = 'block';
// Fetch LoRA models from Hugging Face API
const response = await fetch('https://huggingface.co/api/models/Playtime-AI/Wan2.2-Loras');
const data = await response.json();
// Get safetensors files
const safetensorsFiles = data.siblings.filter(file => file.rfilename.endsWith('.safetensors'));
// Clear loading option
selectElement.innerHTML = '<option value="">Select a LoRA model</option>';
// Add each LoRA model as an option
safetensorsFiles.forEach(file => {
const option = document.createElement('option');
const modelName = file.rfilename.replace('.safetensors', '');
option.value = JSON.stringify({
filename: file.rfilename,
trigger: this.getTriggerWord(modelName)
});
option.textContent = modelName;
selectElement.appendChild(option);
});
// Dispatch event when models are loaded
this.dispatchEvent(new CustomEvent('loras-loaded', {
detail: { models: safetensorsFiles },
bubbles: true
}));
} catch (error) {
console.error('Error loading LoRA models:', error);
selectElement.innerHTML = '<option value="">Failed to load models</option>';
errorMessage.textContent = 'Failed to load LoRA models. Please try again later.';
errorMessage.style.display = 'block';
} finally {
loadingIndicator.style.display = 'none';
}
}
getTriggerWord(modelName) {
const triggers = {
'Wan2.2-Disco-Diffusion': 'disco style',
'Wan2.2-Futuristic-City': 'futuristic cityscape',
'Wan2.2-Anime-Art': 'anime art style',
'Wan2.2-Cyberpunk': 'cyberpunk aesthetic',
'Wan2.2-Fantasy': 'fantasy illustration',
'Wan2.2-Photorealistic': 'photorealistic',
'Wan2.2-Watercolor': 'watercolor painting',
'Wan2.2-Oil-Painting': 'oil painting',
'Wan2.2-Sketch': 'pencil sketch',
'Wan2.2-Impressionist': 'impressionist painting'
};
return triggers[modelName] || 'enhanced style';
}
get selectedValue() {
const selected = this.shadowRoot.getElementById('loraSelect').value;
try {
return JSON.parse(selected);
} catch {
return { filename: '', trigger: '' };
}
}
set selectedValue(value) {
this.shadowRoot.getElementById('loraSelect').value = JSON.stringify(value);
}
}
customElements.define('lora-selector', LoraSelector);