├── jest.setup.ts ├── .eslintignore ├── assets ├── workflow.png ├── full_size.png └── comfy_viewer.png ├── next.config.ts ├── postcss.config.mjs ├── src ├── components │ ├── ui │ │ ├── aspect-ratio.tsx │ │ ├── skeleton.tsx │ │ ├── collapsible.tsx │ │ ├── textarea.tsx │ │ ├── label.tsx │ │ ├── input.tsx │ │ ├── separator.tsx │ │ ├── progress.tsx │ │ ├── sonner.tsx │ │ ├── checkbox.tsx │ │ ├── slider.tsx │ │ ├── switch.tsx │ │ ├── badge.tsx │ │ ├── hover-card.tsx │ │ ├── tooltip.tsx │ │ ├── popover.tsx │ │ ├── radio-group.tsx │ │ ├── avatar.tsx │ │ ├── toggle.tsx │ │ ├── resizable.tsx │ │ ├── alert.tsx │ │ ├── scroll-area.tsx │ │ ├── toggle-group.tsx │ │ ├── tabs.tsx │ │ ├── button.tsx │ │ ├── card.tsx │ │ ├── accordion.tsx │ │ ├── input-otp.tsx │ │ ├── breadcrumb.tsx │ │ ├── pagination.tsx │ │ ├── table.tsx │ │ ├── drawer.tsx │ │ ├── dialog.tsx │ │ ├── sheet.tsx │ │ ├── form.tsx │ │ ├── alert-dialog.tsx │ │ ├── command.tsx │ │ ├── navigation-menu.tsx │ │ ├── select.tsx │ │ ├── carousel.tsx │ │ ├── context-menu.tsx │ │ └── dropdown-menu.tsx │ ├── theme-provider.tsx │ ├── theme-toggle.tsx │ ├── comfy-viewer-dialog.tsx │ ├── comfy-node.tsx │ ├── lazy-image.tsx │ ├── advanced-search-form.tsx │ ├── theme-toggle.test.tsx │ ├── app-header.test.tsx │ ├── app-header.tsx │ ├── file-tree.tsx │ ├── gallery-pagination.tsx │ ├── workflow-viewer.tsx │ ├── image-gallery.tsx │ └── sidebar.tsx ├── types │ ├── react-extensions.d.ts │ └── global.d.ts ├── hooks │ ├── use-debounce.ts │ ├── use-image-selection.ts │ ├── use-image-store.ts │ ├── use-pagination.ts │ ├── use-keyboard-navigation.ts │ └── use-image-filtering.ts ├── app │ ├── api │ │ ├── scan │ │ │ └── route.ts │ │ └── image │ │ │ └── route.ts │ ├── layout.tsx │ └── globals.css └── lib │ ├── comfy-workflow-parser.ts │ ├── file-tree.ts │ ├── utils.ts │ ├── file-tree.test.ts │ └── image-parser.ts ├── public ├── window.svg ├── file.svg └── globe.svg ├── .gitignore ├── tsconfig.json ├── jest.config.ts ├── .eslintrc.json ├── tailwind.config.ts ├── package.json └── README.md /jest.setup.ts: -------------------------------------------------------------------------------- 1 | // In jest.setup.js 2 | import "@testing-library/jest-dom"; -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .next 3 | out 4 | build 5 | next.config.ts 6 | postcss.config.mjs -------------------------------------------------------------------------------- /assets/workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christian-saldana/ComfyViewer/HEAD/assets/workflow.png -------------------------------------------------------------------------------- /assets/full_size.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christian-saldana/ComfyViewer/HEAD/assets/full_size.png -------------------------------------------------------------------------------- /assets/comfy_viewer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christian-saldana/ComfyViewer/HEAD/assets/comfy_viewer.png -------------------------------------------------------------------------------- /next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | 3 | const nextConfig: NextConfig = { 4 | }; 5 | 6 | export default nextConfig; 7 | -------------------------------------------------------------------------------- /postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /src/components/ui/aspect-ratio.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio" 4 | 5 | const AspectRatio = AspectRatioPrimitive.Root 6 | 7 | export { AspectRatio } 8 | -------------------------------------------------------------------------------- /src/components/theme-provider.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as React from "react"; 4 | 5 | import { ThemeProvider as NextThemesProvider, ThemeProviderProps } from "next-themes"; 6 | 7 | export function ThemeProvider({ children, ...props }: ThemeProviderProps) { 8 | return {children}; 9 | } -------------------------------------------------------------------------------- /src/components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/lib/utils" 2 | 3 | function Skeleton({ 4 | className, 5 | ...props 6 | }: React.HTMLAttributes) { 7 | return ( 8 |
12 | ) 13 | } 14 | 15 | export { Skeleton } 16 | -------------------------------------------------------------------------------- /public/window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/file.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/ui/collapsible.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as CollapsiblePrimitive from "@radix-ui/react-collapsible" 4 | 5 | const Collapsible = CollapsiblePrimitive.Root 6 | 7 | const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger 8 | 9 | const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent 10 | 11 | export { Collapsible, CollapsibleTrigger, CollapsibleContent } 12 | -------------------------------------------------------------------------------- /src/types/react-extensions.d.ts: -------------------------------------------------------------------------------- 1 | // This declaration file extends React's default HTML attribute types 2 | // to include non-standard, but widely used, attributes for directory selection. 3 | // This allows us to use them in our JSX without TypeScript errors. 4 | 5 | declare namespace React { 6 | interface InputHTMLAttributes extends HTMLAttributes { 7 | webkitdirectory?: string; 8 | directory?: string; 9 | } 10 | } -------------------------------------------------------------------------------- /src/hooks/use-debounce.ts: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as React from "react"; 4 | 5 | export function useDebounce(value: T, delay: number): T { 6 | const [debouncedValue, setDebouncedValue] = React.useState(value); 7 | 8 | React.useEffect(() => { 9 | const handler = setTimeout(() => { 10 | setDebouncedValue(value); 11 | }, delay); 12 | 13 | return () => { 14 | clearTimeout(handler); 15 | }; 16 | }, [value, delay]); 17 | 18 | return debouncedValue; 19 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.* 7 | .yarn/* 8 | !.yarn/patches 9 | !.yarn/plugins 10 | !.yarn/releases 11 | !.yarn/versions 12 | 13 | # testing 14 | /coverage 15 | 16 | # next.js 17 | /.next/ 18 | /out/ 19 | 20 | # production 21 | /build 22 | 23 | # misc 24 | .DS_Store 25 | *.pem 26 | 27 | # debug 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | .pnpm-debug.log* 32 | 33 | # env files (can opt-in for committing if needed) 34 | .env* 35 | 36 | # vercel 37 | .vercel 38 | 39 | # typescript 40 | *.tsbuildinfo 41 | next-env.d.ts 42 | -------------------------------------------------------------------------------- /src/components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "@/lib/utils" 4 | 5 | const Textarea = React.forwardRef< 6 | HTMLTextAreaElement, 7 | React.ComponentProps<"textarea"> 8 | >(({ className, ...props }, ref) => { 9 | return ( 10 |