Trying to use framework7 components

This commit is contained in:
space-nuko
2023-04-27 16:11:46 -07:00
parent 8dc8755403
commit f2fb491183
17 changed files with 577 additions and 153 deletions

View File

@@ -42,10 +42,12 @@
"@gradio/theme": "workspace:*", "@gradio/theme": "workspace:*",
"@gradio/upload": "workspace:*", "@gradio/upload": "workspace:*",
"@gradio/utils": "workspace:*", "@gradio/utils": "workspace:*",
"@litegraph-ts/tsconfig": "workspace:*",
"@litegraph-ts/core": "workspace:*", "@litegraph-ts/core": "workspace:*",
"@litegraph-ts/nodes-basic": "workspace:*", "@litegraph-ts/nodes-basic": "workspace:*",
"@litegraph-ts/tsconfig": "workspace:*",
"events": "^3.3.0", "events": "^3.3.0",
"framework7": "^8.0.3",
"framework7-svelte": "^8.0.3",
"pollen-css": "^4.6.2", "pollen-css": "^4.6.2",
"radix-icons-svelte": "^1.2.1", "radix-icons-svelte": "^1.2.1",
"svelte-preprocess": "^5.0.3", "svelte-preprocess": "^5.0.3",

53
pnpm-lock.yaml generated
View File

