mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-13 09:00:16 +00:00
fix: enable enforce-consistent-class-order tailwind lint rule (#9428)
## Summary Enable `better-tailwindcss/enforce-consistent-class-order` lint rule and auto-fix all 1027 violations across 263 files. Stacked on #9427. ## Changes - **What**: Sort Tailwind classes into consistent order via `eslint --fix` - Enable `enforce-consistent-class-order` as `'error'` in eslint config - Purely cosmetic reordering — no behavioral or visual changes ## Review Focus Mechanical auto-fix PR — all changes are class reordering only. This is the largest diff but lowest risk since it changes no class names, only their order. **Stack:** #9417 → #9427 → **this PR** Fixes #9300 (partial — 3 of 3 rules) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9428-fix-enable-enforce-consistent-class-order-tailwind-lint-rule-31a6d73d3650811c9065f5178ba3e724) by [Unito](https://www.unito.io)
This commit is contained in:
@@ -26,7 +26,7 @@ function togglePromotion() {
|
||||
<template>
|
||||
<div
|
||||
v-if="isSelectInputsMode"
|
||||
class="col-span-2 flex flex-row pointer-events-auto cursor-pointer gap-1 relative"
|
||||
class="pointer-events-auto relative col-span-2 flex cursor-pointer flex-row gap-1"
|
||||
@pointerdown.capture.stop.prevent="togglePromotion"
|
||||
@click.capture.stop.prevent
|
||||
@pointerup.capture.stop.prevent
|
||||
@@ -36,27 +36,27 @@ function togglePromotion() {
|
||||
<div
|
||||
:class="
|
||||
cn(
|
||||
'border-primary-background border rounded-sm size-4 self-center m-1',
|
||||
isPromoted && 'bg-primary-background flex items-center'
|
||||
'm-1 size-4 self-center rounded-sm border border-primary-background',
|
||||
isPromoted && 'flex items-center bg-primary-background'
|
||||
)
|
||||
"
|
||||
>
|
||||
<i
|
||||
v-if="isPromoted"
|
||||
class="icon-[lucide--check] bg-primary-foreground place-center"
|
||||
class="bg-primary-foreground place-center icon-[lucide--check]"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
:class="
|
||||
cn(
|
||||
'grid grid-cols-2 items-stretch ring-primary-background rounded-lg pointer-events-none flex-1',
|
||||
'pointer-events-none grid flex-1 grid-cols-2 items-stretch rounded-lg ring-primary-background',
|
||||
isPromoted && 'ring-2'
|
||||
)
|
||||
"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
<div class="absolute size-full hover:bg-primary-background/10 rounded-lg" />
|
||||
<div class="absolute size-full rounded-lg hover:bg-primary-background/10" />
|
||||
</div>
|
||||
<slot v-else />
|
||||
</template>
|
||||
|
||||
@@ -25,7 +25,7 @@ function togglePromotion() {
|
||||
<div
|
||||
:class="
|
||||
cn(
|
||||
'absolute size-full pointer-events-auto ring-warning-background/50 ring-5 rounded-2xl',
|
||||
'pointer-events-auto absolute size-full rounded-2xl ring-5 ring-warning-background/50',
|
||||
isPromoted && 'ring-warning-background'
|
||||
)
|
||||
"
|
||||
@@ -38,13 +38,13 @@ function togglePromotion() {
|
||||
<div class="absolute top-0 right-0 size-8">
|
||||
<div
|
||||
v-if="isPromoted"
|
||||
class="absolute -top-1/2 -right-1/2 size-full p-2 bg-warning-background rounded-lg"
|
||||
class="absolute -top-1/2 -right-1/2 size-full rounded-lg bg-warning-background p-2"
|
||||
>
|
||||
<i class="icon-[lucide--check] bg-text-foreground size-full" />
|
||||
<i class="bg-text-foreground icon-[lucide--check] size-full" />
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="absolute -top-1/2 -right-1/2 size-full ring-warning-background/50 ring-4 ring-inset bg-component-node-background rounded-lg"
|
||||
class="absolute -top-1/2 -right-1/2 size-full rounded-lg bg-component-node-background ring-4 ring-warning-background/50 ring-inset"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -44,8 +44,8 @@ const { isOverDropZone } = useDropZone(dropZoneRef, {
|
||||
ref="dropZoneRef"
|
||||
:class="
|
||||
cn(
|
||||
'rounded-lg ring-inset ring-primary-500',
|
||||
canAcceptDrop && isOverDropZone && 'ring-4 bg-primary-500/10'
|
||||
'rounded-lg ring-primary-500 ring-inset',
|
||||
canAcceptDrop && isOverDropZone && 'bg-primary-500/10 ring-4'
|
||||
)
|
||||
"
|
||||
>
|
||||
@@ -54,7 +54,7 @@ const { isOverDropZone } = useDropZone(dropZoneRef, {
|
||||
v-if="dropIndicator"
|
||||
:class="
|
||||
cn(
|
||||
'flex flex-col items-center justify-center gap-2 border-dashed rounded-lg border h-25 border-border-subtle m-3 py-2',
|
||||
'm-3 flex h-25 flex-col items-center justify-center gap-2 rounded-lg border border-dashed border-border-subtle py-2',
|
||||
dropIndicator?.onClick && 'cursor-pointer'
|
||||
)
|
||||
"
|
||||
|
||||
@@ -13,7 +13,7 @@ const width = ref('')
|
||||
const height = ref('')
|
||||
</script>
|
||||
<template>
|
||||
<ZoomPane v-if="!mobile" v-slot="slotProps" class="flex-1 w-full">
|
||||
<ZoomPane v-if="!mobile" v-slot="slotProps" class="w-full flex-1">
|
||||
<img
|
||||
ref="imageRef"
|
||||
:src
|
||||
@@ -31,7 +31,7 @@ const height = ref('')
|
||||
<img
|
||||
v-else
|
||||
ref="imageRef"
|
||||
class="contain-size grow object-contain"
|
||||
class="grow object-contain contain-size"
|
||||
:src
|
||||
@load="
|
||||
() => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="flex-1 min-h-0 w-full flex items-center justify-center">
|
||||
<div class="flex min-h-0 w-full flex-1 items-center justify-center">
|
||||
<div
|
||||
class="aspect-square size-[min(50vw,50vh)] rounded-lg skeleton-shimmer"
|
||||
class="skeleton-shimmer aspect-square size-[min(50vw,50vh)] rounded-lg"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -15,12 +15,12 @@ const { hasOutputs } = storeToRefs(useAppModeStore())
|
||||
v-if="hasOutputs"
|
||||
role="article"
|
||||
data-testid="arrange-preview"
|
||||
class="flex flex-col items-center justify-center h-full w-3/4 gap-6 p-8 mx-auto"
|
||||
class="mx-auto flex h-full w-3/4 flex-col items-center justify-center gap-6 p-8"
|
||||
>
|
||||
<div
|
||||
class="border-warning-background border-2 border-dashed rounded-2xl w-full h-4/5 flex items-center justify-center flex-col p-12"
|
||||
class="flex h-4/5 w-full flex-col items-center justify-center rounded-2xl border-2 border-dashed border-warning-background p-12"
|
||||
>
|
||||
<p class="text-base-foreground font-bold mb-0">
|
||||
<p class="mb-0 font-bold text-base-foreground">
|
||||
{{ t('linearMode.arrange.outputs') }}
|
||||
</p>
|
||||
<p>{{ t('linearMode.arrange.resultsLabel') }}</p>
|
||||
@@ -30,18 +30,18 @@ const { hasOutputs } = storeToRefs(useAppModeStore())
|
||||
v-else
|
||||
role="article"
|
||||
data-testid="arrange-no-outputs"
|
||||
class="flex flex-col items-center justify-center h-full gap-6 p-8 w-lg mx-auto text-center"
|
||||
class="mx-auto flex h-full w-lg flex-col items-center justify-center gap-6 p-8 text-center"
|
||||
>
|
||||
<p class="m-0 text-base-foreground">
|
||||
{{ t('linearMode.arrange.noOutputs') }}
|
||||
</p>
|
||||
|
||||
<div class="flex flex-col gap-1 text-muted-foreground w-lg text-[14px]">
|
||||
<div class="flex w-lg flex-col gap-1 text-[14px] text-muted-foreground">
|
||||
<p class="mt-0 p-0">{{ t('linearMode.arrange.switchToOutputs') }}</p>
|
||||
|
||||
<i18n-t keypath="linearMode.arrange.connectAtLeastOne" tag="div">
|
||||
<template #atLeastOne>
|
||||
<span class="italic font-bold">
|
||||
<span class="font-bold italic">
|
||||
{{ t('linearMode.arrange.atLeastOne') }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
@@ -165,23 +165,23 @@ defineExpose({ runButtonClick })
|
||||
<template>
|
||||
<div
|
||||
v-if="!isBuilderMode && hasOutputs"
|
||||
class="flex flex-col min-w-80 h-full"
|
||||
class="flex h-full min-w-80 flex-col"
|
||||
v-bind="$attrs"
|
||||
>
|
||||
<section
|
||||
v-if="!mobile"
|
||||
data-testid="linear-workflow-info"
|
||||
class="h-12 border-x border-border-subtle py-2 px-4 gap-2 bg-comfy-menu-bg flex items-center contain-size"
|
||||
class="flex h-12 items-center gap-2 border-x border-border-subtle bg-comfy-menu-bg px-4 py-2 contain-size"
|
||||
>
|
||||
<span
|
||||
class="font-bold truncate"
|
||||
class="truncate font-bold"
|
||||
v-text="workflowStore.activeWorkflow?.filename"
|
||||
/>
|
||||
<div class="flex-1" />
|
||||
<Popover
|
||||
v-if="partitionedNodes[0].length"
|
||||
align="end"
|
||||
class="overflow-y-auto overflow-x-clip max-h-(--reka-popover-content-available-height) z-100"
|
||||
class="z-100 max-h-(--reka-popover-content-available-height) overflow-x-clip overflow-y-auto"
|
||||
side="bottom"
|
||||
:side-offset="-8"
|
||||
>
|
||||
@@ -201,7 +201,7 @@ defineExpose({ runButtonClick })
|
||||
/>
|
||||
<NodeWidgets
|
||||
:node-data
|
||||
class="py-3 gap-y-3 **:[.col-span-2]:grid-cols-1 *:has-[textarea]:h-50 rounded-lg max-w-100"
|
||||
class="max-w-100 gap-y-3 rounded-lg py-3 *:has-[textarea]:h-50 **:[.col-span-2]:grid-cols-1"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
@@ -209,7 +209,7 @@ defineExpose({ runButtonClick })
|
||||
<Button v-if="false"> {{ t('menuLabels.publish') }} </Button>
|
||||
</section>
|
||||
<div
|
||||
class="border-x md:border-y gap-2 h-full border-(--interface-stroke) bg-comfy-menu-bg flex flex-col px-2"
|
||||
class="flex h-full flex-col gap-2 border-x border-(--interface-stroke) bg-comfy-menu-bg px-2 md:border-y"
|
||||
>
|
||||
<section
|
||||
data-testid="linear-widgets"
|
||||
@@ -235,9 +235,9 @@ defineExpose({ runButtonClick })
|
||||
:node-data
|
||||
:class="
|
||||
cn(
|
||||
'py-3 gap-y-3 **:[.col-span-2]:grid-cols-1 *:has-[textarea]:h-50 rounded-lg **:[.h-7]:h-10',
|
||||
'gap-y-3 rounded-lg py-3 *:has-[textarea]:h-50 **:[.col-span-2]:grid-cols-1 **:[.h-7]:h-10',
|
||||
nodeData.hasErrors &&
|
||||
'ring-2 ring-inset ring-node-stroke-error'
|
||||
'ring-2 ring-node-stroke-error ring-inset'
|
||||
)
|
||||
"
|
||||
/>
|
||||
@@ -251,7 +251,7 @@ defineExpose({ runButtonClick })
|
||||
:to="toastTo"
|
||||
>
|
||||
<div
|
||||
class="bg-base-foreground md:bg-secondary-background text-base-background md:text-base-foreground rounded-lg flex h-10 md:h-8 p-1 pr-2 gap-2 items-center"
|
||||
class="flex h-10 items-center gap-2 rounded-lg bg-base-foreground p-1 pr-2 text-base-background md:h-8 md:bg-secondary-background md:text-base-foreground"
|
||||
>
|
||||
<template v-if="pendingJobQueues === 0">
|
||||
<i
|
||||
@@ -275,13 +275,13 @@ defineExpose({ runButtonClick })
|
||||
<section
|
||||
v-if="mobile"
|
||||
data-testid="linear-run-button"
|
||||
class="p-4 pb-6 border-t border-node-component-border"
|
||||
class="border-t border-node-component-border p-4 pb-6"
|
||||
>
|
||||
<SubscribeToRunButton
|
||||
v-if="!isActiveSubscription"
|
||||
class="w-full mt-4"
|
||||
class="mt-4 w-full"
|
||||
/>
|
||||
<div v-else class="flex mt-4">
|
||||
<div v-else class="mt-4 flex">
|
||||
<Popover side="top" @open-auto-focus.prevent>
|
||||
<template #button>
|
||||
<Button size="lg" class="-mr-3 pr-7">
|
||||
@@ -290,7 +290,7 @@ defineExpose({ runButtonClick })
|
||||
</Button>
|
||||
</template>
|
||||
<div
|
||||
class="mb-2 m-1 text-node-component-slot-text"
|
||||
class="m-1 mb-2 text-node-component-slot-text"
|
||||
v-text="t('linearMode.runCount')"
|
||||
/>
|
||||
<ScrubableNumberInput
|
||||
@@ -315,10 +315,10 @@ defineExpose({ runButtonClick })
|
||||
<section
|
||||
v-else
|
||||
data-testid="linear-run-button"
|
||||
class="p-4 pb-6 border-t border-node-component-border"
|
||||
class="border-t border-node-component-border p-4 pb-6"
|
||||
>
|
||||
<div
|
||||
class="mb-2 m-1 text-node-component-slot-text"
|
||||
class="m-1 mb-2 text-node-component-slot-text"
|
||||
v-text="t('linearMode.runCount')"
|
||||
/>
|
||||
<ScrubableNumberInput
|
||||
@@ -330,12 +330,12 @@ defineExpose({ runButtonClick })
|
||||
/>
|
||||
<SubscribeToRunButton
|
||||
v-if="!isActiveSubscription"
|
||||
class="w-full mt-4"
|
||||
class="mt-4 w-full"
|
||||
/>
|
||||
<Button
|
||||
v-else
|
||||
variant="primary"
|
||||
class="w-full mt-4 text-sm"
|
||||
class="mt-4 w-full text-sm"
|
||||
size="lg"
|
||||
@click="runButtonClick"
|
||||
>
|
||||
|
||||
@@ -22,7 +22,7 @@ const visible = computed(() => sidebarOnLeft.value === (side === 'left'))
|
||||
<div
|
||||
:class="
|
||||
cn(
|
||||
'flex items-center gap-2 px-4 text-nowrap text-base-foreground self-end pb-4',
|
||||
'flex items-center gap-2 self-end px-4 pb-4 text-nowrap text-base-foreground',
|
||||
side === 'right' && 'flex-row-reverse',
|
||||
!visible && 'invisible'
|
||||
)
|
||||
|
||||
@@ -91,7 +91,7 @@ async function rerun(e: Event) {
|
||||
<section
|
||||
v-if="selectedItem || selectedOutput || !executionStore.isIdle"
|
||||
data-testid="linear-output-info"
|
||||
class="flex flex-wrap gap-2 p-4 w-full md:z-10 tabular-nums justify-center text-sm"
|
||||
class="flex w-full flex-wrap justify-center gap-2 p-4 text-sm tabular-nums md:z-10"
|
||||
>
|
||||
<template v-if="selectedItem">
|
||||
<Button size="md" @click="rerun">
|
||||
@@ -102,7 +102,7 @@ async function rerun(e: Event) {
|
||||
{{ t('linearMode.reuseParameters') }}
|
||||
<i class="icon-[lucide--list-restart]" />
|
||||
</Button>
|
||||
<div class="border-r border-border-subtle mx-1" />
|
||||
<div class="mx-1 border-r border-border-subtle" />
|
||||
</template>
|
||||
<Button
|
||||
v-if="selectedOutput"
|
||||
@@ -153,17 +153,17 @@ async function rerun(e: Event) {
|
||||
<VideoPreview
|
||||
v-else-if="getMediaType(selectedOutput) === 'video'"
|
||||
:src="selectedOutput!.url"
|
||||
class="object-contain flex-1 md:contain-size md:p-3"
|
||||
class="flex-1 object-contain md:p-3 md:contain-size"
|
||||
/>
|
||||
<audio
|
||||
v-else-if="getMediaType(selectedOutput) === 'audio'"
|
||||
class="w-full m-auto"
|
||||
class="m-auto w-full"
|
||||
controls
|
||||
:src="selectedOutput!.url"
|
||||
/>
|
||||
<article
|
||||
v-else-if="getMediaType(selectedOutput) === 'text'"
|
||||
class="w-full max-w-lg m-auto my-12 overflow-y-auto"
|
||||
class="m-auto my-12 w-full max-w-lg overflow-y-auto"
|
||||
v-text="selectedOutput!.url"
|
||||
/>
|
||||
<Preview3d
|
||||
|
||||
@@ -17,7 +17,7 @@ const templateSelectorDialog = useWorkflowTemplateSelectorDialog()
|
||||
<div
|
||||
role="article"
|
||||
data-testid="linear-welcome"
|
||||
class="flex flex-col items-center justify-center h-full gap-6 p-8 max-w-lg mx-auto text-center"
|
||||
class="mx-auto flex h-full max-w-lg flex-col items-center justify-center gap-6 p-8 text-center"
|
||||
>
|
||||
<div class="flex flex-col gap-2">
|
||||
<h2 class="text-3xl font-semibold text-muted-foreground">
|
||||
@@ -25,7 +25,7 @@ const templateSelectorDialog = useWorkflowTemplateSelectorDialog()
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-3 text-muted-foreground max-w-md text-[14px]">
|
||||
<div class="flex max-w-md flex-col gap-3 text-[14px] text-muted-foreground">
|
||||
<p class="mt-0">{{ t('linearMode.welcome.message') }}</p>
|
||||
<p class="mt-0">{{ t('linearMode.welcome.controls') }}</p>
|
||||
<p class="mt-0">{{ t('linearMode.welcome.sharing') }}</p>
|
||||
@@ -35,7 +35,7 @@ const templateSelectorDialog = useWorkflowTemplateSelectorDialog()
|
||||
<i18n-t keypath="linearMode.welcome.getStarted" tag="span">
|
||||
<template #runButton>
|
||||
<span
|
||||
class="inline-flex items-center px-3.5 py-0.5 mx-0.5 transform -translate-y-0.5 rounded-sm bg-primary-background text-base-foreground text-xxs font-medium cursor-default"
|
||||
class="mx-0.5 inline-flex -translate-y-0.5 transform cursor-default items-center rounded-sm bg-primary-background px-3.5 py-0.5 text-xxs font-medium text-base-foreground"
|
||||
>
|
||||
{{ t('menu.run') }}
|
||||
</span>
|
||||
@@ -44,7 +44,7 @@ const templateSelectorDialog = useWorkflowTemplateSelectorDialog()
|
||||
</p>
|
||||
</div>
|
||||
<template v-else>
|
||||
<p v-if="!hasNodes" class="mt-0 text-base-foreground text-sm max-w-md">
|
||||
<p v-if="!hasNodes" class="mt-0 max-w-md text-sm text-base-foreground">
|
||||
{{ t('linearMode.emptyWorkflowExplanation') }}
|
||||
</p>
|
||||
<div class="flex flex-row gap-2">
|
||||
@@ -68,7 +68,7 @@ const templateSelectorDialog = useWorkflowTemplateSelectorDialog()
|
||||
<i class="icon-[lucide--hammer]" />
|
||||
{{ t('linearMode.welcome.buildApp') }}
|
||||
<div
|
||||
class="bg-base-foreground text-base-background text-xxs rounded-full absolute -top-2 -right-2 px-1"
|
||||
class="absolute -top-2 -right-2 rounded-full bg-base-foreground px-1 text-xxs text-base-background"
|
||||
>
|
||||
{{ t('g.experimental') }}
|
||||
</div>
|
||||
|
||||
@@ -149,9 +149,9 @@ const menuEntries = computed<MenuItem[]>(() => [
|
||||
])
|
||||
</script>
|
||||
<template>
|
||||
<section class="absolute size-full flex flex-col bg-secondary-background">
|
||||
<section class="absolute flex size-full flex-col bg-secondary-background">
|
||||
<header
|
||||
class="w-full h-16 px-4 py-3 flex border-border-subtle border-b items-center gap-3 bg-base-background"
|
||||
class="flex h-16 w-full items-center gap-3 border-b border-border-subtle bg-base-background px-4 py-3"
|
||||
>
|
||||
<DropdownMenu :entries="menuEntries" />
|
||||
<Popover
|
||||
@@ -162,52 +162,52 @@ const menuEntries = computed<MenuItem[]>(() => [
|
||||
<template #button>
|
||||
<!--TODO: Use button here? Probably too much work to destyle-->
|
||||
<div
|
||||
class="bg-secondary-background h-10 rounded-sm grow flex items-center p-2 gap-2"
|
||||
class="flex h-10 grow items-center gap-2 rounded-sm bg-secondary-background p-2"
|
||||
>
|
||||
<i
|
||||
class="shrink-0 icon-[lucide--panels-top-left] bg-primary-background"
|
||||
class="icon-[lucide--panels-top-left] shrink-0 bg-primary-background"
|
||||
/>
|
||||
<span
|
||||
class="truncate contain-size size-full"
|
||||
class="size-full truncate contain-size"
|
||||
v-text="workflowStore.activeWorkflow?.filename"
|
||||
/>
|
||||
<i
|
||||
class="shrink-0 icon-[lucide--chevron-down] bg-muted-foreground"
|
||||
class="icon-[lucide--chevron-down] shrink-0 bg-muted-foreground"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</Popover>
|
||||
<CurrentUserButton v-if="isLoggedIn" :show-arrow="false" />
|
||||
</header>
|
||||
<div class="size-full contain-content rounded-b-4xl">
|
||||
<div class="size-full rounded-b-4xl contain-content">
|
||||
<div
|
||||
:class="
|
||||
cn('size-full relative', !isSwiping && 'transition-[translate]')
|
||||
cn('relative size-full', !isSwiping && 'transition-[translate]')
|
||||
"
|
||||
:style="{ translate }"
|
||||
>
|
||||
<div class="overflow-y-auto contain-size h-full w-screen absolute">
|
||||
<div class="absolute h-full w-screen overflow-y-auto contain-size">
|
||||
<LinearControls mobile @navigate-assets="activeIndex = 2" />
|
||||
</div>
|
||||
<div
|
||||
class="w-screen absolute h-full bg-base-background left-[100vw] top-0 flex flex-col"
|
||||
class="absolute top-0 left-[100vw] flex h-full w-screen flex-col bg-base-background"
|
||||
>
|
||||
<LinearPreview mobile />
|
||||
</div>
|
||||
<AssetsSidebarTab
|
||||
class="h-full w-screen absolute bg-base-background left-[200vw] top-0"
|
||||
class="absolute top-0 left-[200vw] h-full w-screen bg-base-background"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
ref="sliderPaneRef"
|
||||
class="h-22 p-4 w-full flex gap-4 items-center justify-around bg-secondary-background"
|
||||
class="flex h-22 w-full items-center justify-around gap-4 bg-secondary-background p-4"
|
||||
>
|
||||
<Button
|
||||
v-for="([label, icon], index) in tabs"
|
||||
:key="label"
|
||||
:variant="index === activeIndex ? 'secondary' : 'muted-textonly'"
|
||||
class="flex-col h-14 grow"
|
||||
class="h-14 grow flex-col"
|
||||
@click="onClick(index)"
|
||||
>
|
||||
<div class="relative size-4">
|
||||
@@ -218,7 +218,7 @@ const menuEntries = computed<MenuItem[]>(() => [
|
||||
(queueStore.runningTasks.length > 0 ||
|
||||
queueStore.pendingTasks.length > 0)
|
||||
"
|
||||
class="absolute bg-primary-background size-2 -top-1 -right-1 rounded-full animate-pulse"
|
||||
class="absolute -top-1 -right-1 size-2 animate-pulse rounded-full bg-primary-background"
|
||||
/>
|
||||
</div>
|
||||
{{ t(label) }}
|
||||
|
||||
@@ -41,7 +41,7 @@ const queueCount = computed(
|
||||
)
|
||||
|
||||
const itemClass = cn(
|
||||
'shrink-0 cursor-pointer p-1 rounded-lg border-2 border-transparent outline-none',
|
||||
'shrink-0 cursor-pointer rounded-lg border-2 border-transparent p-1 outline-none',
|
||||
'data-[state=checked]:border-interface-panel-job-progress-border'
|
||||
)
|
||||
|
||||
@@ -284,15 +284,15 @@ useEventListener(document.body, 'keydown', (e: KeyboardEvent) => {
|
||||
<article
|
||||
ref="outputsRef"
|
||||
data-testid="linear-outputs"
|
||||
class="py-3 overflow-y-clip overflow-x-auto min-w-0"
|
||||
class="min-w-0 overflow-x-auto overflow-y-clip py-3"
|
||||
>
|
||||
<div class="flex items-start gap-0.5 mx-auto w-fit h-21">
|
||||
<div class="mx-auto flex h-21 w-fit items-start gap-0.5">
|
||||
<div
|
||||
v-if="queueCount > 0 || hasActiveContent"
|
||||
:class="
|
||||
cn(
|
||||
'sticky left-0 z-10 shrink-0 flex items-start gap-0.5',
|
||||
'bg-comfy-menu-bg md:bg-comfy-menu-secondary-bg'
|
||||
'sticky left-0 z-10 flex shrink-0 items-start gap-0.5',
|
||||
'md:bg-comfy-menu-secondary-bg bg-comfy-menu-bg'
|
||||
)
|
||||
"
|
||||
>
|
||||
@@ -331,14 +331,14 @@ useEventListener(document.body, 'keydown', (e: KeyboardEvent) => {
|
||||
|
||||
<div
|
||||
v-if="hasActiveContent && visibleHistory.length > 0"
|
||||
class="border-l border-border-default h-12 shrink-0 mx-4"
|
||||
class="mx-4 h-12 shrink-0 border-l border-border-default"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<template v-for="(asset, aIdx) in visibleHistory" :key="asset.id">
|
||||
<div
|
||||
v-if="aIdx > 0"
|
||||
class="border-l border-border-default h-12 shrink-0 mx-4"
|
||||
class="mx-4 h-12 shrink-0 border-l border-border-default"
|
||||
/>
|
||||
<div
|
||||
v-for="(output, key) in toValue(allOutputs(asset))"
|
||||
|
||||
@@ -20,7 +20,7 @@ function clearQueue(close: () => void) {
|
||||
</script>
|
||||
<template>
|
||||
<div
|
||||
class="shrink-0 p-1 border-2 border-transparent relative"
|
||||
class="relative shrink-0 border-2 border-transparent p-1"
|
||||
data-testid="linear-job"
|
||||
>
|
||||
<Popover side="top" :show-arrow="false" @focus-outside.prevent>
|
||||
@@ -30,7 +30,7 @@ function clearQueue(close: () => void) {
|
||||
:aria-label="t('linearMode.queue.clickToClear')"
|
||||
variant="textonly"
|
||||
size="unset"
|
||||
class="size-10 rounded-sm bg-secondary-background flex items-center justify-center"
|
||||
class="flex size-10 items-center justify-center rounded-sm bg-secondary-background"
|
||||
>
|
||||
<Loader size="sm" class="text-muted-foreground" />
|
||||
</Button>
|
||||
@@ -39,7 +39,7 @@ function clearQueue(close: () => void) {
|
||||
<Button
|
||||
:disabled="queueCount === 0"
|
||||
variant="textonly"
|
||||
class="text-destructive-background px-4 text-sm"
|
||||
class="px-4 text-sm text-destructive-background"
|
||||
@click="clearQueue(close)"
|
||||
>
|
||||
<i class="icon-[lucide--list-x]" />
|
||||
@@ -50,7 +50,7 @@ function clearQueue(close: () => void) {
|
||||
<div
|
||||
v-if="queueCount > 0"
|
||||
aria-hidden="true"
|
||||
class="absolute top-0 right-0 min-w-4 h-4 flex justify-center items-center rounded-full bg-primary-background text-text-primary text-xs"
|
||||
class="absolute top-0 right-0 flex h-4 min-w-4 items-center justify-center rounded-full bg-primary-background text-xs text-text-primary"
|
||||
v-text="queueCount"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -13,7 +13,7 @@ const { output } = defineProps<{
|
||||
<template>
|
||||
<img
|
||||
v-if="getMediaType(output) === 'images'"
|
||||
class="block size-10 rounded-sm object-cover bg-secondary-background"
|
||||
class="block size-10 rounded-sm bg-secondary-background object-cover"
|
||||
loading="lazy"
|
||||
width="40"
|
||||
height="40"
|
||||
|
||||
@@ -12,7 +12,7 @@ const { latentPreview } = defineProps<{
|
||||
class="block size-10 rounded-sm object-cover"
|
||||
:src="latentPreview"
|
||||
/>
|
||||
<div v-else class="size-10 rounded-sm skeleton-shimmer" />
|
||||
<LinearProgressBar class="w-10 h-1 mt-1" rounded />
|
||||
<div v-else class="skeleton-shimmer size-10 rounded-sm" />
|
||||
<LinearProgressBar class="mt-1 h-1 w-10" rounded />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -24,7 +24,7 @@ watch([containerRef, () => modelUrl], async () => {
|
||||
<template>
|
||||
<div
|
||||
ref="containerRef"
|
||||
class="relative size-full md:w-[calc(100%-150px)] self-center"
|
||||
class="relative size-full self-center md:w-[calc(100%-150px)]"
|
||||
@mouseenter="viewer.handleMouseEnter"
|
||||
@mouseleave="viewer.handleMouseLeave"
|
||||
@resize="viewer.handleResize"
|
||||
|
||||
@@ -23,5 +23,5 @@ const height = ref('')
|
||||
}
|
||||
"
|
||||
/>
|
||||
<span class="self-center z-10" v-text="`${width} x ${height}`" />
|
||||
<span class="z-10 self-center" v-text="`${width} x ${height}`" />
|
||||
</template>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<div
|
||||
v-if="videoError"
|
||||
role="alert"
|
||||
class="flex flex-auto flex-col items-center justify-center bg-muted-background text-center text-base-foreground py-8"
|
||||
class="flex flex-auto flex-col items-center justify-center bg-muted-background py-8 text-center text-base-foreground"
|
||||
>
|
||||
<i class="mb-2 icon-[lucide--video-off] size-12 text-base-foreground" />
|
||||
<p class="text-sm text-base-foreground">
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="imageUrls.length > 0"
|
||||
class="image-preview group relative flex size-full min-h-55 min-w-16 flex-col px-2 justify-center"
|
||||
class="image-preview group relative flex size-full min-h-55 min-w-16 flex-col justify-center px-2"
|
||||
@keydown="handleKeyDown"
|
||||
>
|
||||
<!-- Image Wrapper -->
|
||||
<div
|
||||
ref="imageWrapperEl"
|
||||
class="min-h-0 flex-1 flex w-full overflow-hidden rounded-[5px] bg-muted-background relative"
|
||||
class="relative flex min-h-0 w-full flex-1 overflow-hidden rounded-[5px] bg-muted-background"
|
||||
tabindex="0"
|
||||
role="img"
|
||||
:aria-label="$t('g.imagePreview')"
|
||||
@@ -21,7 +21,7 @@
|
||||
<div
|
||||
v-if="imageError"
|
||||
role="alert"
|
||||
class="flex flex-1 self-center size-full flex-col items-center justify-around bg-muted-background text-center text-base-foreground py-8"
|
||||
class="flex size-full flex-1 flex-col items-center justify-around self-center bg-muted-background py-8 text-center text-base-foreground"
|
||||
>
|
||||
<i class="mb-2 icon-[lucide--image-off] size-12 text-base-foreground" />
|
||||
<p class="text-sm text-base-foreground">
|
||||
@@ -40,7 +40,7 @@
|
||||
v-if="!imageError"
|
||||
:src="currentImageUrl"
|
||||
:alt="imageAltText"
|
||||
class="absolute inset-0 block size-full object-contain pointer-events-none"
|
||||
class="pointer-events-none absolute inset-0 block size-full object-contain"
|
||||
@load="handleImageLoad"
|
||||
@error="handleImageError"
|
||||
/>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
v-tooltip.left="tooltipConfig"
|
||||
:class="
|
||||
cn(
|
||||
'lg-slot lg-slot--input flex items-center group rounded-r-lg m-0',
|
||||
'lg-slot lg-slot--input group m-0 flex items-center rounded-r-lg',
|
||||
'cursor-crosshair',
|
||||
dotOnly ? 'lg-slot--dot-only' : 'pr-6',
|
||||
{
|
||||
@@ -22,9 +22,9 @@
|
||||
ref="connectionDotRef"
|
||||
:class="
|
||||
cn(
|
||||
'-translate-x-1/2 w-3',
|
||||
'w-3 -translate-x-1/2',
|
||||
hasError &&
|
||||
'before:ring-2 before:ring-error before:ring-offset-0 before:size-4 before:absolute before:rounded-full before:pointer-events-none'
|
||||
'before:pointer-events-none before:absolute before:size-4 before:rounded-full before:ring-2 before:ring-error before:ring-offset-0'
|
||||
)
|
||||
"
|
||||
:slot-data
|
||||
@@ -34,13 +34,13 @@
|
||||
/>
|
||||
|
||||
<!-- Slot Name -->
|
||||
<div class="h-full flex items-center min-w-0">
|
||||
<div class="flex h-full min-w-0 items-center">
|
||||
<span
|
||||
v-if="!props.dotOnly && !hasNoLabel"
|
||||
:class="
|
||||
cn(
|
||||
'truncate text-node-component-slot-text',
|
||||
hasError && 'text-error font-medium'
|
||||
hasError && 'font-medium text-error'
|
||||
)
|
||||
"
|
||||
>
|
||||
|
||||
@@ -9,24 +9,24 @@
|
||||
:data-node-id="nodeData.id"
|
||||
:class="
|
||||
cn(
|
||||
'group/node bg-node-component-header-surface lg-node absolute text-sm',
|
||||
'contain-style contain-layout min-w-[225px] min-h-(--node-height) w-(--node-width)',
|
||||
'group/node lg-node absolute bg-node-component-header-surface text-sm',
|
||||
'min-h-(--node-height) w-(--node-width) min-w-[225px] contain-layout contain-style',
|
||||
shapeClass,
|
||||
'touch-none flex flex-col',
|
||||
'flex touch-none flex-col',
|
||||
'border border-solid border-component-node-border',
|
||||
// hover (only when node should handle events)
|
||||
shouldHandleNodePointerEvents &&
|
||||
'hover:ring-7 ring-node-component-ring',
|
||||
'outline-transparent outline-3 focus-visible:outline-node-component-outline',
|
||||
'ring-node-component-ring hover:ring-7',
|
||||
'outline-3 outline-transparent focus-visible:outline-node-component-outline',
|
||||
borderClass,
|
||||
outlineClass,
|
||||
cursorClass,
|
||||
{
|
||||
[`${beforeShapeClass} before:pointer-events-none before:absolute before:bg-bypass/60 before:inset-0`]:
|
||||
[`${beforeShapeClass} before:pointer-events-none before:absolute before:inset-0 before:bg-bypass/60`]:
|
||||
bypassed,
|
||||
[`${beforeShapeClass} before:pointer-events-none before:absolute before:inset-0`]:
|
||||
muted,
|
||||
'ring-4 ring-primary-500 bg-primary-500/10': isDraggingOver
|
||||
'bg-primary-500/10 ring-4 ring-primary-500': isDraggingOver
|
||||
},
|
||||
shouldHandleNodePointerEvents && !nodeData.flags?.ghost
|
||||
? 'pointer-events-auto'
|
||||
@@ -58,7 +58,7 @@
|
||||
/>
|
||||
<div
|
||||
v-if="displayHeader"
|
||||
class="flex flex-col justify-center items-center relative"
|
||||
class="relative flex flex-col items-center justify-center"
|
||||
>
|
||||
<template v-if="isCollapsed">
|
||||
<SlotConnectionDot
|
||||
@@ -110,14 +110,14 @@
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="flex flex-1 flex-col gap-1 pt-1 pb-3 bg-component-node-background rounded-b-2xl"
|
||||
class="flex flex-1 flex-col gap-1 rounded-b-2xl bg-component-node-background pt-1 pb-3"
|
||||
:data-testid="`node-body-${nodeData.id}`"
|
||||
>
|
||||
<NodeSlots :node-data="nodeData" />
|
||||
|
||||
<NodeWidgets v-if="nodeData.widgets?.length" :node-data="nodeData" />
|
||||
|
||||
<div v-if="hasCustomContent" class="min-h-0 flex-1 flex flex-col">
|
||||
<div v-if="hasCustomContent" class="flex min-h-0 flex-1 flex-col">
|
||||
<NodeContent
|
||||
v-if="nodeMedia"
|
||||
:node-data="nodeData"
|
||||
@@ -147,7 +147,7 @@
|
||||
"
|
||||
:class="
|
||||
cn(
|
||||
'flex w-full h-7 rounded-b-2xl -z-1 text-xs rounded-t-none overflow-hidden divide-x divide-component-node-border',
|
||||
'-z-1 flex h-7 w-full divide-x divide-component-node-border overflow-hidden rounded-t-none rounded-b-2xl text-xs',
|
||||
!isCollapsed && '-mt-5 h-12'
|
||||
)
|
||||
"
|
||||
@@ -157,7 +157,7 @@
|
||||
variant="textonly"
|
||||
:class="
|
||||
cn(
|
||||
'flex-1 rounded-none h-full',
|
||||
'h-full flex-1 rounded-none',
|
||||
hasAnyError &&
|
||||
showErrorsTabEnabled &&
|
||||
!nodeData.color &&
|
||||
@@ -181,7 +181,7 @@
|
||||
variant="textonly"
|
||||
:class="
|
||||
cn(
|
||||
'flex-1 rounded-none h-full bg-error hover:bg-destructive-background-hover',
|
||||
'h-full flex-1 rounded-none bg-error hover:bg-destructive-background-hover',
|
||||
isCollapsed ? 'py-2' : 'pt-7 pb-2'
|
||||
)
|
||||
"
|
||||
@@ -199,7 +199,7 @@
|
||||
"
|
||||
variant="textonly"
|
||||
:class="
|
||||
cn('flex-1 rounded-none h-full', isCollapsed ? 'py-2' : 'pt-7 pb-2')
|
||||
cn('h-full flex-1 rounded-none', isCollapsed ? 'py-2' : 'pt-7 pb-2')
|
||||
"
|
||||
@click.stop="showAdvancedState = !showAdvancedState"
|
||||
>
|
||||
@@ -238,7 +238,7 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 12 12"
|
||||
:class="cn('size-2/5 absolute', handle.svgPositionClasses)"
|
||||
:class="cn('absolute size-2/5', handle.svgPositionClasses)"
|
||||
:style="
|
||||
handle.svgTransform ? { transform: handle.svgTransform } : undefined
|
||||
"
|
||||
|
||||
@@ -3,18 +3,18 @@
|
||||
:data-node-id="nodeData.id"
|
||||
:class="
|
||||
cn(
|
||||
'bg-component-node-background lg-node pb-1 contain-style contain-layout w-[350px] rounded-2xl touch-none flex flex-col border border-solid outline-transparent outline-2 border-node-stroke',
|
||||
'lg-node flex w-[350px] touch-none flex-col rounded-2xl border border-solid border-node-stroke bg-component-node-background pb-1 outline-2 outline-transparent contain-layout contain-style',
|
||||
position
|
||||
)
|
||||
"
|
||||
>
|
||||
<div
|
||||
class="flex flex-col justify-center items-center relative pointer-events-none"
|
||||
class="pointer-events-none relative flex flex-col items-center justify-center"
|
||||
>
|
||||
<NodeHeader :node-data="nodeData" />
|
||||
</div>
|
||||
<div
|
||||
class="flex flex-1 flex-col gap-1 pb-2 pointer-events-none"
|
||||
class="pointer-events-none flex flex-1 flex-col gap-1 pb-2"
|
||||
:data-testid="`node-body-${nodeData.id}`"
|
||||
>
|
||||
<NodeSlots :node-data="nodeData" />
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
v-else
|
||||
:src="imageUrl"
|
||||
:alt="$t('g.liveSamplingPreview')"
|
||||
class="pointer-events-none w-full object-contain contain-size min-h-55 flex-1"
|
||||
class="pointer-events-none min-h-55 w-full flex-1 object-contain contain-size"
|
||||
@load="handleImageLoad"
|
||||
@error="handleImageError"
|
||||
/>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="text"
|
||||
class="min-w-max rounded-sm bg-node-component-surface px-1 py-0.5 text-xs flex items-center gap-1"
|
||||
class="flex min-w-max items-center gap-1 rounded-sm bg-node-component-surface px-1 py-0.5 text-xs"
|
||||
:style="{
|
||||
color: fgColor,
|
||||
backgroundColor: bgColor
|
||||
|
||||
@@ -15,18 +15,18 @@ defineProps<{
|
||||
>
|
||||
<div
|
||||
v-if="hasComfyBadge"
|
||||
class="rounded-full bg-component-node-widget-background size-6 flex justify-center items-center"
|
||||
class="flex size-6 items-center justify-center rounded-full bg-component-node-widget-background"
|
||||
>
|
||||
<i class="icon-[comfy--comfy-c] size-3" />
|
||||
</div>
|
||||
<div
|
||||
v-if="core.length"
|
||||
class="rounded-full bg-component-node-widget-background h-6 flex justify-center items-center overflow-clip"
|
||||
class="flex h-6 items-center justify-center overflow-clip rounded-full bg-component-node-widget-background"
|
||||
>
|
||||
<template v-for="(badge, index) of core" :key="badge.text">
|
||||
<div
|
||||
v-if="index !== 0"
|
||||
class="border-muted-foreground border-r h-4 mr-0.5 pr-0.5"
|
||||
class="mr-0.5 h-4 border-r border-muted-foreground pr-0.5"
|
||||
/>
|
||||
<NodeBadge
|
||||
bg-color="transparent"
|
||||
@@ -37,12 +37,12 @@ defineProps<{
|
||||
</div>
|
||||
<div
|
||||
v-if="extension.length"
|
||||
class="rounded-full bg-component-node-widget-background h-6 flex justify-center items-center overflow-clip"
|
||||
class="flex h-6 items-center justify-center overflow-clip rounded-full bg-component-node-widget-background"
|
||||
>
|
||||
<template v-for="(badge, index) of extension" :key="badge.text">
|
||||
<div
|
||||
v-if="index !== 0"
|
||||
class="border-muted-foreground border-r h-4 mr-0.5 pr-0.5"
|
||||
class="mr-0.5 h-4 border-r border-muted-foreground pr-0.5"
|
||||
/>
|
||||
<NodeBadge
|
||||
bg-color="transparent"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div v-if="renderError" class="node-error p-2 text-sm text-red-500">
|
||||
{{ st('nodeErrors.content', 'Node Content Error') }}
|
||||
</div>
|
||||
<div v-else class="lg-node-content flex grow flex-col flex-auto">
|
||||
<div v-else class="lg-node-content flex flex-auto grow flex-col">
|
||||
<!-- Default slot for custom content -->
|
||||
<slot>
|
||||
<VideoPreview
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
v-else
|
||||
:class="
|
||||
cn(
|
||||
'lg-node-header text-sm py-2 pl-2 pr-3 w-full min-w-0',
|
||||
'lg-node-header w-full min-w-0 py-2 pr-3 pl-2 text-sm',
|
||||
'text-node-component-header',
|
||||
headerShapeClass
|
||||
)
|
||||
@@ -14,9 +14,9 @@
|
||||
:data-testid="`node-header-${nodeData?.id || ''}`"
|
||||
@dblclick="handleDoubleClick"
|
||||
>
|
||||
<div class="flex items-center justify-between gap-2.5 min-w-0">
|
||||
<div class="flex min-w-0 items-center justify-between gap-2.5">
|
||||
<!-- Collapse/Expand Button -->
|
||||
<div class="relative flex items-center gap-2.5 min-w-0 shrink mr-auto">
|
||||
<div class="relative mr-auto flex min-w-0 shrink items-center gap-2.5">
|
||||
<div class="flex shrink-0 items-center px-0.5">
|
||||
<Button
|
||||
size="icon-sm"
|
||||
@@ -43,7 +43,7 @@
|
||||
class="flex min-w-0 flex-1 items-center gap-2"
|
||||
data-testid="node-title"
|
||||
>
|
||||
<div class="truncate flex-1">
|
||||
<div class="flex-1 truncate">
|
||||
<EditableText
|
||||
:model-value="displayTitle"
|
||||
:is-editing="isEditing"
|
||||
@@ -59,17 +59,17 @@
|
||||
<span
|
||||
:class="
|
||||
cn(
|
||||
'flex h-5 bg-component-node-widget-background p-1 items-center text-xs shrink-0',
|
||||
'flex h-5 shrink-0 items-center bg-component-node-widget-background p-1 text-xs',
|
||||
badge.rest ? 'rounded-l-full pr-1' : 'rounded-full'
|
||||
)
|
||||
"
|
||||
>
|
||||
<i class="h-full icon-[lucide--component] bg-amber-400" />
|
||||
<i class="icon-[lucide--component] h-full bg-amber-400" />
|
||||
<span class="truncate" v-text="badge.required" />
|
||||
</span>
|
||||
<span
|
||||
v-if="badge.rest"
|
||||
class="truncate -ml-2.5 grow basis-0 bg-component-node-widget-background rounded-r-full max-w-max min-w-0"
|
||||
class="-ml-2.5 max-w-max min-w-0 grow basis-0 truncate rounded-r-full bg-component-node-widget-background"
|
||||
>
|
||||
<span class="pr-2" v-text="badge.rest" />
|
||||
</span>
|
||||
@@ -77,7 +77,7 @@
|
||||
<NodeBadge v-if="statusBadge" v-bind="statusBadge" />
|
||||
<i
|
||||
v-if="isPinned"
|
||||
class="size-5 icon-[comfy--pin]"
|
||||
class="icon-[comfy--pin] size-5"
|
||||
data-testid="node-pin-indicator"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
<div v-if="renderError" class="node-error p-2 text-sm text-red-500">
|
||||
{{ st('nodeErrors.slots', 'Node Slots Error') }}
|
||||
</div>
|
||||
<div v-else :class="cn('flex justify-between min-w-0', unifiedWrapperClass)">
|
||||
<div v-else :class="cn('flex min-w-0 justify-between', unifiedWrapperClass)">
|
||||
<div
|
||||
v-if="filteredInputs.length"
|
||||
:class="cn('flex flex-col min-w-0', unifiedDotsClass)"
|
||||
:class="cn('flex min-w-0 flex-col', unifiedDotsClass)"
|
||||
>
|
||||
<InputSlot
|
||||
v-for="(input, index) in filteredInputs"
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
<div
|
||||
v-if="nodeData?.outputs?.length"
|
||||
:class="cn('ml-auto flex flex-col min-w-0', unifiedDotsClass)"
|
||||
:class="cn('ml-auto flex min-w-0 flex-col', unifiedDotsClass)"
|
||||
>
|
||||
<OutputSlot
|
||||
v-for="(output, index) in nodeData.outputs"
|
||||
@@ -68,13 +68,13 @@ const filteredInputs = computed(() => [
|
||||
const unifiedWrapperClass = computed((): string =>
|
||||
cn(
|
||||
unified &&
|
||||
'absolute inset-0 items-center pointer-events-none opacity-0 z-30'
|
||||
'pointer-events-none absolute inset-0 z-30 items-center opacity-0'
|
||||
)
|
||||
)
|
||||
const unifiedDotsClass = computed((): string =>
|
||||
cn(
|
||||
unified &&
|
||||
'grid grid-cols-1 grid-rows-1 gap-0 *:row-span-full *:col-span-full place-items-center'
|
||||
'grid grid-cols-1 grid-rows-1 place-items-center gap-0 *:col-span-full *:row-span-full'
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<div
|
||||
:class="
|
||||
cn(
|
||||
'z-10 w-3 opacity-0 transition-opacity duration-150 group-hover:opacity-100 flex items-stretch',
|
||||
'z-10 flex w-3 items-stretch opacity-0 transition-opacity duration-150 group-hover:opacity-100',
|
||||
widget.slotMetadata?.linked && 'opacity-100'
|
||||
)
|
||||
"
|
||||
@@ -64,7 +64,7 @@
|
||||
:class="
|
||||
cn(
|
||||
'col-span-2',
|
||||
widget.hasError && 'text-node-stroke-error font-bold'
|
||||
widget.hasError && 'font-bold text-node-stroke-error'
|
||||
)
|
||||
"
|
||||
@update:model-value="widget.updateHandler"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div v-if="renderError" class="node-error p-1 text-xs text-red-500">⚠️</div>
|
||||
<div v-else v-tooltip.right="tooltipConfig" :class="slotWrapperClass">
|
||||
<div class="relative h-full flex items-center min-w-0">
|
||||
<div class="relative flex h-full min-w-0 items-center">
|
||||
<!-- Slot Name -->
|
||||
<span
|
||||
v-if="!props.dotOnly && !hasNoLabel"
|
||||
@@ -97,7 +97,7 @@ const shouldDim = computed(() => {
|
||||
|
||||
const slotWrapperClass = computed(() =>
|
||||
cn(
|
||||
'lg-slot lg-slot--output flex items-center justify-end group rounded-l-lg h-6',
|
||||
'lg-slot lg-slot--output group flex h-6 items-center justify-end rounded-l-lg',
|
||||
'cursor-crosshair',
|
||||
dotOnly.value ? 'lg-slot--dot-only justify-center' : 'pl-6',
|
||||
{
|
||||
|
||||
@@ -46,13 +46,13 @@ const isListShape = computed(() => props.slotData?.shape === RenderShape.GRID)
|
||||
|
||||
const slotClass = computed(() =>
|
||||
cn(
|
||||
'bg-slate-300 slot-dot',
|
||||
'slot-dot bg-slate-300',
|
||||
isListShape.value ? 'rounded-[1px]' : 'rounded-full',
|
||||
'transition-all duration-150',
|
||||
'border border-solid border-node-component-slot-dot-outline',
|
||||
props.multi
|
||||
? 'w-3 h-6'
|
||||
: 'size-3 cursor-crosshair group-hover/slot:[--node-component-slot-dot-outline-opacity-mult:5] group-hover/slot:scale-125'
|
||||
? 'h-6 w-3'
|
||||
: 'size-3 cursor-crosshair group-hover/slot:scale-125 group-hover/slot:[--node-component-slot-dot-outline-opacity-mult:5]'
|
||||
)
|
||||
)
|
||||
</script>
|
||||
@@ -61,7 +61,7 @@ const slotClass = computed(() =>
|
||||
<div
|
||||
:class="
|
||||
cn(
|
||||
'after:absolute after:inset-y-0 after:w-5/2 relative size-6 flex items-center justify-center group/slot',
|
||||
'group/slot relative flex size-6 items-center justify-center after:absolute after:inset-y-0 after:w-5/2',
|
||||
props.class
|
||||
)
|
||||
"
|
||||
|
||||
@@ -51,10 +51,10 @@ const controlMode = defineModel<ControlOptions>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-113 max-w-md p-4 space-y-4">
|
||||
<div class="w-113 max-w-md space-y-4 p-4">
|
||||
<div class="text-sm/tight text-muted-foreground">
|
||||
{{ $t('widgets.valueControl.header.prefix') }}
|
||||
<span class="text-base-foreground font-medium">
|
||||
<span class="font-medium text-base-foreground">
|
||||
{{
|
||||
widgetControlMode === 'before'
|
||||
? $t('widgets.valueControl.header.before')
|
||||
@@ -71,12 +71,12 @@ const controlMode = defineModel<ControlOptions>()
|
||||
as="label"
|
||||
variant="textonly"
|
||||
size="lg"
|
||||
class="flex w-full h-[unset] text-left items-center justify-between py-2 gap-7"
|
||||
class="flex h-[unset] w-full items-center justify-between gap-7 py-2 text-left"
|
||||
:for="option.mode"
|
||||
>
|
||||
<div class="flex items-center gap-2 flex-1 min-w-0 text-wrap">
|
||||
<div class="flex min-w-0 flex-1 items-center gap-2 text-wrap">
|
||||
<div
|
||||
class="flex items-center justify-center size-8 rounded-lg shrink-0 bg-secondary-background border border-border-subtle"
|
||||
class="flex size-8 shrink-0 items-center justify-center rounded-lg border border-border-subtle bg-secondary-background"
|
||||
>
|
||||
<i
|
||||
v-if="option.icon"
|
||||
@@ -91,7 +91,7 @@ const controlMode = defineModel<ControlOptions>()
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-0.5 min-w-0 flex-1">
|
||||
<div class="flex min-w-0 flex-1 flex-col gap-0.5">
|
||||
<div class="text-sm/tight font-normal text-base-foreground">
|
||||
<span>
|
||||
{{ $t(`widgets.valueControl.${option.title}`) }}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="flex flex-col gap-1">
|
||||
<Button
|
||||
class="text-base-foreground w-full border-0 bg-component-node-widget-background p-2"
|
||||
class="w-full border-0 bg-component-node-widget-background p-2 text-base-foreground"
|
||||
:aria-label="widget.label"
|
||||
size="sm"
|
||||
variant="textonly"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<WidgetLayoutField :widget="widget">
|
||||
<label
|
||||
:class="
|
||||
cn(WidgetInputBaseClass, 'flex items-center gap-2 w-full px-4 py-2')
|
||||
cn(WidgetInputBaseClass, 'flex w-full items-center gap-2 px-4 py-2')
|
||||
"
|
||||
>
|
||||
<ColorPicker
|
||||
@@ -17,7 +17,7 @@
|
||||
@update:model-value="onPickerUpdate"
|
||||
/>
|
||||
<span
|
||||
class="text-xs truncate min-w-[4ch]"
|
||||
class="min-w-[4ch] truncate text-xs"
|
||||
data-testid="widget-color-text"
|
||||
>{{ toHexFromFormat(localValue, format) }}</span
|
||||
>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<WidgetLayoutField :widget="widget">
|
||||
<div :class="cn(WidgetInputBaseClass, 'flex items-center gap-2 pl-3 pr-2')">
|
||||
<div :class="cn(WidgetInputBaseClass, 'flex items-center gap-2 pr-2 pl-3')">
|
||||
<GradientSlider
|
||||
v-model="modelValue"
|
||||
:stops="gradientStops"
|
||||
@@ -9,7 +9,7 @@
|
||||
:step="stepValue"
|
||||
:disabled="widget.options?.disabled"
|
||||
:aria-label="widget.name"
|
||||
class="flex-1 min-w-0"
|
||||
class="min-w-0 flex-1"
|
||||
/>
|
||||
<InputNumber
|
||||
:key="timesEmptied"
|
||||
|
||||
@@ -170,7 +170,7 @@ const inputAriaAttrs = computed(() => ({
|
||||
:hide-buttons="buttonsDisabled"
|
||||
:parse-value="parseWidgetValue"
|
||||
:input-attrs="inputAriaAttrs"
|
||||
:class="cn(WidgetInputBaseClass, 'grow text-xs flex h-7 relative')"
|
||||
:class="cn(WidgetInputBaseClass, 'relative flex h-7 grow text-xs')"
|
||||
@keydown.up.prevent="updateValueBy(stepValue)"
|
||||
@keydown.down.prevent="updateValueBy(-stepValue)"
|
||||
@keydown.page-up.prevent="updateValueBy(10 * stepValue)"
|
||||
@@ -178,10 +178,10 @@ const inputAriaAttrs = computed(() => ({
|
||||
>
|
||||
<template #background>
|
||||
<div
|
||||
class="absolute size-full rounded-lg pointer-events-none overflow-clip"
|
||||
class="pointer-events-none absolute size-full overflow-clip rounded-lg"
|
||||
>
|
||||
<div
|
||||
class="bg-primary-background/15 size-full"
|
||||
class="size-full bg-primary-background/15"
|
||||
:style="{ width: `${sliderWidth}%` }"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<WidgetLayoutField :widget="widget">
|
||||
<div :class="cn(WidgetInputBaseClass, 'flex items-center gap-2 pl-3 pr-2')">
|
||||
<div :class="cn(WidgetInputBaseClass, 'flex items-center gap-2 pr-2 pl-3')">
|
||||
<Slider
|
||||
:model-value="[modelValue]"
|
||||
v-bind="filteredProps"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<Loader
|
||||
v-if="loading"
|
||||
size="sm"
|
||||
class="absolute left-3 top-1/2 z-10 -translate-y-1/2 text-component-node-foreground"
|
||||
class="absolute top-1/2 left-3 z-10 -translate-y-1/2 text-component-node-foreground"
|
||||
/>
|
||||
<InputText
|
||||
v-model="modelValue"
|
||||
@@ -13,7 +13,7 @@
|
||||
cn(
|
||||
WidgetInputBaseClass,
|
||||
'w-full px-4 hover:bg-component-node-widget-background-hovered',
|
||||
size === 'large' ? 'text-sm py-3' : 'text-xs py-2',
|
||||
size === 'large' ? 'py-3 text-sm' : 'py-2 text-xs',
|
||||
loading && 'pl-9'
|
||||
)
|
||||
"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="relative" @pointerdown.stop>
|
||||
<div class="mb-4">
|
||||
<Button
|
||||
class="text-base-foreground w-full border-0 bg-secondary-background hover:bg-secondary-background-hover"
|
||||
class="w-full border-0 bg-secondary-background text-base-foreground hover:bg-secondary-background-hover"
|
||||
:disabled="isRecording || readonly"
|
||||
@click="handleStartRecording"
|
||||
>
|
||||
@@ -12,7 +12,7 @@
|
||||
</div>
|
||||
<div
|
||||
v-if="isRecording || isPlaying || recordedURL"
|
||||
class="flex h-14 w-full min-w-0 items-center gap-2 rounded-lg px-3 bg-node-component-surface text-text-secondary"
|
||||
class="flex h-14 w-full min-w-0 items-center gap-2 rounded-lg bg-node-component-surface px-3 text-text-secondary"
|
||||
>
|
||||
<!-- Recording Status -->
|
||||
<div class="flex shrink-0 items-center gap-1">
|
||||
@@ -45,7 +45,7 @@
|
||||
<button
|
||||
v-if="isRecording"
|
||||
:title="t('g.stopRecording', 'Stop Recording')"
|
||||
class="flex shrink-0 size-8 animate-pulse items-center justify-center rounded-full border-0 bg-smoke-500/33 transition-colors"
|
||||
class="flex size-8 shrink-0 animate-pulse items-center justify-center rounded-full border-0 bg-smoke-500/33 transition-colors"
|
||||
@click="handleStopRecording"
|
||||
>
|
||||
<div class="size-2.5 rounded-sm bg-danger-100" />
|
||||
@@ -54,19 +54,19 @@
|
||||
<button
|
||||
v-else-if="!isRecording && recordedURL && !isPlaying"
|
||||
:title="t('g.playRecording') || 'Play Recording'"
|
||||
class="flex shrink-0 size-8 items-center justify-center rounded-full border-0 bg-smoke-500/33 transition-colors"
|
||||
class="flex size-8 shrink-0 items-center justify-center rounded-full border-0 bg-smoke-500/33 transition-colors"
|
||||
@click="handlePlayRecording"
|
||||
>
|
||||
<i class="text-text-secondary icon-[lucide--play] size-4" />
|
||||
<i class="icon-[lucide--play] size-4 text-text-secondary" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
v-else-if="isPlaying"
|
||||
:title="t('g.stopPlayback') || 'Stop Playback'"
|
||||
class="flex shrink-0 size-8 items-center justify-center rounded-full border-0 bg-smoke-500/33 transition-colors"
|
||||
class="flex size-8 shrink-0 items-center justify-center rounded-full border-0 bg-smoke-500/33 transition-colors"
|
||||
@click="handleStopPlayback"
|
||||
>
|
||||
<i class="text-text-secondary icon-[lucide--square] size-4" />
|
||||
<i class="icon-[lucide--square] size-4 text-text-secondary" />
|
||||
</button>
|
||||
</div>
|
||||
<audio
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
:pt="{
|
||||
option: 'text-xs',
|
||||
dropdown: 'w-8',
|
||||
label: cn('truncate min-w-[4ch]', $slots.default && 'mr-5'),
|
||||
label: cn('min-w-[4ch] truncate', $slots.default && 'mr-5'),
|
||||
overlay: 'w-fit min-w-full'
|
||||
}"
|
||||
data-capture-wheel="true"
|
||||
@@ -24,7 +24,7 @@
|
||||
/>
|
||||
</template>
|
||||
</SelectPlus>
|
||||
<div class="absolute top-5 right-8 h-4 w-7 -translate-y-4/5 flex">
|
||||
<div class="absolute top-5 right-8 flex h-4 w-7 -translate-y-4/5">
|
||||
<slot />
|
||||
</div>
|
||||
</WidgetLayoutField>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div
|
||||
:class="
|
||||
cn(
|
||||
'group relative rounded-lg hover:bg-component-node-widget-background-hovered focus-within:ring focus-within:ring-component-node-widget-background-highlighted transition-all',
|
||||
'group relative rounded-lg transition-all focus-within:ring focus-within:ring-component-node-widget-background-highlighted hover:bg-component-node-widget-background-hovered',
|
||||
widget.borderStyle
|
||||
)
|
||||
"
|
||||
@@ -10,7 +10,7 @@
|
||||
<label
|
||||
v-if="!hideLayoutField"
|
||||
:for="id"
|
||||
class="pointer-events-none absolute left-3 top-1.5 z-10 text-xxs text-muted-foreground"
|
||||
class="pointer-events-none absolute top-1.5 left-3 z-10 text-xxs text-muted-foreground"
|
||||
>
|
||||
{{ displayName }}
|
||||
</label>
|
||||
@@ -21,7 +21,7 @@
|
||||
:class="
|
||||
cn(
|
||||
WidgetInputBaseClass,
|
||||
'size-full text-xs resize-none',
|
||||
'size-full resize-none text-xs',
|
||||
!hideLayoutField && 'pt-5'
|
||||
)
|
||||
"
|
||||
@@ -37,7 +37,7 @@
|
||||
v-if="isReadOnly"
|
||||
variant="textonly"
|
||||
size="icon"
|
||||
class="invisible absolute top-1.5 right-1.5 z-10 hover:bg-base-foreground/10 group-hover:visible group-focus-within:visible"
|
||||
class="invisible absolute top-1.5 right-1.5 z-10 group-focus-within:visible group-hover:visible hover:bg-base-foreground/10"
|
||||
:title="$t('g.copyToClipboard')"
|
||||
:aria-label="$t('g.copyToClipboard')"
|
||||
@click="handleCopy"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
:class="
|
||||
cn(
|
||||
WidgetInputBaseClass,
|
||||
'w-full min-w-0 p-1 flex items-center justify-center gap-1'
|
||||
'flex w-full min-w-0 items-center justify-center gap-1 p-1'
|
||||
)
|
||||
"
|
||||
@update:model-value="(v) => handleOptionChange(v as string)"
|
||||
|
||||
@@ -45,10 +45,10 @@ watch(controlModel, props.widget.controlWidget.update)
|
||||
<Button
|
||||
variant="textonly"
|
||||
size="sm"
|
||||
class="h-4 w-7 p-0 self-center rounded-xl bg-primary-background/30 hover:bg-primary-background-hover/30"
|
||||
class="h-4 w-7 self-center rounded-xl bg-primary-background/30 p-0 hover:bg-primary-background-hover/30"
|
||||
>
|
||||
<i
|
||||
:class="`${controlButtonIcon} text-primary-background text-xs w-full`"
|
||||
:class="`${controlButtonIcon} w-full text-xs text-primary-background`"
|
||||
/>
|
||||
</Button>
|
||||
</template>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="relative" @pointerdown.stop>
|
||||
<div
|
||||
v-if="!hideWhenEmpty || modelValue"
|
||||
class="bg-component-node-widget-background box-border flex gap-4 items-center justify-start relative rounded-lg w-full h-16 px-4 py-0"
|
||||
class="relative box-border flex h-16 w-full items-center justify-start gap-4 rounded-lg bg-component-node-widget-background px-4 py-0"
|
||||
>
|
||||
<!-- Hidden audio element -->
|
||||
<audio
|
||||
@@ -108,7 +108,7 @@
|
||||
popup
|
||||
class="audio-player-menu"
|
||||
:pt:root:class="
|
||||
cn('bg-component-node-widget-background border-component-node-border')
|
||||
cn('border-component-node-border bg-component-node-widget-background')
|
||||
"
|
||||
:pt:submenu:class="cn('bg-component-node-widget-background')"
|
||||
>
|
||||
|
||||
@@ -65,9 +65,9 @@ function handleFocus(event: FocusEvent) {
|
||||
:class="
|
||||
cn(
|
||||
'group',
|
||||
'bg-component-node-widget-background rounded-lg transition-all duration-150',
|
||||
'flex-1 flex items-center',
|
||||
'text-base-foreground border-0',
|
||||
'rounded-lg bg-component-node-widget-background transition-all duration-150',
|
||||
'flex flex-1 items-center',
|
||||
'border-0 text-base-foreground',
|
||||
'focus-within:ring focus-within:ring-component-node-widget-background-highlighted/80',
|
||||
customClass
|
||||
)
|
||||
@@ -76,27 +76,27 @@ function handleFocus(event: FocusEvent) {
|
||||
<i
|
||||
:class="
|
||||
cn(
|
||||
'size-4 ml-2 shrink-0 transition-colors duration-150',
|
||||
'ml-2 size-4 shrink-0 transition-colors duration-150',
|
||||
isQuerying
|
||||
? 'icon-[lucide--loader-circle] animate-spin'
|
||||
: 'icon-[lucide--search]',
|
||||
searchQuery?.trim() !== ''
|
||||
? 'text-base-foreground'
|
||||
: 'text-muted-foreground group-hover:text-base-foreground group-focus-within:text-base-foreground'
|
||||
: 'text-muted-foreground group-focus-within:text-base-foreground group-hover:text-base-foreground'
|
||||
)
|
||||
"
|
||||
/>
|
||||
<input
|
||||
v-model="searchQuery"
|
||||
type="text"
|
||||
class="bg-transparent border-0 outline-0 ring-0 h-5 w-full my-1.5 mx-2 min-w-0"
|
||||
class="mx-2 my-1.5 h-5 w-full min-w-0 border-0 bg-transparent ring-0 outline-0"
|
||||
:placeholder="$t('g.searchPlaceholder', { subject: '' })"
|
||||
:autofocus
|
||||
@focus="handleFocus"
|
||||
/>
|
||||
<button
|
||||
v-if="searchQuery.trim().length > 0"
|
||||
class="text-muted-foreground hover:text-base-foreground bg-transparent shrink-0 border-0 outline-0 ring-0 p-0 m-0 pr-3 pl-1 flex items-center justify-center transition-all duration-150 hover:scale-108"
|
||||
class="m-0 flex shrink-0 items-center justify-center border-0 bg-transparent p-0 pr-3 pl-1 text-muted-foreground ring-0 outline-0 transition-all duration-150 hover:scale-108 hover:text-base-foreground"
|
||||
:aria-label="$t('g.clear')"
|
||||
@click="searchQuery = ''"
|
||||
>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div
|
||||
:class="
|
||||
cn(WidgetInputBaseClass, 'w-full p-1 flex min-w-0 items-center gap-1')
|
||||
cn(WidgetInputBaseClass, 'flex w-full min-w-0 items-center gap-1 p-1')
|
||||
"
|
||||
>
|
||||
<button
|
||||
@@ -9,15 +9,15 @@
|
||||
:key="getOptionValue(option, index)"
|
||||
:class="
|
||||
cn(
|
||||
'flex-1 min-w-0 h-6 px-5 py-[5px] rounded-sm flex justify-center items-center gap-1 transition-all duration-150 ease-in-out truncate',
|
||||
'bg-transparent border-none',
|
||||
'flex h-6 min-w-0 flex-1 items-center justify-center gap-1 truncate rounded-sm px-5 py-[5px] transition-all duration-150 ease-in-out',
|
||||
'border-none bg-transparent',
|
||||
'text-center text-xs font-normal',
|
||||
{
|
||||
'bg-interface-menu-component-surface-selected':
|
||||
isSelected(index) && !disabled,
|
||||
'hover:bg-interface-menu-component-surface-selected/50':
|
||||
!isSelected(index) && !disabled,
|
||||
'opacity-50 cursor-not-allowed': disabled,
|
||||
'cursor-not-allowed opacity-50': disabled,
|
||||
'cursor-pointer': !disabled
|
||||
},
|
||||
isSelected(index) && !disabled
|
||||
|
||||
@@ -43,10 +43,10 @@ const selectedItems = computed(() => {
|
||||
|
||||
const theButtonStyle = computed(() =>
|
||||
cn(
|
||||
'border-0 bg-component-node-widget-background outline-none text-text-secondary',
|
||||
'border-0 bg-component-node-widget-background text-text-secondary outline-none',
|
||||
disabled
|
||||
? 'cursor-not-allowed'
|
||||
: 'hover:bg-component-node-widget-background-hovered cursor-pointer',
|
||||
: 'cursor-pointer hover:bg-component-node-widget-background-hovered',
|
||||
selectedItems.value.length > 0 && 'text-text-primary'
|
||||
)
|
||||
)
|
||||
@@ -56,7 +56,7 @@ const theButtonStyle = computed(() =>
|
||||
<div
|
||||
:class="
|
||||
cn(WidgetInputBaseClass, 'flex text-base leading-none', {
|
||||
'opacity-50 cursor-not-allowed outline-node-component-border': disabled
|
||||
'cursor-not-allowed opacity-50 outline-node-component-border': disabled
|
||||
})
|
||||
"
|
||||
>
|
||||
@@ -64,7 +64,7 @@ const theButtonStyle = computed(() =>
|
||||
:class="
|
||||
cn(
|
||||
theButtonStyle,
|
||||
'flex justify-between items-center flex-1 min-w-0 h-8',
|
||||
'flex h-8 min-w-0 flex-1 items-center justify-between',
|
||||
{
|
||||
'rounded-l-lg': uploadable,
|
||||
'rounded-lg': !uploadable
|
||||
@@ -73,7 +73,7 @@ const theButtonStyle = computed(() =>
|
||||
"
|
||||
@click="emit('select-click', $event)"
|
||||
>
|
||||
<span class="min-w-0 flex-1 px-1 py-2 text-left truncate">
|
||||
<span class="min-w-0 flex-1 truncate px-1 py-2 text-left">
|
||||
<span v-if="!selectedItems.length">
|
||||
{{ placeholder }}
|
||||
</span>
|
||||
@@ -85,7 +85,7 @@ const theButtonStyle = computed(() =>
|
||||
class="icon-[lucide--chevron-down]"
|
||||
:class="
|
||||
cn(
|
||||
'mr-2 size-4 transition-transform duration-200 shrink-0 text-component-node-foreground-secondary',
|
||||
'mr-2 size-4 shrink-0 text-component-node-foreground-secondary transition-transform duration-200',
|
||||
isOpen && 'rotate-180'
|
||||
)
|
||||
"
|
||||
@@ -97,7 +97,7 @@ const theButtonStyle = computed(() =>
|
||||
cn(
|
||||
theButtonStyle,
|
||||
'relative',
|
||||
'size-8 flex justify-center items-center border-l rounded-r-lg border-node-component-border'
|
||||
'flex size-8 items-center justify-center rounded-r-lg border-l border-node-component-border'
|
||||
)
|
||||
"
|
||||
>
|
||||
|
||||
@@ -42,7 +42,7 @@ const baseModelSelected = defineModel<Set<string>>('baseModelSelected', {
|
||||
})
|
||||
|
||||
const actionButtonStyle = cn(
|
||||
'h-8 bg-zinc-500/20 rounded-lg outline-1 -outline-offset-1 outline-node-component-border transition-all duration-150'
|
||||
'h-8 rounded-lg bg-zinc-500/20 outline-1 -outline-offset-1 outline-node-component-border transition-all duration-150'
|
||||
)
|
||||
|
||||
const layoutSwitchItemStyle =
|
||||
@@ -114,7 +114,7 @@ function toggleBaseModelSelection(item: FilterOption) {
|
||||
cn(
|
||||
actionButtonStyle,
|
||||
'hover:outline-component-node-widget-background-highlighted/80',
|
||||
'focus-within:outline-component-node-widget-background-highlighted/80 focus-within:ring-0'
|
||||
'focus-within:ring-0 focus-within:outline-component-node-widget-background-highlighted/80'
|
||||
)
|
||||
"
|
||||
/>
|
||||
@@ -155,7 +155,7 @@ function toggleBaseModelSelection(item: FilterOption) {
|
||||
<div
|
||||
:class="
|
||||
cn(
|
||||
'flex flex-col gap-2 p-2 min-w-32',
|
||||
'flex min-w-32 flex-col gap-2 p-2',
|
||||
'bg-component-node-background',
|
||||
'rounded-lg outline -outline-offset-1 outline-component-node-border'
|
||||
)
|
||||
@@ -166,7 +166,7 @@ function toggleBaseModelSelection(item: FilterOption) {
|
||||
:key="item.name"
|
||||
variant="textonly"
|
||||
size="unset"
|
||||
:class="cn('flex justify-between items-center h-6 text-left')"
|
||||
:class="cn('flex h-6 items-center justify-between text-left')"
|
||||
@click="handleSortSelected(item)"
|
||||
>
|
||||
<span>{{ item.name }}</span>
|
||||
@@ -217,7 +217,7 @@ function toggleBaseModelSelection(item: FilterOption) {
|
||||
<div
|
||||
:class="
|
||||
cn(
|
||||
'flex flex-col gap-2 p-2 min-w-32',
|
||||
'flex min-w-32 flex-col gap-2 p-2',
|
||||
'bg-component-node-background',
|
||||
'rounded-lg outline -outline-offset-1 outline-component-node-border'
|
||||
)
|
||||
@@ -228,7 +228,7 @@ function toggleBaseModelSelection(item: FilterOption) {
|
||||
:key="item.value"
|
||||
variant="textonly"
|
||||
size="unset"
|
||||
:class="cn('flex justify-between items-center h-6 text-left')"
|
||||
:class="cn('flex h-6 items-center justify-between text-left')"
|
||||
@click="handleOwnershipSelected(item)"
|
||||
>
|
||||
<span>{{ item.name }}</span>
|
||||
@@ -279,7 +279,7 @@ function toggleBaseModelSelection(item: FilterOption) {
|
||||
<div
|
||||
:class="
|
||||
cn(
|
||||
'flex flex-col gap-2 p-2 min-w-32',
|
||||
'flex min-w-32 flex-col gap-2 p-2',
|
||||
'bg-component-node-background',
|
||||
'rounded-lg outline -outline-offset-1 outline-component-node-border'
|
||||
)
|
||||
@@ -290,7 +290,7 @@ function toggleBaseModelSelection(item: FilterOption) {
|
||||
:key="item.value"
|
||||
variant="textonly"
|
||||
size="unset"
|
||||
:class="cn('flex justify-between items-center h-6 text-left')"
|
||||
:class="cn('flex h-6 items-center justify-between text-left')"
|
||||
@click="toggleBaseModelSelection(item)"
|
||||
>
|
||||
<span>{{ item.name }}</span>
|
||||
@@ -303,7 +303,7 @@ function toggleBaseModelSelection(item: FilterOption) {
|
||||
<Button
|
||||
variant="textonly"
|
||||
size="unset"
|
||||
:class="cn('flex justify-between items-center h-6 text-left')"
|
||||
:class="cn('flex h-6 items-center justify-between text-left')"
|
||||
@click="baseModelSelected = new Set()"
|
||||
>
|
||||
{{ t('g.clearFilters') }}
|
||||
@@ -315,7 +315,7 @@ function toggleBaseModelSelection(item: FilterOption) {
|
||||
:class="
|
||||
cn(
|
||||
actionButtonStyle,
|
||||
'flex justify-center items-center p-1 gap-1 hover:outline-component-node-widget-background-highlighted'
|
||||
'flex items-center justify-center gap-1 p-1 hover:outline-component-node-widget-background-highlighted'
|
||||
)
|
||||
"
|
||||
>
|
||||
|
||||
@@ -18,7 +18,7 @@ const singleFilterOption = computed(() => filterOptions.length === 1)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="text-secondary mb-4 flex gap-1 px-4 justify-start">
|
||||
<div class="text-secondary mb-4 flex justify-start gap-1 px-4">
|
||||
<button
|
||||
v-for="option in filterOptions"
|
||||
:key="option.value"
|
||||
@@ -26,9 +26,9 @@ const singleFilterOption = computed(() => filterOptions.length === 1)
|
||||
:disabled="singleFilterOption"
|
||||
:class="
|
||||
cn(
|
||||
'px-4 py-2 rounded-md inline-flex justify-center items-center select-none appearance-none border-0 text-base-foreground',
|
||||
'inline-flex appearance-none items-center justify-center rounded-md border-0 px-4 py-2 text-base-foreground select-none',
|
||||
!singleFilterOption &&
|
||||
'transition-all duration-150 hover:text-base-foreground hover:bg-interface-menu-component-surface-hovered cursor-pointer active:scale-95',
|
||||
'cursor-pointer transition-all duration-150 hover:bg-interface-menu-component-surface-hovered hover:text-base-foreground active:scale-95',
|
||||
!singleFilterOption && filterSelected === option.value
|
||||
? 'bg-interface-menu-component-surface-selected! text-base-foreground'
|
||||
: 'bg-transparent'
|
||||
|
||||
@@ -55,13 +55,13 @@ function handleVideoLoad(event: Event) {
|
||||
<div
|
||||
:class="
|
||||
cn(
|
||||
'flex gap-1 select-none group/item cursor-pointer bg-component-node-widget-background',
|
||||
'group/item flex cursor-pointer gap-1 bg-component-node-widget-background select-none',
|
||||
'transition-[transform,box-shadow,background-color] duration-150',
|
||||
{
|
||||
'flex-col text-center': layout === 'grid',
|
||||
'flex-row text-left max-h-16 rounded-lg hover:scale-102 active:scale-98':
|
||||
'max-h-16 flex-row rounded-lg text-left hover:scale-102 active:scale-98':
|
||||
layout === 'list',
|
||||
'flex-row text-left hover:bg-component-node-widget-background-hovered rounded-lg':
|
||||
'flex-row rounded-lg text-left hover:bg-component-node-widget-background-hovered':
|
||||
layout === 'list-small',
|
||||
// selection
|
||||
'ring-2 ring-component-node-widget-background-highlighted':
|
||||
@@ -77,10 +77,10 @@ function handleVideoLoad(event: Event) {
|
||||
:class="
|
||||
cn(
|
||||
'relative',
|
||||
'w-full aspect-square overflow-hidden outline-1 -outline-offset-1 outline-interface-stroke',
|
||||
'aspect-square w-full overflow-hidden outline-1 -outline-offset-1 outline-interface-stroke',
|
||||
'transition-[transform,box-shadow] duration-150',
|
||||
{
|
||||
'min-w-16 max-w-16 rounded-l-lg': layout === 'list',
|
||||
'max-w-16 min-w-16 rounded-l-lg': layout === 'list',
|
||||
'rounded-sm group-hover/item:scale-108 group-active/item:scale-95':
|
||||
layout === 'grid',
|
||||
// selection
|
||||
@@ -96,7 +96,7 @@ function handleVideoLoad(event: Event) {
|
||||
class="absolute top-1 left-1 size-4 rounded-full border border-base-foreground bg-primary-background"
|
||||
>
|
||||
<i
|
||||
class="icon-[lucide--check] size-3 translate-y-[-0.5px] text-base-foreground bold"
|
||||
class="bold icon-[lucide--check] size-3 translate-y-[-0.5px] text-base-foreground"
|
||||
/>
|
||||
</div>
|
||||
<video
|
||||
@@ -125,8 +125,8 @@ function handleVideoLoad(event: Event) {
|
||||
:class="
|
||||
cn('flex gap-1', {
|
||||
'flex-col': layout === 'grid',
|
||||
'flex-col px-4 py-1 w-full justify-center min-w-0': layout === 'list',
|
||||
'flex-row p-2 items-center justify-between w-full':
|
||||
'w-full min-w-0 flex-col justify-center px-4 py-1': layout === 'list',
|
||||
'w-full flex-row items-center justify-between p-2':
|
||||
layout === 'list-small'
|
||||
})
|
||||
"
|
||||
@@ -135,7 +135,7 @@ function handleVideoLoad(event: Event) {
|
||||
v-tooltip="layout === 'grid' ? (label ?? name) : undefined"
|
||||
:class="
|
||||
cn(
|
||||
'block text-xs line-clamp-2 wrap-break-word overflow-hidden',
|
||||
'line-clamp-2 block overflow-hidden text-xs wrap-break-word',
|
||||
'transition-colors duration-150',
|
||||
// selection
|
||||
!!selected && 'text-base-foreground'
|
||||
|
||||
@@ -18,12 +18,12 @@ const hideLayoutField = useHideLayoutField()
|
||||
<div
|
||||
:class="
|
||||
cn(
|
||||
'grid grid-cols-subgrid min-w-0 justify-between gap-1 text-node-component-slot-text',
|
||||
'grid min-w-0 grid-cols-subgrid justify-between gap-1 text-node-component-slot-text',
|
||||
rootClass
|
||||
)
|
||||
"
|
||||
>
|
||||
<div v-if="!hideLayoutField" class="truncate content-center-safe">
|
||||
<div v-if="!hideLayoutField" class="content-center-safe truncate">
|
||||
<template v-if="widget.name">
|
||||
{{ widget.label || widget.name }}
|
||||
</template>
|
||||
@@ -33,7 +33,7 @@ const hideLayoutField = useHideLayoutField()
|
||||
<div
|
||||
:class="
|
||||
cn(
|
||||
'cursor-default min-w-0 rounded-lg focus-within:ring focus-within:ring-component-node-widget-background-highlighted transition-all',
|
||||
'min-w-0 cursor-default rounded-lg transition-all focus-within:ring focus-within:ring-component-node-widget-background-highlighted',
|
||||
widget.borderStyle
|
||||
)
|
||||
"
|
||||
|
||||
@@ -3,7 +3,7 @@ import { cn } from '@comfyorg/tailwind-utils'
|
||||
const sharedButtonClasses = cn(
|
||||
'inline-flex items-center justify-center border-0 bg-transparent text-inherit transition-colors duration-150 ease-in-out',
|
||||
'hover:bg-node-component-surface-hovered active:bg-node-component-surface-selected',
|
||||
'disabled:bg-node-component-disabled disabled:text-node-icon-disabled disabled:cursor-not-allowed'
|
||||
'disabled:cursor-not-allowed disabled:bg-node-component-disabled disabled:text-node-icon-disabled'
|
||||
)
|
||||
|
||||
export function useNumberWidgetButtonPt(options?: {
|
||||
|
||||
Reference in New Issue
Block a user