Fixing UI editing mode
This commit is contained in:
@@ -169,7 +169,12 @@
|
|||||||
</Button>
|
</Button>
|
||||||
<Checkbox label="Lock Nodes" bind:value={$uiState.nodesLocked}/>
|
<Checkbox label="Lock Nodes" bind:value={$uiState.nodesLocked}/>
|
||||||
<Checkbox label="Disable Interaction" bind:value={$uiState.graphLocked}/>
|
<Checkbox label="Disable Interaction" bind:value={$uiState.graphLocked}/>
|
||||||
<Checkbox label="Enable UI Editing" bind:value={$uiState.unlocked}/>
|
<label for="enable-ui-editing">Enable UI Editing</label>
|
||||||
|
<select id="enable-ui-editing" name="enable-ui-editing" bind:value={$uiState.uiEditMode}>
|
||||||
|
<option value="disabled">Disabled</option>
|
||||||
|
<option value="widgets">Widgets</option>
|
||||||
|
<option value="containers">Containers</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<LightboxModal />
|
<LightboxModal />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -53,8 +53,4 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#comfy-ui-panes > :global(.root-container > .block) {
|
|
||||||
padding: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -14,14 +14,15 @@
|
|||||||
import { getComponentForWidgetState } from "$lib/utils"
|
import { getComponentForWidgetState } from "$lib/utils"
|
||||||
|
|
||||||
export let dragItem: IDragItem | null = null;
|
export let dragItem: IDragItem | null = null;
|
||||||
export let zIndex: number = 100;
|
export let zIndex: number = 0;
|
||||||
export let classes: string[] = [];
|
export let classes: string[] = [];
|
||||||
|
export let isRoot: boolean = false;
|
||||||
|
let dragDisabled: boolean = false;
|
||||||
let container: ContainerLayout | null = null;
|
let container: ContainerLayout | null = null;
|
||||||
let widget: WidgetLayout | null = null;
|
let widget: WidgetLayout | null = null;
|
||||||
let widgetState: WidgetUIState | null = null;
|
let widgetState: WidgetUIState | null = null;
|
||||||
let children: IDragItem[] | null = null;
|
let children: IDragItem[] | null = null;
|
||||||
let dragDisabled = true;
|
const flipDurationMs = 100;
|
||||||
const flipDurationMs = 200;
|
|
||||||
|
|
||||||
$: if (dragItem) {
|
$: if (dragItem) {
|
||||||
if (dragItem.type === "container") {
|
if (dragItem.type === "container") {
|
||||||
@@ -37,8 +38,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$: dragDisabled = !$uiState.unlocked;
|
|
||||||
|
|
||||||
function handleConsider(evt: any) {
|
function handleConsider(evt: any) {
|
||||||
children = layoutState.updateChildren(dragItem, evt.detail.items)
|
children = layoutState.updateChildren(dragItem, evt.detail.items)
|
||||||
// console.log(dragItems);
|
// console.log(dragItems);
|
||||||
@@ -47,18 +46,13 @@
|
|||||||
function handleFinalize(evt: any) {
|
function handleFinalize(evt: any) {
|
||||||
children = layoutState.updateChildren(dragItem, evt.detail.items)
|
children = layoutState.updateChildren(dragItem, evt.detail.items)
|
||||||
// Ensure dragging is stopped on drag finish
|
// Ensure dragging is stopped on drag finish
|
||||||
// dragDisabled = true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const startDrag = () => {
|
const startDrag = () => {
|
||||||
if (!$uiState.unlocked)
|
return
|
||||||
return
|
|
||||||
// dragDisabled = false;
|
|
||||||
};
|
};
|
||||||
const stopDrag = () => {
|
const stopDrag = () => {
|
||||||
if (!$uiState.unlocked)
|
return
|
||||||
return
|
|
||||||
// dragDisabled = true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$: if ($queueState && widget) {
|
$: if ($queueState && widget) {
|
||||||
@@ -70,12 +64,14 @@
|
|||||||
|
|
||||||
{#if container && children}
|
{#if container && children}
|
||||||
{@const id = container.id}
|
{@const id = container.id}
|
||||||
<div class="container {container.attrs.direction} {container.attrs.classes} {classes.join(' ')}">
|
<div class="container {container.attrs.direction} {container.attrs.classes} {classes.join(' ')}"
|
||||||
|
class:root-container={isRoot}
|
||||||
|
class:container-edit-outline={$uiState.uiEditMode === "containers" && zIndex > 1}>
|
||||||
<Block>
|
<Block>
|
||||||
{#if container.attrs.showTitle}
|
{#if container.attrs.showTitle}
|
||||||
<label for={String(id)} class={$uiState.unlocked ? "edit-title-label" : ""}>
|
<label for={String(id)} class={$uiState.uiEditMode === "containers" ? "edit-title-label" : ""}>
|
||||||
<BlockTitle>
|
<BlockTitle>
|
||||||
{#if $uiState.unlocked}
|
{#if $uiState.uiEditMode === "containers"}
|
||||||
<input class="edit-title" bind:value={container.attrs.title} type="text" minlength="1" />
|
<input class="edit-title" bind:value={container.attrs.title} type="text" minlength="1" />
|
||||||
{:else}
|
{:else}
|
||||||
{container.attrs.title}
|
{container.attrs.title}
|
||||||
@@ -85,12 +81,22 @@
|
|||||||
{/if}
|
{/if}
|
||||||
<div class="v-pane"
|
<div class="v-pane"
|
||||||
class:empty={children.length === 0}
|
class:empty={children.length === 0}
|
||||||
use:dndzone="{{ items: children, dragDisabled, flipDurationMs }}"
|
class:edit={$uiState.uiEditMode === "containers" && zIndex > 1}
|
||||||
|
use:dndzone="{{
|
||||||
|
items: children,
|
||||||
|
flipDurationMs,
|
||||||
|
morphDisabled: true,
|
||||||
|
dropFromOthersDisabled: zIndex === 0,
|
||||||
|
dragDisabled: zIndex === 0
|
||||||
|
}}"
|
||||||
on:consider="{handleConsider}"
|
on:consider="{handleConsider}"
|
||||||
on:finalize="{handleFinalize}"
|
on:finalize="{handleFinalize}"
|
||||||
>
|
>
|
||||||
{#each children.filter(item => item.id !== SHADOW_PLACEHOLDER_ITEM_ID) as item(item.id)}
|
{#each children.filter(item => item.id !== SHADOW_PLACEHOLDER_ITEM_ID) as item(item.id)}
|
||||||
<div class="animation-wrapper" class:is-executing={item.isNodeExecuting} animate:flip={{duration:flipDurationMs}}>
|
<div class="animation-wrapper"
|
||||||
|
class:edit={$uiState.unlocked}
|
||||||
|
class:is-executing={item.isNodeExecuting}
|
||||||
|
animate:flip={{duration:flipDurationMs}}>
|
||||||
<svelte:self dragItem={item} zIndex={zIndex+1} />
|
<svelte:self dragItem={item} zIndex={zIndex+1} />
|
||||||
{#if item[SHADOW_ITEM_MARKER_PROPERTY_NAME]}
|
{#if item[SHADOW_ITEM_MARKER_PROPERTY_NAME]}
|
||||||
<div in:fade={{duration:200, easing: cubicIn}} class='drag-item-shadow'/>
|
<div in:fade={{duration:200, easing: cubicIn}} class='drag-item-shadow'/>
|
||||||
@@ -98,15 +104,17 @@
|
|||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{#if $uiState.unlocked}
|
{#if $uiState.uiEditMode === "containers" && zIndex > 1}
|
||||||
<div class="handle handle-container" style="z-index: {zIndex}" on:mousedown={startDrag} on:touchstart={startDrag} on:mouseup={stopDrag} on:touchend={stopDrag}/>
|
<div class="handle handle-container" style="z-index: {zIndex+100}" on:mousedown={startDrag} on:touchstart={startDrag} on:mouseup={stopDrag} on:touchend={stopDrag}/>
|
||||||
{/if}
|
{/if}
|
||||||
</Block>
|
</Block>
|
||||||
</div>
|
</div>
|
||||||
{:else if widget}
|
{:else if widget}
|
||||||
<svelte:component this={getComponentForWidgetState(widgetState)} item={widgetState} />
|
<div class:widget-edit-outline={$uiState.uiEditMode === "widgets" && zIndex > 1}>
|
||||||
{#if $uiState.unlocked}
|
<svelte:component this={getComponentForWidgetState(widgetState)} item={widgetState} />
|
||||||
<div class="handle handle-widget" style="z-index: {zIndex}" on:mousedown={startDrag} on:touchstart={startDrag} on:mouseup={stopDrag} on:touchend={stopDrag}/>
|
</div>
|
||||||
|
{#if $uiState.uiEditMode ==="widgets" && zIndex > 1}
|
||||||
|
<div class="handle handle-widget" style="z-index: {zIndex+100}" on:mousedown={startDrag} on:touchstart={startDrag} on:mouseup={stopDrag} on:touchend={stopDrag}/>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
@@ -117,12 +125,16 @@
|
|||||||
overflow: visible;
|
overflow: visible;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
|
.edit {
|
||||||
|
min-width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
&.empty {
|
&.empty {
|
||||||
border-width: 3px;
|
border-width: 3px;
|
||||||
border-color: var(--color-grey-400);
|
border-color: var(--color-grey-400);
|
||||||
border-radius: var(--block-radius);
|
border-radius: var(--block-radius);
|
||||||
background: var(--color-grey-300);
|
background: var(--color-grey-300);
|
||||||
min-height: 50px;
|
min-height: 200px;
|
||||||
border-style: dashed;
|
border-style: dashed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,6 +146,10 @@
|
|||||||
height: fit-content;
|
height: fit-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.container-edit-outline {
|
||||||
|
/* width: 20rem; */
|
||||||
|
}
|
||||||
|
|
||||||
&.horizontal {
|
&.horizontal {
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: var(--layout-gap);
|
gap: var(--layout-gap);
|
||||||
@@ -169,7 +185,10 @@
|
|||||||
|
|
||||||
.animation-wrapper {
|
.animation-wrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
flex-grow: 1;
|
|
||||||
|
&:not(.edit) {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.handle {
|
.handle {
|
||||||
@@ -235,4 +254,22 @@
|
|||||||
.edit-title::placeholder {
|
.edit-title::placeholder {
|
||||||
color: var(--input-placeholder-color);
|
color: var(--input-placeholder-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.container-edit-outline > :global(.block) {
|
||||||
|
border-color: var(--color-pink-500);
|
||||||
|
border-width: 2px;
|
||||||
|
border-style: dashed !important;
|
||||||
|
margin: 0.2em;
|
||||||
|
padding: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.widget-edit-outline {
|
||||||
|
border: 2px dashed var(--color-blue-400);
|
||||||
|
margin: 0.2em;
|
||||||
|
padding: 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.root-container > :global(.block) {
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import type ComfyApp from "$lib/components/ComfyApp"
|
|||||||
import type { LGraphNode, IWidget } from "@litegraph-ts/core"
|
import type { LGraphNode, IWidget } from "@litegraph-ts/core"
|
||||||
import nodeState from "$lib/state/nodeState";
|
import nodeState from "$lib/state/nodeState";
|
||||||
import type { NodeStateStore } from './nodeState';
|
import type { NodeStateStore } from './nodeState';
|
||||||
|
import { dndzone, SHADOW_PLACEHOLDER_ITEM_ID } from 'svelte-dnd-action';
|
||||||
|
|
||||||
type DragItemEntry = {
|
type DragItemEntry = {
|
||||||
dragItem: IDragItem,
|
dragItem: IDragItem,
|
||||||
@@ -136,6 +137,8 @@ function updateChildren(parent: IDragItem, children: IDragItem[]): IDragItem[] {
|
|||||||
const state = get(store);
|
const state = get(store);
|
||||||
state.allItems[parent.id].children = children;
|
state.allItems[parent.id].children = children;
|
||||||
for (const child of children) {
|
for (const child of children) {
|
||||||
|
if (child.id === SHADOW_PLACEHOLDER_ITEM_ID)
|
||||||
|
continue;
|
||||||
state.allItems[child.id].parent = parent;
|
state.allItems[child.id].parent = parent;
|
||||||
}
|
}
|
||||||
store.set(state)
|
store.set(state)
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ import { writable } from 'svelte/store';
|
|||||||
import type { Readable, Writable } from 'svelte/store';
|
import type { Readable, Writable } from 'svelte/store';
|
||||||
import type ComfyApp from "$lib/components/ComfyApp"
|
import type ComfyApp from "$lib/components/ComfyApp"
|
||||||
|
|
||||||
|
export type UIEditMode = "disabled" | "widgets" | "containers" | "layout";
|
||||||
|
|
||||||
export type UIState = {
|
export type UIState = {
|
||||||
app: ComfyApp,
|
app: ComfyApp,
|
||||||
nodesLocked: boolean,
|
nodesLocked: boolean,
|
||||||
graphLocked: boolean,
|
graphLocked: boolean,
|
||||||
unlocked: boolean,
|
uiEditMode: UIEditMode
|
||||||
}
|
}
|
||||||
|
|
||||||
export type WritableUIStateStore = Writable<UIState>;
|
export type WritableUIStateStore = Writable<UIState>;
|
||||||
@@ -14,7 +16,7 @@ const store: WritableUIStateStore = writable(
|
|||||||
{
|
{
|
||||||
graphLocked: true,
|
graphLocked: true,
|
||||||
nodesLocked: false,
|
nodesLocked: false,
|
||||||
unlocked: false,
|
uiEditMode: "disabled",
|
||||||
})
|
})
|
||||||
|
|
||||||
const uiStateStore: WritableUIStateStore =
|
const uiStateStore: WritableUIStateStore =
|
||||||
|
|||||||
Reference in New Issue
Block a user