@@ -43,6 +43,12 @@ importers:
events: events:
specifier: ^3.3.0 specifier: ^3.3.0
version: 3.3.0 version: 3.3.0
framework7:
specifier: ^8.0.3
version: 8.0.3
framework7-svelte:
specifier: ^8.0.3
version: 8.0.3
pollen-css: pollen-css:
specifier: ^4.6.2 specifier: ^4.6.2
version: 4.6.2 version: 4.6.2
@@ -3146,6 +3152,12 @@ packages:
esutils: 2.0.3 esutils: 2.0.3
dev: true dev: true
/dom7@4.0.6:
resolution: {integrity: sha512-emjdpPLhpNubapLFdjNL9tP06Sr+GZkrIHEXLWvOGsytACUrkbeIdjO5g77m00BrHTznnlcNqgmn7pCN192TBA==}
dependencies:
ssr-window: 4.0.2
dev: false
/ecc-jsbn@0.1.2: /ecc-jsbn@0.1.2:
resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==} resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==}
dependencies: dependencies:
@@ -3801,6 +3813,21 @@ packages:
resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==} resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==}
dev: true dev: true
/framework7-svelte@8.0.3:
resolution: {integrity: sha512-SHirFqZBvm9E989Gyy59+pdBZdamZmqxLc/hklvorsY8llKpPuPBXbcS+fGvujvuhDq0fHHmN5tbLqYUPJ9Cyg==}
dev: false
/framework7@8.0.3:
resolution: {integrity: sha512-5DGd9J4OdTUn9hfrRaxDXYXF4hx2RAV+xy+9tzq0+R5d6DgjeE/WkqJ5ElDToww9IVAsafZcRwZodd+4a0wr/Q==}
dependencies:
dom7: 4.0.6
htm: 3.1.1
path-to-regexp: 6.2.1
skeleton-elements: 4.0.1
ssr-window: 4.0.2
swiper: 9.2.4
dev: false
/fs-extra@10.1.0: /fs-extra@10.1.0:
resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -3992,6 +4019,10 @@ packages:
dependencies: dependencies:
function-bind: 1.1.1 function-bind: 1.1.1
/htm@3.1.1:
resolution: {integrity: sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ==}
dev: false
/html-escaper@2.0.2: /html-escaper@2.0.2:
resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
dev: true dev: true
@@ -4096,7 +4127,7 @@ packages:
'@formatjs/ecma402-abstract': 1.11.4 '@formatjs/ecma402-abstract': 1.11.4
'@formatjs/fast-memoize': 1.2.1 '@formatjs/fast-memoize': 1.2.1
'@formatjs/icu-messageformat-parser': 2.1.0 '@formatjs/icu-messageformat-parser': 2.1.0
tslib: 2.3.1 tslib: 2.5.0
dev: false dev: false
/is-arrayish@0.2.1: /is-arrayish@0.2.1:
@@ -5143,6 +5174,10 @@ packages:
/path-parse@1.0.7: /path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
/path-to-regexp@6.2.1:
resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==}
dev: false
/path-type@4.0.0: /path-type@4.0.0:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'} engines: {node: '>=8'}
@@ -5648,6 +5683,10 @@ packages:
resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
dev: true dev: true
/skeleton-elements@4.0.1:
resolution: {integrity: sha512-T7YSF/Vu/raUcM6v3HiE4VSY/OvrNflg8Dur3Zza6VVJkq4slxm4pJRpGLNhoOfblIPZLQKh1cu7ADKveyqm/Q==}
dev: false
/slash@3.0.0: /slash@3.0.0:
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
engines: {node: '>=8'} engines: {node: '>=8'}
@@ -5716,6 +5755,10 @@ packages:
tweetnacl: 0.14.5 tweetnacl: 0.14.5
dev: false dev: false
/ssr-window@4.0.2:
resolution: {integrity: sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ==}
dev: false
/stack-utils@2.0.6: /stack-utils@2.0.6:
resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==}
engines: {node: '>=10'} engines: {node: '>=10'}
@@ -6134,6 +6177,13 @@ packages:
resolution: {integrity: sha512-brIBNNB76mXFmU/Kerm4wFnkskBbluBDCjx/8TcpYRb298Yh2dztS2kQ6bhtjMcvUhd5ynClfwpz5h2gnzdQ1A==} resolution: {integrity: sha512-brIBNNB76mXFmU/Kerm4wFnkskBbluBDCjx/8TcpYRb298Yh2dztS2kQ6bhtjMcvUhd5ynClfwpz5h2gnzdQ1A==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
/swiper@9.2.4:
resolution: {integrity: sha512-L7y3K/iiMXNYQ94FbfcJn7jex4QPnS4+voXGupTdC+UHW4XrR40QDdm4c9hXJ+Br0Il7PP0vP1W3goM9/Ly6Sg==}
engines: {node: '>= 4.7.0'}
dependencies:
ssr-window: 4.0.2
dev: false
/sync-request@6.1.0: /sync-request@6.1.0:
resolution: {integrity: sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw==} resolution: {integrity: sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw==}
engines: {node: '>=8.0.0'} engines: {node: '>=8.0.0'}
@@ -6315,6 +6365,7 @@ packages:
/tslib@2.3.1: /tslib@2.3.1:
resolution: {integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==} resolution: {integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==}
dev: true
/tslib@2.5.0: /tslib@2.5.0:
resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==}

View File

@@ -3,7 +3,9 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" /> <link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, viewport-fit=cover">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="theme-color" content="#2196f3">
%sveltekit.head% %sveltekit.head%
</head> </head>
<body data-sveltekit-preload-data="hover"> <body data-sveltekit-preload-data="hover">

View File

@@ -3,7 +3,7 @@ type PromptRequestBody = {
prompt: any, prompt: any,
extra_data: any, extra_data: any,
front: boolean, front: boolean,
number: number | null number: number | undefined
} }
export type QueueItemType = "queue" | "history"; export type QueueItemType = "queue" | "history";

View File

@@ -181,8 +181,6 @@
</div> </div>
<style lang="scss"> <style lang="scss">
@import '../../scss/shared.scss';
#container { #container {
height: calc(100vh - 60px); height: calc(100vh - 60px);
max-width: 100vw; max-width: 100vw;

View File

