|
import { app } from "../../scripts/app.js"; |
|
import { api } from "../../scripts/api.js"; |
|
import { $el } from "../../scripts/ui.js"; |
|
|
|
|
|
class FramerComfyDialog { |
|
constructor() { |
|
this.dialogContainer = null; |
|
this.overlay = null; |
|
this.dialog = null; |
|
this.inputFields = []; |
|
this.resolvePromise = null; |
|
this.rejectPromise = null; |
|
this.setupStyles(); |
|
} |
|
|
|
setupStyles() { |
|
|
|
const style = document.createElement("style"); |
|
style.textContent = ` |
|
.framer-comfy-overlay { |
|
position: fixed; |
|
top: 0; |
|
left: 0; |
|
width: 100%; |
|
height: 100%; |
|
background-color: rgba(0, 0, 0, 0.5); |
|
display: flex; |
|
justify-content: center; |
|
align-items: center; |
|
z-index: 9999; |
|
} |
|
|
|
.framer-comfy-dialog { |
|
background-color: #1a1a1a; |
|
border-radius: 8px; |
|
padding: 20px; |
|
width: 80%; |
|
max-width: 600px; |
|
max-height: 80vh; |
|
overflow-y: auto; |
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5); |
|
color: #fff; |
|
} |
|
|
|
.framer-comfy-dialog h2 { |
|
margin-top: 0; |
|
margin-bottom: 16px; |
|
font-size: 18px; |
|
border-bottom: 1px solid #333; |
|
padding-bottom: 10px; |
|
} |
|
|
|
.framer-comfy-input-group { |
|
margin-bottom: 16px; |
|
} |
|
|
|
.framer-comfy-input-label { |
|
display: block; |
|
margin-bottom: 6px; |
|
font-size: 14px; |
|
} |
|
|
|
.framer-comfy-input { |
|
width: 100%; |
|
background-color: #333; |
|
border: 1px solid #444; |
|
border-radius: 4px; |
|
padding: 8px 10px; |
|
color: #fff; |
|
font-size: 14px; |
|
} |
|
|
|
.framer-comfy-node-info { |
|
font-size: 12px; |
|
color: #999; |
|
margin-top: 4px; |
|
} |
|
|
|
.framer-comfy-buttons { |
|
display: flex; |
|
justify-content: flex-end; |
|
gap: 10px; |
|
margin-top: 20px; |
|
} |
|
|
|
.framer-comfy-button { |
|
background-color: #555; |
|
color: white; |
|
border: none; |
|
border-radius: 4px; |
|
padding: 8px 16px; |
|
cursor: pointer; |
|
font-size: 14px; |
|
transition: background-color 0.2s; |
|
} |
|
|
|
.framer-comfy-button:hover { |
|
background-color: #666; |
|
} |
|
|
|
.framer-comfy-button-primary { |
|
background-color: #2d8cff; |
|
} |
|
|
|
.framer-comfy-button-primary:hover { |
|
background-color: #1a7ae8; |
|
} |
|
`; |
|
document.head.appendChild(style); |
|
} |
|
|
|
createDialogContainer() { |
|
|
|
if (!this.dialogContainer) { |
|
this.dialogContainer = document.createElement("div"); |
|
document.body.appendChild(this.dialogContainer); |
|
} |
|
return this.dialogContainer; |
|
} |
|
|
|
showModelUrlsDialog(modelInputs) { |
|
this.inputFields = []; |
|
const container = this.createDialogContainer(); |
|
|
|
return new Promise((resolve, reject) => { |
|
this.resolvePromise = resolve; |
|
this.rejectPromise = reject; |
|
|
|
|
|
this.overlay = document.createElement("div"); |
|
this.overlay.className = "framer-comfy-overlay"; |
|
|
|
|
|
this.overlay.addEventListener("click", (e) => { |
|
e.stopPropagation(); |
|
}); |
|
|
|
|
|
this.overlay.addEventListener("keydown", (e) => { |
|
e.stopPropagation(); |
|
}); |
|
|
|
|
|
this.dialog = document.createElement("div"); |
|
this.dialog.className = "framer-comfy-dialog"; |
|
|
|
|
|
this.dialog.addEventListener("click", (e) => { |
|
e.stopPropagation(); |
|
}); |
|
|
|
|
|
const title = document.createElement("h2"); |
|
title.textContent = "Enter Information for FramerComfy"; |
|
this.dialog.appendChild(title); |
|
|
|
|
|
const form = document.createElement("form"); |
|
form.onsubmit = (e) => { |
|
e.preventDefault(); |
|
e.stopPropagation(); |
|
this.handleSubmit(); |
|
}; |
|
|
|
|
|
form.addEventListener("paste", (e) => { |
|
e.stopPropagation(); |
|
}); |
|
|
|
|
|
form.addEventListener("keydown", (e) => { |
|
e.stopPropagation(); |
|
}); |
|
|
|
|
|
const requiredInputsGroup = document.createElement("div"); |
|
requiredInputsGroup.className = "framer-comfy-input-group"; |
|
|
|
|
|
const workflowNameLabel = document.createElement("label"); |
|
workflowNameLabel.className = "framer-comfy-input-label"; |
|
workflowNameLabel.textContent = "Workflow Name (required)"; |
|
requiredInputsGroup.appendChild(workflowNameLabel); |
|
|
|
const workflowNameInput = document.createElement("input"); |
|
workflowNameInput.className = "framer-comfy-input"; |
|
workflowNameInput.type = "text"; |
|
workflowNameInput.placeholder = "Enter workflow name"; |
|
workflowNameInput.required = true; |
|
workflowNameInput.dataset.inputType = "workflow_name"; |
|
|
|
workflowNameInput.addEventListener("paste", (e) => e.stopPropagation()); |
|
workflowNameInput.addEventListener("keydown", (e) => e.stopPropagation()); |
|
workflowNameInput.addEventListener("focus", (e) => e.stopPropagation()); |
|
workflowNameInput.addEventListener("blur", (e) => e.stopPropagation()); |
|
this.inputFields.push(workflowNameInput); |
|
requiredInputsGroup.appendChild(workflowNameInput); |
|
|
|
|
|
const tokenLabel = document.createElement("label"); |
|
tokenLabel.className = "framer-comfy-input-label"; |
|
tokenLabel.textContent = "Hugging Face Access Token (required)"; |
|
tokenLabel.style.marginTop = "16px"; |
|
requiredInputsGroup.appendChild(tokenLabel); |
|
|
|
const tokenInput = document.createElement("input"); |
|
tokenInput.className = "framer-comfy-input"; |
|
tokenInput.type = "password"; |
|
tokenInput.placeholder = "Enter your Hugging Face access token"; |
|
tokenInput.required = true; |
|
tokenInput.dataset.inputType = "huggingface_access_token"; |
|
|
|
tokenInput.addEventListener("paste", (e) => e.stopPropagation()); |
|
tokenInput.addEventListener("keydown", (e) => e.stopPropagation()); |
|
tokenInput.addEventListener("focus", (e) => e.stopPropagation()); |
|
tokenInput.addEventListener("blur", (e) => e.stopPropagation()); |
|
this.inputFields.push(tokenInput); |
|
requiredInputsGroup.appendChild(tokenInput); |
|
|
|
form.appendChild(requiredInputsGroup); |
|
|
|
|
|
const separator = document.createElement("hr"); |
|
separator.style.margin = "20px 0"; |
|
separator.style.borderColor = "#333"; |
|
form.appendChild(separator); |
|
|
|
|
|
if (modelInputs.length > 0) { |
|
const modelSectionTitle = document.createElement("h3"); |
|
modelSectionTitle.textContent = "Model URLs"; |
|
modelSectionTitle.style.fontSize = "16px"; |
|
modelSectionTitle.style.marginBottom = "16px"; |
|
form.appendChild(modelSectionTitle); |
|
} |
|
|
|
|
|
modelInputs.forEach((input, index) => { |
|
const { nodeId, nodeTitle, inputName, promptMessage } = input; |
|
|
|
const inputGroup = document.createElement("div"); |
|
inputGroup.className = "framer-comfy-input-group"; |
|
|
|
const label = document.createElement("label"); |
|
label.className = "framer-comfy-input-label"; |
|
label.textContent = promptMessage; |
|
inputGroup.appendChild(label); |
|
|
|
const inputField = document.createElement("input"); |
|
inputField.className = "framer-comfy-input"; |
|
inputField.type = "text"; |
|
inputField.placeholder = "https://huggingface.co/..."; |
|
inputField.dataset.nodeId = nodeId; |
|
inputField.dataset.inputName = inputName; |
|
inputField.dataset.inputType = "model_url"; |
|
|
|
inputField.addEventListener("paste", (e) => e.stopPropagation()); |
|
inputField.addEventListener("keydown", (e) => e.stopPropagation()); |
|
inputField.addEventListener("focus", (e) => e.stopPropagation()); |
|
inputField.addEventListener("blur", (e) => e.stopPropagation()); |
|
this.inputFields.push(inputField); |
|
inputGroup.appendChild(inputField); |
|
|
|
const nodeInfo = document.createElement("div"); |
|
nodeInfo.className = "framer-comfy-node-info"; |
|
nodeInfo.textContent = `Node: ${nodeTitle} (ID: ${nodeId})`; |
|
inputGroup.appendChild(nodeInfo); |
|
|
|
form.appendChild(inputGroup); |
|
}); |
|
|
|
|
|
const buttonsContainer = document.createElement("div"); |
|
buttonsContainer.className = "framer-comfy-buttons"; |
|
|
|
const cancelButton = document.createElement("button"); |
|
cancelButton.className = "framer-comfy-button"; |
|
cancelButton.textContent = "Cancel"; |
|
cancelButton.type = "button"; |
|
cancelButton.onclick = (e) => { |
|
e.stopPropagation(); |
|
this.handleCancel(); |
|
}; |
|
buttonsContainer.appendChild(cancelButton); |
|
|
|
const submitButton = document.createElement("button"); |
|
submitButton.className = "framer-comfy-button framer-comfy-button-primary"; |
|
submitButton.textContent = "Submit"; |
|
submitButton.type = "submit"; |
|
submitButton.addEventListener("click", (e) => e.stopPropagation()); |
|
buttonsContainer.appendChild(submitButton); |
|
|
|
form.appendChild(buttonsContainer); |
|
this.dialog.appendChild(form); |
|
|
|
|
|
this.overlay.appendChild(this.dialog); |
|
|
|
|
|
container.appendChild(this.overlay); |
|
}); |
|
} |
|
|
|
handleSubmit() { |
|
|
|
const requiredInputs = this.inputFields.filter(input => |
|
input.dataset.inputType === "workflow_name" || |
|
input.dataset.inputType === "huggingface_access_token" |
|
); |
|
|
|
for (const input of requiredInputs) { |
|
if (!input.value.trim()) { |
|
alert(`${input.dataset.inputType === "workflow_name" ? "Workflow Name" : "Hugging Face Access Token"} is required.`); |
|
return; |
|
} |
|
} |
|
|
|
|
|
const workflowInfo = { |
|
workflow_name: "", |
|
huggingface_access_token: "" |
|
}; |
|
|
|
|
|
const modelResults = []; |
|
|
|
for (const input of this.inputFields) { |
|
const value = input.value.trim(); |
|
|
|
if (input.dataset.inputType === "workflow_name") { |
|
workflowInfo.workflow_name = value; |
|
} else if (input.dataset.inputType === "huggingface_access_token") { |
|
workflowInfo.huggingface_access_token = value; |
|
} else if (input.dataset.inputType === "model_url" && value) { |
|
modelResults.push({ |
|
nodeId: input.dataset.nodeId, |
|
inputName: input.dataset.inputName, |
|
value: value |
|
}); |
|
} |
|
} |
|
|
|
this.closeDialog(); |
|
this.resolvePromise({ |
|
workflowInfo: workflowInfo, |
|
modelResults: modelResults |
|
}); |
|
} |
|
|
|
handleCancel() { |
|
this.closeDialog(); |
|
this.resolvePromise([]); |
|
} |
|
|
|
closeDialog() { |
|
if (this.overlay && this.dialogContainer) { |
|
this.dialogContainer.removeChild(this.overlay); |
|
this.overlay = null; |
|
this.dialog = null; |
|
} |
|
} |
|
} |
|
|
|
|
|
export const framerComfyDialog = new FramerComfyDialog(); |
|
|