mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-30 19:21:54 +00:00
Component: Button Migration 2: IconButton (#7598)
## Summary Still a work in progress. Buttons with just icons are already in the stories for button. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7598-WIP-Component-Button-Migration-2-IconButton-2cc6d73d365081c09143c63464ac60b7) by [Unito](https://www.unito.io)
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import clsx, { type ClassArray } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
|
import type { ClassArray } from 'clsx'
|
||||||
import { twMerge } from 'tailwind-merge'
|
import { twMerge } from 'tailwind-merge'
|
||||||
|
|
||||||
export type { ClassValue } from 'clsx'
|
export type { ClassValue } from 'clsx'
|
||||||
|
|||||||
135
pnpm-lock.yaml
generated
135
pnpm-lock.yaml
generated
@@ -265,14 +265,14 @@ catalogs:
|
|||||||
specifier: ^8.49.0
|
specifier: ^8.49.0
|
||||||
version: 8.49.0
|
version: 8.49.0
|
||||||
unplugin-icons:
|
unplugin-icons:
|
||||||
specifier: ^0.22.0
|
specifier: ^22.5.0
|
||||||
version: 0.22.0
|
version: 22.5.0
|
||||||
unplugin-typegpu:
|
unplugin-typegpu:
|
||||||
specifier: 0.8.0
|
specifier: 0.8.0
|
||||||
version: 0.8.0
|
version: 0.8.0
|
||||||
unplugin-vue-components:
|
unplugin-vue-components:
|
||||||
specifier: ^0.28.0
|
specifier: ^30.0.0
|
||||||
version: 0.28.0
|
version: 30.0.0
|
||||||
vite:
|
vite:
|
||||||
specifier: ^7.3.0
|
specifier: ^7.3.0
|
||||||
version: 7.3.0
|
version: 7.3.0
|
||||||
@@ -692,13 +692,13 @@ importers:
|
|||||||
version: 8.49.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
|
version: 8.49.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)
|
||||||
unplugin-icons:
|
unplugin-icons:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 0.22.0(@vue/compiler-sfc@3.5.25)
|
version: 22.5.0(@vue/compiler-sfc@3.5.25)
|
||||||
unplugin-typegpu:
|
unplugin-typegpu:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 0.8.0(typegpu@0.8.2)
|
version: 0.8.0(typegpu@0.8.2)
|
||||||
unplugin-vue-components:
|
unplugin-vue-components:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 0.28.0(@babel/parser@7.28.5)(rollup@4.53.5)(vue@3.5.13(typescript@5.9.3))
|
version: 30.0.0(@babel/parser@7.28.5)(vue@3.5.13(typescript@5.9.3))
|
||||||
uuid:
|
uuid:
|
||||||
specifier: ^11.1.0
|
specifier: ^11.1.0
|
||||||
version: 11.1.0
|
version: 11.1.0
|
||||||
@@ -780,10 +780,10 @@ importers:
|
|||||||
version: 16.6.1
|
version: 16.6.1
|
||||||
unplugin-icons:
|
unplugin-icons:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 0.22.0(@vue/compiler-sfc@3.5.25)
|
version: 22.5.0(@vue/compiler-sfc@3.5.25)
|
||||||
unplugin-vue-components:
|
unplugin-vue-components:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 0.28.0(@babel/parser@7.28.5)(rollup@4.53.5)(vue@3.5.13(typescript@5.9.3))
|
version: 30.0.0(@babel/parser@7.28.5)(vue@3.5.13(typescript@5.9.3))
|
||||||
vite:
|
vite:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.2)
|
version: 7.3.0(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.39.2)(tsx@4.19.4)(yaml@2.8.2)
|
||||||
@@ -907,18 +907,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
|
resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
|
||||||
engines: {node: '>=6.0.0'}
|
engines: {node: '>=6.0.0'}
|
||||||
|
|
||||||
'@antfu/install-pkg@0.5.0':
|
|
||||||
resolution: {integrity: sha512-dKnk2xlAyC7rvTkpkHmu+Qy/2Zc3Vm/l8PtNyIOGDBtXPY3kThfU4ORNEp3V7SXw5XSOb+tOJaUYpfquPzL/Tg==}
|
|
||||||
|
|
||||||
'@antfu/install-pkg@1.1.0':
|
'@antfu/install-pkg@1.1.0':
|
||||||
resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==}
|
resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==}
|
||||||
|
|
||||||
'@antfu/utils@0.7.10':
|
|
||||||
resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==}
|
|
||||||
|
|
||||||
'@antfu/utils@8.1.1':
|
|
||||||
resolution: {integrity: sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==}
|
|
||||||
|
|
||||||
'@asamuzakjp/css-color@3.2.0':
|
'@asamuzakjp/css-color@3.2.0':
|
||||||
resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==}
|
resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==}
|
||||||
|
|
||||||
@@ -2147,8 +2138,8 @@ packages:
|
|||||||
'@iconify/types@2.0.0':
|
'@iconify/types@2.0.0':
|
||||||
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
|
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
|
||||||
|
|
||||||
'@iconify/utils@2.3.0':
|
'@iconify/utils@3.1.0':
|
||||||
resolution: {integrity: sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==}
|
resolution: {integrity: sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==}
|
||||||
|
|
||||||
'@internationalized/date@3.9.0':
|
'@internationalized/date@3.9.0':
|
||||||
resolution: {integrity: sha512-yaN3brAnHRD+4KyyOsJyk49XUvj2wtbNACSqg0bz3u8t2VuzhC8Q5dfRnrSxjnnbDb+ienBnkn1TzQfE154vyg==}
|
resolution: {integrity: sha512-yaN3brAnHRD+4KyyOsJyk49XUvj2wtbNACSqg0bz3u8t2VuzhC8Q5dfRnrSxjnnbDb+ienBnkn1TzQfE154vyg==}
|
||||||
@@ -4430,6 +4421,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
|
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
|
||||||
engines: {node: '>= 8.10.0'}
|
engines: {node: '>= 8.10.0'}
|
||||||
|
|
||||||
|
chokidar@4.0.3:
|
||||||
|
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
|
||||||
|
engines: {node: '>= 14.16.0'}
|
||||||
|
|
||||||
chownr@3.0.0:
|
chownr@3.0.0:
|
||||||
resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==}
|
resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@@ -5170,8 +5165,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==}
|
resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==}
|
||||||
engines: {node: '>=12.0.0'}
|
engines: {node: '>=12.0.0'}
|
||||||
|
|
||||||
exsolve@1.0.7:
|
exsolve@1.0.8:
|
||||||
resolution: {integrity: sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==}
|
resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==}
|
||||||
|
|
||||||
extend-shallow@2.0.1:
|
extend-shallow@2.0.1:
|
||||||
resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==}
|
resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==}
|
||||||
@@ -6129,10 +6124,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==}
|
resolution: {integrity: sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==}
|
||||||
engines: {node: '>=20.0.0'}
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
local-pkg@0.5.1:
|
|
||||||
resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==}
|
|
||||||
engines: {node: '>=14'}
|
|
||||||
|
|
||||||
local-pkg@1.1.2:
|
local-pkg@1.1.2:
|
||||||
resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==}
|
resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
@@ -6696,11 +6687,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-ua1L4OgXSBdsu1FPb7F3tYH0F48a6kxvod4pLUlGY9COeJAJQNX/sNH2IiEmsxw7lqYiAwrdHMjz1FctOsyDQg==}
|
resolution: {integrity: sha512-ua1L4OgXSBdsu1FPb7F3tYH0F48a6kxvod4pLUlGY9COeJAJQNX/sNH2IiEmsxw7lqYiAwrdHMjz1FctOsyDQg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
package-manager-detector@0.2.11:
|
package-manager-detector@1.6.0:
|
||||||
resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==}
|
resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==}
|
||||||
|
|
||||||
package-manager-detector@1.3.0:
|
|
||||||
resolution: {integrity: sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==}
|
|
||||||
|
|
||||||
pako@1.0.11:
|
pako@1.0.11:
|
||||||
resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==}
|
resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==}
|
||||||
@@ -7061,6 +7049,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
||||||
engines: {node: '>=8.10.0'}
|
engines: {node: '>=8.10.0'}
|
||||||
|
|
||||||
|
readdirp@4.1.2:
|
||||||
|
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
|
||||||
|
engines: {node: '>= 14.18.0'}
|
||||||
|
|
||||||
recast@0.23.11:
|
recast@0.23.11:
|
||||||
resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==}
|
resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==}
|
||||||
engines: {node: '>= 4'}
|
engines: {node: '>= 4'}
|
||||||
@@ -7567,8 +7559,9 @@ packages:
|
|||||||
tinyexec@0.3.2:
|
tinyexec@0.3.2:
|
||||||
resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
|
resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
|
||||||
|
|
||||||
tinyexec@1.0.1:
|
tinyexec@1.0.2:
|
||||||
resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==}
|
resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
tinyglobby@0.2.15:
|
tinyglobby@0.2.15:
|
||||||
resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
|
resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
|
||||||
@@ -7772,8 +7765,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
|
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
|
||||||
engines: {node: '>= 10.0.0'}
|
engines: {node: '>= 10.0.0'}
|
||||||
|
|
||||||
unplugin-icons@0.22.0:
|
unplugin-icons@22.5.0:
|
||||||
resolution: {integrity: sha512-CP+iZq5U7doOifer5bcM0jQ9t3Is7EGybIYt3myVxceI8Zuk8EZEpe1NPtJvh7iqMs1VdbK0L41t9+um9VuuLw==}
|
resolution: {integrity: sha512-MBlMtT5RuMYZy4TZgqUL2OTtOdTUVsS1Mhj6G1pEzMlFJlEnq6mhUfoIt45gBWxHcsOdXJDWLg3pRZ+YmvAVWQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@svgr/core': '>=7.0.0'
|
'@svgr/core': '>=7.0.0'
|
||||||
'@svgx/core': ^1.0.1
|
'@svgx/core': ^1.0.1
|
||||||
@@ -7804,12 +7797,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==}
|
resolution: {integrity: sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==}
|
||||||
engines: {node: '>=20.19.0'}
|
engines: {node: '>=20.19.0'}
|
||||||
|
|
||||||
unplugin-vue-components@0.28.0:
|
unplugin-vue-components@30.0.0:
|
||||||
resolution: {integrity: sha512-jiTGtJ3JsRFBjgvyilfrX7yUoGKScFgbdNw+6p6kEXU+Spf/rhxzgvdfuMcvhCcLmflB/dY3pGQshYBVGOUx7Q==}
|
resolution: {integrity: sha512-4qVE/lwCgmdPTp6h0qsRN2u642tt4boBQtcpn4wQcWZAsr8TQwq+SPT3NDu/6kBFxzo/sSEK4ioXhOOBrXc3iw==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@babel/parser': ^7.15.8
|
'@babel/parser': ^7.15.8
|
||||||
'@nuxt/kit': ^3.2.2
|
'@nuxt/kit': ^3.2.2 || ^4.0.0
|
||||||
vue: 2 || 3
|
vue: 2 || 3
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
'@babel/parser':
|
'@babel/parser':
|
||||||
@@ -8411,19 +8404,10 @@ snapshots:
|
|||||||
'@jridgewell/gen-mapping': 0.3.13
|
'@jridgewell/gen-mapping': 0.3.13
|
||||||
'@jridgewell/trace-mapping': 0.3.31
|
'@jridgewell/trace-mapping': 0.3.31
|
||||||
|
|
||||||
'@antfu/install-pkg@0.5.0':
|
|
||||||
dependencies:
|
|
||||||
package-manager-detector: 0.2.11
|
|
||||||
tinyexec: 0.3.2
|
|
||||||
|
|
||||||
'@antfu/install-pkg@1.1.0':
|
'@antfu/install-pkg@1.1.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
package-manager-detector: 1.3.0
|
package-manager-detector: 1.6.0
|
||||||
tinyexec: 1.0.1
|
tinyexec: 1.0.2
|
||||||
|
|
||||||
'@antfu/utils@0.7.10': {}
|
|
||||||
|
|
||||||
'@antfu/utils@8.1.1': {}
|
|
||||||
|
|
||||||
'@asamuzakjp/css-color@3.2.0':
|
'@asamuzakjp/css-color@3.2.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -9797,18 +9781,11 @@ snapshots:
|
|||||||
|
|
||||||
'@iconify/types@2.0.0': {}
|
'@iconify/types@2.0.0': {}
|
||||||
|
|
||||||
'@iconify/utils@2.3.0':
|
'@iconify/utils@3.1.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@antfu/install-pkg': 1.1.0
|
'@antfu/install-pkg': 1.1.0
|
||||||
'@antfu/utils': 8.1.1
|
|
||||||
'@iconify/types': 2.0.0
|
'@iconify/types': 2.0.0
|
||||||
debug: 4.4.3
|
|
||||||
globals: 15.15.0
|
|
||||||
kolorist: 1.8.0
|
|
||||||
local-pkg: 1.1.2
|
|
||||||
mlly: 1.8.0
|
mlly: 1.8.0
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
|
|
||||||
'@internationalized/date@3.9.0':
|
'@internationalized/date@3.9.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -12442,6 +12419,10 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
|
|
||||||
|
chokidar@4.0.3:
|
||||||
|
dependencies:
|
||||||
|
readdirp: 4.1.2
|
||||||
|
|
||||||
chownr@3.0.0: {}
|
chownr@3.0.0: {}
|
||||||
|
|
||||||
clean-css@5.3.3:
|
clean-css@5.3.3:
|
||||||
@@ -13274,7 +13255,7 @@ snapshots:
|
|||||||
|
|
||||||
expect-type@1.2.2: {}
|
expect-type@1.2.2: {}
|
||||||
|
|
||||||
exsolve@1.0.7: {}
|
exsolve@1.0.8: {}
|
||||||
|
|
||||||
extend-shallow@2.0.1:
|
extend-shallow@2.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -14313,11 +14294,6 @@ snapshots:
|
|||||||
rfdc: 1.4.1
|
rfdc: 1.4.1
|
||||||
wrap-ansi: 9.0.2
|
wrap-ansi: 9.0.2
|
||||||
|
|
||||||
local-pkg@0.5.1:
|
|
||||||
dependencies:
|
|
||||||
mlly: 1.8.0
|
|
||||||
pkg-types: 1.3.1
|
|
||||||
|
|
||||||
local-pkg@1.1.2:
|
local-pkg@1.1.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
mlly: 1.8.0
|
mlly: 1.8.0
|
||||||
@@ -15188,11 +15164,7 @@ snapshots:
|
|||||||
registry-url: 6.0.1
|
registry-url: 6.0.1
|
||||||
semver: 7.7.3
|
semver: 7.7.3
|
||||||
|
|
||||||
package-manager-detector@0.2.11:
|
package-manager-detector@1.6.0: {}
|
||||||
dependencies:
|
|
||||||
quansync: 0.2.11
|
|
||||||
|
|
||||||
package-manager-detector@1.3.0: {}
|
|
||||||
|
|
||||||
pako@1.0.11: {}
|
pako@1.0.11: {}
|
||||||
|
|
||||||
@@ -15282,7 +15254,7 @@ snapshots:
|
|||||||
pkg-types@2.3.0:
|
pkg-types@2.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
confbox: 0.2.2
|
confbox: 0.2.2
|
||||||
exsolve: 1.0.7
|
exsolve: 1.0.8
|
||||||
pathe: 2.0.3
|
pathe: 2.0.3
|
||||||
|
|
||||||
playwright-core@1.52.0: {}
|
playwright-core@1.52.0: {}
|
||||||
@@ -15617,6 +15589,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
picomatch: 2.3.1
|
picomatch: 2.3.1
|
||||||
|
|
||||||
|
readdirp@4.1.2: {}
|
||||||
|
|
||||||
recast@0.23.11:
|
recast@0.23.11:
|
||||||
dependencies:
|
dependencies:
|
||||||
ast-types: 0.16.1
|
ast-types: 0.16.1
|
||||||
@@ -16283,7 +16257,7 @@ snapshots:
|
|||||||
|
|
||||||
tinyexec@0.3.2: {}
|
tinyexec@0.3.2: {}
|
||||||
|
|
||||||
tinyexec@1.0.1: {}
|
tinyexec@1.0.2: {}
|
||||||
|
|
||||||
tinyglobby@0.2.15:
|
tinyglobby@0.2.15:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -16498,14 +16472,12 @@ snapshots:
|
|||||||
|
|
||||||
universalify@2.0.1: {}
|
universalify@2.0.1: {}
|
||||||
|
|
||||||
unplugin-icons@0.22.0(@vue/compiler-sfc@3.5.25):
|
unplugin-icons@22.5.0(@vue/compiler-sfc@3.5.25):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@antfu/install-pkg': 0.5.0
|
'@antfu/install-pkg': 1.1.0
|
||||||
'@antfu/utils': 0.7.10
|
'@iconify/utils': 3.1.0
|
||||||
'@iconify/utils': 2.3.0
|
|
||||||
debug: 4.4.3
|
debug: 4.4.3
|
||||||
kolorist: 1.8.0
|
local-pkg: 1.1.2
|
||||||
local-pkg: 0.5.1
|
|
||||||
unplugin: 2.3.11
|
unplugin: 2.3.11
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@vue/compiler-sfc': 3.5.25
|
'@vue/compiler-sfc': 3.5.25
|
||||||
@@ -16530,23 +16502,20 @@ snapshots:
|
|||||||
pathe: 2.0.3
|
pathe: 2.0.3
|
||||||
picomatch: 4.0.3
|
picomatch: 4.0.3
|
||||||
|
|
||||||
unplugin-vue-components@0.28.0(@babel/parser@7.28.5)(rollup@4.53.5)(vue@3.5.13(typescript@5.9.3)):
|
unplugin-vue-components@30.0.0(@babel/parser@7.28.5)(vue@3.5.13(typescript@5.9.3)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@antfu/utils': 0.7.10
|
chokidar: 4.0.3
|
||||||
'@rollup/pluginutils': 5.3.0(rollup@4.53.5)
|
|
||||||
chokidar: 3.6.0
|
|
||||||
debug: 4.4.3
|
debug: 4.4.3
|
||||||
fast-glob: 3.3.3
|
local-pkg: 1.1.2
|
||||||
local-pkg: 0.5.1
|
|
||||||
magic-string: 0.30.21
|
magic-string: 0.30.21
|
||||||
minimatch: 9.0.5
|
|
||||||
mlly: 1.8.0
|
mlly: 1.8.0
|
||||||
|
tinyglobby: 0.2.15
|
||||||
unplugin: 2.3.11
|
unplugin: 2.3.11
|
||||||
|
unplugin-utils: 0.3.1
|
||||||
vue: 3.5.13(typescript@5.9.3)
|
vue: 3.5.13(typescript@5.9.3)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@babel/parser': 7.28.5
|
'@babel/parser': 7.28.5
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- rollup
|
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
unplugin@1.0.1:
|
unplugin@1.0.1:
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
packages:
|
|
||||||
- apps/**
|
|
||||||
- packages/**
|
|
||||||
|
|
||||||
catalog:
|
catalog:
|
||||||
'@alloc/quick-lru': ^5.2.0
|
'@alloc/quick-lru': ^5.2.0
|
||||||
'@comfyorg/comfyui-electron-types': 0.5.5
|
'@comfyorg/comfyui-electron-types': 0.5.5
|
||||||
@@ -89,9 +85,9 @@ catalog:
|
|||||||
typegpu: ^0.8.2
|
typegpu: ^0.8.2
|
||||||
typescript: ^5.9.3
|
typescript: ^5.9.3
|
||||||
typescript-eslint: ^8.49.0
|
typescript-eslint: ^8.49.0
|
||||||
unplugin-icons: ^0.22.0
|
unplugin-icons: ^22.5.0
|
||||||
unplugin-typegpu: 0.8.0
|
unplugin-typegpu: 0.8.0
|
||||||
unplugin-vue-components: ^0.28.0
|
unplugin-vue-components: ^30.0.0
|
||||||
vite: ^7.3.0
|
vite: ^7.3.0
|
||||||
vite-plugin-dts: ^4.5.4
|
vite-plugin-dts: ^4.5.4
|
||||||
vite-plugin-html: ^3.2.2
|
vite-plugin-html: ^3.2.2
|
||||||
@@ -108,15 +104,12 @@ catalog:
|
|||||||
zod: ^3.23.8
|
zod: ^3.23.8
|
||||||
zod-to-json-schema: ^3.24.1
|
zod-to-json-schema: ^3.24.1
|
||||||
zod-validation-error: ^3.3.0
|
zod-validation-error: ^3.3.0
|
||||||
|
|
||||||
cleanupUnusedCatalogs: true
|
cleanupUnusedCatalogs: true
|
||||||
|
|
||||||
ignoredBuiltDependencies:
|
ignoredBuiltDependencies:
|
||||||
- '@firebase/util'
|
- '@firebase/util'
|
||||||
- protobufjs
|
- protobufjs
|
||||||
- unrs-resolver
|
- unrs-resolver
|
||||||
- vue-demi
|
- vue-demi
|
||||||
|
|
||||||
onlyBuiltDependencies:
|
onlyBuiltDependencies:
|
||||||
- '@playwright/browser-chromium'
|
- '@playwright/browser-chromium'
|
||||||
- '@playwright/browser-firefox'
|
- '@playwright/browser-firefox'
|
||||||
@@ -126,6 +119,8 @@ onlyBuiltDependencies:
|
|||||||
- esbuild
|
- esbuild
|
||||||
- nx
|
- nx
|
||||||
- oxc-resolver
|
- oxc-resolver
|
||||||
|
|
||||||
overrides:
|
overrides:
|
||||||
'@types/eslint': '-'
|
'@types/eslint': '-'
|
||||||
|
packages:
|
||||||
|
- apps/**
|
||||||
|
- packages/**
|
||||||
@@ -15,20 +15,19 @@
|
|||||||
v-if="managerState.shouldShowManagerButtons.value && isDesktop"
|
v-if="managerState.shouldShowManagerButtons.value && isDesktop"
|
||||||
class="pointer-events-auto flex h-12 shrink-0 items-center rounded-lg border border-interface-stroke bg-comfy-menu-bg px-2 shadow-interface"
|
class="pointer-events-auto flex h-12 shrink-0 items-center rounded-lg border border-interface-stroke bg-comfy-menu-bg px-2 shadow-interface"
|
||||||
>
|
>
|
||||||
<IconButton
|
<Button
|
||||||
v-tooltip.bottom="customNodesManagerTooltipConfig"
|
v-tooltip.bottom="customNodesManagerTooltipConfig"
|
||||||
type="transparent"
|
variant="secondary"
|
||||||
size="sm"
|
size="icon"
|
||||||
class="text-base-foreground transition-colors duration-200 ease-in-out bg-secondary-background hover:bg-secondary-background-hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-background"
|
|
||||||
:aria-label="t('menu.customNodesManager')"
|
:aria-label="t('menu.customNodesManager')"
|
||||||
@click="openCustomNodeManager"
|
@click="openCustomNodeManager"
|
||||||
>
|
>
|
||||||
<i class="icon-[lucide--puzzle] size-4" />
|
<i class="icon-[lucide--puzzle] size-4" />
|
||||||
</IconButton>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="actionbar-container pointer-events-auto flex h-12 items-center rounded-lg border border-interface-stroke bg-comfy-menu-bg px-2 shadow-interface"
|
class="actionbar-container pointer-events-auto flex gap-2 h-12 items-center rounded-lg border border-interface-stroke bg-comfy-menu-bg px-2 shadow-interface"
|
||||||
>
|
>
|
||||||
<ActionBarButtons />
|
<ActionBarButtons />
|
||||||
<!-- Support for legacy topbar elements attached by custom scripts, hidden if no elements present -->
|
<!-- Support for legacy topbar elements attached by custom scripts, hidden if no elements present -->
|
||||||
@@ -37,11 +36,10 @@
|
|||||||
class="[&:not(:has(*>*:not(:empty)))]:hidden"
|
class="[&:not(:has(*>*:not(:empty)))]:hidden"
|
||||||
></div>
|
></div>
|
||||||
<ComfyActionbar />
|
<ComfyActionbar />
|
||||||
<IconButton
|
<Button
|
||||||
v-tooltip.bottom="queueHistoryTooltipConfig"
|
v-tooltip.bottom="queueHistoryTooltipConfig"
|
||||||
type="transparent"
|
type="destructive"
|
||||||
size="sm"
|
size="icon"
|
||||||
class="relative mr-2 text-base-foreground transition-colors duration-200 ease-in-out bg-secondary-background hover:bg-secondary-background-hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-background"
|
|
||||||
:aria-pressed="isQueueOverlayExpanded"
|
:aria-pressed="isQueueOverlayExpanded"
|
||||||
:aria-label="
|
:aria-label="
|
||||||
t('sideToolbar.queueProgressOverlay.expandCollapsedQueue')
|
t('sideToolbar.queueProgressOverlay.expandCollapsedQueue')
|
||||||
@@ -55,20 +53,19 @@
|
|||||||
>
|
>
|
||||||
{{ queuedCount }}
|
{{ queuedCount }}
|
||||||
</span>
|
</span>
|
||||||
</IconButton>
|
</Button>
|
||||||
<CurrentUserButton v-if="isLoggedIn" class="shrink-0" />
|
<CurrentUserButton v-if="isLoggedIn" class="shrink-0" />
|
||||||
<LoginButton v-else-if="isDesktop" />
|
<LoginButton v-else-if="isDesktop" />
|
||||||
<IconButton
|
<Button
|
||||||
v-if="!isRightSidePanelOpen"
|
v-if="!isRightSidePanelOpen"
|
||||||
v-tooltip.bottom="rightSidePanelTooltipConfig"
|
v-tooltip.bottom="rightSidePanelTooltipConfig"
|
||||||
type="transparent"
|
type="secondary"
|
||||||
size="sm"
|
size="icon"
|
||||||
class="mr-2 text-base-foreground transition-colors duration-200 ease-in-out bg-secondary-background hover:bg-secondary-background-hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-background"
|
|
||||||
:aria-label="t('rightSidePanel.togglePanel')"
|
:aria-label="t('rightSidePanel.togglePanel')"
|
||||||
@click="rightSidePanelStore.togglePanel"
|
@click="rightSidePanelStore.togglePanel"
|
||||||
>
|
>
|
||||||
<i class="icon-[lucide--panel-right] size-4" />
|
<i class="icon-[lucide--panel-right] size-4" />
|
||||||
</IconButton>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<QueueProgressOverlay
|
<QueueProgressOverlay
|
||||||
@@ -86,11 +83,11 @@ import { useI18n } from 'vue-i18n'
|
|||||||
|
|
||||||
import ComfyActionbar from '@/components/actionbar/ComfyActionbar.vue'
|
import ComfyActionbar from '@/components/actionbar/ComfyActionbar.vue'
|
||||||
import SubgraphBreadcrumb from '@/components/breadcrumb/SubgraphBreadcrumb.vue'
|
import SubgraphBreadcrumb from '@/components/breadcrumb/SubgraphBreadcrumb.vue'
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
|
||||||
import QueueProgressOverlay from '@/components/queue/QueueProgressOverlay.vue'
|
import QueueProgressOverlay from '@/components/queue/QueueProgressOverlay.vue'
|
||||||
import ActionBarButtons from '@/components/topbar/ActionBarButtons.vue'
|
import ActionBarButtons from '@/components/topbar/ActionBarButtons.vue'
|
||||||
import CurrentUserButton from '@/components/topbar/CurrentUserButton.vue'
|
import CurrentUserButton from '@/components/topbar/CurrentUserButton.vue'
|
||||||
import LoginButton from '@/components/topbar/LoginButton.vue'
|
import LoginButton from '@/components/topbar/LoginButton.vue'
|
||||||
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
import { useCurrentUser } from '@/composables/auth/useCurrentUser'
|
import { useCurrentUser } from '@/composables/auth/useCurrentUser'
|
||||||
import { useErrorHandling } from '@/composables/useErrorHandling'
|
import { useErrorHandling } from '@/composables/useErrorHandling'
|
||||||
import { buildTooltipConfig } from '@/composables/useTooltipConfig'
|
import { buildTooltipConfig } from '@/composables/useTooltipConfig'
|
||||||
|
|||||||
@@ -18,12 +18,12 @@
|
|||||||
content: { class: isDocked ? 'p-0' : 'p-1' }
|
content: { class: isDocked ? 'p-0' : 'p-1' }
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div ref="panelRef" class="flex items-center select-none">
|
<div ref="panelRef" class="flex items-center select-none gap-2">
|
||||||
<span
|
<span
|
||||||
ref="dragHandleRef"
|
ref="dragHandleRef"
|
||||||
:class="
|
:class="
|
||||||
cn(
|
cn(
|
||||||
'drag-handle cursor-grab w-3 h-max mr-2',
|
'drag-handle cursor-grab w-3 h-max',
|
||||||
isDragging && 'cursor-grabbing'
|
isDragging && 'cursor-grabbing'
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
@@ -31,17 +31,16 @@
|
|||||||
<Suspense @resolve="comfyRunButtonResolved">
|
<Suspense @resolve="comfyRunButtonResolved">
|
||||||
<ComfyRunButton />
|
<ComfyRunButton />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
<IconButton
|
<Button
|
||||||
v-tooltip.bottom="cancelJobTooltipConfig"
|
v-tooltip.bottom="cancelJobTooltipConfig"
|
||||||
type="transparent"
|
variant="destructive"
|
||||||
size="sm"
|
size="icon"
|
||||||
class="ml-2 bg-destructive-background text-base-foreground transition-colors duration-200 ease-in-out hover:bg-destructive-background-hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-destructive-background"
|
|
||||||
:disabled="isExecutionIdle"
|
:disabled="isExecutionIdle"
|
||||||
:aria-label="t('menu.interrupt')"
|
:aria-label="t('menu.interrupt')"
|
||||||
@click="cancelCurrentJob"
|
@click="cancelCurrentJob"
|
||||||
>
|
>
|
||||||
<i class="icon-[lucide--x] size-4" />
|
<i class="icon-[lucide--x] size-4" />
|
||||||
</IconButton>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Panel>
|
</Panel>
|
||||||
</div>
|
</div>
|
||||||
@@ -58,10 +57,10 @@ import { clamp } from 'es-toolkit/compat'
|
|||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import Panel from 'primevue/panel'
|
import Panel from 'primevue/panel'
|
||||||
import { computed, nextTick, ref, watch } from 'vue'
|
import { computed, nextTick, ref, watch } from 'vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
import { buildTooltipConfig } from '@/composables/useTooltipConfig'
|
import { buildTooltipConfig } from '@/composables/useTooltipConfig'
|
||||||
import { t } from '@/i18n'
|
|
||||||
import { useSettingStore } from '@/platform/settings/settingStore'
|
import { useSettingStore } from '@/platform/settings/settingStore'
|
||||||
import { useTelemetry } from '@/platform/telemetry'
|
import { useTelemetry } from '@/platform/telemetry'
|
||||||
import { useCommandStore } from '@/stores/commandStore'
|
import { useCommandStore } from '@/stores/commandStore'
|
||||||
@@ -72,6 +71,7 @@ import ComfyRunButton from './ComfyRunButton'
|
|||||||
|
|
||||||
const settingsStore = useSettingStore()
|
const settingsStore = useSettingStore()
|
||||||
const commandStore = useCommandStore()
|
const commandStore = useCommandStore()
|
||||||
|
const { t } = useI18n()
|
||||||
const { isIdle: isExecutionIdle } = storeToRefs(useExecutionStore())
|
const { isIdle: isExecutionIdle } = storeToRefs(useExecutionStore())
|
||||||
|
|
||||||
const position = computed(() => settingsStore.get('Comfy.UseNewMenu'))
|
const position = computed(() => settingsStore.get('Comfy.UseNewMenu'))
|
||||||
@@ -301,7 +301,7 @@ const panelClass = computed(() =>
|
|||||||
'actionbar pointer-events-auto z-1300',
|
'actionbar pointer-events-auto z-1300',
|
||||||
isDragging.value && 'select-none pointer-events-none',
|
isDragging.value && 'select-none pointer-events-none',
|
||||||
isDocked.value
|
isDocked.value
|
||||||
? 'p-0 static mr-2 border-none bg-transparent'
|
? 'p-0 static border-none bg-transparent'
|
||||||
: 'fixed shadow-interface'
|
: 'fixed shadow-interface'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,152 +0,0 @@
|
|||||||
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
|
||||||
|
|
||||||
import IconButton from './IconButton.vue'
|
|
||||||
|
|
||||||
const meta: Meta<typeof IconButton> = {
|
|
||||||
title: 'Components/Button/IconButton',
|
|
||||||
component: IconButton,
|
|
||||||
tags: ['autodocs'],
|
|
||||||
argTypes: {
|
|
||||||
size: {
|
|
||||||
control: { type: 'select' },
|
|
||||||
options: ['sm', 'md']
|
|
||||||
},
|
|
||||||
type: {
|
|
||||||
control: { type: 'select' },
|
|
||||||
options: ['primary', 'secondary', 'transparent']
|
|
||||||
},
|
|
||||||
border: {
|
|
||||||
control: 'boolean',
|
|
||||||
description: 'Toggle border attribute'
|
|
||||||
},
|
|
||||||
disabled: {
|
|
||||||
control: 'boolean',
|
|
||||||
description: 'Toggle disable status'
|
|
||||||
},
|
|
||||||
onClick: { action: 'clicked' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default meta
|
|
||||||
type Story = StoryObj<typeof meta>
|
|
||||||
|
|
||||||
export const Primary: Story = {
|
|
||||||
render: (args) => ({
|
|
||||||
components: { IconButton },
|
|
||||||
setup() {
|
|
||||||
return { args }
|
|
||||||
},
|
|
||||||
template: `
|
|
||||||
<IconButton v-bind="args">
|
|
||||||
<i class="icon-[lucide--trophy] size-4" />
|
|
||||||
</IconButton>
|
|
||||||
`
|
|
||||||
}),
|
|
||||||
args: {
|
|
||||||
type: 'primary',
|
|
||||||
size: 'md'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Secondary: Story = {
|
|
||||||
render: (args) => ({
|
|
||||||
components: { IconButton },
|
|
||||||
setup() {
|
|
||||||
return { args }
|
|
||||||
},
|
|
||||||
template: `
|
|
||||||
<IconButton v-bind="args">
|
|
||||||
<i class="icon-[lucide--settings] size-4" />
|
|
||||||
</IconButton>
|
|
||||||
`
|
|
||||||
}),
|
|
||||||
args: {
|
|
||||||
type: 'secondary',
|
|
||||||
size: 'md'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Transparent: Story = {
|
|
||||||
render: (args) => ({
|
|
||||||
components: { IconButton },
|
|
||||||
setup() {
|
|
||||||
return { args }
|
|
||||||
},
|
|
||||||
template: `
|
|
||||||
<IconButton v-bind="args">
|
|
||||||
<i class="icon-[lucide--x] size-4" />
|
|
||||||
</IconButton>
|
|
||||||
`
|
|
||||||
}),
|
|
||||||
args: {
|
|
||||||
type: 'transparent',
|
|
||||||
size: 'md'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Small: Story = {
|
|
||||||
render: (args) => ({
|
|
||||||
components: { IconButton },
|
|
||||||
setup() {
|
|
||||||
return { args }
|
|
||||||
},
|
|
||||||
template: `
|
|
||||||
<IconButton v-bind="args">
|
|
||||||
<i class="icon-[lucide--bell] size-3" />
|
|
||||||
</IconButton>
|
|
||||||
`
|
|
||||||
}),
|
|
||||||
args: {
|
|
||||||
type: 'secondary',
|
|
||||||
size: 'sm'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const AllVariants: Story = {
|
|
||||||
render: () => ({
|
|
||||||
components: { IconButton },
|
|
||||||
template: `
|
|
||||||
<div class="flex flex-col gap-4">
|
|
||||||
<div class="flex gap-2 items-center">
|
|
||||||
<IconButton type="primary" size="sm" @click="() => {}">
|
|
||||||
<i class="icon-[lucide--trophy] size-3" />
|
|
||||||
</IconButton>
|
|
||||||
<IconButton type="primary" size="md" @click="() => {}">
|
|
||||||
<i class="icon-[lucide--trophy] size-4" />
|
|
||||||
</IconButton>
|
|
||||||
</div>
|
|
||||||
<div class="flex gap-2 items-center">
|
|
||||||
<IconButton type="secondary" size="sm" @click="() => {}">
|
|
||||||
<i class="icon-[lucide--settings] size-3" />
|
|
||||||
</IconButton>
|
|
||||||
<IconButton type="secondary" size="md" @click="() => {}">
|
|
||||||
<i class="icon-[lucide--settings] size-4" />
|
|
||||||
</IconButton>
|
|
||||||
</div>
|
|
||||||
<div class="flex gap-2 items-center">
|
|
||||||
<IconButton type="transparent" size="sm" @click="() => {}">
|
|
||||||
<i class="icon-[lucide--x] size-3" />
|
|
||||||
</IconButton>
|
|
||||||
<IconButton type="transparent" size="md" @click="() => {}">
|
|
||||||
<i class="icon-[lucide--x] size-4" />
|
|
||||||
</IconButton>
|
|
||||||
</div>
|
|
||||||
<div class="flex gap-2 items-center">
|
|
||||||
<IconButton type="primary" size="md" @click="() => {}">
|
|
||||||
<i class="icon-[lucide--bell] size-4" />
|
|
||||||
</IconButton>
|
|
||||||
<IconButton type="secondary" size="md" @click="() => {}">
|
|
||||||
<i class="icon-[lucide--heart] size-4" />
|
|
||||||
</IconButton>
|
|
||||||
<IconButton type="transparent" size="md" @click="() => {}">
|
|
||||||
<i class="icon-[lucide--download] size-4" />
|
|
||||||
</IconButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`
|
|
||||||
}),
|
|
||||||
parameters: {
|
|
||||||
controls: { disable: true },
|
|
||||||
actions: { disable: true }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
<template>
|
|
||||||
<Button
|
|
||||||
v-bind="$attrs"
|
|
||||||
unstyled
|
|
||||||
:class="buttonStyle"
|
|
||||||
:disabled="disabled"
|
|
||||||
@click="onClick"
|
|
||||||
>
|
|
||||||
<slot></slot>
|
|
||||||
</Button>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import Button from 'primevue/button'
|
|
||||||
import { computed } from 'vue'
|
|
||||||
|
|
||||||
import type { BaseButtonProps } from '@/types/buttonTypes'
|
|
||||||
import {
|
|
||||||
getBaseButtonClasses,
|
|
||||||
getBorderButtonTypeClasses,
|
|
||||||
getButtonTypeClasses,
|
|
||||||
getIconButtonSizeClasses
|
|
||||||
} from '@/types/buttonTypes'
|
|
||||||
import { cn } from '@/utils/tailwindUtil'
|
|
||||||
|
|
||||||
interface IconButtonProps extends BaseButtonProps {
|
|
||||||
onClick?: (event: MouseEvent) => void
|
|
||||||
}
|
|
||||||
|
|
||||||
defineOptions({
|
|
||||||
inheritAttrs: false
|
|
||||||
})
|
|
||||||
|
|
||||||
const {
|
|
||||||
size = 'md',
|
|
||||||
type = 'secondary',
|
|
||||||
border = false,
|
|
||||||
disabled = false,
|
|
||||||
class: className,
|
|
||||||
onClick
|
|
||||||
} = defineProps<IconButtonProps>()
|
|
||||||
|
|
||||||
const buttonStyle = computed(() => {
|
|
||||||
const baseClasses = `${getBaseButtonClasses()} p-0`
|
|
||||||
const sizeClasses = getIconButtonSizeClasses(size)
|
|
||||||
const typeClasses = border
|
|
||||||
? getBorderButtonTypeClasses(type)
|
|
||||||
: getButtonTypeClasses(type)
|
|
||||||
|
|
||||||
return cn(baseClasses, sizeClasses, typeClasses, className)
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
||||||
|
|
||||||
import IconButton from './IconButton.vue'
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
import IconGroup from './IconGroup.vue'
|
import IconGroup from './IconGroup.vue'
|
||||||
|
|
||||||
const meta: Meta<typeof IconGroup> = {
|
const meta: Meta<typeof IconGroup> = {
|
||||||
@@ -16,18 +16,18 @@ type Story = StoryObj<typeof IconGroup>
|
|||||||
|
|
||||||
export const Basic: Story = {
|
export const Basic: Story = {
|
||||||
render: () => ({
|
render: () => ({
|
||||||
components: { IconGroup, IconButton },
|
components: { IconGroup, Button },
|
||||||
template: `
|
template: `
|
||||||
<IconGroup>
|
<IconGroup>
|
||||||
<IconButton @click="console.log('Hello World!!')">
|
<Button size="icon" @click="console.log('Hello World!!')">
|
||||||
<i class="icon-[lucide--heart] size-4" />
|
<i class="icon-[lucide--heart] size-4" />
|
||||||
</IconButton>
|
</Button>
|
||||||
<IconButton @click="console.log('Hello World!!')">
|
<Button size="icon" @click="console.log('Hello World!!')">
|
||||||
<i class="icon-[lucide--download] size-4" />
|
<i class="icon-[lucide--download] size-4" />
|
||||||
</IconButton>
|
</Button>
|
||||||
<IconButton @click="console.log('Hello World!!')">
|
<Button size="icon" @click="console.log('Hello World!!')">
|
||||||
<i class="icon-[lucide--external-link] size-4" />
|
<i class="icon-[lucide--external-link] size-4" />
|
||||||
</IconButton>
|
</Button>
|
||||||
</IconGroup>
|
</IconGroup>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,9 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="relative inline-flex items-center">
|
<div class="relative inline-flex items-center">
|
||||||
<IconButton :size="size" :type="type" @click="popover?.toggle">
|
<Button size="icon" variant="secondary" @click="popover?.toggle">
|
||||||
<i v-if="!isVertical" class="icon-[lucide--ellipsis] text-sm" />
|
<i
|
||||||
<i v-else class="icon-[lucide--more-vertical] text-sm" />
|
:class="
|
||||||
</IconButton>
|
cn(
|
||||||
|
!isVertical
|
||||||
|
? 'icon-[lucide--ellipsis]'
|
||||||
|
: 'icon-[lucide--more-vertical]',
|
||||||
|
'text-sm'
|
||||||
|
)
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
|
||||||
<Popover
|
<Popover
|
||||||
ref="popover"
|
ref="popover"
|
||||||
@@ -49,20 +57,14 @@
|
|||||||
import Popover from 'primevue/popover'
|
import Popover from 'primevue/popover'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
import type { BaseButtonProps } from '@/types/buttonTypes'
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
import { cn } from '@/utils/tailwindUtil'
|
import { cn } from '@/utils/tailwindUtil'
|
||||||
|
|
||||||
import IconButton from './IconButton.vue'
|
interface MoreButtonProps {
|
||||||
|
|
||||||
interface MoreButtonProps extends BaseButtonProps {
|
|
||||||
isVertical?: boolean
|
isVertical?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const { isVertical = false } = defineProps<MoreButtonProps>()
|
||||||
size = 'md',
|
|
||||||
type = 'secondary',
|
|
||||||
isVertical = false
|
|
||||||
} = defineProps<MoreButtonProps>()
|
|
||||||
|
|
||||||
defineEmits<{
|
defineEmits<{
|
||||||
menuOpened: []
|
menuOpened: []
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
import IconButton from '../button/IconButton.vue'
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
import SquareChip from '../chip/SquareChip.vue'
|
import SquareChip from '../chip/SquareChip.vue'
|
||||||
import CardBottom from './CardBottom.vue'
|
import CardBottom from './CardBottom.vue'
|
||||||
import CardContainer from './CardContainer.vue'
|
import CardContainer from './CardContainer.vue'
|
||||||
@@ -173,7 +173,7 @@ const createCardTemplate = (args: CardStoryArgs) => ({
|
|||||||
CardBottom,
|
CardBottom,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
CardDescription,
|
CardDescription,
|
||||||
IconButton,
|
Button,
|
||||||
SquareChip
|
SquareChip
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
@@ -222,19 +222,19 @@ const createCardTemplate = (args: CardStoryArgs) => ({
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="args.showTopRight" #top-right>
|
<template v-if="args.showTopRight" #top-right>
|
||||||
<IconButton
|
<Button
|
||||||
class="!bg-white/90 !text-neutral-900"
|
class="!bg-white/90 !text-neutral-900"
|
||||||
@click="() => console.log('Info clicked')"
|
@click="() => console.log('Info clicked')"
|
||||||
>
|
>
|
||||||
<i class="icon-[lucide--info] size-4" />
|
<i class="icon-[lucide--info] size-4" />
|
||||||
</IconButton>
|
</Button>
|
||||||
<IconButton
|
<Button
|
||||||
class="!bg-white/90"
|
class="!bg-white/90"
|
||||||
:class="favorited ? '!text-red-500' : '!text-neutral-900'"
|
:class="favorited ? '!text-red-500' : '!text-neutral-900'"
|
||||||
@click="toggleFavorite"
|
@click="toggleFavorite"
|
||||||
>
|
>
|
||||||
<i class="icon-[lucide--heart] size-4" :class="favorited ? 'fill-current' : ''" />
|
<i class="icon-[lucide--heart] size-4" :class="favorited ? 'fill-current' : ''" />
|
||||||
</IconButton>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="args.showBottomLeft" #bottom-left>
|
<template v-if="args.showBottomLeft" #bottom-left>
|
||||||
|
|||||||
@@ -17,22 +17,25 @@
|
|||||||
class="absolute inset-0 size-full pl-11 border-none outline-none bg-transparent text-sm"
|
class="absolute inset-0 size-full pl-11 border-none outline-none bg-transparent text-sm"
|
||||||
:aria-label="placeholder"
|
:aria-label="placeholder"
|
||||||
/>
|
/>
|
||||||
<IconButton
|
<Button
|
||||||
v-if="filterIcon"
|
v-if="filterIcon"
|
||||||
class="p-inputicon filter-button absolute right-0 inset-y-0 h-full m-0 p-0"
|
size="icon"
|
||||||
:icon="filterIcon"
|
variant="textonly"
|
||||||
severity="contrast"
|
class="filter-button absolute right-0 inset-y-0 m-0 p-0"
|
||||||
@click="$emit('showFilter', $event)"
|
@click="$emit('showFilter', $event)"
|
||||||
/>
|
>
|
||||||
|
<i :class="filterIcon" />
|
||||||
|
</Button>
|
||||||
<InputIcon v-if="!modelValue" :class="icon" />
|
<InputIcon v-if="!modelValue" :class="icon" />
|
||||||
<Button
|
<Button
|
||||||
v-if="modelValue"
|
v-if="modelValue"
|
||||||
class="p-inputicon clear-button"
|
class="clear-button absolute left-0"
|
||||||
icon="pi pi-times"
|
variant="textonly"
|
||||||
text
|
size="icon"
|
||||||
severity="contrast"
|
|
||||||
@click="modelValue = ''"
|
@click="modelValue = ''"
|
||||||
/>
|
>
|
||||||
|
<i class="icon-[lucide--x] size-4" />
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="filters?.length" class="search-filters flex flex-wrap gap-2 pt-2">
|
<div v-if="filters?.length" class="search-filters flex flex-wrap gap-2 pt-2">
|
||||||
<SearchFilterChip
|
<SearchFilterChip
|
||||||
@@ -49,12 +52,12 @@
|
|||||||
<script setup lang="ts" generic="TFilter extends SearchFilter">
|
<script setup lang="ts" generic="TFilter extends SearchFilter">
|
||||||
import { cn } from '@comfyorg/tailwind-utils'
|
import { cn } from '@comfyorg/tailwind-utils'
|
||||||
import { watchDebounced } from '@vueuse/core'
|
import { watchDebounced } from '@vueuse/core'
|
||||||
import Button from 'primevue/button'
|
|
||||||
import InputIcon from 'primevue/inputicon'
|
import InputIcon from 'primevue/inputicon'
|
||||||
import InputText from 'primevue/inputtext'
|
import InputText from 'primevue/inputtext'
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
|
|
||||||
import IconButton from '../button/IconButton.vue'
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
|
|
||||||
import type { SearchFilter } from './SearchFilterChip.vue'
|
import type { SearchFilter } from './SearchFilterChip.vue'
|
||||||
import SearchFilterChip from './SearchFilterChip.vue'
|
import SearchFilterChip from './SearchFilterChip.vue'
|
||||||
|
|
||||||
@@ -125,8 +128,4 @@ const wrapperStyle = computed(() => {
|
|||||||
:deep(.p-inputtext) {
|
:deep(.p-inputtext) {
|
||||||
--p-form-field-padding-x: 0.625rem;
|
--p-form-field-padding-x: 0.625rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-button.p-inputicon {
|
|
||||||
@apply p-0 w-auto border-none;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -301,16 +301,16 @@
|
|||||||
v-if="template.tutorialUrl"
|
v-if="template.tutorialUrl"
|
||||||
class="flex flex-col-reverse justify-center"
|
class="flex flex-col-reverse justify-center"
|
||||||
>
|
>
|
||||||
<IconButton
|
<Button
|
||||||
v-if="hoveredTemplate === template.name"
|
v-if="hoveredTemplate === template.name"
|
||||||
v-tooltip.bottom="$t('g.seeTutorial')"
|
v-tooltip.bottom="$t('g.seeTutorial')"
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
type="primary"
|
variant="inverted"
|
||||||
size="sm"
|
size="icon"
|
||||||
@click.stop="openTutorial(template)"
|
@click.stop="openTutorial(template)"
|
||||||
>
|
>
|
||||||
<i class="icon-[lucide--info] size-4" />
|
<i class="icon-[lucide--info] size-4" />
|
||||||
</IconButton>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -382,7 +382,6 @@ import ProgressSpinner from 'primevue/progressspinner'
|
|||||||
import { computed, onBeforeUnmount, onMounted, provide, ref, watch } from 'vue'
|
import { computed, onBeforeUnmount, onMounted, provide, ref, watch } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
|
||||||
import IconTextButton from '@/components/button/IconTextButton.vue'
|
import IconTextButton from '@/components/button/IconTextButton.vue'
|
||||||
import CardBottom from '@/components/card/CardBottom.vue'
|
import CardBottom from '@/components/card/CardBottom.vue'
|
||||||
import CardContainer from '@/components/card/CardContainer.vue'
|
import CardContainer from '@/components/card/CardContainer.vue'
|
||||||
@@ -395,6 +394,7 @@ import AudioThumbnail from '@/components/templates/thumbnails/AudioThumbnail.vue
|
|||||||
import CompareSliderThumbnail from '@/components/templates/thumbnails/CompareSliderThumbnail.vue'
|
import CompareSliderThumbnail from '@/components/templates/thumbnails/CompareSliderThumbnail.vue'
|
||||||
import DefaultThumbnail from '@/components/templates/thumbnails/DefaultThumbnail.vue'
|
import DefaultThumbnail from '@/components/templates/thumbnails/DefaultThumbnail.vue'
|
||||||
import HoverDissolveThumbnail from '@/components/templates/thumbnails/HoverDissolveThumbnail.vue'
|
import HoverDissolveThumbnail from '@/components/templates/thumbnails/HoverDissolveThumbnail.vue'
|
||||||
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
import BaseModalLayout from '@/components/widget/layout/BaseModalLayout.vue'
|
import BaseModalLayout from '@/components/widget/layout/BaseModalLayout.vue'
|
||||||
import LeftSidePanel from '@/components/widget/panel/LeftSidePanel.vue'
|
import LeftSidePanel from '@/components/widget/panel/LeftSidePanel.vue'
|
||||||
import { useIntersectionObserver } from '@/composables/useIntersectionObserver'
|
import { useIntersectionObserver } from '@/composables/useIntersectionObserver'
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<IconButton
|
<Button
|
||||||
type="secondary"
|
variant="secondary"
|
||||||
size="fit-content"
|
size="lg"
|
||||||
class="group w-full justify-between gap-3 rounded-lg p-1 text-left font-normal hover:cursor-pointer focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-background"
|
class="group w-full justify-between gap-3 p-1 text-left font-normal hover:cursor-pointer focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-background"
|
||||||
:aria-label="props.ariaLabel"
|
:aria-label="props.ariaLabel"
|
||||||
@click="emit('click', $event)"
|
@click="emit('click', $event)"
|
||||||
>
|
>
|
||||||
@@ -81,11 +81,11 @@
|
|||||||
>
|
>
|
||||||
<i class="icon-[lucide--chevron-down] block size-4 leading-none" />
|
<i class="icon-[lucide--chevron-down] block size-4 leading-none" />
|
||||||
</span>
|
</span>
|
||||||
</IconButton>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
import type {
|
import type {
|
||||||
CompletionSummary,
|
CompletionSummary,
|
||||||
CompletionSummaryMode
|
CompletionSummaryMode
|
||||||
|
|||||||
@@ -42,19 +42,18 @@
|
|||||||
t('sideToolbar.queueProgressOverlay.running')
|
t('sideToolbar.queueProgressOverlay.running')
|
||||||
}}</span>
|
}}</span>
|
||||||
</span>
|
</span>
|
||||||
<IconButton
|
<Button
|
||||||
v-if="runningCount > 0"
|
v-if="runningCount > 0"
|
||||||
v-tooltip.top="cancelJobTooltip"
|
v-tooltip.top="cancelJobTooltip"
|
||||||
type="secondary"
|
variant="destructive"
|
||||||
size="sm"
|
size="icon"
|
||||||
class="size-6 bg-destructive-background hover:bg-destructive-background-hover"
|
|
||||||
:aria-label="t('sideToolbar.queueProgressOverlay.interruptAll')"
|
:aria-label="t('sideToolbar.queueProgressOverlay.interruptAll')"
|
||||||
@click="$emit('interruptAll')"
|
@click="$emit('interruptAll')"
|
||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
class="icon-[lucide--x] block size-4 leading-none text-text-primary"
|
class="icon-[lucide--x] block size-4 leading-none text-text-primary"
|
||||||
/>
|
/>
|
||||||
</IconButton>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
@@ -64,26 +63,25 @@
|
|||||||
t('sideToolbar.queueProgressOverlay.queuedSuffix')
|
t('sideToolbar.queueProgressOverlay.queuedSuffix')
|
||||||
}}</span>
|
}}</span>
|
||||||
</span>
|
</span>
|
||||||
<IconButton
|
<Button
|
||||||
v-if="queuedCount > 0"
|
v-if="queuedCount > 0"
|
||||||
v-tooltip.top="clearQueueTooltip"
|
v-tooltip.top="clearQueueTooltip"
|
||||||
type="secondary"
|
variant="destructive"
|
||||||
size="sm"
|
size="icon"
|
||||||
class="size-6 bg-secondary-background hover:bg-destructive-background"
|
|
||||||
:aria-label="t('sideToolbar.queueProgressOverlay.clearQueued')"
|
:aria-label="t('sideToolbar.queueProgressOverlay.clearQueued')"
|
||||||
@click="$emit('clearQueued')"
|
@click="$emit('clearQueued')"
|
||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
class="icon-[lucide--list-x] block size-4 leading-none text-text-primary"
|
class="icon-[lucide--list-x] block size-4 leading-none text-text-primary"
|
||||||
/>
|
/>
|
||||||
</IconButton>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
class="min-w-30 flex-1 px-2 py-0"
|
class="min-w-30 flex-1 px-2 py-0"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
size="sm"
|
size="md"
|
||||||
@click="$emit('viewAllJobs')"
|
@click="$emit('viewAllJobs')"
|
||||||
>
|
>
|
||||||
{{ t('sideToolbar.queueProgressOverlay.viewAllJobs') }}
|
{{ t('sideToolbar.queueProgressOverlay.viewAllJobs') }}
|
||||||
@@ -96,7 +94,6 @@
|
|||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
|
||||||
import Button from '@/components/ui/button/Button.vue'
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
import { buildTooltipConfig } from '@/composables/useTooltipConfig'
|
import { buildTooltipConfig } from '@/composables/useTooltipConfig'
|
||||||
|
|
||||||
|
|||||||
@@ -31,18 +31,16 @@
|
|||||||
t('sideToolbar.queueProgressOverlay.queuedSuffix')
|
t('sideToolbar.queueProgressOverlay.queuedSuffix')
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
<IconButton
|
<Button
|
||||||
v-if="queuedCount > 0"
|
v-if="queuedCount > 0"
|
||||||
class="group ml-2 size-6 bg-secondary-background hover:bg-destructive-background"
|
class="ml-2"
|
||||||
type="secondary"
|
variant="destructive"
|
||||||
size="sm"
|
size="icon"
|
||||||
:aria-label="t('sideToolbar.queueProgressOverlay.clearQueued')"
|
:aria-label="t('sideToolbar.queueProgressOverlay.clearQueued')"
|
||||||
@click="$emit('clearQueued')"
|
@click="$emit('clearQueued')"
|
||||||
>
|
>
|
||||||
<i
|
<i class="icon-[lucide--list-x] size-4" />
|
||||||
class="pointer-events-none icon-[lucide--list-x] block size-4 leading-none text-text-primary transition-colors group-hover:text-base-background"
|
</Button>
|
||||||
/>
|
|
||||||
</IconButton>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -80,8 +78,8 @@
|
|||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
|
||||||
import IconTextButton from '@/components/button/IconTextButton.vue'
|
import IconTextButton from '@/components/button/IconTextButton.vue'
|
||||||
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
import type {
|
import type {
|
||||||
JobGroup,
|
JobGroup,
|
||||||
JobListItem,
|
JobListItem,
|
||||||
|
|||||||
@@ -18,18 +18,17 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!isCloud" class="flex items-center gap-1">
|
<div v-if="!isCloud" class="flex items-center gap-1">
|
||||||
<IconButton
|
<Button
|
||||||
v-tooltip.top="moreTooltipConfig"
|
v-tooltip.top="moreTooltipConfig"
|
||||||
type="transparent"
|
variant="textonly"
|
||||||
size="sm"
|
size="icon"
|
||||||
class="size-6 bg-transparent hover:bg-secondary-background hover:opacity-100"
|
|
||||||
:aria-label="t('sideToolbar.queueProgressOverlay.moreOptions')"
|
:aria-label="t('sideToolbar.queueProgressOverlay.moreOptions')"
|
||||||
@click="onMoreClick"
|
@click="onMoreClick"
|
||||||
>
|
>
|
||||||
<i
|
<i
|
||||||
class="icon-[lucide--more-horizontal] block size-4 leading-none text-text-secondary"
|
class="icon-[lucide--more-horizontal] block size-4 leading-none text-text-secondary"
|
||||||
/>
|
/>
|
||||||
</IconButton>
|
</Button>
|
||||||
<Popover
|
<Popover
|
||||||
ref="morePopoverRef"
|
ref="morePopoverRef"
|
||||||
:dismissable="true"
|
:dismissable="true"
|
||||||
@@ -72,8 +71,8 @@ import type { PopoverMethods } from 'primevue/popover'
|
|||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
|
||||||
import IconTextButton from '@/components/button/IconTextButton.vue'
|
import IconTextButton from '@/components/button/IconTextButton.vue'
|
||||||
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
import { buildTooltipConfig } from '@/composables/useTooltipConfig'
|
import { buildTooltipConfig } from '@/composables/useTooltipConfig'
|
||||||
import { isCloud } from '@/platform/distribution/types'
|
import { isCloud } from '@/platform/distribution/types'
|
||||||
|
|
||||||
|
|||||||
@@ -8,15 +8,14 @@
|
|||||||
<p class="m-0 text-[14px] font-normal leading-none">
|
<p class="m-0 text-[14px] font-normal leading-none">
|
||||||
{{ t('sideToolbar.queueProgressOverlay.clearHistoryDialogTitle') }}
|
{{ t('sideToolbar.queueProgressOverlay.clearHistoryDialogTitle') }}
|
||||||
</p>
|
</p>
|
||||||
<IconButton
|
<Button
|
||||||
type="transparent"
|
size="icon"
|
||||||
size="sm"
|
variant="muted-textonly"
|
||||||
class="size-6 bg-transparent text-text-secondary hover:bg-secondary-background hover:opacity-100"
|
|
||||||
:aria-label="t('g.close')"
|
:aria-label="t('g.close')"
|
||||||
@click="onCancel"
|
@click="onCancel"
|
||||||
>
|
>
|
||||||
<i class="icon-[lucide--x] block size-4 leading-none" />
|
<i class="icon-[lucide--x] block size-4 leading-none" />
|
||||||
</IconButton>
|
</Button>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="flex flex-col gap-4 px-4 py-4 text-[14px] text-text-secondary">
|
<div class="flex flex-col gap-4 px-4 py-4 text-[14px] text-text-secondary">
|
||||||
@@ -51,7 +50,6 @@
|
|||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
|
||||||
import Button from '@/components/ui/button/Button.vue'
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
import { useErrorHandling } from '@/composables/useErrorHandling'
|
import { useErrorHandling } from '@/composables/useErrorHandling'
|
||||||
import { useDialogStore } from '@/stores/dialogStore'
|
import { useDialogStore } from '@/stores/dialogStore'
|
||||||
|
|||||||
@@ -20,18 +20,15 @@
|
|||||||
class="flex min-w-0 items-center text-[0.75rem] leading-normal font-normal text-text-secondary"
|
class="flex min-w-0 items-center text-[0.75rem] leading-normal font-normal text-text-secondary"
|
||||||
>
|
>
|
||||||
<span class="block min-w-0 truncate">{{ row.value }}</span>
|
<span class="block min-w-0 truncate">{{ row.value }}</span>
|
||||||
<IconButton
|
<Button
|
||||||
v-if="row.canCopy"
|
v-if="row.canCopy"
|
||||||
type="transparent"
|
size="icon"
|
||||||
size="sm"
|
variant="muted-textonly"
|
||||||
class="ml-2 size-6 bg-transparent hover:opacity-90"
|
|
||||||
:aria-label="copyAriaLabel"
|
:aria-label="copyAriaLabel"
|
||||||
@click.stop="copyJobId"
|
@click.stop="copyJobId"
|
||||||
>
|
>
|
||||||
<i
|
<i class="icon-[lucide--copy] size-4" />
|
||||||
class="icon-[lucide--copy] block size-4 leading-none text-text-secondary"
|
</Button>
|
||||||
/>
|
|
||||||
</IconButton>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
@@ -101,10 +98,9 @@
|
|||||||
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
|
||||||
import IconTextButton from '@/components/button/IconTextButton.vue'
|
import IconTextButton from '@/components/button/IconTextButton.vue'
|
||||||
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
import { useCopyToClipboard } from '@/composables/useCopyToClipboard'
|
import { useCopyToClipboard } from '@/composables/useCopyToClipboard'
|
||||||
import { t } from '@/i18n'
|
|
||||||
import { isCloud } from '@/platform/distribution/types'
|
import { isCloud } from '@/platform/distribution/types'
|
||||||
import { useWorkflowStore } from '@/platform/workflow/management/stores/workflowStore'
|
import { useWorkflowStore } from '@/platform/workflow/management/stores/workflowStore'
|
||||||
import { useDialogService } from '@/services/dialogService'
|
import { useDialogService } from '@/services/dialogService'
|
||||||
@@ -128,7 +124,7 @@ const workflowStore = useWorkflowStore()
|
|||||||
const queueStore = useQueueStore()
|
const queueStore = useQueueStore()
|
||||||
const executionStore = useExecutionStore()
|
const executionStore = useExecutionStore()
|
||||||
const dialog = useDialogService()
|
const dialog = useDialogService()
|
||||||
const { locale } = useI18n()
|
const { locale, t } = useI18n()
|
||||||
|
|
||||||
const workflowValue = computed(() => {
|
const workflowValue = computed(() => {
|
||||||
const wid = props.workflowId
|
const wid = props.workflowId
|
||||||
|
|||||||
@@ -15,23 +15,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-2 flex shrink-0 items-center gap-2">
|
<div class="ml-2 flex shrink-0 items-center gap-2">
|
||||||
<IconButton
|
<Button
|
||||||
v-if="showWorkflowFilter"
|
v-if="showWorkflowFilter"
|
||||||
v-tooltip.top="filterTooltipConfig"
|
v-tooltip.top="filterTooltipConfig"
|
||||||
type="secondary"
|
variant="secondary"
|
||||||
size="sm"
|
size="icon"
|
||||||
class="relative size-6 bg-secondary-background hover:bg-secondary-background-hover hover:opacity-90"
|
|
||||||
:aria-label="t('sideToolbar.queueProgressOverlay.filterJobs')"
|
:aria-label="t('sideToolbar.queueProgressOverlay.filterJobs')"
|
||||||
@click="onFilterClick"
|
@click="onFilterClick"
|
||||||
>
|
>
|
||||||
<i
|
<i class="icon-[lucide--list-filter] size-4" />
|
||||||
class="icon-[lucide--list-filter] block size-4 leading-none text-text-primary"
|
|
||||||
/>
|
|
||||||
<span
|
<span
|
||||||
v-if="selectedWorkflowFilter !== 'all'"
|
v-if="selectedWorkflowFilter !== 'all'"
|
||||||
class="pointer-events-none absolute -top-1 -right-1 inline-block size-2 rounded-full bg-base-foreground"
|
class="pointer-events-none absolute -top-1 -right-1 inline-block size-2 rounded-full bg-base-foreground"
|
||||||
/>
|
/>
|
||||||
</IconButton>
|
</Button>
|
||||||
<Popover
|
<Popover
|
||||||
v-if="showWorkflowFilter"
|
v-if="showWorkflowFilter"
|
||||||
ref="filterPopoverRef"
|
ref="filterPopoverRef"
|
||||||
@@ -87,22 +84,19 @@
|
|||||||
</IconTextButton>
|
</IconTextButton>
|
||||||
</div>
|
</div>
|
||||||
</Popover>
|
</Popover>
|
||||||
<IconButton
|
<Button
|
||||||
v-tooltip.top="sortTooltipConfig"
|
v-tooltip.top="sortTooltipConfig"
|
||||||
type="secondary"
|
variant="secondary"
|
||||||
size="sm"
|
size="icon"
|
||||||
class="relative size-6 bg-secondary-background hover:bg-secondary-background-hover hover:opacity-90"
|
|
||||||
:aria-label="t('sideToolbar.queueProgressOverlay.sortJobs')"
|
:aria-label="t('sideToolbar.queueProgressOverlay.sortJobs')"
|
||||||
@click="onSortClick"
|
@click="onSortClick"
|
||||||
>
|
>
|
||||||
<i
|
<i class="icon-[lucide--arrow-up-down] size-4" />
|
||||||
class="icon-[lucide--arrow-up-down] block size-4 leading-none text-text-primary"
|
|
||||||
/>
|
|
||||||
<span
|
<span
|
||||||
v-if="selectedSortMode !== 'mostRecent'"
|
v-if="selectedSortMode !== 'mostRecent'"
|
||||||
class="pointer-events-none absolute -top-1 -right-1 inline-block size-2 rounded-full bg-base-foreground"
|
class="pointer-events-none absolute -top-1 -right-1 inline-block size-2 rounded-full bg-base-foreground"
|
||||||
/>
|
/>
|
||||||
</IconButton>
|
</Button>
|
||||||
<Popover
|
<Popover
|
||||||
ref="sortPopoverRef"
|
ref="sortPopoverRef"
|
||||||
:dismissable="true"
|
:dismissable="true"
|
||||||
@@ -152,7 +146,6 @@ import Popover from 'primevue/popover'
|
|||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
|
||||||
import IconTextButton from '@/components/button/IconTextButton.vue'
|
import IconTextButton from '@/components/button/IconTextButton.vue'
|
||||||
import Button from '@/components/ui/button/Button.vue'
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
import { jobSortModes, jobTabs } from '@/composables/queue/useJobList'
|
import { jobSortModes, jobTabs } from '@/composables/queue/useJobList'
|
||||||
|
|||||||
@@ -128,51 +128,47 @@
|
|||||||
key="actions"
|
key="actions"
|
||||||
class="inline-flex items-center gap-2 pr-1"
|
class="inline-flex items-center gap-2 pr-1"
|
||||||
>
|
>
|
||||||
<IconButton
|
<Button
|
||||||
v-if="props.state === 'failed' && computedShowClear"
|
v-if="props.state === 'failed' && computedShowClear"
|
||||||
v-tooltip.top="deleteTooltipConfig"
|
v-tooltip.top="deleteTooltipConfig"
|
||||||
type="transparent"
|
variant="destructive"
|
||||||
size="sm"
|
size="icon"
|
||||||
class="size-6 transform gap-1 rounded bg-destructive-background text-text-primary transition duration-150 ease-in-out hover:-translate-y-px hover:bg-destructive-background-hover hover:opacity-95"
|
|
||||||
:aria-label="t('g.delete')"
|
:aria-label="t('g.delete')"
|
||||||
@click.stop="onDeleteClick"
|
@click.stop="onDeleteClick"
|
||||||
>
|
>
|
||||||
<i class="icon-[lucide--trash-2] size-4" />
|
<i class="icon-[lucide--trash-2] size-4" />
|
||||||
</IconButton>
|
</Button>
|
||||||
<IconButton
|
<Button
|
||||||
v-else-if="
|
v-else-if="
|
||||||
props.state !== 'completed' &&
|
props.state !== 'completed' &&
|
||||||
props.state !== 'running' &&
|
props.state !== 'running' &&
|
||||||
computedShowClear
|
computedShowClear
|
||||||
"
|
"
|
||||||
v-tooltip.top="cancelTooltipConfig"
|
v-tooltip.top="cancelTooltipConfig"
|
||||||
type="transparent"
|
variant="destructive"
|
||||||
size="sm"
|
size="icon"
|
||||||
class="size-6 transform gap-1 rounded bg-destructive-background text-text-primary transition duration-150 ease-in-out hover:-translate-y-px hover:bg-destructive-background-hover hover:opacity-95"
|
|
||||||
:aria-label="t('g.cancel')"
|
:aria-label="t('g.cancel')"
|
||||||
@click.stop="onCancelClick"
|
@click.stop="onCancelClick"
|
||||||
>
|
>
|
||||||
<i class="icon-[lucide--x] size-4" />
|
<i class="icon-[lucide--x] size-4" />
|
||||||
</IconButton>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
v-else-if="props.state === 'completed'"
|
v-else-if="props.state === 'completed'"
|
||||||
class="transform bg-modal-card-button-surface px-2 py-0 transition duration-150 ease-in-out hover:-translate-y-px hover:opacity-95"
|
|
||||||
variant="textonly"
|
variant="textonly"
|
||||||
size="sm"
|
size="sm"
|
||||||
@click.stop="emit('view')"
|
@click.stop="emit('view')"
|
||||||
>{{ t('menuLabels.View') }}</Button
|
>{{ t('menuLabels.View') }}</Button
|
||||||
>
|
>
|
||||||
<IconButton
|
<Button
|
||||||
v-if="props.showMenu !== undefined ? props.showMenu : true"
|
v-if="props.showMenu !== undefined ? props.showMenu : true"
|
||||||
v-tooltip.top="moreTooltipConfig"
|
v-tooltip.top="moreTooltipConfig"
|
||||||
type="transparent"
|
variant="textonly"
|
||||||
size="sm"
|
size="icon-sm"
|
||||||
class="size-6 transform gap-1 rounded bg-modal-card-button-surface text-text-primary transition duration-150 ease-in-out hover:-translate-y-px hover:opacity-95"
|
|
||||||
:aria-label="t('g.more')"
|
:aria-label="t('g.more')"
|
||||||
@click.stop="emit('menu', $event)"
|
@click.stop="emit('menu', $event)"
|
||||||
>
|
>
|
||||||
<i class="icon-[lucide--more-horizontal] size-4" />
|
<i class="icon-[lucide--more-horizontal] size-4" />
|
||||||
</IconButton>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-else-if="props.state !== 'running'"
|
v-else-if="props.state !== 'running'"
|
||||||
@@ -183,17 +179,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
<!-- Running job cancel button - always visible -->
|
<!-- Running job cancel button - always visible -->
|
||||||
<IconButton
|
<Button
|
||||||
v-if="props.state === 'running' && computedShowClear"
|
v-if="props.state === 'running' && computedShowClear"
|
||||||
v-tooltip.top="cancelTooltipConfig"
|
v-tooltip.top="cancelTooltipConfig"
|
||||||
type="transparent"
|
variant="destructive"
|
||||||
size="sm"
|
size="icon"
|
||||||
class="size-6 transform gap-1 rounded bg-destructive-background text-text-primary transition duration-150 ease-in-out hover:-translate-y-px hover:bg-destructive-background-hover hover:opacity-95"
|
|
||||||
:aria-label="t('g.cancel')"
|
:aria-label="t('g.cancel')"
|
||||||
@click.stop="onCancelClick"
|
@click.stop="onCancelClick"
|
||||||
>
|
>
|
||||||
<i class="icon-[lucide--x] size-4" />
|
<i class="icon-[lucide--x] size-4" />
|
||||||
</IconButton>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -203,7 +198,6 @@
|
|||||||
import { computed, nextTick, ref, watch } from 'vue'
|
import { computed, nextTick, ref, watch } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
|
||||||
import JobDetailsPopover from '@/components/queue/job/JobDetailsPopover.vue'
|
import JobDetailsPopover from '@/components/queue/job/JobDetailsPopover.vue'
|
||||||
import QueueAssetPreview from '@/components/queue/job/QueueAssetPreview.vue'
|
import QueueAssetPreview from '@/components/queue/job/QueueAssetPreview.vue'
|
||||||
import Button from '@/components/ui/button/Button.vue'
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ import { storeToRefs } from 'pinia'
|
|||||||
import { computed, ref, toValue, watchEffect } from 'vue'
|
import { computed, ref, toValue, watchEffect } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
|
||||||
import EditableText from '@/components/common/EditableText.vue'
|
import EditableText from '@/components/common/EditableText.vue'
|
||||||
import Tab from '@/components/tab/Tab.vue'
|
import Tab from '@/components/tab/Tab.vue'
|
||||||
import TabList from '@/components/tab/TabList.vue'
|
import TabList from '@/components/tab/TabList.vue'
|
||||||
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
import { SubgraphNode } from '@/lib/litegraph/src/litegraph'
|
import { SubgraphNode } from '@/lib/litegraph/src/litegraph'
|
||||||
import type { LGraphNode } from '@/lib/litegraph/src/litegraph'
|
import type { LGraphNode } from '@/lib/litegraph/src/litegraph'
|
||||||
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
|
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
|
||||||
@@ -140,16 +140,11 @@ function handleTitleCancel() {
|
|||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<IconButton
|
<Button
|
||||||
v-if="isSubgraphNode"
|
v-if="isSubgraphNode"
|
||||||
type="transparent"
|
variant="secondary"
|
||||||
size="sm"
|
size="icon"
|
||||||
:class="
|
:class="cn(isEditingSubgraph && 'bg-secondary-background-selected')"
|
||||||
cn(
|
|
||||||
'bg-secondary-background hover:bg-secondary-background-hover text-base-foreground',
|
|
||||||
isEditingSubgraph && 'bg-secondary-background-selected'
|
|
||||||
)
|
|
||||||
"
|
|
||||||
@click="
|
@click="
|
||||||
rightSidePanelStore.openPanel(
|
rightSidePanelStore.openPanel(
|
||||||
isEditingSubgraph ? 'parameters' : 'subgraph'
|
isEditingSubgraph ? 'parameters' : 'subgraph'
|
||||||
@@ -157,17 +152,16 @@ function handleTitleCancel() {
|
|||||||
"
|
"
|
||||||
>
|
>
|
||||||
<i class="icon-[lucide--settings-2]" />
|
<i class="icon-[lucide--settings-2]" />
|
||||||
</IconButton>
|
</Button>
|
||||||
<IconButton
|
<Button
|
||||||
type="transparent"
|
variant="secondary"
|
||||||
size="sm"
|
size="icon"
|
||||||
class="bg-secondary-background hover:bg-secondary-background-hover text-base-foreground"
|
|
||||||
:aria-pressed="rightSidePanelStore.isOpen"
|
:aria-pressed="rightSidePanelStore.isOpen"
|
||||||
:aria-label="t('rightSidePanel.togglePanel')"
|
:aria-label="t('rightSidePanel.togglePanel')"
|
||||||
@click="closePanel"
|
@click="closePanel"
|
||||||
>
|
>
|
||||||
<i class="icon-[lucide--panel-right] size-4" />
|
<i class="icon-[lucide--panel-right] size-4" />
|
||||||
</IconButton>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<nav v-if="hasSelection" class="px-4 pb-2 pt-1">
|
<nav v-if="hasSelection" class="px-4 pb-2 pt-1">
|
||||||
|
|||||||
@@ -128,18 +128,19 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2 pr-4">
|
<div class="flex shrink gap-2 pr-4 items-center-safe">
|
||||||
<template v-if="isCompact">
|
<template v-if="isCompact">
|
||||||
<!-- Compact mode: Icon only -->
|
<!-- Compact mode: Icon only -->
|
||||||
<IconButton
|
<Button
|
||||||
v-if="shouldShowDeleteButton"
|
v-if="shouldShowDeleteButton"
|
||||||
|
size="icon"
|
||||||
@click="handleDeleteSelected"
|
@click="handleDeleteSelected"
|
||||||
>
|
>
|
||||||
<i class="icon-[lucide--trash-2] size-4" />
|
<i class="icon-[lucide--trash-2] size-4" />
|
||||||
</IconButton>
|
</Button>
|
||||||
<IconButton @click="handleDownloadSelected">
|
<Button size="icon" @click="handleDownloadSelected">
|
||||||
<i class="icon-[lucide--download] size-4" />
|
<i class="icon-[lucide--download] size-4" />
|
||||||
</IconButton>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<!-- Normal mode: Icon + Text -->
|
<!-- Normal mode: Icon + Text -->
|
||||||
@@ -183,7 +184,6 @@ import { useToast } from 'primevue/usetoast'
|
|||||||
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
|
||||||
import IconTextButton from '@/components/button/IconTextButton.vue'
|
import IconTextButton from '@/components/button/IconTextButton.vue'
|
||||||
import NoResultsPlaceholder from '@/components/common/NoResultsPlaceholder.vue'
|
import NoResultsPlaceholder from '@/components/common/NoResultsPlaceholder.vue'
|
||||||
import VirtualGrid from '@/components/common/VirtualGrid.vue'
|
import VirtualGrid from '@/components/common/VirtualGrid.vue'
|
||||||
|
|||||||
@@ -47,7 +47,13 @@ function generateVariants() {
|
|||||||
for (const variant of variants) {
|
for (const variant of variants) {
|
||||||
for (const size of sizes) {
|
for (const size of sizes) {
|
||||||
variantButtons.push(
|
variantButtons.push(
|
||||||
`<Button variant="${variant}" size="${size}">${size === 'icon' ? `<i class="icon-[lucide--settings]" />` : variant}</Button>`
|
`<Button
|
||||||
|
variant="${variant}"
|
||||||
|
size="${size}">${
|
||||||
|
size.startsWith('icon')
|
||||||
|
? `<i class="icon-[lucide--settings]" />`
|
||||||
|
: variant
|
||||||
|
}</Button>`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,7 +65,7 @@ export const AllVariants: Story = {
|
|||||||
render: () => ({
|
render: () => ({
|
||||||
components: { Button },
|
components: { Button },
|
||||||
template: `
|
template: `
|
||||||
<div class="grid grid-cols-4 gap-4 place-items-center-safe">
|
<div class="grid grid-cols-5 gap-4 place-items-center-safe">
|
||||||
${generateVariants().join('\n')}
|
${generateVariants().join('\n')}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ export const buttonVariants = cva({
|
|||||||
sm: 'h-6 rounded-sm px-2 py-1 text-xs',
|
sm: 'h-6 rounded-sm px-2 py-1 text-xs',
|
||||||
md: 'h-8 rounded-lg p-2 text-xs',
|
md: 'h-8 rounded-lg p-2 text-xs',
|
||||||
lg: 'h-10 rounded-lg px-4 py-2 text-sm',
|
lg: 'h-10 rounded-lg px-4 py-2 text-sm',
|
||||||
icon: 'size-9'
|
icon: 'size-8',
|
||||||
|
'icon-sm': 'size-5 p-0'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -42,7 +43,7 @@ const variants = [
|
|||||||
'textonly',
|
'textonly',
|
||||||
'muted-textonly'
|
'muted-textonly'
|
||||||
] as const satisfies Array<ButtonVariants['variant']>
|
] as const satisfies Array<ButtonVariants['variant']>
|
||||||
const sizes = ['sm', 'md', 'lg', 'icon'] as const satisfies Array<
|
const sizes = ['sm', 'md', 'lg', 'icon', 'icon-sm'] as const satisfies Array<
|
||||||
ButtonVariants['size']
|
ButtonVariants['size']
|
||||||
>
|
>
|
||||||
|
|
||||||
|
|||||||
@@ -99,12 +99,13 @@
|
|||||||
<div class="h-full w-full bg-blue-500"></div>
|
<div class="h-full w-full bg-blue-500"></div>
|
||||||
</template>
|
</template>
|
||||||
<template #top-right>
|
<template #top-right>
|
||||||
<IconButton
|
<Button
|
||||||
|
size="icon"
|
||||||
class="!bg-white !text-neutral-900"
|
class="!bg-white !text-neutral-900"
|
||||||
@click="() => {}"
|
@click="() => {}"
|
||||||
>
|
>
|
||||||
<i class="icon-[lucide--info]" />
|
<i class="icon-[lucide--info]" />
|
||||||
</IconButton>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
<template #bottom-right>
|
<template #bottom-right>
|
||||||
<SquareChip label="png" />
|
<SquareChip label="png" />
|
||||||
@@ -133,7 +134,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, provide, ref } from 'vue'
|
import { computed, provide, ref } from 'vue'
|
||||||
|
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
|
||||||
import IconTextButton from '@/components/button/IconTextButton.vue'
|
import IconTextButton from '@/components/button/IconTextButton.vue'
|
||||||
import MoreButton from '@/components/button/MoreButton.vue'
|
import MoreButton from '@/components/button/MoreButton.vue'
|
||||||
import CardBottom from '@/components/card/CardBottom.vue'
|
import CardBottom from '@/components/card/CardBottom.vue'
|
||||||
@@ -143,6 +143,7 @@ import SquareChip from '@/components/chip/SquareChip.vue'
|
|||||||
import SearchBox from '@/components/common/SearchBox.vue'
|
import SearchBox from '@/components/common/SearchBox.vue'
|
||||||
import MultiSelect from '@/components/input/MultiSelect.vue'
|
import MultiSelect from '@/components/input/MultiSelect.vue'
|
||||||
import SingleSelect from '@/components/input/SingleSelect.vue'
|
import SingleSelect from '@/components/input/SingleSelect.vue'
|
||||||
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
import BaseModalLayout from '@/components/widget/layout/BaseModalLayout.vue'
|
import BaseModalLayout from '@/components/widget/layout/BaseModalLayout.vue'
|
||||||
import LeftSidePanel from '@/components/widget/panel/LeftSidePanel.vue'
|
import LeftSidePanel from '@/components/widget/panel/LeftSidePanel.vue'
|
||||||
import RightSidePanel from '@/components/widget/panel/RightSidePanel.vue'
|
import RightSidePanel from '@/components/widget/panel/RightSidePanel.vue'
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
||||||
import { computed, provide, ref } from 'vue'
|
import { computed, provide, ref } from 'vue'
|
||||||
|
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
import IconTextButton from '@/components/button/IconTextButton.vue'
|
import IconTextButton from '@/components/button/IconTextButton.vue'
|
||||||
import MoreButton from '@/components/button/MoreButton.vue'
|
import MoreButton from '@/components/button/MoreButton.vue'
|
||||||
import CardBottom from '@/components/card/CardBottom.vue'
|
import CardBottom from '@/components/card/CardBottom.vue'
|
||||||
@@ -74,7 +74,7 @@ const createStoryTemplate = (args: StoryArgs) => ({
|
|||||||
SearchBox,
|
SearchBox,
|
||||||
MultiSelect,
|
MultiSelect,
|
||||||
SingleSelect,
|
SingleSelect,
|
||||||
IconButton,
|
Button,
|
||||||
IconTextButton,
|
IconTextButton,
|
||||||
MoreButton,
|
MoreButton,
|
||||||
CardContainer,
|
CardContainer,
|
||||||
@@ -277,9 +277,9 @@ const createStoryTemplate = (args: StoryArgs) => ({
|
|||||||
<div class="w-full h-full bg-blue-500"></div>
|
<div class="w-full h-full bg-blue-500"></div>
|
||||||
</template>
|
</template>
|
||||||
<template #top-right>
|
<template #top-right>
|
||||||
<IconButton class="!bg-white !text-neutral-900" @click="() => {}">
|
<Button size="icon" class="!bg-white !text-neutral-900" @click="() => {}">
|
||||||
<i class="icon-[lucide--info] size-4" />
|
<i class="icon-[lucide--info] size-4" />
|
||||||
</IconButton>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
<template #bottom-right>
|
<template #bottom-right>
|
||||||
<SquareChip label="png" />
|
<SquareChip label="png" />
|
||||||
@@ -399,9 +399,9 @@ const createStoryTemplate = (args: StoryArgs) => ({
|
|||||||
<div class="w-full h-full bg-blue-500"></div>
|
<div class="w-full h-full bg-blue-500"></div>
|
||||||
</template>
|
</template>
|
||||||
<template #top-right>
|
<template #top-right>
|
||||||
<IconButton class="!bg-white !text-neutral-900" @click="() => {}">
|
<Button size="icon" class="!bg-white !text-neutral-900" @click="() => {}">
|
||||||
<i class="icon-[lucide--info] size-4" />
|
<i class="icon-[lucide--info] size-4" />
|
||||||
</IconButton>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
<template #bottom-right>
|
<template #bottom-right>
|
||||||
<SquareChip label="png" />
|
<SquareChip label="png" />
|
||||||
|
|||||||
@@ -1,15 +1,23 @@
|
|||||||
<template>
|
<template>
|
||||||
<div :class="layoutClasses">
|
<div class="base-widget-layout rounded-2xl overflow-hidden relative">
|
||||||
<IconButton
|
<Button
|
||||||
v-show="!isRightPanelOpen && hasRightPanel"
|
v-show="!isRightPanelOpen && hasRightPanel"
|
||||||
:class="rightPanelButtonClasses"
|
size="icon"
|
||||||
|
:class="
|
||||||
|
cn('absolute top-4 right-18 z-10', 'transition-opacity duration-200', {
|
||||||
|
'opacity-0 pointer-events-none': isRightPanelOpen || !hasRightPanel
|
||||||
|
})
|
||||||
|
"
|
||||||
@click="toggleRightPanel"
|
@click="toggleRightPanel"
|
||||||
>
|
>
|
||||||
<i class="icon-[lucide--panel-right] text-sm" />
|
<i class="icon-[lucide--panel-right] text-sm" />
|
||||||
</IconButton>
|
</Button>
|
||||||
<IconButton :class="closeButtonClasses" @click="closeDialog">
|
<Button
|
||||||
|
class="absolute top-4 right-6 z-10 transition-opacity duration-200"
|
||||||
|
@click="closeDialog"
|
||||||
|
>
|
||||||
<i class="pi pi-times text-sm"></i>
|
<i class="pi pi-times text-sm"></i>
|
||||||
</IconButton>
|
</Button>
|
||||||
<div class="flex h-full w-full">
|
<div class="flex h-full w-full">
|
||||||
<Transition name="slide-panel">
|
<Transition name="slide-panel">
|
||||||
<nav
|
<nav
|
||||||
@@ -24,27 +32,42 @@
|
|||||||
</nav>
|
</nav>
|
||||||
</Transition>
|
</Transition>
|
||||||
|
|
||||||
<div :class="mainContainerClasses">
|
<div class="flex-1 flex bg-base-background">
|
||||||
<div class="flex h-full w-full flex-col">
|
<div class="flex h-full w-full flex-col">
|
||||||
<header v-if="$slots.header" :class="headerClasses">
|
<header
|
||||||
|
v-if="$slots.header"
|
||||||
|
class="w-full h-18 px-6 flex items-center justify-between gap-2"
|
||||||
|
>
|
||||||
<div class="flex flex-1 shrink-0 gap-2">
|
<div class="flex flex-1 shrink-0 gap-2">
|
||||||
<IconButton v-if="!notMobile" @click="toggleLeftPanel">
|
<Button v-if="!notMobile" size="icon" @click="toggleLeftPanel">
|
||||||
<i
|
<i
|
||||||
v-if="!showLeftPanel"
|
:class="
|
||||||
class="icon-[lucide--panel-left] text-sm"
|
cn(
|
||||||
|
showLeftPanel
|
||||||
|
? 'icon-[lucide--panel-left]'
|
||||||
|
: 'icon-[lucide--panel-left-close]'
|
||||||
|
)
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
<i v-else class="icon-[lucide--panel-left-close] text-sm" />
|
</Button>
|
||||||
</IconButton>
|
|
||||||
<slot name="header"></slot>
|
<slot name="header"></slot>
|
||||||
</div>
|
</div>
|
||||||
<slot name="header-right-area"></slot>
|
<slot name="header-right-area"></slot>
|
||||||
<div :class="rightAreaClasses">
|
<div
|
||||||
<IconButton
|
:class="
|
||||||
|
cn(
|
||||||
|
'flex justify-end gap-2 w-0',
|
||||||
|
hasRightPanel && !isRightPanelOpen ? 'min-w-22' : 'min-w-10'
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
v-if="isRightPanelOpen && hasRightPanel"
|
v-if="isRightPanelOpen && hasRightPanel"
|
||||||
|
size="icon"
|
||||||
@click="toggleRightPanel"
|
@click="toggleRightPanel"
|
||||||
>
|
>
|
||||||
<i class="icon-[lucide--panel-right-close] text-sm" />
|
<i class="icon-[lucide--panel-right-close]" />
|
||||||
</IconButton>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
@@ -57,14 +80,14 @@
|
|||||||
>
|
>
|
||||||
{{ contentTitle }}
|
{{ contentTitle }}
|
||||||
</h2>
|
</h2>
|
||||||
<div :class="contentContainerClasses">
|
<div class="min-h-0 px-6 pt-0 pb-10 overflow-y-auto">
|
||||||
<slot name="content"></slot>
|
<slot name="content"></slot>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
<aside
|
<aside
|
||||||
v-if="hasRightPanel && isRightPanelOpen"
|
v-if="hasRightPanel && isRightPanelOpen"
|
||||||
:class="rightPanelClasses"
|
class="w-1/4 min-w-40 max-w-80"
|
||||||
>
|
>
|
||||||
<slot name="rightPanel"></slot>
|
<slot name="rightPanel"></slot>
|
||||||
</aside>
|
</aside>
|
||||||
@@ -77,7 +100,7 @@
|
|||||||
import { useBreakpoints } from '@vueuse/core'
|
import { useBreakpoints } from '@vueuse/core'
|
||||||
import { computed, inject, ref, useSlots, watch } from 'vue'
|
import { computed, inject, ref, useSlots, watch } from 'vue'
|
||||||
|
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
import { OnCloseKey } from '@/types/widgetTypes'
|
import { OnCloseKey } from '@/types/widgetTypes'
|
||||||
import { cn } from '@/utils/tailwindUtil'
|
import { cn } from '@/utils/tailwindUtil'
|
||||||
|
|
||||||
@@ -128,46 +151,6 @@ const toggleLeftPanel = () => {
|
|||||||
const toggleRightPanel = () => {
|
const toggleRightPanel = () => {
|
||||||
isRightPanelOpen.value = !isRightPanelOpen.value
|
isRightPanelOpen.value = !isRightPanelOpen.value
|
||||||
}
|
}
|
||||||
|
|
||||||
// Computed classes for better readability
|
|
||||||
const layoutClasses = cn(
|
|
||||||
'base-widget-layout',
|
|
||||||
'rounded-2xl overflow-hidden relative'
|
|
||||||
)
|
|
||||||
|
|
||||||
const rightPanelButtonClasses = computed(() => {
|
|
||||||
return cn('absolute top-4 right-18 z-10', 'transition-opacity duration-200', {
|
|
||||||
'opacity-0 pointer-events-none':
|
|
||||||
isRightPanelOpen.value || !hasRightPanel.value
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
const closeButtonClasses = cn(
|
|
||||||
'absolute top-4 right-6 z-10',
|
|
||||||
'transition-opacity duration-200'
|
|
||||||
)
|
|
||||||
|
|
||||||
const mainContainerClasses = cn('flex-1 flex bg-base-background')
|
|
||||||
|
|
||||||
const headerClasses = cn(
|
|
||||||
'w-full h-18 px-6',
|
|
||||||
'flex items-center justify-between gap-2'
|
|
||||||
)
|
|
||||||
|
|
||||||
const rightAreaClasses = computed(() => {
|
|
||||||
return cn(
|
|
||||||
'flex justify-end gap-2 w-0',
|
|
||||||
hasRightPanel.value && !isRightPanelOpen.value ? 'min-w-22' : 'min-w-10'
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
const contentContainerClasses = computed(() => {
|
|
||||||
return cn('min-h-0 px-6 pt-0 pb-10', 'overflow-y-auto')
|
|
||||||
})
|
|
||||||
|
|
||||||
const rightPanelClasses = computed(() => {
|
|
||||||
return cn('w-1/4 min-w-40 max-w-80')
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.base-widget-layout {
|
.base-widget-layout {
|
||||||
|
|||||||
@@ -41,9 +41,6 @@
|
|||||||
)
|
)
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<IconButton v-if="false" size="sm">
|
|
||||||
<i class="icon-[lucide--file-text]" />
|
|
||||||
</IconButton>
|
|
||||||
<MoreButton ref="dropdown-menu-button" size="sm">
|
<MoreButton ref="dropdown-menu-button" size="sm">
|
||||||
<template #default>
|
<template #default>
|
||||||
<IconTextButton
|
<IconTextButton
|
||||||
@@ -123,7 +120,6 @@ import { useImage } from '@vueuse/core'
|
|||||||
import { computed, ref, toValue, useId, useTemplateRef } from 'vue'
|
import { computed, ref, toValue, useId, useTemplateRef } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
|
||||||
import IconGroup from '@/components/button/IconGroup.vue'
|
import IconGroup from '@/components/button/IconGroup.vue'
|
||||||
import IconTextButton from '@/components/button/IconTextButton.vue'
|
import IconTextButton from '@/components/button/IconTextButton.vue'
|
||||||
import MoreButton from '@/components/button/MoreButton.vue'
|
import MoreButton from '@/components/button/MoreButton.vue'
|
||||||
|
|||||||
@@ -59,12 +59,12 @@
|
|||||||
|
|
||||||
<!-- Media actions - show on hover or when playing -->
|
<!-- Media actions - show on hover or when playing -->
|
||||||
<IconGroup v-else-if="showActionsOverlay">
|
<IconGroup v-else-if="showActionsOverlay">
|
||||||
<IconButton size="sm" @click.stop="handleZoomClick">
|
<Button size="icon" @click.stop="handleZoomClick">
|
||||||
<i class="icon-[lucide--zoom-in] size-4" />
|
<i class="icon-[lucide--zoom-in] size-4" />
|
||||||
</IconButton>
|
</Button>
|
||||||
<IconButton size="sm" @click.stop="handleContextMenu">
|
<Button size="icon" @click.stop="handleContextMenu">
|
||||||
<i class="icon-[lucide--ellipsis] size-4" />
|
<i class="icon-[lucide--ellipsis] size-4" />
|
||||||
</IconButton>
|
</Button>
|
||||||
</IconGroup>
|
</IconGroup>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -129,13 +129,13 @@
|
|||||||
import { useElementHover, whenever } from '@vueuse/core'
|
import { useElementHover, whenever } from '@vueuse/core'
|
||||||
import { computed, defineAsyncComponent, provide, ref, toRef } from 'vue'
|
import { computed, defineAsyncComponent, provide, ref, toRef } from 'vue'
|
||||||
|
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
|
||||||
import IconGroup from '@/components/button/IconGroup.vue'
|
import IconGroup from '@/components/button/IconGroup.vue'
|
||||||
import IconTextButton from '@/components/button/IconTextButton.vue'
|
import IconTextButton from '@/components/button/IconTextButton.vue'
|
||||||
import CardBottom from '@/components/card/CardBottom.vue'
|
import CardBottom from '@/components/card/CardBottom.vue'
|
||||||
import CardContainer from '@/components/card/CardContainer.vue'
|
import CardContainer from '@/components/card/CardContainer.vue'
|
||||||
import CardTop from '@/components/card/CardTop.vue'
|
import CardTop from '@/components/card/CardTop.vue'
|
||||||
import SquareChip from '@/components/chip/SquareChip.vue'
|
import SquareChip from '@/components/chip/SquareChip.vue'
|
||||||
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
import { formatDuration, getMediaTypeFromFilename } from '@/utils/formatUtil'
|
import { formatDuration, getMediaTypeFromFilename } from '@/utils/formatUtil'
|
||||||
import { cn } from '@/utils/tailwindUtil'
|
import { cn } from '@/utils/tailwindUtil'
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="relative inline-flex items-center">
|
<div class="relative inline-flex items-center">
|
||||||
<IconButton :size :type @click="toggle">
|
<Button variant="secondary" size="icon" @click="toggle">
|
||||||
<i class="icon-[lucide--list-filter] text-sm" />
|
<i class="icon-[lucide--list-filter]" />
|
||||||
</IconButton>
|
</Button>
|
||||||
|
|
||||||
<Popover
|
<Popover
|
||||||
ref="popover"
|
ref="popover"
|
||||||
@@ -27,17 +27,11 @@
|
|||||||
import Popover from 'primevue/popover'
|
import Popover from 'primevue/popover'
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
|
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
import type { BaseButtonProps } from '@/types/buttonTypes'
|
|
||||||
import { cn } from '@/utils/tailwindUtil'
|
import { cn } from '@/utils/tailwindUtil'
|
||||||
|
|
||||||
interface AssetFilterButtonProps extends BaseButtonProps {}
|
|
||||||
|
|
||||||
const popover = ref<InstanceType<typeof Popover>>()
|
const popover = ref<InstanceType<typeof Popover>>()
|
||||||
|
|
||||||
const { size = 'md', type = 'secondary' } =
|
|
||||||
defineProps<AssetFilterButtonProps>()
|
|
||||||
|
|
||||||
defineEmits<{
|
defineEmits<{
|
||||||
menuOpened: []
|
menuOpened: []
|
||||||
menuClosed: []
|
menuClosed: []
|
||||||
@@ -57,9 +51,7 @@ const pt = computed(() => ({
|
|||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
class: cn(
|
class: cn(
|
||||||
'mt-1 rounded-lg',
|
'mt-1 rounded-lg bg-base-background text-base-foreground border border-border-default shadow-lg'
|
||||||
'bg-base-background text-base-foreground border border-border-default',
|
|
||||||
'shadow-lg'
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="relative inline-flex items-center">
|
<div class="relative inline-flex items-center">
|
||||||
<IconButton :size="size" :type="type" @click="toggle">
|
<Button variant="secondary" size="icon" @click="toggle">
|
||||||
<i class="icon-[lucide--arrow-up-down] text-sm" />
|
<i class="icon-[lucide--arrow-up-down]" />
|
||||||
</IconButton>
|
</Button>
|
||||||
|
|
||||||
<Popover
|
<Popover
|
||||||
ref="popover"
|
ref="popover"
|
||||||
@@ -27,16 +27,11 @@
|
|||||||
import Popover from 'primevue/popover'
|
import Popover from 'primevue/popover'
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
|
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
import type { BaseButtonProps } from '@/types/buttonTypes'
|
|
||||||
import { cn } from '@/utils/tailwindUtil'
|
import { cn } from '@/utils/tailwindUtil'
|
||||||
|
|
||||||
interface AssetSortButtonProps extends BaseButtonProps {}
|
|
||||||
|
|
||||||
const popover = ref<InstanceType<typeof Popover>>()
|
const popover = ref<InstanceType<typeof Popover>>()
|
||||||
|
|
||||||
const { size = 'md', type = 'secondary' } = defineProps<AssetSortButtonProps>()
|
|
||||||
|
|
||||||
defineEmits<{
|
defineEmits<{
|
||||||
menuOpened: []
|
menuOpened: []
|
||||||
menuClosed: []
|
menuClosed: []
|
||||||
|
|||||||
@@ -14,13 +14,15 @@
|
|||||||
:style="{ width: '90vw', maxWidth: '800px' }"
|
:style="{ width: '90vw', maxWidth: '800px' }"
|
||||||
>
|
>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<IconButton
|
<Button
|
||||||
|
variant="textonly"
|
||||||
|
size="icon"
|
||||||
class="absolute top-4 right-6 z-10"
|
class="absolute top-4 right-6 z-10"
|
||||||
:aria-label="$t('g.close')"
|
:aria-label="$t('g.close')"
|
||||||
@click="isVisible = false"
|
@click="isVisible = false"
|
||||||
>
|
>
|
||||||
<i class="pi pi-times text-sm" />
|
<i class="pi pi-times text-sm" />
|
||||||
</IconButton>
|
</Button>
|
||||||
<video
|
<video
|
||||||
autoplay
|
autoplay
|
||||||
muted
|
muted
|
||||||
@@ -40,7 +42,7 @@ import { useEventListener } from '@vueuse/core'
|
|||||||
import Dialog from 'primevue/dialog'
|
import Dialog from 'primevue/dialog'
|
||||||
import { onWatcherCleanup, watch } from 'vue'
|
import { onWatcherCleanup, watch } from 'vue'
|
||||||
|
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
|
|
||||||
const isVisible = defineModel<boolean>({ required: true })
|
const isVisible = defineModel<boolean>({ required: true })
|
||||||
|
|
||||||
|
|||||||
@@ -19,9 +19,10 @@
|
|||||||
<!-- Collapse/Expand Button -->
|
<!-- Collapse/Expand Button -->
|
||||||
<div class="relative grow-1 flex items-center gap-2.5 min-w-0 flex-1">
|
<div class="relative grow-1 flex items-center gap-2.5 min-w-0 flex-1">
|
||||||
<div class="flex shrink-0 items-center px-0.5">
|
<div class="flex shrink-0 items-center px-0.5">
|
||||||
<IconButton
|
<Button
|
||||||
size="fit-content"
|
size="icon-sm"
|
||||||
type="transparent"
|
variant="textonly"
|
||||||
|
class="hover:bg-transparent"
|
||||||
data-testid="node-collapse-button"
|
data-testid="node-collapse-button"
|
||||||
@click.stop="handleCollapse"
|
@click.stop="handleCollapse"
|
||||||
@dblclick.stop
|
@dblclick.stop
|
||||||
@@ -33,20 +34,22 @@
|
|||||||
collapsed && '-rotate-90'
|
collapsed && '-rotate-90'
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
class="relative top-px text-xs leading-none text-node-component-header-icon"
|
class="text-node-component-header-icon"
|
||||||
/>
|
/>
|
||||||
</IconButton>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="isSubgraphNode" class="icon-[comfy--workflow] size-4" />
|
<div v-if="isSubgraphNode" class="icon-[comfy--workflow] size-4" />
|
||||||
<div
|
<div
|
||||||
v-if="isApiNode"
|
v-if="isApiNode"
|
||||||
:class="
|
:class="
|
||||||
flags.subscriptionTiersEnabled
|
cn(
|
||||||
? 'icon-[lucide--component]'
|
'size-4',
|
||||||
: 'icon-[lucide--dollar-sign]'
|
flags.subscriptionTiersEnabled
|
||||||
|
? 'icon-[lucide--component]'
|
||||||
|
: 'icon-[lucide--dollar-sign]'
|
||||||
|
)
|
||||||
"
|
"
|
||||||
class="size-4"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Node Title -->
|
<!-- Node Title -->
|
||||||
@@ -79,22 +82,19 @@
|
|||||||
class="size-5"
|
class="size-5"
|
||||||
data-testid="node-pin-indicator"
|
data-testid="node-pin-indicator"
|
||||||
/>
|
/>
|
||||||
<IconButton
|
<Button
|
||||||
v-if="isSubgraphNode"
|
v-if="isSubgraphNode"
|
||||||
v-tooltip.top="enterSubgraphTooltipConfig"
|
v-tooltip.top="enterSubgraphTooltipConfig"
|
||||||
type="transparent"
|
variant="textonly"
|
||||||
|
size="sm"
|
||||||
data-testid="subgraph-enter-button"
|
data-testid="subgraph-enter-button"
|
||||||
class="ml-2 text-node-component-header h-5"
|
class="text-node-component-header h-5 px-0.5"
|
||||||
@click.stop="handleEnterSubgraph"
|
@click.stop="handleEnterSubgraph"
|
||||||
@dblclick.stop
|
@dblclick.stop
|
||||||
>
|
>
|
||||||
<div
|
<span>{{ $t('g.edit') }}</span>
|
||||||
class="min-w-max rounded-sm bg-node-component-surface px-1 py-0.5 text-xs flex items-center gap-1"
|
<i class="icon-[lucide--scaling] size-5" />
|
||||||
>
|
</Button>
|
||||||
{{ $t('g.edit') }}
|
|
||||||
<i class="icon-[lucide--scaling] size-5" />
|
|
||||||
</div>
|
|
||||||
</IconButton>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -103,8 +103,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onErrorCaptured, ref, toValue, watch } from 'vue'
|
import { computed, onErrorCaptured, ref, toValue, watch } from 'vue'
|
||||||
|
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
|
||||||
import EditableText from '@/components/common/EditableText.vue'
|
import EditableText from '@/components/common/EditableText.vue'
|
||||||
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
import type { VueNodeData } from '@/composables/graph/useGraphNodeManager'
|
import type { VueNodeData } from '@/composables/graph/useGraphNodeManager'
|
||||||
import { useErrorHandling } from '@/composables/useErrorHandling'
|
import { useErrorHandling } from '@/composables/useErrorHandling'
|
||||||
import { useFeatureFlags } from '@/composables/useFeatureFlags'
|
import { useFeatureFlags } from '@/composables/useFeatureFlags'
|
||||||
|
|||||||
@@ -60,16 +60,6 @@ export const getBorderButtonTypeClasses = (type: ButtonType = 'primary') => {
|
|||||||
return `${baseByType[type]} ${borderByType[type]}`
|
return `${baseByType[type]} ${borderByType[type]}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getIconButtonSizeClasses = (size: ButtonSize = 'md') => {
|
|
||||||
const sizeClasses = {
|
|
||||||
'fit-content': 'w-auto h-auto',
|
|
||||||
'full-width': 'w-full h-auto',
|
|
||||||
sm: 'size-8 text-xs !rounded-md',
|
|
||||||
md: 'size-10 text-sm'
|
|
||||||
}
|
|
||||||
return sizeClasses[size]
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getBaseButtonClasses = () => {
|
export const getBaseButtonClasses = () => {
|
||||||
return [
|
return [
|
||||||
'flex items-center justify-center shrink-0',
|
'flex items-center justify-center shrink-0',
|
||||||
|
|||||||
@@ -6,13 +6,20 @@
|
|||||||
<ContentDivider :width="0.3" />
|
<ContentDivider :width="0.3" />
|
||||||
<Button
|
<Button
|
||||||
v-if="isSmallScreen"
|
v-if="isSmallScreen"
|
||||||
:icon="isSideNavOpen ? 'pi pi-chevron-left' : 'pi pi-chevron-right'"
|
variant="secondary"
|
||||||
severity="secondary"
|
size="icon"
|
||||||
filled
|
:class="
|
||||||
class="absolute top-1/2 z-10 -translate-y-1/2"
|
cn(
|
||||||
:class="isSideNavOpen ? 'left-[12rem]' : 'left-2'"
|
'absolute top-1/2 z-10 -translate-y-1/2',
|
||||||
|
isSideNavOpen ? 'left-[12rem]' : 'left-2'
|
||||||
|
)
|
||||||
|
"
|
||||||
@click="toggleSideNav"
|
@click="toggleSideNav"
|
||||||
/>
|
>
|
||||||
|
<i
|
||||||
|
:class="isSideNavOpen ? 'pi pi-chevron-left' : 'pi pi-chevron-right'"
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
<div class="relative flex flex-1 overflow-hidden">
|
<div class="relative flex flex-1 overflow-hidden">
|
||||||
<ManagerNavSidebar
|
<ManagerNavSidebar
|
||||||
v-if="isSideNavOpen"
|
v-if="isSideNavOpen"
|
||||||
@@ -46,13 +53,14 @@
|
|||||||
{{ $t('manager.conflicts.warningBanner.button') }}
|
{{ $t('manager.conflicts.warningBanner.button') }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<IconButton
|
<Button
|
||||||
class="absolute top-0 right-0"
|
class="absolute top-0 right-0"
|
||||||
type="transparent"
|
variant="textonly"
|
||||||
|
size="icon"
|
||||||
@click="dismissWarningBanner"
|
@click="dismissWarningBanner"
|
||||||
>
|
>
|
||||||
<i class="pi pi-times text-xs text-base-foreground"></i>
|
<i class="pi pi-times text-xs text-base-foreground"></i>
|
||||||
</IconButton>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<RegistrySearchBar
|
<RegistrySearchBar
|
||||||
v-model:search-query="searchQuery"
|
v-model:search-query="searchQuery"
|
||||||
@@ -125,7 +133,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { whenever } from '@vueuse/core'
|
import { whenever } from '@vueuse/core'
|
||||||
import { merge } from 'es-toolkit/compat'
|
import { merge } from 'es-toolkit/compat'
|
||||||
import Button from 'primevue/button'
|
|
||||||
import {
|
import {
|
||||||
computed,
|
computed,
|
||||||
onBeforeUnmount,
|
onBeforeUnmount,
|
||||||
@@ -137,14 +144,15 @@ import {
|
|||||||
} from 'vue'
|
} from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import IconButton from '@/components/button/IconButton.vue'
|
|
||||||
import ContentDivider from '@/components/common/ContentDivider.vue'
|
import ContentDivider from '@/components/common/ContentDivider.vue'
|
||||||
import NoResultsPlaceholder from '@/components/common/NoResultsPlaceholder.vue'
|
import NoResultsPlaceholder from '@/components/common/NoResultsPlaceholder.vue'
|
||||||
import VirtualGrid from '@/components/common/VirtualGrid.vue'
|
import VirtualGrid from '@/components/common/VirtualGrid.vue'
|
||||||
|
import Button from '@/components/ui/button/Button.vue'
|
||||||
import { useResponsiveCollapse } from '@/composables/element/useResponsiveCollapse'
|
import { useResponsiveCollapse } from '@/composables/element/useResponsiveCollapse'
|
||||||
import { useExternalLink } from '@/composables/useExternalLink'
|
import { useExternalLink } from '@/composables/useExternalLink'
|
||||||
import { useComfyRegistryStore } from '@/stores/comfyRegistryStore'
|
import { useComfyRegistryStore } from '@/stores/comfyRegistryStore'
|
||||||
import type { components } from '@/types/comfyRegistryTypes'
|
import type { components } from '@/types/comfyRegistryTypes'
|
||||||
|
import { cn } from '@/utils/tailwindUtil'
|
||||||
import ManagerNavSidebar from '@/workbench/extensions/manager/components/manager/ManagerNavSidebar.vue'
|
import ManagerNavSidebar from '@/workbench/extensions/manager/components/manager/ManagerNavSidebar.vue'
|
||||||
import InfoPanel from '@/workbench/extensions/manager/components/manager/infoPanel/InfoPanel.vue'
|
import InfoPanel from '@/workbench/extensions/manager/components/manager/infoPanel/InfoPanel.vue'
|
||||||
import InfoPanelMultiItem from '@/workbench/extensions/manager/components/manager/infoPanel/InfoPanelMultiItem.vue'
|
import InfoPanelMultiItem from '@/workbench/extensions/manager/components/manager/infoPanel/InfoPanelMultiItem.vue'
|
||||||
|
|||||||
Reference in New Issue
Block a user