@@ -11,7 +11,7 @@ import type TypedEmitter from "typed-emitter";
import * as basic from "@litegraph-ts/nodes-basic" import * as basic from "@litegraph-ts/nodes-basic"
import * as nodes from "$lib/nodes/index" import * as nodes from "$lib/nodes/index"
import ComfyGraphCanvas from "$lib/ComfyGraphCanvas"; import ComfyGraphCanvas from "$lib/ComfyGraphCanvas";
import type ComfyGraphNode from "$lib/ComfyGraphNode"; import type ComfyGraphNode from "$lib/nodes/ComfyGraphNode";
import type { WidgetStateStore, WidgetUIState } from "$lib/stores/widgetState"; import type { WidgetStateStore, WidgetUIState } from "$lib/stores/widgetState";
import * as widgets from "$lib/widgets/index" import * as widgets from "$lib/widgets/index"
import type ComfyWidget from "$lib/widgets/ComfyWidget"; import type ComfyWidget from "$lib/widgets/ComfyWidget";
@@ -423,7 +423,7 @@ export default class ComfyApp {
this.clean(); this.clean();
if (!graphData) { if (!graphData) {
graphData = structuredClone(defaultGraph) as SerializedLGraph; graphData = structuredClone(defaultGraph.workflow)
} }
// Patch T2IAdapterLoader to ControlNetLoader since they are the same node now // Patch T2IAdapterLoader to ControlNetLoader since they are the same node now

View File

@@ -1,119 +1,401 @@
export default { import type SerializedAppState from "./ComfyApp"
const defaultGraph: SerializedAppState = {
createdBy: "ComfyBox",
version: 1,
workflow: {
last_node_id: 9, last_node_id: 9,
last_link_id: 9, last_link_id: 9,
nodes: [ nodes: [
{ {
id: 7, id: 7,
type: "CLIPTextEncode", type: "CLIPTextEncode",
pos: [413, 389], pos: [
size: { 0: 425.27801513671875, 1: 180.6060791015625 }, 413,
389
],
size: [
425.27801513671875,
180.6060791015625
],
flags: {}, flags: {},
order: 3, order: 3,
mode: 0, mode: 0,
inputs: [{ name: "clip", type: "CLIP", link: 5 }], inputs: [
outputs: [{ name: "CONDITIONING", type: "CONDITIONING", links: [6], slot_index: 0 }], {
name: "clip",
type: "CLIP",
link: 5
}
],
outputs: [
{
name: "CONDITIONING",
type: "CONDITIONING",
links: [
6
],
slot_index: 0
}
],
title: "CLIPTextEncode",
properties: {}, properties: {},
widgets_values: ["bad hands"], widgets_values: [
"bad hands"
]
}, },
{ {
id: 6, id: 6,
type: "CLIPTextEncode", type: "CLIPTextEncode",
pos: [415, 186], pos: [
size: { 0: 422.84503173828125, 1: 164.31304931640625 }, 415,
186
],
size: [
422.84503173828125,
164.31304931640625
],
flags: {}, flags: {},
order: 2, order: 2,
mode: 0, mode: 0,
inputs: [{ name: "clip", type: "CLIP", link: 3 }], inputs: [
outputs: [{ name: "CONDITIONING", type: "CONDITIONING", links: [4], slot_index: 0 }], {
name: "clip",
type: "CLIP",
link: 3
}
],
outputs: [
{
name: "CONDITIONING",
type: "CONDITIONING",
links: [
4
],
slot_index: 0
}
],
title: "CLIPTextEncode",
properties: {}, properties: {},
widgets_values: ["masterpiece best quality girl"], widgets_values: [
"masterpiece best quality girl"
]
}, },
{ {
id: 5, id: 5,
type: "EmptyLatentImage", type: "EmptyLatentImage",
pos: [473, 609], pos: [
size: { 0: 315, 1: 106 }, 473,
609
],
size: [
315,
106
],
flags: {}, flags: {},
order: 1, order: 0,
mode: 0, mode: 0,
outputs: [{ name: "LATENT", type: "LATENT", links: [2], slot_index: 0 }], inputs: [],
outputs: [
{
name: "LATENT",
type: "LATENT",
links: [
2
],
slot_index: 0
}
],
title: "EmptyLatentImage",
properties: {}, properties: {},
widgets_values: [512, 512, 1], widgets_values: [
512,
512,
1
]
}, },
{ {
id: 3, id: 3,
type: "KSampler", type: "KSampler",
pos: [863, 186], pos: [
size: { 0: 315, 1: 262 }, 863,
186
],
size: [
315,
262
],
flags: {}, flags: {},
order: 4, order: 4,
mode: 0, mode: 0,
inputs: [ inputs: [
{ name: "model", type: "MODEL", link: 1 }, {
{ name: "positive", type: "CONDITIONING", link: 4 }, name: "model",
{ name: "negative", type: "CONDITIONING", link: 6 }, type: "MODEL",
{ name: "latent_image", type: "LATENT", link: 2 }, link: 1
},
{
name: "positive",
type: "CONDITIONING",
link: 4
},
{
name: "negative",
type: "CONDITIONING",
link: 6
},
{
name: "latent_image",
type: "LATENT",
link: 2
}
], ],
outputs: [{ name: "LATENT", type: "LATENT", links: [7], slot_index: 0 }], outputs: [
{
name: "LATENT",
type: "LATENT",
links: [
7
],
slot_index: 0
}
],
title: "KSampler",
properties: {}, properties: {},
widgets_values: [8566257, 20, 8, "euler", "normal", 1], widgets_values: [
8566257,
"randomize",
8,
8,
"euler",
"normal",
1
]
}, },
{ {
id: 8, id: 8,
type: "VAEDecode", type: "VAEDecode",
pos: [1209, 188], pos: [
size: { 0: 210, 1: 46 }, 1209,
188
],
size: [
210,
46
],
flags: {}, flags: {},
order: 5, order: 5,
mode: 0, mode: 0,
inputs: [ inputs: [
{ name: "samples", type: "LATENT", link: 7 }, {
{ name: "vae", type: "VAE", link: 8 }, name: "samples",
type: "LATENT",
link: 7
},
{
name: "vae",
type: "VAE",
link: 8
}
], ],
outputs: [{ name: "IMAGE", type: "IMAGE", links: [9], slot_index: 0 }], outputs: [
properties: {}, {
name: "IMAGE",
type: "IMAGE",
links: [
9
],
slot_index: 0
}
],
title: "VAEDecode",
properties: {}
}, },
{ {
id: 9, id: 9,
type: "SaveImage", type: "SaveImage",
pos: [1451, 189], pos: [
size: { 0: 210, 1: 26 }, 1451,
189
],
size: [
210,
82
],
flags: {}, flags: {},
order: 6, order: 6,
mode: 0, mode: 0,
inputs: [{ name: "images", type: "IMAGE", link: 9 }], inputs: [
{
name: "images",
type: "IMAGE",
link: 9
}
],
outputs: [],
title: "SaveImage",
properties: {}, properties: {},
widgets_values: [
[],
"ComfyUI"
]
}, },
{ {
id: 4, id: 4,
type: "CheckpointLoaderSimple", type: "CheckpointLoaderSimple",
pos: [26, 474], pos: [
size: { 0: 315, 1: 98 }, 26,
flags: {}, 474
order: 0,
mode: 0,
outputs: [
{ name: "MODEL", type: "MODEL", links: [1], slot_index: 0 },
{ name: "CLIP", type: "CLIP", links: [3, 5], slot_index: 1 },
{ name: "VAE", type: "VAE", links: [8], slot_index: 2 },
], ],
properties: {}, size: [
widgets_values: ["v1-5-pruned-emaonly.ckpt"], 315,
98
],
flags: {},
order: 1,
mode: 0,
inputs: [],
outputs: [
{
name: "MODEL",
type: "MODEL",
links: [
1
],
slot_index: 0
}, },
{
name: "CLIP",
type: "CLIP",
links: [
3,
5
],
slot_index: 1
},
{
name: "VAE",
type: "VAE",
links: [
8
],
slot_index: 2
}
],
title: "CheckpointLoaderSimple",
properties: {},
widgets_values: [
"v1-5-pruned-emaonly.ckpt"
]
}
], ],
links: [ links: [
[1, 4, 0, 3, 0, "MODEL"], [
[2, 5, 0, 3, 3, "LATENT"], 1,
[3, 4, 1, 6, 0, "CLIP"], 4,
[4, 6, 0, 3, 1, "CONDITIONING"], 0,
[5, 4, 1, 7, 0, "CLIP"], 3,
[6, 7, 0, 3, 2, "CONDITIONING"], 0,
[7, 3, 0, 8, 0, "LATENT"], "MODEL"
[8, 4, 2, 8, 1, "VAE"], ],
[9, 8, 0, 9, 0, "IMAGE"], [
2,
5,
0,
3,
3,
"LATENT"
],
[
3,
4,
1,
6,
0,
"CLIP"
],
[
4,
6,
0,
3,
1,
"CONDITIONING"
],
[
5,
4,
1,
7,
0,
"CLIP"
],
[
6,
7,
0,
3,
2,
"CONDITIONING"
],
[
7,
3,
0,
8,
0,
"LATENT"
],
[
8,
4,
2,
8,
1,
"VAE"
],
[
9,
8,
0,
9,
0,
"IMAGE"
]
], ],
groups: [], groups: [],
config: {}, config: {},
extra: {}, extra: {},
version: 0.4, version: 10
}; },
panes: {
panels: [
[
{
nodeId: 7
},
{
nodeId: 3
}
],
[
{
nodeId: 6
},
{
nodeId: 9
},
{
nodeId: 4
}
],
[
{
nodeId: 5
}
]
]
}
}
export default defaultGraph;

View File

@@ -101,8 +101,7 @@ function configureFinished(graph: LGraph) {
state[node.id][i].value.set(value); state[node.id][i].value.set(value);
} }
else { else {
console.error("Mismatch in widgets_values!", node.id, node.type, state[node.id].map(i => get(i.value)), node.widgets_values) console.log("Skip virtual widget", node.id, node.type, state[node.id][i].widget)
break;
} }
} }
} }

