mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-01-26 10:59:53 +00:00
Lint: Add tailwind linter (#5984)
## Summary Adds the [tailwind lint plugin](https://github.com/francoismassart/eslint-plugin-tailwindcss/?tab=readme-ov-file#eslint-plugin-tailwindcss) and fixes the currently fixable rules ([v4 is still in beta](https://github.com/francoismassart/eslint-plugin-tailwindcss/?tab=readme-ov-file#about-tailwind-css-4-support)). ## Changes - **What**: Enforces things like consistent class order, and eventually can prohibit extra classes that could be utilities instead - **Dependencies**: The plugin and its types ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5984-Lint-Add-tailwind-linter-2866d73d365081d89db0d998232533bb) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
@@ -4,36 +4,67 @@ import pluginI18n from '@intlify/eslint-plugin-vue-i18n'
|
||||
import { importX } from 'eslint-plugin-import-x'
|
||||
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
|
||||
import storybook from 'eslint-plugin-storybook'
|
||||
import tailwind from 'eslint-plugin-tailwindcss'
|
||||
import unusedImports from 'eslint-plugin-unused-imports'
|
||||
import pluginVue from 'eslint-plugin-vue'
|
||||
import { defineConfig } from 'eslint/config'
|
||||
import globals from 'globals'
|
||||
import tseslint from 'typescript-eslint'
|
||||
import {
|
||||
configs as tseslintConfigs,
|
||||
parser as tseslintParser
|
||||
} from 'typescript-eslint'
|
||||
import vueParser from 'vue-eslint-parser'
|
||||
|
||||
const extraFileExtensions = ['.vue']
|
||||
|
||||
const commonGlobals = {
|
||||
...globals.browser,
|
||||
__COMFYUI_FRONTEND_VERSION__: 'readonly'
|
||||
} as const
|
||||
|
||||
const settings = {
|
||||
'import/resolver': {
|
||||
typescript: true,
|
||||
node: true
|
||||
},
|
||||
tailwindcss: {
|
||||
config: `${import.meta.dirname}/packages/design-system/src/css/style.css`,
|
||||
functions: ['cn', 'clsx', 'tw']
|
||||
}
|
||||
} as const
|
||||
|
||||
const commonParserOptions = {
|
||||
parser: tseslintParser,
|
||||
projectService: true,
|
||||
tsConfigRootDir: import.meta.dirname,
|
||||
ecmaVersion: 2020,
|
||||
sourceType: 'module',
|
||||
extraFileExtensions
|
||||
} as const
|
||||
|
||||
export default defineConfig([
|
||||
{
|
||||
ignores: [
|
||||
'src/scripts/*',
|
||||
'src/extensions/core/*',
|
||||
'src/types/vue-shim.d.ts',
|
||||
'packages/registry-types/src/comfyRegistryTypes.ts',
|
||||
'src/types/generatedManagerTypes.ts',
|
||||
'.i18nrc.cjs',
|
||||
'components.d.ts',
|
||||
'lint-staged.config.js',
|
||||
'vitest.setup.ts',
|
||||
'**/vite.config.*.timestamp*',
|
||||
'**/vitest.config.*.timestamp*'
|
||||
'**/vitest.config.*.timestamp*',
|
||||
'packages/registry-types/src/comfyRegistryTypes.ts',
|
||||
'src/extensions/core/*',
|
||||
'src/scripts/*',
|
||||
'src/types/generatedManagerTypes.ts',
|
||||
'src/types/vue-shim.d.ts'
|
||||
]
|
||||
},
|
||||
{
|
||||
files: ['./**/*.{ts,mts}'],
|
||||
settings,
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
__COMFYUI_FRONTEND_VERSION__: 'readonly'
|
||||
},
|
||||
globals: commonGlobals,
|
||||
parserOptions: {
|
||||
parser: tseslint.parser,
|
||||
...commonParserOptions,
|
||||
projectService: {
|
||||
allowDefaultProject: [
|
||||
'vite.config.mts',
|
||||
@@ -42,47 +73,26 @@ export default defineConfig([
|
||||
'playwright.config.ts',
|
||||
'playwright.i18n.config.ts'
|
||||
]
|
||||
},
|
||||
tsConfigRootDir: import.meta.dirname,
|
||||
ecmaVersion: 2020,
|
||||
sourceType: 'module',
|
||||
extraFileExtensions
|
||||
}
|
||||
},
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
typescript: true,
|
||||
node: true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['./**/*.vue'],
|
||||
settings,
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
__COMFYUI_FRONTEND_VERSION__: 'readonly'
|
||||
},
|
||||
globals: commonGlobals,
|
||||
parser: vueParser,
|
||||
parserOptions: {
|
||||
parser: tseslint.parser,
|
||||
projectService: true,
|
||||
tsConfigRootDir: import.meta.dirname,
|
||||
ecmaVersion: 2020,
|
||||
sourceType: 'module',
|
||||
extraFileExtensions
|
||||
}
|
||||
},
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
typescript: true,
|
||||
node: true
|
||||
}
|
||||
parserOptions: commonParserOptions
|
||||
}
|
||||
},
|
||||
pluginJs.configs.recommended,
|
||||
// eslint-disable-next-line import-x/no-named-as-default-member
|
||||
tseslint.configs.recommended,
|
||||
|
||||
tseslintConfigs.recommended,
|
||||
// Difference in typecheck on CI vs Local
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore Bad types in the plugin
|
||||
tailwind.configs['flat/recommended'],
|
||||
pluginVue.configs['flat/recommended'],
|
||||
eslintPluginPrettierRecommended,
|
||||
storybook.configs['flat/recommended'],
|
||||
@@ -114,6 +124,7 @@ export default defineConfig([
|
||||
'import-x/no-relative-packages': 'error',
|
||||
'unused-imports/no-unused-imports': 'error',
|
||||
'no-console': ['error', { allow: ['warn', 'error'] }],
|
||||
'tailwindcss/no-custom-classname': 'off', // TODO: fix
|
||||
'vue/no-v-html': 'off',
|
||||
// Enforce dark-theme: instead of dark: prefix
|
||||
'vue/no-restricted-class': ['error', '/^dark:/'],
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
"@storybook/vue3-vite": "catalog:",
|
||||
"@tailwindcss/vite": "catalog:",
|
||||
"@trivago/prettier-plugin-sort-imports": "catalog:",
|
||||
"@types/eslint-plugin-tailwindcss": "catalog:",
|
||||
"@types/fs-extra": "catalog:",
|
||||
"@types/jsdom": "catalog:",
|
||||
"@types/node": "catalog:",
|
||||
@@ -73,6 +74,7 @@
|
||||
"eslint-plugin-import-x": "catalog:",
|
||||
"eslint-plugin-prettier": "catalog:",
|
||||
"eslint-plugin-storybook": "catalog:",
|
||||
"eslint-plugin-tailwindcss": "catalog:",
|
||||
"eslint-plugin-unused-imports": "catalog:",
|
||||
"eslint-plugin-vue": "catalog:",
|
||||
"fs-extra": "^11.2.0",
|
||||
|
||||
50
pnpm-lock.yaml
generated
50
pnpm-lock.yaml
generated
@@ -84,6 +84,9 @@ catalogs:
|
||||
'@trivago/prettier-plugin-sort-imports':
|
||||
specifier: ^5.2.0
|
||||
version: 5.2.2
|
||||
'@types/eslint-plugin-tailwindcss':
|
||||
specifier: ^3.17.0
|
||||
version: 3.17.0
|
||||
'@types/fs-extra':
|
||||
specifier: ^11.0.4
|
||||
version: 11.0.4
|
||||
@@ -147,6 +150,9 @@ catalogs:
|
||||
eslint-plugin-storybook:
|
||||
specifier: ^9.1.6
|
||||
version: 9.1.6
|
||||
eslint-plugin-tailwindcss:
|
||||
specifier: 4.0.0-beta.0
|
||||
version: 4.0.0-beta.0
|
||||
eslint-plugin-unused-imports:
|
||||
specifier: ^4.2.0
|
||||
version: 4.2.0
|
||||
@@ -274,6 +280,9 @@ catalogs:
|
||||
specifier: ^3.3.0
|
||||
version: 3.3.0
|
||||
|
||||
overrides:
|
||||
'@types/eslint': '-'
|
||||
|
||||
importers:
|
||||
|
||||
.:
|
||||
@@ -489,6 +498,9 @@ importers:
|
||||
'@trivago/prettier-plugin-sort-imports':
|
||||
specifier: 'catalog:'
|
||||
version: 5.2.2(@vue/compiler-sfc@3.5.13)(prettier@3.3.2)
|
||||
'@types/eslint-plugin-tailwindcss':
|
||||
specifier: 'catalog:'
|
||||
version: 3.17.0
|
||||
'@types/fs-extra':
|
||||
specifier: 'catalog:'
|
||||
version: 11.0.4
|
||||
@@ -537,6 +549,9 @@ importers:
|
||||
eslint-plugin-storybook:
|
||||
specifier: 'catalog:'
|
||||
version: 9.1.6(eslint@9.35.0(jiti@2.4.2))(storybook@9.1.6(@testing-library/dom@10.4.1)(prettier@3.3.2)(vite@5.4.19(@types/node@20.14.10)(lightningcss@1.30.1)(terser@5.39.2)))(typescript@5.9.2)
|
||||
eslint-plugin-tailwindcss:
|
||||
specifier: 'catalog:'
|
||||
version: 4.0.0-beta.0(tailwindcss@4.1.12)
|
||||
eslint-plugin-unused-imports:
|
||||
specifier: 'catalog:'
|
||||
version: 4.2.0(@typescript-eslint/eslint-plugin@8.44.0(@typescript-eslint/parser@8.44.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.35.0(jiti@2.4.2))
|
||||
@@ -2990,6 +3005,9 @@ packages:
|
||||
'@types/diff-match-patch@1.0.36':
|
||||
resolution: {integrity: sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==}
|
||||
|
||||
'@types/eslint-plugin-tailwindcss@3.17.0':
|
||||
resolution: {integrity: sha512-ucQGf2YIdTcndYcxRU3UdZgmhUHsOlbIF4BaRtl0op+7k2JmqM2i3aXZ6XIcfZgVq1ZKov7VM5c/BR81ukmkyg==}
|
||||
|
||||
'@types/estree@1.0.5':
|
||||
resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
|
||||
|
||||
@@ -4508,7 +4526,7 @@ packages:
|
||||
resolution: {integrity: sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
'@types/eslint': '>=8.0.0'
|
||||
'@types/eslint': '*'
|
||||
eslint: '>=8.0.0'
|
||||
eslint-config-prettier: '>= 7.0.0 <10.0.0 || >=10.1.0'
|
||||
prettier: '>=3.0.0'
|
||||
@@ -4525,6 +4543,12 @@ packages:
|
||||
eslint: '>=8'
|
||||
storybook: ^9.1.6
|
||||
|
||||
eslint-plugin-tailwindcss@4.0.0-beta.0:
|
||||
resolution: {integrity: sha512-WWCajZgQu38Sd67ZCl2W6i3MRzqB0d+H8s4qV9iB6lBJbsDOIpIlj6R1Fj2FXkoWErbo05pZnZYbCGIU9o/DsA==}
|
||||
engines: {node: '>=18.12.0'}
|
||||
peerDependencies:
|
||||
tailwindcss: ^3.4.0 || ^4.0.0
|
||||
|
||||
eslint-plugin-unused-imports@4.2.0:
|
||||
resolution: {integrity: sha512-hLbJ2/wnjKq4kGA9AUaExVFIbNzyxYdVo49QZmKCnhk5pc9wcYRbfgLHvWJ8tnsdcseGhoUAddm9gn/lt+d74w==}
|
||||
peerDependencies:
|
||||
@@ -6966,6 +6990,11 @@ packages:
|
||||
resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
|
||||
tailwind-api-utils@1.0.3:
|
||||
resolution: {integrity: sha512-KpzUHkH1ug1sq4394SLJX38ZtpeTiqQ1RVyFTTSY2XuHsNSTWUkRo108KmyyrMWdDbQrLYkSHaNKj/a3bmA4sQ==}
|
||||
peerDependencies:
|
||||
tailwindcss: ^3.3.0 || ^4.0.0 || ^4.0.0-beta
|
||||
|
||||
tailwind-merge@2.6.0:
|
||||
resolution: {integrity: sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==}
|
||||
|
||||
@@ -10336,6 +10365,8 @@ snapshots:
|
||||
|
||||
'@types/diff-match-patch@1.0.36': {}
|
||||
|
||||
'@types/eslint-plugin-tailwindcss@3.17.0': {}
|
||||
|
||||
'@types/estree@1.0.5': {}
|
||||
|
||||
'@types/estree@1.0.8': {}
|
||||
@@ -10748,7 +10779,7 @@ snapshots:
|
||||
'@vue/shared': 3.5.13
|
||||
estree-walker: 2.0.2
|
||||
magic-string: 0.30.19
|
||||
postcss: 8.5.1
|
||||
postcss: 8.5.6
|
||||
source-map-js: 1.2.1
|
||||
|
||||
'@vue/compiler-ssr@3.5.13':
|
||||
@@ -12097,6 +12128,14 @@ snapshots:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
eslint-plugin-tailwindcss@4.0.0-beta.0(tailwindcss@4.1.12):
|
||||
dependencies:
|
||||
fast-glob: 3.3.3
|
||||
postcss: 8.5.6
|
||||
synckit: 0.11.11
|
||||
tailwind-api-utils: 1.0.3(tailwindcss@4.1.12)
|
||||
tailwindcss: 4.1.12
|
||||
|
||||
eslint-plugin-unused-imports@4.2.0(@typescript-eslint/eslint-plugin@8.44.0(@typescript-eslint/parser@8.44.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.35.0(jiti@2.4.2)):
|
||||
dependencies:
|
||||
eslint: 9.35.0(jiti@2.4.2)
|
||||
@@ -15115,6 +15154,13 @@ snapshots:
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
|
||||
tailwind-api-utils@1.0.3(tailwindcss@4.1.12):
|
||||
dependencies:
|
||||
enhanced-resolve: 5.18.3
|
||||
jiti: 2.5.1
|
||||
local-pkg: 1.1.2
|
||||
tailwindcss: 4.1.12
|
||||
|
||||
tailwind-merge@2.6.0: {}
|
||||
|
||||
tailwindcss-primeui@0.6.1(tailwindcss@4.1.12):
|
||||
|
||||
@@ -29,6 +29,7 @@ catalog:
|
||||
'@storybook/vue3-vite': ^9.1.1
|
||||
'@tailwindcss/vite': ^4.1.12
|
||||
'@trivago/prettier-plugin-sort-imports': ^5.2.0
|
||||
'@types/eslint-plugin-tailwindcss': ^3.17.0
|
||||
'@types/fs-extra': ^11.0.4
|
||||
'@types/jsdom': ^21.1.7
|
||||
'@types/node': ^20.14.8
|
||||
@@ -50,6 +51,7 @@ catalog:
|
||||
eslint-plugin-import-x: ^4.16.1
|
||||
eslint-plugin-prettier: ^5.5.4
|
||||
eslint-plugin-storybook: ^9.1.6
|
||||
eslint-plugin-tailwindcss: 4.0.0-beta.0
|
||||
eslint-plugin-unused-imports: ^4.2.0
|
||||
eslint-plugin-vue: ^10.4.0
|
||||
firebase: ^11.6.0
|
||||
@@ -95,6 +97,9 @@ catalog:
|
||||
|
||||
cleanupUnusedCatalogs: true
|
||||
|
||||
overrides:
|
||||
'@types/eslint': '-'
|
||||
|
||||
ignoredBuiltDependencies:
|
||||
- '@firebase/util'
|
||||
- protobufjs
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<router-view />
|
||||
<ProgressSpinner
|
||||
v-if="isLoading"
|
||||
class="absolute inset-0 flex justify-center items-center h-[unset]"
|
||||
class="absolute inset-0 flex h-[unset] items-center justify-center"
|
||||
/>
|
||||
<GlobalDialog />
|
||||
<BlockUI full-screen :blocked="isLoading" />
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<template>
|
||||
<div class="flex flex-col h-full">
|
||||
<div class="flex h-full flex-col">
|
||||
<Tabs
|
||||
:key="$i18n.locale"
|
||||
v-model:value="bottomPanelStore.activeBottomPanelTabId"
|
||||
>
|
||||
<TabList pt:tab-list="border-none">
|
||||
<div class="w-full flex justify-between">
|
||||
<div class="flex w-full justify-between">
|
||||
<div class="tabs-container">
|
||||
<Tab
|
||||
v-for="tab in bottomPanelStore.bottomPanelTabs"
|
||||
:key="tab.id"
|
||||
:value="tab.id"
|
||||
class="p-3 border-none"
|
||||
class="border-none p-3"
|
||||
>
|
||||
<span class="font-bold">
|
||||
{{ getTabDisplayTitle(tab) }}
|
||||
@@ -41,7 +41,7 @@
|
||||
</TabList>
|
||||
</Tabs>
|
||||
<!-- h-0 to force the div to grow -->
|
||||
<div class="grow h-0">
|
||||
<div class="h-0 grow">
|
||||
<ExtensionSlot
|
||||
v-if="
|
||||
bottomPanelStore.bottomPanelVisible &&
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="h-full flex flex-col p-4">
|
||||
<div class="flex-1 min-h-0 overflow-auto">
|
||||
<div class="flex h-full flex-col p-4">
|
||||
<div class="min-h-0 flex-1 overflow-auto">
|
||||
<ShortcutsList
|
||||
:commands="essentialsCommands"
|
||||
:subcategories="essentialsSubcategories"
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<template>
|
||||
<div class="shortcuts-list flex justify-center">
|
||||
<div class="grid gap-4 md:gap-24 h-full grid-cols-1 md:grid-cols-3 w-[90%]">
|
||||
<div class="grid h-full w-[90%] grid-cols-1 gap-4 md:grid-cols-3 md:gap-24">
|
||||
<div
|
||||
v-for="(subcategoryCommands, subcategory) in filteredSubcategories"
|
||||
:key="subcategory"
|
||||
class="flex flex-col"
|
||||
>
|
||||
<h3
|
||||
class="subcategory-title text-xs font-bold uppercase tracking-wide text-surface-600 dark-theme:text-surface-400 mb-4"
|
||||
class="subcategory-title mb-4 text-xs font-bold tracking-wide text-surface-600 uppercase dark-theme:text-surface-400"
|
||||
>
|
||||
{{ getSubcategoryTitle(subcategory) }}
|
||||
</h3>
|
||||
@@ -16,7 +16,7 @@
|
||||
<div
|
||||
v-for="command in subcategoryCommands"
|
||||
:key="command.id"
|
||||
class="shortcut-item flex justify-between items-center py-2 rounded hover:bg-surface-100 dark-theme:hover:bg-surface-700 transition-colors duration-200"
|
||||
class="shortcut-item flex items-center justify-between rounded py-2 transition-colors duration-200 hover:bg-surface-100 dark-theme:hover:bg-surface-700"
|
||||
>
|
||||
<div class="shortcut-info grow pr-4">
|
||||
<div class="shortcut-name text-sm font-medium">
|
||||
@@ -32,7 +32,7 @@
|
||||
<span
|
||||
v-for="key in command.keybinding!.combo.getKeySequences()"
|
||||
:key="key"
|
||||
class="key-badge px-2 py-1 text-xs font-mono bg-surface-200 dark-theme:bg-surface-600 rounded border min-w-6 text-center"
|
||||
class="key-badge min-w-6 rounded border bg-surface-200 px-2 py-1 text-center font-mono text-xs dark-theme:bg-surface-600"
|
||||
>
|
||||
{{ formatKey(key) }}
|
||||
</span>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="h-full flex flex-col p-4">
|
||||
<div class="flex-1 min-h-0 overflow-auto">
|
||||
<div class="flex h-full flex-col p-4">
|
||||
<div class="min-h-0 flex-1 overflow-auto">
|
||||
<ShortcutsList
|
||||
:commands="viewControlsCommands"
|
||||
:subcategories="viewControlsSubcategories"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<div
|
||||
ref="rootEl"
|
||||
class="relative overflow-hidden h-full w-full bg-neutral-900"
|
||||
class="relative h-full w-full overflow-hidden bg-neutral-900"
|
||||
>
|
||||
<div class="p-terminal rounded-none h-full w-full p-2">
|
||||
<div ref="terminalEl" class="h-full terminal-host" />
|
||||
<div class="p-terminal h-full w-full rounded-none p-2">
|
||||
<div ref="terminalEl" class="terminal-host h-full" />
|
||||
</div>
|
||||
<Button
|
||||
v-tooltip.left="{
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div class="bg-black h-full w-full">
|
||||
<div class="h-full w-full bg-black">
|
||||
<p v-if="errorMessage" class="p-4 text-center">
|
||||
{{ errorMessage }}
|
||||
</p>
|
||||
<ProgressSpinner
|
||||
v-else-if="loading"
|
||||
class="relative inset-0 flex justify-center items-center h-full z-10"
|
||||
class="relative inset-0 z-10 flex h-full items-center justify-center"
|
||||
/>
|
||||
<BaseTerminal v-show="!loading" @created="terminalCreated" />
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
showDelay: 512
|
||||
}"
|
||||
href="#"
|
||||
class="cursor-pointer p-breadcrumb-item-link"
|
||||
class="p-breadcrumb-item-link cursor-pointer"
|
||||
:class="{
|
||||
'flex items-center gap-1': isActive,
|
||||
'p-breadcrumb-item-link-menu-visible': menu?.overlayVisible,
|
||||
@@ -37,7 +37,7 @@
|
||||
v-if="isEditing"
|
||||
ref="itemInputRef"
|
||||
v-model="itemLabel"
|
||||
class="fixed z-10000 text-[.8rem] px-2 py-2"
|
||||
class="fixed z-10000 px-2 py-2 text-[.8rem]"
|
||||
@blur="inputBlur(true)"
|
||||
@click.stop
|
||||
@keydown.enter="inputBlur(true)"
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
unstyled
|
||||
:pt="pt"
|
||||
>
|
||||
<div class="flex flex-col gap-2 p-2 min-w-40">
|
||||
<div class="flex min-w-40 flex-col gap-2 p-2">
|
||||
<slot :close="hide" />
|
||||
</div>
|
||||
</Popover>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="text-zinc-500 dark-theme:text-zinc-400 text-xs line-clamp-2 h-7">
|
||||
<div class="line-clamp-2 h-7 text-xs text-zinc-500 dark-theme:text-zinc-400">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
<template>
|
||||
<div :class="topStyle">
|
||||
<slot class="absolute top-0 left-0 w-full h-full"></slot>
|
||||
<slot class="absolute top-0 left-0 h-full w-full"></slot>
|
||||
|
||||
<div
|
||||
v-if="slots['top-left']"
|
||||
class="absolute top-2 left-2 flex gap-2 flex-wrap justify-start"
|
||||
class="absolute top-2 left-2 flex flex-wrap justify-start gap-2"
|
||||
>
|
||||
<slot name="top-left"></slot>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="slots['top-right']"
|
||||
class="absolute top-2 right-2 flex gap-2 flex-wrap justify-end"
|
||||
class="absolute top-2 right-2 flex flex-wrap justify-end gap-2"
|
||||
>
|
||||
<slot name="top-right"></slot>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="slots['bottom-left']"
|
||||
class="absolute bottom-2 left-2 flex gap-2 flex-wrap justify-start"
|
||||
class="absolute bottom-2 left-2 flex flex-wrap justify-start gap-2"
|
||||
>
|
||||
<slot name="bottom-left"></slot>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="slots['bottom-right']"
|
||||
class="absolute bottom-2 right-2 flex gap-2 flex-wrap justify-end"
|
||||
class="absolute right-2 bottom-2 flex flex-wrap justify-end gap-2"
|
||||
>
|
||||
<slot name="bottom-right"></slot>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div
|
||||
class="inline-flex justify-center items-center gap-1 shrink-0 py-1 px-2 text-xs bg-[#D9D9D966]/40 rounded font-bold text-white/90"
|
||||
class="inline-flex shrink-0 items-center justify-center gap-1 rounded bg-[#D9D9D966]/40 px-2 py-1 text-xs font-bold text-white/90"
|
||||
>
|
||||
<slot name="icon" class="text-xs text-white/90"></slot>
|
||||
<span>{{ label }}</span>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
icon="pi pi-exclamation-triangle"
|
||||
size="small"
|
||||
variant="outlined"
|
||||
class="h-min my-2 px-1 max-w-xs"
|
||||
class="my-2 h-min max-w-xs px-1"
|
||||
:title="props.error"
|
||||
:pt="{
|
||||
text: { class: 'overflow-hidden text-ellipsis' }
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
<template>
|
||||
<div class="image-upload-wrapper">
|
||||
<div class="flex gap-2 items-center">
|
||||
<div class="flex items-center gap-2">
|
||||
<div
|
||||
class="preview-box border rounded p-2 w-16 h-16 flex items-center justify-center"
|
||||
class="preview-box flex h-16 w-16 items-center justify-center rounded border p-2"
|
||||
:class="{ 'bg-gray-100 dark-theme:bg-gray-800': !modelValue }"
|
||||
>
|
||||
<img
|
||||
v-if="modelValue"
|
||||
:src="modelValue"
|
||||
class="max-w-full max-h-full object-contain"
|
||||
class="max-h-full max-w-full object-contain"
|
||||
/>
|
||||
<i v-else class="pi pi-image text-gray-400 text-xl" />
|
||||
<i v-else class="pi pi-image text-xl text-gray-400" />
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div
|
||||
ref="containerRef"
|
||||
class="relative overflow-hidden w-full h-full flex items-center justify-center"
|
||||
class="relative flex h-full w-full items-center justify-center overflow-hidden"
|
||||
>
|
||||
<Skeleton
|
||||
v-if="!isImageLoaded"
|
||||
@@ -22,7 +22,7 @@
|
||||
/>
|
||||
<div
|
||||
v-if="hasError"
|
||||
class="absolute inset-0 flex items-center justify-center bg-surface-50 dark-theme:bg-surface-800 text-muted"
|
||||
class="absolute inset-0 flex items-center justify-center bg-surface-50 text-muted dark-theme:bg-surface-800"
|
||||
>
|
||||
<img
|
||||
src="/assets/images/default-template.png"
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div class="no-results-placeholder p-8 h-full" :class="props.class">
|
||||
<div class="no-results-placeholder h-full p-8" :class="props.class">
|
||||
<Card>
|
||||
<template #content>
|
||||
<div class="flex flex-col items-center">
|
||||
<i :class="icon" style="font-size: 3rem; margin-bottom: 1rem" />
|
||||
<h3>{{ title }}</h3>
|
||||
<p :class="textClass" class="whitespace-pre-line text-center">
|
||||
<p :class="textClass" class="text-center whitespace-pre-line">
|
||||
{{ message }}
|
||||
</p>
|
||||
<Button
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
</IconField>
|
||||
<div
|
||||
v-if="filters?.length"
|
||||
class="search-filters pt-2 flex flex-wrap gap-2"
|
||||
class="search-filters flex flex-wrap gap-2 pt-2"
|
||||
>
|
||||
<SearchFilterChip
|
||||
v-for="filter in filters"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="system-stats">
|
||||
<div class="mb-6">
|
||||
<h2 class="text-2xl font-semibold mb-4">
|
||||
<h2 class="mb-4 text-2xl font-semibold">
|
||||
{{ $t('g.systemInfo') }}
|
||||
</h2>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
@@ -17,7 +17,7 @@
|
||||
<Divider />
|
||||
|
||||
<div>
|
||||
<h2 class="text-2xl font-semibold mb-4">
|
||||
<h2 class="mb-4 text-2xl font-semibold">
|
||||
{{ $t('g.devices') }}
|
||||
</h2>
|
||||
<TabView v-if="props.stats.devices.length > 1">
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<Tree
|
||||
v-model:expanded-keys="expandedKeys"
|
||||
v-model:selection-keys="selectionKeys"
|
||||
class="tree-explorer py-0 px-2 2xl:px-4"
|
||||
class="tree-explorer px-2 py-0 2xl:px-4"
|
||||
:class="props.class"
|
||||
:value="renderedRoot.children"
|
||||
selection-mode="single"
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
:class="{
|
||||
'pi pi-spin pi-spinner text-neutral-400':
|
||||
validationState === ValidationState.LOADING,
|
||||
'pi pi-check text-green-500 cursor-pointer':
|
||||
'pi pi-check cursor-pointer text-green-500':
|
||||
validationState === ValidationState.VALID,
|
||||
'pi pi-times text-red-500 cursor-pointer':
|
||||
'pi pi-times cursor-pointer text-red-500':
|
||||
validationState === ValidationState.INVALID
|
||||
}"
|
||||
@click="validateUrl(props.modelValue)"
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
severity="secondary"
|
||||
icon="pi pi-dollar"
|
||||
rounded
|
||||
class="text-amber-400 p-1"
|
||||
class="p-1 text-amber-400"
|
||||
/>
|
||||
<div :class="textClass">{{ formattedBalance }}</div>
|
||||
</div>
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
</template>
|
||||
|
||||
<template #contentFilter>
|
||||
<div class="relative px-6 pt-2 pb-4 flex gap-2 flex-wrap">
|
||||
<div class="relative flex flex-wrap gap-2 px-6 pt-2 pb-4">
|
||||
<!-- Model Filter -->
|
||||
<MultiSelect
|
||||
v-model="selectedModelObjects"
|
||||
@@ -97,7 +97,7 @@
|
||||
</div>
|
||||
<div
|
||||
v-if="!isLoading"
|
||||
class="px-6 pt-4 pb-2 text-2xl font-semibold text-neutral"
|
||||
class="text-neutral px-6 pt-4 pb-2 text-2xl font-semibold"
|
||||
>
|
||||
<span>
|
||||
{{ pageTitle }}
|
||||
@@ -109,10 +109,10 @@
|
||||
<!-- No Results State (only show when loaded and no results) -->
|
||||
<div
|
||||
v-if="!isLoading && filteredTemplates.length === 0"
|
||||
class="flex flex-col items-center justify-center h-64 text-neutral-500"
|
||||
class="flex h-64 flex-col items-center justify-center text-neutral-500"
|
||||
>
|
||||
<i class="icon-[lucide--search] w-12 h-12 mb-4 opacity-50" />
|
||||
<p class="text-lg mb-2">
|
||||
<i class="mb-4 icon-[lucide--search] h-12 w-12 opacity-50" />
|
||||
<p class="mb-2 text-lg">
|
||||
{{ $t('templateWorkflows.noResults', 'No templates found') }}
|
||||
</p>
|
||||
<p class="text-sm">
|
||||
@@ -128,7 +128,7 @@
|
||||
<!-- Title -->
|
||||
<span
|
||||
v-if="isLoading"
|
||||
class="inline-block h-8 w-48 bg-dialog-surface rounded animate-pulse"
|
||||
class="inline-block h-8 w-48 animate-pulse rounded bg-dialog-surface"
|
||||
></span>
|
||||
|
||||
<!-- Template Cards Grid -->
|
||||
@@ -148,7 +148,7 @@
|
||||
<CardTop ratio="landscape">
|
||||
<template #default>
|
||||
<div
|
||||
class="w-full h-full bg-dialog-surface animate-pulse"
|
||||
class="h-full w-full animate-pulse bg-dialog-surface"
|
||||
></div>
|
||||
</template>
|
||||
</CardTop>
|
||||
@@ -157,10 +157,10 @@
|
||||
<CardBottom>
|
||||
<div class="px-4 py-3">
|
||||
<div
|
||||
class="h-6 bg-dialog-surface rounded animate-pulse mb-2"
|
||||
class="mb-2 h-6 animate-pulse rounded bg-dialog-surface"
|
||||
></div>
|
||||
<div
|
||||
class="h-4 bg-dialog-surface rounded animate-pulse"
|
||||
class="h-4 animate-pulse rounded bg-dialog-surface"
|
||||
></div>
|
||||
</div>
|
||||
</CardBottom>
|
||||
@@ -184,7 +184,7 @@
|
||||
<template #default>
|
||||
<!-- Template Thumbnail -->
|
||||
<div
|
||||
class="w-full h-full relative rounded-lg overflow-hidden"
|
||||
class="relative h-full w-full overflow-hidden rounded-lg"
|
||||
>
|
||||
<template v-if="template.mediaType === 'audio'">
|
||||
<AudioThumbnail :src="getBaseThumbnailSrc(template)" />
|
||||
@@ -248,7 +248,7 @@
|
||||
</template>
|
||||
<ProgressSpinner
|
||||
v-if="loadingTemplate === template.name"
|
||||
class="absolute inset-0 z-10 w-12 h-12 m-auto"
|
||||
class="absolute inset-0 z-10 m-auto h-12 w-12"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -267,7 +267,7 @@
|
||||
<CardBottom>
|
||||
<div class="flex flex-col gap-2 pt-3">
|
||||
<h3
|
||||
class="line-clamp-1 text-sm m-0"
|
||||
class="m-0 line-clamp-1 text-sm"
|
||||
:title="
|
||||
getTemplateTitle(
|
||||
template,
|
||||
@@ -285,7 +285,7 @@
|
||||
<div class="flex justify-between gap-2">
|
||||
<div class="flex-1">
|
||||
<p
|
||||
class="line-clamp-2 text-sm text-muted m-0"
|
||||
class="m-0 line-clamp-2 text-sm text-muted"
|
||||
:title="getTemplateDescription(template)"
|
||||
>
|
||||
{{ getTemplateDescription(template) }}
|
||||
@@ -323,7 +323,7 @@
|
||||
<CardTop ratio="square">
|
||||
<template #default>
|
||||
<div
|
||||
class="w-full h-full bg-dialog-surface animate-pulse"
|
||||
class="h-full w-full animate-pulse bg-dialog-surface"
|
||||
></div>
|
||||
</template>
|
||||
</CardTop>
|
||||
@@ -332,10 +332,10 @@
|
||||
<CardBottom>
|
||||
<div class="px-4 py-3">
|
||||
<div
|
||||
class="h-6 bg-dialog-surface rounded animate-pulse mb-2"
|
||||
class="mb-2 h-6 animate-pulse rounded bg-dialog-surface"
|
||||
></div>
|
||||
<div
|
||||
class="h-4 bg-dialog-surface rounded animate-pulse"
|
||||
class="h-4 animate-pulse rounded bg-dialog-surface"
|
||||
></div>
|
||||
</div>
|
||||
</CardBottom>
|
||||
@@ -348,7 +348,7 @@
|
||||
<div
|
||||
v-if="!isLoading && hasMoreTemplates"
|
||||
ref="loadTrigger"
|
||||
class="w-full h-4 flex justify-center items-center mt-4"
|
||||
class="mt-4 flex h-4 w-full items-center justify-center"
|
||||
>
|
||||
<div v-if="isLoadingMore" class="text-sm text-muted">
|
||||
{{ $t('templateWorkflows.loadingMore', 'Loading more...') }}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
<template>
|
||||
<div class="flex flex-col gap-4 max-w-96 h-110 p-2">
|
||||
<div class="text-2xl font-medium mb-2">
|
||||
<div class="flex h-110 max-w-96 flex-col gap-4 p-2">
|
||||
<div class="mb-2 text-2xl font-medium">
|
||||
{{ t('apiNodesSignInDialog.title') }}
|
||||
</div>
|
||||
|
||||
<div class="text-base mb-4">
|
||||
<div class="mb-4 text-base">
|
||||
{{ t('apiNodesSignInDialog.message') }}
|
||||
</div>
|
||||
|
||||
<ApiNodesList :node-names="apiNodeNames" />
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="flex items-center justify-between">
|
||||
<Button :label="t('g.learnMore')" link @click="handleLearnMoreClick" />
|
||||
<div class="flex gap-2">
|
||||
<Button
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<section class="prompt-dialog-content flex flex-col gap-6 m-2 mt-4">
|
||||
<section class="prompt-dialog-content m-2 mt-4 flex flex-col gap-6">
|
||||
<span>{{ message }}</span>
|
||||
<ul v-if="itemList?.length" class="pl-4 m-0 flex flex-col gap-2">
|
||||
<ul v-if="itemList?.length" class="m-0 flex flex-col gap-2 pl-4">
|
||||
<li v-for="item of itemList" :key="item">
|
||||
{{ item }}
|
||||
</li>
|
||||
@@ -15,14 +15,14 @@
|
||||
>
|
||||
{{ hint }}
|
||||
</Message>
|
||||
<div class="flex gap-4 justify-end">
|
||||
<div class="flex justify-end gap-4">
|
||||
<div
|
||||
v-if="type === 'overwriteBlueprint'"
|
||||
class="flex gap-4 justify-start"
|
||||
class="flex justify-start gap-4"
|
||||
>
|
||||
<Checkbox
|
||||
v-model="doNotAskAgain"
|
||||
class="flex gap-4 justify-start"
|
||||
class="flex justify-start gap-4"
|
||||
input-id="doNotAskAgain"
|
||||
binary
|
||||
/>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<span class="font-bold">{{ error.extensionFile }}</span>
|
||||
</template>
|
||||
|
||||
<div class="flex gap-2 justify-center">
|
||||
<div class="flex justify-center gap-2">
|
||||
<Button
|
||||
v-show="!reportOpen"
|
||||
text
|
||||
@@ -29,12 +29,12 @@
|
||||
</div>
|
||||
<template v-if="reportOpen">
|
||||
<Divider />
|
||||
<ScrollPanel class="w-full h-[400px] max-w-[80vw]">
|
||||
<pre class="whitespace-pre-wrap break-words">{{ reportContent }}</pre>
|
||||
<ScrollPanel class="h-[400px] w-full max-w-[80vw]">
|
||||
<pre class="break-words whitespace-pre-wrap">{{ reportContent }}</pre>
|
||||
</ScrollPanel>
|
||||
<Divider />
|
||||
</template>
|
||||
<div class="flex gap-4 justify-end">
|
||||
<div class="flex justify-end gap-4">
|
||||
<FindIssueButton
|
||||
:error-message="error.exceptionMessage"
|
||||
:repo-owner="repoOwner"
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
}"
|
||||
>
|
||||
<template #option="slotProps">
|
||||
<div class="flex align-items-center">
|
||||
<div class="align-items-center flex">
|
||||
<span class="node-type">{{ slotProps.option.label }}</span>
|
||||
<span v-if="slotProps.option.hint" class="node-hint">{{
|
||||
slotProps.option.hint
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
v-if="hasMissingCoreNodes"
|
||||
severity="info"
|
||||
icon="pi pi-info-circle"
|
||||
class="my-2 mx-2"
|
||||
class="mx-2 my-2"
|
||||
:pt="{
|
||||
root: { class: 'flex-col' },
|
||||
text: { class: 'flex-1' }
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
:title="t('missingModelsDialog.missingModels')"
|
||||
:message="t('missingModelsDialog.missingModelsMessage')"
|
||||
/>
|
||||
<div class="flex gap-1 mb-4">
|
||||
<div class="mb-4 flex gap-1">
|
||||
<Checkbox v-model="doNotAskAgain" binary input-id="doNotAskAgain" />
|
||||
<label for="doNotAskAgain">{{
|
||||
t('missingModelsDialog.doNotAskAgain')
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="w-96 p-2 overflow-x-hidden">
|
||||
<div class="w-96 overflow-x-hidden p-2">
|
||||
<ApiKeyForm
|
||||
v-if="showApiKeyForm"
|
||||
@back="showApiKeyForm = false"
|
||||
@@ -7,11 +7,11 @@
|
||||
/>
|
||||
<template v-else>
|
||||
<!-- Header -->
|
||||
<div class="flex flex-col gap-4 mb-8">
|
||||
<h1 class="text-2xl font-medium leading-normal my-0">
|
||||
<div class="mb-8 flex flex-col gap-4">
|
||||
<h1 class="my-0 text-2xl leading-normal font-medium">
|
||||
{{ isSignIn ? t('auth.login.title') : t('auth.signup.title') }}
|
||||
</h1>
|
||||
<p class="text-base my-0">
|
||||
<p class="my-0 text-base">
|
||||
<span class="text-muted">{{
|
||||
isSignIn
|
||||
? t('auth.login.newUser')
|
||||
@@ -88,17 +88,17 @@
|
||||
>
|
||||
<img
|
||||
src="/assets/images/comfy-logo-mono.svg"
|
||||
class="w-5 h-5 mr-2"
|
||||
class="mr-2 h-5 w-5"
|
||||
alt="Comfy"
|
||||
/>
|
||||
{{ t('auth.login.useApiKey') }}
|
||||
</Button>
|
||||
<small class="text-muted text-center">
|
||||
<small class="text-center text-muted">
|
||||
{{ t('auth.apiKey.helpText') }}
|
||||
<a
|
||||
:href="`${COMFY_PLATFORM_BASE_URL}/login`"
|
||||
target="_blank"
|
||||
class="text-blue-500 cursor-pointer"
|
||||
class="cursor-pointer text-blue-500"
|
||||
>
|
||||
{{ t('auth.apiKey.generateKey') }}
|
||||
</a>
|
||||
@@ -115,12 +115,12 @@
|
||||
</div>
|
||||
|
||||
<!-- Terms & Contact -->
|
||||
<p class="text-xs text-muted mt-8">
|
||||
<p class="mt-8 text-xs text-muted">
|
||||
{{ t('auth.login.termsText') }}
|
||||
<a
|
||||
href="https://www.comfy.org/terms-of-service"
|
||||
target="_blank"
|
||||
class="text-blue-500 cursor-pointer"
|
||||
class="cursor-pointer text-blue-500"
|
||||
>
|
||||
{{ t('auth.login.termsLink') }}
|
||||
</a>
|
||||
@@ -128,12 +128,12 @@
|
||||
<a
|
||||
href="https://www.comfy.org/privacy"
|
||||
target="_blank"
|
||||
class="text-blue-500 cursor-pointer"
|
||||
class="cursor-pointer text-blue-500"
|
||||
>
|
||||
{{ t('auth.login.privacyLink') }} </a
|
||||
>.
|
||||
{{ t('auth.login.questionsContactPrefix') }}
|
||||
<a href="mailto:hello@comfy.org" class="text-blue-500 cursor-pointer">
|
||||
<a href="mailto:hello@comfy.org" class="cursor-pointer text-blue-500">
|
||||
hello@comfy.org</a
|
||||
>.
|
||||
</p>
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
<template>
|
||||
<div class="flex flex-col w-96 p-2 gap-10">
|
||||
<div class="flex w-96 flex-col gap-10 p-2">
|
||||
<div v-if="isInsufficientCredits" class="flex flex-col gap-4">
|
||||
<h1 class="text-2xl font-medium leading-normal my-0">
|
||||
<h1 class="my-0 text-2xl leading-normal font-medium">
|
||||
{{ $t('credits.topUp.insufficientTitle') }}
|
||||
</h1>
|
||||
<p class="text-base my-0">
|
||||
<p class="my-0 text-base">
|
||||
{{ $t('credits.topUp.insufficientMessage') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Balance Section -->
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="flex flex-col gap-2 w-full">
|
||||
<div class="text-muted text-base">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex w-full flex-col gap-2">
|
||||
<div class="text-base text-muted">
|
||||
{{ $t('credits.yourCreditBalance') }}
|
||||
</div>
|
||||
<div class="flex items-center justify-between w-full">
|
||||
<div class="flex w-full items-center justify-between">
|
||||
<UserCredit text-class="text-2xl" />
|
||||
<Button
|
||||
outlined
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
<!-- Amount Input Section -->
|
||||
<div class="flex flex-col gap-2">
|
||||
<span class="text-muted text-sm"
|
||||
<span class="text-sm text-muted"
|
||||
>{{ $t('credits.topUp.quickPurchase') }}:</span
|
||||
>
|
||||
<div class="grid grid-cols-[2fr_1fr] gap-2">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<Form
|
||||
class="flex flex-col gap-6 w-96"
|
||||
class="flex w-96 flex-col gap-6"
|
||||
:resolver="zodResolver(updatePasswordSchema)"
|
||||
@submit="onSubmit"
|
||||
>
|
||||
@@ -10,7 +10,7 @@
|
||||
<Button
|
||||
type="submit"
|
||||
:label="$t('userSettings.updatePassword')"
|
||||
class="h-10 font-medium mt-4"
|
||||
class="mt-4 h-10 font-medium"
|
||||
:loading="loading"
|
||||
/>
|
||||
</Form>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
severity="secondary"
|
||||
icon="pi pi-dollar"
|
||||
rounded
|
||||
class="text-amber-400 p-1"
|
||||
class="p-1 text-amber-400"
|
||||
/>
|
||||
<InputNumber
|
||||
v-if="editable"
|
||||
@@ -21,7 +21,7 @@
|
||||
/>
|
||||
<span v-else class="text-xl">{{ amount }}</span>
|
||||
</div>
|
||||
<ProgressSpinner v-if="loading" class="w-8 h-8" />
|
||||
<ProgressSpinner v-if="loading" class="h-8 w-8" />
|
||||
<Button
|
||||
v-else
|
||||
:severity="preselected ? 'primary' : 'secondary'"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<PanelTemplate value="About" class="about-container">
|
||||
<h2 class="text-2xl font-bold mb-2">
|
||||
<h2 class="mb-2 text-2xl font-bold">
|
||||
{{ $t('g.about') }}
|
||||
</h2>
|
||||
<div class="space-y-2">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<TabPanel value="Credits" class="credits-container h-full">
|
||||
<div class="flex flex-col h-full">
|
||||
<h2 class="text-2xl font-bold mb-2">
|
||||
<div class="flex h-full flex-col">
|
||||
<h2 class="mb-2 text-2xl font-bold">
|
||||
{{ $t('credits.credits') }}
|
||||
</h2>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<h3 class="text-sm font-medium text-muted">
|
||||
{{ $t('credits.yourCreditBalance') }}
|
||||
</h3>
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="flex items-center justify-between">
|
||||
<UserCredit text-class="text-3xl font-bold" />
|
||||
<Skeleton v-if="loading" width="2rem" height="2rem" />
|
||||
<Button
|
||||
@@ -41,7 +41,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="flex items-center justify-between">
|
||||
<h3>{{ $t('credits.activity') }}</h3>
|
||||
<Button
|
||||
:label="$t('credits.invoiceHistory')"
|
||||
@@ -66,7 +66,7 @@
|
||||
<template #body="{ data }">
|
||||
<div
|
||||
:class="[
|
||||
'text-base font-medium text-center',
|
||||
'text-center text-base font-medium',
|
||||
data.isPositive ? 'text-sky-500' : 'text-red-400'
|
||||
]"
|
||||
>
|
||||
|
||||
@@ -51,10 +51,7 @@
|
||||
class="max-w-64 2xl:max-w-full"
|
||||
>
|
||||
<template #body="slotProps">
|
||||
<div
|
||||
class="overflow-hidden text-ellipsis whitespace-nowrap"
|
||||
:title="slotProps.data.id"
|
||||
>
|
||||
<div class="truncate" :title="slotProps.data.id">
|
||||
{{ slotProps.data.label }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<TabPanel :value="props.value" class="h-full w-full" :class="props.class">
|
||||
<div class="flex flex-col h-full w-full gap-2">
|
||||
<div class="flex h-full w-full flex-col gap-2">
|
||||
<slot name="header" />
|
||||
<ScrollPanel class="grow h-0 pr-2">
|
||||
<ScrollPanel class="h-0 grow pr-2">
|
||||
<slot />
|
||||
</ScrollPanel>
|
||||
<slot name="footer" />
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<div class="event-details">
|
||||
<!-- Credits Added -->
|
||||
<template v-if="data.event_type === EventType.CREDIT_ADDED">
|
||||
<div class="text-green-500 font-semibold">
|
||||
<div class="font-semibold text-green-500">
|
||||
{{ $t('credits.added') }} ${{
|
||||
customerEventService.formatAmount(data.params?.amount)
|
||||
}}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<TabPanel value="User" class="user-settings-container h-full">
|
||||
<div class="flex flex-col h-full">
|
||||
<h2 class="text-2xl font-bold mb-2">{{ $t('userSettings.title') }}</h2>
|
||||
<div class="flex h-full flex-col">
|
||||
<h2 class="mb-2 text-2xl font-bold">{{ $t('userSettings.title') }}</h2>
|
||||
<Divider class="mb-3" />
|
||||
|
||||
<!-- Normal User Panel -->
|
||||
@@ -35,7 +35,7 @@
|
||||
<h3 class="font-medium">
|
||||
{{ $t('userSettings.provider') }}
|
||||
</h3>
|
||||
<div class="text-muted flex items-center gap-1">
|
||||
<div class="flex items-center gap-1 text-muted">
|
||||
<i :class="providerIcon" />
|
||||
{{ providerName }}
|
||||
<Button
|
||||
@@ -54,7 +54,7 @@
|
||||
|
||||
<ProgressSpinner
|
||||
v-if="loading"
|
||||
class="w-8 h-8 mt-4"
|
||||
class="mt-4 h-8 w-8"
|
||||
style="--pc-spinner-color: #000"
|
||||
/>
|
||||
<div v-else class="mt-4 flex flex-col gap-2">
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<template>
|
||||
<div class="flex flex-col gap-6">
|
||||
<div class="flex flex-col gap-4 mb-8">
|
||||
<h1 class="text-2xl font-medium leading-normal my-0">
|
||||
<div class="mb-8 flex flex-col gap-4">
|
||||
<h1 class="my-0 text-2xl leading-normal font-medium">
|
||||
{{ t('auth.apiKey.title') }}
|
||||
</h1>
|
||||
<div class="flex flex-col gap-2">
|
||||
<p class="text-base my-0 text-muted">
|
||||
<p class="my-0 text-base text-muted">
|
||||
{{ t('auth.apiKey.description') }}
|
||||
</p>
|
||||
<a
|
||||
href="https://docs.comfy.org/interface/user#logging-in-with-an-api-key"
|
||||
target="_blank"
|
||||
class="text-blue-500 cursor-pointer"
|
||||
class="cursor-pointer text-blue-500"
|
||||
>
|
||||
{{ t('g.learnMore') }}
|
||||
</a>
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
<label
|
||||
class="opacity-80 text-base font-medium mb-2"
|
||||
class="mb-2 text-base font-medium opacity-80"
|
||||
for="comfy-org-api-key"
|
||||
>
|
||||
{{ t('auth.apiKey.label') }}
|
||||
@@ -50,7 +50,7 @@
|
||||
<a
|
||||
:href="`${COMFY_PLATFORM_BASE_URL}/login`"
|
||||
target="_blank"
|
||||
class="text-blue-500 cursor-pointer"
|
||||
class="cursor-pointer text-blue-500"
|
||||
>
|
||||
{{ t('auth.apiKey.generateKey') }}
|
||||
</a>
|
||||
@@ -58,7 +58,7 @@
|
||||
<a
|
||||
href="https://docs.comfy.org/tutorials/api-nodes/overview#log-in-with-api-key-on-non-whitelisted-websites"
|
||||
target="_blank"
|
||||
class="text-blue-500 cursor-pointer"
|
||||
class="cursor-pointer text-blue-500"
|
||||
>
|
||||
{{ t('auth.apiKey.whitelistInfo') }}
|
||||
</a>
|
||||
@@ -66,7 +66,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between items-center mt-4">
|
||||
<div class="mt-4 flex items-center justify-between">
|
||||
<Button type="button" link @click="$emit('back')">
|
||||
{{ t('g.back') }}
|
||||
</Button>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<!-- Password Field -->
|
||||
<FormField v-slot="$field" name="password" class="flex flex-col gap-2">
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<label
|
||||
class="opacity-80 text-base font-medium"
|
||||
class="text-base font-medium opacity-80"
|
||||
for="comfy-org-sign-up-password"
|
||||
>
|
||||
{{ t('auth.signup.passwordLabel') }}
|
||||
@@ -68,7 +68,7 @@
|
||||
<!-- Confirm Password Field -->
|
||||
<FormField v-slot="$field" name="confirmPassword" class="flex flex-col gap-2">
|
||||
<label
|
||||
class="opacity-80 text-base font-medium mb-2"
|
||||
class="mb-2 text-base font-medium opacity-80"
|
||||
for="comfy-org-sign-up-confirm-password"
|
||||
>
|
||||
{{ t('auth.login.confirmPasswordLabel') }}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
>
|
||||
<!-- Email Field -->
|
||||
<div class="flex flex-col gap-2">
|
||||
<label class="opacity-80 text-base font-medium mb-2" :for="emailInputId">
|
||||
<label class="mb-2 text-base font-medium opacity-80" :for="emailInputId">
|
||||
{{ t('auth.login.emailLabel') }}
|
||||
</label>
|
||||
<InputText
|
||||
@@ -26,15 +26,15 @@
|
||||
|
||||
<!-- Password Field -->
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex justify-between items-center mb-2">
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<label
|
||||
class="opacity-80 text-base font-medium"
|
||||
class="text-base font-medium opacity-80"
|
||||
for="comfy-org-sign-in-password"
|
||||
>
|
||||
{{ t('auth.login.passwordLabel') }}
|
||||
</label>
|
||||
<span
|
||||
class="text-muted text-base font-medium cursor-pointer select-none"
|
||||
class="cursor-pointer text-base font-medium text-muted select-none"
|
||||
:class="{
|
||||
'text-link-disabled': !$form.email?.value || $form.email?.invalid
|
||||
}"
|
||||
@@ -60,12 +60,12 @@
|
||||
</div>
|
||||
|
||||
<!-- Submit Button -->
|
||||
<ProgressSpinner v-if="loading" class="w-8 h-8" />
|
||||
<ProgressSpinner v-if="loading" class="h-8 w-8" />
|
||||
<Button
|
||||
v-else
|
||||
type="submit"
|
||||
:label="t('auth.login.loginButton')"
|
||||
class="h-10 font-medium mt-4"
|
||||
class="mt-4 h-10 font-medium"
|
||||
/>
|
||||
</Form>
|
||||
</template>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<!-- Email Field -->
|
||||
<FormField v-slot="$field" name="email" class="flex flex-col gap-2">
|
||||
<label
|
||||
class="opacity-80 text-base font-medium mb-2"
|
||||
class="mb-2 text-base font-medium opacity-80"
|
||||
for="comfy-org-sign-up-email"
|
||||
>
|
||||
{{ t('auth.signup.emailLabel') }}
|
||||
@@ -40,11 +40,11 @@
|
||||
/>
|
||||
<label
|
||||
for="comfy-org-sign-up-personal-data-consent"
|
||||
class="opacity-80 text-base font-medium"
|
||||
class="text-base font-medium opacity-80"
|
||||
>
|
||||
{{ t('auth.signup.personalDataConsentLabel') }}
|
||||
</label>
|
||||
<small v-if="$field.error" class="text-red-500 -mt-4">{{
|
||||
<small v-if="$field.error" class="-mt-4 text-red-500">{{
|
||||
$field.error.message
|
||||
}}</small>
|
||||
</FormField>
|
||||
@@ -53,7 +53,7 @@
|
||||
<Button
|
||||
type="submit"
|
||||
:label="t('auth.signup.signUpButton')"
|
||||
class="h-10 font-medium mt-4"
|
||||
class="mt-4 h-10 font-medium"
|
||||
/>
|
||||
</Form>
|
||||
</template>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<BottomPanel />
|
||||
</template>
|
||||
<template #graph-canvas-panel>
|
||||
<div class="absolute top-0 left-0 w-auto max-w-full pointer-events-auto">
|
||||
<div class="pointer-events-auto absolute top-0 left-0 w-auto max-w-full">
|
||||
<SecondRowWorkflowTabs
|
||||
v-if="workflowTabsPosition === 'Topbar (2nd-row)'"
|
||||
/>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
></div>
|
||||
|
||||
<ButtonGroup
|
||||
class="p-buttongroup-vertical p-1 absolute bottom-4 right-2 md:right-4"
|
||||
class="p-buttongroup-vertical absolute right-2 bottom-4 p-1 md:right-4"
|
||||
:style="stringifiedMinimapStyles.buttonGroupStyles"
|
||||
@wheel="canvasInteractions.handleWheel"
|
||||
>
|
||||
@@ -44,7 +44,7 @@
|
||||
</Button>
|
||||
|
||||
<!-- vertical line with bg E1DED5 -->
|
||||
<div class="w-px my-1 bg-[#E1DED5] dark-theme:bg-[#2E3037] mx-2" />
|
||||
<div class="mx-2 my-1 w-px bg-[#E1DED5] dark-theme:bg-[#2E3037]" />
|
||||
|
||||
<Button
|
||||
v-tooltip.top="fitViewTooltip"
|
||||
@@ -52,7 +52,7 @@
|
||||
icon="pi pi-expand"
|
||||
:aria-label="fitViewTooltip"
|
||||
:style="stringifiedMinimapStyles.buttonStyles"
|
||||
class="dark-theme:hover:bg-[#444444]! hover:bg-[#E7E6E6]!"
|
||||
class="hover:bg-[#E7E6E6]! dark-theme:hover:bg-[#444444]!"
|
||||
@click="() => commandStore.execute('Comfy.Canvas.FitView')"
|
||||
>
|
||||
<template #icon>
|
||||
@@ -77,7 +77,7 @@
|
||||
</span>
|
||||
</Button>
|
||||
|
||||
<div class="w-px my-1 bg-[#E1DED5] dark-theme:bg-[#2E3037] mx-2" />
|
||||
<div class="mx-2 my-1 w-px bg-[#E1DED5] dark-theme:bg-[#2E3037]" />
|
||||
|
||||
<Button
|
||||
ref="focusButton"
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
<div
|
||||
ref="toolboxRef"
|
||||
style="transform: translate(var(--tb-x), var(--tb-y))"
|
||||
class="fixed left-0 top-0 z-40 pointer-events-none"
|
||||
class="pointer-events-none fixed top-0 left-0 z-40"
|
||||
>
|
||||
<Transition name="slide-up">
|
||||
<Panel
|
||||
v-if="visible"
|
||||
class="rounded-lg selection-toolbox pointer-events-auto"
|
||||
class="selection-toolbox pointer-events-auto rounded-lg"
|
||||
:style="`backgroundColor: ${containerStyles.backgroundColor};`"
|
||||
:pt="{
|
||||
header: 'hidden',
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="visible"
|
||||
class="w-[250px] absolute flex justify-center right-2 md:right-11 z-1300 bottom-[66px] bg-inherit! border-0!"
|
||||
class="absolute right-2 bottom-[66px] z-1300 flex w-[250px] justify-center border-0! bg-inherit! md:right-11"
|
||||
>
|
||||
<div
|
||||
class="bg-white dark-theme:bg-[#2b2b2b] border border-gray-200 dark-theme:border-gray-700 rounded-lg shadow-lg p-4 w-4/5"
|
||||
class="w-4/5 rounded-lg border border-gray-200 bg-white p-4 shadow-lg dark-theme:border-gray-700 dark-theme:bg-[#2b2b2b]"
|
||||
:style="filteredMinimapStyles"
|
||||
@click.stop
|
||||
>
|
||||
@@ -26,10 +26,10 @@
|
||||
@mouseleave="stopRepeat"
|
||||
>
|
||||
<template #default>
|
||||
<span class="text-sm font-medium block">{{
|
||||
<span class="block text-sm font-medium">{{
|
||||
$t('graphCanvasMenu.zoomIn')
|
||||
}}</span>
|
||||
<span class="text-sm text-gray-500 block">{{
|
||||
<span class="block text-sm text-gray-500">{{
|
||||
zoomInCommandText
|
||||
}}</span>
|
||||
</template>
|
||||
@@ -52,10 +52,10 @@
|
||||
@mouseleave="stopRepeat"
|
||||
>
|
||||
<template #default>
|
||||
<span class="text-sm font-medium block">{{
|
||||
<span class="block text-sm font-medium">{{
|
||||
$t('graphCanvasMenu.zoomOut')
|
||||
}}</span>
|
||||
<span class="text-sm text-gray-500 block">{{
|
||||
<span class="block text-sm text-gray-500">{{
|
||||
zoomOutCommandText
|
||||
}}</span>
|
||||
</template>
|
||||
@@ -76,15 +76,15 @@
|
||||
@click="executeCommand('Comfy.Canvas.FitView')"
|
||||
>
|
||||
<template #default>
|
||||
<span class="text-sm font-medium block">{{
|
||||
<span class="block text-sm font-medium">{{
|
||||
$t('zoomControls.zoomToFit')
|
||||
}}</span>
|
||||
<span class="text-sm text-gray-500 block">{{
|
||||
<span class="block text-sm text-gray-500">{{
|
||||
zoomToFitCommandText
|
||||
}}</span>
|
||||
</template>
|
||||
</Button>
|
||||
<hr class="border-[#E1DED5] mb-1 dark-theme:border-[#2E3037]" />
|
||||
<hr class="mb-1 border-[#E1DED5] dark-theme:border-[#2E3037]" />
|
||||
<Button
|
||||
severity="secondary"
|
||||
text
|
||||
@@ -101,18 +101,18 @@
|
||||
@click="executeCommand('Comfy.Canvas.ToggleMinimap')"
|
||||
>
|
||||
<template #default>
|
||||
<span class="text-sm font-medium block">{{
|
||||
<span class="block text-sm font-medium">{{
|
||||
minimapToggleText
|
||||
}}</span>
|
||||
<span class="text-sm text-gray-500 block">{{
|
||||
<span class="block text-sm text-gray-500">{{
|
||||
showMinimapCommandText
|
||||
}}</span>
|
||||
</template>
|
||||
</Button>
|
||||
<hr class="border-[#E1DED5] mt-1 dark-theme:border-[#2E3037]" />
|
||||
<hr class="mt-1 border-[#E1DED5] dark-theme:border-[#2E3037]" />
|
||||
<div
|
||||
ref="zoomInputContainer"
|
||||
class="flex items-center px-2 bg-[#E7E6E6] focus-within:bg-[#F3F3F3] dark-theme:bg-[#8282821A] rounded p-2 zoomInputContainer"
|
||||
class="zoomInputContainer flex items-center rounded bg-[#E7E6E6] p-2 px-2 focus-within:bg-[#F3F3F3] dark-theme:bg-[#8282821A]"
|
||||
>
|
||||
<InputNumber
|
||||
ref="zoomInput"
|
||||
@@ -127,7 +127,7 @@
|
||||
@input="applyZoom"
|
||||
@keyup.enter="applyZoom"
|
||||
/>
|
||||
<span class="text-sm text-gray-500 -ml-4">%</span>
|
||||
<span class="-ml-4 text-sm text-gray-500">%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
severity="secondary"
|
||||
text
|
||||
data-testid="bypass-button"
|
||||
class="hover:dark-theme:bg-charcoal-600 hover:bg-[#E7E6E6]"
|
||||
class="hover:bg-[#E7E6E6] hover:dark-theme:bg-charcoal-600"
|
||||
@click="toggleBypass"
|
||||
>
|
||||
<template #icon>
|
||||
<i class="icon-[lucide--ban] w-4 h-4" />
|
||||
<i class="icon-[lucide--ban] h-4 w-4" />
|
||||
</template>
|
||||
</Button>
|
||||
</template>
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
>
|
||||
<div class="flex items-center gap-1 px-0">
|
||||
<i
|
||||
class="w-4 h-4 pi pi-circle-fill"
|
||||
class="pi pi-circle-fill h-4 w-4"
|
||||
:style="{ color: currentColor ?? '' }"
|
||||
/>
|
||||
<i
|
||||
class="w-4 h-4 pi pi-chevron-down py-1"
|
||||
class="pi pi-chevron-down h-4 w-4 py-1"
|
||||
:style="{ fontSize: '0.5rem' }"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
@click="() => commandStore.execute('Comfy.Graph.UnpackSubgraph')"
|
||||
>
|
||||
<template #icon>
|
||||
<i class="icon-[lucide--expand] w-4 h-4" />
|
||||
<i class="icon-[lucide--expand] h-4 w-4" />
|
||||
</template>
|
||||
</Button>
|
||||
<Button
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
value: t('selectionToolbox.executeButton.tooltip'),
|
||||
showDelay: 1000
|
||||
}"
|
||||
class="dark-theme:bg-[#0B8CE9] bg-[#31B9F4] size-8 !p-0"
|
||||
class="size-8 bg-[#31B9F4] !p-0 dark-theme:bg-[#0B8CE9]"
|
||||
text
|
||||
@mouseenter="() => handleMouseEnter()"
|
||||
@mouseleave="() => handleMouseLeave()"
|
||||
@click="handleClick"
|
||||
>
|
||||
<i class="icon-[lucide--play] text-white size-4" />
|
||||
<i class="icon-[lucide--play] size-4 text-white" />
|
||||
</Button>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
severity="secondary"
|
||||
@click="frameNodes"
|
||||
>
|
||||
<i class="icon-[lucide--frame] w-4 h-4" />
|
||||
<i class="icon-[lucide--frame] h-4 w-4" />
|
||||
</Button>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
severity="secondary"
|
||||
@click="toggleHelp"
|
||||
>
|
||||
<i class="icon-[lucide--info] w-4 h-4" />
|
||||
<i class="icon-[lucide--info] h-4 w-4" />
|
||||
</Button>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
text
|
||||
@click="openMaskEditor"
|
||||
>
|
||||
<i-comfy:mask class="!w-4 !h-4" />
|
||||
<i-comfy:mask class="!h-4 !w-4" />
|
||||
</Button>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="option.type === 'divider'"
|
||||
class="h-px bg-gray-200 dark-theme:bg-zinc-700 my-1"
|
||||
class="my-1 h-px bg-gray-200 dark-theme:bg-zinc-700"
|
||||
/>
|
||||
<div
|
||||
v-else
|
||||
role="button"
|
||||
class="flex items-center gap-2 px-3 py-1.5 text-sm text-left hover:bg-gray-100 dark-theme:hover:bg-zinc-700 rounded cursor-pointer"
|
||||
class="flex cursor-pointer items-center gap-2 rounded px-3 py-1.5 text-left text-sm hover:bg-gray-100 dark-theme:hover:bg-zinc-700"
|
||||
@click="handleClick"
|
||||
>
|
||||
<i v-if="option.icon" :class="[option.icon, 'w-4 h-4']" />
|
||||
<i v-if="option.icon" :class="[option.icon, 'h-4 w-4']" />
|
||||
<span class="flex-1">{{ option.label }}</span>
|
||||
<span v-if="option.shortcut" class="text-xs opacity-60">
|
||||
{{ option.shortcut }}
|
||||
@@ -24,11 +24,11 @@
|
||||
:severity="option.badge === 'new' ? 'info' : 'secondary'"
|
||||
:value="t(option.badge)"
|
||||
:class="{
|
||||
'bg-[#31B9F4] dark-theme:bg-[#0B8CE9] rounded-4xl':
|
||||
'rounded-4xl bg-[#31B9F4] dark-theme:bg-[#0B8CE9]':
|
||||
option.badge === 'new',
|
||||
'bg-[#9C9EAB] dark-theme:bg-[#000] rounded-4xl':
|
||||
'rounded-4xl bg-[#9C9EAB] dark-theme:bg-[#000]':
|
||||
option.badge === 'deprecated',
|
||||
'text-white uppercase text-[9px] h-4 px-1 gap-2.5': true
|
||||
'h-4 gap-2.5 px-1 text-[9px] text-white uppercase': true
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
@hide="onPopoverHide"
|
||||
@wheel="canvasInteractions.forwardEventToCanvas"
|
||||
>
|
||||
<div class="flex flex-col p-2 min-w-48">
|
||||
<div class="flex min-w-48 flex-col p-2">
|
||||
<MenuOptionItem
|
||||
v-for="(option, index) in menuOptions"
|
||||
:key="option.label || `divider-${index}`"
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
severity="secondary"
|
||||
@click="handleClick"
|
||||
>
|
||||
<i class="icon-[lucide--more-vertical] w-4 h-4" />
|
||||
<i class="icon-[lucide--more-vertical] h-4 w-4" />
|
||||
</Button>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
data-testid="refresh-button"
|
||||
@click="refreshSelected"
|
||||
>
|
||||
<i class="icon-[lucide--refresh-cw] w-4 h-4" />
|
||||
<i class="icon-[lucide--refresh-cw] h-4 w-4" />
|
||||
</Button>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -28,13 +28,13 @@
|
||||
>
|
||||
<div
|
||||
v-if="subOption.color"
|
||||
class="w-5 h-5 rounded-full border border-gray-300 dark-theme:border-zinc-600"
|
||||
class="h-5 w-5 rounded-full border border-gray-300 dark-theme:border-zinc-600"
|
||||
:style="{ backgroundColor: subOption.color }"
|
||||
/>
|
||||
<template v-else-if="!subOption.color">
|
||||
<i
|
||||
v-if="isShapeSelected(subOption)"
|
||||
class="icon-[lucide--check] w-4 h-4 flex-shrink-0"
|
||||
class="icon-[lucide--check] h-4 w-4 flex-shrink-0"
|
||||
/>
|
||||
<div v-else class="w-4 flex-shrink-0" />
|
||||
<span>{{ subOption.label }}</span>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<template>
|
||||
<div class="h-6 w-px bg-gray-300/10 dark-theme:bg-gray-600/10 self-center" />
|
||||
<div class="h-6 w-px self-center bg-gray-300/10 dark-theme:bg-gray-600/10" />
|
||||
</template>
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
<template>
|
||||
<ScrollPanel
|
||||
ref="scrollPanelRef"
|
||||
class="w-full min-h-[400px] rounded-lg px-2 py-2 text-xs"
|
||||
class="min-h-[400px] w-full rounded-lg px-2 py-2 text-xs"
|
||||
:pt="{ content: { id: 'chat-scroll-content' } }"
|
||||
>
|
||||
<div v-for="(item, i) in parsedHistory" :key="i" class="mb-4">
|
||||
<!-- Prompt (user, right) -->
|
||||
<span
|
||||
:class="{
|
||||
'opacity-40 pointer-events-none': editIndex !== null && i > editIndex
|
||||
'pointer-events-none opacity-40': editIndex !== null && i > editIndex
|
||||
}"
|
||||
>
|
||||
<div class="flex justify-end mb-1">
|
||||
<div class="mb-1 flex justify-end">
|
||||
<div
|
||||
class="bg-gray-300 dark-theme:bg-gray-800 rounded-xl px-4 py-1 max-w-[80%] text-right"
|
||||
class="max-w-[80%] rounded-xl bg-gray-300 px-4 py-1 text-right dark-theme:bg-gray-800"
|
||||
>
|
||||
<div class="break-words text-[12px]">{{ item.prompt }}</div>
|
||||
<div class="text-[12px] break-words">{{ item.prompt }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end mb-2 mr-1">
|
||||
<div class="mr-1 mb-2 flex justify-end">
|
||||
<CopyButton :text="item.prompt" />
|
||||
<Button
|
||||
v-tooltip="
|
||||
@@ -26,7 +26,7 @@
|
||||
"
|
||||
text
|
||||
rounded
|
||||
class="p-1! h-4! w-4! text-gray-400 hover:text-gray-600 hover:dark-theme:text-gray-200 transition"
|
||||
class="h-4! w-4! p-1! text-gray-400 transition hover:text-gray-600 hover:dark-theme:text-gray-200"
|
||||
pt:icon:class="text-xs!"
|
||||
:icon="editIndex === i ? 'pi pi-times' : 'pi pi-pencil'"
|
||||
:aria-label="
|
||||
@@ -40,7 +40,7 @@
|
||||
<ResponseBlurb
|
||||
:text="item.response"
|
||||
:class="{
|
||||
'opacity-25 pointer-events-none': editIndex !== null && i >= editIndex
|
||||
'pointer-events-none opacity-25': editIndex !== null && i >= editIndex
|
||||
}"
|
||||
>
|
||||
<div v-html="nl2br(linkifyHtml(item.response))" />
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div
|
||||
class="relative w-full text-xs min-h-[28px] max-h-[200px] rounded-lg px-4 py-2 overflow-y-auto"
|
||||
class="relative max-h-[200px] min-h-[28px] w-full overflow-y-auto rounded-lg px-4 py-2 text-xs"
|
||||
>
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="flex-1 break-all flex items-center gap-2">
|
||||
<div class="flex flex-1 items-center gap-2 break-all">
|
||||
<span v-html="formattedText"></span>
|
||||
<Skeleton v-if="isParentNodeExecuting" class="flex-1! h-4!" />
|
||||
<Skeleton v-if="isParentNodeExecuting" class="h-4! flex-1!" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"
|
||||
text
|
||||
rounded
|
||||
class="p-1! h-4! w-6! text-gray-400 hover:text-gray-600 hover:dark-theme:text-gray-200 transition"
|
||||
class="h-4! w-6! p-1! text-gray-400 transition hover:text-gray-600 hover:dark-theme:text-gray-200"
|
||||
pt:icon:class="text-xs!"
|
||||
:icon="copied ? 'pi pi-check' : 'pi pi-copy'"
|
||||
:aria-label="
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<template>
|
||||
<span>
|
||||
<div class="flex justify-start mb-1">
|
||||
<div class="rounded-xl px-4 py-1 max-w-[80%]">
|
||||
<div class="break-words text-[12px]">
|
||||
<div class="mb-1 flex justify-start">
|
||||
<div class="max-w-[80%] rounded-xl px-4 py-1">
|
||||
<div class="text-[12px] break-words">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-start ml-1">
|
||||
<div class="ml-1 flex justify-start">
|
||||
<CopyButton :text="text" />
|
||||
</div>
|
||||
</span>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
v-if="showSearchBox || showSelectedCount || showClearButton"
|
||||
#header
|
||||
>
|
||||
<div class="pt-2 pb-0 px-2 flex flex-col">
|
||||
<div class="flex flex-col px-2 pt-2 pb-0">
|
||||
<SearchBox
|
||||
v-if="showSearchBox"
|
||||
v-model="searchQuery"
|
||||
@@ -39,7 +39,7 @@
|
||||
>
|
||||
<span
|
||||
v-if="showSelectedCount"
|
||||
class="text-sm text-neutral-400 dark-theme:text-zinc-500 px-1"
|
||||
class="px-1 text-sm text-neutral-400 dark-theme:text-zinc-500"
|
||||
>
|
||||
{{
|
||||
selectedCount > 0
|
||||
@@ -67,7 +67,7 @@
|
||||
</span>
|
||||
<span
|
||||
v-if="selectedCount > 0"
|
||||
class="pointer-events-none absolute -right-2 -top-2 z-10 flex h-5 w-5 items-center justify-center rounded-full bg-blue-400 dark-theme:bg-blue-500 text-xs font-semibold text-white"
|
||||
class="pointer-events-none absolute -top-2 -right-2 z-10 flex h-5 w-5 items-center justify-center rounded-full bg-blue-400 text-xs font-semibold text-white dark-theme:bg-blue-500"
|
||||
>
|
||||
{{ selectedCount }}
|
||||
</span>
|
||||
@@ -82,7 +82,7 @@
|
||||
<template #option="slotProps">
|
||||
<div class="flex items-center gap-2" :style="popoverStyle">
|
||||
<div
|
||||
class="flex h-4 w-4 p-0.5 shrink-0 items-center justify-center rounded transition-all duration-200"
|
||||
class="flex h-4 w-4 shrink-0 items-center justify-center rounded p-0.5 transition-all duration-200"
|
||||
:class="
|
||||
slotProps.selected
|
||||
? 'bg-blue-400 dark-theme:border-blue-500 dark-theme:bg-blue-500'
|
||||
@@ -91,11 +91,11 @@
|
||||
>
|
||||
<i
|
||||
v-if="slotProps.selected"
|
||||
class="icon-[lucide--check] text-xs text-bold text-white"
|
||||
class="text-bold icon-[lucide--check] text-xs text-white"
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
class="border-none outline-none bg-transparent text-left"
|
||||
class="border-none bg-transparent text-left outline-none"
|
||||
unstyled
|
||||
>{{ slotProps.option.name }}</Button
|
||||
>
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
<!-- Option row -->
|
||||
<template #option="{ option, selected }">
|
||||
<div
|
||||
class="flex items-center justify-between gap-3 w-full"
|
||||
class="flex w-full items-center justify-between gap-3"
|
||||
:style="optionStyle"
|
||||
>
|
||||
<span class="truncate">{{ option.name }}</span>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div
|
||||
class="relative w-full h-full"
|
||||
class="relative h-full w-full"
|
||||
@mouseenter="handleMouseEnter"
|
||||
@mouseleave="handleMouseLeave"
|
||||
>
|
||||
@@ -59,14 +59,14 @@
|
||||
/>
|
||||
<div
|
||||
v-if="enable3DViewer"
|
||||
class="absolute top-12 right-2 z-20 pointer-events-auto"
|
||||
class="pointer-events-auto absolute top-12 right-2 z-20"
|
||||
>
|
||||
<ViewerControls :node="node" />
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="showRecordingControls"
|
||||
class="absolute right-2 z-20 pointer-events-auto"
|
||||
class="pointer-events-auto absolute right-2 z-20"
|
||||
:class="{
|
||||
'top-12': !enable3DViewer,
|
||||
'top-24': enable3DViewer
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div
|
||||
class="relative w-full h-full"
|
||||
class="relative h-full w-full"
|
||||
@mouseenter="handleMouseEnter"
|
||||
@mouseleave="handleMouseLeave"
|
||||
>
|
||||
@@ -34,7 +34,7 @@
|
||||
@up-direction-change="listenUpDirectionChange"
|
||||
@recording-status-change="listenRecordingStatusChange"
|
||||
/>
|
||||
<div class="absolute top-0 left-0 w-full h-full pointer-events-none">
|
||||
<div class="pointer-events-none absolute top-0 left-0 h-full w-full">
|
||||
<Load3DControls
|
||||
:input-spec="inputSpec"
|
||||
:background-color="backgroundColor"
|
||||
@@ -69,7 +69,7 @@
|
||||
</div>
|
||||
<div
|
||||
v-if="showRecordingControls"
|
||||
class="absolute top-12 right-2 z-20 pointer-events-auto"
|
||||
class="pointer-events-auto absolute top-12 right-2 z-20"
|
||||
>
|
||||
<RecordingControls
|
||||
:node="node"
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="animations && animations.length > 0"
|
||||
class="absolute top-0 left-0 w-full flex justify-center pt-2 gap-2 items-center pointer-events-auto z-10"
|
||||
class="pointer-events-auto absolute top-0 left-0 z-10 flex w-full items-center justify-center gap-2 pt-2"
|
||||
>
|
||||
<Button class="p-button-rounded p-button-text" @click="togglePlay">
|
||||
<i
|
||||
:class="['pi', playing ? 'pi-pause' : 'pi-play', 'text-white text-lg']"
|
||||
:class="['pi', playing ? 'pi-pause' : 'pi-play', 'text-lg text-white']"
|
||||
/>
|
||||
</Button>
|
||||
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
<template>
|
||||
<div
|
||||
class="absolute top-12 left-2 flex flex-col pointer-events-auto z-20 bg-gray-700/30 rounded-lg"
|
||||
class="pointer-events-auto absolute top-12 left-2 z-20 flex flex-col rounded-lg bg-gray-700/30"
|
||||
>
|
||||
<div class="relative show-menu">
|
||||
<div class="show-menu relative">
|
||||
<Button class="p-button-rounded p-button-text" @click="toggleMenu">
|
||||
<i class="pi pi-bars text-white text-lg" />
|
||||
<i class="pi pi-bars text-lg text-white" />
|
||||
</Button>
|
||||
|
||||
<div
|
||||
v-show="isMenuOpen"
|
||||
class="absolute left-12 top-0 bg-black/50 rounded-lg shadow-lg"
|
||||
class="absolute top-0 left-12 rounded-lg bg-black/50 shadow-lg"
|
||||
>
|
||||
<div class="flex flex-col">
|
||||
<Button
|
||||
v-for="category in availableCategories"
|
||||
:key="category"
|
||||
class="p-button-text w-full flex items-center justify-start"
|
||||
class="p-button-text flex w-full items-center justify-start"
|
||||
:class="{ 'bg-gray-600': activeCategory === category }"
|
||||
@click="selectCategory(category)"
|
||||
>
|
||||
@@ -26,7 +26,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-show="activeCategory" class="bg-gray-700/30 rounded-lg">
|
||||
<div v-show="activeCategory" class="rounded-lg bg-gray-700/30">
|
||||
<SceneControls
|
||||
v-if="activeCategory === 'scene'"
|
||||
ref="sceneControlsRef"
|
||||
@@ -81,7 +81,7 @@
|
||||
:class="[
|
||||
'pi',
|
||||
showPreview ? 'pi-eye' : 'pi-eye-slash',
|
||||
'text-white text-lg'
|
||||
'text-lg text-white'
|
||||
]"
|
||||
/>
|
||||
</Button>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div ref="container" class="w-full h-full relative comfy-load-3d">
|
||||
<div ref="container" class="comfy-load-3d relative h-full w-full">
|
||||
<LoadingOverlay ref="loadingOverlayRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -6,18 +6,18 @@
|
||||
@mouseenter="viewer.handleMouseEnter"
|
||||
@mouseleave="viewer.handleMouseLeave"
|
||||
>
|
||||
<div ref="mainContentRef" class="flex-1 relative">
|
||||
<div ref="mainContentRef" class="relative flex-1">
|
||||
<div
|
||||
ref="containerRef"
|
||||
class="absolute w-full h-full comfy-load-3d-viewer"
|
||||
class="comfy-load-3d-viewer absolute h-full w-full"
|
||||
@resize="viewer.handleResize"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="w-72 flex flex-col">
|
||||
<div class="flex w-72 flex-col">
|
||||
<div class="flex-1 overflow-y-auto p-4">
|
||||
<div class="space-y-2">
|
||||
<div class="p-2 space-y-4">
|
||||
<div class="space-y-4 p-2">
|
||||
<SceneControls
|
||||
v-model:background-color="viewer.backgroundColor.value"
|
||||
v-model:show-grid="viewer.showGrid.value"
|
||||
@@ -26,27 +26,27 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="p-2 space-y-4">
|
||||
<div class="space-y-4 p-2">
|
||||
<ModelControls
|
||||
v-model:up-direction="viewer.upDirection.value"
|
||||
v-model:material-mode="viewer.materialMode.value"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="p-2 space-y-4">
|
||||
<div class="space-y-4 p-2">
|
||||
<CameraControls
|
||||
v-model:camera-type="viewer.cameraType.value"
|
||||
v-model:fov="viewer.fov.value"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="p-2 space-y-4">
|
||||
<div class="space-y-4 p-2">
|
||||
<LightControls
|
||||
v-model:light-intensity="viewer.lightIntensity.value"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="p-2 space-y-4">
|
||||
<div class="space-y-4 p-2">
|
||||
<ExportControls @export-model="viewer.exportModel" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
<Transition name="fade">
|
||||
<div
|
||||
v-if="modelLoading"
|
||||
class="absolute inset-0 bg-black/50 flex items-center justify-center z-50"
|
||||
class="absolute inset-0 z-50 flex items-center justify-center bg-black/50"
|
||||
>
|
||||
<div class="flex flex-col items-center">
|
||||
<div class="spinner" />
|
||||
<div class="text-white mt-4 text-lg">
|
||||
<div class="mt-4 text-lg text-white">
|
||||
{{ loadingMessage }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,19 +6,19 @@
|
||||
value: t('load3d.switchCamera'),
|
||||
showDelay: 300
|
||||
}"
|
||||
:class="['pi', getCameraIcon, 'text-white text-lg']"
|
||||
:class="['pi', getCameraIcon, 'text-lg text-white']"
|
||||
/>
|
||||
</Button>
|
||||
<div v-if="showFOVButton" class="relative show-fov">
|
||||
<div v-if="showFOVButton" class="show-fov relative">
|
||||
<Button class="p-button-rounded p-button-text" @click="toggleFOV">
|
||||
<i
|
||||
v-tooltip.right="{ value: t('load3d.fov'), showDelay: 300 }"
|
||||
class="pi pi-expand text-white text-lg"
|
||||
class="pi pi-expand text-lg text-white"
|
||||
/>
|
||||
</Button>
|
||||
<div
|
||||
v-show="showFOV"
|
||||
class="absolute left-12 top-0 bg-black/50 p-4 rounded-lg shadow-lg"
|
||||
class="absolute top-0 left-12 rounded-lg bg-black/50 p-4 shadow-lg"
|
||||
style="width: 150px"
|
||||
>
|
||||
<Slider
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="flex flex-col">
|
||||
<div class="relative show-export-formats">
|
||||
<div class="show-export-formats relative">
|
||||
<Button
|
||||
class="p-button-rounded p-button-text"
|
||||
@click="toggleExportFormats"
|
||||
@@ -10,12 +10,12 @@
|
||||
value: t('load3d.exportModel'),
|
||||
showDelay: 300
|
||||
}"
|
||||
class="pi pi-download text-white text-lg"
|
||||
class="pi pi-download text-lg text-white"
|
||||
/>
|
||||
</Button>
|
||||
<div
|
||||
v-show="showExportFormats"
|
||||
class="absolute left-12 top-0 bg-black/50 rounded-lg shadow-lg"
|
||||
class="absolute top-0 left-12 rounded-lg bg-black/50 shadow-lg"
|
||||
>
|
||||
<div class="flex flex-col">
|
||||
<Button
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="flex flex-col">
|
||||
<div v-if="showLightIntensityButton" class="relative show-light-intensity">
|
||||
<div v-if="showLightIntensityButton" class="show-light-intensity relative">
|
||||
<Button
|
||||
class="p-button-rounded p-button-text"
|
||||
@click="toggleLightIntensity"
|
||||
@@ -10,12 +10,12 @@
|
||||
value: t('load3d.lightIntensity'),
|
||||
showDelay: 300
|
||||
}"
|
||||
class="pi pi-sun text-white text-lg"
|
||||
class="pi pi-sun text-lg text-white"
|
||||
/>
|
||||
</Button>
|
||||
<div
|
||||
v-show="showLightIntensity"
|
||||
class="absolute left-12 top-0 bg-black/50 p-4 rounded-lg shadow-lg"
|
||||
class="absolute top-0 left-12 rounded-lg bg-black/50 p-4 shadow-lg"
|
||||
style="width: 150px"
|
||||
>
|
||||
<Slider
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<template>
|
||||
<div class="flex flex-col">
|
||||
<div class="relative show-up-direction">
|
||||
<div class="show-up-direction relative">
|
||||
<Button class="p-button-rounded p-button-text" @click="toggleUpDirection">
|
||||
<i
|
||||
v-tooltip.right="{
|
||||
value: t('load3d.upDirection'),
|
||||
showDelay: 300
|
||||
}"
|
||||
class="pi pi-arrow-up text-white text-lg"
|
||||
class="pi pi-arrow-up text-lg text-white"
|
||||
/>
|
||||
</Button>
|
||||
<div
|
||||
v-show="showUpDirection"
|
||||
class="absolute left-12 top-0 bg-black/50 rounded-lg shadow-lg"
|
||||
class="absolute top-0 left-12 rounded-lg bg-black/50 shadow-lg"
|
||||
>
|
||||
<div class="flex flex-col">
|
||||
<Button
|
||||
@@ -28,7 +28,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative show-material-mode">
|
||||
<div class="show-material-mode relative">
|
||||
<Button
|
||||
class="p-button-rounded p-button-text"
|
||||
@click="toggleMaterialMode"
|
||||
@@ -38,12 +38,12 @@
|
||||
value: t('load3d.materialMode'),
|
||||
showDelay: 300
|
||||
}"
|
||||
class="pi pi-box text-white text-lg"
|
||||
class="pi pi-box text-lg text-white"
|
||||
/>
|
||||
</Button>
|
||||
<div
|
||||
v-show="showMaterialMode"
|
||||
class="absolute left-12 top-0 bg-black/50 rounded-lg shadow-lg"
|
||||
class="absolute top-0 left-12 rounded-lg bg-black/50 shadow-lg"
|
||||
>
|
||||
<div class="flex flex-col">
|
||||
<Button
|
||||
@@ -59,7 +59,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="materialMode === 'lineart'" class="relative show-edge-threshold">
|
||||
<div v-if="materialMode === 'lineart'" class="show-edge-threshold relative">
|
||||
<Button
|
||||
class="p-button-rounded p-button-text"
|
||||
@click="toggleEdgeThreshold"
|
||||
@@ -69,15 +69,15 @@
|
||||
value: t('load3d.edgeThreshold'),
|
||||
showDelay: 300
|
||||
}"
|
||||
class="pi pi-sliders-h text-white text-lg"
|
||||
class="pi pi-sliders-h text-lg text-white"
|
||||
/>
|
||||
</Button>
|
||||
<div
|
||||
v-show="showEdgeThreshold"
|
||||
class="absolute left-12 top-0 bg-black/50 p-4 rounded-lg shadow-lg"
|
||||
class="absolute top-0 left-12 rounded-lg bg-black/50 p-4 shadow-lg"
|
||||
style="width: 150px"
|
||||
>
|
||||
<label class="text-white text-xs mb-1 block"
|
||||
<label class="mb-1 block text-xs text-white"
|
||||
>{{ t('load3d.edgeThreshold') }}: {{ edgeThreshold }}°</label
|
||||
>
|
||||
<Slider
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="relative bg-gray-700/30 rounded-lg">
|
||||
<div class="relative rounded-lg bg-gray-700/30">
|
||||
<div class="flex flex-col gap-2">
|
||||
<Button
|
||||
class="p-button-rounded p-button-text"
|
||||
@@ -10,7 +10,7 @@
|
||||
value: t('load3d.resizeNodeMatchOutput'),
|
||||
showDelay: 300
|
||||
}"
|
||||
class="pi pi-window-maximize text-white text-lg"
|
||||
class="pi pi-window-maximize text-lg text-white"
|
||||
/>
|
||||
</Button>
|
||||
<Button
|
||||
@@ -31,7 +31,7 @@
|
||||
:class="[
|
||||
'pi',
|
||||
isRecording ? 'pi-circle-fill' : 'pi-video',
|
||||
'text-white text-lg'
|
||||
'text-lg text-white'
|
||||
]"
|
||||
/>
|
||||
</Button>
|
||||
@@ -46,7 +46,7 @@
|
||||
value: t('load3d.exportRecording'),
|
||||
showDelay: 300
|
||||
}"
|
||||
class="pi pi-download text-white text-lg"
|
||||
class="pi pi-download text-lg text-white"
|
||||
/>
|
||||
</Button>
|
||||
|
||||
@@ -60,13 +60,13 @@
|
||||
value: t('load3d.clearRecording'),
|
||||
showDelay: 300
|
||||
}"
|
||||
class="pi pi-trash text-white text-lg"
|
||||
class="pi pi-trash text-lg text-white"
|
||||
/>
|
||||
</Button>
|
||||
|
||||
<div
|
||||
v-if="recordingDuration > 0 && !isRecording"
|
||||
class="text-xs text-white text-center mt-1"
|
||||
class="mt-1 text-center text-xs text-white"
|
||||
>
|
||||
{{ formatDuration(recordingDuration) }}
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
>
|
||||
<i
|
||||
v-tooltip.right="{ value: t('load3d.showGrid'), showDelay: 300 }"
|
||||
class="pi pi-table text-white text-lg"
|
||||
class="pi pi-table text-lg text-white"
|
||||
/>
|
||||
</Button>
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
value: t('load3d.backgroundColor'),
|
||||
showDelay: 300
|
||||
}"
|
||||
class="pi pi-palette text-white text-lg"
|
||||
class="pi pi-palette text-lg text-white"
|
||||
/>
|
||||
<input
|
||||
ref="colorPickerRef"
|
||||
type="color"
|
||||
:value="backgroundColor"
|
||||
class="absolute opacity-0 w-0 h-0 p-0 m-0 pointer-events-none"
|
||||
class="pointer-events-none absolute m-0 h-0 w-0 p-0 opacity-0"
|
||||
@input="
|
||||
updateBackgroundColor(($event.target as HTMLInputElement).value)
|
||||
"
|
||||
@@ -39,13 +39,13 @@
|
||||
value: t('load3d.uploadBackgroundImage'),
|
||||
showDelay: 300
|
||||
}"
|
||||
class="pi pi-image text-white text-lg"
|
||||
class="pi pi-image text-lg text-white"
|
||||
/>
|
||||
<input
|
||||
ref="imagePickerRef"
|
||||
type="file"
|
||||
accept="image/*"
|
||||
class="absolute opacity-0 w-0 h-0 p-0 m-0 pointer-events-none"
|
||||
class="pointer-events-none absolute m-0 h-0 w-0 p-0 opacity-0"
|
||||
@change="uploadBackgroundImage"
|
||||
/>
|
||||
</Button>
|
||||
@@ -61,7 +61,7 @@
|
||||
value: t('load3d.removeBackgroundImage'),
|
||||
showDelay: 300
|
||||
}"
|
||||
class="pi pi-times text-white text-lg"
|
||||
class="pi pi-times text-lg text-white"
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="relative bg-gray-700/30 rounded-lg">
|
||||
<div class="relative rounded-lg bg-gray-700/30">
|
||||
<div class="flex flex-col gap-2">
|
||||
<Button class="p-button-rounded p-button-text" @click="openIn3DViewer">
|
||||
<i
|
||||
@@ -7,7 +7,7 @@
|
||||
value: t('load3d.openIn3DViewer'),
|
||||
showDelay: 300
|
||||
}"
|
||||
class="pi pi-expand text-white text-lg"
|
||||
class="pi pi-expand text-lg text-white"
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,7 @@ https://github.com/Nuked88/ComfyUI-N-Sidebar/blob/7ae7da4a9761009fb6629bc04c6830
|
||||
<div v-else class="_sb_node_preview">
|
||||
<div class="_sb_table">
|
||||
<div
|
||||
class="node_header text-ellipsis mr-4"
|
||||
class="node_header mr-4 text-ellipsis"
|
||||
:title="nodeDef.display_name"
|
||||
:style="{
|
||||
backgroundColor: litegraphColors.NODE_DEFAULT_COLOR,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<div
|
||||
class="comfy-vue-node-search-container flex justify-center items-center w-full min-w-96"
|
||||
class="comfy-vue-node-search-container flex w-full min-w-96 items-center justify-center"
|
||||
>
|
||||
<div
|
||||
v-if="enableNodePreview"
|
||||
class="comfy-vue-node-preview-container absolute left-[-350px] top-[50px]"
|
||||
class="comfy-vue-node-preview-container absolute top-[50px] left-[-350px]"
|
||||
>
|
||||
<NodePreview
|
||||
v-if="hoveredSuggestion"
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div
|
||||
class="option-container flex justify-between items-center px-2 py-0 cursor-pointer overflow-hidden w-full"
|
||||
class="option-container flex w-full cursor-pointer items-center justify-between overflow-hidden px-2 py-0"
|
||||
>
|
||||
<div class="option-display-name font-semibold flex flex-col">
|
||||
<div class="option-display-name flex flex-col font-semibold">
|
||||
<div>
|
||||
<span v-if="isBookmarked">
|
||||
<i class="pi pi-bookmark-fill text-sm mr-1" />
|
||||
<i class="pi pi-bookmark-fill mr-1 text-sm" />
|
||||
</span>
|
||||
<span v-html="highlightQuery(nodeDef.display_name, currentQuery)" />
|
||||
<span> </span>
|
||||
@@ -15,7 +15,7 @@
|
||||
</div>
|
||||
<div
|
||||
v-if="showCategory"
|
||||
class="option-category font-light text-sm text-muted overflow-hidden text-ellipsis whitespace-nowrap"
|
||||
class="option-category truncate text-sm font-light text-muted"
|
||||
>
|
||||
{{ nodeDef.category.replaceAll('/', ' > ') }}
|
||||
</div>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
</teleport>
|
||||
<div
|
||||
v-if="selectedTab"
|
||||
class="sidebar-content-container h-full overflow-y-auto overflow-x-hidden"
|
||||
class="sidebar-content-container h-full overflow-x-hidden overflow-y-auto"
|
||||
>
|
||||
<ExtensionSlot :extension="selectedTab" />
|
||||
</div>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<template>
|
||||
<div
|
||||
class="comfy-vue-side-bar-container flex flex-col h-full group/sidebar-tab"
|
||||
class="comfy-vue-side-bar-container group/sidebar-tab flex h-full flex-col"
|
||||
:class="props.class"
|
||||
>
|
||||
<div class="comfy-vue-side-bar-header">
|
||||
<Toolbar class="border-x-0 border-t-0 rounded-none px-2 py-1 min-h-8">
|
||||
<Toolbar class="min-h-8 rounded-none border-x-0 border-t-0 px-2 py-1">
|
||||
<template #start>
|
||||
<span class="text-xs 2xl:text-sm truncate" :title="props.title">
|
||||
<span class="truncate text-xs 2xl:text-sm" :title="props.title">
|
||||
{{ props.title.toUpperCase() }}
|
||||
</span>
|
||||
</template>
|
||||
<template #end>
|
||||
<div
|
||||
class="flex flex-row motion-safe:w-0 motion-safe:opacity-0 motion-safe:group-hover/sidebar-tab:w-auto motion-safe:group-hover/sidebar-tab:opacity-100 motion-safe:group-focus-within/sidebar-tab:w-auto motion-safe:group-focus-within/sidebar-tab:opacity-100 touch:w-auto touch:opacity-100 transition-all duration-200"
|
||||
class="touch:w-auto touch:opacity-100 flex flex-row transition-all duration-200 motion-safe:w-0 motion-safe:opacity-0 motion-safe:group-focus-within/sidebar-tab:w-auto motion-safe:group-focus-within/sidebar-tab:opacity-100 motion-safe:group-hover/sidebar-tab:w-auto motion-safe:group-hover/sidebar-tab:opacity-100"
|
||||
>
|
||||
<slot name="tool-buttons" />
|
||||
</div>
|
||||
@@ -21,7 +21,7 @@
|
||||
<slot name="header" />
|
||||
</div>
|
||||
<!-- h-0 to force scrollpanel to grow -->
|
||||
<ScrollPanel class="comfy-vue-side-bar-body grow h-0">
|
||||
<ScrollPanel class="comfy-vue-side-bar-body h-0 grow">
|
||||
<slot name="body" />
|
||||
</ScrollPanel>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
</div>
|
||||
<div v-if="['cancelled', 'error'].includes(download.status ?? '')">
|
||||
<Chip
|
||||
class="h-6 text-sm font-light bg-red-700 mt-2"
|
||||
class="mt-2 h-6 bg-red-700 text-sm font-light"
|
||||
removable
|
||||
@remove="handleRemoveDownload"
|
||||
>
|
||||
@@ -30,7 +30,7 @@
|
||||
<Button
|
||||
v-if="download.status === 'in_progress'"
|
||||
v-tooltip.top="t('electronFileDownload.pause')"
|
||||
class="file-action-button w-[22px] h-[22px]"
|
||||
class="file-action-button h-[22px] w-[22px]"
|
||||
size="small"
|
||||
rounded
|
||||
icon="pi pi-pause"
|
||||
@@ -40,7 +40,7 @@
|
||||
<Button
|
||||
v-if="download.status === 'paused'"
|
||||
v-tooltip.top="t('electronFileDownload.resume')"
|
||||
class="file-action-button w-[22px] h-[22px]"
|
||||
class="file-action-button h-[22px] w-[22px]"
|
||||
size="small"
|
||||
rounded
|
||||
icon="pi pi-play"
|
||||
@@ -50,7 +50,7 @@
|
||||
<Button
|
||||
v-if="['in_progress', 'paused'].includes(download.status ?? '')"
|
||||
v-tooltip.top="t('electronFileDownload.cancel')"
|
||||
class="file-action-button w-[22px] h-[22px] p-red"
|
||||
class="file-action-button p-red h-[22px] w-[22px]"
|
||||
size="small"
|
||||
rounded
|
||||
severity="danger"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div v-if="inProgressDownloads.length > 0" class="mx-6 mb-4">
|
||||
<div class="text-lg my-4">
|
||||
<div class="my-4 text-lg">
|
||||
{{ $t('electronFileDownload.inProgress') }}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="flex flex-col h-full bg-(--p-tree-background) overflow-auto">
|
||||
<div class="flex h-full flex-col overflow-auto bg-(--p-tree-background)">
|
||||
<div
|
||||
class="px-3 py-2 flex items-center border-b border-(--p-divider-color)"
|
||||
class="flex items-center border-b border-(--p-divider-color) px-3 py-2"
|
||||
>
|
||||
<Button
|
||||
v-tooltip.bottom="$t('g.back')"
|
||||
@@ -12,7 +12,7 @@
|
||||
/>
|
||||
<span class="ml-2 font-semibold">{{ node.display_name }}</span>
|
||||
</div>
|
||||
<div class="p-4 grow node-help-content w-full mx-auto">
|
||||
<div class="node-help-content mx-auto w-full grow p-4">
|
||||
<ProgressSpinner
|
||||
v-if="isLoading"
|
||||
class="m-auto"
|
||||
@@ -25,7 +25,7 @@
|
||||
v-html="renderedHelpHtml"
|
||||
/>
|
||||
<!-- Fallback: markdown not found or fetch error -->
|
||||
<div v-else class="text-sm space-y-6 fallback-content">
|
||||
<div v-else class="fallback-content space-y-6 text-sm">
|
||||
<p v-if="node.description">
|
||||
<strong>{{ $t('g.description') }}:</strong> {{ node.description }}
|
||||
</p>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<template>
|
||||
<BaseThumbnail>
|
||||
<div
|
||||
class="w-full h-full flex items-center justify-center p-4"
|
||||
class="flex h-full w-full items-center justify-center p-4"
|
||||
:style="{
|
||||
backgroundImage: 'url(/assets/images/default-template.png)',
|
||||
backgroundRepeat: 'round'
|
||||
}"
|
||||
>
|
||||
<audio controls class="w-full relative" :src="src" @click.stop />
|
||||
<audio controls class="relative w-full" :src="src" @click.stop />
|
||||
</div>
|
||||
</BaseThumbnail>
|
||||
</template>
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
<template>
|
||||
<div
|
||||
class="relative w-full aspect-square rounded-t-lg overflow-hidden select-none"
|
||||
class="relative aspect-square w-full overflow-hidden rounded-t-lg select-none"
|
||||
>
|
||||
<div
|
||||
v-if="!error"
|
||||
ref="contentRef"
|
||||
class="w-full h-full transform-gpu transition-transform duration-1000 ease-out"
|
||||
class="h-full w-full transform-gpu transition-transform duration-1000 ease-out"
|
||||
:style="
|
||||
isHovered ? { transform: `scale(${1 + hoverZoom / 100})` } : undefined
|
||||
"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
<div v-else class="w-full h-full flex items-center justify-center">
|
||||
<div v-else class="flex h-full w-full items-center justify-center">
|
||||
<img
|
||||
src="/assets/images/default-template.png"
|
||||
draggable="false"
|
||||
class="transform-gpu transition-transform duration-300 ease-out w-full h-full object-cover"
|
||||
class="h-full w-full transform-gpu object-cover transition-transform duration-300 ease-out"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
}"
|
||||
/>
|
||||
<div
|
||||
class="absolute inset-y-0 w-0.5 bg-white/30 backdrop-blur-sm z-10 pointer-events-none"
|
||||
class="pointer-events-none absolute inset-y-0 z-10 w-0.5 bg-white/30 backdrop-blur-sm"
|
||||
:style="{
|
||||
left: `${sliderPosition}%`
|
||||
}"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<BaseThumbnail :is-hovered="isHovered">
|
||||
<div class="relative w-full h-full">
|
||||
<div class="relative h-full w-full">
|
||||
<div class="absolute inset-0">
|
||||
<LazyImage
|
||||
:src="baseImageSrc"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<Toast group="reroute-migration">
|
||||
<template #message>
|
||||
<div class="flex flex-col items-start flex-auto">
|
||||
<div class="font-medium text-lg my-4">
|
||||
<div class="flex flex-auto flex-col items-start">
|
||||
<div class="my-4 text-lg font-medium">
|
||||
{{ t('toastMessages.migrateToLitegraphReroute') }}
|
||||
</div>
|
||||
<Button
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div
|
||||
class="comfyui-logo-wrapper p-1 flex justify-center items-center cursor-pointer rounded-md mr-2"
|
||||
class="comfyui-logo-wrapper mr-2 flex cursor-pointer items-center justify-center rounded-md p-1"
|
||||
:class="{
|
||||
'comfyui-logo-menu-visible': menuRef?.visible
|
||||
}"
|
||||
@@ -59,11 +59,11 @@
|
||||
/>
|
||||
<span
|
||||
v-if="item?.comfyCommand?.keybinding"
|
||||
class="ml-auto border border-surface rounded text-muted text-xs text-nowrap p-1 keybinding-tag"
|
||||
class="keybinding-tag ml-auto rounded border border-surface p-1 text-xs text-nowrap text-muted"
|
||||
>
|
||||
{{ item.comfyCommand.keybinding.combo.toString() }}
|
||||
</span>
|
||||
<i v-if="item.items" class="ml-auto pi pi-angle-right" />
|
||||
<i v-if="item.items" class="pi pi-angle-right ml-auto" />
|
||||
</a>
|
||||
</template>
|
||||
</TieredMenu>
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
/>
|
||||
|
||||
<!-- User Details -->
|
||||
<h3 class="text-lg font-semibold truncate my-0 mb-1">
|
||||
<h3 class="my-0 mb-1 truncate text-lg font-semibold">
|
||||
{{ userDisplayName || $t('g.user') }}
|
||||
</h3>
|
||||
<p v-if="userEmail" class="text-sm text-muted truncate my-0">
|
||||
<p v-if="userEmail" class="my-0 truncate text-sm text-muted">
|
||||
{{ userEmail }}
|
||||
</p>
|
||||
</div>
|
||||
@@ -61,11 +61,11 @@
|
||||
|
||||
<Divider class="my-2" />
|
||||
|
||||
<div class="w-full flex flex-col gap-2 p-2">
|
||||
<div class="text-muted text-sm">
|
||||
<div class="flex w-full flex-col gap-2 p-2">
|
||||
<div class="text-sm text-muted">
|
||||
{{ $t('credits.yourCreditBalance') }}
|
||||
</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="flex items-center justify-between">
|
||||
<UserCredit text-class="text-2xl" />
|
||||
<Button :label="$t('credits.topUp.topUp')" @click="handleTopUp" />
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div>
|
||||
<div
|
||||
v-show="showTopMenu && workflowTabsPosition === 'Topbar'"
|
||||
class="w-full flex content-end z-1001 h-[38px]"
|
||||
class="z-1001 flex h-[38px] w-full content-end"
|
||||
style="background: var(--border-color)"
|
||||
>
|
||||
<WorkflowTabs />
|
||||
@@ -14,7 +14,7 @@
|
||||
:class="{ dropzone: isDropZone, 'dropzone-active': isDroppable }"
|
||||
>
|
||||
<CommandMenubar />
|
||||
<div class="grow min-w-0 app-drag h-full"></div>
|
||||
<div class="app-drag h-full min-w-0 grow"></div>
|
||||
<div
|
||||
ref="menuRight"
|
||||
class="comfyui-menu-right flex-shrink-1 overflow-auto"
|
||||
@@ -26,7 +26,7 @@
|
||||
<!-- Virtual top menu for native window (drag handle) -->
|
||||
<div
|
||||
v-show="isNativeWindow() && !showTopMenu"
|
||||
class="fixed top-0 left-0 app-drag w-full h-(--comfy-topbar-height)"
|
||||
class="app-drag fixed top-0 left-0 h-(--comfy-topbar-height) w-full"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
<template>
|
||||
<div
|
||||
ref="workflowTabRef"
|
||||
class="flex p-2 gap-2 workflow-tab group"
|
||||
class="workflow-tab group flex gap-2 p-2"
|
||||
v-bind="$attrs"
|
||||
@mouseenter="handleMouseEnter"
|
||||
@mouseleave="handleMouseLeave"
|
||||
@click="handleClick"
|
||||
>
|
||||
<span class="workflow-label text-sm max-w-[150px] truncate inline-block">
|
||||
<span class="workflow-label inline-block max-w-[150px] truncate text-sm">
|
||||
{{ workflowOption.workflow.filename }}
|
||||
</span>
|
||||
<div class="relative">
|
||||
<span
|
||||
v-if="shouldShowStatusIndicator"
|
||||
class="group-hover:hidden absolute font-bold text-2xl top-1/2 left-1/2 -translate-1/2 z-10 bg-(--comfy-menu-bg) w-4"
|
||||
class="absolute top-1/2 left-1/2 z-10 w-4 -translate-1/2 bg-(--comfy-menu-bg) text-2xl font-bold group-hover:hidden"
|
||||
>•</span
|
||||
>
|
||||
<Button
|
||||
class="close-button p-0 w-auto invisible"
|
||||
class="close-button invisible w-auto p-0"
|
||||
icon="pi pi-times"
|
||||
text
|
||||
severity="secondary"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user