View File

@@ -21,7 +21,7 @@
</script> </script>
<div class="wrapper"> <div class="wrapper">
{#if item && option} {#if item !== null && option !== undefined}
<label> <label>
<BlockTitle show_label={true}>{item.widget.name}</BlockTitle> <BlockTitle show_label={true}>{item.widget.name}</BlockTitle>
<Select <Select

View File

@@ -1,11 +1,15 @@
<script lang="ts"> <script lang="ts">
import type { WidgetUIState, WidgetUIStateStore } from "$lib/stores/widgetState"; import type { WidgetUIState, WidgetUIStateStore } from "$lib/stores/widgetState";
import { Range } from "@gradio/form"; import { Range } from "framework7-svelte";
import { BlockTitle } from "@gradio/atoms";
import { createEventDispatcher } from "svelte"
import { get } from "svelte/store"; import { get } from "svelte/store";
export let item: WidgetUIState | null = null; export let item: WidgetUIState | null = null;
let itemValue: WidgetUIStateStore | null = null; let itemValue: WidgetUIStateStore | null = null;
let option: number | null = null; let option: number | null = null;
const dispatch = createEventDispatcher();
$: if (item) { $: if (item) {
itemValue = item.value; itemValue = item.value;
updateOption(); // don't react on option updateOption(); // don't react on option
@@ -15,29 +19,89 @@
option = get(itemValue); option = get(itemValue);
} }
function onRelease(e: Event) { function onMouseup(value: number) {
if (itemValue && option) {
$itemValue = option $itemValue = option
} }
function onChange(e: Event) {
option = e.detail[0]
} }
function onRelease(e: Event) {
option = e.detail[0]
$itemValue = option
}
const clamp = () => {
if (itemValue && option) {
onMouseup();
option = Math.min(Math.max(option, item.widget.options.min), item.widget.options.max);
}
};
</script> </script>
<div class="wrapper"> <div class="wrapper">
{#if item && option} {#if item !== null && option !== undefined}
<div class="wrap">
<div class="head">
<BlockTitle>{item.widget.name}</BlockTitle>
<input
type="number"
bind:value={option}
min={item.widget.options.min}
max={item.widget.options.max}
step={item.widget.options.step}
on:blur={clamp}
on:mouseup={onMouseup}
/>
</div>
</div>
<Range <Range
bind:value={option} bind:value={option}
minimum={item.widget.options.min} min={item.widget.options.min}
maximum={item.widget.options.max} max={item.widget.options.max}
step={item.widget.options.step} step={item.widget.options.step}
label={item.widget.name} label={false}
show_label={true} on:rangeChanged={onRelease}
on:release={onRelease} on:rangeChange={onChange}
on:change
/> />
{/if} {/if}
</div> </div>
<style> <style>
.wrap {
display: flex;
flex-direction: column;
width: 100%;
}
.head {
display: flex;
justify-content: space-between;
}
input[type="number"] {
display: block;
position: relative;
outline: none !important;
box-shadow: var(--input-shadow);
border: var(--input-border-width) solid var(--input-border-color);
border-radius: var(--input-radius);
background: var(--input-background-fill);
padding: var(--size-2) var(--size-2);
height: var(--size-6);
color: var(--body-text-color);
font-size: var(--input-text-size);
line-height: var(--line-sm);
text-align: center;
}
input::placeholder {
color: var(--input-placeholder-color);
}
input[type="number"]:focus {
box-shadow: var(--input-shadow-focus);
border-color: var(--input-border-color-focus);
}
.wrapper { .wrapper {
padding: 2px; padding: 2px;
width: 100%; width: 100%;

View File

@@ -7,7 +7,7 @@
</script> </script>
<div class="wrapper"> <div class="wrapper">
{#if item && itemValue} {#if item !== null && itemValue !== null}
<TextBox <TextBox
bind:value={$itemValue} bind:value={$itemValue}
label={item.widget.name} label={item.widget.name}

View File

@@ -1,9 +1,22 @@
<script lang="ts"> <script lang="ts">
import ComfyApp from "$lib/components/ComfyApp.svelte" import ComfyApp from "$lib/components/ComfyApp.svelte"
import "@litegraph-ts/core/css/litegraph.css"; import "@litegraph-ts/core/css/litegraph.css";
import "framework7/css/bundle";
import "../scss/global.scss";
import { onMount } from 'svelte';
import { f7, f7ready, App } from 'framework7-svelte';
onMount(() => {
f7ready(() => {
// Framework7 initialized
f7.theme = "ios";
})
})
</script> </script>
<App>
<ComfyApp/> <ComfyApp/>
</App>
<style> <style>
:root { :root {

View File

@@ -1,5 +1,10 @@
import type { PageLoad } from "./$types" import type { PageLoad } from "./$types"
import Framework7 from 'framework7/lite-bundle';
import Framework7Svelte from 'framework7-svelte';
Framework7.use(Framework7Svelte)
// `PageServerData` will contain everything from the layouts and also the // `PageServerData` will contain everything from the layouts and also the
// `data` from the `+page.server.ts` file. // `data` from the `+page.server.ts` file.
type OutputProps = {} type OutputProps = {}

8
src/scss/global.scss Normal file
View File

@@ -0,0 +1,8 @@
button {
width: auto !important;
}
:root {
--f7-block-margin-vertical: 10px;
--f7-block-padding-horizontal: 0px;
}

View File

View File

@@ -14,7 +14,7 @@ const config = {
compilerOptions: { compilerOptions: {
debug: true, debug: true,
} }
} },
}) })
] ]
}; };

View File

@@ -8,7 +8,7 @@ export default defineConfig({
plugins: [ plugins: [
// tsconfigPaths({ loose: true }), // tsconfigPaths({ loose: true }),
sveltekit(), sveltekit(),
FullReload(["src/**/*.{js,ts,svelte}"]) // FullReload(["src/**/*.{js,ts,svelte}"])
], ],
build: { build: {
sourcemap: true, sourcemap: true,