@teamflojo/floimg-studio-ui 0.4.4 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../node_modules/.pnpm/zustand@5.0.9_@types+react@18.3.27_immer@10.2.0_react@19.2.3_use-sync-external-store@1.6.0_react@19.2.3_/node_modules/zustand/esm/middleware.mjs","../src/api/client.ts","../src/api/sse.ts","../src/stores/settingsStore.ts","../src/stores/workflowStore.ts","../src/editor/nodeTypes.tsx","../src/editor/WorkflowEditor.tsx","../src/components/UploadGallery.tsx","../src/components/NodePalette.tsx","../src/components/NodeInspector.tsx","../src/utils/codeGenerator.ts","../src/components/ImportModal.tsx","../src/components/Toolbar.tsx","../src/components/Gallery.tsx","../../../../packages/floimg-templates/dist/templates/data-viz.js","../../../../packages/floimg-templates/dist/templates/ai-workflows.js","../../../../packages/floimg-templates/dist/templates/marketing.js","../../../../packages/floimg-templates/dist/templates/utilities.js","../../../../packages/floimg-templates/dist/index.js","../src/components/TemplateGallery.tsx","../src/components/WorkflowLibrary.tsx","../src/components/AISettings.tsx","../src/components/AIChat.tsx","../src/components/OutputInspector.tsx","../src/App.tsx"],"sourcesContent":["const reduxImpl = (reducer, initial) => (set, _get, api) => {\n api.dispatch = (action) => {\n set((state) => reducer(state, action), false, action);\n return action;\n };\n api.dispatchFromDevtools = true;\n return { dispatch: (...args) => api.dispatch(...args), ...initial };\n};\nconst redux = reduxImpl;\n\nconst trackedConnections = /* @__PURE__ */ new Map();\nconst getTrackedConnectionState = (name) => {\n const api = trackedConnections.get(name);\n if (!api) return {};\n return Object.fromEntries(\n Object.entries(api.stores).map(([key, api2]) => [key, api2.getState()])\n );\n};\nconst extractConnectionInformation = (store, extensionConnector, options) => {\n if (store === void 0) {\n return {\n type: \"untracked\",\n connection: extensionConnector.connect(options)\n };\n }\n const existingConnection = trackedConnections.get(options.name);\n if (existingConnection) {\n return { type: \"tracked\", store, ...existingConnection };\n }\n const newConnection = {\n connection: extensionConnector.connect(options),\n stores: {}\n };\n trackedConnections.set(options.name, newConnection);\n return { type: \"tracked\", store, ...newConnection };\n};\nconst removeStoreFromTrackedConnections = (name, store) => {\n if (store === void 0) return;\n const connectionInfo = trackedConnections.get(name);\n if (!connectionInfo) return;\n delete connectionInfo.stores[store];\n if (Object.keys(connectionInfo.stores).length === 0) {\n trackedConnections.delete(name);\n }\n};\nconst findCallerName = (stack) => {\n var _a, _b;\n if (!stack) return void 0;\n const traceLines = stack.split(\"\\n\");\n const apiSetStateLineIndex = traceLines.findIndex(\n (traceLine) => traceLine.includes(\"api.setState\")\n );\n if (apiSetStateLineIndex < 0) return void 0;\n const callerLine = ((_a = traceLines[apiSetStateLineIndex + 1]) == null ? void 0 : _a.trim()) || \"\";\n return (_b = /.+ (.+) .+/.exec(callerLine)) == null ? void 0 : _b[1];\n};\nconst devtoolsImpl = (fn, devtoolsOptions = {}) => (set, get, api) => {\n const { enabled, anonymousActionType, store, ...options } = devtoolsOptions;\n let extensionConnector;\n try {\n extensionConnector = (enabled != null ? enabled : (import.meta.env ? import.meta.env.MODE : void 0) !== \"production\") && window.__REDUX_DEVTOOLS_EXTENSION__;\n } catch (e) {\n }\n if (!extensionConnector) {\n return fn(set, get, api);\n }\n const { connection, ...connectionInformation } = extractConnectionInformation(store, extensionConnector, options);\n let isRecording = true;\n api.setState = ((state, replace, nameOrAction) => {\n const r = set(state, replace);\n if (!isRecording) return r;\n const action = nameOrAction === void 0 ? {\n type: anonymousActionType || findCallerName(new Error().stack) || \"anonymous\"\n } : typeof nameOrAction === \"string\" ? { type: nameOrAction } : nameOrAction;\n if (store === void 0) {\n connection == null ? void 0 : connection.send(action, get());\n return r;\n }\n connection == null ? void 0 : connection.send(\n {\n ...action,\n type: `${store}/${action.type}`\n },\n {\n ...getTrackedConnectionState(options.name),\n [store]: api.getState()\n }\n );\n return r;\n });\n api.devtools = {\n cleanup: () => {\n if (connection && typeof connection.unsubscribe === \"function\") {\n connection.unsubscribe();\n }\n removeStoreFromTrackedConnections(options.name, store);\n }\n };\n const setStateFromDevtools = (...a) => {\n const originalIsRecording = isRecording;\n isRecording = false;\n set(...a);\n isRecording = originalIsRecording;\n };\n const initialState = fn(api.setState, get, api);\n if (connectionInformation.type === \"untracked\") {\n connection == null ? void 0 : connection.init(initialState);\n } else {\n connectionInformation.stores[connectionInformation.store] = api;\n connection == null ? void 0 : connection.init(\n Object.fromEntries(\n Object.entries(connectionInformation.stores).map(([key, store2]) => [\n key,\n key === connectionInformation.store ? initialState : store2.getState()\n ])\n )\n );\n }\n if (api.dispatchFromDevtools && typeof api.dispatch === \"function\") {\n let didWarnAboutReservedActionType = false;\n const originalDispatch = api.dispatch;\n api.dispatch = (...args) => {\n if ((import.meta.env ? import.meta.env.MODE : void 0) !== \"production\" && args[0].type === \"__setState\" && !didWarnAboutReservedActionType) {\n console.warn(\n '[zustand devtools middleware] \"__setState\" action type is reserved to set state from the devtools. Avoid using it.'\n );\n didWarnAboutReservedActionType = true;\n }\n originalDispatch(...args);\n };\n }\n connection.subscribe((message) => {\n var _a;\n switch (message.type) {\n case \"ACTION\":\n if (typeof message.payload !== \"string\") {\n console.error(\n \"[zustand devtools middleware] Unsupported action format\"\n );\n return;\n }\n return parseJsonThen(\n message.payload,\n (action) => {\n if (action.type === \"__setState\") {\n if (store === void 0) {\n setStateFromDevtools(action.state);\n return;\n }\n if (Object.keys(action.state).length !== 1) {\n console.error(\n `\n [zustand devtools middleware] Unsupported __setState action format.\n When using 'store' option in devtools(), the 'state' should have only one key, which is a value of 'store' that was passed in devtools(),\n and value of this only key should be a state object. Example: { \"type\": \"__setState\", \"state\": { \"abc123Store\": { \"foo\": \"bar\" } } }\n `\n );\n }\n const stateFromDevtools = action.state[store];\n if (stateFromDevtools === void 0 || stateFromDevtools === null) {\n return;\n }\n if (JSON.stringify(api.getState()) !== JSON.stringify(stateFromDevtools)) {\n setStateFromDevtools(stateFromDevtools);\n }\n return;\n }\n if (!api.dispatchFromDevtools) return;\n if (typeof api.dispatch !== \"function\") return;\n api.dispatch(action);\n }\n );\n case \"DISPATCH\":\n switch (message.payload.type) {\n case \"RESET\":\n setStateFromDevtools(initialState);\n if (store === void 0) {\n return connection == null ? void 0 : connection.init(api.getState());\n }\n return connection == null ? void 0 : connection.init(getTrackedConnectionState(options.name));\n case \"COMMIT\":\n if (store === void 0) {\n connection == null ? void 0 : connection.init(api.getState());\n return;\n }\n return connection == null ? void 0 : connection.init(getTrackedConnectionState(options.name));\n case \"ROLLBACK\":\n return parseJsonThen(message.state, (state) => {\n if (store === void 0) {\n setStateFromDevtools(state);\n connection == null ? void 0 : connection.init(api.getState());\n return;\n }\n setStateFromDevtools(state[store]);\n connection == null ? void 0 : connection.init(getTrackedConnectionState(options.name));\n });\n case \"JUMP_TO_STATE\":\n case \"JUMP_TO_ACTION\":\n return parseJsonThen(message.state, (state) => {\n if (store === void 0) {\n setStateFromDevtools(state);\n return;\n }\n if (JSON.stringify(api.getState()) !== JSON.stringify(state[store])) {\n setStateFromDevtools(state[store]);\n }\n });\n case \"IMPORT_STATE\": {\n const { nextLiftedState } = message.payload;\n const lastComputedState = (_a = nextLiftedState.computedStates.slice(-1)[0]) == null ? void 0 : _a.state;\n if (!lastComputedState) return;\n if (store === void 0) {\n setStateFromDevtools(lastComputedState);\n } else {\n setStateFromDevtools(lastComputedState[store]);\n }\n connection == null ? void 0 : connection.send(\n null,\n // FIXME no-any\n nextLiftedState\n );\n return;\n }\n case \"PAUSE_RECORDING\":\n return isRecording = !isRecording;\n }\n return;\n }\n });\n return initialState;\n};\nconst devtools = devtoolsImpl;\nconst parseJsonThen = (stringified, fn) => {\n let parsed;\n try {\n parsed = JSON.parse(stringified);\n } catch (e) {\n console.error(\n \"[zustand devtools middleware] Could not parse the received json\",\n e\n );\n }\n if (parsed !== void 0) fn(parsed);\n};\n\nconst subscribeWithSelectorImpl = (fn) => (set, get, api) => {\n const origSubscribe = api.subscribe;\n api.subscribe = ((selector, optListener, options) => {\n let listener = selector;\n if (optListener) {\n const equalityFn = (options == null ? void 0 : options.equalityFn) || Object.is;\n let currentSlice = selector(api.getState());\n listener = (state) => {\n const nextSlice = selector(state);\n if (!equalityFn(currentSlice, nextSlice)) {\n const previousSlice = currentSlice;\n optListener(currentSlice = nextSlice, previousSlice);\n }\n };\n if (options == null ? void 0 : options.fireImmediately) {\n optListener(currentSlice, currentSlice);\n }\n }\n return origSubscribe(listener);\n });\n const initialState = fn(set, get, api);\n return initialState;\n};\nconst subscribeWithSelector = subscribeWithSelectorImpl;\n\nfunction combine(initialState, create) {\n return (...args) => Object.assign({}, initialState, create(...args));\n}\n\nfunction createJSONStorage(getStorage, options) {\n let storage;\n try {\n storage = getStorage();\n } catch (e) {\n return;\n }\n const persistStorage = {\n getItem: (name) => {\n var _a;\n const parse = (str2) => {\n if (str2 === null) {\n return null;\n }\n return JSON.parse(str2, options == null ? void 0 : options.reviver);\n };\n const str = (_a = storage.getItem(name)) != null ? _a : null;\n if (str instanceof Promise) {\n return str.then(parse);\n }\n return parse(str);\n },\n setItem: (name, newValue) => storage.setItem(name, JSON.stringify(newValue, options == null ? void 0 : options.replacer)),\n removeItem: (name) => storage.removeItem(name)\n };\n return persistStorage;\n}\nconst toThenable = (fn) => (input) => {\n try {\n const result = fn(input);\n if (result instanceof Promise) {\n return result;\n }\n return {\n then(onFulfilled) {\n return toThenable(onFulfilled)(result);\n },\n catch(_onRejected) {\n return this;\n }\n };\n } catch (e) {\n return {\n then(_onFulfilled) {\n return this;\n },\n catch(onRejected) {\n return toThenable(onRejected)(e);\n }\n };\n }\n};\nconst persistImpl = (config, baseOptions) => (set, get, api) => {\n let options = {\n storage: createJSONStorage(() => localStorage),\n partialize: (state) => state,\n version: 0,\n merge: (persistedState, currentState) => ({\n ...currentState,\n ...persistedState\n }),\n ...baseOptions\n };\n let hasHydrated = false;\n const hydrationListeners = /* @__PURE__ */ new Set();\n const finishHydrationListeners = /* @__PURE__ */ new Set();\n let storage = options.storage;\n if (!storage) {\n return config(\n (...args) => {\n console.warn(\n `[zustand persist middleware] Unable to update item '${options.name}', the given storage is currently unavailable.`\n );\n set(...args);\n },\n get,\n api\n );\n }\n const setItem = () => {\n const state = options.partialize({ ...get() });\n return storage.setItem(options.name, {\n state,\n version: options.version\n });\n };\n const savedSetState = api.setState;\n api.setState = (state, replace) => {\n savedSetState(state, replace);\n return setItem();\n };\n const configResult = config(\n (...args) => {\n set(...args);\n return setItem();\n },\n get,\n api\n );\n api.getInitialState = () => configResult;\n let stateFromStorage;\n const hydrate = () => {\n var _a, _b;\n if (!storage) return;\n hasHydrated = false;\n hydrationListeners.forEach((cb) => {\n var _a2;\n return cb((_a2 = get()) != null ? _a2 : configResult);\n });\n const postRehydrationCallback = ((_b = options.onRehydrateStorage) == null ? void 0 : _b.call(options, (_a = get()) != null ? _a : configResult)) || void 0;\n return toThenable(storage.getItem.bind(storage))(options.name).then((deserializedStorageValue) => {\n if (deserializedStorageValue) {\n if (typeof deserializedStorageValue.version === \"number\" && deserializedStorageValue.version !== options.version) {\n if (options.migrate) {\n const migration = options.migrate(\n deserializedStorageValue.state,\n deserializedStorageValue.version\n );\n if (migration instanceof Promise) {\n return migration.then((result) => [true, result]);\n }\n return [true, migration];\n }\n console.error(\n `State loaded from storage couldn't be migrated since no migrate function was provided`\n );\n } else {\n return [false, deserializedStorageValue.state];\n }\n }\n return [false, void 0];\n }).then((migrationResult) => {\n var _a2;\n const [migrated, migratedState] = migrationResult;\n stateFromStorage = options.merge(\n migratedState,\n (_a2 = get()) != null ? _a2 : configResult\n );\n set(stateFromStorage, true);\n if (migrated) {\n return setItem();\n }\n }).then(() => {\n postRehydrationCallback == null ? void 0 : postRehydrationCallback(stateFromStorage, void 0);\n stateFromStorage = get();\n hasHydrated = true;\n finishHydrationListeners.forEach((cb) => cb(stateFromStorage));\n }).catch((e) => {\n postRehydrationCallback == null ? void 0 : postRehydrationCallback(void 0, e);\n });\n };\n api.persist = {\n setOptions: (newOptions) => {\n options = {\n ...options,\n ...newOptions\n };\n if (newOptions.storage) {\n storage = newOptions.storage;\n }\n },\n clearStorage: () => {\n storage == null ? void 0 : storage.removeItem(options.name);\n },\n getOptions: () => options,\n rehydrate: () => hydrate(),\n hasHydrated: () => hasHydrated,\n onHydrate: (cb) => {\n hydrationListeners.add(cb);\n return () => {\n hydrationListeners.delete(cb);\n };\n },\n onFinishHydration: (cb) => {\n finishHydrationListeners.add(cb);\n return () => {\n finishHydrationListeners.delete(cb);\n };\n }\n };\n if (!options.skipHydration) {\n hydrate();\n }\n return stateFromStorage || configResult;\n};\nconst persist = persistImpl;\n\nfunction ssrSafe(config, isSSR = typeof window === \"undefined\") {\n return (set, get, api) => {\n if (!isSSR) {\n return config(set, get, api);\n }\n const ssrSet = () => {\n throw new Error(\"Cannot set state of Zustand store in SSR\");\n };\n api.setState = ssrSet;\n return config(ssrSet, get, api);\n };\n}\n\nexport { combine, createJSONStorage, devtools, persist, redux, subscribeWithSelector, ssrSafe as unstable_ssrSafe };\n","import type {\n NodeDefinition,\n StudioNode,\n StudioEdge,\n ImageMetadata,\n GenerateWorkflowRequest,\n GenerateWorkflowResponse,\n GenerateStatusResponse,\n} from \"@teamflojo/floimg-studio-shared\";\n\nconst API_BASE = \"/api\";\n\nasync function fetchJson<T>(url: string, options?: RequestInit): Promise<T> {\n const response = await fetch(url, {\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ error: \"Unknown error\" }));\n throw new Error(error.error || `HTTP ${response.status}`);\n }\n\n return response.json();\n}\n\n// Node registry\nexport async function getGenerators(): Promise<NodeDefinition[]> {\n return fetchJson(`${API_BASE}/nodes/generators`);\n}\n\nexport async function getTransforms(): Promise<NodeDefinition[]> {\n return fetchJson(`${API_BASE}/nodes/transforms`);\n}\n\nexport async function getTextProviders(): Promise<NodeDefinition[]> {\n return fetchJson(`${API_BASE}/nodes/text`);\n}\n\nexport async function getVisionProviders(): Promise<NodeDefinition[]> {\n return fetchJson(`${API_BASE}/nodes/vision`);\n}\n\n// AI provider configuration passed to backend\nexport interface AIProviderConfig {\n openai?: { apiKey: string };\n anthropic?: { apiKey: string };\n gemini?: { apiKey: string };\n grok?: { apiKey: string };\n openrouter?: { apiKey: string };\n ollama?: { baseUrl: string };\n lmstudio?: { baseUrl: string };\n}\n\n// Execution\nexport async function executeWorkflow(\n nodes: StudioNode[],\n edges: StudioEdge[],\n aiProviders?: AIProviderConfig\n): Promise<{\n status: string;\n imageIds: string[];\n imageUrls?: string[]; // Presigned cloud URLs (FSC only)\n previews?: Record<string, string>;\n dataOutputs?: Record<\n string,\n { dataType: \"text\" | \"json\"; content: string; parsed?: Record<string, unknown> }\n >;\n error?: string;\n}> {\n return fetchJson(`${API_BASE}/execute/sync`, {\n method: \"POST\",\n body: JSON.stringify({ nodes, edges, aiProviders }),\n });\n}\n\n// Export\nexport async function exportYaml(\n nodes: StudioNode[],\n edges: StudioEdge[]\n): Promise<{ yaml: string }> {\n return fetchJson(`${API_BASE}/export/yaml`, {\n method: \"POST\",\n body: JSON.stringify({ nodes, edges }),\n });\n}\n\n// Images\nexport interface ImageInfo {\n id: string;\n filename: string;\n mime: string;\n size: number;\n createdAt: number;\n}\n\nexport async function listImages(): Promise<ImageInfo[]> {\n return fetchJson(`${API_BASE}/images`);\n}\n\nexport function getImageUrl(id: string): string {\n return `${API_BASE}/images/${id}/blob`;\n}\n\nexport async function getImageWorkflow(id: string): Promise<ImageMetadata | null> {\n try {\n return await fetchJson(`${API_BASE}/images/${id}/workflow`);\n } catch {\n return null; // Workflow metadata not available for this image\n }\n}\n\n// Uploads\nexport interface UploadInfo {\n id: string;\n filename: string;\n mime: string;\n size: number;\n createdAt: number;\n}\n\nexport async function uploadImage(file: File): Promise<UploadInfo> {\n const formData = new FormData();\n formData.append(\"file\", file);\n\n const response = await fetch(`${API_BASE}/uploads`, {\n method: \"POST\",\n body: formData,\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ error: \"Upload failed\" }));\n throw new Error(error.error || `HTTP ${response.status}`);\n }\n\n return response.json();\n}\n\nexport async function listUploads(): Promise<UploadInfo[]> {\n return fetchJson(`${API_BASE}/uploads`);\n}\n\nexport async function getUploadThumbnail(id: string): Promise<{ dataUrl: string }> {\n return fetchJson(`${API_BASE}/uploads/${id}/thumbnail`);\n}\n\nexport async function deleteUpload(id: string): Promise<void> {\n const response = await fetch(`${API_BASE}/uploads/${id}`, {\n method: \"DELETE\",\n });\n if (!response.ok) {\n throw new Error(`Failed to delete upload: ${response.status}`);\n }\n}\n\nexport function getUploadBlobUrl(id: string): string {\n return `${API_BASE}/uploads/${id}/blob`;\n}\n\n// Input nodes\nexport async function getInputNodes(): Promise<NodeDefinition[]> {\n return fetchJson(`${API_BASE}/nodes/inputs`);\n}\n\n// Import\nexport interface ImportResult {\n success: boolean;\n nodes: StudioNode[];\n edges: StudioEdge[];\n name: string;\n error?: string;\n line?: number;\n column?: number;\n}\n\nexport interface ImportValidationResult {\n valid: boolean;\n errors: Array<{ message: string; line?: number; column?: number }>;\n}\n\nexport async function importYaml(yaml: string): Promise<ImportResult> {\n return fetchJson(`${API_BASE}/import`, {\n method: \"POST\",\n body: JSON.stringify({ yaml }),\n });\n}\n\nexport async function validateYaml(yaml: string): Promise<ImportValidationResult> {\n return fetchJson(`${API_BASE}/import/validate`, {\n method: \"POST\",\n body: JSON.stringify({ yaml }),\n });\n}\n\n// Workflow Generation\nexport async function generateWorkflow(\n request: GenerateWorkflowRequest\n): Promise<GenerateWorkflowResponse> {\n return fetchJson(`${API_BASE}/generate/workflow`, {\n method: \"POST\",\n body: JSON.stringify(request),\n });\n}\n\nexport async function getGenerateStatus(): Promise<GenerateStatusResponse> {\n return fetchJson(`${API_BASE}/generate/status`);\n}\n","/**\n * Server-Sent Events (SSE) client utility\n *\n * Handles POST-based SSE connections for streaming execution and generation updates.\n * Uses fetch with streaming response body parsing.\n */\n\nexport interface SSEConnectionHandlers<T> {\n onMessage: (event: T) => void;\n onError: (error: Error) => void;\n onClose: () => void;\n}\n\nexport interface SSEConnection {\n abort: () => void;\n}\n\n/**\n * Create an SSE connection using POST request with JSON body.\n *\n * SSE typically uses GET, but we need POST to send workflow data.\n * This implements manual SSE parsing over a fetch streaming response.\n */\nexport function createSSEConnection<T>(\n url: string,\n body: unknown,\n handlers: SSEConnectionHandlers<T>\n): SSEConnection {\n const controller = new AbortController();\n\n // Start the streaming request\n (async () => {\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorBody = await response.json().catch(() => ({ error: \"Unknown error\" }));\n throw new Error(errorBody.error || `HTTP ${response.status}`);\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Response body is not readable\");\n }\n\n const decoder = new globalThis.TextDecoder();\n let buffer = \"\";\n\n // Read the stream\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) {\n // Process any remaining data in buffer\n if (buffer.trim()) {\n processBuffer(buffer, handlers);\n }\n break;\n }\n\n // Decode chunk and add to buffer\n buffer += decoder.decode(value, { stream: true });\n\n // Process complete SSE messages (separated by double newlines)\n const messages = buffer.split(\"\\n\\n\");\n buffer = messages.pop() || \"\"; // Keep incomplete message in buffer\n\n for (const message of messages) {\n if (message.trim()) {\n processSSEMessage(message, handlers);\n }\n }\n }\n\n handlers.onClose();\n } catch (error) {\n // Don't report abort errors\n if (error instanceof Error && error.name === \"AbortError\") {\n handlers.onClose();\n return;\n }\n handlers.onError(error instanceof Error ? error : new Error(String(error)));\n }\n })();\n\n return {\n abort: () => controller.abort(),\n };\n}\n\n/**\n * Process a single SSE message block\n */\nfunction processSSEMessage<T>(message: string, handlers: SSEConnectionHandlers<T>): void {\n const lines = message.split(\"\\n\");\n let data = \"\";\n\n for (const line of lines) {\n if (line.startsWith(\"data: \")) {\n // Accumulate data lines (SSE spec allows multiple data: lines)\n data += (data ? \"\\n\" : \"\") + line.slice(6);\n }\n // Ignore other SSE fields (event:, id:, retry:) for simplicity\n }\n\n if (data) {\n try {\n const parsed = JSON.parse(data) as T;\n handlers.onMessage(parsed);\n } catch (error) {\n console.warn(\"SSE: Failed to parse message data:\", {\n error: error instanceof Error ? error.message : String(error),\n dataPreview: data.slice(0, 200),\n dataLength: data.length,\n });\n }\n }\n}\n\n/**\n * Process remaining buffer content\n */\nfunction processBuffer<T>(buffer: string, handlers: SSEConnectionHandlers<T>): void {\n const lines = buffer.split(\"\\n\");\n let data = \"\";\n\n for (const line of lines) {\n if (line.startsWith(\"data: \")) {\n data += (data ? \"\\n\" : \"\") + line.slice(6);\n }\n }\n\n if (data) {\n try {\n const parsed = JSON.parse(data) as T;\n handlers.onMessage(parsed);\n } catch (error) {\n // Log incomplete/malformed data at end of stream for debugging\n console.warn(\"SSE: Incomplete data at end of stream:\", {\n error: error instanceof Error ? error.message : String(error),\n dataPreview: data.slice(0, 200),\n dataLength: data.length,\n });\n }\n }\n}\n","import { create } from \"zustand\";\nimport { persist } from \"zustand/middleware\";\n\n// Provider configuration for cloud APIs\ninterface CloudProvider {\n apiKey: string;\n enabled: boolean;\n}\n\n// Provider configuration for local APIs\ninterface LocalProvider {\n baseUrl: string;\n enabled: boolean;\n}\n\n// All AI provider settings\nexport interface AISettings {\n // Cloud providers (require API keys)\n openai?: CloudProvider;\n anthropic?: CloudProvider;\n gemini?: CloudProvider;\n grok?: CloudProvider;\n openrouter?: CloudProvider;\n\n // Local providers (no API key, just URL)\n ollama?: LocalProvider;\n lmstudio?: LocalProvider;\n}\n\ninterface SettingsStore {\n // AI provider settings\n ai: AISettings;\n setAIProvider: (provider: keyof AISettings, config: CloudProvider | LocalProvider) => void;\n clearAIProvider: (provider: keyof AISettings) => void;\n\n // Settings modal visibility\n showSettings: boolean;\n openSettings: () => void;\n closeSettings: () => void;\n\n // Get configured providers for API calls\n getConfiguredProviders: () => {\n openai?: { apiKey: string };\n anthropic?: { apiKey: string };\n gemini?: { apiKey: string };\n grok?: { apiKey: string };\n openrouter?: { apiKey: string };\n ollama?: { baseUrl: string };\n lmstudio?: { baseUrl: string };\n };\n}\n\n// Default URLs for local providers\nconst DEFAULT_OLLAMA_URL = \"http://localhost:11434\";\nconst DEFAULT_LMSTUDIO_URL = \"http://localhost:1234\";\n\nexport const useSettingsStore = create<SettingsStore>()(\n persist(\n (set, get) => ({\n ai: {\n ollama: {\n baseUrl: DEFAULT_OLLAMA_URL,\n enabled: false,\n },\n lmstudio: {\n baseUrl: DEFAULT_LMSTUDIO_URL,\n enabled: false,\n },\n },\n showSettings: false,\n\n setAIProvider: (provider, config) => {\n set((state) => ({\n ai: {\n ...state.ai,\n [provider]: config,\n },\n }));\n },\n\n clearAIProvider: (provider) => {\n set((state) => {\n const newAI = { ...state.ai };\n delete newAI[provider];\n return { ai: newAI };\n });\n },\n\n openSettings: () => set({ showSettings: true }),\n closeSettings: () => set({ showSettings: false }),\n\n getConfiguredProviders: () => {\n const { ai } = get();\n const result: ReturnType<SettingsStore[\"getConfiguredProviders\"]> = {};\n\n // Cloud providers - only include if enabled and has API key\n if (ai.openai?.enabled && ai.openai.apiKey) {\n result.openai = { apiKey: ai.openai.apiKey };\n }\n if (ai.anthropic?.enabled && ai.anthropic.apiKey) {\n result.anthropic = { apiKey: ai.anthropic.apiKey };\n }\n if (ai.gemini?.enabled && ai.gemini.apiKey) {\n result.gemini = { apiKey: ai.gemini.apiKey };\n }\n if (ai.grok?.enabled && ai.grok.apiKey) {\n result.grok = { apiKey: ai.grok.apiKey };\n }\n if (ai.openrouter?.enabled && ai.openrouter.apiKey) {\n result.openrouter = { apiKey: ai.openrouter.apiKey };\n }\n\n // Local providers - only include if enabled\n if (ai.ollama?.enabled) {\n result.ollama = { baseUrl: ai.ollama.baseUrl || DEFAULT_OLLAMA_URL };\n }\n if (ai.lmstudio?.enabled) {\n result.lmstudio = { baseUrl: ai.lmstudio.baseUrl || DEFAULT_LMSTUDIO_URL };\n }\n\n return result;\n },\n }),\n {\n name: \"floimg-studio-settings\",\n // Only persist AI settings, not modal visibility\n partialize: (state) => ({ ai: state.ai }),\n }\n )\n);\n","import { create } from \"zustand\";\nimport { persist } from \"zustand/middleware\";\nimport type { Node, Edge, Connection } from \"reactflow\";\nimport type {\n GeneratorNodeData,\n TransformNodeData,\n SaveNodeData,\n InputNodeData,\n VisionNodeData,\n TextNodeData,\n NodeDefinition,\n GeneratedWorkflowData,\n StudioNodeType,\n ExecutionSSEEvent,\n} from \"@teamflojo/floimg-studio-shared\";\nimport type { Template } from \"@teamflojo/floimg-templates\";\nimport { exportYaml } from \"../api/client\";\nimport { createSSEConnection, type SSEConnection } from \"../api/sse\";\n\n// Module-level variable to store active SSE connection (not in store since it's not serializable)\nlet activeExecutionConnection: SSEConnection | null = null;\nimport type { StudioNode, StudioEdge, StudioNodeData } from \"@teamflojo/floimg-studio-shared\";\nimport { useSettingsStore } from \"./settingsStore\";\n\ntype NodeData =\n | GeneratorNodeData\n | TransformNodeData\n | SaveNodeData\n | InputNodeData\n | VisionNodeData\n | TextNodeData;\n\ntype NodeExecutionStatus = \"idle\" | \"pending\" | \"running\" | \"completed\" | \"error\";\n\ninterface DataOutput {\n dataType: \"text\" | \"json\";\n content: string;\n parsed?: Record<string, unknown>;\n}\n\n// Saved workflow structure for persistence\nexport interface SavedWorkflow {\n id: string;\n name: string;\n nodes: Node<NodeData>[];\n edges: Edge[];\n createdAt: number;\n updatedAt: number;\n templateId?: string;\n}\n\ninterface ExecutionState {\n status: \"idle\" | \"running\" | \"completed\" | \"error\";\n imageIds: string[];\n imageUrls: string[]; // Presigned cloud URLs for thumbnails (FSC only)\n previews: Record<string, string>; // nodeId -> data URL\n dataOutputs: Record<string, DataOutput>; // nodeId -> text/json output (for vision/text nodes)\n nodeStatus: Record<string, NodeExecutionStatus>; // per-node execution status\n error?: string;\n}\n\ninterface WorkflowStore {\n // Nodes and edges (React Flow compatible)\n nodes: Node<NodeData>[];\n edges: Edge[];\n selectedNodeId: string | null;\n\n // Template tracking\n currentTemplateId: string | null;\n loadTemplate: (template: Template) => void;\n clearWorkflow: () => void;\n\n // Workflow persistence\n savedWorkflows: SavedWorkflow[];\n activeWorkflowId: string | null;\n activeWorkflowName: string;\n hasUnsavedChanges: boolean;\n showLibrary: boolean;\n\n // Workflow persistence methods\n saveWorkflow: (name?: string) => string;\n loadWorkflow: (id: string) => void;\n deleteWorkflow: (id: string) => void;\n renameWorkflow: (id: string, name: string) => void;\n duplicateWorkflow: (id: string) => string;\n newWorkflow: () => void;\n setActiveWorkflowName: (name: string) => void;\n toggleLibrary: () => void;\n markDirty: () => void;\n\n // Preview visibility per node (default: true)\n previewVisible: Record<string, boolean>;\n togglePreview: (id: string) => void;\n\n // Node registry\n generators: NodeDefinition[];\n transforms: NodeDefinition[];\n textProviders: NodeDefinition[];\n visionProviders: NodeDefinition[];\n setGenerators: (generators: NodeDefinition[]) => void;\n setTransforms: (transforms: NodeDefinition[]) => void;\n setTextProviders: (textProviders: NodeDefinition[]) => void;\n setVisionProviders: (visionProviders: NodeDefinition[]) => void;\n\n // Node operations\n addNode: (definition: NodeDefinition, position: { x: number; y: number }) => void;\n updateNodeData: (id: string, data: Partial<NodeData>) => void;\n deleteNode: (id: string) => void;\n duplicateNode: (id: string) => void;\n setNodes: (nodes: Node<NodeData>[]) => void;\n\n // Edge operations\n addEdge: (connection: Connection) => void;\n deleteEdge: (id: string) => void;\n setEdges: (edges: Edge[]) => void;\n\n // Selection\n setSelectedNode: (id: string | null) => void;\n\n // Execution\n execution: ExecutionState;\n execute: () => Promise<void>;\n cancelExecution: () => void;\n\n // Export\n exportToYaml: () => Promise<string>;\n\n // Import\n importFromYaml: (nodes: StudioNode[], edges: StudioEdge[], name?: string) => void;\n\n // AI-generated workflow\n loadGeneratedWorkflow: (workflow: GeneratedWorkflowData) => void;\n\n // Output inspector\n inspectedNodeId: string | null;\n openOutputInspector: (nodeId: string) => void;\n closeOutputInspector: () => void;\n}\n\nlet nodeIdCounter = 0;\n\nfunction generateNodeId(): string {\n return `node_${++nodeIdCounter}`;\n}\n\n// Helper to generate unique workflow IDs\nfunction generateWorkflowId(): string {\n const timestamp = Date.now();\n const random = Math.random().toString(36).substring(2, 8);\n return `wf_${timestamp}_${random}`;\n}\n\nexport const useWorkflowStore = create<WorkflowStore>()(\n persist(\n (set, get) => {\n // Helper to enrich node data with definition properties (isAI, acceptsReferenceImages, etc.)\n // Used by loadTemplate, importFromYaml, and loadGeneratedWorkflow\n const enrichNodeData = (studioNode: StudioNode): NodeData => {\n if (studioNode.type === \"generator\") {\n const data = studioNode.data as GeneratorNodeData;\n const def = get().generators.find((g) => g.name === data.generatorName);\n return {\n ...data,\n isAI: data.isAI ?? def?.isAI,\n acceptsReferenceImages: data.acceptsReferenceImages ?? def?.acceptsReferenceImages,\n maxReferenceImages: data.maxReferenceImages ?? def?.maxReferenceImages,\n };\n }\n if (studioNode.type === \"transform\") {\n const data = studioNode.data as TransformNodeData;\n const def = get().transforms.find(\n (t) => t.name === data.operation && t.providerName === data.providerName\n );\n return {\n ...data,\n isAI: data.isAI ?? def?.isAI,\n acceptsReferenceImages: data.acceptsReferenceImages ?? def?.acceptsReferenceImages,\n maxReferenceImages: data.maxReferenceImages ?? def?.maxReferenceImages,\n };\n }\n return studioNode.data as NodeData;\n };\n\n return {\n nodes: [],\n edges: [],\n selectedNodeId: null,\n currentTemplateId: null,\n previewVisible: {},\n generators: [],\n transforms: [],\n textProviders: [],\n visionProviders: [],\n\n // Workflow persistence state\n savedWorkflows: [],\n activeWorkflowId: null,\n activeWorkflowName: \"Untitled Workflow\",\n hasUnsavedChanges: false,\n showLibrary: false,\n\n execution: {\n status: \"idle\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: {},\n },\n\n // Output inspector state\n inspectedNodeId: null,\n openOutputInspector: (nodeId) => set({ inspectedNodeId: nodeId }),\n closeOutputInspector: () => set({ inspectedNodeId: null }),\n\n loadTemplate: (template) => {\n // Convert StudioNodes to React Flow nodes with new IDs\n const idMap = new Map<string, string>();\n\n const nodes: Node<NodeData>[] = template.workflow.nodes.map((studioNode) => {\n const newId = generateNodeId();\n idMap.set(studioNode.id, newId);\n\n return {\n id: newId,\n type: studioNode.type,\n position: studioNode.position,\n data: enrichNodeData(studioNode),\n };\n });\n\n // Convert edges with mapped IDs\n const edges: Edge[] = template.workflow.edges.map((studioEdge) => {\n const newSource = idMap.get(studioEdge.source) || studioEdge.source;\n const newTarget = idMap.get(studioEdge.target) || studioEdge.target;\n\n return {\n id: `edge_${newSource}_${newTarget}`,\n source: newSource,\n target: newTarget,\n };\n });\n\n set({\n nodes,\n edges,\n selectedNodeId: null,\n currentTemplateId: template.id,\n previewVisible: {},\n execution: {\n status: \"idle\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: {},\n },\n });\n },\n\n clearWorkflow: () => {\n set({\n nodes: [],\n edges: [],\n selectedNodeId: null,\n currentTemplateId: null,\n previewVisible: {},\n execution: {\n status: \"idle\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: {},\n },\n });\n },\n\n togglePreview: (id) => {\n set((state) => ({\n previewVisible: {\n ...state.previewVisible,\n [id]: state.previewVisible[id] === false ? true : false, // default true, toggle\n },\n }));\n },\n\n setGenerators: (generators) => set({ generators }),\n setTransforms: (transforms) => set({ transforms }),\n setTextProviders: (textProviders) => set({ textProviders }),\n setVisionProviders: (visionProviders) => set({ visionProviders }),\n\n addNode: (definition, position) => {\n const id = generateNodeId();\n let data: NodeData;\n\n if (definition.type === \"generator\") {\n data = {\n generatorName: definition.name,\n params: getDefaultParams(definition),\n isAI: definition.isAI, // Track if this is an AI generator (can accept text input)\n acceptsReferenceImages: definition.acceptsReferenceImages,\n maxReferenceImages: definition.maxReferenceImages,\n } as GeneratorNodeData;\n } else if (definition.type === \"transform\") {\n data = {\n operation: definition.name,\n providerName: definition.providerName, // Track which provider this transform belongs to\n isAI: definition.isAI, // Track if this is an AI transform (can accept text input)\n params: getDefaultParams(definition),\n acceptsReferenceImages: definition.acceptsReferenceImages,\n maxReferenceImages: definition.maxReferenceImages,\n } as TransformNodeData;\n } else if (definition.type === \"input\") {\n data = {\n uploadId: undefined,\n filename: undefined,\n mime: undefined,\n } as InputNodeData;\n } else if (definition.type === \"vision\") {\n data = {\n providerName: definition.name,\n providerLabel: definition.label, // Human-readable label (e.g., \"Gemini Vision\")\n params: getDefaultParams(definition),\n } as VisionNodeData;\n } else if (definition.type === \"text\") {\n data = {\n providerName: definition.name,\n providerLabel: definition.label, // Human-readable label (e.g., \"Gemini Text\")\n params: getDefaultParams(definition),\n } as TextNodeData;\n } else {\n // Save node - read provider and destination from definition params\n const props = definition.params?.properties || {};\n const provider = (props.provider?.default as string) || \"filesystem\";\n const destination = (props.destination?.default as string) || \"./output/image.png\";\n data = {\n destination,\n provider,\n } as SaveNodeData;\n }\n\n const newNode: Node<NodeData> = {\n id,\n type: definition.type,\n position,\n data,\n };\n\n set((state) => ({\n nodes: [...state.nodes, newNode],\n }));\n },\n\n updateNodeData: (id, data) => {\n set((state) => ({\n nodes: state.nodes.map((node) =>\n node.id === id ? { ...node, data: { ...node.data, ...data } } : node\n ),\n }));\n },\n\n deleteNode: (id) => {\n set((state) => ({\n nodes: state.nodes.filter((n) => n.id !== id),\n edges: state.edges.filter((e) => e.source !== id && e.target !== id),\n selectedNodeId: state.selectedNodeId === id ? null : state.selectedNodeId,\n }));\n },\n\n duplicateNode: (id) => {\n const state = get();\n const nodeToDuplicate = state.nodes.find((n) => n.id === id);\n if (!nodeToDuplicate) return;\n\n const newId = generateNodeId();\n const newNode: Node<NodeData> = {\n ...nodeToDuplicate,\n id: newId,\n position: {\n x: nodeToDuplicate.position.x + 50,\n y: nodeToDuplicate.position.y + 50,\n },\n data: JSON.parse(JSON.stringify(nodeToDuplicate.data)), // Deep clone\n selected: false,\n };\n\n set({\n nodes: [...state.nodes, newNode],\n selectedNodeId: newId, // Select the new node\n });\n },\n\n setNodes: (nodes) => set({ nodes }),\n\n addEdge: (connection) => {\n if (!connection.source || !connection.target) return;\n\n // Include sourceHandle and targetHandle in edge ID for uniqueness\n const handleSuffix = [connection.sourceHandle, connection.targetHandle]\n .filter(Boolean)\n .join(\"_\");\n const id = handleSuffix\n ? `edge_${connection.source}_${connection.target}_${handleSuffix}`\n : `edge_${connection.source}_${connection.target}`;\n\n const newEdge: Edge = {\n id,\n source: connection.source,\n target: connection.target,\n sourceHandle: connection.sourceHandle ?? undefined,\n targetHandle: connection.targetHandle ?? undefined,\n };\n\n set((state) => ({\n edges: [...state.edges, newEdge],\n }));\n },\n\n deleteEdge: (id) => {\n set((state) => ({\n edges: state.edges.filter((e) => e.id !== id),\n }));\n },\n\n setEdges: (edges) => set({ edges }),\n\n setSelectedNode: (id) => set({ selectedNodeId: id }),\n\n execute: async () => {\n const { nodes, edges } = get();\n\n // Convert React Flow nodes to StudioNodes\n const studioNodes = nodes.map((n) => ({\n id: n.id,\n type: n.type as \"generator\" | \"transform\" | \"save\",\n position: n.position,\n data: n.data,\n }));\n\n const studioEdges = edges.map((e) => ({\n id: e.id,\n source: e.source,\n target: e.target,\n sourceHandle: e.sourceHandle ?? undefined,\n targetHandle: e.targetHandle ?? undefined,\n }));\n\n // Get AI provider settings\n const aiProviders = useSettingsStore.getState().getConfiguredProviders();\n\n // Set all nodes to \"pending\" status (not running yet)\n const initialNodeStatus: Record<string, NodeExecutionStatus> = {};\n for (const node of nodes) {\n initialNodeStatus[node.id] = \"pending\";\n }\n\n set({\n execution: {\n status: \"running\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: initialNodeStatus,\n },\n });\n\n // Use SSE streaming for real-time progress updates\n return new Promise<void>((resolve, reject) => {\n activeExecutionConnection = createSSEConnection<ExecutionSSEEvent>(\n \"/api/execute/stream\",\n { nodes: studioNodes, edges: studioEdges, aiProviders },\n {\n onMessage: (event) => {\n const state = get();\n\n if (event.type === \"execution.started\") {\n // All nodes start as pending, they'll transition to running as they execute\n }\n\n if (event.type === \"execution.step\") {\n const step = event.data;\n\n // Update the specific node's status\n const newNodeStatus = {\n ...state.execution.nodeStatus,\n [step.nodeId]: step.status as NodeExecutionStatus,\n };\n\n // Update previews if this step has one\n const newPreviews = step.preview\n ? { ...state.execution.previews, [step.nodeId]: step.preview }\n : state.execution.previews;\n\n // Update dataOutputs if this is a text/vision node\n const newDataOutputs =\n step.dataType && step.content\n ? {\n ...state.execution.dataOutputs,\n [step.nodeId]: {\n dataType: step.dataType,\n content: step.content,\n parsed: step.parsed,\n },\n }\n : state.execution.dataOutputs;\n\n set({\n execution: {\n ...state.execution,\n nodeStatus: newNodeStatus,\n previews: newPreviews,\n dataOutputs: newDataOutputs,\n },\n });\n }\n\n if (event.type === \"execution.completed\") {\n // Mark any remaining pending nodes as completed\n const finalNodeStatus = { ...state.execution.nodeStatus };\n for (const nodeId of Object.keys(finalNodeStatus)) {\n if (\n finalNodeStatus[nodeId] === \"pending\" ||\n finalNodeStatus[nodeId] === \"running\"\n ) {\n finalNodeStatus[nodeId] = \"completed\";\n }\n }\n\n set({\n execution: {\n ...state.execution,\n status: \"completed\",\n imageIds: event.data.imageIds,\n imageUrls: event.data.imageUrls,\n nodeStatus: finalNodeStatus,\n },\n });\n resolve();\n }\n\n if (event.type === \"execution.error\") {\n // Mark nodes as error\n const errorNodeStatus = { ...state.execution.nodeStatus };\n if (event.data.nodeId) {\n errorNodeStatus[event.data.nodeId] = \"error\";\n }\n\n set({\n execution: {\n ...state.execution,\n status: \"error\",\n nodeStatus: errorNodeStatus,\n error: event.data.error,\n },\n });\n reject(new Error(event.data.error));\n }\n },\n onError: (error) => {\n const state = get();\n const errorNodeStatus: Record<string, NodeExecutionStatus> = {};\n for (const nodeId of Object.keys(state.execution.nodeStatus)) {\n errorNodeStatus[nodeId] = \"error\";\n }\n\n set({\n execution: {\n ...state.execution,\n status: \"error\",\n nodeStatus: errorNodeStatus,\n error: error.message,\n },\n });\n reject(error);\n },\n onClose: () => {\n // Clear the connection reference\n activeExecutionConnection = null;\n\n // Stream closed - check why\n const state = get();\n if (state.execution.status === \"running\") {\n // Check if this was a user cancellation (status would be 'cancelled' if so)\n // Otherwise treat as unexpected closure\n set({\n execution: {\n ...state.execution,\n status: \"error\",\n error: \"Connection closed unexpectedly\",\n },\n });\n reject(new Error(\"Connection closed unexpectedly\"));\n }\n },\n }\n );\n });\n },\n\n cancelExecution: () => {\n // Abort the active connection if any\n if (activeExecutionConnection) {\n activeExecutionConnection.abort();\n activeExecutionConnection = null;\n }\n\n // Reset execution state to idle\n set({\n execution: {\n status: \"idle\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: {},\n },\n });\n },\n\n exportToYaml: async () => {\n const { nodes, edges } = get();\n\n const studioNodes = nodes.map((n) => ({\n id: n.id,\n type: n.type as \"generator\" | \"transform\" | \"save\",\n position: n.position,\n data: n.data,\n }));\n\n const studioEdges = edges.map((e) => ({\n id: e.id,\n source: e.source,\n target: e.target,\n sourceHandle: e.sourceHandle ?? undefined,\n targetHandle: e.targetHandle ?? undefined,\n }));\n\n const result = await exportYaml(studioNodes, studioEdges);\n return result.yaml;\n },\n\n importFromYaml: (studioNodes, studioEdges, name) => {\n // Convert StudioNodes to React Flow nodes with new IDs\n const idMap = new Map<string, string>();\n\n const nodes: Node<NodeData>[] = studioNodes.map((studioNode) => {\n const newId = generateNodeId();\n idMap.set(studioNode.id, newId);\n\n return {\n id: newId,\n type: studioNode.type,\n position: studioNode.position,\n data: enrichNodeData(studioNode),\n };\n });\n\n // Convert edges with mapped IDs\n const edges: Edge[] = studioEdges.map((studioEdge) => {\n const newSource = idMap.get(studioEdge.source) || studioEdge.source;\n const newTarget = idMap.get(studioEdge.target) || studioEdge.target;\n\n return {\n id: `edge_${newSource}_${newTarget}`,\n source: newSource,\n target: newTarget,\n };\n });\n\n set({\n nodes,\n edges,\n selectedNodeId: null,\n currentTemplateId: null,\n previewVisible: {},\n activeWorkflowId: null,\n activeWorkflowName: name || \"Imported Workflow\",\n hasUnsavedChanges: true,\n execution: {\n status: \"idle\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: {},\n },\n });\n },\n\n // Workflow persistence methods\n markDirty: () => set({ hasUnsavedChanges: true }),\n\n toggleLibrary: () => set((state) => ({ showLibrary: !state.showLibrary })),\n\n setActiveWorkflowName: (name) => set({ activeWorkflowName: name, hasUnsavedChanges: true }),\n\n newWorkflow: () => {\n set({\n nodes: [],\n edges: [],\n selectedNodeId: null,\n currentTemplateId: null,\n previewVisible: {},\n activeWorkflowId: null,\n activeWorkflowName: \"Untitled Workflow\",\n hasUnsavedChanges: false,\n execution: {\n status: \"idle\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: {},\n },\n });\n },\n\n saveWorkflow: (name) => {\n const {\n nodes,\n edges,\n activeWorkflowId,\n activeWorkflowName,\n savedWorkflows,\n currentTemplateId,\n } = get();\n const now = Date.now();\n\n if (activeWorkflowId) {\n // Update existing workflow\n const updated = savedWorkflows.map((wf) =>\n wf.id === activeWorkflowId\n ? { ...wf, name: name || activeWorkflowName, nodes, edges, updatedAt: now }\n : wf\n );\n set({\n savedWorkflows: updated,\n activeWorkflowName: name || activeWorkflowName,\n hasUnsavedChanges: false,\n });\n return activeWorkflowId;\n } else {\n // Create new workflow\n const id = generateWorkflowId();\n const newWorkflow: SavedWorkflow = {\n id,\n name: name || activeWorkflowName,\n nodes,\n edges,\n createdAt: now,\n updatedAt: now,\n templateId: currentTemplateId || undefined,\n };\n set({\n savedWorkflows: [...savedWorkflows, newWorkflow],\n activeWorkflowId: id,\n activeWorkflowName: name || activeWorkflowName,\n hasUnsavedChanges: false,\n });\n return id;\n }\n },\n\n loadWorkflow: (id) => {\n const { savedWorkflows } = get();\n const workflow = savedWorkflows.find((wf) => wf.id === id);\n if (!workflow) return;\n\n // Enrich node data with definition properties (in case workflow was saved before enrichment existed)\n const enrichedNodes = workflow.nodes.map((node) => ({\n ...node,\n data: enrichNodeData({\n id: node.id,\n type: node.type as StudioNodeType,\n position: node.position,\n data: node.data as StudioNodeData,\n }),\n }));\n\n set({\n nodes: enrichedNodes,\n edges: workflow.edges,\n selectedNodeId: null,\n currentTemplateId: workflow.templateId || null,\n previewVisible: {},\n activeWorkflowId: id,\n activeWorkflowName: workflow.name,\n hasUnsavedChanges: false,\n execution: {\n status: \"idle\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: {},\n },\n });\n },\n\n deleteWorkflow: (id) => {\n const { savedWorkflows, activeWorkflowId } = get();\n const filtered = savedWorkflows.filter((wf) => wf.id !== id);\n\n if (activeWorkflowId === id) {\n // If deleting the active workflow, clear the canvas\n set({\n savedWorkflows: filtered,\n nodes: [],\n edges: [],\n selectedNodeId: null,\n currentTemplateId: null,\n previewVisible: {},\n activeWorkflowId: null,\n activeWorkflowName: \"Untitled Workflow\",\n hasUnsavedChanges: false,\n execution: {\n status: \"idle\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: {},\n },\n });\n } else {\n set({ savedWorkflows: filtered });\n }\n },\n\n renameWorkflow: (id, name) => {\n const { savedWorkflows, activeWorkflowId } = get();\n const updated = savedWorkflows.map((wf) =>\n wf.id === id ? { ...wf, name, updatedAt: Date.now() } : wf\n );\n set({\n savedWorkflows: updated,\n ...(activeWorkflowId === id ? { activeWorkflowName: name } : {}),\n });\n },\n\n duplicateWorkflow: (id) => {\n const { savedWorkflows } = get();\n const workflow = savedWorkflows.find((wf) => wf.id === id);\n if (!workflow) return \"\";\n\n const now = Date.now();\n const newId = generateWorkflowId();\n const duplicate: SavedWorkflow = {\n ...workflow,\n id: newId,\n name: `${workflow.name} (Copy)`,\n createdAt: now,\n updatedAt: now,\n };\n set({ savedWorkflows: [...savedWorkflows, duplicate] });\n return newId;\n },\n\n loadGeneratedWorkflow: (workflow: GeneratedWorkflowData) => {\n // Convert AI-generated workflow to React Flow nodes\n const idMap = new Map<string, string>();\n\n // Auto-layout: arrange nodes in a grid\n const GRID_SPACING_X = 250;\n const GRID_SPACING_Y = 150;\n const NODES_PER_ROW = 3;\n\n const nodes: Node<NodeData>[] = workflow.nodes.map((genNode, index) => {\n const newId = generateNodeId();\n idMap.set(genNode.id, newId);\n\n // Parse nodeType to extract type and name\n // Format: \"generator:dalle-3\", \"transform:sharp:resize\", \"input:upload\", etc.\n const parts = genNode.nodeType.split(\":\");\n const nodeType = parts[0] as StudioNodeType;\n\n // Calculate grid position\n const row = Math.floor(index / NODES_PER_ROW);\n const col = index % NODES_PER_ROW;\n const position = {\n x: 100 + col * GRID_SPACING_X,\n y: 100 + row * GRID_SPACING_Y,\n };\n\n // Build node data based on type\n let data: NodeData;\n\n if (nodeType === \"generator\") {\n const generatorName = parts.slice(1).join(\":\");\n // Look up generator definition to get acceptsReferenceImages and other properties\n const generatorDef = get().generators.find((g) => g.name === generatorName);\n data = {\n generatorName,\n params: genNode.parameters,\n isAI: generatorDef?.isAI ?? true, // Use definition or assume AI\n acceptsReferenceImages: generatorDef?.acceptsReferenceImages,\n maxReferenceImages: generatorDef?.maxReferenceImages,\n } as GeneratorNodeData;\n } else if (nodeType === \"transform\") {\n const providerName = parts[1];\n const operation = parts.slice(2).join(\":\");\n // Look up transform definition to get isAI and acceptsReferenceImages\n const transformDef = get().transforms.find(\n (t) => t.providerName === providerName && t.name === operation\n );\n data = {\n operation,\n providerName,\n params: genNode.parameters,\n isAI: transformDef?.isAI,\n acceptsReferenceImages: transformDef?.acceptsReferenceImages,\n maxReferenceImages: transformDef?.maxReferenceImages,\n } as TransformNodeData;\n } else if (nodeType === \"input\") {\n data = {\n uploadId: undefined,\n filename: undefined,\n mime: undefined,\n } as InputNodeData;\n } else if (nodeType === \"vision\") {\n const providerName = parts.slice(1).join(\":\");\n data = {\n providerName,\n params: genNode.parameters,\n } as VisionNodeData;\n } else if (nodeType === \"text\") {\n const providerName = parts.slice(1).join(\":\");\n // Extract jsonSchema from params and convert to outputSchema for UI\n const jsonSchema = genNode.parameters.jsonSchema as\n | { properties?: Record<string, { type?: string; description?: string }> }\n | undefined;\n const outputSchema = jsonSchema?.properties\n ? {\n type: \"object\" as const,\n properties: Object.fromEntries(\n Object.entries(jsonSchema.properties).map(([key, prop]) => [\n key,\n {\n type:\n (prop.type as \"string\" | \"number\" | \"boolean\" | \"object\" | \"array\") ||\n \"string\",\n description: prop.description,\n },\n ])\n ),\n }\n : undefined;\n data = {\n providerName,\n params: genNode.parameters,\n outputSchema,\n } as TextNodeData;\n } else {\n // Default to save node\n data = {\n destination: (genNode.parameters.destination as string) || \"./output/image.png\",\n provider: (genNode.parameters.provider as string) || \"filesystem\",\n } as SaveNodeData;\n }\n\n return {\n id: newId,\n type: nodeType,\n position,\n data,\n };\n });\n\n // Convert edges with mapped IDs\n const edges: Edge[] = workflow.edges.map((genEdge) => {\n const newSource = idMap.get(genEdge.source) || genEdge.source;\n const newTarget = idMap.get(genEdge.target) || genEdge.target;\n\n // Include handles in edge ID for uniqueness (multiple edges from same source)\n const handleSuffix = [genEdge.sourceHandle, genEdge.targetHandle]\n .filter(Boolean)\n .join(\"_\");\n const edgeId = handleSuffix\n ? `edge_${newSource}_${newTarget}_${handleSuffix}`\n : `edge_${newSource}_${newTarget}`;\n\n return {\n id: edgeId,\n source: newSource,\n target: newTarget,\n sourceHandle: genEdge.sourceHandle ?? undefined,\n targetHandle: genEdge.targetHandle ?? undefined,\n };\n });\n\n set({\n nodes,\n edges,\n selectedNodeId: null,\n currentTemplateId: null,\n previewVisible: {},\n activeWorkflowId: null,\n activeWorkflowName: \"AI Generated Workflow\",\n hasUnsavedChanges: true,\n execution: {\n status: \"idle\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: {},\n },\n });\n },\n };\n },\n {\n name: \"floimg-studio-workflows\",\n // Only persist savedWorkflows - current canvas state is ephemeral\n partialize: (state) => ({\n savedWorkflows: state.savedWorkflows,\n }),\n }\n )\n);\n\n// Helper to extract default values from schema\nfunction getDefaultParams(definition: NodeDefinition): Record<string, unknown> {\n const params: Record<string, unknown> = {};\n\n if (definition.params?.properties) {\n for (const [key, field] of Object.entries(definition.params.properties)) {\n if (field.default !== undefined) {\n params[key] = field.default;\n }\n }\n }\n\n return params;\n}\n","import { memo, useCallback, useRef } from \"react\";\nimport { Handle, Position, type NodeProps } from \"reactflow\";\nimport type {\n GeneratorNodeData,\n TransformNodeData,\n SaveNodeData,\n InputNodeData,\n VisionNodeData,\n TextNodeData,\n} from \"@teamflojo/floimg-studio-shared\";\nimport { useWorkflowStore } from \"../stores/workflowStore\";\nimport { uploadImage, getUploadBlobUrl } from \"../api/client\";\n\n// Helper to get execution status class for node border\nfunction getExecutionClass(nodeStatus: string | undefined): string {\n if (nodeStatus === \"pending\") {\n return \"border-gray-400 dark:border-zinc-500\";\n }\n if (nodeStatus === \"running\") {\n return \"border-yellow-400 animate-pulse\";\n }\n if (nodeStatus === \"completed\") {\n return \"border-green-500\";\n }\n if (nodeStatus === \"error\") {\n return \"border-red-500\";\n }\n return \"\";\n}\n\n// Eye icon for preview toggle\nfunction PreviewToggle({ nodeId, color }: { nodeId: string; color: string }) {\n const previewVisible = useWorkflowStore((s) => s.previewVisible[nodeId] !== false);\n const togglePreview = useWorkflowStore((s) => s.togglePreview);\n\n return (\n <button\n onClick={(e) => {\n e.stopPropagation();\n togglePreview(nodeId);\n }}\n className={`ml-auto p-1 rounded hover:bg-gray-200 dark:hover:bg-zinc-600 transition-colors ${previewVisible ? \"opacity-100\" : \"opacity-40\"}`}\n title={previewVisible ? \"Hide preview\" : \"Show preview\"}\n >\n <svg className={`w-3.5 h-3.5 ${color}`} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n {previewVisible ? (\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z\"\n />\n ) : (\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21\"\n />\n )}\n </svg>\n </button>\n );\n}\n\n// Generator Node (source nodes - have output only)\n// AI generators may also have a text input handle and/or references input handle\nexport const GeneratorNode = memo(function GeneratorNode({\n id,\n data,\n selected,\n}: NodeProps<GeneratorNodeData>) {\n const preview = useWorkflowStore((s) => s.execution.previews[id]);\n const nodeStatus = useWorkflowStore((s) => s.execution.nodeStatus[id]);\n const previewVisible = useWorkflowStore((s) => s.previewVisible[id] !== false);\n\n const executionClass = getExecutionClass(nodeStatus);\n const borderClass = executionClass || (selected ? \"border-blue-500\" : \"border-blue-200\");\n\n // AI generators get a text input handle for dynamic prompts\n const isAI = data.isAI;\n // Check if this generator accepts reference images\n const acceptsReferences = data.acceptsReferenceImages;\n\n return (\n <div\n className={`rounded-lg border-2 bg-white dark:bg-zinc-800 shadow-md min-w-[180px] overflow-hidden ${borderClass}`}\n >\n {/* Text input handle for AI generators (optional - for dynamic prompts) */}\n {isAI && (\n <Handle\n type=\"target\"\n position={Position.Top}\n id=\"text\"\n className=\"w-3 h-3 !bg-pink-500\"\n title=\"Text input (optional prompt from text/vision node)\"\n />\n )}\n {/* Reference images input handle (for AI generators) */}\n {acceptsReferences && (\n <Handle\n type=\"target\"\n position={Position.Left}\n id=\"references\"\n className=\"w-3 h-3 !bg-violet-500\"\n style={{ top: \"50%\" }}\n title={`Reference images (up to ${data.maxReferenceImages || 14})`}\n />\n )}\n {preview && previewVisible && (\n <div className=\"bg-gray-100 dark:bg-zinc-900 border-b border-gray-200 dark:border-zinc-700\">\n <img src={preview} alt=\"Preview\" className=\"w-full h-24 object-contain\" />\n </div>\n )}\n <div className=\"px-4 py-3\">\n <div className=\"flex items-center gap-2 mb-2\">\n <div className=\"w-3 h-3 rounded-full bg-blue-500\" />\n <span className=\"font-semibold text-sm text-blue-700 dark:text-blue-400\">\n {data.generatorName}\n </span>\n <PreviewToggle nodeId={id} color=\"text-blue-500 dark:text-blue-400\" />\n </div>\n {isAI && (\n <div className=\"text-[10px] text-pink-500 dark:text-pink-400 mb-1\">\n ↑ Connect text node for dynamic prompt\n </div>\n )}\n {acceptsReferences && (\n <div className=\"text-[10px] text-violet-500 dark:text-violet-400 mb-1\">\n ← Connect reference images\n </div>\n )}\n <div className=\"text-xs text-gray-500 dark:text-zinc-400\">\n {Object.entries(data.params)\n .filter(([, value]) => typeof value !== \"object\" || value === null)\n .slice(0, 2)\n .map(([key, value]) => (\n <div key={key} className=\"truncate\">\n {key}: {String(value).slice(0, 20)}\n </div>\n ))}\n </div>\n </div>\n <Handle type=\"source\" position={Position.Right} className=\"w-3 h-3 !bg-blue-500\" />\n </div>\n );\n});\n\n// Transform Node (have both input and output)\n// AI transforms also have an optional text input at the top\n// AI transforms that accept references have a references input at the bottom\nexport const TransformNode = memo(function TransformNode({\n id,\n data,\n selected,\n}: NodeProps<TransformNodeData>) {\n const preview = useWorkflowStore((s) => s.execution.previews[id]);\n const nodeStatus = useWorkflowStore((s) => s.execution.nodeStatus[id]);\n const previewVisible = useWorkflowStore((s) => s.previewVisible[id] !== false);\n\n const executionClass = getExecutionClass(nodeStatus);\n const borderClass = executionClass || (selected ? \"border-teal-500\" : \"border-teal-200\");\n\n // AI transforms get a purple accent to indicate AI-powered\n const isAI = data.isAI;\n // Check if this transform accepts reference images\n const acceptsReferences = data.acceptsReferenceImages;\n\n return (\n <div\n className={`rounded-lg border-2 bg-white dark:bg-zinc-800 shadow-md min-w-[180px] overflow-hidden ${borderClass}`}\n >\n {/* Text input handle for AI transforms (optional - for dynamic prompts) */}\n {isAI && (\n <Handle\n type=\"target\"\n position={Position.Top}\n id=\"text\"\n className=\"w-3 h-3 !bg-pink-500\"\n title=\"Text input (optional prompt from text/vision node)\"\n />\n )}\n {/* Image input handle */}\n <Handle type=\"target\" position={Position.Left} id=\"image\" className=\"w-3 h-3 !bg-teal-500\" />\n {/* Reference images input handle (for AI transforms that accept additional references) */}\n {acceptsReferences && (\n <Handle\n type=\"target\"\n position={Position.Bottom}\n id=\"references\"\n className=\"w-3 h-3 !bg-violet-500\"\n title={`Reference images (up to ${data.maxReferenceImages || 13})`}\n />\n )}\n {preview && previewVisible && (\n <div className=\"bg-gray-100 dark:bg-zinc-900 border-b border-gray-200 dark:border-zinc-700\">\n <img src={preview} alt=\"Preview\" className=\"w-full h-24 object-contain\" />\n </div>\n )}\n <div className=\"px-4 py-3\">\n <div className=\"flex items-center gap-2 mb-2\">\n {isAI ? (\n <svg className=\"w-3 h-3 text-purple-500\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path d=\"M13 7H7v6h6V7z\" />\n <path\n fillRule=\"evenodd\"\n d=\"M7 2a1 1 0 012 0v1h2V2a1 1 0 112 0v1h2a2 2 0 012 2v2h1a1 1 0 110 2h-1v2h1a1 1 0 110 2h-1v2a2 2 0 01-2 2h-2v1a1 1 0 11-2 0v-1H9v1a1 1 0 11-2 0v-1H5a2 2 0 01-2-2v-2H2a1 1 0 110-2h1V9H2a1 1 0 010-2h1V5a2 2 0 012-2h2V2zM5 5h10v10H5V5z\"\n clipRule=\"evenodd\"\n />\n </svg>\n ) : (\n <div className=\"w-3 h-3 rounded-full bg-teal-500\" />\n )}\n <span\n className={`font-semibold text-sm ${isAI ? \"text-purple-700 dark:text-purple-400\" : \"text-teal-700 dark:text-teal-400\"}`}\n >\n {data.operation}\n </span>\n <PreviewToggle\n nodeId={id}\n color={\n isAI ? \"text-purple-500 dark:text-purple-400\" : \"text-teal-500 dark:text-teal-400\"\n }\n />\n </div>\n {isAI && (\n <div className=\"text-[10px] text-pink-500 dark:text-pink-400 mb-1\">\n ↑ Connect text node for dynamic prompt\n </div>\n )}\n {acceptsReferences && (\n <div className=\"text-[10px] text-violet-500 dark:text-violet-400 mb-1\">\n ↓ Connect reference images\n </div>\n )}\n <div className=\"text-xs text-gray-500 dark:text-zinc-400\">\n {Object.entries(data.params)\n .filter(([, value]) => typeof value !== \"object\" || value === null)\n .slice(0, 2)\n .map(([key, value]) => (\n <div key={key} className=\"truncate\">\n {key}: {String(value).slice(0, 20)}\n </div>\n ))}\n </div>\n </div>\n <Handle type=\"source\" position={Position.Right} className=\"w-3 h-3 !bg-teal-500\" />\n </div>\n );\n});\n\n// Save Node (sink nodes - have input only)\nexport const SaveNode = memo(function SaveNode({ id, data, selected }: NodeProps<SaveNodeData>) {\n const nodeStatus = useWorkflowStore((s) => s.execution.nodeStatus[id]);\n\n const executionClass = getExecutionClass(nodeStatus);\n const borderClass = executionClass || (selected ? \"border-green-500\" : \"border-green-200\");\n\n return (\n <div\n className={`px-4 py-3 rounded-lg border-2 bg-white dark:bg-zinc-800 shadow-md min-w-[180px] ${borderClass}`}\n >\n <Handle type=\"target\" position={Position.Left} className=\"w-3 h-3 !bg-green-500\" />\n <div className=\"flex items-center gap-2 mb-2\">\n <div className=\"w-3 h-3 rounded-full bg-green-500\" />\n <span className=\"font-semibold text-sm text-green-700 dark:text-green-400\">Save</span>\n </div>\n <div className=\"text-xs text-gray-500 dark:text-zinc-400 truncate\">{data.destination}</div>\n </div>\n );\n});\n\n// Input Node (source nodes with uploaded images - have output only)\nexport const InputNode = memo(function InputNode({ id, data, selected }: NodeProps<InputNodeData>) {\n const preview = useWorkflowStore((s) => s.execution.previews[id]);\n const nodeStatus = useWorkflowStore((s) => s.execution.nodeStatus[id]);\n const previewVisible = useWorkflowStore((s) => s.previewVisible[id] !== false);\n const updateNodeData = useWorkflowStore((s) => s.updateNodeData);\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const executionClass = getExecutionClass(nodeStatus);\n const borderClass = executionClass || (selected ? \"border-amber-500\" : \"border-amber-200\");\n\n // Handle file selection\n const handleFileSelect = useCallback(\n async (file: File) => {\n try {\n const result = await uploadImage(file);\n updateNodeData(id, {\n uploadId: result.id,\n filename: result.filename,\n mime: result.mime,\n });\n } catch (error) {\n console.error(\"Upload failed:\", error);\n }\n },\n [id, updateNodeData]\n );\n\n // Handle drag and drop\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n const file = e.dataTransfer.files[0];\n if (file && file.type.startsWith(\"image/\")) {\n handleFileSelect(file);\n }\n },\n [handleFileSelect]\n );\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n // Handle file input change\n const handleInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (file) {\n handleFileSelect(file);\n }\n },\n [handleFileSelect]\n );\n\n // Get preview URL - either execution preview or static upload URL\n const previewUrl = preview || (data.uploadId ? getUploadBlobUrl(data.uploadId) : null);\n\n return (\n <div\n className={`rounded-lg border-2 bg-white dark:bg-zinc-800 shadow-md min-w-[180px] overflow-hidden ${borderClass}`}\n onDrop={handleDrop}\n onDragOver={handleDragOver}\n >\n {previewUrl && previewVisible ? (\n <div className=\"bg-gray-100 dark:bg-zinc-900 border-b border-gray-200 dark:border-zinc-700\">\n <img src={previewUrl} alt=\"Uploaded\" className=\"w-full h-24 object-contain\" />\n </div>\n ) : !previewUrl ? (\n <div\n className=\"bg-amber-50 dark:bg-amber-900/30 border-b border-amber-100 dark:border-amber-800 h-24 flex items-center justify-center cursor-pointer hover:bg-amber-100 dark:hover:bg-amber-900/50 transition-colors\"\n onClick={() => fileInputRef.current?.click()}\n >\n <div className=\"text-center text-amber-600 dark:text-amber-400\">\n <div className=\"text-2xl mb-1\">+</div>\n <div className=\"text-xs\">Drop image or click</div>\n </div>\n </div>\n ) : null}\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n className=\"hidden\"\n onChange={handleInputChange}\n />\n <div className=\"px-4 py-3\">\n <div className=\"flex items-center gap-2 mb-2\">\n <div className=\"w-3 h-3 rounded-full bg-amber-500\" />\n <span className=\"font-semibold text-sm text-amber-700 dark:text-amber-400\">Input</span>\n <PreviewToggle nodeId={id} color=\"text-amber-500 dark:text-amber-400\" />\n </div>\n <div className=\"text-xs text-gray-500 dark:text-zinc-400 truncate\">\n {data.filename || \"No image selected\"}\n </div>\n </div>\n <Handle type=\"source\" position={Position.Right} className=\"w-3 h-3 !bg-amber-500\" />\n </div>\n );\n});\n\n// Vision Node (AI image analysis - has input and output)\n// Supports multiple output handles when outputSchema is defined\nexport const VisionNode = memo(function VisionNode({\n id,\n data,\n selected,\n}: NodeProps<VisionNodeData>) {\n const nodeStatus = useWorkflowStore((s) => s.execution.nodeStatus[id]);\n const dataOutput = useWorkflowStore((s) => s.execution.dataOutputs?.[id]);\n const openOutputInspector = useWorkflowStore((s) => s.openOutputInspector);\n\n const executionClass = getExecutionClass(nodeStatus);\n const borderClass = executionClass || (selected ? \"border-cyan-500\" : \"border-cyan-200\");\n\n // Get output schema properties for multi-output handles\n const outputProperties = data.outputSchema?.properties\n ? Object.entries(data.outputSchema.properties)\n : [];\n const hasMultiOutput = outputProperties.length > 0;\n\n return (\n <div\n className={`rounded-lg border-2 bg-white dark:bg-zinc-800 shadow-md min-w-[180px] overflow-hidden ${borderClass}`}\n >\n <Handle type=\"target\" position={Position.Left} className=\"w-3 h-3 !bg-cyan-500\" />\n {dataOutput && (\n <div className=\"bg-cyan-50 dark:bg-cyan-900/30 border-b border-cyan-100 dark:border-cyan-800 p-2 max-h-24 overflow-auto\">\n <pre className=\"text-xs text-cyan-800 dark:text-cyan-200 whitespace-pre-wrap\">\n {dataOutput.content?.slice(0, 200)}\n {(dataOutput.content?.length || 0) > 200 && \"...\"}\n </pre>\n {dataOutput.content && dataOutput.content.length > 100 && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n openOutputInspector(id);\n }}\n className=\"mt-1 text-xs text-cyan-600 dark:text-cyan-400 hover:text-cyan-800 dark:hover:text-cyan-300 hover:underline\"\n >\n View Full Output\n </button>\n )}\n </div>\n )}\n <div className=\"px-4 py-3\">\n <div className=\"flex items-center gap-2 mb-2\">\n <svg className=\"w-3 h-3 text-cyan-500\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path d=\"M10 12a2 2 0 100-4 2 2 0 000 4z\" />\n <path\n fillRule=\"evenodd\"\n d=\"M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z\"\n clipRule=\"evenodd\"\n />\n </svg>\n <span className=\"font-semibold text-sm text-cyan-700 dark:text-cyan-400\">\n {data.providerLabel || data.providerName}\n </span>\n </div>\n <div className=\"text-xs text-gray-500 dark:text-zinc-400\">\n {data.params.prompt ? (\n <div className=\"truncate\">{String(data.params.prompt).slice(0, 30)}...</div>\n ) : null}\n </div>\n {/* Show output schema info if defined */}\n {hasMultiOutput && (\n <div className=\"mt-2 pt-2 border-t border-cyan-200 dark:border-cyan-800\">\n <div className=\"text-[10px] text-cyan-500 dark:text-cyan-400 font-medium mb-1\">\n Outputs:\n </div>\n {outputProperties.map(([key]) => (\n <div\n key={key}\n className=\"text-[10px] text-gray-500 dark:text-zinc-400 flex items-center gap-1\"\n >\n <span className=\"w-1.5 h-1.5 rounded-full bg-cyan-400\"></span>\n {key}\n </div>\n ))}\n </div>\n )}\n </div>\n {/* Multi-output handles: one for each schema property */}\n {hasMultiOutput ? (\n <>\n {/* Full output handle (backward compat) */}\n <Handle\n type=\"source\"\n position={Position.Right}\n id=\"output\"\n className=\"w-3 h-3 !bg-cyan-500\"\n style={{ top: \"50%\" }}\n title=\"Full JSON output\"\n />\n {/* Individual property handles */}\n {outputProperties.map(([key, prop], index) => (\n <Handle\n key={key}\n type=\"source\"\n position={Position.Right}\n id={`output.${key}`}\n className=\"w-2.5 h-2.5 !bg-cyan-400\"\n style={{\n top: `${70 + index * 14}%`,\n }}\n title={`${key}: ${prop.description || prop.type}`}\n />\n ))}\n </>\n ) : (\n <Handle type=\"source\" position={Position.Right} className=\"w-3 h-3 !bg-cyan-500\" />\n )}\n </div>\n );\n});\n\n// Text Node (AI text generation - has optional input and output)\n// Supports multiple output handles when outputSchema is defined\nexport const TextNode = memo(function TextNode({ id, data, selected }: NodeProps<TextNodeData>) {\n const nodeStatus = useWorkflowStore((s) => s.execution.nodeStatus[id]);\n const dataOutput = useWorkflowStore((s) => s.execution.dataOutputs?.[id]);\n const openOutputInspector = useWorkflowStore((s) => s.openOutputInspector);\n\n const executionClass = getExecutionClass(nodeStatus);\n const borderClass = executionClass || (selected ? \"border-pink-500\" : \"border-pink-200\");\n\n // Get output schema properties for multi-output handles\n const outputProperties = data.outputSchema?.properties\n ? Object.entries(data.outputSchema.properties)\n : [];\n const hasMultiOutput = outputProperties.length > 0;\n\n return (\n <div\n className={`rounded-lg border-2 bg-white dark:bg-zinc-800 shadow-md min-w-[180px] overflow-hidden ${borderClass}`}\n >\n <Handle type=\"target\" position={Position.Left} className=\"w-3 h-3 !bg-pink-500\" />\n {dataOutput && (\n <div className=\"bg-pink-50 dark:bg-pink-900/30 border-b border-pink-100 dark:border-pink-800 p-2 max-h-24 overflow-auto\">\n <pre className=\"text-xs text-pink-800 dark:text-pink-200 whitespace-pre-wrap\">\n {dataOutput.content?.slice(0, 200)}\n {(dataOutput.content?.length || 0) > 200 && \"...\"}\n </pre>\n {dataOutput.content && dataOutput.content.length > 100 && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n openOutputInspector(id);\n }}\n className=\"mt-1 text-xs text-pink-600 dark:text-pink-400 hover:text-pink-800 dark:hover:text-pink-300 hover:underline\"\n >\n View Full Output\n </button>\n )}\n </div>\n )}\n <div className=\"px-4 py-3\">\n <div className=\"flex items-center gap-2 mb-2\">\n <svg className=\"w-3 h-3 text-pink-500\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path\n fillRule=\"evenodd\"\n d=\"M18 13V5a2 2 0 00-2-2H4a2 2 0 00-2 2v8a2 2 0 002 2h3l3 3 3-3h3a2 2 0 002-2zM5 7a1 1 0 011-1h8a1 1 0 110 2H6a1 1 0 01-1-1zm1 3a1 1 0 100 2h3a1 1 0 100-2H6z\"\n clipRule=\"evenodd\"\n />\n </svg>\n <span className=\"font-semibold text-sm text-pink-700 dark:text-pink-400\">\n {data.providerLabel || data.providerName}\n </span>\n </div>\n <div className=\"text-xs text-gray-500 dark:text-zinc-400\">\n {data.params.prompt ? (\n <div className=\"truncate\">{String(data.params.prompt).slice(0, 30)}...</div>\n ) : null}\n </div>\n {/* Show output schema info if defined */}\n {hasMultiOutput && (\n <div className=\"mt-2 pt-2 border-t border-pink-200 dark:border-pink-800\">\n <div className=\"text-[10px] text-pink-500 dark:text-pink-400 font-medium mb-1\">\n Outputs:\n </div>\n {outputProperties.map(([key]) => (\n <div\n key={key}\n className=\"text-[10px] text-gray-500 dark:text-zinc-400 flex items-center gap-1\"\n >\n <span className=\"w-1.5 h-1.5 rounded-full bg-pink-400\"></span>\n {key}\n </div>\n ))}\n </div>\n )}\n </div>\n {/* Multi-output handles: one for each schema property */}\n {hasMultiOutput ? (\n <>\n {/* Full output handle (backward compat) */}\n <Handle\n type=\"source\"\n position={Position.Right}\n id=\"output\"\n className=\"w-3 h-3 !bg-pink-500\"\n style={{ top: \"50%\" }}\n title=\"Full JSON output\"\n />\n {/* Individual property handles */}\n {outputProperties.map(([key, prop], index) => (\n <Handle\n key={key}\n type=\"source\"\n position={Position.Right}\n id={`output.${key}`}\n className=\"w-2.5 h-2.5 !bg-pink-400\"\n style={{\n top: `${70 + index * 14}%`,\n }}\n title={`${key}: ${prop.description || prop.type}`}\n />\n ))}\n </>\n ) : (\n <Handle type=\"source\" position={Position.Right} className=\"w-3 h-3 !bg-pink-500\" />\n )}\n </div>\n );\n});\n\nexport const nodeTypes = {\n generator: GeneratorNode,\n transform: TransformNode,\n save: SaveNode,\n input: InputNode,\n vision: VisionNode,\n text: TextNode,\n};\n","import { useCallback, useMemo } from \"react\";\nimport ReactFlow, {\n Background,\n Controls,\n MiniMap,\n MarkerType,\n type Connection,\n type NodeMouseHandler,\n type OnNodesChange,\n type OnEdgesChange,\n type DefaultEdgeOptions,\n applyNodeChanges,\n applyEdgeChanges,\n} from \"reactflow\";\nimport \"reactflow/dist/style.css\";\nimport \"./reactflow-dark.css\";\nimport type { GeneratorNodeData } from \"@teamflojo/floimg-studio-shared\";\nimport { useWorkflowStore } from \"../stores/workflowStore\";\nimport { nodeTypes } from \"./nodeTypes\";\n\n// Default edge styling with arrows to show direction\nconst defaultEdgeOptions: DefaultEdgeOptions = {\n type: \"smoothstep\",\n animated: false,\n markerEnd: {\n type: MarkerType.ArrowClosed,\n color: \"#64748b\",\n width: 20,\n height: 20,\n },\n style: {\n stroke: \"#64748b\",\n strokeWidth: 2,\n },\n // Make edges easier to select\n interactionWidth: 20,\n};\n\nexport function WorkflowEditor() {\n const nodes = useWorkflowStore((s) => s.nodes);\n const edges = useWorkflowStore((s) => s.edges);\n const setNodes = useWorkflowStore((s) => s.setNodes);\n const setEdges = useWorkflowStore((s) => s.setEdges);\n const addEdge = useWorkflowStore((s) => s.addEdge);\n const setSelectedNode = useWorkflowStore((s) => s.setSelectedNode);\n\n // Memoize nodeTypes to prevent React Flow warning during HMR\n // The nodeTypes object is defined outside, but HMR can cause module re-evaluation\n const memoizedNodeTypes = useMemo(() => nodeTypes, []);\n\n // Validate connections based on node types\n const isValidConnection = useCallback(\n (connection: Connection) => {\n const { source, target, targetHandle } = connection;\n if (!source || !target) return false;\n\n const sourceNode = nodes.find((n) => n.id === source);\n const targetNode = nodes.find((n) => n.id === target);\n\n if (!sourceNode || !targetNode) return false;\n\n // Rule 1: Cannot connect FROM a save node (no output)\n if (sourceNode.type === \"save\") return false;\n\n // Rule 2: Cannot connect TO a generator UNLESS it has specific input handles\n // AI generators have \"text\" (for prompts) and \"references\" (for reference images) handles\n if (targetNode.type === \"generator\") {\n const data = targetNode.data as GeneratorNodeData;\n // Allow connections to text handle if it's an AI generator\n if (targetHandle === \"text\" && data.isAI) return true;\n // Allow connections to references handle if it accepts reference images\n if (targetHandle === \"references\" && data.acceptsReferenceImages) return true;\n // Block all other connections to generators\n return false;\n }\n\n // Rule 3: Cannot connect TO an input node (no input port)\n if (targetNode.type === \"input\") return false;\n\n // Rule 4: No self-connections\n if (source === target) return false;\n\n // Note: We allow replacing existing connections - handled in onConnect\n return true;\n },\n [nodes]\n );\n\n const onNodesChange: OnNodesChange = useCallback(\n (changes) => {\n setNodes(applyNodeChanges(changes, nodes));\n },\n [nodes, setNodes]\n );\n\n const onEdgesChange: OnEdgesChange = useCallback(\n (changes) => {\n setEdges(applyEdgeChanges(changes, edges));\n },\n [edges, setEdges]\n );\n\n const onConnect = useCallback(\n (connection: Connection) => {\n // \"references\" handles accept multiple connections (for reference images)\n // All other handles (text, image, default) are single-connection and auto-replace\n const isMultiConnectionHandle = connection.targetHandle === \"references\";\n\n if (!isMultiConnectionHandle) {\n // Remove any existing connection to the same target handle before adding new one\n // Handle edge creation inconsistencies from AI generation or YAML import\n const edgesToRemove = edges.filter((e) => {\n if (e.target !== connection.target) return false;\n\n // Exact handle match (including both being null/undefined)\n const existingHandle = e.targetHandle || null;\n const newHandle = connection.targetHandle || null;\n if (existingHandle === newHandle) return true;\n\n // For \"text\" or \"image\" handle connections, also remove edges with no targetHandle\n // These are the primary single-input handles that should auto-replace\n if (\n (connection.targetHandle === \"text\" || connection.targetHandle === \"image\") &&\n !e.targetHandle\n ) {\n return true;\n }\n\n // If connecting to default handle (no targetHandle), remove edges to \"image\" handle\n // since that's the main input for transforms\n if (!connection.targetHandle && e.targetHandle === \"image\") {\n return true;\n }\n\n return false;\n });\n\n if (edgesToRemove.length > 0) {\n const removeIds = new Set(edgesToRemove.map((e) => e.id));\n setEdges(edges.filter((e) => !removeIds.has(e.id)));\n }\n }\n addEdge(connection);\n },\n [addEdge, edges, setEdges]\n );\n\n const onNodeClick: NodeMouseHandler = useCallback(\n (_event, node) => {\n setSelectedNode(node.id);\n },\n [setSelectedNode]\n );\n\n const onPaneClick = useCallback(() => {\n setSelectedNode(null);\n }, [setSelectedNode]);\n\n return (\n <div className=\"h-full w-full\">\n <ReactFlow\n nodes={nodes}\n edges={edges}\n onNodesChange={onNodesChange}\n onEdgesChange={onEdgesChange}\n onConnect={onConnect}\n onNodeClick={onNodeClick}\n onPaneClick={onPaneClick}\n nodeTypes={memoizedNodeTypes}\n defaultEdgeOptions={defaultEdgeOptions}\n isValidConnection={isValidConnection}\n nodesDraggable={true}\n nodesConnectable={true}\n elementsSelectable={true}\n edgesFocusable={true}\n deleteKeyCode={[\"Backspace\", \"Delete\"]}\n proOptions={{ hideAttribution: true }}\n fitView\n snapToGrid\n snapGrid={[15, 15]}\n >\n <Background />\n <Controls />\n <MiniMap nodeStrokeWidth={3} zoomable pannable />\n </ReactFlow>\n </div>\n );\n}\n","import { useState, useEffect } from \"react\";\nimport { listUploads, deleteUpload, getUploadBlobUrl, type UploadInfo } from \"../api/client\";\n\ninterface UploadGalleryProps {\n onSelect?: (upload: UploadInfo) => void;\n}\n\nexport function UploadGallery({ onSelect }: UploadGalleryProps) {\n const [uploads, setUploads] = useState<UploadInfo[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n const fetchUploads = async () => {\n try {\n setLoading(true);\n const data = await listUploads();\n setUploads(data);\n setError(null);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to load uploads\");\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n fetchUploads();\n }, []);\n\n const handleDelete = async (id: string, e: React.MouseEvent) => {\n e.stopPropagation();\n if (!confirm(\"Delete this upload?\")) return;\n\n try {\n await deleteUpload(id);\n setUploads((prev) => prev.filter((u) => u.id !== id));\n } catch (err) {\n console.error(\"Failed to delete:\", err);\n }\n };\n\n const formatSize = (bytes: number) => {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n };\n\n if (loading) {\n return (\n <div className=\"p-4 text-center text-gray-500 dark:text-zinc-400\">Loading uploads...</div>\n );\n }\n\n if (error) {\n return (\n <div className=\"p-4 text-center text-red-500 dark:text-red-400\">\n {error}\n <button\n onClick={fetchUploads}\n className=\"ml-2 text-teal-500 dark:text-teal-400 hover:underline\"\n >\n Retry\n </button>\n </div>\n );\n }\n\n if (uploads.length === 0) {\n return (\n <div className=\"p-4 text-center text-gray-500 dark:text-zinc-400\">\n No uploads yet. Drag an image onto an Input node to upload.\n </div>\n );\n }\n\n return (\n <div className=\"p-2\">\n <div className=\"grid grid-cols-2 gap-2\">\n {uploads.map((upload) => (\n <div\n key={upload.id}\n className=\"relative group rounded border border-gray-200 dark:border-zinc-700 overflow-hidden cursor-pointer hover:border-amber-400 dark:hover:border-amber-500 transition-colors\"\n onClick={() => onSelect?.(upload)}\n >\n <img\n src={getUploadBlobUrl(upload.id)}\n alt={upload.filename}\n className=\"w-full h-20 object-cover\"\n />\n <div className=\"absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center\">\n <button\n onClick={(e) => handleDelete(upload.id, e)}\n className=\"p-1 bg-red-500 rounded text-white text-xs hover:bg-red-600\"\n >\n Delete\n </button>\n </div>\n <div className=\"p-1 text-xs truncate bg-white dark:bg-zinc-800 text-gray-800 dark:text-zinc-200\">\n {upload.filename}\n </div>\n <div className=\"px-1 pb-1 text-xs text-gray-400 dark:text-zinc-500 bg-white dark:bg-zinc-800\">\n {formatSize(upload.size)}\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport type { NodeDefinition } from \"@teamflojo/floimg-studio-shared\";\nimport { getGenerators, getTransforms, getTextProviders, getVisionProviders } from \"../api/client\";\nimport { useWorkflowStore } from \"../stores/workflowStore\";\nimport { UploadGallery } from \"./UploadGallery\";\n\nexport function NodePalette() {\n const setGenerators = useWorkflowStore((s) => s.setGenerators);\n const setTransforms = useWorkflowStore((s) => s.setTransforms);\n const setTextProviders = useWorkflowStore((s) => s.setTextProviders);\n const setVisionProviders = useWorkflowStore((s) => s.setVisionProviders);\n const generators = useWorkflowStore((s) => s.generators);\n const transforms = useWorkflowStore((s) => s.transforms);\n const textProviders = useWorkflowStore((s) => s.textProviders);\n const visionProviders = useWorkflowStore((s) => s.visionProviders);\n const addNode = useWorkflowStore((s) => s.addNode);\n const [showUploads, setShowUploads] = useState(false);\n\n // Fetch node definitions\n const { data: fetchedGenerators } = useQuery({\n queryKey: [\"generators\"],\n queryFn: getGenerators,\n });\n\n const { data: fetchedTransforms } = useQuery({\n queryKey: [\"transforms\"],\n queryFn: getTransforms,\n });\n\n const { data: fetchedTextProviders } = useQuery({\n queryKey: [\"textProviders\"],\n queryFn: getTextProviders,\n });\n\n const { data: fetchedVisionProviders } = useQuery({\n queryKey: [\"visionProviders\"],\n queryFn: getVisionProviders,\n });\n\n useEffect(() => {\n if (fetchedGenerators) setGenerators(fetchedGenerators);\n }, [fetchedGenerators, setGenerators]);\n\n useEffect(() => {\n if (fetchedTransforms) setTransforms(fetchedTransforms);\n }, [fetchedTransforms, setTransforms]);\n\n useEffect(() => {\n if (fetchedTextProviders) setTextProviders(fetchedTextProviders);\n }, [fetchedTextProviders, setTextProviders]);\n\n useEffect(() => {\n if (fetchedVisionProviders) setVisionProviders(fetchedVisionProviders);\n }, [fetchedVisionProviders, setVisionProviders]);\n\n const handleDragStart = (e: React.DragEvent, definition: NodeDefinition) => {\n e.dataTransfer.setData(\"application/json\", JSON.stringify(definition));\n e.dataTransfer.effectAllowed = \"move\";\n };\n\n const handleDoubleClick = (definition: NodeDefinition) => {\n // Add node at center of canvas\n addNode(definition, { x: 250, y: 150 + Math.random() * 100 });\n };\n\n // Input node definition (special case - for uploaded images)\n const inputDefinition: NodeDefinition = {\n id: \"input:upload\",\n type: \"input\",\n name: \"upload\",\n label: \"Upload Image\",\n description: \"Use an uploaded image\",\n category: \"Input\",\n params: {\n type: \"object\",\n properties: {},\n },\n };\n\n // Save node definition (special case)\n const saveDefinition: NodeDefinition = {\n id: \"save:filesystem\",\n type: \"save\",\n name: \"save\",\n label: \"Save\",\n description: \"Save image to file\",\n category: \"Output\",\n params: {\n type: \"object\",\n properties: {\n destination: {\n type: \"string\",\n title: \"Destination\",\n default: \"./output/image.png\",\n },\n provider: {\n type: \"string\",\n default: \"filesystem\",\n },\n },\n },\n };\n\n // Group generators by category\n const generatorsByCategory = generators.reduce(\n (acc, g) => {\n const cat = g.category || \"Other\";\n if (!acc[cat]) acc[cat] = [];\n acc[cat].push(g);\n return acc;\n },\n {} as Record<string, NodeDefinition[]>\n );\n\n // Group transforms by category\n const transformsByCategory = transforms.reduce(\n (acc, t) => {\n const cat = t.category || \"Other\";\n if (!acc[cat]) acc[cat] = [];\n acc[cat].push(t);\n return acc;\n },\n {} as Record<string, NodeDefinition[]>\n );\n\n return (\n <div className=\"w-64 bg-gray-50 dark:bg-zinc-800 border-r border-gray-200 dark:border-zinc-700 overflow-y-auto\">\n <div className=\"p-4\">\n <h2 className=\"text-lg font-semibold text-gray-800 dark:text-white mb-4\">Nodes</h2>\n\n {/* Input */}\n <div className=\"mb-6\">\n <div className=\"flex items-center justify-between mb-2\">\n <h3 className=\"text-sm font-medium text-amber-600 dark:text-amber-400 uppercase tracking-wide\">\n Input\n </h3>\n <button\n onClick={() => setShowUploads(!showUploads)}\n className=\"text-xs text-amber-600 dark:text-amber-400 hover:text-amber-700 dark:hover:text-amber-300\"\n >\n {showUploads ? \"Hide\" : \"Browse\"} Uploads\n </button>\n </div>\n <div\n draggable\n onDragStart={(e) => handleDragStart(e, inputDefinition)}\n onDoubleClick={() => handleDoubleClick(inputDefinition)}\n className=\"px-3 py-2 bg-amber-50 dark:bg-amber-900/30 border border-amber-200 dark:border-amber-700 rounded cursor-grab active:cursor-grabbing hover:bg-amber-100 dark:hover:bg-amber-900/50 transition-colors\"\n >\n <div className=\"text-sm font-medium text-amber-700 dark:text-amber-300\">\n Upload Image\n </div>\n <div className=\"text-xs text-gray-500 dark:text-zinc-400\">Start with your image</div>\n </div>\n {showUploads && (\n <div className=\"mt-2 border border-amber-200 dark:border-amber-700 rounded bg-white dark:bg-zinc-900 max-h-64 overflow-y-auto\">\n <UploadGallery />\n </div>\n )}\n </div>\n\n {/* Generators */}\n <div className=\"mb-6\">\n <h3 className=\"text-sm font-medium text-blue-600 dark:text-blue-400 uppercase tracking-wide mb-2\">\n Generators\n </h3>\n {Object.entries(generatorsByCategory).map(([category, nodes]) => (\n <div key={category} className=\"mb-3\">\n <div className=\"text-xs text-gray-500 dark:text-zinc-400 mb-1\">{category}</div>\n {nodes.map((def) => (\n <div\n key={def.id}\n draggable\n onDragStart={(e) => handleDragStart(e, def)}\n onDoubleClick={() => handleDoubleClick(def)}\n className=\"px-3 py-2 bg-blue-50 dark:bg-blue-900/30 border border-blue-200 dark:border-blue-700 rounded mb-1 cursor-grab active:cursor-grabbing hover:bg-blue-100 dark:hover:bg-blue-900/50 transition-colors\"\n >\n <div className=\"text-sm font-medium text-blue-700 dark:text-blue-300\">\n {def.label}\n </div>\n {def.description && (\n <div className=\"text-xs text-gray-500 dark:text-zinc-400 truncate\">\n {def.description}\n </div>\n )}\n </div>\n ))}\n </div>\n ))}\n </div>\n\n {/* Transforms */}\n <div className=\"mb-6\">\n <h3 className=\"text-sm font-medium text-teal-600 dark:text-teal-400 uppercase tracking-wide mb-2\">\n Transforms\n </h3>\n {Object.entries(transformsByCategory).map(([category, nodes]) => (\n <div key={category} className=\"mb-3\">\n <div className=\"text-xs text-gray-500 dark:text-zinc-400 mb-1\">{category}</div>\n {nodes.map((def) => (\n <div\n key={def.id}\n draggable\n onDragStart={(e) => handleDragStart(e, def)}\n onDoubleClick={() => handleDoubleClick(def)}\n className=\"px-3 py-2 bg-teal-50 dark:bg-teal-900/30 border border-teal-200 dark:border-teal-700 rounded mb-1 cursor-grab active:cursor-grabbing hover:bg-teal-100 dark:hover:bg-teal-900/50 transition-colors\"\n >\n <div className=\"text-sm font-medium text-teal-700 dark:text-teal-300\">\n {def.label}\n </div>\n {def.description && (\n <div className=\"text-xs text-gray-500 dark:text-zinc-400 truncate\">\n {def.description}\n </div>\n )}\n </div>\n ))}\n </div>\n ))}\n </div>\n\n {/* AI Text */}\n {textProviders.length > 0 && (\n <div className=\"mb-6\">\n <h3 className=\"text-sm font-medium text-pink-600 dark:text-pink-400 uppercase tracking-wide mb-2\">\n AI Text\n </h3>\n {textProviders.map((def) => (\n <div\n key={def.id}\n draggable\n onDragStart={(e) => handleDragStart(e, def)}\n onDoubleClick={() => handleDoubleClick(def)}\n className=\"px-3 py-2 bg-pink-50 dark:bg-pink-900/30 border border-pink-200 dark:border-pink-700 rounded mb-1 cursor-grab active:cursor-grabbing hover:bg-pink-100 dark:hover:bg-pink-900/50 transition-colors\"\n >\n <div className=\"text-sm font-medium text-pink-700 dark:text-pink-300\">\n {def.label}\n </div>\n {def.description && (\n <div className=\"text-xs text-gray-500 dark:text-zinc-400 truncate\">\n {def.description}\n </div>\n )}\n </div>\n ))}\n </div>\n )}\n\n {/* AI Vision */}\n {visionProviders.length > 0 && (\n <div className=\"mb-6\">\n <h3 className=\"text-sm font-medium text-cyan-600 dark:text-cyan-400 uppercase tracking-wide mb-2\">\n AI Vision\n </h3>\n {visionProviders.map((def) => (\n <div\n key={def.id}\n draggable\n onDragStart={(e) => handleDragStart(e, def)}\n onDoubleClick={() => handleDoubleClick(def)}\n className=\"px-3 py-2 bg-cyan-50 dark:bg-cyan-900/30 border border-cyan-200 dark:border-cyan-700 rounded mb-1 cursor-grab active:cursor-grabbing hover:bg-cyan-100 dark:hover:bg-cyan-900/50 transition-colors\"\n >\n <div className=\"text-sm font-medium text-cyan-700 dark:text-cyan-300\">\n {def.label}\n </div>\n {def.description && (\n <div className=\"text-xs text-gray-500 dark:text-zinc-400 truncate\">\n {def.description}\n </div>\n )}\n </div>\n ))}\n </div>\n )}\n\n {/* Output */}\n <div className=\"mb-6\">\n <h3 className=\"text-sm font-medium text-green-600 dark:text-green-400 uppercase tracking-wide mb-2\">\n Output\n </h3>\n <div\n draggable\n onDragStart={(e) => handleDragStart(e, saveDefinition)}\n onDoubleClick={() => handleDoubleClick(saveDefinition)}\n className=\"px-3 py-2 bg-green-50 dark:bg-green-900/30 border border-green-200 dark:border-green-700 rounded cursor-grab active:cursor-grabbing hover:bg-green-100 dark:hover:bg-green-900/50 transition-colors\"\n >\n <div className=\"text-sm font-medium text-green-700 dark:text-green-300\">Save</div>\n <div className=\"text-xs text-gray-500 dark:text-zinc-400\">Save to file</div>\n </div>\n </div>\n </div>\n </div>\n );\n}\n","import { useState } from \"react\";\nimport type {\n GeneratorNodeData,\n TransformNodeData,\n SaveNodeData,\n TextNodeData,\n VisionNodeData,\n ParamField,\n OutputSchema,\n OutputProperty,\n} from \"@teamflojo/floimg-studio-shared\";\nimport { useWorkflowStore } from \"../stores/workflowStore\";\n\nexport function NodeInspector() {\n const selectedNodeId = useWorkflowStore((s) => s.selectedNodeId);\n const nodes = useWorkflowStore((s) => s.nodes);\n const generators = useWorkflowStore((s) => s.generators);\n const transforms = useWorkflowStore((s) => s.transforms);\n const textProviders = useWorkflowStore((s) => s.textProviders);\n const visionProviders = useWorkflowStore((s) => s.visionProviders);\n const updateNodeData = useWorkflowStore((s) => s.updateNodeData);\n const deleteNode = useWorkflowStore((s) => s.deleteNode);\n\n const selectedNode = nodes.find((n) => n.id === selectedNodeId);\n\n if (!selectedNode) {\n return (\n <div className=\"w-80 bg-gray-50 dark:bg-zinc-800 border-l border-gray-200 dark:border-zinc-700 p-4\">\n <div className=\"text-gray-500 dark:text-zinc-400 text-sm\">\n Select a node to edit its properties\n </div>\n </div>\n );\n }\n\n // Get schema for the selected node\n let schema: Record<string, ParamField> | undefined;\n let nodeLabel = \"\";\n\n if (selectedNode.type === \"generator\") {\n const data = selectedNode.data as GeneratorNodeData;\n const def = generators.find((g) => g.name === data.generatorName);\n schema = def?.params?.properties;\n nodeLabel = def?.label || data.generatorName;\n } else if (selectedNode.type === \"transform\") {\n const data = selectedNode.data as TransformNodeData;\n const def = transforms.find((t) => t.name === data.operation);\n schema = def?.params?.properties;\n nodeLabel = def?.label || data.operation;\n } else if (selectedNode.type === \"save\") {\n const data = selectedNode.data as SaveNodeData;\n const isCloudSave = data.provider === \"floimg-cloud\";\n\n nodeLabel = isCloudSave ? \"Save to FloImg Cloud\" : \"Save\";\n schema = {\n destination: {\n type: \"string\",\n title: isCloudSave ? \"Filename\" : \"Destination\",\n description: isCloudSave ? \"Filename for cloud storage\" : \"File path to save the image\",\n },\n };\n } else if (selectedNode.type === \"text\") {\n const data = selectedNode.data as TextNodeData;\n const def = textProviders.find((t) => t.name === data.providerName);\n schema = def?.params?.properties;\n nodeLabel = def?.label || data.providerName;\n } else if (selectedNode.type === \"vision\") {\n const data = selectedNode.data as VisionNodeData;\n const def = visionProviders.find((v) => v.name === data.providerName);\n schema = def?.params?.properties;\n nodeLabel = def?.label || data.providerName;\n }\n\n const handleParamChange = (key: string, value: unknown) => {\n if (selectedNode.type === \"generator\") {\n const data = selectedNode.data as GeneratorNodeData;\n updateNodeData(selectedNode.id, {\n params: { ...data.params, [key]: value },\n });\n } else if (selectedNode.type === \"transform\") {\n const data = selectedNode.data as TransformNodeData;\n updateNodeData(selectedNode.id, {\n params: { ...data.params, [key]: value },\n });\n } else if (selectedNode.type === \"save\") {\n updateNodeData(selectedNode.id, { [key]: value });\n } else if (selectedNode.type === \"text\") {\n const data = selectedNode.data as TextNodeData;\n updateNodeData(selectedNode.id, {\n params: { ...data.params, [key]: value },\n });\n } else if (selectedNode.type === \"vision\") {\n const data = selectedNode.data as VisionNodeData;\n updateNodeData(selectedNode.id, {\n params: { ...data.params, [key]: value },\n });\n }\n };\n\n const getParamValue = (key: string): unknown => {\n if (selectedNode.type === \"generator\") {\n return (selectedNode.data as GeneratorNodeData).params[key];\n } else if (selectedNode.type === \"transform\") {\n return (selectedNode.data as TransformNodeData).params[key];\n } else if (selectedNode.type === \"save\") {\n return (selectedNode.data as SaveNodeData)[key as keyof SaveNodeData];\n } else if (selectedNode.type === \"text\") {\n return (selectedNode.data as TextNodeData).params[key];\n } else if (selectedNode.type === \"vision\") {\n return (selectedNode.data as VisionNodeData).params[key];\n }\n return undefined;\n };\n\n // Determine which fields should be visible based on current parameter values\n const isFieldVisible = (key: string, _field: ParamField): boolean => {\n // For shapes generator, apply conditional visibility\n if (\n selectedNode.type === \"generator\" &&\n (selectedNode.data as GeneratorNodeData).generatorName === \"shapes\"\n ) {\n const shapeType = getParamValue(\"shapeType\") || \"rectangle\";\n const fillType = getParamValue(\"fillType\") || \"solid\";\n\n // Shape-specific parameters\n if (key === \"sides\") return shapeType === \"polygon\";\n if (key === \"points\" || key === \"innerRadius\") return shapeType === \"star\";\n if (key === \"cornerRadius\") return shapeType === \"rectangle\";\n\n // Fill-specific parameters\n if (key === \"fillColor\") return fillType === \"solid\";\n if (\n key === \"gradientType\" ||\n key === \"gradientColor1\" ||\n key === \"gradientColor2\" ||\n key === \"gradientAngle\"\n ) {\n return fillType === \"gradient\";\n }\n if (\n key === \"patternType\" ||\n key === \"patternColor\" ||\n key === \"patternBackground\" ||\n key === \"patternScale\"\n ) {\n return fillType === \"pattern\";\n }\n }\n\n return true;\n };\n\n return (\n <div className=\"w-80 bg-gray-50 dark:bg-zinc-800 border-l border-gray-200 dark:border-zinc-700 overflow-y-auto\">\n <div className=\"p-4\">\n <div className=\"flex items-center justify-between mb-4\">\n <h2 className=\"text-lg font-semibold text-gray-800 dark:text-white\">{nodeLabel}</h2>\n <button\n onClick={() => deleteNode(selectedNode.id)}\n className=\"text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 text-sm\"\n >\n Delete\n </button>\n </div>\n\n <div className=\"space-y-4\">\n {schema &&\n Object.entries(schema)\n .filter(([key, field]) => isFieldVisible(key, field))\n .map(([key, field]) => (\n <FieldEditor\n key={key}\n name={key}\n field={field}\n value={getParamValue(key)}\n onChange={(value) => handleParamChange(key, value)}\n />\n ))}\n </div>\n\n {/* Output Schema Editor for text/vision nodes */}\n {(selectedNode.type === \"text\" || selectedNode.type === \"vision\") && (\n <OutputSchemaEditor\n nodeId={selectedNode.id}\n outputSchema={(selectedNode.data as TextNodeData | VisionNodeData).outputSchema}\n updateNodeData={updateNodeData}\n />\n )}\n </div>\n </div>\n );\n}\n\ninterface FieldEditorProps {\n name: string;\n field: ParamField;\n value: unknown;\n onChange: (value: unknown) => void;\n}\n\nfunction FieldEditor({ name, field, value, onChange }: FieldEditorProps) {\n const label = field.title || name;\n const inputClasses =\n \"w-full px-3 py-2 border border-gray-300 dark:border-zinc-600 rounded-md shadow-sm focus:ring-teal-500 focus:border-teal-500 bg-white dark:bg-zinc-900 text-gray-900 dark:text-zinc-100\";\n\n // Enum -> select dropdown\n if (field.enum) {\n return (\n <div>\n <label className=\"block text-sm font-medium text-gray-700 dark:text-zinc-300 mb-1\">\n {label}\n </label>\n <select\n value={String(value || \"\")}\n onChange={(e) => onChange(e.target.value)}\n className={inputClasses}\n >\n <option value=\"\">Select...</option>\n {field.enum.map((opt) => (\n <option key={opt} value={opt}>\n {opt}\n </option>\n ))}\n </select>\n {field.description && (\n <p className=\"mt-1 text-xs text-gray-500 dark:text-zinc-400\">{field.description}</p>\n )}\n </div>\n );\n }\n\n // Number input\n if (field.type === \"number\") {\n return (\n <div>\n <label className=\"block text-sm font-medium text-gray-700 dark:text-zinc-300 mb-1\">\n {label}\n </label>\n <input\n type=\"number\"\n value={value !== undefined ? Number(value) : \"\"}\n onChange={(e) => onChange(Number(e.target.value))}\n min={field.minimum}\n max={field.maximum}\n className={inputClasses}\n />\n {field.description && (\n <p className=\"mt-1 text-xs text-gray-500 dark:text-zinc-400\">{field.description}</p>\n )}\n </div>\n );\n }\n\n // Boolean -> checkbox\n if (field.type === \"boolean\") {\n return (\n <div className=\"flex items-center gap-2\">\n <input\n type=\"checkbox\"\n checked={Boolean(value)}\n onChange={(e) => onChange(e.target.checked)}\n className=\"h-4 w-4 text-teal-600 focus:ring-teal-500 border-gray-300 dark:border-zinc-600 rounded bg-white dark:bg-zinc-900\"\n />\n <label className=\"text-sm font-medium text-gray-700 dark:text-zinc-300\">{label}</label>\n </div>\n );\n }\n\n // Color picker for color-related fields\n if (name.toLowerCase().includes(\"color\") && typeof value === \"string\" && value.startsWith(\"#\")) {\n return (\n <div>\n <label className=\"block text-sm font-medium text-gray-700 dark:text-zinc-300 mb-1\">\n {label}\n </label>\n <div className=\"flex gap-2\">\n <input\n type=\"color\"\n value={String(value || \"#000000\")}\n onChange={(e) => onChange(e.target.value)}\n className=\"h-10 w-14 p-1 border border-gray-300 dark:border-zinc-600 rounded\"\n />\n <input\n type=\"text\"\n value={String(value || \"\")}\n onChange={(e) => onChange(e.target.value)}\n className={inputClasses + \" flex-1\"}\n />\n </div>\n </div>\n );\n }\n\n // Default: text input (also for objects as JSON)\n if (field.type === \"object\") {\n return (\n <div>\n <label className=\"block text-sm font-medium text-gray-700 dark:text-zinc-300 mb-1\">\n {label}\n </label>\n <textarea\n value={value ? JSON.stringify(value, null, 2) : \"{}\"}\n onChange={(e) => {\n try {\n onChange(JSON.parse(e.target.value));\n } catch {\n // Invalid JSON, ignore\n }\n }}\n rows={4}\n className={inputClasses + \" font-mono text-xs\"}\n />\n {field.description && (\n <p className=\"mt-1 text-xs text-gray-500 dark:text-zinc-400\">{field.description}</p>\n )}\n </div>\n );\n }\n\n // String input (default)\n return (\n <div>\n <label className=\"block text-sm font-medium text-gray-700 dark:text-zinc-300 mb-1\">\n {label}\n </label>\n {name === \"prompt\" || name === \"code\" || name === \"text\" ? (\n <textarea\n value={String(value || \"\")}\n onChange={(e) => onChange(e.target.value)}\n rows={3}\n className={inputClasses}\n />\n ) : (\n <input\n type=\"text\"\n value={String(value || \"\")}\n onChange={(e) => onChange(e.target.value)}\n className={inputClasses}\n />\n )}\n {field.description && (\n <p className=\"mt-1 text-xs text-gray-500 dark:text-zinc-400\">{field.description}</p>\n )}\n </div>\n );\n}\n\n// ============================================================================\n// Output Schema Editor for text/vision nodes\n// ============================================================================\n\ninterface OutputSchemaEditorProps {\n nodeId: string;\n outputSchema?: OutputSchema;\n updateNodeData: (id: string, data: Partial<TextNodeData | VisionNodeData>) => void;\n}\n\nfunction OutputSchemaEditor({ nodeId, outputSchema, updateNodeData }: OutputSchemaEditorProps) {\n const [newPropertyName, setNewPropertyName] = useState(\"\");\n\n const properties = outputSchema?.properties || {};\n const propertyEntries = Object.entries(properties);\n\n const handleAddProperty = () => {\n if (!newPropertyName.trim()) return;\n\n const newSchema: OutputSchema = {\n type: \"object\",\n properties: {\n ...properties,\n [newPropertyName.trim()]: { type: \"string\" },\n },\n };\n\n updateNodeData(nodeId, { outputSchema: newSchema });\n setNewPropertyName(\"\");\n };\n\n const handleRemoveProperty = (key: string) => {\n const newProperties = { ...properties };\n delete newProperties[key];\n\n if (Object.keys(newProperties).length === 0) {\n updateNodeData(nodeId, { outputSchema: undefined });\n } else {\n updateNodeData(nodeId, {\n outputSchema: { type: \"object\", properties: newProperties },\n });\n }\n };\n\n const handleTypeChange = (key: string, type: OutputProperty[\"type\"]) => {\n updateNodeData(nodeId, {\n outputSchema: {\n type: \"object\",\n properties: {\n ...properties,\n [key]: { ...properties[key], type },\n },\n },\n });\n };\n\n const handleDescriptionChange = (key: string, description: string) => {\n updateNodeData(nodeId, {\n outputSchema: {\n type: \"object\",\n properties: {\n ...properties,\n [key]: { ...properties[key], description: description || undefined },\n },\n },\n });\n };\n\n return (\n <div className=\"mt-6 pt-4 border-t border-gray-200 dark:border-zinc-700\">\n <div className=\"flex items-center justify-between mb-3\">\n <h3 className=\"text-sm font-medium text-gray-700 dark:text-zinc-300\">Output Schema</h3>\n <span className=\"text-xs text-gray-500 dark:text-zinc-500\">\n {propertyEntries.length > 0\n ? `${propertyEntries.length} output${propertyEntries.length > 1 ? \"s\" : \"\"}`\n : \"No outputs defined\"}\n </span>\n </div>\n\n <p className=\"text-xs text-gray-500 dark:text-zinc-400 mb-3\">\n Define output properties to enable connecting individual JSON fields to other nodes.\n </p>\n\n {/* Existing properties */}\n {propertyEntries.length > 0 && (\n <div className=\"space-y-2 mb-3\">\n {propertyEntries.map(([key, prop]) => (\n <div\n key={key}\n className=\"flex items-center gap-2 p-2 bg-pink-50 dark:bg-pink-900/20 rounded border border-pink-200 dark:border-pink-800\"\n >\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium text-pink-700 dark:text-pink-300 truncate\">\n {key}\n </span>\n <select\n value={prop.type}\n onChange={(e) =>\n handleTypeChange(key, e.target.value as OutputProperty[\"type\"])\n }\n className=\"text-xs px-1.5 py-0.5 rounded border border-pink-300 dark:border-pink-700 bg-white dark:bg-zinc-800 text-gray-700 dark:text-zinc-300\"\n >\n <option value=\"string\">string</option>\n <option value=\"number\">number</option>\n <option value=\"boolean\">boolean</option>\n <option value=\"object\">object</option>\n <option value=\"array\">array</option>\n </select>\n </div>\n <input\n type=\"text\"\n value={prop.description || \"\"}\n onChange={(e) => handleDescriptionChange(key, e.target.value)}\n placeholder=\"Description (optional)\"\n className=\"mt-1 w-full text-xs px-2 py-1 rounded border border-pink-200 dark:border-pink-700 bg-white dark:bg-zinc-800 text-gray-600 dark:text-zinc-400 placeholder-gray-400 dark:placeholder-zinc-500\"\n />\n </div>\n <button\n onClick={() => handleRemoveProperty(key)}\n className=\"text-pink-500 hover:text-pink-700 dark:text-pink-400 dark:hover:text-pink-300 p-1\"\n title=\"Remove property\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n </div>\n ))}\n </div>\n )}\n\n {/* Add new property */}\n <div className=\"flex gap-2\">\n <input\n type=\"text\"\n value={newPropertyName}\n onChange={(e) => setNewPropertyName(e.target.value)}\n onKeyDown={(e) => e.key === \"Enter\" && handleAddProperty()}\n placeholder=\"Property name...\"\n className=\"flex-1 px-2 py-1.5 text-sm border border-gray-300 dark:border-zinc-600 rounded bg-white dark:bg-zinc-900 text-gray-900 dark:text-zinc-100 placeholder-gray-400 dark:placeholder-zinc-500\"\n />\n <button\n onClick={handleAddProperty}\n disabled={!newPropertyName.trim()}\n className=\"px-3 py-1.5 text-sm font-medium text-white bg-pink-500 rounded hover:bg-pink-600 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n Add\n </button>\n </div>\n\n {/* Hint about usage */}\n {propertyEntries.length > 0 && (\n <p className=\"mt-3 text-xs text-gray-500 dark:text-zinc-500\">\n Connect from the small pink handles on the right of the node to route individual\n properties.\n </p>\n )}\n </div>\n );\n}\n","import type { Node, Edge } from \"reactflow\";\nimport type {\n GeneratorNodeData,\n TransformNodeData,\n SaveNodeData,\n InputNodeData,\n VisionNodeData,\n TextNodeData,\n} from \"@teamflojo/floimg-studio-shared\";\n\ntype NodeData =\n | GeneratorNodeData\n | TransformNodeData\n | SaveNodeData\n | InputNodeData\n | VisionNodeData\n | TextNodeData;\n\n/**\n * Topologically sort nodes based on edges (dependencies)\n * Returns nodes in execution order\n */\nfunction topologicalSort(nodes: Node<NodeData>[], edges: Edge[]): Node<NodeData>[] {\n const nodeMap = new Map(nodes.map((n) => [n.id, n]));\n const inDegree = new Map<string, number>();\n const adjacency = new Map<string, string[]>();\n\n // Initialize\n for (const node of nodes) {\n inDegree.set(node.id, 0);\n adjacency.set(node.id, []);\n }\n\n // Build graph\n for (const edge of edges) {\n const targets = adjacency.get(edge.source) || [];\n targets.push(edge.target);\n adjacency.set(edge.source, targets);\n inDegree.set(edge.target, (inDegree.get(edge.target) || 0) + 1);\n }\n\n // Find nodes with no incoming edges (sources)\n const queue: string[] = [];\n for (const [id, degree] of inDegree) {\n if (degree === 0) {\n queue.push(id);\n }\n }\n\n // Process in order\n const sorted: Node<NodeData>[] = [];\n while (queue.length > 0) {\n const id = queue.shift()!;\n const node = nodeMap.get(id);\n if (node) {\n sorted.push(node);\n }\n\n const neighbors = adjacency.get(id) || [];\n for (const neighbor of neighbors) {\n const newDegree = (inDegree.get(neighbor) || 1) - 1;\n inDegree.set(neighbor, newDegree);\n if (newDegree === 0) {\n queue.push(neighbor);\n }\n }\n }\n\n return sorted;\n}\n\n/**\n * Get the variable name for a node\n */\nfunction getNodeVarName(node: Node<NodeData>): string {\n const type = node.type || \"node\";\n const suffix = node.id.replace(/[^a-zA-Z0-9]/g, \"_\");\n return `${type}_${suffix}`;\n}\n\n/**\n * Stringify a value for code generation\n */\nfunction stringify(value: unknown): string {\n if (typeof value === \"string\") {\n // Escape special characters and use template literal if multiline\n if (value.includes(\"\\n\")) {\n return \"`\" + value.replace(/`/g, \"\\\\`\").replace(/\\$/g, \"\\\\$\") + \"`\";\n }\n return JSON.stringify(value);\n }\n return JSON.stringify(value, null, 2);\n}\n\n/**\n * Generate JavaScript code for a single node\n */\nfunction generateNodeCode(\n node: Node<NodeData>,\n edges: Edge[],\n nodeVarNames: Map<string, string>\n): { code: string; imports: string[] } {\n const varName = nodeVarNames.get(node.id)!;\n const imports: string[] = [];\n\n // Find input node (source of edge pointing to this node)\n const inputEdge = edges.find((e) => e.target === node.id);\n const inputVarName = inputEdge ? nodeVarNames.get(inputEdge.source) : null;\n\n switch (node.type) {\n case \"generator\": {\n const data = node.data as GeneratorNodeData;\n imports.push(data.generatorName);\n\n const params = data.params || {};\n const paramStr = Object.entries(params)\n .filter(([, v]) => v !== undefined && v !== \"\")\n .map(([k, v]) => ` ${k}: ${stringify(v)}`)\n .join(\",\\n\");\n\n return {\n code: `// Generate image using ${data.generatorName}\nconst ${varName} = await ${data.generatorName}({\n${paramStr}\n});`,\n imports,\n };\n }\n\n case \"input\": {\n return {\n code: `// Load input image\nconst ${varName} = await flo.loadImage(\"./input.png\");`,\n imports: [],\n };\n }\n\n case \"transform\": {\n const data = node.data as TransformNodeData;\n const params = data.params || {};\n const paramStr = Object.entries(params)\n .filter(([, v]) => v !== undefined && v !== \"\")\n .map(([k, v]) => `${k}: ${stringify(v)}`)\n .join(\", \");\n\n const input = inputVarName || \"image\";\n return {\n code: `// Apply ${data.operation} transform\nconst ${varName} = await flo.transform(${input}, \"${data.operation}\"${paramStr ? `, { ${paramStr} }` : \"\"});`,\n imports: [],\n };\n }\n\n case \"vision\": {\n const data = node.data as VisionNodeData;\n imports.push(data.providerName);\n\n const params = data.params || {};\n const input = inputVarName || \"image\";\n const paramStr = Object.entries(params)\n .filter(([, v]) => v !== undefined && v !== \"\")\n .map(([k, v]) => ` ${k}: ${stringify(v)}`)\n .join(\",\\n\");\n\n return {\n code: `// Analyze image with ${data.providerName}\nconst ${varName} = await ${data.providerName}.analyze(${input}, {\n${paramStr}\n});`,\n imports,\n };\n }\n\n case \"text\": {\n const data = node.data as TextNodeData;\n imports.push(data.providerName);\n\n const params = data.params || {};\n const paramStr = Object.entries(params)\n .filter(([, v]) => v !== undefined && v !== \"\")\n .map(([k, v]) => ` ${k}: ${stringify(v)}`)\n .join(\",\\n\");\n\n return {\n code: `// Generate text with ${data.providerName}\nconst ${varName} = await ${data.providerName}.generate({\n${paramStr}\n});`,\n imports,\n };\n }\n\n case \"save\": {\n const data = node.data as SaveNodeData;\n const input = inputVarName || \"result\";\n return {\n code: `// Save result\nawait flo.save(${input}, ${stringify(data.destination)});`,\n imports: [],\n };\n }\n\n default:\n return {\n code: `// Unknown node type: ${node.type}`,\n imports: [],\n };\n }\n}\n\n/**\n * Generate JavaScript code from workflow nodes and edges\n */\nexport function generateJavaScript(nodes: Node<NodeData>[], edges: Edge[]): string {\n if (nodes.length === 0) {\n return `// Empty workflow\n// Add nodes to your canvas to generate code`;\n }\n\n // Sort nodes topologically\n const sortedNodes = topologicalSort(nodes, edges);\n\n // Generate variable names\n const nodeVarNames = new Map<string, string>();\n for (const node of sortedNodes) {\n nodeVarNames.set(node.id, getNodeVarName(node));\n }\n\n // Generate code for each node\n const allImports = new Set<string>();\n const codeBlocks: string[] = [];\n\n for (const node of sortedNodes) {\n const { code, imports } = generateNodeCode(node, edges, nodeVarNames);\n codeBlocks.push(code);\n for (const imp of imports) {\n allImports.add(imp);\n }\n }\n\n // Build final code\n const importLines: string[] = [];\n if (allImports.size > 0) {\n importLines.push(`import { ${Array.from(allImports).join(\", \")} } from \"@teamflojo/floimg\";`);\n }\n importLines.push(`import * as flo from \"@teamflojo/floimg\";`);\n\n const header = `/**\n * FloImg Workflow\n * Generated by FloImg Studio\n * https://floimg.com\n */\n\n`;\n\n const mainCode = `\nasync function runWorkflow() {\n${codeBlocks\n .map((block) =>\n block\n .split(\"\\n\")\n .map((line) => \" \" + line)\n .join(\"\\n\")\n )\n .join(\"\\n\\n\")}\n}\n\n// Run the workflow\nrunWorkflow().catch(console.error);\n`;\n\n return header + importLines.join(\"\\n\") + \"\\n\" + mainCode;\n}\n","import { useState, useCallback, type DragEvent } from \"react\";\nimport { importYaml, validateYaml } from \"../api/client\";\nimport type { StudioNode, StudioEdge } from \"@teamflojo/floimg-studio-shared\";\n\ninterface ImportModalProps {\n isOpen: boolean;\n onClose: () => void;\n onImport: (nodes: StudioNode[], edges: StudioEdge[], name?: string) => void;\n}\n\ninterface ValidationError {\n message: string;\n line?: number;\n column?: number;\n}\n\nexport function ImportModal({ isOpen, onClose, onImport }: ImportModalProps) {\n const [yamlContent, setYamlContent] = useState(\"\");\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<ValidationError | null>(null);\n const [isDragging, setIsDragging] = useState(false);\n\n const handleImport = useCallback(async () => {\n if (!yamlContent.trim()) {\n setError({ message: \"Please enter or paste YAML content\" });\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const result = await importYaml(yamlContent);\n\n if (result.success) {\n onImport(result.nodes, result.edges, result.name);\n setYamlContent(\"\");\n onClose();\n } else {\n setError({\n message: result.error || \"Import failed\",\n line: result.line,\n column: result.column,\n });\n }\n } catch (err) {\n setError({ message: err instanceof Error ? err.message : \"Import failed\" });\n } finally {\n setIsLoading(false);\n }\n }, [yamlContent, onImport, onClose]);\n\n const handleValidate = useCallback(async () => {\n if (!yamlContent.trim()) {\n setError({ message: \"Please enter or paste YAML content\" });\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const result = await validateYaml(yamlContent);\n\n if (result.valid) {\n setError(null);\n // Show success briefly\n setError({ message: \"Valid YAML!\" });\n setTimeout(() => setError(null), 2000);\n } else if (result.errors.length > 0) {\n setError(result.errors[0]);\n }\n } catch (err) {\n setError({ message: err instanceof Error ? err.message : \"Validation failed\" });\n } finally {\n setIsLoading(false);\n }\n }, [yamlContent]);\n\n const handleFileUpload = useCallback(async (file: File) => {\n if (!file.name.endsWith(\".yaml\") && !file.name.endsWith(\".yml\")) {\n setError({ message: \"Please upload a .yaml or .yml file\" });\n return;\n }\n\n try {\n const text = await file.text();\n setYamlContent(text);\n setError(null);\n } catch {\n setError({ message: \"Failed to read file\" });\n }\n }, []);\n\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault();\n setIsDragging(true);\n }, []);\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault();\n setIsDragging(false);\n }, []);\n\n const handleDrop = useCallback(\n (e: DragEvent) => {\n e.preventDefault();\n setIsDragging(false);\n\n const file = e.dataTransfer.files[0];\n if (file) {\n handleFileUpload(file);\n }\n },\n [handleFileUpload]\n );\n\n const handleFileInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (file) {\n handleFileUpload(file);\n }\n },\n [handleFileUpload]\n );\n\n if (!isOpen) return null;\n\n return (\n <div className=\"fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50\">\n <div className=\"bg-white dark:bg-zinc-800 rounded-lg shadow-xl max-w-2xl w-full mx-4 max-h-[80vh] flex flex-col\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-gray-200 dark:border-zinc-700\">\n <h3 className=\"text-lg font-semibold text-gray-900 dark:text-white\">Import Workflow</h3>\n <button\n onClick={onClose}\n className=\"text-gray-500 dark:text-zinc-400 hover:text-gray-700 dark:hover:text-zinc-200\"\n >\n <svg className=\"h-6 w-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n </div>\n\n {/* Content */}\n <div className=\"p-4 flex-1 overflow-auto\">\n <p className=\"text-sm text-gray-600 dark:text-zinc-400 mb-4\">\n Paste YAML content or drag and drop a .yaml file to import a workflow.\n </p>\n\n {/* File drop zone */}\n <div\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n className={`border-2 border-dashed rounded-lg p-4 mb-4 text-center transition-colors ${\n isDragging\n ? \"border-teal-500 bg-teal-50 dark:bg-teal-900/20\"\n : \"border-gray-300 dark:border-zinc-600\"\n }`}\n >\n <input\n type=\"file\"\n accept=\".yaml,.yml\"\n onChange={handleFileInputChange}\n className=\"hidden\"\n id=\"yaml-file-input\"\n />\n <label\n htmlFor=\"yaml-file-input\"\n className=\"cursor-pointer text-sm text-gray-600 dark:text-zinc-400\"\n >\n <svg\n className=\"h-8 w-8 mx-auto mb-2 text-gray-400 dark:text-zinc-500\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12\"\n />\n </svg>\n <span className=\"text-teal-600 dark:text-teal-400 hover:underline\">\n Click to upload\n </span>{\" \"}\n or drag and drop\n <br />\n <span className=\"text-xs\">.yaml or .yml files</span>\n </label>\n </div>\n\n {/* YAML textarea */}\n <textarea\n value={yamlContent}\n onChange={(e) => {\n setYamlContent(e.target.value);\n setError(null);\n }}\n placeholder={`name: My Workflow\nsteps:\n - kind: generate\n generator: quickchart\n params:\n type: bar\n data:\n labels: [Q1, Q2, Q3, Q4]\n datasets:\n - label: Revenue\n data: [12, 19, 8, 15]\n out: v0\n\n - kind: transform\n op: resize\n in: v0\n params:\n width: 800\n out: v1`}\n className=\"w-full h-64 p-3 font-mono text-sm bg-gray-100 dark:bg-zinc-900 border border-gray-300 dark:border-zinc-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-teal-500 text-gray-800 dark:text-zinc-200\"\n />\n\n {/* Error/Success message */}\n {error && (\n <div\n className={`mt-4 p-3 rounded-lg text-sm ${\n error.message === \"Valid YAML!\"\n ? \"bg-green-50 dark:bg-green-900/30 text-green-700 dark:text-green-400\"\n : \"bg-red-50 dark:bg-red-900/30 text-red-700 dark:text-red-400\"\n }`}\n >\n <span className=\"font-medium\">{error.message}</span>\n {error.line && (\n <span className=\"ml-2 text-xs\">\n (line {error.line}\n {error.column ? `, column ${error.column}` : \"\"})\n </span>\n )}\n </div>\n )}\n </div>\n\n {/* Footer */}\n <div className=\"flex justify-between items-center px-4 py-3 border-t border-gray-200 dark:border-zinc-700\">\n <span className=\"text-xs text-gray-500 dark:text-zinc-400\">\n Use with floimg CLI: floimg run workflow.yaml\n </span>\n <div className=\"flex gap-2\">\n <button\n onClick={handleValidate}\n disabled={isLoading || !yamlContent.trim()}\n className=\"px-4 py-2 text-sm font-medium text-gray-700 dark:text-zinc-200 bg-white dark:bg-zinc-700 border border-gray-300 dark:border-zinc-600 rounded-md hover:bg-gray-50 dark:hover:bg-zinc-600 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n Validate\n </button>\n <button\n onClick={handleImport}\n disabled={isLoading || !yamlContent.trim()}\n className=\"px-4 py-2 text-sm font-medium text-white bg-teal-600 rounded-md hover:bg-teal-700 disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2\"\n >\n {isLoading && (\n <svg className=\"animate-spin h-4 w-4\" viewBox=\"0 0 24 24\" fill=\"none\">\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\"\n />\n </svg>\n )}\n Import\n </button>\n </div>\n </div>\n </div>\n </div>\n );\n}\n","import { useState, useEffect, useCallback, type ReactNode } from \"react\";\nimport { useWorkflowStore } from \"../stores/workflowStore\";\nimport { useSettingsStore } from \"../stores/settingsStore\";\nimport { generateJavaScript } from \"../utils/codeGenerator\";\nimport { ImportModal } from \"./ImportModal\";\nimport type { StudioNode, StudioEdge } from \"@teamflojo/floimg-studio-shared\";\n\ntype ExportTab = \"yaml\" | \"javascript\";\n\n/**\n * Props for the Toolbar component.\n * All props are optional to maintain backward compatibility.\n */\nexport interface ToolbarProps {\n /** Slot rendered after the branding text (e.g., \"Cloud\" badge) */\n brandingSlot?: ReactNode;\n /** Slot rendered before the action buttons (e.g., usage counter) */\n beforeActionsSlot?: ReactNode;\n /** Slot rendered after all action buttons (e.g., auth/user menu) */\n afterActionsSlot?: ReactNode;\n /** Hide the \"by Flojo\" attribution link */\n hideAttribution?: boolean;\n /** Hide the \"My Workflows\" library toggle button (for wrappers providing custom workflow management) */\n hideWorkflowLibrary?: boolean;\n}\n\nexport function Toolbar({\n brandingSlot,\n beforeActionsSlot,\n afterActionsSlot,\n hideAttribution = false,\n hideWorkflowLibrary = false,\n}: ToolbarProps = {}) {\n const execution = useWorkflowStore((s) => s.execution);\n const execute = useWorkflowStore((s) => s.execute);\n const cancelExecution = useWorkflowStore((s) => s.cancelExecution);\n const exportToYaml = useWorkflowStore((s) => s.exportToYaml);\n const importFromYaml = useWorkflowStore((s) => s.importFromYaml);\n const nodes = useWorkflowStore((s) => s.nodes);\n const edges = useWorkflowStore((s) => s.edges);\n const openSettings = useSettingsStore((s) => s.openSettings);\n\n // Workflow persistence state\n const activeWorkflowName = useWorkflowStore((s) => s.activeWorkflowName);\n const hasUnsavedChanges = useWorkflowStore((s) => s.hasUnsavedChanges);\n const saveWorkflow = useWorkflowStore((s) => s.saveWorkflow);\n const toggleLibrary = useWorkflowStore((s) => s.toggleLibrary);\n const setActiveWorkflowName = useWorkflowStore((s) => s.setActiveWorkflowName);\n\n // Node operations\n const selectedNodeId = useWorkflowStore((s) => s.selectedNodeId);\n const duplicateNode = useWorkflowStore((s) => s.duplicateNode);\n\n const [showExport, setShowExport] = useState(false);\n const [showImport, setShowImport] = useState(false);\n const [exportTab, setExportTab] = useState<ExportTab>(\"yaml\");\n const [yamlContent, setYamlContent] = useState(\"\");\n const [jsContent, setJsContent] = useState(\"\");\n const [notification, setNotification] = useState<string | null>(null);\n const [isEditingName, setIsEditingName] = useState(false);\n const [editingName, setEditingName] = useState(\"\");\n\n // Listen for new workflow event\n useEffect(() => {\n const handleNewWorkflow = () => {\n setNotification(\"New workflow created\");\n setTimeout(() => setNotification(null), 2000);\n };\n window.addEventListener(\"new-workflow-created\", handleNewWorkflow);\n return () => window.removeEventListener(\"new-workflow-created\", handleNewWorkflow);\n }, []);\n\n // Handle save with Cmd+S / Ctrl+S\n const handleSave = useCallback(() => {\n if (nodes.length === 0) return;\n saveWorkflow();\n setNotification(\"Saved!\");\n setTimeout(() => setNotification(null), 2000);\n }, [nodes.length, saveWorkflow]);\n\n // Handle inline rename\n const handleStartRename = () => {\n setEditingName(activeWorkflowName);\n setIsEditingName(true);\n };\n\n const handleSaveRename = () => {\n const trimmed = editingName.trim();\n if (trimmed && trimmed !== activeWorkflowName) {\n setActiveWorkflowName(trimmed);\n }\n setIsEditingName(false);\n };\n\n // Handle duplicate with Cmd+D / Ctrl+D\n const handleDuplicate = useCallback(() => {\n if (selectedNodeId) {\n duplicateNode(selectedNodeId);\n }\n }, [selectedNodeId, duplicateNode]);\n\n // Keyboard shortcuts\n useEffect(() => {\n function handleKeyDown(e: KeyboardEvent) {\n if ((e.metaKey || e.ctrlKey) && e.key === \"s\") {\n e.preventDefault();\n handleSave();\n }\n if ((e.metaKey || e.ctrlKey) && e.key === \"d\") {\n e.preventDefault();\n handleDuplicate();\n }\n }\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [handleSave, handleDuplicate]);\n\n const handleExecute = async () => {\n await execute();\n };\n\n const handleExport = async () => {\n const yaml = await exportToYaml();\n setYamlContent(yaml);\n const js = generateJavaScript(nodes, edges);\n setJsContent(js);\n setShowExport(true);\n };\n\n const handleCopy = () => {\n const content = exportTab === \"yaml\" ? yamlContent : jsContent;\n navigator.clipboard.writeText(content);\n };\n\n const handleImport = useCallback(\n (importedNodes: StudioNode[], importedEdges: StudioEdge[], name?: string) => {\n importFromYaml(importedNodes, importedEdges, name);\n setNotification(\"Workflow imported!\");\n setTimeout(() => setNotification(null), 2000);\n },\n [importFromYaml]\n );\n\n return (\n <>\n <div className=\"h-14 bg-white dark:bg-zinc-800 border-b border-gray-200 dark:border-zinc-700 flex items-center justify-between px-4\">\n <div className=\"flex items-center gap-4\">\n {/* My Workflows button - can be hidden when custom workflow management is provided */}\n {!hideWorkflowLibrary && (\n <button\n onClick={toggleLibrary}\n className=\"p-2 text-gray-500 dark:text-zinc-400 hover:text-gray-700 dark:hover:text-zinc-200 hover:bg-gray-100 dark:hover:bg-zinc-700 rounded-md\"\n title=\"My Workflows\"\n >\n <svg className=\"h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 6h16M4 12h16M4 18h7\"\n />\n </svg>\n </button>\n )}\n\n <div className=\"flex items-baseline gap-2\">\n <h1 className=\"text-xl font-bold text-gray-800 dark:text-white\">FloImg Studio</h1>\n {brandingSlot}\n {!hideAttribution && (\n <a\n href=\"https://flojo.io\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-xs text-gray-400 dark:text-zinc-500 hover:text-gray-600 dark:hover:text-zinc-300\"\n >\n by Flojo\n </a>\n )}\n </div>\n\n {/* Workflow name and status - click to rename */}\n <div className=\"flex items-center gap-2\">\n {isEditingName ? (\n <input\n type=\"text\"\n value={editingName}\n onChange={(e) => setEditingName(e.target.value)}\n onBlur={handleSaveRename}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") handleSaveRename();\n if (e.key === \"Escape\") {\n setEditingName(activeWorkflowName);\n setIsEditingName(false);\n }\n }}\n className=\"w-48 px-2 py-1 text-sm font-medium bg-white dark:bg-zinc-900 border border-teal-500 rounded focus:outline-none focus:ring-1 focus:ring-teal-500 text-gray-900 dark:text-zinc-100\"\n autoFocus\n />\n ) : (\n <button\n onClick={handleStartRename}\n className=\"text-sm text-gray-700 dark:text-zinc-300 font-medium hover:text-gray-900 dark:hover:text-zinc-100 rounded px-2 py-1 -mx-2 hover:bg-gray-100 dark:hover:bg-zinc-700 transition-colors\"\n title=\"Click to rename\"\n >\n {activeWorkflowName}\n </button>\n )}\n {hasUnsavedChanges && (\n <span className=\"text-xs text-amber-600 dark:text-amber-400\">(unsaved)</span>\n )}\n {notification && (\n <span className=\"text-xs text-green-600 dark:text-green-400\">{notification}</span>\n )}\n </div>\n\n <span className=\"text-sm text-gray-500 dark:text-zinc-400\">\n {nodes.length} node{nodes.length !== 1 ? \"s\" : \"\"}\n </span>\n </div>\n\n <div className=\"flex items-center gap-3\">\n {beforeActionsSlot}\n <button\n onClick={openSettings}\n className=\"p-2 text-gray-500 dark:text-zinc-400 hover:text-gray-700 dark:hover:text-zinc-200 hover:bg-gray-100 dark:hover:bg-zinc-700 rounded-md\"\n title=\"AI Settings\"\n >\n <svg className=\"h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z\"\n />\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z\"\n />\n </svg>\n </button>\n\n {/* Save button */}\n <button\n onClick={handleSave}\n disabled={nodes.length === 0}\n className=\"p-2 text-gray-500 dark:text-zinc-400 hover:text-gray-700 dark:hover:text-zinc-200 hover:bg-gray-100 dark:hover:bg-zinc-700 rounded-md disabled:opacity-50 disabled:cursor-not-allowed\"\n title=\"Save Workflow (Cmd+S)\"\n >\n <svg className=\"h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4\"\n />\n </svg>\n </button>\n\n <button\n onClick={() => setShowImport(true)}\n className=\"px-4 py-2 text-sm font-medium text-gray-700 dark:text-zinc-200 bg-white dark:bg-zinc-700 border border-gray-300 dark:border-zinc-600 rounded-md hover:bg-gray-50 dark:hover:bg-zinc-600\"\n >\n Import\n </button>\n\n <button\n onClick={handleExport}\n disabled={nodes.length === 0}\n className=\"px-4 py-2 text-sm font-medium text-gray-700 dark:text-zinc-200 bg-white dark:bg-zinc-700 border border-gray-300 dark:border-zinc-600 rounded-md hover:bg-gray-50 dark:hover:bg-zinc-600 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n Export\n </button>\n\n {execution.status === \"running\" ? (\n <button\n onClick={cancelExecution}\n className=\"px-4 py-2 text-sm font-medium text-white bg-red-600 rounded-md hover:bg-red-700 flex items-center gap-2\"\n >\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n Cancel\n </button>\n ) : (\n <button\n onClick={handleExecute}\n disabled={nodes.length === 0}\n className=\"px-4 py-2 text-sm font-medium text-white bg-teal-600 rounded-md hover:bg-teal-700 disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2\"\n >\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z\"\n />\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n Execute\n </button>\n )}\n {afterActionsSlot}\n </div>\n </div>\n\n {/* Execution result banner */}\n {execution.status === \"completed\" && execution.imageIds.length > 0 && (\n <div className=\"bg-green-50 dark:bg-green-900/30 border-b border-green-200 dark:border-green-800 px-4 py-3\">\n <div className=\"flex items-center gap-4\">\n <span className=\"text-green-700 dark:text-green-400 font-medium\">\n Generated {execution.imageIds.length} image\n {execution.imageIds.length !== 1 ? \"s\" : \"\"}\n </span>\n <div className=\"flex gap-2\">\n {execution.imageUrls.slice(0, 4).map((url, idx) => (\n <a key={idx} href={url} target=\"_blank\" rel=\"noopener noreferrer\" className=\"block\">\n <img\n src={url}\n alt=\"Generated\"\n className=\"h-12 w-12 object-cover rounded border border-green-300 dark:border-green-700\"\n />\n </a>\n ))}\n </div>\n </div>\n </div>\n )}\n\n {execution.status === \"error\" && (\n <div className=\"bg-red-50 dark:bg-red-900/30 border-b border-red-200 dark:border-red-800 px-4 py-3\">\n <span className=\"text-red-700 dark:text-red-400\">Error: {execution.error}</span>\n </div>\n )}\n\n {/* Export modal with tabs */}\n {showExport && (\n <div className=\"fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50\">\n <div className=\"bg-white dark:bg-zinc-800 rounded-lg shadow-xl max-w-2xl w-full mx-4 max-h-[80vh] flex flex-col\">\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-gray-200 dark:border-zinc-700\">\n <div className=\"flex items-center gap-4\">\n <h3 className=\"text-lg font-semibold text-gray-900 dark:text-white\">\n Export Workflow\n </h3>\n {/* Tabs */}\n <div className=\"flex gap-1 bg-gray-100 dark:bg-zinc-700 rounded-lg p-1\">\n <button\n onClick={() => setExportTab(\"yaml\")}\n className={`px-3 py-1 text-sm font-medium rounded-md transition-colors ${\n exportTab === \"yaml\"\n ? \"bg-white dark:bg-zinc-600 text-gray-900 dark:text-white shadow-sm\"\n : \"text-gray-600 dark:text-zinc-400 hover:text-gray-900 dark:hover:text-white\"\n }`}\n >\n YAML\n </button>\n <button\n onClick={() => setExportTab(\"javascript\")}\n className={`px-3 py-1 text-sm font-medium rounded-md transition-colors ${\n exportTab === \"javascript\"\n ? \"bg-white dark:bg-zinc-600 text-gray-900 dark:text-white shadow-sm\"\n : \"text-gray-600 dark:text-zinc-400 hover:text-gray-900 dark:hover:text-white\"\n }`}\n >\n JavaScript\n </button>\n </div>\n </div>\n <button\n onClick={() => setShowExport(false)}\n className=\"text-gray-500 dark:text-zinc-400 hover:text-gray-700 dark:hover:text-zinc-200\"\n >\n <svg className=\"h-6 w-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n </div>\n <div className=\"p-4 overflow-auto flex-1\">\n <pre className=\"bg-gray-100 dark:bg-zinc-900 p-4 rounded text-sm font-mono whitespace-pre-wrap text-gray-800 dark:text-zinc-200\">\n {exportTab === \"yaml\" ? yamlContent : jsContent}\n </pre>\n </div>\n <div className=\"flex justify-between items-center px-4 py-3 border-t border-gray-200 dark:border-zinc-700\">\n <span className=\"text-xs text-gray-500 dark:text-zinc-400\">\n {exportTab === \"yaml\"\n ? \"Use with floimg CLI: floimg run workflow.yaml\"\n : \"Run with Node.js or Bun\"}\n </span>\n <div className=\"flex gap-2\">\n <button\n onClick={handleCopy}\n className=\"px-4 py-2 text-sm font-medium text-gray-700 dark:text-zinc-200 bg-white dark:bg-zinc-700 border border-gray-300 dark:border-zinc-600 rounded-md hover:bg-gray-50 dark:hover:bg-zinc-600\"\n >\n Copy to Clipboard\n </button>\n <button\n onClick={() => setShowExport(false)}\n className=\"px-4 py-2 text-sm font-medium text-white bg-teal-600 rounded-md hover:bg-teal-700\"\n >\n Close\n </button>\n </div>\n </div>\n </div>\n </div>\n )}\n\n {/* Import modal */}\n <ImportModal\n isOpen={showImport}\n onClose={() => setShowImport(false)}\n onImport={handleImport}\n />\n </>\n );\n}\n","import { useState } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { listImages, getImageUrl, getImageWorkflow, type ImageInfo } from \"../api/client\";\nimport { useWorkflowStore } from \"../stores/workflowStore\";\nimport type { Template } from \"@teamflojo/floimg-templates\";\n\nexport function Gallery() {\n const loadTemplate = useWorkflowStore((s) => s.loadTemplate);\n const [loadingWorkflow, setLoadingWorkflow] = useState<string | null>(null);\n\n const {\n data: images,\n isLoading,\n error,\n refetch,\n } = useQuery({\n queryKey: [\"images\"],\n queryFn: listImages,\n refetchInterval: 5000, // Auto-refresh every 5 seconds\n });\n\n const handleLoadWorkflow = async (imageId: string) => {\n setLoadingWorkflow(imageId);\n try {\n const metadata = await getImageWorkflow(imageId);\n if (metadata?.workflow) {\n // Convert to Template format for loading\n const template: Template = {\n id: `image-${imageId}`,\n name: `Workflow from ${imageId}`,\n description: \"Loaded from gallery image\",\n category: \"Utilities\",\n generator: \"unknown\",\n workflow: {\n nodes: metadata.workflow.nodes,\n edges: metadata.workflow.edges,\n },\n };\n loadTemplate(template);\n // Navigate to editor tab (parent handles this via URL or state)\n window.dispatchEvent(new CustomEvent(\"workflow-loaded\"));\n } else {\n alert(\"No workflow metadata available for this image\");\n }\n } catch (err) {\n console.error(\"Failed to load workflow:\", err);\n alert(\"Failed to load workflow\");\n } finally {\n setLoadingWorkflow(null);\n }\n };\n\n if (isLoading) {\n return (\n <div className=\"p-8 text-center text-gray-500 dark:text-zinc-400\">Loading images...</div>\n );\n }\n\n if (error) {\n return (\n <div className=\"p-8 text-center text-red-500 dark:text-red-400\">\n Error loading images: {error instanceof Error ? error.message : \"Unknown error\"}\n </div>\n );\n }\n\n if (!images || images.length === 0) {\n return (\n <div className=\"p-8 text-center text-gray-500 dark:text-zinc-400\">\n <div className=\"text-lg mb-2\">No images yet</div>\n <div className=\"text-sm\">Create a workflow and click Execute to generate images</div>\n </div>\n );\n }\n\n return (\n <div className=\"p-4 bg-gray-100 dark:bg-zinc-900 min-h-full\">\n <div className=\"flex items-center justify-between mb-4\">\n <div>\n <h2 className=\"text-lg font-semibold text-gray-800 dark:text-white\">\n Images ({images.length})\n </h2>\n <p className=\"text-xs text-gray-500 dark:text-zinc-500\">Your generated images</p>\n </div>\n <button\n onClick={() => refetch()}\n className=\"text-sm text-teal-600 dark:text-teal-400 hover:text-teal-700 dark:hover:text-violet-300\"\n >\n Refresh\n </button>\n </div>\n\n <div className=\"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4\">\n {images.map((image) => (\n <ImageCard\n key={image.id}\n image={image}\n onLoadWorkflow={() => handleLoadWorkflow(image.id)}\n isLoading={loadingWorkflow === image.id}\n />\n ))}\n </div>\n </div>\n );\n}\n\ninterface ImageCardProps {\n image: ImageInfo;\n onLoadWorkflow: () => void;\n isLoading: boolean;\n}\n\nfunction ImageCard({ image, onLoadWorkflow, isLoading }: ImageCardProps) {\n const formatDate = (timestamp: number) => {\n return new Date(timestamp).toLocaleString();\n };\n\n const formatSize = (bytes: number) => {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n };\n\n return (\n <div className=\"bg-white dark:bg-zinc-800 rounded-lg border border-gray-200 dark:border-zinc-700 overflow-hidden shadow-sm hover:shadow-md transition-shadow group\">\n <div className=\"relative\">\n <a\n href={getImageUrl(image.id)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"block aspect-square bg-gray-100 dark:bg-zinc-900\"\n >\n <img\n src={getImageUrl(image.id)}\n alt={image.filename}\n className=\"w-full h-full object-cover\"\n loading=\"lazy\"\n />\n </a>\n {/* Hover overlay with action buttons */}\n <div className=\"absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center gap-2\">\n <button\n onClick={(e) => {\n e.preventDefault();\n onLoadWorkflow();\n }}\n disabled={isLoading}\n className=\"px-3 py-1.5 bg-teal-600 text-white text-sm rounded-lg hover:bg-teal-700 disabled:opacity-50\"\n >\n {isLoading ? \"Loading...\" : \"Load Workflow\"}\n </button>\n <a\n href={getImageUrl(image.id)}\n download={image.filename}\n onClick={(e) => e.stopPropagation()}\n className=\"p-1.5 bg-zinc-700 text-white rounded-lg hover:bg-zinc-600\"\n title=\"Download image\"\n >\n <svg className=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\"\n />\n </svg>\n </a>\n </div>\n </div>\n <div className=\"p-3\">\n <div className=\"text-sm font-medium text-gray-800 dark:text-white truncate\">\n {image.filename}\n </div>\n <div className=\"text-xs text-gray-500 dark:text-zinc-400 mt-1\">\n {image.mime} • {formatSize(image.size)}\n </div>\n <div className=\"text-xs text-gray-400 dark:text-zinc-500 mt-1\">\n {formatDate(image.createdAt)}\n </div>\n </div>\n </div>\n );\n}\n","/**\n * Data Visualization Templates\n *\n * Charts, graphs, and diagrams using QuickChart and Mermaid generators.\n * All templates in this category work offline (OSS-compatible).\n */\n/**\n * Revenue Dashboard Pipeline\n * Canonical ID: revenue-chart\n *\n * Multi-step workflow: Generate chart → Resize → Add caption → WebP export\n * Demonstrates: chart generation with professional output formatting\n */\nexport const revenueChart = {\n id: \"revenue-chart\",\n name: \"Revenue Dashboard\",\n description: \"Quarterly revenue chart with caption and web-optimized export\",\n category: \"Data Viz\",\n generator: \"quickchart\",\n tags: [\"bar\", \"revenue\", \"quarterly\", \"dashboard\", \"sales\", \"pipeline\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"chart\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/revenue-chart.png\",\n },\n codeExample: `const chart = await floimg\n .generate('quickchart', {\n chart: {\n type: 'bar',\n data: {\n labels: ['Q1', 'Q2', 'Q3', 'Q4'],\n datasets: [{ label: 'Revenue ($K)', data: [120, 190, 175, 240] }]\n }\n }\n })\n .transform('resize', { width: 800, height: 500, fit: 'inside' })\n .transform('addCaption', {\n text: 'Source: Finance Dashboard',\n position: 'bottom-right',\n fontSize: 12\n })\n .transform('convert', { to: 'image/webp', quality: 90 })\n .toBlob();`,\n seo: {\n title: \"Revenue Dashboard Chart Template\",\n description: \"Generate professional quarterly revenue bar charts with caption and optimization\",\n keywords: [\"revenue chart\", \"bar chart\", \"quarterly report\", \"dashboard\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"quickchart\",\n params: {\n chart: {\n type: \"bar\",\n data: {\n labels: [\"Q1\", \"Q2\", \"Q3\", \"Q4\"],\n datasets: [\n {\n label: \"Revenue ($K)\",\n data: [120, 190, 175, 240],\n backgroundColor: [\n \"rgba(99, 102, 241, 0.8)\",\n \"rgba(139, 92, 246, 0.8)\",\n \"rgba(168, 85, 247, 0.8)\",\n \"rgba(192, 132, 252, 0.8)\",\n ],\n },\n ],\n },\n options: {\n plugins: {\n title: {\n display: true,\n text: \"Quarterly Revenue 2024\",\n },\n },\n },\n },\n width: 600,\n height: 400,\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 800,\n height: 500,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-caption\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"addCaption\",\n params: {\n text: \"Source: Finance Dashboard\",\n position: \"bottom-right\",\n fontSize: 12,\n color: \"#6B7280\",\n padding: 8,\n },\n },\n },\n {\n id: \"transform-webp\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/webp\",\n quality: 90,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-caption\" },\n { id: \"e3\", source: \"transform-caption\", target: \"transform-webp\" },\n ],\n },\n};\n/**\n * User Growth Chart for Investor Updates\n * Canonical ID: monthly-users\n *\n * Multi-step workflow: Generate chart → Resize for slides → Round corners for modern look → PNG export\n * JTBD: Create polished growth charts for investor decks and board presentations\n */\nexport const monthlyUsers = {\n id: \"monthly-users\",\n name: \"User Growth Chart\",\n description: \"Polished user growth chart ready for investor decks and presentations\",\n category: \"Data Viz\",\n generator: \"quickchart\",\n tags: [\"line\", \"growth\", \"users\", \"monthly\", \"analytics\", \"pipeline\", \"investor\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"chart\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/monthly-users.png\",\n },\n codeExample: `const chart = await floimg\n .generate('quickchart', {\n chart: {\n type: 'line',\n data: {\n labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],\n datasets: [{ label: 'Active Users', data: [1200, 1900, 3000, 5000, 6200, 8100] }]\n }\n }\n })\n .transform('resize', { width: 1200, height: 675 }) // 16:9 for slides\n .transform('roundCorners', { radius: 16 })\n .transform('convert', { to: 'image/png' })\n .toBlob();`,\n seo: {\n title: \"User Growth Chart Template\",\n description: \"Visualize monthly user growth with smooth bezier curves for investor presentations\",\n keywords: [\"user growth\", \"line chart\", \"analytics\", \"investor deck\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"quickchart\",\n params: {\n chart: {\n type: \"line\",\n data: {\n labels: [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\"],\n datasets: [\n {\n label: \"Active Users\",\n data: [1200, 1900, 3000, 5000, 6200, 8100],\n borderColor: \"rgb(99, 102, 241)\",\n backgroundColor: \"rgba(99, 102, 241, 0.1)\",\n fill: true,\n tension: 0.4,\n },\n ],\n },\n options: {\n plugins: {\n title: {\n display: true,\n text: \"User Growth 2024\",\n },\n },\n },\n },\n width: 600,\n height: 400,\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 1200,\n height: 675,\n fit: \"contain\",\n background: \"#ffffff\",\n },\n },\n },\n {\n id: \"transform-corners\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"roundCorners\",\n params: {\n radius: 16,\n },\n },\n },\n {\n id: \"transform-png\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/png\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-corners\" },\n { id: \"e3\", source: \"transform-corners\", target: \"transform-png\" },\n ],\n },\n};\n/**\n * Framework Comparison for Blog Posts\n * Canonical ID: framework-usage\n *\n * Multi-step workflow: Generate chart → Resize for blog → Add padding → WebP for fast loading\n * JTBD: Create comparison charts for technical blog posts and documentation\n */\nexport const frameworkUsage = {\n id: \"framework-usage\",\n name: \"Framework Usage Stats\",\n description: \"Blog-ready comparison chart with optimized sizing and fast web loading\",\n category: \"Data Viz\",\n generator: \"quickchart\",\n tags: [\"bar\", \"comparison\", \"stats\", \"horizontal\", \"frameworks\", \"pipeline\", \"blog\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"chart\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/framework-usage.png\",\n },\n codeExample: `const chart = await floimg\n .generate('quickchart', {\n chart: {\n type: 'horizontalBar',\n data: {\n labels: ['React', 'Vue', 'Angular', 'Svelte', 'Solid'],\n datasets: [{ label: 'Usage %', data: [42, 18, 15, 8, 4] }]\n }\n }\n })\n .transform('resize', { width: 800, height: 450 }) // Blog content width\n .transform('extend', { top: 16, bottom: 16, left: 16, right: 16, background: '#ffffff' })\n .transform('convert', { to: 'image/webp', quality: 85 })\n .toBlob();`,\n seo: {\n title: \"Framework Comparison Chart Template\",\n description: \"Generate comparison charts for technical blog posts with optimized web delivery\",\n keywords: [\"framework comparison\", \"bar chart\", \"tech blog\", \"documentation\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"quickchart\",\n params: {\n chart: {\n type: \"horizontalBar\",\n data: {\n labels: [\"React\", \"Vue\", \"Angular\", \"Svelte\", \"Solid\"],\n datasets: [\n {\n label: \"Usage %\",\n data: [42, 18, 15, 8, 4],\n backgroundColor: [\n \"rgba(97, 218, 251, 0.8)\",\n \"rgba(65, 184, 131, 0.8)\",\n \"rgba(221, 0, 49, 0.8)\",\n \"rgba(255, 62, 0, 0.8)\",\n \"rgba(68, 107, 158, 0.8)\",\n ],\n },\n ],\n },\n options: {\n plugins: {\n title: {\n display: true,\n text: \"Frontend Framework Usage 2024\",\n },\n },\n },\n },\n width: 600,\n height: 400,\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 800,\n height: 450,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-padding\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"extend\",\n params: {\n top: 16,\n bottom: 16,\n left: 16,\n right: 16,\n background: \"#ffffff\",\n },\n },\n },\n {\n id: \"transform-webp\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/webp\",\n quality: 85,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-padding\" },\n { id: \"e3\", source: \"transform-padding\", target: \"transform-webp\" },\n ],\n },\n};\n/**\n * Traffic Breakdown for Slack/Reports\n * Canonical ID: traffic-breakdown\n *\n * Multi-step workflow: Generate chart → Square format for Slack → Add date annotation → PNG\n * JTBD: Share analytics breakdowns in Slack channels and weekly reports\n */\nexport const trafficBreakdown = {\n id: \"traffic-breakdown\",\n name: \"Traffic by Device\",\n description: \"Analytics breakdown optimized for Slack sharing and weekly reports\",\n category: \"Data Viz\",\n generator: \"quickchart\",\n tags: [\"doughnut\", \"traffic\", \"analytics\", \"pie\", \"devices\", \"pipeline\", \"slack\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"chart\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/traffic-breakdown.png\",\n },\n codeExample: `const chart = await floimg\n .generate('quickchart', {\n chart: {\n type: 'doughnut',\n data: {\n labels: ['Desktop', 'Mobile', 'Tablet'],\n datasets: [{ data: [55, 35, 10] }]\n }\n }\n })\n .transform('resize', { width: 500, height: 500 }) // Square for Slack preview\n .transform('addCaption', {\n text: 'Week of Jan 1, 2026',\n position: 'bottom-center',\n fontSize: 14,\n color: '#6B7280'\n })\n .transform('convert', { to: 'image/png' })\n .toBlob();`,\n seo: {\n title: \"Traffic Breakdown Chart Template\",\n description: \"Generate analytics breakdown charts optimized for Slack sharing and reports\",\n keywords: [\"traffic analytics\", \"doughnut chart\", \"slack\", \"weekly report\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"quickchart\",\n params: {\n chart: {\n type: \"doughnut\",\n data: {\n labels: [\"Desktop\", \"Mobile\", \"Tablet\"],\n datasets: [\n {\n data: [55, 35, 10],\n backgroundColor: [\n \"rgba(99, 102, 241, 0.8)\",\n \"rgba(34, 197, 94, 0.8)\",\n \"rgba(249, 115, 22, 0.8)\",\n ],\n },\n ],\n },\n options: {\n plugins: {\n title: {\n display: true,\n text: \"Traffic by Device Type\",\n },\n },\n },\n },\n width: 400,\n height: 400,\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 500,\n height: 500,\n fit: \"contain\",\n background: \"#ffffff\",\n },\n },\n },\n {\n id: \"transform-caption\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"addCaption\",\n params: {\n text: \"Week of Jan 1, 2026\",\n position: \"bottom-center\",\n fontSize: 14,\n color: \"#6B7280\",\n padding: 12,\n },\n },\n },\n {\n id: \"transform-png\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/png\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-caption\" },\n { id: \"e3\", source: \"transform-caption\", target: \"transform-png\" },\n ],\n },\n};\n/**\n * API Documentation Sequence Diagram\n * Canonical ID: api-flow\n *\n * Multi-step workflow: Generate diagram → Resize for docs → Add padding → PNG for docs\n * JTBD: Create API flow diagrams for technical documentation and README files\n */\nexport const apiFlow = {\n id: \"api-flow\",\n name: \"API Request Flow\",\n description: \"Sequence diagram ready for API documentation and README files\",\n category: \"Data Viz\",\n generator: \"mermaid\",\n tags: [\"sequence\", \"api\", \"authentication\", \"diagram\", \"flow\", \"pipeline\", \"docs\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"diagram\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/api-flow.png\",\n },\n codeExample: `const diagram = await floimg\n .generate('mermaid', {\n code: \\`sequenceDiagram\n participant Client\n participant API\n participant Auth\n Client->>API: POST /login\n API->>Auth: Validate\n Auth-->>API: JWT token\n API-->>Client: 200 OK\\`\n })\n .transform('resize', { width: 800, fit: 'inside' })\n .transform('extend', { top: 24, bottom: 24, left: 24, right: 24, background: '#ffffff' })\n .transform('convert', { to: 'image/png' })\n .toBlob();`,\n seo: {\n title: \"API Flow Diagram Template\",\n description: \"Generate sequence diagrams for API documentation and README files\",\n keywords: [\"api diagram\", \"sequence diagram\", \"documentation\", \"readme\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"mermaid\",\n params: {\n code: `sequenceDiagram\n participant Client\n participant API\n participant Auth\n participant DB\n\n Client->>API: POST /login\n API->>Auth: Validate credentials\n Auth->>DB: Query user\n DB-->>Auth: User data\n Auth-->>API: JWT token\n API-->>Client: 200 OK + token\n\n Client->>API: GET /data (+ JWT)\n API->>Auth: Verify token\n Auth-->>API: Valid\n API->>DB: Fetch data\n DB-->>API: Data\n API-->>Client: 200 OK + data`,\n theme: \"default\",\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 800,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-padding\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"extend\",\n params: {\n top: 24,\n bottom: 24,\n left: 24,\n right: 24,\n background: \"#ffffff\",\n },\n },\n },\n {\n id: \"transform-png\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/png\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-padding\" },\n { id: \"e3\", source: \"transform-padding\", target: \"transform-png\" },\n ],\n },\n};\n/**\n * System Architecture for Technical Docs\n * Canonical ID: system-architecture\n *\n * Multi-step workflow: Generate diagram → Resize for wiki → Add padding → WebP for fast loading\n * JTBD: Create architecture diagrams for Confluence/Notion/README documentation\n */\nexport const systemArchitecture = {\n id: \"system-architecture\",\n name: \"System Architecture\",\n description: \"Architecture diagram optimized for Confluence, Notion, and technical documentation\",\n category: \"Data Viz\",\n generator: \"mermaid\",\n tags: [\n \"architecture\",\n \"microservices\",\n \"flowchart\",\n \"system\",\n \"infrastructure\",\n \"pipeline\",\n \"confluence\",\n ],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"diagram\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/system-architecture.png\",\n },\n codeExample: `const diagram = await floimg\n .generate('mermaid', {\n code: \\`flowchart TB\n subgraph Gateway\n LB[Load Balancer]\n API[API Gateway]\n end\n subgraph Services\n Auth[Auth]\n Users[Users]\n end\n LB --> API --> Auth & Users\\`\n })\n .transform('resize', { width: 1000, fit: 'inside' })\n .transform('extend', { top: 32, bottom: 32, left: 32, right: 32, background: '#ffffff' })\n .transform('convert', { to: 'image/webp', quality: 90 })\n .toBlob();`,\n seo: {\n title: \"System Architecture Diagram Template\",\n description: \"Generate architecture diagrams for Confluence, Notion, and technical documentation\",\n keywords: [\"architecture diagram\", \"microservices\", \"confluence\", \"notion\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"mermaid\",\n params: {\n code: `flowchart TB\n subgraph Client\n Web[Web App]\n Mobile[Mobile App]\n end\n\n subgraph Gateway\n LB[Load Balancer]\n API[API Gateway]\n end\n\n subgraph Services\n Auth[Auth Service]\n Users[User Service]\n Orders[Order Service]\n Notify[Notification Service]\n end\n\n subgraph Data\n PG[(PostgreSQL)]\n Redis[(Redis Cache)]\n S3[(S3 Storage)]\n end\n\n Web --> LB\n Mobile --> LB\n LB --> API\n API --> Auth\n API --> Users\n API --> Orders\n API --> Notify\n Auth --> Redis\n Users --> PG\n Orders --> PG\n Notify --> Redis`,\n theme: \"default\",\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 1000,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-padding\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"extend\",\n params: {\n top: 32,\n bottom: 32,\n left: 32,\n right: 32,\n background: \"#ffffff\",\n },\n },\n },\n {\n id: \"transform-webp\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/webp\",\n quality: 90,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-padding\" },\n { id: \"e3\", source: \"transform-padding\", target: \"transform-webp\" },\n ],\n },\n};\n/**\n * Git Workflow for Team Onboarding\n * Canonical ID: git-workflow\n *\n * Multi-step workflow: Generate diagram → Resize for wiki → Add caption → PNG for docs\n * JTBD: Create git workflow diagrams for team onboarding and CONTRIBUTING.md files\n */\nexport const gitWorkflow = {\n id: \"git-workflow\",\n name: \"Git Branch Workflow\",\n description: \"Git branching diagram for team onboarding and CONTRIBUTING.md\",\n category: \"Data Viz\",\n generator: \"mermaid\",\n tags: [\n \"git\",\n \"branching\",\n \"workflow\",\n \"development\",\n \"version-control\",\n \"pipeline\",\n \"onboarding\",\n ],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"diagram\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/git-workflow.png\",\n },\n codeExample: `const diagram = await floimg\n .generate('mermaid', {\n code: \\`gitGraph\n commit id: \"Initial\"\n branch develop\n commit id: \"Setup\"\n branch feature/auth\n commit id: \"Add login\"\n checkout develop\n merge feature/auth tag: \"v1.0.0\"\\`\n })\n .transform('resize', { width: 900, fit: 'inside' })\n .transform('addCaption', {\n text: 'Our Git Branching Strategy',\n position: 'top-center',\n fontSize: 16\n })\n .transform('convert', { to: 'image/png' })\n .toBlob();`,\n seo: {\n title: \"Git Workflow Diagram Template\",\n description: \"Generate git branching diagrams for team onboarding and CONTRIBUTING.md\",\n keywords: [\"git workflow\", \"branching strategy\", \"team onboarding\", \"contributing\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"mermaid\",\n params: {\n code: `gitGraph\n commit id: \"Initial\"\n branch develop\n checkout develop\n commit id: \"Setup\"\n branch feature/auth\n checkout feature/auth\n commit id: \"Add login\"\n commit id: \"Add signup\"\n checkout develop\n merge feature/auth\n branch feature/dashboard\n checkout feature/dashboard\n commit id: \"Add charts\"\n checkout develop\n merge feature/dashboard\n checkout main\n merge develop tag: \"v1.0.0\"\n checkout develop\n commit id: \"Post-release\"`,\n theme: \"default\",\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 900,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-caption\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"addCaption\",\n params: {\n text: \"Our Git Branching Strategy\",\n position: \"top-center\",\n fontSize: 16,\n color: \"#374151\",\n padding: 16,\n },\n },\n },\n {\n id: \"transform-png\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/png\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-caption\" },\n { id: \"e3\", source: \"transform-caption\", target: \"transform-png\" },\n ],\n },\n};\n/**\n * All data visualization templates\n */\nexport const dataVizTemplates = [\n revenueChart,\n monthlyUsers,\n frameworkUsage,\n trafficBreakdown,\n apiFlow,\n systemArchitecture,\n gitWorkflow,\n];\n//# sourceMappingURL=data-viz.js.map","/**\n * AI Workflow Templates\n *\n * Templates that use AI image generation (OpenAI DALL-E, etc.)\n * These require API keys (cloud deployment) to execute.\n */\n/**\n * AI Product Photography for E-commerce\n * Canonical ID: ai-product-shot\n *\n * Multi-step workflow: AI generate → Remove background → Resize for listing → Add watermark\n * JTBD: Create e-commerce-ready product photos with transparent backgrounds and consistent sizing\n */\nexport const aiProductShot = {\n id: \"ai-product-shot\",\n name: \"AI Product Photography\",\n description: \"Generate AI product photos with background removal and e-commerce-ready sizing\",\n category: \"AI Workflows\",\n generator: \"openai\",\n tags: [\"product\", \"ecommerce\", \"photography\", \"dall-e\", \"ai\", \"pipeline\", \"background-removal\"],\n requiresCloud: true,\n requiresAuth: true,\n usesAI: true,\n aiCreditsNeeded: 1,\n capabilities: {\n pipeline: true,\n },\n icon: \"sparkles\",\n valueProp: \"E-commerce-ready product photos in seconds\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/ai-product-shot.png\",\n },\n codeExample: `const product = await floimg\n .generate('openai', {\n prompt: 'Professional product photo of headphones on white background',\n model: 'dall-e-3',\n size: '1024x1024'\n })\n .transform('removeBackground')\n .transform('resize', { width: 800, height: 800, fit: 'contain', background: '#ffffff' })\n .transform('addCaption', { text: 'SKU-12345', position: 'bottom-right', fontSize: 12 })\n .toBlob();`,\n seo: {\n title: \"AI Product Photography Template\",\n description: \"Generate e-commerce-ready product photos with AI and background removal\",\n keywords: [\"product photography\", \"ai generation\", \"ecommerce\", \"background removal\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-ai\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"openai\",\n params: {\n prompt: \"Professional product photo of modern wireless headphones on a clean white background, studio lighting, high-end commercial photography style\",\n model: \"dall-e-3\",\n size: \"1024x1024\",\n quality: \"hd\",\n },\n },\n },\n {\n id: \"transform-bg\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"removeBackground\",\n params: {},\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 800,\n height: 800,\n fit: \"contain\",\n background: \"#ffffff\",\n },\n },\n },\n {\n id: \"transform-caption\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"addCaption\",\n params: {\n text: \"SKU-12345\",\n position: \"bottom-right\",\n fontSize: 12,\n color: \"#9CA3AF\",\n padding: 8,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-ai\", target: \"transform-bg\" },\n { id: \"e2\", source: \"transform-bg\", target: \"transform-resize\" },\n { id: \"e3\", source: \"transform-resize\", target: \"transform-caption\" },\n ],\n },\n};\n/**\n * AI Hero Image for Landing Pages\n * Canonical ID: ai-hero-image\n *\n * Multi-step workflow: AI generate → Resize to OG dimensions → Round corners → WebP for fast loading\n * JTBD: Create landing page hero images optimized for web performance and social sharing\n */\nexport const aiHeroImage = {\n id: \"ai-hero-image\",\n name: \"AI Hero Image\",\n description: \"Generate landing page hero images optimized for web and social sharing\",\n category: \"AI Workflows\",\n generator: \"openai\",\n tags: [\"hero\", \"landing-page\", \"marketing\", \"dall-e\", \"ai\", \"pipeline\", \"og-image\"],\n requiresCloud: true,\n requiresAuth: true,\n usesAI: true,\n aiCreditsNeeded: 1,\n capabilities: {\n pipeline: true,\n },\n icon: \"sparkles\",\n valueProp: \"Landing page hero images in seconds\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/ai-hero-image.png\",\n },\n codeExample: `const hero = await floimg\n .generate('openai', {\n prompt: 'Futuristic city skyline at sunset, cinematic lighting',\n model: 'dall-e-3',\n size: '1792x1024'\n })\n .transform('resize', { width: 1200, height: 630 }) // OG image dimensions\n .transform('roundCorners', { radius: 8 })\n .transform('convert', { to: 'image/webp', quality: 85 })\n .toBlob();`,\n seo: {\n title: \"AI Hero Image Generator\",\n description: \"Generate landing page hero images optimized for web and social sharing\",\n keywords: [\"hero image\", \"landing page\", \"og image\", \"social sharing\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-ai\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"openai\",\n params: {\n prompt: \"Futuristic city skyline at golden hour sunset, cinematic wide angle, volumetric lighting, sci-fi architecture, dramatic clouds, professional photography\",\n model: \"dall-e-3\",\n size: \"1792x1024\",\n quality: \"hd\",\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 1200,\n height: 630,\n fit: \"cover\",\n },\n },\n },\n {\n id: \"transform-corners\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"roundCorners\",\n params: {\n radius: 8,\n },\n },\n },\n {\n id: \"transform-webp\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/webp\",\n quality: 85,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-ai\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-corners\" },\n { id: \"e3\", source: \"transform-corners\", target: \"transform-webp\" },\n ],\n },\n};\n/**\n * AI Mascot with Brand Kit Export\n * Canonical ID: ai-mascot\n *\n * Multi-step workflow: AI generate → Remove background → Export multiple sizes for different uses\n * JTBD: Create mascot assets ready for favicon, social avatars, and website use\n */\nexport const aiMascot = {\n id: \"ai-mascot\",\n name: \"AI Mascot Generator\",\n description: \"Generate mascot with transparent background and multiple export sizes\",\n category: \"AI Workflows\",\n generator: \"openai\",\n tags: [\"mascot\", \"character\", \"branding\", \"dall-e\", \"ai\", \"pipeline\", \"favicon\", \"avatar\"],\n requiresCloud: true,\n requiresAuth: true,\n usesAI: true,\n aiCreditsNeeded: 1,\n capabilities: {\n pipeline: true,\n },\n icon: \"sparkles\",\n valueProp: \"Brand-ready mascot assets in seconds\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/ai-mascot.png\",\n },\n codeExample: `const mascot = await floimg\n .generate('openai', {\n prompt: 'Friendly robot mascot, modern flat design, teal colors, white background',\n model: 'dall-e-3',\n size: '1024x1024'\n })\n .transform('removeBackground')\n .transform('resize', { width: 512, height: 512, fit: 'contain' })\n .transform('convert', { to: 'image/png' })\n .toBlob();`,\n seo: {\n title: \"AI Mascot Generator\",\n description: \"Create brand mascots with transparent backgrounds ready for any use\",\n keywords: [\"mascot design\", \"character design\", \"branding\", \"favicon\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-ai\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"openai\",\n params: {\n prompt: \"Friendly robot mascot character, modern flat design style, vibrant teal and purple colors, simple geometric shapes, suitable for tech company branding, white background\",\n model: \"dall-e-3\",\n size: \"1024x1024\",\n quality: \"hd\",\n },\n },\n },\n {\n id: \"transform-bg\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"removeBackground\",\n params: {},\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 512,\n height: 512,\n fit: \"contain\",\n },\n },\n },\n {\n id: \"transform-png\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/png\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-ai\", target: \"transform-bg\" },\n { id: \"e2\", source: \"transform-bg\", target: \"transform-resize\" },\n { id: \"e3\", source: \"transform-resize\", target: \"transform-png\" },\n ],\n },\n};\n/**\n * AI Logo to Brand Kit (Cloud Onboarding)\n * Canonical ID: cloud-ai-logo-brand\n */\nexport const aiLogoBrandKit = {\n id: \"cloud-ai-logo-brand\",\n name: \"AI Logo to Brand Kit\",\n description: \"Generate a logo with AI, then create production-ready brand assets\",\n category: \"AI Workflows\",\n generator: \"openai\",\n tags: [\"ai\", \"logo\", \"branding\", \"dall-e\", \"pipeline\"],\n requiresCloud: true,\n requiresAuth: true,\n usesAI: true,\n aiCreditsNeeded: 1,\n capabilities: {\n pipeline: true,\n },\n icon: \"sparkles\",\n valueProp: \"From idea to brand kit in seconds\",\n seo: {\n title: \"AI Logo to Brand Kit\",\n description: \"Generate a logo with AI and create production-ready brand assets\",\n keywords: [\"logo design\", \"brand kit\", \"ai generation\", \"branding\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-ai\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"openai\",\n params: {\n prompt: \"A modern minimalist logo for a tech startup called 'Nexus', clean geometric lines, professional, suitable for business cards and websites, white background\",\n model: \"dall-e-3\",\n size: \"1024x1024\",\n quality: \"standard\",\n },\n },\n },\n {\n id: \"transform-bg\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"removeBackground\",\n params: {},\n },\n },\n {\n id: \"transform-watermark\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"addCaption\",\n params: {\n text: \"Nexus Inc.\",\n position: \"bottom-right\",\n fontSize: 14,\n color: \"#6B7280\",\n padding: 16,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-ai\", target: \"transform-bg\" },\n { id: \"e2\", source: \"transform-bg\", target: \"transform-watermark\" },\n ],\n },\n};\n/**\n * Product Photo Enhancement (Cloud Onboarding)\n * Canonical ID: cloud-product-enhance\n */\nexport const productPhotoEnhancement = {\n id: \"cloud-product-enhance\",\n name: \"Product Photo Enhancement\",\n description: \"Remove background and add professional product labeling\",\n category: \"AI Workflows\",\n generator: \"input\",\n tags: [\"product\", \"ecommerce\", \"background-removal\", \"pipeline\"],\n requiresCloud: true,\n requiresAuth: true,\n usesAI: false, // Uses AI transforms but not AI generation\n aiCreditsNeeded: 0,\n capabilities: {\n pipeline: true,\n },\n icon: \"image\",\n valueProp: \"E-commerce ready in one click\",\n workflow: {\n nodes: [\n {\n id: \"input-1\",\n type: \"input\",\n position: { x: 100, y: 150 },\n data: {},\n },\n {\n id: \"transform-bg\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"removeBackground\",\n params: {},\n },\n },\n {\n id: \"transform-caption\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"addCaption\",\n params: {\n text: \"Premium Quality\",\n position: \"bottom-center\",\n fontSize: 24,\n color: \"#18181B\",\n padding: 20,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"input-1\", target: \"transform-bg\" },\n { id: \"e2\", source: \"transform-bg\", target: \"transform-caption\" },\n ],\n },\n};\n/**\n * AI Art to Social Post (Cloud Onboarding)\n * Canonical ID: cloud-ai-social\n */\nexport const aiArtSocialPost = {\n id: \"cloud-ai-social\",\n name: \"AI Art to Social Post\",\n description: \"Generate creative AI art, optimize for social media\",\n category: \"AI Workflows\",\n generator: \"openai\",\n tags: [\"ai\", \"art\", \"social-media\", \"dall-e\", \"pipeline\"],\n requiresCloud: true,\n requiresAuth: true,\n usesAI: true,\n aiCreditsNeeded: 1,\n capabilities: {\n pipeline: true,\n },\n icon: \"share\",\n valueProp: \"Creative content for your feed\",\n workflow: {\n nodes: [\n {\n id: \"gen-ai\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"openai\",\n params: {\n prompt: \"Abstract colorful digital art with flowing gradients, trending on artstation, vibrant neon colors, perfect for social media\",\n model: \"dall-e-3\",\n size: \"1024x1024\",\n style: \"vivid\",\n },\n },\n },\n {\n id: \"transform-corners\",\n type: \"transform\",\n position: { x: 400, y: 100 },\n data: {\n operation: \"roundCorners\",\n params: {\n radius: 24,\n },\n },\n },\n {\n id: \"transform-caption\",\n type: \"transform\",\n position: { x: 700, y: 100 },\n data: {\n operation: \"addCaption\",\n params: {\n text: \"@floimg\",\n position: \"bottom-right\",\n fontSize: 18,\n color: \"#FFFFFF\",\n padding: 16,\n },\n },\n },\n {\n id: \"transform-webp\",\n type: \"transform\",\n position: { x: 1000, y: 100 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/webp\",\n quality: 85,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-ai\", target: \"transform-corners\" },\n { id: \"e2\", source: \"transform-corners\", target: \"transform-caption\" },\n { id: \"e3\", source: \"transform-caption\", target: \"transform-webp\" },\n ],\n },\n};\n/**\n * All AI workflow templates\n */\nexport const aiWorkflowTemplates = [\n aiProductShot,\n aiHeroImage,\n aiMascot,\n aiLogoBrandKit,\n productPhotoEnhancement,\n aiArtSocialPost,\n];\n//# sourceMappingURL=ai-workflows.js.map","/**\n * Marketing Templates\n *\n * Social media kits, branding, and promotional asset workflows.\n * Most are pipeline templates that work offline (OSS-compatible).\n */\n/**\n * Social Media Kit\n * Canonical ID: social-media-kit\n */\nexport const socialMediaKit = {\n id: \"social-media-kit\",\n name: \"Social Media Kit\",\n description: \"Generate optimized images for all social platforms from one source\",\n category: \"Marketing\",\n generator: \"pipeline\",\n tags: [\"social\", \"og-image\", \"twitter\", \"instagram\", \"resize\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"share\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/social-media-kit.png\",\n },\n codeExample: `// One source -> all platforms\nconst socialKit = await floimg.pipeline(heroImage, [\n { op: 'resize', params: { width: 1200, height: 630 }, save: 'og-image.png' },\n { op: 'resize', params: { width: 800, height: 418 }, save: 'twitter-card.png' },\n { op: 'resize', params: { width: 1080, height: 1080 }, save: 'instagram.png' },\n]);`,\n seo: {\n title: \"Social Media Kit Generator\",\n description: \"Generate optimized images for all social platforms from one source image\",\n keywords: [\"social media\", \"og image\", \"twitter card\", \"instagram\", \"image resize\"],\n },\n workflow: {\n nodes: [\n {\n id: \"input-1\",\n type: \"input\",\n position: { x: 100, y: 200 },\n data: {},\n },\n {\n id: \"transform-og\",\n type: \"transform\",\n position: { x: 400, y: 100 },\n data: {\n operation: \"resize\",\n params: {\n width: 1200,\n height: 630,\n fit: \"cover\",\n },\n },\n },\n {\n id: \"transform-twitter\",\n type: \"transform\",\n position: { x: 400, y: 200 },\n data: {\n operation: \"resize\",\n params: {\n width: 800,\n height: 418,\n fit: \"cover\",\n },\n },\n },\n {\n id: \"transform-instagram\",\n type: \"transform\",\n position: { x: 400, y: 300 },\n data: {\n operation: \"resize\",\n params: {\n width: 1080,\n height: 1080,\n fit: \"cover\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"input-1\", target: \"transform-og\" },\n { id: \"e2\", source: \"input-1\", target: \"transform-twitter\" },\n { id: \"e3\", source: \"input-1\", target: \"transform-instagram\" },\n ],\n },\n};\n/**\n * Avatar Processing Pipeline\n * Canonical ID: avatar-pipeline\n */\nexport const avatarPipeline = {\n id: \"avatar-pipeline\",\n name: \"Avatar Processing\",\n description: \"Generate consistent avatar sizes with circular crop and optimization\",\n category: \"Marketing\",\n generator: \"pipeline\",\n tags: [\"avatar\", \"profile\", \"resize\", \"crop\", \"user\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"image\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/avatar-pipeline.png\",\n },\n codeExample: `const avatars = await floimg.pipeline(photo, [\n { op: 'crop', params: { shape: 'circle' } },\n { op: 'resize', params: { width: 256 }, save: 'avatar-256.png' },\n { op: 'resize', params: { width: 128 }, save: 'avatar-128.png' },\n { op: 'resize', params: { width: 64 }, save: 'avatar-64.png' },\n]);`,\n seo: {\n title: \"Avatar Processing Pipeline\",\n description: \"Generate consistent avatar sizes with circular crop and optimization\",\n keywords: [\"avatar\", \"profile picture\", \"image resize\", \"circular crop\"],\n },\n workflow: {\n nodes: [\n {\n id: \"input-1\",\n type: \"input\",\n position: { x: 100, y: 200 },\n data: {},\n },\n {\n id: \"transform-crop\",\n type: \"transform\",\n position: { x: 350, y: 200 },\n data: {\n operation: \"crop\",\n params: {\n shape: \"circle\",\n },\n },\n },\n {\n id: \"transform-256\",\n type: \"transform\",\n position: { x: 600, y: 100 },\n data: {\n operation: \"resize\",\n params: {\n width: 256,\n height: 256,\n },\n },\n },\n {\n id: \"transform-128\",\n type: \"transform\",\n position: { x: 600, y: 200 },\n data: {\n operation: \"resize\",\n params: {\n width: 128,\n height: 128,\n },\n },\n },\n {\n id: \"transform-64\",\n type: \"transform\",\n position: { x: 600, y: 300 },\n data: {\n operation: \"resize\",\n params: {\n width: 64,\n height: 64,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"input-1\", target: \"transform-crop\" },\n { id: \"e2\", source: \"transform-crop\", target: \"transform-256\" },\n { id: \"e3\", source: \"transform-crop\", target: \"transform-128\" },\n { id: \"e4\", source: \"transform-crop\", target: \"transform-64\" },\n ],\n },\n};\n/**\n * Branded Watermark\n * Canonical ID: watermark-branding\n */\nexport const watermarkBranding = {\n id: \"watermark-branding\",\n name: \"Branded Watermark\",\n description: \"Add your logo watermark to images automatically\",\n category: \"Marketing\",\n generator: \"pipeline\",\n tags: [\"watermark\", \"branding\", \"logo\", \"protection\", \"copyright\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"image\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/watermark-branding.png\",\n },\n seo: {\n title: \"Branded Watermark Template\",\n description: \"Add professional watermarks to protect and brand your images\",\n keywords: [\"watermark\", \"branding\", \"image protection\", \"logo overlay\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 100 },\n data: {\n generatorName: \"quickchart\",\n params: {\n chart: {\n type: \"bar\",\n data: {\n labels: [\"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\"],\n datasets: [\n {\n label: \"Sales\",\n data: [45, 62, 38, 71, 55],\n backgroundColor: \"rgba(99, 102, 241, 0.8)\",\n },\n ],\n },\n },\n width: 600,\n height: 400,\n },\n },\n },\n {\n id: \"transform-1\",\n type: \"transform\",\n position: { x: 400, y: 100 },\n data: {\n operation: \"addCaption\",\n params: {\n text: \"floimg.com\",\n position: \"bottom-right\",\n fontSize: 14,\n color: \"#9ca3af\",\n padding: 10,\n },\n },\n },\n {\n id: \"transform-2\",\n type: \"transform\",\n position: { x: 700, y: 100 },\n data: {\n operation: \"roundCorners\",\n params: {\n radius: 16,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-1\" },\n { id: \"e2\", source: \"transform-1\", target: \"transform-2\" },\n ],\n },\n};\n/**\n * Image Filters\n * Canonical ID: filter-showcase\n */\nexport const filterShowcase = {\n id: \"filter-showcase\",\n name: \"Image Filters\",\n description: \"Apply artistic filters: vintage, dramatic, vibrant, and more\",\n category: \"Marketing\",\n generator: \"pipeline\",\n tags: [\"filter\", \"vintage\", \"effects\", \"artistic\", \"photo\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"image\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/filter-showcase.png\",\n },\n seo: {\n title: \"Image Filter Effects\",\n description: \"Apply artistic filters like vintage, dramatic, and vibrant effects\",\n keywords: [\"image filter\", \"photo effects\", \"vintage filter\", \"artistic\"],\n },\n workflow: {\n nodes: [\n {\n id: \"input-1\",\n type: \"input\",\n position: { x: 100, y: 200 },\n data: {},\n },\n {\n id: \"transform-vintage\",\n type: \"transform\",\n position: { x: 400, y: 100 },\n data: {\n operation: \"adjustColors\",\n params: {\n saturation: 0.7,\n brightness: 0.9,\n sepia: 0.3,\n },\n },\n },\n {\n id: \"transform-vibrant\",\n type: \"transform\",\n position: { x: 400, y: 200 },\n data: {\n operation: \"adjustColors\",\n params: {\n saturation: 1.4,\n contrast: 1.2,\n },\n },\n },\n {\n id: \"transform-dramatic\",\n type: \"transform\",\n position: { x: 400, y: 300 },\n data: {\n operation: \"adjustColors\",\n params: {\n contrast: 1.5,\n brightness: 0.8,\n saturation: 0.9,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"input-1\", target: \"transform-vintage\" },\n { id: \"e2\", source: \"input-1\", target: \"transform-vibrant\" },\n { id: \"e3\", source: \"input-1\", target: \"transform-dramatic\" },\n ],\n },\n};\n/**\n * Responsive Image Pipeline\n * Canonical ID: responsive-images\n *\n * Multi-step workflow: Input → 5 parallel resize branches for responsive web\n * JTBD: Generate all responsive image sizes from one source for web performance\n */\nexport const responsiveImages = {\n id: \"responsive-images\",\n name: \"Responsive Image Pipeline\",\n description: \"Generate thumbnail, mobile, tablet, desktop, and retina sizes from one source\",\n category: \"Marketing\",\n generator: \"pipeline\",\n tags: [\"responsive\", \"web\", \"performance\", \"srcset\", \"resize\", \"pipeline\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"image\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/responsive-images.png\",\n },\n codeExample: `// One source → all responsive sizes\nconst responsive = await floimg.from(source)\n .transform('resize', { width: 320 }) // Mobile\n .transform('resize', { width: 768 }) // Tablet\n .transform('resize', { width: 1024 }) // Desktop\n .transform('resize', { width: 2048 }) // Retina\n .toBlob();`,\n seo: {\n title: \"Responsive Image Pipeline\",\n description: \"Generate all responsive image sizes for web srcset from one source\",\n keywords: [\"responsive images\", \"srcset\", \"web performance\", \"image optimization\"],\n },\n workflow: {\n nodes: [\n {\n id: \"input-1\",\n type: \"input\",\n position: { x: 100, y: 250 },\n data: {},\n },\n {\n id: \"transform-thumb\",\n type: \"transform\",\n position: { x: 400, y: 50 },\n data: {\n operation: \"resize\",\n params: {\n width: 150,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-mobile\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 320,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-tablet\",\n type: \"transform\",\n position: { x: 400, y: 250 },\n data: {\n operation: \"resize\",\n params: {\n width: 768,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-desktop\",\n type: \"transform\",\n position: { x: 400, y: 350 },\n data: {\n operation: \"resize\",\n params: {\n width: 1024,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-retina\",\n type: \"transform\",\n position: { x: 400, y: 450 },\n data: {\n operation: \"resize\",\n params: {\n width: 2048,\n fit: \"inside\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"input-1\", target: \"transform-thumb\" },\n { id: \"e2\", source: \"input-1\", target: \"transform-mobile\" },\n { id: \"e3\", source: \"input-1\", target: \"transform-tablet\" },\n { id: \"e4\", source: \"input-1\", target: \"transform-desktop\" },\n { id: \"e5\", source: \"input-1\", target: \"transform-retina\" },\n ],\n },\n};\n/**\n * Team Headshot Standardizer\n * Canonical ID: team-headshots\n *\n * Multi-step workflow: Input → Crop square → Resize → Grayscale → PNG export\n * JTBD: Standardize team photos for about pages and directories\n */\nexport const teamHeadshots = {\n id: \"team-headshots\",\n name: \"Team Headshot Standardizer\",\n description: \"Standardize team photos with consistent sizing and professional styling\",\n category: \"Marketing\",\n generator: \"pipeline\",\n tags: [\"headshot\", \"team\", \"about-page\", \"profile\", \"standardize\", \"pipeline\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"image\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/team-headshots.png\",\n },\n codeExample: `const headshot = await floimg.from(photo)\n .transform('extract', { width: 400, height: 400, gravity: 'face' })\n .transform('resize', { width: 300, height: 300 })\n .transform('grayscale')\n .transform('convert', { to: 'image/png' })\n .toBlob();`,\n seo: {\n title: \"Team Headshot Standardizer\",\n description: \"Standardize team photos with consistent sizing for about pages\",\n keywords: [\"headshot\", \"team photo\", \"about page\", \"profile picture\"],\n },\n workflow: {\n nodes: [\n {\n id: \"input-1\",\n type: \"input\",\n position: { x: 100, y: 150 },\n data: {},\n },\n {\n id: \"transform-crop\",\n type: \"transform\",\n position: { x: 350, y: 150 },\n data: {\n operation: \"extract\",\n params: {\n width: 400,\n height: 400,\n gravity: \"center\",\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 600, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 300,\n height: 300,\n fit: \"cover\",\n },\n },\n },\n {\n id: \"transform-grayscale\",\n type: \"transform\",\n position: { x: 850, y: 150 },\n data: {\n operation: \"grayscale\",\n params: {},\n },\n },\n {\n id: \"transform-png\",\n type: \"transform\",\n position: { x: 1100, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/png\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"input-1\", target: \"transform-crop\" },\n { id: \"e2\", source: \"transform-crop\", target: \"transform-resize\" },\n { id: \"e3\", source: \"transform-resize\", target: \"transform-grayscale\" },\n { id: \"e4\", source: \"transform-grayscale\", target: \"transform-png\" },\n ],\n },\n};\n/**\n * Screenshot to Documentation Asset\n * Canonical ID: screenshot-docs\n *\n * Multi-step workflow: Screenshot URL → Resize → Add border/shadow → Optimize\n * JTBD: Prepare screenshots for documentation and README files\n */\nexport const screenshotDocs = {\n id: \"screenshot-docs\",\n name: \"Screenshot to Docs\",\n description: \"Prepare screenshots for documentation with borders and optimization\",\n category: \"Marketing\",\n generator: \"screenshot\",\n tags: [\"screenshot\", \"documentation\", \"readme\", \"border\", \"pipeline\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"image\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/screenshot-docs.png\",\n },\n codeExample: `const docImage = await floimg\n .generate('screenshot', { url: 'https://example.com', width: 1280 })\n .transform('resize', { width: 800, fit: 'inside' })\n .transform('extend', { top: 16, bottom: 16, left: 16, right: 16, background: '#f3f4f6' })\n .transform('roundCorners', { radius: 8 })\n .transform('convert', { to: 'image/png' })\n .toBlob();`,\n seo: {\n title: \"Screenshot to Documentation Asset\",\n description: \"Prepare screenshots for documentation with professional styling\",\n keywords: [\"screenshot\", \"documentation\", \"readme\", \"developer tools\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"screenshot\",\n params: {\n url: \"https://floimg.com\",\n width: 1280,\n height: 800,\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 800,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-border\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"extend\",\n params: {\n top: 16,\n bottom: 16,\n left: 16,\n right: 16,\n background: \"#f3f4f6\",\n },\n },\n },\n {\n id: \"transform-corners\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"roundCorners\",\n params: {\n radius: 8,\n },\n },\n },\n {\n id: \"transform-png\",\n type: \"transform\",\n position: { x: 1300, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/png\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-border\" },\n { id: \"e3\", source: \"transform-border\", target: \"transform-corners\" },\n { id: \"e4\", source: \"transform-corners\", target: \"transform-png\" },\n ],\n },\n};\n/**\n * Blog Post OG Image\n * Canonical ID: blog-og-image\n *\n * Multi-step workflow: Input → Resize to OG → Add title overlay → WebP export\n * JTBD: Create social sharing images for blog posts with title overlay\n */\nexport const blogOgImage = {\n id: \"blog-og-image\",\n name: \"Blog Post OG Image\",\n description: \"Create social sharing images for blog posts with title overlay\",\n category: \"Marketing\",\n generator: \"pipeline\",\n tags: [\"blog\", \"og-image\", \"social\", \"title\", \"overlay\", \"pipeline\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"share\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/blog-og-image.png\",\n },\n codeExample: `const ogImage = await floimg.from(heroImage)\n .transform('resize', { width: 1200, height: 630, fit: 'cover' })\n .transform('addCaption', {\n text: 'How to Build Image Pipelines',\n position: 'center',\n fontSize: 48,\n color: '#ffffff'\n })\n .transform('convert', { to: 'image/webp', quality: 85 })\n .toBlob();`,\n seo: {\n title: \"Blog Post OG Image Generator\",\n description: \"Create social sharing images for blog posts with title overlay\",\n keywords: [\"og image\", \"blog\", \"social sharing\", \"title overlay\"],\n },\n workflow: {\n nodes: [\n {\n id: \"input-1\",\n type: \"input\",\n position: { x: 100, y: 150 },\n data: {},\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 1200,\n height: 630,\n fit: \"cover\",\n },\n },\n },\n {\n id: \"transform-caption\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"addCaption\",\n params: {\n text: \"Your Blog Post Title\",\n position: \"center\",\n fontSize: 48,\n color: \"#ffffff\",\n padding: 32,\n },\n },\n },\n {\n id: \"transform-webp\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/webp\",\n quality: 85,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"input-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-caption\" },\n { id: \"e3\", source: \"transform-caption\", target: \"transform-webp\" },\n ],\n },\n};\n/**\n * Email Banner\n * Canonical ID: email-banner\n *\n * Multi-step workflow: Input → Resize 600x200 → Add CTA text → PNG export\n * JTBD: Create email header banners with consistent dimensions for newsletters\n */\nexport const emailBanner = {\n id: \"email-banner\",\n name: \"Email Banner\",\n description: \"Create email header banners with consistent dimensions for newsletters\",\n category: \"Marketing\",\n generator: \"pipeline\",\n tags: [\"email\", \"banner\", \"newsletter\", \"header\", \"marketing\", \"pipeline\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"share\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/email-banner.png\",\n },\n codeExample: `const banner = await floimg.from(image)\n .transform('resize', { width: 600, height: 200, fit: 'cover' })\n .transform('addCaption', {\n text: 'Weekly Newsletter',\n position: 'center',\n fontSize: 32,\n color: '#ffffff'\n })\n .transform('convert', { to: 'image/png' })\n .toBlob();`,\n seo: {\n title: \"Email Banner Generator\",\n description: \"Create email header banners with consistent dimensions\",\n keywords: [\"email banner\", \"newsletter\", \"email marketing\", \"header image\"],\n },\n workflow: {\n nodes: [\n {\n id: \"input-1\",\n type: \"input\",\n position: { x: 100, y: 150 },\n data: {},\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 600,\n height: 200,\n fit: \"cover\",\n },\n },\n },\n {\n id: \"transform-caption\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"addCaption\",\n params: {\n text: \"Weekly Newsletter\",\n position: \"center\",\n fontSize: 32,\n color: \"#ffffff\",\n padding: 16,\n },\n },\n },\n {\n id: \"transform-png\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/png\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"input-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-caption\" },\n { id: \"e3\", source: \"transform-caption\", target: \"transform-png\" },\n ],\n },\n};\n/**\n * App Icon Generator\n * Canonical ID: app-icons\n *\n * Multi-step workflow: Input → Remove background → Multiple iOS/Android sizes\n * JTBD: Generate all required app icon sizes for iOS and Android from one source\n */\nexport const appIcons = {\n id: \"app-icons\",\n name: \"App Icon Generator\",\n description: \"Generate iOS and Android app icon sizes from one source image\",\n category: \"Marketing\",\n generator: \"pipeline\",\n tags: [\"app-icon\", \"ios\", \"android\", \"mobile\", \"resize\", \"pipeline\"],\n requiresCloud: true,\n requiresAuth: true,\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"image\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/app-icons.png\",\n },\n codeExample: `const icons = await floimg.from(logo)\n .transform('removeBackground')\n .transform('resize', { width: 180, height: 180 }) // iOS\n .transform('resize', { width: 192, height: 192 }) // Android\n .transform('resize', { width: 512, height: 512 }) // Store\n .toBlob();`,\n seo: {\n title: \"App Icon Generator\",\n description: \"Generate all required iOS and Android app icon sizes\",\n keywords: [\"app icon\", \"ios icon\", \"android icon\", \"mobile app\"],\n },\n workflow: {\n nodes: [\n {\n id: \"input-1\",\n type: \"input\",\n position: { x: 100, y: 200 },\n data: {},\n },\n {\n id: \"transform-bg\",\n type: \"transform\",\n position: { x: 350, y: 200 },\n data: {\n operation: \"removeBackground\",\n params: {},\n },\n },\n {\n id: \"transform-ios-60\",\n type: \"transform\",\n position: { x: 600, y: 50 },\n data: {\n operation: \"resize\",\n params: {\n width: 60,\n height: 60,\n fit: \"contain\",\n },\n },\n },\n {\n id: \"transform-ios-180\",\n type: \"transform\",\n position: { x: 600, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 180,\n height: 180,\n fit: \"contain\",\n },\n },\n },\n {\n id: \"transform-android-192\",\n type: \"transform\",\n position: { x: 600, y: 250 },\n data: {\n operation: \"resize\",\n params: {\n width: 192,\n height: 192,\n fit: \"contain\",\n },\n },\n },\n {\n id: \"transform-store-512\",\n type: \"transform\",\n position: { x: 600, y: 350 },\n data: {\n operation: \"resize\",\n params: {\n width: 512,\n height: 512,\n fit: \"contain\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"input-1\", target: \"transform-bg\" },\n { id: \"e2\", source: \"transform-bg\", target: \"transform-ios-60\" },\n { id: \"e3\", source: \"transform-bg\", target: \"transform-ios-180\" },\n { id: \"e4\", source: \"transform-bg\", target: \"transform-android-192\" },\n { id: \"e5\", source: \"transform-bg\", target: \"transform-store-512\" },\n ],\n },\n};\n/**\n * All marketing templates\n */\nexport const marketingTemplates = [\n socialMediaKit,\n avatarPipeline,\n watermarkBranding,\n filterShowcase,\n responsiveImages,\n teamHeadshots,\n screenshotDocs,\n blogOgImage,\n emailBanner,\n appIcons,\n];\n//# sourceMappingURL=marketing.js.map","/**\n * Utility Templates\n *\n * QR codes, format conversion, and general-purpose utilities.\n * All templates in this category work offline (OSS-compatible).\n */\n/**\n * Branded QR Code Pipeline\n * Canonical ID: branded-qr\n *\n * Multi-step workflow: Generate QR → Resize → Add rounded corners → Convert to PNG\n * Demonstrates: composable transforms on generated content\n */\nexport const brandedQR = {\n id: \"branded-qr\",\n name: \"Branded QR Code\",\n description: \"QR code with custom colors, rounded corners, and optimized for print or digital\",\n category: \"Utilities\",\n generator: \"qr\",\n tags: [\"qr\", \"branded\", \"link\", \"custom\", \"url\", \"pipeline\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"qr\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/branded-qr.png\",\n },\n codeExample: `const qr = await floimg\n .generate('qr', {\n text: 'https://floimg.com',\n color: { dark: '#0d9488', light: '#ffffff' }\n })\n .transform('resize', { width: 300, height: 300 })\n .transform('roundCorners', { radius: 16 })\n .transform('convert', { to: 'image/png' })\n .toBlob();`,\n seo: {\n title: \"Branded QR Code Generator\",\n description: \"Generate QR codes with custom colors, rounded corners, and professional styling\",\n keywords: [\"qr code\", \"branded qr\", \"custom qr\", \"marketing\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"qr\",\n params: {\n text: \"https://floimg.com\",\n width: 400,\n margin: 2,\n color: { dark: \"#0d9488\", light: \"#ffffff\" },\n errorCorrectionLevel: \"M\",\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 300,\n height: 300,\n fit: \"contain\",\n },\n },\n },\n {\n id: \"transform-corners\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"roundCorners\",\n params: {\n radius: 16,\n },\n },\n },\n {\n id: \"transform-convert\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/png\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-corners\" },\n { id: \"e3\", source: \"transform-corners\", target: \"transform-convert\" },\n ],\n },\n};\n/**\n * Dark Mode QR Code Pipeline\n * Canonical ID: dark-qr\n *\n * Multi-step workflow: Generate inverted QR → Resize → Add subtle border → WebP export\n * Demonstrates: transforms for dark UI integration\n */\nexport const darkQR = {\n id: \"dark-qr\",\n name: \"Dark Mode QR\",\n description: \"QR code optimized for dark backgrounds with subtle border and web-optimized export\",\n category: \"Utilities\",\n generator: \"qr\",\n tags: [\"qr\", \"dark-mode\", \"link\", \"inverted\", \"pipeline\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"qr\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/dark-qr.png\",\n },\n codeExample: `const qr = await floimg\n .generate('qr', {\n text: 'https://floimg.com',\n color: { dark: '#ffffff', light: '#18181b' }\n })\n .transform('resize', { width: 300, height: 300 })\n .transform('extend', {\n top: 8, bottom: 8, left: 8, right: 8,\n background: '#27272a'\n })\n .transform('convert', { to: 'image/webp', quality: 90 })\n .toBlob();`,\n seo: {\n title: \"Dark Mode QR Code\",\n description: \"QR codes optimized for dark backgrounds and dark mode UIs\",\n keywords: [\"qr code\", \"dark mode\", \"inverted qr\", \"night mode\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"qr\",\n params: {\n text: \"https://floimg.com\",\n width: 400,\n margin: 2,\n color: { dark: \"#ffffff\", light: \"#18181b\" },\n errorCorrectionLevel: \"M\",\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 300,\n height: 300,\n fit: \"contain\",\n },\n },\n },\n {\n id: \"transform-border\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"extend\",\n params: {\n top: 8,\n bottom: 8,\n left: 8,\n right: 8,\n background: \"#27272a\",\n },\n },\n },\n {\n id: \"transform-webp\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/webp\",\n quality: 90,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-border\" },\n { id: \"e3\", source: \"transform-border\", target: \"transform-webp\" },\n ],\n },\n};\n/**\n * WiFi QR Code Pipeline\n * Canonical ID: wifi-qr\n *\n * Multi-step workflow: Generate WiFi QR → Resize → Add caption label → Rounded corners\n * Demonstrates: adding context/labels to generated content\n */\nexport const wifiQR = {\n id: \"wifi-qr\",\n name: \"WiFi QR Code\",\n description: \"Scannable WiFi QR code with network name label and professional styling\",\n category: \"Utilities\",\n generator: \"qr\",\n tags: [\"qr\", \"wifi\", \"network\", \"guest\", \"access\", \"pipeline\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"qr\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/wifi-qr.png\",\n },\n codeExample: `const qr = await floimg\n .generate('qr', {\n text: 'WIFI:T:WPA;S:GuestNetwork;P:welcome123;;',\n color: { dark: '#059669', light: '#ffffff' }\n })\n .transform('resize', { width: 300, height: 300 })\n .transform('addCaption', {\n text: 'Scan for WiFi',\n position: 'bottom-center',\n fontSize: 18,\n color: '#059669'\n })\n .transform('roundCorners', { radius: 12 })\n .toBlob();`,\n seo: {\n title: \"WiFi QR Code Generator\",\n description: \"Generate scannable QR codes for easy WiFi network access sharing\",\n keywords: [\"wifi qr\", \"network access\", \"guest wifi\", \"qr code\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"qr\",\n params: {\n text: \"WIFI:T:WPA;S:GuestNetwork;P:welcome123;;\",\n width: 400,\n margin: 2,\n color: { dark: \"#059669\", light: \"#ffffff\" },\n errorCorrectionLevel: \"H\",\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 300,\n height: 300,\n fit: \"contain\",\n },\n },\n },\n {\n id: \"transform-caption\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"addCaption\",\n params: {\n text: \"Scan for WiFi\",\n position: \"bottom-center\",\n fontSize: 18,\n color: \"#059669\",\n padding: 16,\n },\n },\n },\n {\n id: \"transform-corners\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"roundCorners\",\n params: {\n radius: 12,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-caption\" },\n { id: \"e3\", source: \"transform-caption\", target: \"transform-corners\" },\n ],\n },\n};\n/**\n * Thumbnail Generator\n * Canonical ID: thumbnail-generator\n */\nexport const thumbnailGenerator = {\n id: \"thumbnail-generator\",\n name: \"Thumbnail Generator\",\n description: \"Create multiple thumbnail sizes with automatic optimization\",\n category: \"Utilities\",\n generator: \"pipeline\",\n tags: [\"thumbnail\", \"resize\", \"optimize\", \"batch\", \"responsive\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"image\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/thumbnail-generator.png\",\n },\n seo: {\n title: \"Thumbnail Generator\",\n description: \"Generate multiple thumbnail sizes with automatic optimization\",\n keywords: [\"thumbnail\", \"image resize\", \"responsive images\", \"optimization\"],\n },\n workflow: {\n nodes: [\n {\n id: \"input-1\",\n type: \"input\",\n position: { x: 100, y: 200 },\n data: {},\n },\n {\n id: \"transform-800\",\n type: \"transform\",\n position: { x: 400, y: 100 },\n data: {\n operation: \"resize\",\n params: {\n width: 800,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-400\",\n type: \"transform\",\n position: { x: 400, y: 200 },\n data: {\n operation: \"resize\",\n params: {\n width: 400,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-200\",\n type: \"transform\",\n position: { x: 400, y: 300 },\n data: {\n operation: \"resize\",\n params: {\n width: 200,\n fit: \"inside\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"input-1\", target: \"transform-800\" },\n { id: \"e2\", source: \"input-1\", target: \"transform-400\" },\n { id: \"e3\", source: \"input-1\", target: \"transform-200\" },\n ],\n },\n};\n/**\n * Diagram to WebP Conversion\n * Canonical ID: diagram-webp\n */\nexport const diagramWebp = {\n id: \"diagram-webp\",\n name: \"Diagram to WebP\",\n description: \"Mermaid diagram converted to optimized WebP format\",\n category: \"Utilities\",\n generator: \"mermaid\",\n tags: [\"mermaid\", \"webp\", \"optimize\", \"pipeline\", \"conversion\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"diagram\",\n seo: {\n title: \"Diagram to WebP Converter\",\n description: \"Convert Mermaid diagrams to optimized WebP format\",\n keywords: [\"mermaid diagram\", \"webp conversion\", \"image optimization\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 100 },\n data: {\n generatorName: \"mermaid\",\n params: {\n code: `graph LR\n A[Start] --> B{Decision}\n B -->|Yes| C[Action 1]\n B -->|No| D[Action 2]\n C --> E[End]\n D --> E`,\n theme: \"neutral\",\n },\n },\n },\n {\n id: \"transform-1\",\n type: \"transform\",\n position: { x: 400, y: 100 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/webp\",\n quality: 90,\n },\n },\n },\n ],\n edges: [{ id: \"e1\", source: \"gen-1\", target: \"transform-1\" }],\n },\n};\n/**\n * All utility templates\n */\nexport const utilityTemplates = [\n brandedQR,\n darkQR,\n wifiQR,\n thumbnailGenerator,\n diagramWebp,\n];\n//# sourceMappingURL=utilities.js.map","/**\n * @teamflojo/floimg-templates\n *\n * Official workflow templates for FloImg Studio.\n * Single source of truth for template definitions.\n *\n * @example\n * ```typescript\n * // Self-hosted: Get only templates that work offline\n * import { getCoreTemplates } from '@teamflojo/floimg-templates';\n * const templates = getCoreTemplates();\n *\n * // Cloud/full: Get all templates including those requiring API keys\n * import { getAllTemplates } from '@teamflojo/floimg-templates';\n * const templates = getAllTemplates();\n *\n * // Get specific template with metadata\n * import { getTemplateById } from '@teamflojo/floimg-templates';\n * const template = getTemplateById('revenue-chart');\n * ```\n */\n// Import all template categories\nimport { dataVizTemplates } from \"./templates/data-viz.js\";\nimport { aiWorkflowTemplates } from \"./templates/ai-workflows.js\";\nimport { marketingTemplates } from \"./templates/marketing.js\";\nimport { utilityTemplates } from \"./templates/utilities.js\";\n// Re-export individual templates for direct imports\nexport * from \"./templates/data-viz.js\";\nexport * from \"./templates/ai-workflows.js\";\nexport * from \"./templates/marketing.js\";\nexport * from \"./templates/utilities.js\";\n// ============================================\n// Template Registry\n// ============================================\n/**\n * All templates combined\n */\nexport const allTemplates = [\n ...dataVizTemplates,\n ...aiWorkflowTemplates,\n ...marketingTemplates,\n ...utilityTemplates,\n];\n/**\n * Core templates that work offline (no cloud required)\n * For FloImg Studio OSS and self-hosted deployments\n */\nexport const coreTemplates = allTemplates.filter((t) => !t.requiresCloud);\n/**\n * Cloud-only templates (require API keys like OpenAI, etc.)\n */\nexport const cloudTemplates = allTemplates.filter((t) => t.requiresCloud);\n// ============================================\n// Query Functions\n// ============================================\n/**\n * Get all templates (includes cloud-only templates)\n */\nexport function getAllTemplates() {\n return allTemplates;\n}\n/**\n * Get only core templates that work offline (for OSS Studio)\n */\nexport function getCoreTemplates() {\n return coreTemplates;\n}\n/**\n * Get cloud-only templates (require API keys)\n */\nexport function getCloudTemplates() {\n return cloudTemplates;\n}\n/**\n * Get a template by ID (searches all templates)\n */\nexport function getTemplateById(id) {\n return allTemplates.find((t) => t.id === id);\n}\n/**\n * Get a core template by ID (OSS-compatible only)\n */\nexport function getCoreTemplateById(id) {\n return coreTemplates.find((t) => t.id === id);\n}\n/**\n * Get all unique categories (from all templates)\n */\nexport function getCategories() {\n const categories = new Set(allTemplates.map((t) => t.category));\n return Array.from(categories);\n}\n/**\n * Get categories available in core templates (OSS-compatible)\n */\nexport function getCoreCategories() {\n const categories = new Set(coreTemplates.map((t) => t.category));\n return Array.from(categories);\n}\n/**\n * Get templates by category (from all templates)\n */\nexport function getTemplatesByCategory(category) {\n return allTemplates.filter((t) => t.category === category);\n}\n/**\n * Get core templates by category (OSS-compatible)\n */\nexport function getCoreTemplatesByCategory(category) {\n return coreTemplates.filter((t) => t.category === category);\n}\n/**\n * Get templates by generator type\n */\nexport function getTemplatesByGenerator(generator) {\n return allTemplates.filter((t) => t.generator === generator);\n}\n/**\n * Search templates by query (searches name, description, tags)\n */\nexport function searchTemplates(query) {\n const q = query.toLowerCase();\n return allTemplates.filter((t) => t.name.toLowerCase().includes(q) ||\n t.description.toLowerCase().includes(q) ||\n t.category.toLowerCase().includes(q) ||\n t.generator.toLowerCase().includes(q) ||\n t.tags?.some((tag) => tag.toLowerCase().includes(q)));\n}\n/**\n * Search core templates by query (OSS-compatible)\n */\nexport function searchCoreTemplates(query) {\n const q = query.toLowerCase();\n return coreTemplates.filter((t) => t.name.toLowerCase().includes(q) ||\n t.description.toLowerCase().includes(q) ||\n t.category.toLowerCase().includes(q) ||\n t.generator.toLowerCase().includes(q) ||\n t.tags?.some((tag) => tag.toLowerCase().includes(q)));\n}\n/**\n * Get templates that require authentication\n */\nexport function getAuthRequiredTemplates() {\n return allTemplates.filter((t) => t.requiresAuth);\n}\n/**\n * Get templates by capability\n */\nexport function getTemplatesByCapability(capability) {\n return allTemplates.filter((t) => t.capabilities?.[capability]);\n}\n// ============================================\n// Studio URL Helpers\n// ============================================\n/**\n * Get the Studio URL for a template\n * @param templateId - The template ID\n * @param baseUrl - Base URL (defaults to studio.floimg.com for cloud, or can be overridden for self-hosted)\n */\nexport function getStudioUrl(templateId, baseUrl = \"https://studio.floimg.com\") {\n return `${baseUrl}/?template=${templateId}`;\n}\n/**\n * Get the OSS Studio URL for a template (localhost default)\n * @param templateId - The template ID\n * @param port - Port number (defaults to 5173)\n */\nexport function getOSSStudioUrl(templateId, port = 5173) {\n return `http://localhost:${port}/?template=${templateId}`;\n}\n/**\n * Resolve a template by ID\n * @param id - Template ID\n * @returns The template or undefined\n */\nexport function resolveTemplate(id) {\n return getTemplateById(id);\n}\n// ============================================\n// Computed Metadata Helpers\n// ============================================\n/**\n * Get the node count for a template\n * Uses explicit nodeCount if set, otherwise computes from workflow.nodes.length\n */\nexport function getNodeCount(template) {\n if (template.nodeCount !== undefined) {\n return template.nodeCount;\n }\n return template.workflow.nodes.length;\n}\n/**\n * Get all templates with computed nodeCount added\n * Useful for consumers that want to display node count\n */\nexport function getAllTemplatesWithNodeCount() {\n return allTemplates.map((t) => ({\n ...t,\n nodeCount: getNodeCount(t),\n }));\n}\n/**\n * Get templates that are true pipelines (2+ nodes)\n */\nexport function getPipelineTemplates() {\n return allTemplates.filter((t) => getNodeCount(t) >= 2);\n}\n/**\n * Get templates sorted by complexity (node count, descending)\n */\nexport function getTemplatesByComplexity() {\n return [...allTemplates].sort((a, b) => getNodeCount(b) - getNodeCount(a));\n}\n//# sourceMappingURL=index.js.map","import { useState, useMemo } from \"react\";\nimport {\n coreTemplates as templates,\n getCoreCategories as getCategories,\n type Template,\n} from \"@teamflojo/floimg-templates\";\n\ninterface TemplateGalleryProps {\n onSelect: (templateId: string) => void;\n}\n\nexport function TemplateGallery({ onSelect }: TemplateGalleryProps) {\n const [selectedCategory, setSelectedCategory] = useState<string | null>(null);\n const [searchQuery, setSearchQuery] = useState(\"\");\n\n const categories = useMemo(() => getCategories(), []);\n\n const filteredTemplates = useMemo(() => {\n let result = templates;\n\n // Filter by category\n if (selectedCategory) {\n result = result.filter((t) => t.category === selectedCategory);\n }\n\n // Filter by search query\n if (searchQuery) {\n const q = searchQuery.toLowerCase();\n result = result.filter(\n (t) =>\n t.name.toLowerCase().includes(q) ||\n t.description.toLowerCase().includes(q) ||\n t.generator.toLowerCase().includes(q) ||\n t.tags?.some((tag) => tag.toLowerCase().includes(q))\n );\n }\n\n return result;\n }, [selectedCategory, searchQuery]);\n\n return (\n <div className=\"p-6\">\n <div className=\"mb-6\">\n <h2 className=\"text-2xl font-bold text-gray-900 dark:text-white mb-2\">Templates</h2>\n <p className=\"text-gray-600 dark:text-zinc-400\">\n Start with a pre-built workflow. Click any template to load it into the editor.\n </p>\n </div>\n\n {/* Search and filters */}\n <div className=\"flex flex-wrap gap-4 mb-6\">\n <input\n type=\"text\"\n placeholder=\"Search templates...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"px-4 py-2 border border-gray-300 dark:border-zinc-600 rounded-lg bg-white dark:bg-zinc-800 text-gray-900 dark:text-white focus:ring-2 focus:ring-teal-500 focus:border-transparent w-64\"\n />\n\n <div className=\"flex gap-2 flex-wrap\">\n <button\n onClick={() => setSelectedCategory(null)}\n className={`px-3 py-1.5 rounded-full text-sm font-medium transition-colors ${\n selectedCategory === null\n ? \"bg-teal-600 text-white\"\n : \"bg-gray-200 dark:bg-zinc-700 text-gray-700 dark:text-zinc-300 hover:bg-gray-300 dark:hover:bg-zinc-600\"\n }`}\n >\n All\n </button>\n {categories.map((category) => (\n <button\n key={category}\n onClick={() => setSelectedCategory(category)}\n className={`px-3 py-1.5 rounded-full text-sm font-medium transition-colors ${\n selectedCategory === category\n ? \"bg-teal-600 text-white\"\n : \"bg-gray-200 dark:bg-zinc-700 text-gray-700 dark:text-zinc-300 hover:bg-gray-300 dark:hover:bg-zinc-600\"\n }`}\n >\n {category}\n </button>\n ))}\n </div>\n </div>\n\n {/* Template grid */}\n {filteredTemplates.length === 0 ? (\n <div className=\"text-center py-12 text-gray-500 dark:text-zinc-400\">\n No templates found matching your criteria.\n </div>\n ) : (\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6\">\n {filteredTemplates.map((template) => (\n <TemplateCard\n key={template.id}\n template={template}\n onSelect={() => onSelect(template.id)}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\ninterface TemplateCardProps {\n template: Template;\n onSelect: () => void;\n}\n\nfunction TemplateCard({ template, onSelect }: TemplateCardProps) {\n const nodeCount = template.workflow.nodes.length;\n const edgeCount = template.workflow.edges.length;\n\n // Generator badge colors\n const generatorColors: Record<string, string> = {\n quickchart: \"bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300\",\n mermaid: \"bg-pink-100 text-pink-800 dark:bg-pink-900/30 dark:text-pink-300\",\n qr: \"bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300\",\n d3: \"bg-orange-100 text-orange-800 dark:bg-orange-900/30 dark:text-orange-300\",\n };\n\n return (\n <div className=\"bg-white dark:bg-zinc-800 rounded-lg border border-gray-200 dark:border-zinc-700 overflow-hidden hover:shadow-lg transition-shadow\">\n {/* Preview area */}\n <div className=\"aspect-video bg-gray-100 dark:bg-zinc-900 flex items-center justify-center p-4\">\n {template.preview ? (\n <img\n src={template.preview.imageUrl}\n alt={template.name}\n className=\"max-w-full max-h-full object-contain\"\n />\n ) : (\n <div className=\"text-center text-gray-400 dark:text-zinc-500\">\n <svg\n className=\"w-12 h-12 mx-auto mb-2\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.5}\n d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\"\n />\n </svg>\n <span className=\"text-sm\">No preview</span>\n </div>\n )}\n </div>\n\n {/* Content */}\n <div className=\"p-4\">\n <div className=\"flex items-start justify-between mb-2\">\n <h3 className=\"text-lg font-semibold text-gray-900 dark:text-white\">{template.name}</h3>\n <span\n className={`px-2 py-0.5 rounded text-xs font-medium ${\n generatorColors[template.generator] ||\n \"bg-gray-100 text-gray-800 dark:bg-zinc-700 dark:text-zinc-300\"\n }`}\n >\n {template.generator}\n </span>\n </div>\n\n <p className=\"text-sm text-gray-600 dark:text-zinc-400 mb-3\">{template.description}</p>\n\n {/* Metadata */}\n <div className=\"flex items-center gap-4 text-xs text-gray-500 dark:text-zinc-500 mb-4\">\n <span className=\"flex items-center gap-1\">\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 6h16M4 12h16M4 18h7\"\n />\n </svg>\n {nodeCount} node{nodeCount !== 1 ? \"s\" : \"\"}\n </span>\n {edgeCount > 0 && (\n <span className=\"flex items-center gap-1\">\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M13 7l5 5m0 0l-5 5m5-5H6\"\n />\n </svg>\n {edgeCount} edge{edgeCount !== 1 ? \"s\" : \"\"}\n </span>\n )}\n </div>\n\n {/* Tags */}\n {template.tags && template.tags.length > 0 && (\n <div className=\"flex flex-wrap gap-1 mb-4\">\n {template.tags.slice(0, 4).map((tag) => (\n <span\n key={tag}\n className=\"px-2 py-0.5 bg-gray-100 dark:bg-zinc-700 text-gray-600 dark:text-zinc-400 rounded text-xs\"\n >\n {tag}\n </span>\n ))}\n </div>\n )}\n\n {/* Action button */}\n <button\n onClick={onSelect}\n className=\"w-full py-2 px-4 bg-teal-600 hover:bg-teal-700 text-white rounded-lg font-medium transition-colors\"\n >\n Use Template\n </button>\n </div>\n </div>\n );\n}\n","import { useState } from \"react\";\nimport { useWorkflowStore, type SavedWorkflow } from \"../stores/workflowStore\";\n\ninterface WorkflowItemProps {\n workflow: SavedWorkflow;\n isActive: boolean;\n onLoad: () => void;\n onDelete: () => void;\n onRename: (name: string) => void;\n onDuplicate: () => void;\n}\n\nfunction WorkflowItem({\n workflow,\n isActive,\n onLoad,\n onDelete,\n onRename,\n onDuplicate,\n}: WorkflowItemProps) {\n const [isEditing, setIsEditing] = useState(false);\n const [editName, setEditName] = useState(workflow.name);\n const [showMenu, setShowMenu] = useState(false);\n\n const handleRename = () => {\n if (editName.trim() && editName !== workflow.name) {\n onRename(editName.trim());\n }\n setIsEditing(false);\n };\n\n const formatDate = (timestamp: number) => {\n const date = new Date(timestamp);\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffMins = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMs / 3600000);\n const diffDays = Math.floor(diffMs / 86400000);\n\n if (diffMins < 1) return \"Just now\";\n if (diffMins < 60) return `${diffMins}m ago`;\n if (diffHours < 24) return `${diffHours}h ago`;\n if (diffDays < 7) return `${diffDays}d ago`;\n return date.toLocaleDateString();\n };\n\n return (\n <div\n className={`group relative p-3 rounded-lg border transition-colors ${\n isActive\n ? \"bg-teal-50 dark:bg-teal-900/20 border-teal-200 dark:border-teal-800\"\n : \"bg-white dark:bg-zinc-800 border-zinc-200 dark:border-zinc-700 hover:border-zinc-300 dark:hover:border-zinc-600\"\n }`}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <button onClick={onLoad} className=\"flex-1 text-left min-w-0\">\n {isEditing ? (\n <input\n type=\"text\"\n value={editName}\n onChange={(e) => setEditName(e.target.value)}\n onBlur={handleRename}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") handleRename();\n if (e.key === \"Escape\") {\n setEditName(workflow.name);\n setIsEditing(false);\n }\n }}\n className=\"w-full px-1 py-0.5 text-sm font-medium bg-white dark:bg-zinc-900 border border-teal-500 rounded focus:outline-none focus:ring-1 focus:ring-teal-500\"\n autoFocus\n onClick={(e) => e.stopPropagation()}\n />\n ) : (\n <span className=\"block text-sm font-medium text-zinc-900 dark:text-zinc-100 truncate\">\n {workflow.name}\n </span>\n )}\n <span className=\"block text-xs text-zinc-500 dark:text-zinc-400 mt-0.5\">\n {workflow.nodes.length} nodes · Updated {formatDate(workflow.updatedAt)}\n </span>\n </button>\n\n <div className=\"relative\">\n <button\n onClick={(e) => {\n e.stopPropagation();\n setShowMenu(!showMenu);\n }}\n className=\"p-1 text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300 rounded opacity-0 group-hover:opacity-100 transition-opacity\"\n >\n <svg className=\"w-4 h-4\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path d=\"M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z\" />\n </svg>\n </button>\n\n {showMenu && (\n <>\n <div className=\"fixed inset-0 z-10\" onClick={() => setShowMenu(false)} />\n <div className=\"absolute right-0 top-full mt-1 w-36 bg-white dark:bg-zinc-800 rounded-lg shadow-lg border border-zinc-200 dark:border-zinc-700 py-1 z-20\">\n <button\n onClick={(e) => {\n e.stopPropagation();\n setIsEditing(true);\n setShowMenu(false);\n }}\n className=\"w-full px-3 py-1.5 text-left text-sm text-zinc-700 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-700\"\n >\n Rename\n </button>\n <button\n onClick={(e) => {\n e.stopPropagation();\n onDuplicate();\n setShowMenu(false);\n }}\n className=\"w-full px-3 py-1.5 text-left text-sm text-zinc-700 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-700\"\n >\n Duplicate\n </button>\n <button\n onClick={(e) => {\n e.stopPropagation();\n if (window.confirm(\"Delete this workflow?\")) {\n onDelete();\n }\n setShowMenu(false);\n }}\n className=\"w-full px-3 py-1.5 text-left text-sm text-red-600 dark:text-red-400 hover:bg-zinc-100 dark:hover:bg-zinc-700\"\n >\n Delete\n </button>\n </div>\n </>\n )}\n </div>\n </div>\n\n {isActive && <span className=\"absolute top-2 right-2 w-2 h-2 bg-teal-500 rounded-full\" />}\n </div>\n );\n}\n\nexport function WorkflowLibrary() {\n const showLibrary = useWorkflowStore((s) => s.showLibrary);\n const toggleLibrary = useWorkflowStore((s) => s.toggleLibrary);\n const savedWorkflows = useWorkflowStore((s) => s.savedWorkflows);\n const activeWorkflowId = useWorkflowStore((s) => s.activeWorkflowId);\n const loadWorkflow = useWorkflowStore((s) => s.loadWorkflow);\n const deleteWorkflow = useWorkflowStore((s) => s.deleteWorkflow);\n const renameWorkflow = useWorkflowStore((s) => s.renameWorkflow);\n const duplicateWorkflow = useWorkflowStore((s) => s.duplicateWorkflow);\n const newWorkflow = useWorkflowStore((s) => s.newWorkflow);\n\n if (!showLibrary) return null;\n\n // Sort by most recently updated\n const sortedWorkflows = [...savedWorkflows].sort((a, b) => b.updatedAt - a.updatedAt);\n\n return (\n <>\n {/* Backdrop */}\n <div className=\"fixed inset-0 bg-black/20 dark:bg-black/40 z-40\" onClick={toggleLibrary} />\n\n {/* Panel */}\n <div className=\"fixed left-0 top-0 bottom-0 w-80 bg-zinc-50 dark:bg-zinc-900 border-r border-zinc-200 dark:border-zinc-700 z-50 flex flex-col shadow-xl\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-zinc-200 dark:border-zinc-700\">\n <h2 className=\"text-lg font-semibold text-zinc-900 dark:text-zinc-100\">My Workflows</h2>\n <button\n onClick={toggleLibrary}\n className=\"p-1 text-zinc-500 hover:text-zinc-700 dark:hover:text-zinc-300 rounded\"\n >\n <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n </div>\n\n {/* New Workflow Button */}\n <div className=\"p-4 border-b border-zinc-200 dark:border-zinc-700\">\n <button\n onClick={() => {\n newWorkflow();\n toggleLibrary();\n window.dispatchEvent(new window.CustomEvent(\"new-workflow-created\"));\n }}\n className=\"w-full flex items-center justify-center gap-2 px-4 py-2 text-sm font-medium text-white bg-teal-600 rounded-lg hover:bg-teal-700 transition-colors\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 4v16m8-8H4\"\n />\n </svg>\n New Workflow\n </button>\n </div>\n\n {/* Workflow List */}\n <div className=\"flex-1 overflow-y-auto p-4\">\n {sortedWorkflows.length === 0 ? (\n <div className=\"text-center py-8\">\n <div className=\"w-12 h-12 mx-auto mb-3 rounded-full bg-zinc-200 dark:bg-zinc-700 flex items-center justify-center\">\n <svg\n className=\"w-6 h-6 text-zinc-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10\"\n />\n </svg>\n </div>\n <p className=\"text-sm text-zinc-500 dark:text-zinc-400\">No saved workflows yet</p>\n <p className=\"text-xs text-zinc-400 dark:text-zinc-500 mt-1\">\n Build a workflow and save it to see it here\n </p>\n </div>\n ) : (\n <div className=\"space-y-2\">\n {sortedWorkflows.map((workflow) => (\n <WorkflowItem\n key={workflow.id}\n workflow={workflow}\n isActive={workflow.id === activeWorkflowId}\n onLoad={() => {\n loadWorkflow(workflow.id);\n toggleLibrary();\n }}\n onDelete={() => deleteWorkflow(workflow.id)}\n onRename={(name) => renameWorkflow(workflow.id, name)}\n onDuplicate={() => duplicateWorkflow(workflow.id)}\n />\n ))}\n </div>\n )}\n </div>\n\n {/* Footer */}\n <div className=\"px-4 py-3 border-t border-zinc-200 dark:border-zinc-700 text-xs text-zinc-500 dark:text-zinc-400\">\n {savedWorkflows.length} workflow{savedWorkflows.length !== 1 ? \"s\" : \"\"} saved locally\n </div>\n </div>\n </>\n );\n}\n","import { useState } from \"react\";\nimport { useSettingsStore } from \"../stores/settingsStore\";\n\n// Provider metadata\nconst CLOUD_PROVIDERS = [\n {\n id: \"openai\" as const,\n name: \"OpenAI\",\n description: \"GPT-4 Vision, GPT-4 Text, DALL-E 3\",\n placeholder: \"sk-...\",\n docsUrl: \"https://platform.openai.com/api-keys\",\n },\n {\n id: \"anthropic\" as const,\n name: \"Anthropic\",\n description: \"Claude Vision, Claude Text\",\n placeholder: \"sk-ant-...\",\n docsUrl: \"https://console.anthropic.com/settings/keys\",\n },\n {\n id: \"gemini\" as const,\n name: \"Google AI\",\n description: \"Gemini Vision, Gemini Text, Gemini Edit\",\n placeholder: \"AIza...\",\n docsUrl: \"https://aistudio.google.com/apikey\",\n },\n {\n id: \"grok\" as const,\n name: \"xAI (Grok)\",\n description: \"Grok Vision, Grok Text\",\n placeholder: \"xai-...\",\n docsUrl: \"https://console.x.ai/\",\n },\n {\n id: \"openrouter\" as const,\n name: \"OpenRouter\",\n description: \"Access multiple models with one API key\",\n placeholder: \"sk-or-...\",\n docsUrl: \"https://openrouter.ai/keys\",\n },\n];\n\nconst LOCAL_PROVIDERS = [\n {\n id: \"ollama\" as const,\n name: \"Ollama\",\n description: \"Local LLaVA Vision, Llama/Mistral Text\",\n defaultUrl: \"http://localhost:11434\",\n docsUrl: \"https://ollama.ai\",\n },\n {\n id: \"lmstudio\" as const,\n name: \"LM Studio\",\n description: \"Local models via OpenAI-compatible API\",\n defaultUrl: \"http://localhost:1234\",\n docsUrl: \"https://lmstudio.ai\",\n },\n];\n\nfunction CloudProviderRow({ provider }: { provider: (typeof CLOUD_PROVIDERS)[number] }) {\n const ai = useSettingsStore((s) => s.ai);\n const setAIProvider = useSettingsStore((s) => s.setAIProvider);\n\n const config = ai[provider.id];\n const isEnabled = config?.enabled ?? false;\n const apiKey = (config as { apiKey?: string })?.apiKey ?? \"\";\n\n const [localKey, setLocalKey] = useState(apiKey);\n const [showKey, setShowKey] = useState(false);\n\n const handleToggle = () => {\n setAIProvider(provider.id, {\n apiKey: localKey,\n enabled: !isEnabled,\n });\n };\n\n const handleKeyChange = (value: string) => {\n setLocalKey(value);\n setAIProvider(provider.id, {\n apiKey: value,\n enabled: isEnabled,\n });\n };\n\n return (\n <div className=\"flex items-start gap-4 p-4 border border-gray-200 dark:border-zinc-700 rounded-lg\">\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium text-gray-900 dark:text-white\">{provider.name}</span>\n <a\n href={provider.docsUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-xs text-teal-600 dark:text-teal-400 hover:underline\"\n >\n Get API key\n </a>\n </div>\n <p className=\"text-sm text-gray-500 dark:text-zinc-400 mt-0.5\">{provider.description}</p>\n <div className=\"mt-2 flex items-center gap-2\">\n <div className=\"relative flex-1\">\n <input\n type={showKey ? \"text\" : \"password\"}\n value={localKey}\n onChange={(e) => handleKeyChange(e.target.value)}\n placeholder={provider.placeholder}\n className=\"w-full px-3 py-1.5 text-sm border border-gray-300 dark:border-zinc-600 rounded bg-white dark:bg-zinc-800 text-gray-900 dark:text-white placeholder-gray-400 dark:placeholder-zinc-500\"\n />\n <button\n type=\"button\"\n onClick={() => setShowKey(!showKey)}\n className=\"absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-zinc-300\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n {showKey ? (\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21\"\n />\n ) : (\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z\"\n />\n )}\n </svg>\n </button>\n </div>\n </div>\n </div>\n <div className=\"flex items-center\">\n <button\n onClick={handleToggle}\n className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${\n isEnabled ? \"bg-teal-600\" : \"bg-gray-300 dark:bg-zinc-600\"\n }`}\n >\n <span\n className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${\n isEnabled ? \"translate-x-6\" : \"translate-x-1\"\n }`}\n />\n </button>\n </div>\n </div>\n );\n}\n\nfunction LocalProviderRow({ provider }: { provider: (typeof LOCAL_PROVIDERS)[number] }) {\n const ai = useSettingsStore((s) => s.ai);\n const setAIProvider = useSettingsStore((s) => s.setAIProvider);\n\n const config = ai[provider.id];\n const isEnabled = config?.enabled ?? false;\n const baseUrl = (config as { baseUrl?: string })?.baseUrl ?? provider.defaultUrl;\n\n const [localUrl, setLocalUrl] = useState(baseUrl);\n\n const handleToggle = () => {\n setAIProvider(provider.id, {\n baseUrl: localUrl,\n enabled: !isEnabled,\n });\n };\n\n const handleUrlChange = (value: string) => {\n setLocalUrl(value);\n setAIProvider(provider.id, {\n baseUrl: value,\n enabled: isEnabled,\n });\n };\n\n return (\n <div className=\"flex items-start gap-4 p-4 border border-gray-200 dark:border-zinc-700 rounded-lg\">\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium text-gray-900 dark:text-white\">{provider.name}</span>\n <a\n href={provider.docsUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-xs text-teal-600 dark:text-teal-400 hover:underline\"\n >\n Docs\n </a>\n <span className=\"text-xs bg-green-100 dark:bg-green-900/50 text-green-700 dark:text-green-400 px-1.5 py-0.5 rounded\">\n Local\n </span>\n </div>\n <p className=\"text-sm text-gray-500 dark:text-zinc-400 mt-0.5\">{provider.description}</p>\n <div className=\"mt-2\">\n <input\n type=\"text\"\n value={localUrl}\n onChange={(e) => handleUrlChange(e.target.value)}\n placeholder={provider.defaultUrl}\n className=\"w-full px-3 py-1.5 text-sm border border-gray-300 dark:border-zinc-600 rounded bg-white dark:bg-zinc-800 text-gray-900 dark:text-white placeholder-gray-400 dark:placeholder-zinc-500\"\n />\n </div>\n </div>\n <div className=\"flex items-center\">\n <button\n onClick={handleToggle}\n className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${\n isEnabled ? \"bg-teal-600\" : \"bg-gray-300 dark:bg-zinc-600\"\n }`}\n >\n <span\n className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${\n isEnabled ? \"translate-x-6\" : \"translate-x-1\"\n }`}\n />\n </button>\n </div>\n </div>\n );\n}\n\nexport function AISettings() {\n const showSettings = useSettingsStore((s) => s.showSettings);\n const closeSettings = useSettingsStore((s) => s.closeSettings);\n\n if (!showSettings) return null;\n\n return (\n <div className=\"fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50\">\n <div className=\"bg-white dark:bg-zinc-800 rounded-lg shadow-xl max-w-xl w-full mx-4 max-h-[85vh] flex flex-col\">\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-gray-200 dark:border-zinc-700\">\n <div>\n <h2 className=\"text-lg font-semibold text-gray-900 dark:text-white\">\n AI Provider Settings\n </h2>\n <p className=\"text-sm text-gray-500 dark:text-zinc-400 mt-0.5\">\n Configure your AI providers for vision and text generation\n </p>\n </div>\n <button\n onClick={closeSettings}\n className=\"text-gray-500 dark:text-zinc-400 hover:text-gray-700 dark:hover:text-zinc-200\"\n >\n <svg className=\"h-6 w-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n </div>\n\n <div className=\"flex-1 overflow-y-auto p-6 space-y-6\">\n {/* Cloud Providers */}\n <section>\n <h3 className=\"text-sm font-medium text-gray-700 dark:text-zinc-300 mb-3\">\n Cloud Providers\n </h3>\n <div className=\"space-y-3\">\n {CLOUD_PROVIDERS.map((provider) => (\n <CloudProviderRow key={provider.id} provider={provider} />\n ))}\n </div>\n </section>\n\n {/* Local Providers */}\n <section>\n <h3 className=\"text-sm font-medium text-gray-700 dark:text-zinc-300 mb-3\">\n Local Providers\n </h3>\n <div className=\"space-y-3\">\n {LOCAL_PROVIDERS.map((provider) => (\n <LocalProviderRow key={provider.id} provider={provider} />\n ))}\n </div>\n </section>\n\n {/* Privacy Notice */}\n <div className=\"bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4\">\n <div className=\"flex items-start gap-3\">\n <svg\n className=\"w-5 h-5 text-blue-600 dark:text-blue-400 mt-0.5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z\"\n />\n </svg>\n <div>\n <p className=\"text-sm font-medium text-blue-900 dark:text-blue-300\">\n Your keys stay local\n </p>\n <p className=\"text-sm text-blue-700 dark:text-blue-400 mt-1\">\n API keys are stored in your browser only and sent directly to providers. They\n never pass through our servers.\n </p>\n </div>\n </div>\n </div>\n </div>\n\n <div className=\"flex justify-end px-6 py-4 border-t border-gray-200 dark:border-zinc-700\">\n <button\n onClick={closeSettings}\n className=\"px-4 py-2 text-sm font-medium text-white bg-teal-600 rounded-md hover:bg-teal-700\"\n >\n Done\n </button>\n </div>\n </div>\n </div>\n );\n}\n","import { useState, useRef, useEffect, useCallback } from \"react\";\nimport type {\n GenerateWorkflowMessage,\n GeneratedWorkflowData,\n GenerateStatusReason,\n GenerationPhase,\n GenerationSSEEvent,\n} from \"@teamflojo/floimg-studio-shared\";\nimport { getGenerateStatus } from \"../api/client\";\nimport { createSSEConnection, type SSEConnection } from \"../api/sse\";\n\n// Module-level connection reference for cancellation\n// (Not in component state because SSEConnection is not serializable)\nlet activeGenerationConnection: SSEConnection | null = null;\n\ninterface AIChatProps {\n isOpen: boolean;\n onClose: () => void;\n onApplyWorkflow: (workflow: GeneratedWorkflowData) => void;\n}\n\nexport function AIChat({ isOpen, onClose, onApplyWorkflow }: AIChatProps) {\n const [messages, setMessages] = useState<GenerateWorkflowMessage[]>([]);\n const [input, setInput] = useState(\"\");\n const [isLoading, setIsLoading] = useState(false);\n const [generationPhase, setGenerationPhase] = useState<GenerationPhase | null>(null);\n const [generationMessage, setGenerationMessage] = useState(\"\");\n const [error, setError] = useState<string | null>(null);\n const [isAvailable, setIsAvailable] = useState<boolean | null>(null);\n const [statusMessage, setStatusMessage] = useState(\"\");\n const [statusReason, setStatusReason] = useState<GenerateStatusReason | undefined>();\n const [isCloudDeployment, setIsCloudDeployment] = useState(false);\n const [supportUrl, setSupportUrl] = useState<string | undefined>();\n const messagesEndRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLTextAreaElement>(null);\n\n // Check if generation is available on mount\n useEffect(() => {\n if (isOpen && isAvailable === null) {\n getGenerateStatus()\n .then((status) => {\n setIsAvailable(status.available);\n setStatusMessage(status.message);\n setStatusReason(status.reason);\n setIsCloudDeployment(status.isCloudDeployment ?? false);\n setSupportUrl(status.supportUrl);\n })\n .catch(() => {\n setIsAvailable(false);\n setStatusMessage(\"Failed to check AI availability\");\n setStatusReason(\"service_unavailable\");\n });\n }\n }, [isOpen, isAvailable]);\n\n // Focus input when opened\n useEffect(() => {\n if (isOpen && inputRef.current) {\n inputRef.current.focus();\n }\n }, [isOpen]);\n\n // Scroll to bottom on new messages\n useEffect(() => {\n messagesEndRef.current?.scrollIntoView({ behavior: \"smooth\" });\n }, [messages]);\n\n const handleSubmit = useCallback(() => {\n if (!input.trim() || isLoading) return;\n\n const userMessage: GenerateWorkflowMessage = {\n role: \"user\",\n content: input.trim(),\n timestamp: Date.now(),\n };\n\n setMessages((prev) => [...prev, userMessage]);\n setInput(\"\");\n setIsLoading(true);\n setError(null);\n setGenerationPhase(null);\n setGenerationMessage(\"\");\n\n let receivedWorkflow: GeneratedWorkflowData | undefined;\n\n activeGenerationConnection = createSSEConnection<GenerationSSEEvent>(\n \"/api/generate/workflow/stream\",\n { prompt: userMessage.content, history: messages },\n {\n onMessage: (event) => {\n if (event.type === \"generation.started\") {\n // Started - no visible change needed\n }\n\n if (event.type === \"generation.progress\") {\n setGenerationPhase(event.data.phase);\n setGenerationMessage(event.data.message);\n }\n\n if (event.type === \"generation.completed\") {\n receivedWorkflow = event.data;\n }\n\n if (event.type === \"generation.error\") {\n setError(event.data.error);\n }\n },\n onError: (err) => {\n activeGenerationConnection = null;\n setError(err.message || \"Failed to generate workflow\");\n setIsLoading(false);\n setGenerationPhase(null);\n },\n onClose: () => {\n activeGenerationConnection = null;\n // Stream completed - add the assistant message\n const assistantMessage: GenerateWorkflowMessage = {\n role: \"assistant\",\n content: receivedWorkflow\n ? \"I've created a workflow based on your description. Click 'Apply to Canvas' to use it.\"\n : \"I couldn't generate a workflow. Please try a different description.\",\n workflow: receivedWorkflow,\n timestamp: Date.now(),\n };\n\n setMessages((prev) => [...prev, assistantMessage]);\n setIsLoading(false);\n setGenerationPhase(null);\n setGenerationMessage(\"\");\n },\n }\n );\n }, [input, isLoading, messages]);\n\n const handleCancelGeneration = useCallback(() => {\n if (activeGenerationConnection) {\n activeGenerationConnection.abort();\n activeGenerationConnection = null;\n }\n setIsLoading(false);\n setGenerationPhase(null);\n setGenerationMessage(\"\");\n }, []);\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n handleSubmit();\n }\n };\n\n const handleApply = (workflow: GeneratedWorkflowData) => {\n onApplyWorkflow(workflow);\n onClose();\n };\n\n const handleNewChat = () => {\n setMessages([]);\n setError(null);\n };\n\n if (!isOpen) return null;\n\n return (\n <div className=\"fixed inset-0 bg-black/50 flex items-center justify-center z-50\">\n <div className=\"bg-white dark:bg-zinc-800 rounded-lg shadow-xl w-full max-w-2xl mx-4 h-[80vh] flex flex-col\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-gray-200 dark:border-zinc-700\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex items-center gap-2\">\n <svg\n className=\"h-5 w-5 text-teal-600\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z\"\n />\n </svg>\n <h3 className=\"text-lg font-semibold text-gray-900 dark:text-white\">\n AI Workflow Generator\n </h3>\n </div>\n <span className=\"text-xs bg-teal-100 dark:bg-teal-900 text-teal-700 dark:text-teal-300 px-2 py-0.5 rounded\">\n Gemini 3 Pro\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n {messages.length > 0 && (\n <button\n onClick={handleNewChat}\n className=\"p-2 text-gray-500 dark:text-zinc-400 hover:text-gray-700 dark:hover:text-zinc-200 hover:bg-gray-100 dark:hover:bg-zinc-700 rounded\"\n title=\"New Chat\"\n >\n <svg className=\"h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 4v16m8-8H4\"\n />\n </svg>\n </button>\n )}\n <button\n onClick={onClose}\n className=\"p-2 text-gray-500 dark:text-zinc-400 hover:text-gray-700 dark:hover:text-zinc-200 hover:bg-gray-100 dark:hover:bg-zinc-700 rounded\"\n >\n <svg className=\"h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n </div>\n </div>\n\n {/* Messages */}\n <div className=\"flex-1 overflow-auto p-4 space-y-4\">\n {isAvailable === false && (\n <div className=\"bg-amber-50 dark:bg-amber-900/30 border border-amber-200 dark:border-amber-800 rounded-lg p-4\">\n <div className=\"flex items-start gap-3\">\n {/* Icon varies by reason */}\n {statusReason === \"tier_limit\" ? (\n <svg\n className=\"h-5 w-5 text-amber-600 dark:text-amber-400 mt-0.5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z\"\n />\n </svg>\n ) : (\n <svg\n className=\"h-5 w-5 text-amber-600 dark:text-amber-400 mt-0.5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n )}\n <div>\n <p className=\"font-medium text-amber-800 dark:text-amber-200\">\n {statusReason === \"tier_limit\"\n ? \"AI Workflow Generation Not Available\"\n : \"AI Generation Not Available\"}\n </p>\n <p className=\"text-sm text-amber-700 dark:text-amber-300 mt-1\">{statusMessage}</p>\n\n {/* Context-aware actions */}\n <div className=\"flex flex-col sm:flex-row gap-2 mt-3\">\n {statusReason === \"tier_limit\" && (\n <a\n href=\"/pricing\"\n className=\"text-sm font-medium text-teal-600 hover:text-teal-700 dark:text-teal-400 dark:hover:text-teal-300\"\n >\n View Plans\n </a>\n )}\n {statusReason === \"service_unavailable\" && supportUrl && (\n <a\n href={supportUrl}\n className=\"text-sm font-medium text-amber-700 hover:text-amber-800 dark:text-amber-400 dark:hover:text-amber-300\"\n >\n Contact Support\n </a>\n )}\n {statusReason === \"not_configured\" && !isCloudDeployment && (\n <a\n href=\"https://floimg.com/docs/studio/ai-workflows\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm font-medium text-teal-600 hover:text-teal-700 dark:text-teal-400 dark:hover:text-teal-300\"\n >\n View Setup Guide\n </a>\n )}\n </div>\n </div>\n </div>\n </div>\n )}\n\n {messages.length === 0 && isAvailable !== false && (\n <div className=\"text-center py-8\">\n <div className=\"inline-flex items-center justify-center w-16 h-16 bg-teal-100 dark:bg-teal-900/50 rounded-full mb-4\">\n <svg\n className=\"h-8 w-8 text-teal-600 dark:text-teal-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z\"\n />\n </svg>\n </div>\n <h4 className=\"text-lg font-medium text-gray-900 dark:text-white mb-2\">\n Describe your workflow\n </h4>\n <p className=\"text-sm text-gray-500 dark:text-zinc-400 max-w-md mx-auto\">\n Tell me what you want to create and I&apos;ll generate a workflow for you. For\n example:\n </p>\n <div className=\"mt-4 space-y-2\">\n {[\n \"Generate an image of a sunset and resize it to 800x600\",\n \"Use Gemini text to generate 3 creative image prompts about space exploration, then generate images from each prompt\",\n \"Generate an image with Gemini, then use it as a reference to create a variation with different lighting\",\n \"Create a product mockup: generate a minimalist logo, then composite it onto a t-shirt image\",\n \"Build an AI art pipeline: generate a base image, apply artistic style transfer, then upscale to 4K\",\n ].map((example, i) => (\n <button\n key={i}\n onClick={() => setInput(example)}\n className=\"block w-full text-left text-sm px-4 py-2 bg-gray-100 dark:bg-zinc-700 hover:bg-gray-200 dark:hover:bg-zinc-600 rounded-lg text-gray-700 dark:text-zinc-300 transition-colors\"\n >\n &quot;{example}&quot;\n </button>\n ))}\n </div>\n </div>\n )}\n\n {messages.map((msg, idx) => (\n <div\n key={idx}\n className={`flex ${msg.role === \"user\" ? \"justify-end\" : \"justify-start\"}`}\n >\n <div\n className={`max-w-[80%] rounded-lg px-4 py-3 ${\n msg.role === \"user\"\n ? \"bg-teal-600 text-white\"\n : \"bg-gray-100 dark:bg-zinc-700 text-gray-900 dark:text-white\"\n }`}\n >\n <p className=\"text-sm whitespace-pre-wrap\">{msg.content}</p>\n\n {/* Workflow preview for assistant messages */}\n {msg.role === \"assistant\" && msg.workflow && (\n <div className=\"mt-3 pt-3 border-t border-gray-200 dark:border-zinc-600\">\n <div className=\"flex items-center justify-between mb-2\">\n <span className=\"text-xs font-medium text-gray-500 dark:text-zinc-400\">\n Generated Workflow\n </span>\n <button\n onClick={() => handleApply(msg.workflow!)}\n className=\"text-xs px-3 py-1 bg-teal-600 hover:bg-teal-700 text-white rounded transition-colors\"\n >\n Apply to Canvas\n </button>\n </div>\n <div className=\"bg-white dark:bg-zinc-800 rounded p-2 text-xs\">\n <div className=\"space-y-1\">\n {msg.workflow.nodes.map((node, nodeIdx) => (\n <div\n key={nodeIdx}\n className=\"flex items-center gap-2 text-gray-600 dark:text-zinc-300\"\n >\n <span className=\"font-mono bg-gray-100 dark:bg-zinc-700 px-1.5 py-0.5 rounded\">\n {node.nodeType.split(\":\").pop()}\n </span>\n {node.label && <span className=\"text-gray-400\">({node.label})</span>}\n </div>\n ))}\n {msg.workflow.edges.length > 0 && (\n <div className=\"text-gray-400 dark:text-zinc-500 pt-1\">\n {msg.workflow.edges.length} connection\n {msg.workflow.edges.length !== 1 ? \"s\" : \"\"}\n </div>\n )}\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n ))}\n\n {isLoading && (\n <div className=\"flex justify-start\">\n <div className=\"bg-gray-100 dark:bg-zinc-700 rounded-lg px-4 py-3\">\n <div className=\"flex items-center gap-3\">\n {/* Phase indicator */}\n <div className=\"flex items-center gap-2\">\n {generationPhase === \"analyzing\" && (\n <svg\n className=\"h-4 w-4 text-teal-500 animate-pulse\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"\n />\n </svg>\n )}\n {generationPhase === \"selecting_nodes\" && (\n <svg\n className=\"h-4 w-4 text-teal-500 animate-pulse\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z\"\n />\n </svg>\n )}\n {generationPhase === \"generating\" && (\n <svg\n className=\"h-4 w-4 text-teal-500 animate-spin\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"\n />\n </svg>\n )}\n {generationPhase === \"validating\" && (\n <svg\n className=\"h-4 w-4 text-teal-500 animate-pulse\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n )}\n {!generationPhase && (\n <div className=\"flex space-x-1\">\n <div className=\"w-2 h-2 bg-teal-400 rounded-full animate-bounce\" />\n <div\n className=\"w-2 h-2 bg-teal-400 rounded-full animate-bounce\"\n style={{ animationDelay: \"0.1s\" }}\n />\n <div\n className=\"w-2 h-2 bg-teal-400 rounded-full animate-bounce\"\n style={{ animationDelay: \"0.2s\" }}\n />\n </div>\n )}\n </div>\n <span className=\"text-sm text-gray-600 dark:text-zinc-300\">\n {generationMessage || \"Connecting...\"}\n </span>\n {/* Cancel button */}\n <button\n onClick={handleCancelGeneration}\n className=\"ml-2 px-2 py-1 text-xs font-medium text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/30 rounded transition-colors\"\n title=\"Cancel generation\"\n >\n Cancel\n </button>\n </div>\n {/* Progress steps */}\n {generationPhase && (\n <div className=\"flex items-center gap-1 mt-2\">\n <div\n className={`h-1 w-8 rounded-full ${generationPhase === \"analyzing\" || generationPhase === \"selecting_nodes\" || generationPhase === \"generating\" || generationPhase === \"validating\" ? \"bg-teal-500\" : \"bg-gray-300 dark:bg-zinc-600\"}`}\n />\n <div\n className={`h-1 w-8 rounded-full ${generationPhase === \"selecting_nodes\" || generationPhase === \"generating\" || generationPhase === \"validating\" ? \"bg-teal-500\" : \"bg-gray-300 dark:bg-zinc-600\"}`}\n />\n <div\n className={`h-1 w-8 rounded-full ${generationPhase === \"generating\" || generationPhase === \"validating\" ? \"bg-teal-500\" : \"bg-gray-300 dark:bg-zinc-600\"}`}\n />\n <div\n className={`h-1 w-8 rounded-full ${generationPhase === \"validating\" ? \"bg-teal-500\" : \"bg-gray-300 dark:bg-zinc-600\"}`}\n />\n </div>\n )}\n </div>\n </div>\n )}\n\n {error && (\n <div className=\"bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 rounded-lg p-3\">\n <p className=\"text-sm text-red-700 dark:text-red-300\">{error}</p>\n </div>\n )}\n\n <div ref={messagesEndRef} />\n </div>\n\n {/* Input */}\n <div className=\"border-t border-gray-200 dark:border-zinc-700 p-4\">\n <div className=\"flex gap-2\">\n <textarea\n ref={inputRef}\n value={input}\n onChange={(e) => setInput(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={\n isAvailable === false\n ? \"AI generation not available\"\n : \"Describe what workflow you want to create...\"\n }\n disabled={isLoading || isAvailable === false}\n rows={2}\n className=\"flex-1 resize-none rounded-lg border border-gray-300 dark:border-zinc-600 bg-white dark:bg-zinc-900 px-4 py-2 text-sm text-gray-900 dark:text-white placeholder-gray-400 dark:placeholder-zinc-500 focus:border-teal-500 focus:outline-none focus:ring-1 focus:ring-teal-500 disabled:opacity-50 disabled:cursor-not-allowed\"\n />\n <button\n onClick={handleSubmit}\n disabled={!input.trim() || isLoading || isAvailable === false}\n className=\"self-end px-4 py-2 bg-teal-600 hover:bg-teal-700 disabled:opacity-50 disabled:cursor-not-allowed text-white rounded-lg transition-colors\"\n >\n <svg className=\"h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 19l9 2-9-18-9 18 9-2zm0 0v-8\"\n />\n </svg>\n </button>\n </div>\n <p className=\"text-xs text-gray-400 dark:text-zinc-500 mt-2\">\n Press Enter to send, Shift+Enter for new line\n </p>\n </div>\n </div>\n </div>\n );\n}\n","import { useState, useCallback } from \"react\";\n\n// Size/depth limits to prevent browser freeze on large outputs\nconst MAX_JSON_DEPTH = 20;\nconst MAX_ARRAY_ITEMS = 500;\nconst LARGE_OUTPUT_THRESHOLD = 100_000; // 100KB\n\ninterface DataOutput {\n dataType: \"text\" | \"json\";\n content: string;\n parsed?: Record<string, unknown>;\n}\n\ninterface OutputInspectorProps {\n isOpen: boolean;\n onClose: () => void;\n nodeId: string;\n nodeLabel: string;\n output: DataOutput;\n}\n\nexport function OutputInspector({ isOpen, onClose, nodeLabel, output }: OutputInspectorProps) {\n const [viewMode, setViewMode] = useState<\"formatted\" | \"raw\">(\"formatted\");\n const [copied, setCopied] = useState(false);\n\n const handleCopy = useCallback(() => {\n const textToCopy =\n viewMode === \"formatted\" && output.parsed\n ? JSON.stringify(output.parsed, null, 2)\n : output.content;\n\n navigator.clipboard.writeText(textToCopy).then(() => {\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n });\n }, [viewMode, output]);\n\n if (!isOpen) return null;\n\n const hasFormattedView = output.dataType === \"json\" && output.parsed;\n\n return (\n <div className=\"fixed inset-0 bg-black/50 flex items-center justify-center z-50\">\n <div className=\"bg-white dark:bg-zinc-800 rounded-lg shadow-xl w-full max-w-3xl mx-4 max-h-[85vh] flex flex-col\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-gray-200 dark:border-zinc-700\">\n <div className=\"flex items-center gap-3\">\n <svg\n className=\"h-5 w-5 text-pink-500\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"\n />\n </svg>\n <div>\n <h3 className=\"text-lg font-semibold text-gray-900 dark:text-white\">\n {nodeLabel} Output\n </h3>\n <span className=\"text-xs text-gray-500 dark:text-zinc-400\">\n {output.dataType === \"json\" ? \"Structured JSON\" : \"Text\"}\n </span>\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n {/* View mode toggle */}\n {hasFormattedView && (\n <div className=\"flex bg-gray-100 dark:bg-zinc-700 rounded-lg p-0.5\">\n <button\n onClick={() => setViewMode(\"formatted\")}\n className={`px-3 py-1 text-sm rounded-md transition-colors ${\n viewMode === \"formatted\"\n ? \"bg-white dark:bg-zinc-600 text-gray-900 dark:text-white shadow-sm\"\n : \"text-gray-600 dark:text-zinc-400 hover:text-gray-900 dark:hover:text-white\"\n }`}\n >\n Formatted\n </button>\n <button\n onClick={() => setViewMode(\"raw\")}\n className={`px-3 py-1 text-sm rounded-md transition-colors ${\n viewMode === \"raw\"\n ? \"bg-white dark:bg-zinc-600 text-gray-900 dark:text-white shadow-sm\"\n : \"text-gray-600 dark:text-zinc-400 hover:text-gray-900 dark:hover:text-white\"\n }`}\n >\n Raw\n </button>\n </div>\n )}\n {/* Close button */}\n <button\n onClick={onClose}\n className=\"p-2 text-gray-500 dark:text-zinc-400 hover:text-gray-700 dark:hover:text-zinc-200 hover:bg-gray-100 dark:hover:bg-zinc-700 rounded\"\n >\n <svg className=\"h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n </div>\n </div>\n\n {/* Large output warning */}\n {output.content.length > LARGE_OUTPUT_THRESHOLD && (\n <div className=\"px-4 py-2 bg-amber-50 dark:bg-amber-900/20 border-b border-amber-200 dark:border-amber-800 flex items-center gap-2\">\n <svg\n className=\"h-4 w-4 text-amber-600 dark:text-amber-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n <span className=\"text-sm text-amber-700 dark:text-amber-300\">\n Large output ({Math.round(output.content.length / 1024)}KB) - rendering may be slow\n </span>\n </div>\n )}\n\n {/* Content */}\n <div className=\"flex-1 overflow-auto p-4\">\n {viewMode === \"formatted\" && hasFormattedView ? (\n <JsonTree data={output.parsed!} />\n ) : (\n <pre className=\"whitespace-pre-wrap font-mono text-sm text-gray-800 dark:text-zinc-200 bg-gray-50 dark:bg-zinc-900 rounded-lg p-4 overflow-auto\">\n {output.content}\n </pre>\n )}\n </div>\n\n {/* Footer */}\n <div className=\"flex items-center justify-between px-4 py-3 border-t border-gray-200 dark:border-zinc-700\">\n <span className=\"text-xs text-gray-500 dark:text-zinc-400\">\n {output.content.length.toLocaleString()} characters\n </span>\n <button\n onClick={handleCopy}\n className=\"flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-teal-600 dark:text-teal-400 hover:bg-teal-50 dark:hover:bg-teal-900/30 rounded-lg transition-colors\"\n >\n {copied ? (\n <>\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M5 13l4 4L19 7\"\n />\n </svg>\n Copied!\n </>\n ) : (\n <>\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\"\n />\n </svg>\n Copy to Clipboard\n </>\n )}\n </button>\n </div>\n </div>\n </div>\n );\n}\n\n// Simple JSON tree viewer component with depth/size limits\nfunction JsonTree({ data }: { data: Record<string, unknown> }) {\n return (\n <div className=\"font-mono text-sm\">\n <JsonNode value={data} depth={0} maxDepth={MAX_JSON_DEPTH} />\n </div>\n );\n}\n\ninterface JsonNodeProps {\n value: unknown;\n depth: number;\n keyName?: string;\n maxDepth: number;\n}\n\nfunction JsonNode({ value, depth, keyName, maxDepth }: JsonNodeProps) {\n const indent = depth * 16;\n\n // Check depth limit\n if (depth >= maxDepth) {\n return (\n <div style={{ marginLeft: indent }} className=\"py-0.5\">\n {keyName && <span className=\"text-pink-600 dark:text-pink-400\">&quot;{keyName}&quot;</span>}\n {keyName && <span className=\"text-gray-600 dark:text-zinc-400\">: </span>}\n <span className=\"text-zinc-500 italic\">[max depth reached]</span>\n </div>\n );\n }\n\n if (value === null) {\n return (\n <div style={{ marginLeft: indent }} className=\"py-0.5\">\n {keyName && <span className=\"text-pink-600 dark:text-pink-400\">&quot;{keyName}&quot;</span>}\n {keyName && <span className=\"text-gray-600 dark:text-zinc-400\">: </span>}\n <span className=\"text-gray-500 dark:text-zinc-500\">null</span>\n </div>\n );\n }\n\n if (typeof value === \"boolean\") {\n return (\n <div style={{ marginLeft: indent }} className=\"py-0.5\">\n {keyName && <span className=\"text-pink-600 dark:text-pink-400\">&quot;{keyName}&quot;</span>}\n {keyName && <span className=\"text-gray-600 dark:text-zinc-400\">: </span>}\n <span className=\"text-blue-600 dark:text-blue-400\">{value.toString()}</span>\n </div>\n );\n }\n\n if (typeof value === \"number\") {\n return (\n <div style={{ marginLeft: indent }} className=\"py-0.5\">\n {keyName && <span className=\"text-pink-600 dark:text-pink-400\">&quot;{keyName}&quot;</span>}\n {keyName && <span className=\"text-gray-600 dark:text-zinc-400\">: </span>}\n <span className=\"text-green-600 dark:text-green-400\">{value}</span>\n </div>\n );\n }\n\n if (typeof value === \"string\") {\n // Truncate long strings in the tree view\n const displayValue = value.length > 100 ? value.slice(0, 100) + \"...\" : value;\n return (\n <div style={{ marginLeft: indent }} className=\"py-0.5\">\n {keyName && <span className=\"text-pink-600 dark:text-pink-400\">&quot;{keyName}&quot;</span>}\n {keyName && <span className=\"text-gray-600 dark:text-zinc-400\">: </span>}\n <span className=\"text-amber-600 dark:text-amber-400\">&quot;{displayValue}&quot;</span>\n </div>\n );\n }\n\n if (Array.isArray(value)) {\n const itemsToRender = value.slice(0, MAX_ARRAY_ITEMS);\n const hiddenCount = value.length - itemsToRender.length;\n\n return (\n <div style={{ marginLeft: indent }}>\n {keyName && (\n <div className=\"py-0.5\">\n <span className=\"text-pink-600 dark:text-pink-400\">&quot;{keyName}&quot;</span>\n <span className=\"text-gray-600 dark:text-zinc-400\">: </span>\n <span className=\"text-gray-500 dark:text-zinc-500\">[{value.length} items]</span>\n </div>\n )}\n {!keyName && <span className=\"text-gray-500 dark:text-zinc-500 py-0.5 block\">[</span>}\n {itemsToRender.map((item, index) => (\n <JsonNode key={index} value={item} depth={depth + 1} maxDepth={maxDepth} />\n ))}\n {hiddenCount > 0 && (\n <div style={{ marginLeft: (depth + 1) * 16 }} className=\"py-0.5 text-zinc-500 italic\">\n ...and {hiddenCount} more items\n </div>\n )}\n {!keyName && <span className=\"text-gray-500 dark:text-zinc-500 py-0.5 block\">]</span>}\n </div>\n );\n }\n\n if (typeof value === \"object\") {\n const entries = Object.entries(value);\n return (\n <div style={{ marginLeft: indent }}>\n {keyName && (\n <div className=\"py-0.5\">\n <span className=\"text-pink-600 dark:text-pink-400\">&quot;{keyName}&quot;</span>\n <span className=\"text-gray-600 dark:text-zinc-400\">: </span>\n <span className=\"text-gray-500 dark:text-zinc-500\">{\"{\"}</span>\n </div>\n )}\n {!keyName && <span className=\"text-gray-500 dark:text-zinc-500 py-0.5 block\">{\"{\"}</span>}\n {entries.map(([key, val]) => (\n <JsonNode key={key} value={val} depth={depth + 1} keyName={key} maxDepth={maxDepth} />\n ))}\n <div style={{ marginLeft: keyName ? 0 : indent }} className=\"py-0.5\">\n <span className=\"text-gray-500 dark:text-zinc-500\">{\"}\"}</span>\n </div>\n </div>\n );\n }\n\n return null;\n}\n","import { useState, useCallback, useEffect, DragEvent } from \"react\";\nimport { ReactFlowProvider, useReactFlow } from \"reactflow\";\nimport { WorkflowEditor } from \"./editor/WorkflowEditor\";\nimport { NodePalette } from \"./components/NodePalette\";\nimport { NodeInspector } from \"./components/NodeInspector\";\nimport { Toolbar } from \"./components/Toolbar\";\nimport { Gallery } from \"./components/Gallery\";\nimport { TemplateGallery } from \"./components/TemplateGallery\";\nimport { WorkflowLibrary } from \"./components/WorkflowLibrary\";\nimport { AISettings } from \"./components/AISettings\";\nimport { AIChat } from \"./components/AIChat\";\nimport { OutputInspector } from \"./components/OutputInspector\";\nimport { useWorkflowStore } from \"./stores/workflowStore\";\nimport { resolveTemplate } from \"@teamflojo/floimg-templates\";\nimport type { NodeDefinition, GeneratedWorkflowData } from \"@teamflojo/floimg-studio-shared\";\n\n// EditorDropZone - handles node drops with correct coordinate conversion\n// Must be inside ReactFlowProvider to access useReactFlow hook\nfunction EditorDropZone() {\n const { screenToFlowPosition } = useReactFlow();\n const addNode = useWorkflowStore((s) => s.addNode);\n\n const handleDrop = useCallback(\n (event: DragEvent<HTMLDivElement>) => {\n event.preventDefault();\n\n const data = event.dataTransfer.getData(\"application/json\");\n if (!data) return;\n\n try {\n const definition: NodeDefinition = JSON.parse(data);\n\n // Use screenToFlowPosition to correctly convert screen coordinates\n // to flow coordinates, accounting for zoom and pan\n const position = screenToFlowPosition({\n x: event.clientX,\n y: event.clientY,\n });\n\n addNode(definition, position);\n } catch (e) {\n console.error(\"Failed to parse dropped node:\", e);\n }\n },\n [addNode, screenToFlowPosition]\n );\n\n const handleDragOver = useCallback((event: DragEvent<HTMLDivElement>) => {\n event.preventDefault();\n event.dataTransfer.dropEffect = \"move\";\n }, []);\n\n return (\n <div className=\"flex-1\" onDrop={handleDrop} onDragOver={handleDragOver}>\n <WorkflowEditor />\n </div>\n );\n}\n\ntype TabType = \"editor\" | \"gallery\" | \"templates\";\n\nfunction App() {\n const [activeTab, setActiveTab] = useState<TabType>(\"editor\");\n const [showAIChat, setShowAIChat] = useState(false);\n const loadTemplate = useWorkflowStore((s) => s.loadTemplate);\n const loadGeneratedWorkflow = useWorkflowStore((s) => s.loadGeneratedWorkflow);\n\n // Output inspector state\n const inspectedNodeId = useWorkflowStore((s) => s.inspectedNodeId);\n const executionDataOutputs = useWorkflowStore((s) => s.execution.dataOutputs);\n const closeOutputInspector = useWorkflowStore((s) => s.closeOutputInspector);\n const nodes = useWorkflowStore((s) => s.nodes);\n\n // Get inspected node info\n const inspectedNode = inspectedNodeId ? nodes.find((n) => n.id === inspectedNodeId) : null;\n const inspectedOutput = inspectedNodeId ? executionDataOutputs[inspectedNodeId] : null;\n\n // Handle ?template=<id> URL parameter\n useEffect(() => {\n const params = new URLSearchParams(window.location.search);\n const templateId = params.get(\"template\");\n\n if (templateId) {\n // resolveTemplate handles both canonical IDs and legacy IDs\n const template = resolveTemplate(templateId);\n if (template) {\n loadTemplate(template);\n // Clean up URL without reload\n window.history.replaceState({}, \"\", window.location.pathname);\n }\n }\n }, [loadTemplate]);\n\n // Listen for workflow-loaded event (from Gallery)\n useEffect(() => {\n const handleWorkflowLoaded = () => {\n setActiveTab(\"editor\");\n };\n window.addEventListener(\"workflow-loaded\", handleWorkflowLoaded);\n return () => {\n window.removeEventListener(\"workflow-loaded\", handleWorkflowLoaded);\n };\n }, []);\n\n // Handler for template selection (from TemplateGallery)\n const handleTemplateSelect = useCallback(\n (templateId: string) => {\n const template = resolveTemplate(templateId);\n if (template) {\n loadTemplate(template);\n setActiveTab(\"editor\");\n }\n },\n [loadTemplate]\n );\n\n // Handler for AI-generated workflow\n const handleApplyWorkflow = useCallback(\n (workflow: GeneratedWorkflowData) => {\n loadGeneratedWorkflow(workflow);\n setActiveTab(\"editor\");\n },\n [loadGeneratedWorkflow]\n );\n\n return (\n <ReactFlowProvider>\n {/* AI Settings Modal */}\n <AISettings />\n\n {/* AI Chat Modal */}\n <AIChat\n isOpen={showAIChat}\n onClose={() => setShowAIChat(false)}\n onApplyWorkflow={handleApplyWorkflow}\n />\n\n {/* Output Inspector Modal */}\n {inspectedNode && inspectedOutput && (\n <OutputInspector\n isOpen={true}\n onClose={closeOutputInspector}\n nodeId={inspectedNodeId!}\n nodeLabel={\n (inspectedNode.data as { providerLabel?: string }).providerLabel ||\n inspectedNode.type ||\n \"Node\"\n }\n output={inspectedOutput}\n />\n )}\n\n {/* Workflow Library slide-out panel */}\n <WorkflowLibrary />\n\n <div className=\"h-screen flex flex-col bg-gray-100 dark:bg-zinc-900\">\n <Toolbar />\n\n {/* Tab navigation */}\n <div className=\"bg-white dark:bg-zinc-800 border-b border-gray-200 dark:border-zinc-700\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex\">\n <button\n onClick={() => setActiveTab(\"editor\")}\n className={`px-6 py-3 text-sm font-medium border-b-2 transition-colors ${\n activeTab === \"editor\"\n ? \"border-teal-500 text-teal-600 dark:text-teal-400\"\n : \"border-transparent text-gray-500 dark:text-zinc-400 hover:text-gray-700 dark:hover:text-zinc-200\"\n }`}\n >\n Editor\n </button>\n <button\n onClick={() => setActiveTab(\"gallery\")}\n className={`px-6 py-3 text-sm font-medium border-b-2 transition-colors ${\n activeTab === \"gallery\"\n ? \"border-teal-500 text-teal-600 dark:text-teal-400\"\n : \"border-transparent text-gray-500 dark:text-zinc-400 hover:text-gray-700 dark:hover:text-zinc-200\"\n }`}\n >\n Images\n </button>\n <button\n onClick={() => setActiveTab(\"templates\")}\n className={`px-6 py-3 text-sm font-medium border-b-2 transition-colors ${\n activeTab === \"templates\"\n ? \"border-teal-500 text-teal-600 dark:text-teal-400\"\n : \"border-transparent text-gray-500 dark:text-zinc-400 hover:text-gray-700 dark:hover:text-zinc-200\"\n }`}\n >\n Templates\n </button>\n </div>\n\n {/* AI Generate button */}\n <button\n onClick={() => setShowAIChat(true)}\n className=\"mr-4 px-4 py-1.5 text-sm font-medium text-white bg-gradient-to-r from-teal-500 to-cyan-500 hover:from-teal-600 hover:to-cyan-600 rounded-full flex items-center gap-2 transition-all shadow-sm hover:shadow\"\n >\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z\"\n />\n </svg>\n AI Generate\n </button>\n </div>\n </div>\n\n {/* Main content */}\n <div className=\"flex-1 flex overflow-hidden\">\n {activeTab === \"editor\" && (\n <>\n <NodePalette />\n <EditorDropZone />\n <NodeInspector />\n </>\n )}\n {activeTab === \"gallery\" && (\n <div className=\"flex-1 overflow-auto\">\n <Gallery />\n </div>\n )}\n {activeTab === \"templates\" && (\n <div className=\"flex-1 overflow-auto\">\n <TemplateGallery onSelect={handleTemplateSelect} />\n </div>\n )}\n </div>\n </div>\n </ReactFlowProvider>\n );\n}\n\nexport default App;\n"],"names":["createJSONStorage","getStorage","options","storage","name","_a","parse","str2","str","newValue","toThenable","fn","input","result","onFulfilled","_onRejected","e","_onFulfilled","onRejected","persistImpl","config","baseOptions","set","get","api","state","persistedState","currentState","hasHydrated","hydrationListeners","finishHydrationListeners","args","setItem","savedSetState","replace","configResult","stateFromStorage","hydrate","_b","cb","_a2","postRehydrationCallback","deserializedStorageValue","migration","migrationResult","migrated","migratedState","newOptions","persist","API_BASE","fetchJson","url","response","error","getGenerators","getTransforms","getTextProviders","getVisionProviders","exportYaml","nodes","edges","listImages","getImageUrl","id","getImageWorkflow","uploadImage","file","formData","listUploads","deleteUpload","getUploadBlobUrl","importYaml","yaml","validateYaml","getGenerateStatus","createSSEConnection","body","handlers","controller","errorBody","reader","decoder","buffer","done","value","processBuffer","messages","message","processSSEMessage","lines","data","line","parsed","DEFAULT_OLLAMA_URL","DEFAULT_LMSTUDIO_URL","useSettingsStore","create","provider","newAI","ai","_c","_d","_e","_f","_g","activeExecutionConnection","nodeIdCounter","generateNodeId","generateWorkflowId","timestamp","random","useWorkflowStore","enrichNodeData","studioNode","def","g","t","nodeId","template","idMap","newId","studioEdge","newSource","newTarget","generators","transforms","textProviders","visionProviders","definition","position","getDefaultParams","props","newNode","node","n","nodeToDuplicate","connection","handleSuffix","newEdge","studioNodes","studioEdges","aiProviders","initialNodeStatus","resolve","reject","event","step","newNodeStatus","newPreviews","newDataOutputs","finalNodeStatus","errorNodeStatus","activeWorkflowId","activeWorkflowName","savedWorkflows","currentTemplateId","now","updated","wf","newWorkflow","workflow","enrichedNodes","filtered","duplicate","GRID_SPACING_X","GRID_SPACING_Y","NODES_PER_ROW","genNode","index","parts","nodeType","row","generatorName","generatorDef","providerName","operation","transformDef","jsonSchema","outputSchema","key","prop","genEdge","params","field","getExecutionClass","nodeStatus","PreviewToggle","color","previewVisible","s","togglePreview","jsx","GeneratorNode","memo","selected","preview","borderClass","isAI","acceptsReferences","jsxs","Handle","Position","TransformNode","SaveNode","InputNode","updateNodeData","fileInputRef","useRef","handleFileSelect","useCallback","handleDrop","handleDragOver","handleInputChange","previewUrl","VisionNode","dataOutput","openOutputInspector","outputProperties","hasMultiOutput","Fragment","TextNode","nodeTypes","defaultEdgeOptions","MarkerType","WorkflowEditor","setNodes","setEdges","addEdge","setSelectedNode","memoizedNodeTypes","useMemo","isValidConnection","source","target","targetHandle","sourceNode","targetNode","onNodesChange","changes","applyNodeChanges","onEdgesChange","applyEdgeChanges","onConnect","edgesToRemove","existingHandle","newHandle","removeIds","onNodeClick","_event","onPaneClick","ReactFlow","Background","Controls","MiniMap","UploadGallery","onSelect","uploads","setUploads","useState","loading","setLoading","setError","fetchUploads","err","useEffect","handleDelete","prev","u","formatSize","bytes","upload","NodePalette","setGenerators","setTransforms","setTextProviders","setVisionProviders","addNode","showUploads","setShowUploads","fetchedGenerators","useQuery","fetchedTransforms","fetchedTextProviders","fetchedVisionProviders","handleDragStart","handleDoubleClick","inputDefinition","saveDefinition","generatorsByCategory","acc","cat","transformsByCategory","category","NodeInspector","selectedNodeId","deleteNode","selectedNode","schema","nodeLabel","isCloudSave","v","handleParamChange","getParamValue","isFieldVisible","_field","shapeType","fillType","FieldEditor","OutputSchemaEditor","onChange","label","inputClasses","opt","newPropertyName","setNewPropertyName","properties","propertyEntries","handleAddProperty","newSchema","handleRemoveProperty","newProperties","handleTypeChange","type","handleDescriptionChange","description","topologicalSort","nodeMap","inDegree","adjacency","edge","targets","queue","degree","sorted","neighbors","neighbor","newDegree","getNodeVarName","suffix","stringify","generateNodeCode","nodeVarNames","varName","imports","inputEdge","inputVarName","paramStr","k","generateJavaScript","sortedNodes","allImports","codeBlocks","code","imp","importLines","header","mainCode","block","ImportModal","isOpen","onClose","onImport","yamlContent","setYamlContent","isLoading","setIsLoading","isDragging","setIsDragging","handleImport","handleValidate","handleFileUpload","text","handleDragLeave","handleFileInputChange","Toolbar","brandingSlot","beforeActionsSlot","afterActionsSlot","hideAttribution","hideWorkflowLibrary","execution","execute","cancelExecution","exportToYaml","importFromYaml","openSettings","hasUnsavedChanges","saveWorkflow","toggleLibrary","setActiveWorkflowName","duplicateNode","showExport","setShowExport","showImport","setShowImport","exportTab","setExportTab","jsContent","setJsContent","notification","setNotification","isEditingName","setIsEditingName","editingName","setEditingName","handleNewWorkflow","handleSave","handleStartRename","handleSaveRename","trimmed","handleDuplicate","handleKeyDown","handleExecute","handleExport","js","handleCopy","content","importedNodes","importedEdges","idx","Gallery","loadTemplate","loadingWorkflow","setLoadingWorkflow","images","refetch","handleLoadWorkflow","imageId","metadata","image","ImageCard","onLoadWorkflow","formatDate","revenueChart","monthlyUsers","frameworkUsage","trafficBreakdown","apiFlow","systemArchitecture","gitWorkflow","dataVizTemplates","aiProductShot","aiHeroImage","aiMascot","aiLogoBrandKit","productPhotoEnhancement","aiArtSocialPost","aiWorkflowTemplates","socialMediaKit","avatarPipeline","watermarkBranding","filterShowcase","responsiveImages","teamHeadshots","screenshotDocs","blogOgImage","emailBanner","appIcons","marketingTemplates","brandedQR","darkQR","wifiQR","thumbnailGenerator","diagramWebp","utilityTemplates","allTemplates","coreTemplates","getTemplateById","getCoreTemplateById","getCoreCategories","categories","getCoreTemplatesByCategory","searchCoreTemplates","query","q","tag","resolveTemplate","TemplateGallery","selectedCategory","setSelectedCategory","searchQuery","setSearchQuery","getCategories","filteredTemplates","templates","TemplateCard","nodeCount","edgeCount","generatorColors","WorkflowItem","isActive","onLoad","onDelete","onRename","onDuplicate","isEditing","setIsEditing","editName","setEditName","showMenu","setShowMenu","handleRename","date","diffMs","diffMins","diffHours","diffDays","WorkflowLibrary","showLibrary","loadWorkflow","deleteWorkflow","renameWorkflow","duplicateWorkflow","sortedWorkflows","a","b","CLOUD_PROVIDERS","LOCAL_PROVIDERS","CloudProviderRow","setAIProvider","isEnabled","apiKey","localKey","setLocalKey","showKey","setShowKey","handleToggle","handleKeyChange","LocalProviderRow","baseUrl","localUrl","setLocalUrl","handleUrlChange","AISettings","showSettings","closeSettings","activeGenerationConnection","AIChat","onApplyWorkflow","setMessages","setInput","generationPhase","setGenerationPhase","generationMessage","setGenerationMessage","isAvailable","setIsAvailable","statusMessage","setStatusMessage","statusReason","setStatusReason","isCloudDeployment","setIsCloudDeployment","supportUrl","setSupportUrl","messagesEndRef","inputRef","status","handleSubmit","userMessage","receivedWorkflow","assistantMessage","handleCancelGeneration","handleApply","handleNewChat","example","i","msg","nodeIdx","MAX_JSON_DEPTH","MAX_ARRAY_ITEMS","LARGE_OUTPUT_THRESHOLD","OutputInspector","output","viewMode","setViewMode","copied","setCopied","textToCopy","hasFormattedView","JsonTree","JsonNode","depth","keyName","maxDepth","indent","displayValue","itemsToRender","hiddenCount","item","entries","val","EditorDropZone","screenToFlowPosition","useReactFlow","App","activeTab","setActiveTab","showAIChat","setShowAIChat","loadGeneratedWorkflow","inspectedNodeId","executionDataOutputs","closeOutputInspector","inspectedNode","inspectedOutput","templateId","handleWorkflowLoaded","handleTemplateSelect","handleApplyWorkflow","ReactFlowProvider"],"mappings":"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","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"index.js","sources":["../../../../node_modules/.pnpm/zustand@5.0.9_@types+react@18.3.27_immer@10.2.0_react@19.2.3_use-sync-external-store@1.6.0_react@19.2.3_/node_modules/zustand/esm/middleware.mjs","../src/api/client.ts","../src/api/sse.ts","../src/lib/keyboard/types.ts","../src/lib/keyboard/shortcuts.ts","../src/lib/keyboard/conflicts.ts","../src/stores/settingsStore.ts","../src/stores/workflowStore.ts","../src/editor/nodeTypes.tsx","../src/editor/WorkflowEditor.tsx","../src/components/UploadGallery.tsx","../src/components/NodePalette.tsx","../src/components/NodeInspector.tsx","../../../../node_modules/.pnpm/react-hotkeys-hook@5.2.1_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/react-hotkeys-hook/packages/react-hotkeys-hook/dist/index.js","../src/lib/keyboard/useKeyboardShortcuts.tsx","../src/lib/keyboard/platformUtils.ts","../src/utils/codeGenerator.ts","../src/components/ImportModal.tsx","../src/components/Toolbar.tsx","../src/components/Gallery.tsx","../../../../packages/floimg-templates/dist/templates/data-viz.js","../../../../packages/floimg-templates/dist/templates/ai-workflows.js","../../../../packages/floimg-templates/dist/templates/marketing.js","../../../../packages/floimg-templates/dist/templates/utilities.js","../../../../packages/floimg-templates/dist/index.js","../src/components/TemplateGallery.tsx","../src/components/WorkflowLibrary.tsx","../src/components/AISettings.tsx","../src/components/AIChat.tsx","../src/components/OutputInspector.tsx","../src/components/KeyBadge.tsx","../src/lib/useFocusTrap.ts","../src/components/CommandPalette.tsx","../src/components/KeyboardShortcutsModal.tsx","../src/components/ConfirmationDialog.tsx","../src/App.tsx"],"sourcesContent":["const reduxImpl = (reducer, initial) => (set, _get, api) => {\n api.dispatch = (action) => {\n set((state) => reducer(state, action), false, action);\n return action;\n };\n api.dispatchFromDevtools = true;\n return { dispatch: (...args) => api.dispatch(...args), ...initial };\n};\nconst redux = reduxImpl;\n\nconst trackedConnections = /* @__PURE__ */ new Map();\nconst getTrackedConnectionState = (name) => {\n const api = trackedConnections.get(name);\n if (!api) return {};\n return Object.fromEntries(\n Object.entries(api.stores).map(([key, api2]) => [key, api2.getState()])\n );\n};\nconst extractConnectionInformation = (store, extensionConnector, options) => {\n if (store === void 0) {\n return {\n type: \"untracked\",\n connection: extensionConnector.connect(options)\n };\n }\n const existingConnection = trackedConnections.get(options.name);\n if (existingConnection) {\n return { type: \"tracked\", store, ...existingConnection };\n }\n const newConnection = {\n connection: extensionConnector.connect(options),\n stores: {}\n };\n trackedConnections.set(options.name, newConnection);\n return { type: \"tracked\", store, ...newConnection };\n};\nconst removeStoreFromTrackedConnections = (name, store) => {\n if (store === void 0) return;\n const connectionInfo = trackedConnections.get(name);\n if (!connectionInfo) return;\n delete connectionInfo.stores[store];\n if (Object.keys(connectionInfo.stores).length === 0) {\n trackedConnections.delete(name);\n }\n};\nconst findCallerName = (stack) => {\n var _a, _b;\n if (!stack) return void 0;\n const traceLines = stack.split(\"\\n\");\n const apiSetStateLineIndex = traceLines.findIndex(\n (traceLine) => traceLine.includes(\"api.setState\")\n );\n if (apiSetStateLineIndex < 0) return void 0;\n const callerLine = ((_a = traceLines[apiSetStateLineIndex + 1]) == null ? void 0 : _a.trim()) || \"\";\n return (_b = /.+ (.+) .+/.exec(callerLine)) == null ? void 0 : _b[1];\n};\nconst devtoolsImpl = (fn, devtoolsOptions = {}) => (set, get, api) => {\n const { enabled, anonymousActionType, store, ...options } = devtoolsOptions;\n let extensionConnector;\n try {\n extensionConnector = (enabled != null ? enabled : (import.meta.env ? import.meta.env.MODE : void 0) !== \"production\") && window.__REDUX_DEVTOOLS_EXTENSION__;\n } catch (e) {\n }\n if (!extensionConnector) {\n return fn(set, get, api);\n }\n const { connection, ...connectionInformation } = extractConnectionInformation(store, extensionConnector, options);\n let isRecording = true;\n api.setState = ((state, replace, nameOrAction) => {\n const r = set(state, replace);\n if (!isRecording) return r;\n const action = nameOrAction === void 0 ? {\n type: anonymousActionType || findCallerName(new Error().stack) || \"anonymous\"\n } : typeof nameOrAction === \"string\" ? { type: nameOrAction } : nameOrAction;\n if (store === void 0) {\n connection == null ? void 0 : connection.send(action, get());\n return r;\n }\n connection == null ? void 0 : connection.send(\n {\n ...action,\n type: `${store}/${action.type}`\n },\n {\n ...getTrackedConnectionState(options.name),\n [store]: api.getState()\n }\n );\n return r;\n });\n api.devtools = {\n cleanup: () => {\n if (connection && typeof connection.unsubscribe === \"function\") {\n connection.unsubscribe();\n }\n removeStoreFromTrackedConnections(options.name, store);\n }\n };\n const setStateFromDevtools = (...a) => {\n const originalIsRecording = isRecording;\n isRecording = false;\n set(...a);\n isRecording = originalIsRecording;\n };\n const initialState = fn(api.setState, get, api);\n if (connectionInformation.type === \"untracked\") {\n connection == null ? void 0 : connection.init(initialState);\n } else {\n connectionInformation.stores[connectionInformation.store] = api;\n connection == null ? void 0 : connection.init(\n Object.fromEntries(\n Object.entries(connectionInformation.stores).map(([key, store2]) => [\n key,\n key === connectionInformation.store ? initialState : store2.getState()\n ])\n )\n );\n }\n if (api.dispatchFromDevtools && typeof api.dispatch === \"function\") {\n let didWarnAboutReservedActionType = false;\n const originalDispatch = api.dispatch;\n api.dispatch = (...args) => {\n if ((import.meta.env ? import.meta.env.MODE : void 0) !== \"production\" && args[0].type === \"__setState\" && !didWarnAboutReservedActionType) {\n console.warn(\n '[zustand devtools middleware] \"__setState\" action type is reserved to set state from the devtools. Avoid using it.'\n );\n didWarnAboutReservedActionType = true;\n }\n originalDispatch(...args);\n };\n }\n connection.subscribe((message) => {\n var _a;\n switch (message.type) {\n case \"ACTION\":\n if (typeof message.payload !== \"string\") {\n console.error(\n \"[zustand devtools middleware] Unsupported action format\"\n );\n return;\n }\n return parseJsonThen(\n message.payload,\n (action) => {\n if (action.type === \"__setState\") {\n if (store === void 0) {\n setStateFromDevtools(action.state);\n return;\n }\n if (Object.keys(action.state).length !== 1) {\n console.error(\n `\n [zustand devtools middleware] Unsupported __setState action format.\n When using 'store' option in devtools(), the 'state' should have only one key, which is a value of 'store' that was passed in devtools(),\n and value of this only key should be a state object. Example: { \"type\": \"__setState\", \"state\": { \"abc123Store\": { \"foo\": \"bar\" } } }\n `\n );\n }\n const stateFromDevtools = action.state[store];\n if (stateFromDevtools === void 0 || stateFromDevtools === null) {\n return;\n }\n if (JSON.stringify(api.getState()) !== JSON.stringify(stateFromDevtools)) {\n setStateFromDevtools(stateFromDevtools);\n }\n return;\n }\n if (!api.dispatchFromDevtools) return;\n if (typeof api.dispatch !== \"function\") return;\n api.dispatch(action);\n }\n );\n case \"DISPATCH\":\n switch (message.payload.type) {\n case \"RESET\":\n setStateFromDevtools(initialState);\n if (store === void 0) {\n return connection == null ? void 0 : connection.init(api.getState());\n }\n return connection == null ? void 0 : connection.init(getTrackedConnectionState(options.name));\n case \"COMMIT\":\n if (store === void 0) {\n connection == null ? void 0 : connection.init(api.getState());\n return;\n }\n return connection == null ? void 0 : connection.init(getTrackedConnectionState(options.name));\n case \"ROLLBACK\":\n return parseJsonThen(message.state, (state) => {\n if (store === void 0) {\n setStateFromDevtools(state);\n connection == null ? void 0 : connection.init(api.getState());\n return;\n }\n setStateFromDevtools(state[store]);\n connection == null ? void 0 : connection.init(getTrackedConnectionState(options.name));\n });\n case \"JUMP_TO_STATE\":\n case \"JUMP_TO_ACTION\":\n return parseJsonThen(message.state, (state) => {\n if (store === void 0) {\n setStateFromDevtools(state);\n return;\n }\n if (JSON.stringify(api.getState()) !== JSON.stringify(state[store])) {\n setStateFromDevtools(state[store]);\n }\n });\n case \"IMPORT_STATE\": {\n const { nextLiftedState } = message.payload;\n const lastComputedState = (_a = nextLiftedState.computedStates.slice(-1)[0]) == null ? void 0 : _a.state;\n if (!lastComputedState) return;\n if (store === void 0) {\n setStateFromDevtools(lastComputedState);\n } else {\n setStateFromDevtools(lastComputedState[store]);\n }\n connection == null ? void 0 : connection.send(\n null,\n // FIXME no-any\n nextLiftedState\n );\n return;\n }\n case \"PAUSE_RECORDING\":\n return isRecording = !isRecording;\n }\n return;\n }\n });\n return initialState;\n};\nconst devtools = devtoolsImpl;\nconst parseJsonThen = (stringified, fn) => {\n let parsed;\n try {\n parsed = JSON.parse(stringified);\n } catch (e) {\n console.error(\n \"[zustand devtools middleware] Could not parse the received json\",\n e\n );\n }\n if (parsed !== void 0) fn(parsed);\n};\n\nconst subscribeWithSelectorImpl = (fn) => (set, get, api) => {\n const origSubscribe = api.subscribe;\n api.subscribe = ((selector, optListener, options) => {\n let listener = selector;\n if (optListener) {\n const equalityFn = (options == null ? void 0 : options.equalityFn) || Object.is;\n let currentSlice = selector(api.getState());\n listener = (state) => {\n const nextSlice = selector(state);\n if (!equalityFn(currentSlice, nextSlice)) {\n const previousSlice = currentSlice;\n optListener(currentSlice = nextSlice, previousSlice);\n }\n };\n if (options == null ? void 0 : options.fireImmediately) {\n optListener(currentSlice, currentSlice);\n }\n }\n return origSubscribe(listener);\n });\n const initialState = fn(set, get, api);\n return initialState;\n};\nconst subscribeWithSelector = subscribeWithSelectorImpl;\n\nfunction combine(initialState, create) {\n return (...args) => Object.assign({}, initialState, create(...args));\n}\n\nfunction createJSONStorage(getStorage, options) {\n let storage;\n try {\n storage = getStorage();\n } catch (e) {\n return;\n }\n const persistStorage = {\n getItem: (name) => {\n var _a;\n const parse = (str2) => {\n if (str2 === null) {\n return null;\n }\n return JSON.parse(str2, options == null ? void 0 : options.reviver);\n };\n const str = (_a = storage.getItem(name)) != null ? _a : null;\n if (str instanceof Promise) {\n return str.then(parse);\n }\n return parse(str);\n },\n setItem: (name, newValue) => storage.setItem(name, JSON.stringify(newValue, options == null ? void 0 : options.replacer)),\n removeItem: (name) => storage.removeItem(name)\n };\n return persistStorage;\n}\nconst toThenable = (fn) => (input) => {\n try {\n const result = fn(input);\n if (result instanceof Promise) {\n return result;\n }\n return {\n then(onFulfilled) {\n return toThenable(onFulfilled)(result);\n },\n catch(_onRejected) {\n return this;\n }\n };\n } catch (e) {\n return {\n then(_onFulfilled) {\n return this;\n },\n catch(onRejected) {\n return toThenable(onRejected)(e);\n }\n };\n }\n};\nconst persistImpl = (config, baseOptions) => (set, get, api) => {\n let options = {\n storage: createJSONStorage(() => localStorage),\n partialize: (state) => state,\n version: 0,\n merge: (persistedState, currentState) => ({\n ...currentState,\n ...persistedState\n }),\n ...baseOptions\n };\n let hasHydrated = false;\n const hydrationListeners = /* @__PURE__ */ new Set();\n const finishHydrationListeners = /* @__PURE__ */ new Set();\n let storage = options.storage;\n if (!storage) {\n return config(\n (...args) => {\n console.warn(\n `[zustand persist middleware] Unable to update item '${options.name}', the given storage is currently unavailable.`\n );\n set(...args);\n },\n get,\n api\n );\n }\n const setItem = () => {\n const state = options.partialize({ ...get() });\n return storage.setItem(options.name, {\n state,\n version: options.version\n });\n };\n const savedSetState = api.setState;\n api.setState = (state, replace) => {\n savedSetState(state, replace);\n return setItem();\n };\n const configResult = config(\n (...args) => {\n set(...args);\n return setItem();\n },\n get,\n api\n );\n api.getInitialState = () => configResult;\n let stateFromStorage;\n const hydrate = () => {\n var _a, _b;\n if (!storage) return;\n hasHydrated = false;\n hydrationListeners.forEach((cb) => {\n var _a2;\n return cb((_a2 = get()) != null ? _a2 : configResult);\n });\n const postRehydrationCallback = ((_b = options.onRehydrateStorage) == null ? void 0 : _b.call(options, (_a = get()) != null ? _a : configResult)) || void 0;\n return toThenable(storage.getItem.bind(storage))(options.name).then((deserializedStorageValue) => {\n if (deserializedStorageValue) {\n if (typeof deserializedStorageValue.version === \"number\" && deserializedStorageValue.version !== options.version) {\n if (options.migrate) {\n const migration = options.migrate(\n deserializedStorageValue.state,\n deserializedStorageValue.version\n );\n if (migration instanceof Promise) {\n return migration.then((result) => [true, result]);\n }\n return [true, migration];\n }\n console.error(\n `State loaded from storage couldn't be migrated since no migrate function was provided`\n );\n } else {\n return [false, deserializedStorageValue.state];\n }\n }\n return [false, void 0];\n }).then((migrationResult) => {\n var _a2;\n const [migrated, migratedState] = migrationResult;\n stateFromStorage = options.merge(\n migratedState,\n (_a2 = get()) != null ? _a2 : configResult\n );\n set(stateFromStorage, true);\n if (migrated) {\n return setItem();\n }\n }).then(() => {\n postRehydrationCallback == null ? void 0 : postRehydrationCallback(stateFromStorage, void 0);\n stateFromStorage = get();\n hasHydrated = true;\n finishHydrationListeners.forEach((cb) => cb(stateFromStorage));\n }).catch((e) => {\n postRehydrationCallback == null ? void 0 : postRehydrationCallback(void 0, e);\n });\n };\n api.persist = {\n setOptions: (newOptions) => {\n options = {\n ...options,\n ...newOptions\n };\n if (newOptions.storage) {\n storage = newOptions.storage;\n }\n },\n clearStorage: () => {\n storage == null ? void 0 : storage.removeItem(options.name);\n },\n getOptions: () => options,\n rehydrate: () => hydrate(),\n hasHydrated: () => hasHydrated,\n onHydrate: (cb) => {\n hydrationListeners.add(cb);\n return () => {\n hydrationListeners.delete(cb);\n };\n },\n onFinishHydration: (cb) => {\n finishHydrationListeners.add(cb);\n return () => {\n finishHydrationListeners.delete(cb);\n };\n }\n };\n if (!options.skipHydration) {\n hydrate();\n }\n return stateFromStorage || configResult;\n};\nconst persist = persistImpl;\n\nfunction ssrSafe(config, isSSR = typeof window === \"undefined\") {\n return (set, get, api) => {\n if (!isSSR) {\n return config(set, get, api);\n }\n const ssrSet = () => {\n throw new Error(\"Cannot set state of Zustand store in SSR\");\n };\n api.setState = ssrSet;\n return config(ssrSet, get, api);\n };\n}\n\nexport { combine, createJSONStorage, devtools, persist, redux, subscribeWithSelector, ssrSafe as unstable_ssrSafe };\n","import type {\n NodeDefinition,\n StudioNode,\n StudioEdge,\n ImageMetadata,\n GenerateWorkflowRequest,\n GenerateWorkflowResponse,\n GenerateStatusResponse,\n} from \"@teamflojo/floimg-studio-shared\";\n\nconst API_BASE = \"/api\";\n\nasync function fetchJson<T>(url: string, options?: RequestInit): Promise<T> {\n const response = await fetch(url, {\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options?.headers,\n },\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ error: \"Unknown error\" }));\n throw new Error(error.error || `HTTP ${response.status}`);\n }\n\n return response.json();\n}\n\n// Node registry\nexport async function getGenerators(): Promise<NodeDefinition[]> {\n return fetchJson(`${API_BASE}/nodes/generators`);\n}\n\nexport async function getTransforms(): Promise<NodeDefinition[]> {\n return fetchJson(`${API_BASE}/nodes/transforms`);\n}\n\nexport async function getTextProviders(): Promise<NodeDefinition[]> {\n return fetchJson(`${API_BASE}/nodes/text`);\n}\n\nexport async function getVisionProviders(): Promise<NodeDefinition[]> {\n return fetchJson(`${API_BASE}/nodes/vision`);\n}\n\n// AI provider configuration passed to backend\nexport interface AIProviderConfig {\n openai?: { apiKey: string };\n anthropic?: { apiKey: string };\n gemini?: { apiKey: string };\n grok?: { apiKey: string };\n openrouter?: { apiKey: string };\n ollama?: { baseUrl: string };\n lmstudio?: { baseUrl: string };\n}\n\n// Execution\nexport async function executeWorkflow(\n nodes: StudioNode[],\n edges: StudioEdge[],\n aiProviders?: AIProviderConfig\n): Promise<{\n status: string;\n imageIds: string[];\n imageUrls?: string[]; // Presigned cloud URLs (FSC only)\n previews?: Record<string, string>;\n dataOutputs?: Record<\n string,\n { dataType: \"text\" | \"json\"; content: string; parsed?: Record<string, unknown> }\n >;\n error?: string;\n}> {\n return fetchJson(`${API_BASE}/execute/sync`, {\n method: \"POST\",\n body: JSON.stringify({ nodes, edges, aiProviders }),\n });\n}\n\n// Export\nexport async function exportYaml(\n nodes: StudioNode[],\n edges: StudioEdge[]\n): Promise<{ yaml: string }> {\n return fetchJson(`${API_BASE}/export/yaml`, {\n method: \"POST\",\n body: JSON.stringify({ nodes, edges }),\n });\n}\n\n// Images\nexport interface ImageInfo {\n id: string;\n filename: string;\n mime: string;\n size: number;\n createdAt: number;\n}\n\nexport async function listImages(): Promise<ImageInfo[]> {\n return fetchJson(`${API_BASE}/images`);\n}\n\nexport function getImageUrl(id: string): string {\n return `${API_BASE}/images/${id}/blob`;\n}\n\nexport async function getImageWorkflow(id: string): Promise<ImageMetadata | null> {\n try {\n return await fetchJson(`${API_BASE}/images/${id}/workflow`);\n } catch {\n return null; // Workflow metadata not available for this image\n }\n}\n\n// Uploads\nexport interface UploadInfo {\n id: string;\n filename: string;\n mime: string;\n size: number;\n createdAt: number;\n}\n\nexport async function uploadImage(file: File): Promise<UploadInfo> {\n const formData = new FormData();\n formData.append(\"file\", file);\n\n const response = await fetch(`${API_BASE}/uploads`, {\n method: \"POST\",\n body: formData,\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ error: \"Upload failed\" }));\n throw new Error(error.error || `HTTP ${response.status}`);\n }\n\n return response.json();\n}\n\nexport async function listUploads(): Promise<UploadInfo[]> {\n return fetchJson(`${API_BASE}/uploads`);\n}\n\nexport async function getUploadThumbnail(id: string): Promise<{ dataUrl: string }> {\n return fetchJson(`${API_BASE}/uploads/${id}/thumbnail`);\n}\n\nexport async function deleteUpload(id: string): Promise<void> {\n const response = await fetch(`${API_BASE}/uploads/${id}`, {\n method: \"DELETE\",\n });\n if (!response.ok) {\n throw new Error(`Failed to delete upload: ${response.status}`);\n }\n}\n\nexport function getUploadBlobUrl(id: string): string {\n return `${API_BASE}/uploads/${id}/blob`;\n}\n\n// Input nodes\nexport async function getInputNodes(): Promise<NodeDefinition[]> {\n return fetchJson(`${API_BASE}/nodes/inputs`);\n}\n\n// Import\nexport interface ImportResult {\n success: boolean;\n nodes: StudioNode[];\n edges: StudioEdge[];\n name: string;\n error?: string;\n line?: number;\n column?: number;\n}\n\nexport interface ImportValidationResult {\n valid: boolean;\n errors: Array<{ message: string; line?: number; column?: number }>;\n}\n\nexport async function importYaml(yaml: string): Promise<ImportResult> {\n return fetchJson(`${API_BASE}/import`, {\n method: \"POST\",\n body: JSON.stringify({ yaml }),\n });\n}\n\nexport async function validateYaml(yaml: string): Promise<ImportValidationResult> {\n return fetchJson(`${API_BASE}/import/validate`, {\n method: \"POST\",\n body: JSON.stringify({ yaml }),\n });\n}\n\n// Workflow Generation\nexport async function generateWorkflow(\n request: GenerateWorkflowRequest\n): Promise<GenerateWorkflowResponse> {\n return fetchJson(`${API_BASE}/generate/workflow`, {\n method: \"POST\",\n body: JSON.stringify(request),\n });\n}\n\nexport async function getGenerateStatus(): Promise<GenerateStatusResponse> {\n return fetchJson(`${API_BASE}/generate/status`);\n}\n","/**\n * Server-Sent Events (SSE) client utility\n *\n * Handles POST-based SSE connections for streaming execution and generation updates.\n * Uses fetch with streaming response body parsing.\n */\n\nexport interface SSEConnectionHandlers<T> {\n onMessage: (event: T) => void;\n onError: (error: Error) => void;\n onClose: () => void;\n}\n\nexport interface SSEConnection {\n abort: () => void;\n}\n\n/**\n * Create an SSE connection using POST request with JSON body.\n *\n * SSE typically uses GET, but we need POST to send workflow data.\n * This implements manual SSE parsing over a fetch streaming response.\n */\nexport function createSSEConnection<T>(\n url: string,\n body: unknown,\n handlers: SSEConnectionHandlers<T>\n): SSEConnection {\n const controller = new AbortController();\n\n // Start the streaming request\n (async () => {\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorBody = await response.json().catch(() => ({ error: \"Unknown error\" }));\n throw new Error(errorBody.error || `HTTP ${response.status}`);\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"Response body is not readable\");\n }\n\n const decoder = new globalThis.TextDecoder();\n let buffer = \"\";\n\n // Read the stream\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) {\n // Process any remaining data in buffer\n if (buffer.trim()) {\n processBuffer(buffer, handlers);\n }\n break;\n }\n\n // Decode chunk and add to buffer\n buffer += decoder.decode(value, { stream: true });\n\n // Process complete SSE messages (separated by double newlines)\n const messages = buffer.split(\"\\n\\n\");\n buffer = messages.pop() || \"\"; // Keep incomplete message in buffer\n\n for (const message of messages) {\n if (message.trim()) {\n processSSEMessage(message, handlers);\n }\n }\n }\n\n handlers.onClose();\n } catch (error) {\n // Don't report abort errors\n if (error instanceof Error && error.name === \"AbortError\") {\n handlers.onClose();\n return;\n }\n handlers.onError(error instanceof Error ? error : new Error(String(error)));\n }\n })();\n\n return {\n abort: () => controller.abort(),\n };\n}\n\n/**\n * Process a single SSE message block\n */\nfunction processSSEMessage<T>(message: string, handlers: SSEConnectionHandlers<T>): void {\n const lines = message.split(\"\\n\");\n let data = \"\";\n\n for (const line of lines) {\n if (line.startsWith(\"data: \")) {\n // Accumulate data lines (SSE spec allows multiple data: lines)\n data += (data ? \"\\n\" : \"\") + line.slice(6);\n }\n // Ignore other SSE fields (event:, id:, retry:) for simplicity\n }\n\n if (data) {\n try {\n const parsed = JSON.parse(data) as T;\n handlers.onMessage(parsed);\n } catch (error) {\n console.warn(\"SSE: Failed to parse message data:\", {\n error: error instanceof Error ? error.message : String(error),\n dataPreview: data.slice(0, 200),\n dataLength: data.length,\n });\n }\n }\n}\n\n/**\n * Process remaining buffer content\n */\nfunction processBuffer<T>(buffer: string, handlers: SSEConnectionHandlers<T>): void {\n const lines = buffer.split(\"\\n\");\n let data = \"\";\n\n for (const line of lines) {\n if (line.startsWith(\"data: \")) {\n data += (data ? \"\\n\" : \"\") + line.slice(6);\n }\n }\n\n if (data) {\n try {\n const parsed = JSON.parse(data) as T;\n handlers.onMessage(parsed);\n } catch (error) {\n // Log incomplete/malformed data at end of stream for debugging\n console.warn(\"SSE: Incomplete data at end of stream:\", {\n error: error instanceof Error ? error.message : String(error),\n dataPreview: data.slice(0, 200),\n dataLength: data.length,\n });\n }\n }\n}\n","/**\n * Keyboard shortcut system types\n */\n\n/** Categories for organizing shortcuts */\nexport type ShortcutCategory = \"workflow\" | \"editing\" | \"canvas\" | \"ui\";\n\n/** All valid shortcut action identifiers */\nexport const VALID_SHORTCUT_ACTIONS = [\n // Workflow\n \"save\",\n \"execute\",\n \"newWorkflow\",\n \"exportWorkflow\",\n \"importWorkflow\",\n // Editing\n \"duplicate\",\n \"delete\",\n \"selectAll\",\n \"deselect\",\n // Canvas\n \"zoomIn\",\n \"zoomOut\",\n \"zoomFit\",\n \"panMode\",\n // UI\n \"commandPalette\",\n \"showShortcuts\",\n \"toggleAIChat\",\n \"toggleLibrary\",\n \"settings\",\n \"toggleNodePalette\",\n // User-assignable (no default)\n \"cancelExecution\",\n \"focusSearch\",\n] as const;\n\n/** Shortcut action identifiers */\nexport type ShortcutAction = (typeof VALID_SHORTCUT_ACTIONS)[number];\n\n/** Shortcut definition with metadata */\nexport interface ShortcutDefinition {\n /** Action identifier */\n action: ShortcutAction;\n /** Human-readable name */\n name: string;\n /** Description for help modal */\n description: string;\n /** Category for grouping */\n category: ShortcutCategory;\n /** Default key binding (uses 'mod' for Cmd/Ctrl) */\n defaultBinding: string | null;\n /** Whether shortcut can be customized */\n customizable: boolean;\n}\n\n/** User's keyboard settings */\nexport interface KeyboardSettings {\n /** User's custom shortcut overrides (action -> binding) */\n shortcuts: Partial<Record<ShortcutAction, string>>;\n /** Whether keyboard shortcuts are enabled globally */\n enabled: boolean;\n}\n\n/** Command for command palette */\nexport interface Command {\n /** Unique identifier */\n id: string;\n /** Display name */\n name: string;\n /** Category for grouping */\n category: ShortcutCategory | \"nodes\";\n /** Optional keyboard shortcut */\n shortcut?: string;\n /** Optional icon (React node) */\n icon?: React.ReactNode;\n /** Action to execute */\n action: () => void;\n /** Optional function to check if command is enabled */\n enabled?: () => boolean;\n /** Optional keywords for search */\n keywords?: string[];\n}\n\n/** Key event info for shortcut recording */\nexport interface RecordedShortcut {\n /** Raw key string */\n key: string;\n /** Modifier keys pressed */\n modifiers: {\n ctrl: boolean;\n meta: boolean;\n alt: boolean;\n shift: boolean;\n };\n /** Formatted binding string (e.g., 'mod+s') */\n binding: string;\n /** Display string (e.g., '⌘S' on Mac) */\n displayString: string;\n}\n\n/** Conflict check result */\nexport interface ConflictCheckResult {\n /** Whether there's a conflict */\n hasConflict: boolean;\n /** Type of conflict */\n conflictType?: \"browser\" | \"internal\" | \"reactflow\";\n /** Human-readable conflict message */\n message?: string;\n /** Action that conflicts (for internal conflicts) */\n conflictingAction?: ShortcutAction;\n}\n","/**\n * Keyboard shortcut definitions and registry\n */\n\nimport type { ShortcutAction, ShortcutDefinition, ShortcutCategory } from \"./types\";\n\n/** All shortcut definitions */\nexport const SHORTCUT_DEFINITIONS: ShortcutDefinition[] = [\n // Workflow shortcuts\n {\n action: \"save\",\n name: \"Save Workflow\",\n description: \"Save the current workflow\",\n category: \"workflow\",\n defaultBinding: \"mod+s\",\n customizable: true,\n },\n {\n action: \"execute\",\n name: \"Execute Workflow\",\n description: \"Run the current workflow\",\n category: \"workflow\",\n defaultBinding: \"mod+enter\",\n customizable: true,\n },\n {\n action: \"newWorkflow\",\n name: \"New Workflow\",\n description: \"Create a new empty workflow\",\n category: \"workflow\",\n defaultBinding: \"mod+n\",\n customizable: true,\n },\n {\n action: \"exportWorkflow\",\n name: \"Export Workflow\",\n description: \"Export workflow as YAML or JavaScript\",\n category: \"workflow\",\n defaultBinding: \"mod+e\",\n customizable: true,\n },\n {\n action: \"importWorkflow\",\n name: \"Import Workflow\",\n description: \"Import workflow from YAML\",\n category: \"workflow\",\n defaultBinding: \"mod+i\",\n customizable: true,\n },\n\n // Editing shortcuts\n {\n action: \"duplicate\",\n name: \"Duplicate Node\",\n description: \"Duplicate the selected node\",\n category: \"editing\",\n defaultBinding: \"mod+d\",\n customizable: true,\n },\n {\n action: \"delete\",\n name: \"Delete Node\",\n description: \"Delete the selected node(s)\",\n category: \"editing\",\n defaultBinding: \"delete,backspace\",\n customizable: false, // Handled by React Flow\n },\n {\n action: \"selectAll\",\n name: \"Select All\",\n description: \"Select all nodes on the canvas\",\n category: \"editing\",\n defaultBinding: \"mod+a\",\n customizable: true,\n },\n {\n action: \"deselect\",\n name: \"Deselect\",\n description: \"Deselect all nodes and close modals\",\n category: \"editing\",\n defaultBinding: \"escape\",\n customizable: true,\n },\n\n // Canvas shortcuts\n {\n action: \"zoomIn\",\n name: \"Zoom In\",\n description: \"Zoom in on the canvas\",\n category: \"canvas\",\n defaultBinding: \"mod+equal\",\n customizable: true,\n },\n {\n action: \"zoomOut\",\n name: \"Zoom Out\",\n description: \"Zoom out on the canvas\",\n category: \"canvas\",\n defaultBinding: \"mod+minus\",\n customizable: true,\n },\n {\n action: \"zoomFit\",\n name: \"Zoom to Fit\",\n description: \"Fit all nodes in view\",\n category: \"canvas\",\n defaultBinding: \"mod+0\",\n customizable: true,\n },\n {\n action: \"panMode\",\n name: \"Pan Mode\",\n description: \"Hold to pan the canvas\",\n category: \"canvas\",\n defaultBinding: \"space\",\n customizable: false, // Special handling for hold\n },\n\n // UI shortcuts\n {\n action: \"commandPalette\",\n name: \"Command Palette\",\n description: \"Open the command palette\",\n category: \"ui\",\n defaultBinding: \"mod+k\",\n customizable: true,\n },\n {\n action: \"showShortcuts\",\n name: \"Keyboard Shortcuts\",\n description: \"Show keyboard shortcuts help\",\n category: \"ui\",\n defaultBinding: \"mod+shift+slash\",\n customizable: true,\n },\n {\n action: \"toggleAIChat\",\n name: \"Toggle AI Chat\",\n description: \"Open or close the AI chat panel\",\n category: \"ui\",\n defaultBinding: \"mod+slash\",\n customizable: true,\n },\n {\n action: \"toggleLibrary\",\n name: \"Toggle Workflow Library\",\n description: \"Show or hide the workflow library\",\n category: \"ui\",\n defaultBinding: \"mod+b\",\n customizable: true,\n },\n {\n action: \"settings\",\n name: \"Open Settings\",\n description: \"Open the settings modal\",\n category: \"ui\",\n defaultBinding: \"mod+comma\",\n customizable: true,\n },\n {\n action: \"toggleNodePalette\",\n name: \"Toggle Node Palette\",\n description: \"Show or hide the node palette\",\n category: \"ui\",\n defaultBinding: \"mod+p\",\n customizable: true,\n },\n\n // User-assignable (no default)\n {\n action: \"cancelExecution\",\n name: \"Cancel Execution\",\n description: \"Stop the running workflow\",\n category: \"workflow\",\n defaultBinding: null,\n customizable: true,\n },\n {\n action: \"focusSearch\",\n name: \"Focus Search\",\n description: \"Focus the node search field\",\n category: \"ui\",\n defaultBinding: null,\n customizable: true,\n },\n];\n\n/** Get default shortcuts as a record */\nexport function getDefaultShortcuts(): Record<ShortcutAction, string | null> {\n const defaults: Partial<Record<ShortcutAction, string | null>> = {};\n for (const def of SHORTCUT_DEFINITIONS) {\n defaults[def.action] = def.defaultBinding;\n }\n return defaults as Record<ShortcutAction, string | null>;\n}\n\n/** Get shortcut definition by action */\nexport function getShortcutDefinition(action: ShortcutAction): ShortcutDefinition | undefined {\n return SHORTCUT_DEFINITIONS.find((d) => d.action === action);\n}\n\n/** Get shortcuts grouped by category */\nexport function getShortcutsByCategory(): Record<ShortcutCategory, ShortcutDefinition[]> {\n const grouped: Record<ShortcutCategory, ShortcutDefinition[]> = {\n workflow: [],\n editing: [],\n canvas: [],\n ui: [],\n };\n\n for (const def of SHORTCUT_DEFINITIONS) {\n grouped[def.category].push(def);\n }\n\n return grouped;\n}\n\n/** Category display names */\nexport const CATEGORY_NAMES: Record<ShortcutCategory, string> = {\n workflow: \"Workflow\",\n editing: \"Editing\",\n canvas: \"Canvas\",\n ui: \"Interface\",\n};\n","/**\n * Keyboard shortcut conflict detection\n */\n\nimport type { ConflictCheckResult, ShortcutAction } from \"./types\";\nimport { SHORTCUT_DEFINITIONS } from \"./shortcuts\";\n\n/**\n * Browser-reserved shortcuts that cannot be overridden\n * These are blocked by browsers and will not work in web apps\n */\nexport const BROWSER_RESERVED = [\n \"mod+w\", // Close tab\n \"mod+t\", // New tab\n \"mod+n\", // New window (can sometimes work, but risky)\n \"mod+q\", // Quit browser\n \"mod+r\", // Refresh\n \"mod+shift+r\", // Hard refresh\n \"mod+shift+t\", // Reopen closed tab\n \"mod+shift+n\", // New incognito window\n \"mod+shift+i\", // DevTools\n \"mod+shift+j\", // DevTools console\n \"mod+alt+i\", // DevTools (Chrome)\n \"mod+alt+j\", // DevTools console (Chrome)\n \"f5\", // Refresh\n \"f11\", // Fullscreen\n \"f12\", // DevTools\n \"alt+f4\", // Close window (Windows)\n];\n\n/**\n * React Flow's built-in shortcuts that we should warn about\n */\nexport const REACT_FLOW_DEFAULTS = [\n \"delete\", // Delete selected\n \"backspace\", // Delete selected\n];\n\n/**\n * Check if a binding conflicts with browser reserved shortcuts\n */\nexport function isBrowserReserved(binding: string): boolean {\n const normalized = binding.toLowerCase().replace(/\\s+/g, \"\");\n return BROWSER_RESERVED.includes(normalized);\n}\n\n/**\n * Check if a binding conflicts with React Flow defaults\n */\nexport function isReactFlowDefault(binding: string): boolean {\n const normalized = binding.toLowerCase().replace(/\\s+/g, \"\");\n // Handle comma-separated bindings\n const bindings = normalized.split(\",\");\n return bindings.some((b) => REACT_FLOW_DEFAULTS.includes(b));\n}\n\n/**\n * Check if a binding conflicts with an existing shortcut\n */\nexport function checkShortcutConflict(\n binding: string,\n currentShortcuts: Partial<Record<ShortcutAction, string>>,\n excludeAction?: ShortcutAction\n): ConflictCheckResult {\n // Check browser reserved first\n if (isBrowserReserved(binding)) {\n return {\n hasConflict: true,\n conflictType: \"browser\",\n message: \"This shortcut is reserved by the browser and cannot be used\",\n };\n }\n\n // Check React Flow defaults\n if (isReactFlowDefault(binding)) {\n return {\n hasConflict: true,\n conflictType: \"reactflow\",\n message: \"This shortcut is used by the canvas for node deletion\",\n };\n }\n\n // Check internal conflicts\n const normalized = binding.toLowerCase().replace(/\\s+/g, \"\");\n\n for (const [action, existingBinding] of Object.entries(currentShortcuts)) {\n if (action === excludeAction) continue;\n if (!existingBinding) continue;\n\n const existingNormalized = existingBinding.toLowerCase().replace(/\\s+/g, \"\");\n\n // Handle comma-separated bindings\n const newBindings = normalized.split(\",\");\n const existingBindings = existingNormalized.split(\",\");\n\n for (const nb of newBindings) {\n for (const eb of existingBindings) {\n if (nb === eb) {\n const def = SHORTCUT_DEFINITIONS.find((d) => d.action === action);\n return {\n hasConflict: true,\n conflictType: \"internal\",\n message: `This shortcut is already used by \"${def?.name || action}\"`,\n conflictingAction: action as ShortcutAction,\n };\n }\n }\n }\n }\n\n return { hasConflict: false };\n}\n\n/**\n * Validate a binding string format\n */\nexport function isValidBinding(binding: string): boolean {\n if (!binding || binding.trim() === \"\") return false;\n\n const parts = binding.toLowerCase().split(\"+\");\n\n // Must have at least one non-modifier key\n const modifiers = [\"mod\", \"ctrl\", \"control\", \"alt\", \"option\", \"shift\", \"meta\", \"cmd\", \"command\"];\n const nonModifiers = parts.filter((p) => !modifiers.includes(p));\n\n if (nonModifiers.length === 0) return false;\n\n // Check for valid key names\n const validKeys =\n /^[a-z0-9]$|^f[1-9]$|^f1[0-2]$|^(enter|return|escape|backspace|delete|space|tab|comma|slash|equal|minus|period|arrowup|arrowdown|arrowleft|arrowright)$/;\n\n for (const key of nonModifiers) {\n if (!validKeys.test(key)) return false;\n }\n\n return true;\n}\n","import { create } from \"zustand\";\nimport { persist } from \"zustand/middleware\";\nimport type { ShortcutAction } from \"../lib/keyboard/types\";\nimport { VALID_SHORTCUT_ACTIONS } from \"../lib/keyboard/types\";\nimport { getDefaultShortcuts } from \"../lib/keyboard/shortcuts\";\nimport { checkShortcutConflict, isValidBinding } from \"../lib/keyboard/conflicts\";\n\n// Provider configuration for cloud APIs\ninterface CloudProvider {\n apiKey: string;\n enabled: boolean;\n}\n\n// Provider configuration for local APIs\ninterface LocalProvider {\n baseUrl: string;\n enabled: boolean;\n}\n\n// All AI provider settings\nexport interface AISettings {\n // Cloud providers (require API keys)\n openai?: CloudProvider;\n anthropic?: CloudProvider;\n gemini?: CloudProvider;\n grok?: CloudProvider;\n openrouter?: CloudProvider;\n\n // Local providers (no API key, just URL)\n ollama?: LocalProvider;\n lmstudio?: LocalProvider;\n}\n\n// Keyboard settings\nexport interface KeyboardSettings {\n // User's custom shortcut overrides (action -> binding)\n shortcuts: Partial<Record<ShortcutAction, string>>;\n // Whether keyboard shortcuts are enabled globally\n enabled: boolean;\n}\n\ninterface SettingsStore {\n // AI provider settings\n ai: AISettings;\n setAIProvider: (provider: keyof AISettings, config: CloudProvider | LocalProvider) => void;\n clearAIProvider: (provider: keyof AISettings) => void;\n\n // Keyboard settings\n keyboard: KeyboardSettings;\n updateShortcut: (action: ShortcutAction, binding: string | null) => void;\n resetShortcut: (action: ShortcutAction) => void;\n resetAllShortcuts: () => void;\n isShortcutConflicting: (binding: string, excludeAction?: ShortcutAction) => string | null;\n\n // Settings modal visibility\n showSettings: boolean;\n openSettings: () => void;\n closeSettings: () => void;\n\n // Command palette modal\n showCommandPalette: boolean;\n openCommandPalette: () => void;\n closeCommandPalette: () => void;\n\n // Keyboard shortcuts help modal\n showShortcutsModal: boolean;\n openShortcutsModal: () => void;\n closeShortcutsModal: () => void;\n\n // Export modal\n showExport: boolean;\n openExport: () => void;\n closeExport: () => void;\n\n // Import modal\n showImport: boolean;\n openImport: () => void;\n closeImport: () => void;\n\n // New workflow confirmation dialog\n showNewWorkflowConfirm: boolean;\n newWorkflowConfirmCallback: (() => void) | null;\n requestNewWorkflow: (hasUnsavedChanges: boolean, onConfirm: () => void) => void;\n confirmNewWorkflow: () => void;\n cancelNewWorkflow: () => void;\n\n // Get configured providers for API calls\n getConfiguredProviders: () => {\n openai?: { apiKey: string };\n anthropic?: { apiKey: string };\n gemini?: { apiKey: string };\n grok?: { apiKey: string };\n openrouter?: { apiKey: string };\n ollama?: { baseUrl: string };\n lmstudio?: { baseUrl: string };\n };\n}\n\n// Default URLs for local providers\nconst DEFAULT_OLLAMA_URL = \"http://localhost:11434\";\nconst DEFAULT_LMSTUDIO_URL = \"http://localhost:1234\";\n\n/**\n * Validate and sanitize keyboard settings loaded from localStorage.\n * This prevents malicious or corrupted data from causing issues.\n */\nfunction validateKeyboardSettings(stored: unknown): KeyboardSettings {\n const defaultSettings: KeyboardSettings = {\n shortcuts: {},\n enabled: true,\n };\n\n // If stored is not an object, return defaults\n if (!stored || typeof stored !== \"object\") {\n return defaultSettings;\n }\n\n const settings = stored as Record<string, unknown>;\n\n // Validate 'enabled' field\n const enabled = typeof settings.enabled === \"boolean\" ? settings.enabled : true;\n\n // Validate shortcuts object\n const validatedShortcuts: Partial<Record<ShortcutAction, string>> = {};\n\n if (settings.shortcuts && typeof settings.shortcuts === \"object\") {\n const shortcuts = settings.shortcuts as Record<string, unknown>;\n\n for (const [action, binding] of Object.entries(shortcuts)) {\n // Skip if action is not a valid ShortcutAction\n if (!VALID_SHORTCUT_ACTIONS.includes(action as ShortcutAction)) {\n console.warn(`[Settings] Removing invalid shortcut action: ${action}`);\n continue;\n }\n\n // Skip if binding is not a string or null\n if (binding !== null && typeof binding !== \"string\") {\n console.warn(`[Settings] Removing invalid binding for ${action}: ${binding}`);\n continue;\n }\n\n // Skip if binding is a string but not a valid format\n if (typeof binding === \"string\" && !isValidBinding(binding)) {\n console.warn(`[Settings] Removing invalid binding format for ${action}: ${binding}`);\n continue;\n }\n\n // Valid shortcut override\n if (binding === null) {\n validatedShortcuts[action as ShortcutAction] = undefined as unknown as string;\n } else {\n validatedShortcuts[action as ShortcutAction] = binding;\n }\n }\n }\n\n return {\n shortcuts: validatedShortcuts,\n enabled,\n };\n}\n\nexport const useSettingsStore = create<SettingsStore>()(\n persist(\n (set, get) => ({\n ai: {\n ollama: {\n baseUrl: DEFAULT_OLLAMA_URL,\n enabled: false,\n },\n lmstudio: {\n baseUrl: DEFAULT_LMSTUDIO_URL,\n enabled: false,\n },\n },\n\n // Keyboard settings with defaults\n keyboard: {\n shortcuts: {},\n enabled: true,\n },\n\n // Modal visibility states\n showSettings: false,\n showCommandPalette: false,\n showShortcutsModal: false,\n showExport: false,\n showImport: false,\n showNewWorkflowConfirm: false,\n newWorkflowConfirmCallback: null,\n\n setAIProvider: (provider, config) => {\n set((state) => ({\n ai: {\n ...state.ai,\n [provider]: config,\n },\n }));\n },\n\n clearAIProvider: (provider) => {\n set((state) => {\n const newAI = { ...state.ai };\n delete newAI[provider];\n return { ai: newAI };\n });\n },\n\n // Keyboard shortcut methods\n updateShortcut: (action, binding) => {\n set((state) => ({\n keyboard: {\n ...state.keyboard,\n shortcuts: {\n ...state.keyboard.shortcuts,\n [action]: binding ?? undefined,\n },\n },\n }));\n },\n\n resetShortcut: (action) => {\n set((state) => {\n const newShortcuts = { ...state.keyboard.shortcuts };\n delete newShortcuts[action];\n return {\n keyboard: {\n ...state.keyboard,\n shortcuts: newShortcuts,\n },\n };\n });\n },\n\n resetAllShortcuts: () => {\n set((state) => ({\n keyboard: {\n ...state.keyboard,\n shortcuts: {},\n },\n }));\n },\n\n isShortcutConflicting: (binding, excludeAction) => {\n const { keyboard } = get();\n // Merge defaults with user overrides\n const defaults = getDefaultShortcuts();\n const currentShortcuts: Partial<Record<ShortcutAction, string>> = {};\n\n for (const [action, defaultBinding] of Object.entries(defaults)) {\n const userBinding = keyboard.shortcuts[action as ShortcutAction];\n if (userBinding !== undefined) {\n currentShortcuts[action as ShortcutAction] = userBinding;\n } else if (defaultBinding) {\n currentShortcuts[action as ShortcutAction] = defaultBinding;\n }\n }\n\n const result = checkShortcutConflict(binding, currentShortcuts, excludeAction);\n return result.hasConflict ? (result.message ?? \"Conflict detected\") : null;\n },\n\n // Modal controls\n openSettings: () => set({ showSettings: true }),\n closeSettings: () => set({ showSettings: false }),\n\n openCommandPalette: () => set({ showCommandPalette: true }),\n closeCommandPalette: () => set({ showCommandPalette: false }),\n\n openShortcutsModal: () => set({ showShortcutsModal: true }),\n closeShortcutsModal: () => set({ showShortcutsModal: false }),\n\n openExport: () => set({ showExport: true }),\n closeExport: () => set({ showExport: false }),\n\n openImport: () => set({ showImport: true }),\n closeImport: () => set({ showImport: false }),\n\n // New workflow confirmation\n requestNewWorkflow: (hasUnsavedChanges, onConfirm) => {\n if (hasUnsavedChanges) {\n set({ showNewWorkflowConfirm: true, newWorkflowConfirmCallback: onConfirm });\n } else {\n onConfirm();\n }\n },\n confirmNewWorkflow: () => {\n const callback = get().newWorkflowConfirmCallback;\n set({ showNewWorkflowConfirm: false, newWorkflowConfirmCallback: null });\n callback?.();\n },\n cancelNewWorkflow: () => {\n set({ showNewWorkflowConfirm: false, newWorkflowConfirmCallback: null });\n },\n\n getConfiguredProviders: () => {\n const { ai } = get();\n const result: ReturnType<SettingsStore[\"getConfiguredProviders\"]> = {};\n\n // Cloud providers - only include if enabled and has API key\n if (ai.openai?.enabled && ai.openai.apiKey) {\n result.openai = { apiKey: ai.openai.apiKey };\n }\n if (ai.anthropic?.enabled && ai.anthropic.apiKey) {\n result.anthropic = { apiKey: ai.anthropic.apiKey };\n }\n if (ai.gemini?.enabled && ai.gemini.apiKey) {\n result.gemini = { apiKey: ai.gemini.apiKey };\n }\n if (ai.grok?.enabled && ai.grok.apiKey) {\n result.grok = { apiKey: ai.grok.apiKey };\n }\n if (ai.openrouter?.enabled && ai.openrouter.apiKey) {\n result.openrouter = { apiKey: ai.openrouter.apiKey };\n }\n\n // Local providers - only include if enabled\n if (ai.ollama?.enabled) {\n result.ollama = { baseUrl: ai.ollama.baseUrl || DEFAULT_OLLAMA_URL };\n }\n if (ai.lmstudio?.enabled) {\n result.lmstudio = { baseUrl: ai.lmstudio.baseUrl || DEFAULT_LMSTUDIO_URL };\n }\n\n return result;\n },\n }),\n {\n name: \"floimg-studio-settings\",\n // Persist AI settings and keyboard settings, not modal visibility\n partialize: (state) => ({\n ai: state.ai,\n keyboard: state.keyboard,\n }),\n // Validate persisted data on load to prevent malicious/corrupted data\n merge: (persistedState, currentState) => {\n const persisted = persistedState as Partial<SettingsStore> | undefined;\n\n return {\n ...currentState,\n ai: persisted?.ai ?? currentState.ai,\n keyboard: validateKeyboardSettings(persisted?.keyboard),\n };\n },\n }\n )\n);\n","import { create } from \"zustand\";\nimport { persist } from \"zustand/middleware\";\nimport type { Node, Edge, Connection } from \"reactflow\";\nimport type {\n GeneratorNodeData,\n TransformNodeData,\n SaveNodeData,\n InputNodeData,\n VisionNodeData,\n TextNodeData,\n FanOutNodeData,\n CollectNodeData,\n RouterNodeData,\n NodeDefinition,\n GeneratedWorkflowData,\n StudioNodeType,\n ExecutionSSEEvent,\n} from \"@teamflojo/floimg-studio-shared\";\nimport type { Template } from \"@teamflojo/floimg-templates\";\nimport { exportYaml } from \"../api/client\";\nimport { createSSEConnection, type SSEConnection } from \"../api/sse\";\n\n// Module-level variable to store active SSE connection (not in store since it's not serializable)\nlet activeExecutionConnection: SSEConnection | null = null;\nimport type { StudioNode, StudioEdge, StudioNodeData } from \"@teamflojo/floimg-studio-shared\";\nimport { useSettingsStore } from \"./settingsStore\";\n\ntype NodeData =\n | GeneratorNodeData\n | TransformNodeData\n | SaveNodeData\n | InputNodeData\n | VisionNodeData\n | TextNodeData\n | FanOutNodeData\n | CollectNodeData\n | RouterNodeData;\n\ntype NodeExecutionStatus = \"idle\" | \"pending\" | \"running\" | \"completed\" | \"error\";\n\ninterface DataOutput {\n dataType: \"text\" | \"json\";\n content: string;\n parsed?: Record<string, unknown>;\n}\n\n// Saved workflow structure for persistence\nexport interface SavedWorkflow {\n id: string;\n name: string;\n nodes: Node<NodeData>[];\n edges: Edge[];\n createdAt: number;\n updatedAt: number;\n templateId?: string;\n}\n\ninterface ExecutionState {\n status: \"idle\" | \"running\" | \"completed\" | \"error\";\n imageIds: string[];\n imageUrls: string[]; // Presigned cloud URLs for thumbnails (FSC only)\n previews: Record<string, string>; // nodeId -> data URL\n dataOutputs: Record<string, DataOutput>; // nodeId -> text/json output (for vision/text nodes)\n nodeStatus: Record<string, NodeExecutionStatus>; // per-node execution status\n error?: string;\n}\n\ninterface WorkflowStore {\n // Nodes and edges (React Flow compatible)\n nodes: Node<NodeData>[];\n edges: Edge[];\n selectedNodeId: string | null;\n\n // Template tracking\n currentTemplateId: string | null;\n loadTemplate: (template: Template) => void;\n clearWorkflow: () => void;\n\n // Workflow persistence\n savedWorkflows: SavedWorkflow[];\n activeWorkflowId: string | null;\n activeWorkflowName: string;\n hasUnsavedChanges: boolean;\n showLibrary: boolean;\n\n // Workflow persistence methods\n saveWorkflow: (name?: string) => string;\n loadWorkflow: (id: string) => void;\n deleteWorkflow: (id: string) => void;\n renameWorkflow: (id: string, name: string) => void;\n duplicateWorkflow: (id: string) => string;\n newWorkflow: () => void;\n setActiveWorkflowName: (name: string) => void;\n toggleLibrary: () => void;\n markDirty: () => void;\n\n // Preview visibility per node (default: true)\n previewVisible: Record<string, boolean>;\n togglePreview: (id: string) => void;\n\n // Node registry\n generators: NodeDefinition[];\n transforms: NodeDefinition[];\n textProviders: NodeDefinition[];\n visionProviders: NodeDefinition[];\n setGenerators: (generators: NodeDefinition[]) => void;\n setTransforms: (transforms: NodeDefinition[]) => void;\n setTextProviders: (textProviders: NodeDefinition[]) => void;\n setVisionProviders: (visionProviders: NodeDefinition[]) => void;\n\n // Node operations\n addNode: (definition: NodeDefinition, position: { x: number; y: number }) => void;\n updateNodeData: (id: string, data: Partial<NodeData>) => void;\n deleteNode: (id: string) => void;\n duplicateNode: (id: string) => void;\n setNodes: (nodes: Node<NodeData>[]) => void;\n\n // Edge operations\n addEdge: (connection: Connection) => void;\n deleteEdge: (id: string) => void;\n setEdges: (edges: Edge[]) => void;\n\n // Selection\n setSelectedNode: (id: string | null) => void;\n\n // Execution\n execution: ExecutionState;\n execute: () => Promise<void>;\n cancelExecution: () => void;\n\n // Export\n exportToYaml: () => Promise<string>;\n\n // Import\n importFromYaml: (nodes: StudioNode[], edges: StudioEdge[], name?: string) => void;\n\n // AI-generated workflow\n loadGeneratedWorkflow: (workflow: GeneratedWorkflowData) => void;\n\n // Output inspector\n inspectedNodeId: string | null;\n openOutputInspector: (nodeId: string) => void;\n closeOutputInspector: () => void;\n}\n\nlet nodeIdCounter = 0;\n\nfunction generateNodeId(): string {\n return `node_${++nodeIdCounter}`;\n}\n\n// Helper to generate unique workflow IDs\nfunction generateWorkflowId(): string {\n const timestamp = Date.now();\n const random = Math.random().toString(36).substring(2, 8);\n return `wf_${timestamp}_${random}`;\n}\n\nexport const useWorkflowStore = create<WorkflowStore>()(\n persist(\n (set, get) => {\n // Helper to enrich node data with definition properties (isAI, acceptsReferenceImages, etc.)\n // Used by loadTemplate, importFromYaml, and loadGeneratedWorkflow\n const enrichNodeData = (studioNode: StudioNode): NodeData => {\n if (studioNode.type === \"generator\") {\n const data = studioNode.data as GeneratorNodeData;\n const def = get().generators.find((g) => g.name === data.generatorName);\n return {\n ...data,\n isAI: data.isAI ?? def?.isAI,\n acceptsReferenceImages: data.acceptsReferenceImages ?? def?.acceptsReferenceImages,\n maxReferenceImages: data.maxReferenceImages ?? def?.maxReferenceImages,\n };\n }\n if (studioNode.type === \"transform\") {\n const data = studioNode.data as TransformNodeData;\n const def = get().transforms.find(\n (t) => t.name === data.operation && t.providerName === data.providerName\n );\n return {\n ...data,\n isAI: data.isAI ?? def?.isAI,\n acceptsReferenceImages: data.acceptsReferenceImages ?? def?.acceptsReferenceImages,\n maxReferenceImages: data.maxReferenceImages ?? def?.maxReferenceImages,\n };\n }\n return studioNode.data as NodeData;\n };\n\n return {\n nodes: [],\n edges: [],\n selectedNodeId: null,\n currentTemplateId: null,\n previewVisible: {},\n generators: [],\n transforms: [],\n textProviders: [],\n visionProviders: [],\n\n // Workflow persistence state\n savedWorkflows: [],\n activeWorkflowId: null,\n activeWorkflowName: \"Untitled Workflow\",\n hasUnsavedChanges: false,\n showLibrary: false,\n\n execution: {\n status: \"idle\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: {},\n },\n\n // Output inspector state\n inspectedNodeId: null,\n openOutputInspector: (nodeId) => set({ inspectedNodeId: nodeId }),\n closeOutputInspector: () => set({ inspectedNodeId: null }),\n\n loadTemplate: (template) => {\n // Convert StudioNodes to React Flow nodes with new IDs\n const idMap = new Map<string, string>();\n\n const nodes: Node<NodeData>[] = template.workflow.nodes.map((studioNode) => {\n const newId = generateNodeId();\n idMap.set(studioNode.id, newId);\n\n return {\n id: newId,\n type: studioNode.type,\n position: studioNode.position,\n data: enrichNodeData(studioNode),\n };\n });\n\n // Convert edges with mapped IDs\n const edges: Edge[] = template.workflow.edges.map((studioEdge) => {\n const newSource = idMap.get(studioEdge.source) || studioEdge.source;\n const newTarget = idMap.get(studioEdge.target) || studioEdge.target;\n\n return {\n id: `edge_${newSource}_${newTarget}`,\n source: newSource,\n target: newTarget,\n };\n });\n\n set({\n nodes,\n edges,\n selectedNodeId: null,\n currentTemplateId: template.id,\n previewVisible: {},\n execution: {\n status: \"idle\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: {},\n },\n });\n },\n\n clearWorkflow: () => {\n set({\n nodes: [],\n edges: [],\n selectedNodeId: null,\n currentTemplateId: null,\n previewVisible: {},\n execution: {\n status: \"idle\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: {},\n },\n });\n },\n\n togglePreview: (id) => {\n set((state) => ({\n previewVisible: {\n ...state.previewVisible,\n [id]: state.previewVisible[id] === false ? true : false, // default true, toggle\n },\n }));\n },\n\n setGenerators: (generators) => set({ generators }),\n setTransforms: (transforms) => set({ transforms }),\n setTextProviders: (textProviders) => set({ textProviders }),\n setVisionProviders: (visionProviders) => set({ visionProviders }),\n\n addNode: (definition, position) => {\n const id = generateNodeId();\n let data: NodeData;\n\n if (definition.type === \"generator\") {\n data = {\n generatorName: definition.name,\n params: getDefaultParams(definition),\n isAI: definition.isAI, // Track if this is an AI generator (can accept text input)\n acceptsReferenceImages: definition.acceptsReferenceImages,\n maxReferenceImages: definition.maxReferenceImages,\n } as GeneratorNodeData;\n } else if (definition.type === \"transform\") {\n data = {\n operation: definition.name,\n providerName: definition.providerName, // Track which provider this transform belongs to\n isAI: definition.isAI, // Track if this is an AI transform (can accept text input)\n params: getDefaultParams(definition),\n acceptsReferenceImages: definition.acceptsReferenceImages,\n maxReferenceImages: definition.maxReferenceImages,\n } as TransformNodeData;\n } else if (definition.type === \"input\") {\n data = {\n uploadId: undefined,\n filename: undefined,\n mime: undefined,\n } as InputNodeData;\n } else if (definition.type === \"vision\") {\n data = {\n providerName: definition.name,\n providerLabel: definition.label, // Human-readable label (e.g., \"Gemini Vision\")\n params: getDefaultParams(definition),\n } as VisionNodeData;\n } else if (definition.type === \"text\") {\n data = {\n providerName: definition.name,\n providerLabel: definition.label, // Human-readable label (e.g., \"Gemini Text\")\n params: getDefaultParams(definition),\n } as TextNodeData;\n } else {\n // Save node - read provider and destination from definition params\n const props = definition.params?.properties || {};\n const provider = (props.provider?.default as string) || \"filesystem\";\n const destination = (props.destination?.default as string) || \"./output/image.png\";\n data = {\n destination,\n provider,\n } as SaveNodeData;\n }\n\n const newNode: Node<NodeData> = {\n id,\n type: definition.type,\n position,\n data,\n };\n\n set((state) => ({\n nodes: [...state.nodes, newNode],\n }));\n },\n\n updateNodeData: (id, data) => {\n set((state) => ({\n nodes: state.nodes.map((node) =>\n node.id === id ? { ...node, data: { ...node.data, ...data } } : node\n ),\n }));\n },\n\n deleteNode: (id) => {\n set((state) => ({\n nodes: state.nodes.filter((n) => n.id !== id),\n edges: state.edges.filter((e) => e.source !== id && e.target !== id),\n selectedNodeId: state.selectedNodeId === id ? null : state.selectedNodeId,\n }));\n },\n\n duplicateNode: (id) => {\n const state = get();\n const nodeToDuplicate = state.nodes.find((n) => n.id === id);\n if (!nodeToDuplicate) return;\n\n const newId = generateNodeId();\n const newNode: Node<NodeData> = {\n ...nodeToDuplicate,\n id: newId,\n position: {\n x: nodeToDuplicate.position.x + 50,\n y: nodeToDuplicate.position.y + 50,\n },\n data: JSON.parse(JSON.stringify(nodeToDuplicate.data)), // Deep clone\n selected: false,\n };\n\n set({\n nodes: [...state.nodes, newNode],\n selectedNodeId: newId, // Select the new node\n });\n },\n\n setNodes: (nodes) => set({ nodes }),\n\n addEdge: (connection) => {\n if (!connection.source || !connection.target) return;\n\n // Include sourceHandle and targetHandle in edge ID for uniqueness\n const handleSuffix = [connection.sourceHandle, connection.targetHandle]\n .filter(Boolean)\n .join(\"_\");\n const id = handleSuffix\n ? `edge_${connection.source}_${connection.target}_${handleSuffix}`\n : `edge_${connection.source}_${connection.target}`;\n\n const newEdge: Edge = {\n id,\n source: connection.source,\n target: connection.target,\n sourceHandle: connection.sourceHandle ?? undefined,\n targetHandle: connection.targetHandle ?? undefined,\n };\n\n set((state) => ({\n edges: [...state.edges, newEdge],\n }));\n },\n\n deleteEdge: (id) => {\n set((state) => ({\n edges: state.edges.filter((e) => e.id !== id),\n }));\n },\n\n setEdges: (edges) => set({ edges }),\n\n setSelectedNode: (id) => set({ selectedNodeId: id }),\n\n execute: async () => {\n const { nodes, edges } = get();\n\n // Convert React Flow nodes to StudioNodes\n const studioNodes = nodes.map((n) => ({\n id: n.id,\n type: n.type as \"generator\" | \"transform\" | \"save\",\n position: n.position,\n data: n.data,\n }));\n\n const studioEdges = edges.map((e) => ({\n id: e.id,\n source: e.source,\n target: e.target,\n sourceHandle: e.sourceHandle ?? undefined,\n targetHandle: e.targetHandle ?? undefined,\n }));\n\n // Get AI provider settings\n const aiProviders = useSettingsStore.getState().getConfiguredProviders();\n\n // Set all nodes to \"pending\" status (not running yet)\n const initialNodeStatus: Record<string, NodeExecutionStatus> = {};\n for (const node of nodes) {\n initialNodeStatus[node.id] = \"pending\";\n }\n\n set({\n execution: {\n status: \"running\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: initialNodeStatus,\n },\n });\n\n // Use SSE streaming for real-time progress updates\n return new Promise<void>((resolve, reject) => {\n activeExecutionConnection = createSSEConnection<ExecutionSSEEvent>(\n \"/api/execute/stream\",\n { nodes: studioNodes, edges: studioEdges, aiProviders },\n {\n onMessage: (event) => {\n const state = get();\n\n if (event.type === \"execution.started\") {\n // All nodes start as pending, they'll transition to running as they execute\n }\n\n if (event.type === \"execution.step\") {\n const step = event.data;\n\n // Update the specific node's status\n const newNodeStatus = {\n ...state.execution.nodeStatus,\n [step.nodeId]: step.status as NodeExecutionStatus,\n };\n\n // Update previews if this step has one\n const newPreviews = step.preview\n ? { ...state.execution.previews, [step.nodeId]: step.preview }\n : state.execution.previews;\n\n // Update dataOutputs if this is a text/vision node\n const newDataOutputs =\n step.dataType && step.content\n ? {\n ...state.execution.dataOutputs,\n [step.nodeId]: {\n dataType: step.dataType,\n content: step.content,\n parsed: step.parsed,\n },\n }\n : state.execution.dataOutputs;\n\n set({\n execution: {\n ...state.execution,\n nodeStatus: newNodeStatus,\n previews: newPreviews,\n dataOutputs: newDataOutputs,\n },\n });\n }\n\n if (event.type === \"execution.completed\") {\n // Mark any remaining pending nodes as completed\n const finalNodeStatus = { ...state.execution.nodeStatus };\n for (const nodeId of Object.keys(finalNodeStatus)) {\n if (\n finalNodeStatus[nodeId] === \"pending\" ||\n finalNodeStatus[nodeId] === \"running\"\n ) {\n finalNodeStatus[nodeId] = \"completed\";\n }\n }\n\n set({\n execution: {\n ...state.execution,\n status: \"completed\",\n imageIds: event.data.imageIds,\n imageUrls: event.data.imageUrls,\n nodeStatus: finalNodeStatus,\n },\n });\n resolve();\n }\n\n if (event.type === \"execution.error\") {\n // Mark nodes as error\n const errorNodeStatus = { ...state.execution.nodeStatus };\n if (event.data.nodeId) {\n errorNodeStatus[event.data.nodeId] = \"error\";\n }\n\n set({\n execution: {\n ...state.execution,\n status: \"error\",\n nodeStatus: errorNodeStatus,\n error: event.data.error,\n },\n });\n reject(new Error(event.data.error));\n }\n },\n onError: (error) => {\n const state = get();\n const errorNodeStatus: Record<string, NodeExecutionStatus> = {};\n for (const nodeId of Object.keys(state.execution.nodeStatus)) {\n errorNodeStatus[nodeId] = \"error\";\n }\n\n set({\n execution: {\n ...state.execution,\n status: \"error\",\n nodeStatus: errorNodeStatus,\n error: error.message,\n },\n });\n reject(error);\n },\n onClose: () => {\n // Clear the connection reference\n activeExecutionConnection = null;\n\n // Stream closed - check why\n const state = get();\n if (state.execution.status === \"running\") {\n // Check if this was a user cancellation (status would be 'cancelled' if so)\n // Otherwise treat as unexpected closure\n set({\n execution: {\n ...state.execution,\n status: \"error\",\n error: \"Connection closed unexpectedly\",\n },\n });\n reject(new Error(\"Connection closed unexpectedly\"));\n }\n },\n }\n );\n });\n },\n\n cancelExecution: () => {\n // Abort the active connection if any\n if (activeExecutionConnection) {\n activeExecutionConnection.abort();\n activeExecutionConnection = null;\n }\n\n // Reset execution state to idle\n set({\n execution: {\n status: \"idle\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: {},\n },\n });\n },\n\n exportToYaml: async () => {\n const { nodes, edges } = get();\n\n const studioNodes = nodes.map((n) => ({\n id: n.id,\n type: n.type as \"generator\" | \"transform\" | \"save\",\n position: n.position,\n data: n.data,\n }));\n\n const studioEdges = edges.map((e) => ({\n id: e.id,\n source: e.source,\n target: e.target,\n sourceHandle: e.sourceHandle ?? undefined,\n targetHandle: e.targetHandle ?? undefined,\n }));\n\n const result = await exportYaml(studioNodes, studioEdges);\n return result.yaml;\n },\n\n importFromYaml: (studioNodes, studioEdges, name) => {\n // Convert StudioNodes to React Flow nodes with new IDs\n const idMap = new Map<string, string>();\n\n const nodes: Node<NodeData>[] = studioNodes.map((studioNode) => {\n const newId = generateNodeId();\n idMap.set(studioNode.id, newId);\n\n return {\n id: newId,\n type: studioNode.type,\n position: studioNode.position,\n data: enrichNodeData(studioNode),\n };\n });\n\n // Convert edges with mapped IDs\n const edges: Edge[] = studioEdges.map((studioEdge) => {\n const newSource = idMap.get(studioEdge.source) || studioEdge.source;\n const newTarget = idMap.get(studioEdge.target) || studioEdge.target;\n\n return {\n id: `edge_${newSource}_${newTarget}`,\n source: newSource,\n target: newTarget,\n };\n });\n\n set({\n nodes,\n edges,\n selectedNodeId: null,\n currentTemplateId: null,\n previewVisible: {},\n activeWorkflowId: null,\n activeWorkflowName: name || \"Imported Workflow\",\n hasUnsavedChanges: true,\n execution: {\n status: \"idle\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: {},\n },\n });\n },\n\n // Workflow persistence methods\n markDirty: () => set({ hasUnsavedChanges: true }),\n\n toggleLibrary: () => set((state) => ({ showLibrary: !state.showLibrary })),\n\n setActiveWorkflowName: (name) => set({ activeWorkflowName: name, hasUnsavedChanges: true }),\n\n newWorkflow: () => {\n set({\n nodes: [],\n edges: [],\n selectedNodeId: null,\n currentTemplateId: null,\n previewVisible: {},\n activeWorkflowId: null,\n activeWorkflowName: \"Untitled Workflow\",\n hasUnsavedChanges: false,\n execution: {\n status: \"idle\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: {},\n },\n });\n },\n\n saveWorkflow: (name) => {\n const {\n nodes,\n edges,\n activeWorkflowId,\n activeWorkflowName,\n savedWorkflows,\n currentTemplateId,\n } = get();\n const now = Date.now();\n\n if (activeWorkflowId) {\n // Update existing workflow\n const updated = savedWorkflows.map((wf) =>\n wf.id === activeWorkflowId\n ? { ...wf, name: name || activeWorkflowName, nodes, edges, updatedAt: now }\n : wf\n );\n set({\n savedWorkflows: updated,\n activeWorkflowName: name || activeWorkflowName,\n hasUnsavedChanges: false,\n });\n return activeWorkflowId;\n } else {\n // Create new workflow\n const id = generateWorkflowId();\n const newWorkflow: SavedWorkflow = {\n id,\n name: name || activeWorkflowName,\n nodes,\n edges,\n createdAt: now,\n updatedAt: now,\n templateId: currentTemplateId || undefined,\n };\n set({\n savedWorkflows: [...savedWorkflows, newWorkflow],\n activeWorkflowId: id,\n activeWorkflowName: name || activeWorkflowName,\n hasUnsavedChanges: false,\n });\n return id;\n }\n },\n\n loadWorkflow: (id) => {\n const { savedWorkflows } = get();\n const workflow = savedWorkflows.find((wf) => wf.id === id);\n if (!workflow) return;\n\n // Enrich node data with definition properties (in case workflow was saved before enrichment existed)\n const enrichedNodes = workflow.nodes.map((node) => ({\n ...node,\n data: enrichNodeData({\n id: node.id,\n type: node.type as StudioNodeType,\n position: node.position,\n data: node.data as StudioNodeData,\n }),\n }));\n\n set({\n nodes: enrichedNodes,\n edges: workflow.edges,\n selectedNodeId: null,\n currentTemplateId: workflow.templateId || null,\n previewVisible: {},\n activeWorkflowId: id,\n activeWorkflowName: workflow.name,\n hasUnsavedChanges: false,\n execution: {\n status: \"idle\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: {},\n },\n });\n },\n\n deleteWorkflow: (id) => {\n const { savedWorkflows, activeWorkflowId } = get();\n const filtered = savedWorkflows.filter((wf) => wf.id !== id);\n\n if (activeWorkflowId === id) {\n // If deleting the active workflow, clear the canvas\n set({\n savedWorkflows: filtered,\n nodes: [],\n edges: [],\n selectedNodeId: null,\n currentTemplateId: null,\n previewVisible: {},\n activeWorkflowId: null,\n activeWorkflowName: \"Untitled Workflow\",\n hasUnsavedChanges: false,\n execution: {\n status: \"idle\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: {},\n },\n });\n } else {\n set({ savedWorkflows: filtered });\n }\n },\n\n renameWorkflow: (id, name) => {\n const { savedWorkflows, activeWorkflowId } = get();\n const updated = savedWorkflows.map((wf) =>\n wf.id === id ? { ...wf, name, updatedAt: Date.now() } : wf\n );\n set({\n savedWorkflows: updated,\n ...(activeWorkflowId === id ? { activeWorkflowName: name } : {}),\n });\n },\n\n duplicateWorkflow: (id) => {\n const { savedWorkflows } = get();\n const workflow = savedWorkflows.find((wf) => wf.id === id);\n if (!workflow) return \"\";\n\n const now = Date.now();\n const newId = generateWorkflowId();\n const duplicate: SavedWorkflow = {\n ...workflow,\n id: newId,\n name: `${workflow.name} (Copy)`,\n createdAt: now,\n updatedAt: now,\n };\n set({ savedWorkflows: [...savedWorkflows, duplicate] });\n return newId;\n },\n\n loadGeneratedWorkflow: (workflow: GeneratedWorkflowData) => {\n // Convert AI-generated workflow to React Flow nodes\n const idMap = new Map<string, string>();\n\n // Flow-based layout: arrange nodes left-to-right following data flow\n const COLUMN_SPACING = 300; // Horizontal space between columns\n const ROW_SPACING = 180; // Vertical space between nodes in same column\n\n // Step 1: Build dependency graph to compute node depths\n const incomingEdges = new Map<string, string[]>();\n const outgoingEdges = new Map<string, string[]>();\n for (const node of workflow.nodes) {\n incomingEdges.set(node.id, []);\n outgoingEdges.set(node.id, []);\n }\n for (const edge of workflow.edges) {\n incomingEdges.get(edge.target)?.push(edge.source);\n outgoingEdges.get(edge.source)?.push(edge.target);\n }\n\n // Step 2: Compute depth (column) for each node using topological order\n const nodeDepth = new Map<string, number>();\n const visited = new Set<string>();\n\n function computeDepth(nodeId: string): number {\n if (nodeDepth.has(nodeId)) return nodeDepth.get(nodeId)!;\n if (visited.has(nodeId)) return 0; // Cycle protection\n visited.add(nodeId);\n\n const incoming = incomingEdges.get(nodeId) || [];\n if (incoming.length === 0) {\n nodeDepth.set(nodeId, 0);\n return 0;\n }\n\n const maxParentDepth = Math.max(...incoming.map(computeDepth));\n const depth = maxParentDepth + 1;\n nodeDepth.set(nodeId, depth);\n return depth;\n }\n\n for (const node of workflow.nodes) {\n computeDepth(node.id);\n }\n\n // Step 3: Group nodes by depth (column)\n const nodesByDepth = new Map<number, string[]>();\n for (const node of workflow.nodes) {\n const depth = nodeDepth.get(node.id) || 0;\n if (!nodesByDepth.has(depth)) nodesByDepth.set(depth, []);\n nodesByDepth.get(depth)!.push(node.id);\n }\n\n // Step 4: Calculate positions based on depth and vertical index\n const nodePositions = new Map<string, { x: number; y: number }>();\n for (const [depth, nodeIds] of nodesByDepth) {\n const columnHeight = nodeIds.length * ROW_SPACING;\n const startY = 100 + (columnHeight > ROW_SPACING ? -columnHeight / 4 : 0);\n\n nodeIds.forEach((nodeId, verticalIndex) => {\n nodePositions.set(nodeId, {\n x: 100 + depth * COLUMN_SPACING,\n y: startY + verticalIndex * ROW_SPACING,\n });\n });\n }\n\n const nodes: Node<NodeData>[] = workflow.nodes.map((genNode) => {\n const newId = generateNodeId();\n idMap.set(genNode.id, newId);\n\n // Parse nodeType to extract type and name\n // Format: \"generator:dalle-3\", \"transform:sharp:resize\", \"input:upload\", \"flow:fanout\", etc.\n const parts = genNode.nodeType.split(\":\");\n\n // Use computed flow position\n const position = nodePositions.get(genNode.id) || { x: 100, y: 100 };\n\n // Handle flow control nodes specially (flow:fanout, flow:collect, flow:router)\n // The actual node type is the second part, not \"flow\"\n if (parts[0] === \"flow\") {\n const flowNodeType = parts[1] as \"fanout\" | \"collect\" | \"router\";\n let data: NodeData;\n\n if (flowNodeType === \"fanout\") {\n data = {\n mode: (genNode.parameters.mode as \"array\" | \"count\") || \"count\",\n count: (genNode.parameters.count as number) || 3,\n arrayProperty: genNode.parameters.arrayProperty as string | undefined,\n } as FanOutNodeData;\n } else if (flowNodeType === \"collect\") {\n data = {\n expectedInputs: (genNode.parameters.expectedCount as number) || 3,\n waitMode: \"all\",\n } as CollectNodeData;\n } else {\n // router\n data = {\n selectionProperty:\n (genNode.parameters.selectionProperty as string) || \"best_index\",\n selectionType: \"index\",\n outputCount: 1,\n contextProperty: genNode.parameters.contextProperty as string | undefined,\n } as RouterNodeData;\n }\n\n return {\n id: newId,\n type: flowNodeType as StudioNodeType,\n position,\n data,\n };\n }\n\n // Standard node types\n const nodeType = parts[0] as StudioNodeType;\n\n // Build node data based on type\n let data: NodeData;\n\n if (nodeType === \"generator\") {\n const generatorName = parts.slice(1).join(\":\");\n // Look up generator definition to get acceptsReferenceImages and other properties\n const generatorDef = get().generators.find((g) => g.name === generatorName);\n data = {\n generatorName,\n params: genNode.parameters,\n isAI: generatorDef?.isAI ?? true, // Use definition or assume AI\n acceptsReferenceImages: generatorDef?.acceptsReferenceImages,\n maxReferenceImages: generatorDef?.maxReferenceImages,\n } as GeneratorNodeData;\n } else if (nodeType === \"transform\") {\n const providerName = parts[1];\n const operation = parts.slice(2).join(\":\");\n // Look up transform definition to get isAI and acceptsReferenceImages\n const transformDef = get().transforms.find(\n (t) => t.providerName === providerName && t.name === operation\n );\n data = {\n operation,\n providerName,\n params: genNode.parameters,\n isAI: transformDef?.isAI,\n acceptsReferenceImages: transformDef?.acceptsReferenceImages,\n maxReferenceImages: transformDef?.maxReferenceImages,\n } as TransformNodeData;\n } else if (nodeType === \"input\") {\n data = {\n uploadId: undefined,\n filename: undefined,\n mime: undefined,\n } as InputNodeData;\n } else if (nodeType === \"vision\") {\n const providerName = parts.slice(1).join(\":\");\n data = {\n providerName,\n params: genNode.parameters,\n } as VisionNodeData;\n } else if (nodeType === \"text\") {\n const providerName = parts.slice(1).join(\":\");\n // Extract jsonSchema from params and convert to outputSchema for UI\n const jsonSchema = genNode.parameters.jsonSchema as\n | { properties?: Record<string, { type?: string; description?: string }> }\n | undefined;\n const outputSchema = jsonSchema?.properties\n ? {\n type: \"object\" as const,\n properties: Object.fromEntries(\n Object.entries(jsonSchema.properties).map(([key, prop]) => [\n key,\n {\n type:\n (prop.type as \"string\" | \"number\" | \"boolean\" | \"object\" | \"array\") ||\n \"string\",\n description: prop.description,\n },\n ])\n ),\n }\n : undefined;\n data = {\n providerName,\n params: genNode.parameters,\n outputSchema,\n } as TextNodeData;\n } else {\n // Default to save node\n data = {\n destination: (genNode.parameters.destination as string) || \"./output/image.png\",\n provider: (genNode.parameters.provider as string) || \"filesystem\",\n } as SaveNodeData;\n }\n\n return {\n id: newId,\n type: nodeType,\n position,\n data,\n };\n });\n\n // Convert edges with mapped IDs\n const edges: Edge[] = workflow.edges.map((genEdge) => {\n const newSource = idMap.get(genEdge.source) || genEdge.source;\n const newTarget = idMap.get(genEdge.target) || genEdge.target;\n\n // Include handles in edge ID for uniqueness (multiple edges from same source)\n const handleSuffix = [genEdge.sourceHandle, genEdge.targetHandle]\n .filter(Boolean)\n .join(\"_\");\n const edgeId = handleSuffix\n ? `edge_${newSource}_${newTarget}_${handleSuffix}`\n : `edge_${newSource}_${newTarget}`;\n\n return {\n id: edgeId,\n source: newSource,\n target: newTarget,\n sourceHandle: genEdge.sourceHandle ?? undefined,\n targetHandle: genEdge.targetHandle ?? undefined,\n };\n });\n\n set({\n nodes,\n edges,\n selectedNodeId: null,\n currentTemplateId: null,\n previewVisible: {},\n activeWorkflowId: null,\n activeWorkflowName: \"AI Generated Workflow\",\n hasUnsavedChanges: true,\n execution: {\n status: \"idle\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: {},\n },\n });\n },\n };\n },\n {\n name: \"floimg-studio-workflows\",\n // Only persist savedWorkflows - current canvas state is ephemeral\n partialize: (state) => ({\n savedWorkflows: state.savedWorkflows,\n }),\n }\n )\n);\n\n// Helper to extract default values from schema\nfunction getDefaultParams(definition: NodeDefinition): Record<string, unknown> {\n const params: Record<string, unknown> = {};\n\n if (definition.params?.properties) {\n for (const [key, field] of Object.entries(definition.params.properties)) {\n if (field.default !== undefined) {\n params[key] = field.default;\n }\n }\n }\n\n return params;\n}\n","import { memo, useCallback, useRef } from \"react\";\nimport { Handle, Position, type NodeProps } from \"reactflow\";\nimport type {\n GeneratorNodeData,\n TransformNodeData,\n SaveNodeData,\n InputNodeData,\n VisionNodeData,\n TextNodeData,\n FanOutNodeData,\n CollectNodeData,\n RouterNodeData,\n} from \"@teamflojo/floimg-studio-shared\";\nimport { useWorkflowStore } from \"../stores/workflowStore\";\nimport { uploadImage, getUploadBlobUrl } from \"../api/client\";\n\n// Helper to get execution status class for node styling\nfunction getExecutionClass(nodeStatus: string | undefined): string {\n if (nodeStatus === \"pending\") return \"floimg-node--pending\";\n if (nodeStatus === \"running\") return \"floimg-node--running\";\n if (nodeStatus === \"completed\") return \"floimg-node--completed\";\n if (nodeStatus === \"error\") return \"floimg-node--error\";\n return \"\";\n}\n\n// Eye icon for preview toggle\nfunction PreviewToggle({ nodeId, color }: { nodeId: string; color: string }) {\n const previewVisible = useWorkflowStore((s) => s.previewVisible[nodeId] !== false);\n const togglePreview = useWorkflowStore((s) => s.togglePreview);\n\n return (\n <button\n onClick={(e) => {\n e.stopPropagation();\n togglePreview(nodeId);\n }}\n className={`ml-auto p-1 rounded hover:bg-gray-200 dark:hover:bg-zinc-600 transition-colors ${previewVisible ? \"opacity-100\" : \"opacity-40\"}`}\n title={previewVisible ? \"Hide preview\" : \"Show preview\"}\n >\n <svg className={`w-3.5 h-3.5 ${color}`} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n {previewVisible ? (\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z\"\n />\n ) : (\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21\"\n />\n )}\n </svg>\n </button>\n );\n}\n\n// Generator Node (source nodes - have output only)\n// AI generators may also have a text input handle and/or references input handle\nexport const GeneratorNode = memo(function GeneratorNode({\n id,\n data,\n selected,\n}: NodeProps<GeneratorNodeData>) {\n const preview = useWorkflowStore((s) => s.execution.previews[id]);\n const nodeStatus = useWorkflowStore((s) => s.execution.nodeStatus[id]);\n const previewVisible = useWorkflowStore((s) => s.previewVisible[id] !== false);\n\n const executionClass = getExecutionClass(nodeStatus);\n\n // AI generators get a text input handle for dynamic prompts\n const isAI = data.isAI;\n // Check if this generator accepts reference images\n const acceptsReferences = data.acceptsReferenceImages;\n\n return (\n <div\n className={`floimg-node floimg-node--generator relative min-w-[190px] overflow-hidden ${selected ? \"selected\" : \"\"} ${executionClass}`}\n >\n {/* Text input handle for AI generators (optional - for dynamic prompts) */}\n {isAI && (\n <Handle\n type=\"target\"\n position={Position.Top}\n id=\"text\"\n className=\"!w-3 !h-3 !bg-pink-500 !border-2 !border-white dark:!border-zinc-800\"\n title=\"Text input (optional prompt from text/vision node)\"\n />\n )}\n {/* Reference images input handle (for AI generators) */}\n {acceptsReferences && (\n <Handle\n type=\"target\"\n position={Position.Left}\n id=\"references\"\n className=\"!w-3 !h-3 !bg-violet-500 !border-2 !border-white dark:!border-zinc-800\"\n style={{ top: \"50%\" }}\n title={`Reference images (up to ${data.maxReferenceImages || 14})`}\n />\n )}\n {preview && previewVisible && (\n <div className=\"floimg-node__preview\">\n <img src={preview} alt=\"Preview\" className=\"w-full h-20 object-contain rounded-md\" />\n </div>\n )}\n <div className=\"floimg-node__header\">\n <div className=\"floimg-node__icon bg-blue-500/10\">\n <div className=\"w-2 h-2 rounded-full bg-blue-500\" />\n </div>\n <span className=\"floimg-node__title text-blue-600 dark:text-blue-400\">\n {data.generatorName}\n </span>\n <PreviewToggle\n nodeId={id}\n color=\"text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300\"\n />\n </div>\n <div className=\"floimg-node__content\">\n {isAI && (\n <div className=\"text-[10px] text-pink-500/80 dark:text-pink-400/80 mb-1.5 flex items-center gap-1\">\n <span className=\"w-1 h-1 rounded-full bg-pink-400\" />\n Text input for dynamic prompt\n </div>\n )}\n {acceptsReferences && (\n <div className=\"text-[10px] text-violet-500/80 dark:text-violet-400/80 mb-1.5 flex items-center gap-1\">\n <span className=\"w-1 h-1 rounded-full bg-violet-400\" />\n Reference images\n </div>\n )}\n <div className=\"space-y-0.5\">\n {Object.entries(data.params)\n .filter(([, value]) => typeof value !== \"object\" || value === null)\n .slice(0, 2)\n .map(([key, value]) => (\n <div key={key} className=\"floimg-node__param truncate\">\n <span className=\"text-zinc-400 dark:text-zinc-500\">{key}:</span>{\" \"}\n {String(value).slice(0, 20)}\n </div>\n ))}\n </div>\n </div>\n <Handle\n type=\"source\"\n position={Position.Right}\n className=\"!w-3 !h-3 !bg-blue-500 !border-2 !border-white dark:!border-zinc-800\"\n />\n </div>\n );\n});\n\n// Transform Node (have both input and output)\n// AI transforms also have an optional text input at the top\n// AI transforms that accept references have a references input at the bottom\nexport const TransformNode = memo(function TransformNode({\n id,\n data,\n selected,\n}: NodeProps<TransformNodeData>) {\n const preview = useWorkflowStore((s) => s.execution.previews[id]);\n const nodeStatus = useWorkflowStore((s) => s.execution.nodeStatus[id]);\n const previewVisible = useWorkflowStore((s) => s.previewVisible[id] !== false);\n\n const executionClass = getExecutionClass(nodeStatus);\n\n // AI transforms get an indigo accent to indicate AI-powered\n const isAI = data.isAI;\n // Check if this transform accepts reference images\n const acceptsReferences = data.acceptsReferenceImages;\n\n const nodeTypeClass = isAI ? \"floimg-node--ai-transform\" : \"floimg-node--transform\";\n\n return (\n <div\n className={`floimg-node ${nodeTypeClass} relative min-w-[190px] overflow-hidden ${selected ? \"selected\" : \"\"} ${executionClass}`}\n >\n {/* Text input handle for AI transforms (optional - for dynamic prompts) */}\n {isAI && (\n <Handle\n type=\"target\"\n position={Position.Top}\n id=\"text\"\n className=\"!w-3 !h-3 !bg-pink-500 !border-2 !border-white dark:!border-zinc-800\"\n title=\"Text input (optional prompt from text/vision node)\"\n />\n )}\n {/* Image input handle */}\n <Handle\n type=\"target\"\n position={Position.Left}\n id=\"image\"\n className=\"!w-3 !h-3 !bg-teal-500 !border-2 !border-white dark:!border-zinc-800\"\n />\n {/* Reference images input handle (for AI transforms that accept additional references) */}\n {acceptsReferences && (\n <Handle\n type=\"target\"\n position={Position.Bottom}\n id=\"references\"\n className=\"!w-3 !h-3 !bg-violet-500 !border-2 !border-white dark:!border-zinc-800\"\n title={`Reference images (up to ${data.maxReferenceImages || 13})`}\n />\n )}\n {preview && previewVisible && (\n <div className=\"floimg-node__preview\">\n <img src={preview} alt=\"Preview\" className=\"w-full h-20 object-contain rounded-md\" />\n </div>\n )}\n <div className=\"floimg-node__header\">\n <div className={`floimg-node__icon ${isAI ? \"bg-indigo-500/10\" : \"bg-teal-500/10\"}`}>\n {isAI ? (\n <svg className=\"w-2.5 h-2.5 text-indigo-500\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path d=\"M13 7H7v6h6V7z\" />\n <path\n fillRule=\"evenodd\"\n d=\"M7 2a1 1 0 012 0v1h2V2a1 1 0 112 0v1h2a2 2 0 012 2v2h1a1 1 0 110 2h-1v2h1a1 1 0 110 2h-1v2a2 2 0 01-2 2h-2v1a1 1 0 11-2 0v-1H9v1a1 1 0 11-2 0v-1H5a2 2 0 01-2-2v-2H2a1 1 0 110-2h1V9H2a1 1 0 010-2h1V5a2 2 0 012-2h2V2zM5 5h10v10H5V5z\"\n clipRule=\"evenodd\"\n />\n </svg>\n ) : (\n <div className=\"w-2 h-2 rounded-full bg-teal-500\" />\n )}\n </div>\n <span\n className={`floimg-node__title ${isAI ? \"text-indigo-600 dark:text-indigo-400\" : \"text-teal-600 dark:text-teal-400\"}`}\n >\n {data.operation}\n </span>\n <PreviewToggle\n nodeId={id}\n color=\"text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300\"\n />\n </div>\n <div className=\"floimg-node__content\">\n {isAI && (\n <div className=\"text-[10px] text-pink-500/80 dark:text-pink-400/80 mb-1.5 flex items-center gap-1\">\n <span className=\"w-1 h-1 rounded-full bg-pink-400\" />\n Text input for dynamic prompt\n </div>\n )}\n {acceptsReferences && (\n <div className=\"text-[10px] text-violet-500/80 dark:text-violet-400/80 mb-1.5 flex items-center gap-1\">\n <span className=\"w-1 h-1 rounded-full bg-violet-400\" />\n Reference images\n </div>\n )}\n <div className=\"space-y-0.5\">\n {Object.entries(data.params)\n .filter(([, value]) => typeof value !== \"object\" || value === null)\n .slice(0, 2)\n .map(([key, value]) => (\n <div key={key} className=\"floimg-node__param truncate\">\n <span className=\"text-zinc-400 dark:text-zinc-500\">{key}:</span>{\" \"}\n {String(value).slice(0, 20)}\n </div>\n ))}\n </div>\n </div>\n <Handle\n type=\"source\"\n position={Position.Right}\n className={`!w-3 !h-3 ${isAI ? \"!bg-indigo-500\" : \"!bg-teal-500\"} !border-2 !border-white dark:!border-zinc-800`}\n />\n </div>\n );\n});\n\n// Save Node (sink nodes - have input only)\nexport const SaveNode = memo(function SaveNode({ id, data, selected }: NodeProps<SaveNodeData>) {\n const nodeStatus = useWorkflowStore((s) => s.execution.nodeStatus[id]);\n\n const executionClass = getExecutionClass(nodeStatus);\n\n return (\n <div\n className={`floimg-node floimg-node--save relative min-w-[190px] ${selected ? \"selected\" : \"\"} ${executionClass}`}\n >\n <Handle\n type=\"target\"\n position={Position.Left}\n className=\"!w-3 !h-3 !bg-emerald-500 !border-2 !border-white dark:!border-zinc-800\"\n />\n <div className=\"floimg-node__header\">\n <div className=\"floimg-node__icon bg-emerald-500/10\">\n <svg\n className=\"w-2.5 h-2.5 text-emerald-500\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n </div>\n <span className=\"floimg-node__title text-emerald-600 dark:text-emerald-400\">Save</span>\n </div>\n <div className=\"floimg-node__content\">\n <div className=\"floimg-node__param truncate\">{data.destination}</div>\n </div>\n </div>\n );\n});\n\n// Input Node (source nodes with uploaded images - have output only)\nexport const InputNode = memo(function InputNode({ id, data, selected }: NodeProps<InputNodeData>) {\n const preview = useWorkflowStore((s) => s.execution.previews[id]);\n const nodeStatus = useWorkflowStore((s) => s.execution.nodeStatus[id]);\n const previewVisible = useWorkflowStore((s) => s.previewVisible[id] !== false);\n const updateNodeData = useWorkflowStore((s) => s.updateNodeData);\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const executionClass = getExecutionClass(nodeStatus);\n\n // Handle file selection\n const handleFileSelect = useCallback(\n async (file: File) => {\n try {\n const result = await uploadImage(file);\n updateNodeData(id, {\n uploadId: result.id,\n filename: result.filename,\n mime: result.mime,\n });\n } catch (error) {\n console.error(\"Upload failed:\", error);\n }\n },\n [id, updateNodeData]\n );\n\n // Handle drag and drop\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n const file = e.dataTransfer.files[0];\n if (file && file.type.startsWith(\"image/\")) {\n handleFileSelect(file);\n }\n },\n [handleFileSelect]\n );\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n // Handle file input change\n const handleInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (file) {\n handleFileSelect(file);\n }\n },\n [handleFileSelect]\n );\n\n // Get preview URL - either execution preview or static upload URL\n const previewUrl = preview || (data.uploadId ? getUploadBlobUrl(data.uploadId) : null);\n\n return (\n <div\n className={`floimg-node floimg-node--input relative min-w-[190px] overflow-hidden ${selected ? \"selected\" : \"\"} ${executionClass}`}\n onDrop={handleDrop}\n onDragOver={handleDragOver}\n >\n {previewUrl && previewVisible ? (\n <div className=\"floimg-node__preview\">\n <img src={previewUrl} alt=\"Uploaded\" className=\"w-full h-20 object-contain rounded-md\" />\n </div>\n ) : !previewUrl ? (\n <div\n className=\"h-20 flex items-center justify-center cursor-pointer bg-amber-50/50 dark:bg-amber-900/20 hover:bg-amber-100/50 dark:hover:bg-amber-900/30 transition-colors border-b border-amber-100/50 dark:border-amber-800/30\"\n onClick={() => fileInputRef.current?.click()}\n >\n <div className=\"text-center text-amber-500 dark:text-amber-400\">\n <svg\n className=\"w-6 h-6 mx-auto mb-1 opacity-60\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.5}\n d=\"M12 4v16m8-8H4\"\n />\n </svg>\n <div className=\"text-[10px] opacity-70\">Drop or click</div>\n </div>\n </div>\n ) : null}\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n className=\"hidden\"\n onChange={handleInputChange}\n />\n <div className=\"floimg-node__header\">\n <div className=\"floimg-node__icon bg-amber-500/10\">\n <svg\n className=\"w-2.5 h-2.5 text-amber-500\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\"\n />\n </svg>\n </div>\n <span className=\"floimg-node__title text-amber-600 dark:text-amber-400\">Input</span>\n <PreviewToggle\n nodeId={id}\n color=\"text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300\"\n />\n </div>\n <div className=\"floimg-node__content\">\n <div className=\"floimg-node__param truncate\">{data.filename || \"No image selected\"}</div>\n </div>\n <Handle\n type=\"source\"\n position={Position.Right}\n className=\"!w-3 !h-3 !bg-amber-500 !border-2 !border-white dark:!border-zinc-800\"\n />\n </div>\n );\n});\n\n// Vision Node (AI image analysis - has input and output)\n// Supports multiple output handles when outputSchema is defined\nexport const VisionNode = memo(function VisionNode({\n id,\n data,\n selected,\n}: NodeProps<VisionNodeData>) {\n const nodeStatus = useWorkflowStore((s) => s.execution.nodeStatus[id]);\n const dataOutput = useWorkflowStore((s) => s.execution.dataOutputs?.[id]);\n const openOutputInspector = useWorkflowStore((s) => s.openOutputInspector);\n\n const executionClass = getExecutionClass(nodeStatus);\n\n // Get output schema properties for multi-output handles\n const outputProperties = data.outputSchema?.properties\n ? Object.entries(data.outputSchema.properties)\n : [];\n const hasMultiOutput = outputProperties.length > 0;\n\n return (\n <div\n className={`floimg-node floimg-node--vision relative min-w-[190px] overflow-hidden ${selected ? \"selected\" : \"\"} ${executionClass}`}\n >\n {/* Text/context input handle (top) - for workflow context */}\n <Handle\n type=\"target\"\n position={Position.Top}\n id=\"context\"\n className=\"!w-3 !h-3 !bg-pink-500 !border-2 !border-white dark:!border-zinc-800\"\n title=\"Context input (optional - from text/vision node for evaluation context)\"\n />\n {/* Image input handle (left) - for images to analyze */}\n <Handle\n type=\"target\"\n position={Position.Left}\n id=\"image\"\n className=\"!w-3 !h-3 !bg-cyan-500 !border-2 !border-white dark:!border-zinc-800\"\n title=\"Image input\"\n />\n {dataOutput && (\n <div className=\"bg-cyan-50/50 dark:bg-cyan-900/20 border-b border-cyan-100/50 dark:border-cyan-800/30 p-2.5 max-h-20 overflow-auto\">\n <pre className=\"text-[11px] text-cyan-700 dark:text-cyan-300 whitespace-pre-wrap font-mono\">\n {dataOutput.content?.slice(0, 150)}\n {(dataOutput.content?.length || 0) > 150 && \"...\"}\n </pre>\n {dataOutput.content && dataOutput.content.length > 100 && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n openOutputInspector(id);\n }}\n className=\"mt-1.5 text-[10px] text-cyan-500 dark:text-cyan-400 hover:text-cyan-600 dark:hover:text-cyan-300 font-medium\"\n >\n View Full Output\n </button>\n )}\n </div>\n )}\n <div className=\"floimg-node__header\">\n <div className=\"floimg-node__icon bg-cyan-500/10\">\n <svg className=\"w-2.5 h-2.5 text-cyan-500\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path d=\"M10 12a2 2 0 100-4 2 2 0 000 4z\" />\n <path\n fillRule=\"evenodd\"\n d=\"M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </div>\n <span className=\"floimg-node__title text-cyan-600 dark:text-cyan-400\">\n {data.providerLabel || data.providerName}\n </span>\n </div>\n <div className=\"floimg-node__content\">\n {data.params.prompt ? (\n <div className=\"floimg-node__param truncate\">\n {String(data.params.prompt).slice(0, 30)}...\n </div>\n ) : null}\n {/* Show output schema info if defined */}\n {hasMultiOutput && (\n <div className=\"mt-2 pt-2 border-t border-zinc-100 dark:border-zinc-700/50\">\n <div className=\"text-[10px] text-cyan-500 dark:text-cyan-400 font-medium mb-1\">\n Outputs:\n </div>\n {outputProperties.map(([key]) => (\n <div\n key={key}\n className=\"text-[10px] text-zinc-500 dark:text-zinc-400 flex items-center gap-1\"\n >\n <span className=\"w-1 h-1 rounded-full bg-cyan-400\"></span>\n {key}\n </div>\n ))}\n </div>\n )}\n </div>\n {/* Multi-output handles: one for each schema property */}\n {hasMultiOutput ? (\n <>\n {/* Full output handle (backward compat) */}\n <Handle\n type=\"source\"\n position={Position.Right}\n id=\"output\"\n className=\"!w-3 !h-3 !bg-cyan-500 !border-2 !border-white dark:!border-zinc-800\"\n style={{ top: \"50%\" }}\n title=\"Full JSON output\"\n />\n {/* Individual property handles */}\n {outputProperties.map(([key, prop], index) => (\n <Handle\n key={key}\n type=\"source\"\n position={Position.Right}\n id={`output.${key}`}\n className=\"!w-2.5 !h-2.5 !bg-cyan-400 !border-2 !border-white dark:!border-zinc-800\"\n style={{\n top: `${70 + index * 14}%`,\n }}\n title={`${key}: ${prop.description || prop.type}`}\n />\n ))}\n </>\n ) : (\n <Handle\n type=\"source\"\n position={Position.Right}\n className=\"!w-3 !h-3 !bg-cyan-500 !border-2 !border-white dark:!border-zinc-800\"\n />\n )}\n </div>\n );\n});\n\n// Text Node (AI text generation - has optional input and output)\n// Supports multiple output handles when outputSchema is defined\nexport const TextNode = memo(function TextNode({ id, data, selected }: NodeProps<TextNodeData>) {\n const nodeStatus = useWorkflowStore((s) => s.execution.nodeStatus[id]);\n const dataOutput = useWorkflowStore((s) => s.execution.dataOutputs?.[id]);\n const openOutputInspector = useWorkflowStore((s) => s.openOutputInspector);\n\n const executionClass = getExecutionClass(nodeStatus);\n\n // Get output schema properties for multi-output handles\n const outputProperties = data.outputSchema?.properties\n ? Object.entries(data.outputSchema.properties)\n : [];\n const hasMultiOutput = outputProperties.length > 0;\n\n return (\n <div\n className={`floimg-node floimg-node--text relative min-w-[190px] overflow-hidden ${selected ? \"selected\" : \"\"} ${executionClass}`}\n >\n <Handle\n type=\"target\"\n position={Position.Left}\n className=\"!w-3 !h-3 !bg-pink-500 !border-2 !border-white dark:!border-zinc-800\"\n />\n {dataOutput && (\n <div className=\"bg-pink-50/50 dark:bg-pink-900/20 border-b border-pink-100/50 dark:border-pink-800/30 p-2.5 max-h-20 overflow-auto\">\n <pre className=\"text-[11px] text-pink-700 dark:text-pink-300 whitespace-pre-wrap font-mono\">\n {dataOutput.content?.slice(0, 150)}\n {(dataOutput.content?.length || 0) > 150 && \"...\"}\n </pre>\n {dataOutput.content && dataOutput.content.length > 100 && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n openOutputInspector(id);\n }}\n className=\"mt-1.5 text-[10px] text-pink-500 dark:text-pink-400 hover:text-pink-600 dark:hover:text-pink-300 font-medium\"\n >\n View Full Output\n </button>\n )}\n </div>\n )}\n <div className=\"floimg-node__header\">\n <div className=\"floimg-node__icon bg-pink-500/10\">\n <svg className=\"w-2.5 h-2.5 text-pink-500\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path\n fillRule=\"evenodd\"\n d=\"M18 13V5a2 2 0 00-2-2H4a2 2 0 00-2 2v8a2 2 0 002 2h3l3 3 3-3h3a2 2 0 002-2zM5 7a1 1 0 011-1h8a1 1 0 110 2H6a1 1 0 01-1-1zm1 3a1 1 0 100 2h3a1 1 0 100-2H6z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </div>\n <span className=\"floimg-node__title text-pink-600 dark:text-pink-400\">\n {data.providerLabel || data.providerName}\n </span>\n </div>\n <div className=\"floimg-node__content\">\n {data.params.prompt ? (\n <div className=\"floimg-node__param truncate\">\n {String(data.params.prompt).slice(0, 30)}...\n </div>\n ) : null}\n {/* Show output schema info if defined */}\n {hasMultiOutput && (\n <div className=\"mt-2 pt-2 border-t border-zinc-100 dark:border-zinc-700/50\">\n <div className=\"text-[10px] text-pink-500 dark:text-pink-400 font-medium mb-1\">\n Outputs:\n </div>\n {outputProperties.map(([key]) => (\n <div\n key={key}\n className=\"text-[10px] text-zinc-500 dark:text-zinc-400 flex items-center gap-1\"\n >\n <span className=\"w-1 h-1 rounded-full bg-pink-400\"></span>\n {key}\n </div>\n ))}\n </div>\n )}\n </div>\n {/* Multi-output handles: one for each schema property */}\n {hasMultiOutput ? (\n <>\n {/* Full output handle (backward compat) */}\n <Handle\n type=\"source\"\n position={Position.Right}\n id=\"output\"\n className=\"!w-3 !h-3 !bg-pink-500 !border-2 !border-white dark:!border-zinc-800\"\n style={{ top: \"50%\" }}\n title=\"Full JSON output\"\n />\n {/* Individual property handles */}\n {outputProperties.map(([key, prop], index) => (\n <Handle\n key={key}\n type=\"source\"\n position={Position.Right}\n id={`output.${key}`}\n className=\"!w-2.5 !h-2.5 !bg-pink-400 !border-2 !border-white dark:!border-zinc-800\"\n style={{\n top: `${70 + index * 14}%`,\n }}\n title={`${key}: ${prop.description || prop.type}`}\n />\n ))}\n </>\n ) : (\n <Handle\n type=\"source\"\n position={Position.Right}\n className=\"!w-3 !h-3 !bg-pink-500 !border-2 !border-white dark:!border-zinc-800\"\n />\n )}\n </div>\n );\n});\n\n// ============================================\n// Iterative Workflow Nodes\n// ============================================\n\n// Fan-Out Node - distributes execution across parallel branches\nexport const FanOutNode = memo(function FanOutNode({\n id,\n data,\n selected,\n}: NodeProps<FanOutNodeData>) {\n const nodeStatus = useWorkflowStore((s) => s.execution.nodeStatus[id]);\n\n const executionClass = getExecutionClass(nodeStatus);\n\n // Determine output count based on mode\n const outputCount = data.mode === \"count\" ? data.count || 3 : 3;\n\n return (\n <div\n className={`floimg-node floimg-node--iterative relative min-w-[170px] overflow-hidden ${selected ? \"selected\" : \"\"} ${executionClass}`}\n >\n {/* Input handle - accepts data/array from upstream */}\n <Handle\n type=\"target\"\n position={Position.Left}\n id=\"input\"\n className=\"!w-3 !h-3 !bg-orange-500 !border-2 !border-white dark:!border-zinc-800\"\n style={{ top: \"50%\" }}\n />\n\n <div className=\"floimg-node__header\">\n <div className=\"floimg-node__icon bg-orange-500/10\">\n <svg\n className=\"w-2.5 h-2.5 text-orange-500\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4\"\n />\n </svg>\n </div>\n <span className=\"floimg-node__title text-orange-600 dark:text-orange-400\">Fan-Out</span>\n <span className=\"ml-auto text-[10px] bg-orange-500/10 text-orange-600 dark:text-orange-400 px-1.5 py-0.5 rounded-full font-medium\">\n ×{outputCount}\n </span>\n </div>\n <div className=\"floimg-node__content\">\n <div className=\"floimg-node__param\">\n {data.mode === \"array\" ? (\n <span>Iterate: {data.arrayProperty || \"items\"}</span>\n ) : (\n <span>Duplicate: {outputCount} copies</span>\n )}\n </div>\n </div>\n\n {/* Dynamic output handles */}\n {Array.from({ length: outputCount }).map((_, i) => (\n <Handle\n key={i}\n type=\"source\"\n position={Position.Right}\n id={`out[${i}]`}\n className=\"!w-2.5 !h-2.5 !bg-orange-400 !border-2 !border-white dark:!border-zinc-800\"\n style={{\n top: `${((i + 1) / (outputCount + 1)) * 100}%`,\n }}\n title={`Output ${i}`}\n />\n ))}\n </div>\n );\n});\n\n// Collect Node - gathers outputs from parallel branches\nexport const CollectNode = memo(function CollectNode({\n id,\n data,\n selected,\n}: NodeProps<CollectNodeData>) {\n const nodeStatus = useWorkflowStore((s) => s.execution.nodeStatus[id]);\n\n const executionClass = getExecutionClass(nodeStatus);\n\n const inputCount = data.expectedInputs || 3;\n\n return (\n <div\n className={`floimg-node floimg-node--iterative relative min-w-[170px] overflow-hidden ${selected ? \"selected\" : \"\"} ${executionClass}`}\n >\n {/* Dynamic input handles */}\n {Array.from({ length: inputCount }).map((_, i) => (\n <Handle\n key={i}\n type=\"target\"\n position={Position.Left}\n id={`in[${i}]`}\n className=\"!w-2.5 !h-2.5 !bg-orange-400 !border-2 !border-white dark:!border-zinc-800\"\n style={{\n top: `${((i + 1) / (inputCount + 1)) * 100}%`,\n }}\n title={`Input ${i}`}\n />\n ))}\n\n <div className=\"floimg-node__header\">\n <div className=\"floimg-node__icon bg-orange-500/10\">\n <svg\n className=\"w-2.5 h-2.5 text-orange-500\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 7h12m0 0l-4-4m4 4l-4 4m8 6H8m0 0l4 4m-4-4l4-4\"\n />\n </svg>\n </div>\n <span className=\"floimg-node__title text-orange-600 dark:text-orange-400\">Collect</span>\n <span className=\"ml-auto text-[10px] bg-orange-500/10 text-orange-600 dark:text-orange-400 px-1.5 py-0.5 rounded-full font-medium\">\n {inputCount}→1\n </span>\n </div>\n <div className=\"floimg-node__content\">\n <div className=\"floimg-node__param\">\n {data.waitMode === \"all\" ? \"Wait for all\" : \"Use available\"}\n </div>\n </div>\n\n {/* Output handle - single array output */}\n <Handle\n type=\"source\"\n position={Position.Right}\n id=\"output\"\n className=\"!w-3 !h-3 !bg-orange-500 !border-2 !border-white dark:!border-zinc-800\"\n style={{ top: \"50%\" }}\n />\n </div>\n );\n});\n\n// Router Node - routes based on AI selection\nexport const RouterNode = memo(function RouterNode({\n id,\n data,\n selected,\n}: NodeProps<RouterNodeData>) {\n const nodeStatus = useWorkflowStore((s) => s.execution.nodeStatus[id]);\n\n const executionClass = getExecutionClass(nodeStatus);\n\n const hasContextOutput = !!data.contextProperty;\n\n return (\n <div\n className={`floimg-node floimg-node--iterative relative min-w-[170px] overflow-hidden ${selected ? \"selected\" : \"\"} ${executionClass}`}\n >\n {/* Candidates input - array of options */}\n <Handle\n type=\"target\"\n position={Position.Left}\n id=\"candidates\"\n className=\"!w-3 !h-3 !bg-amber-500 !border-2 !border-white dark:!border-zinc-800\"\n style={{ top: \"35%\" }}\n title=\"Candidates (array)\"\n />\n {/* Selection input - AI decision data */}\n <Handle\n type=\"target\"\n position={Position.Left}\n id=\"selection\"\n className=\"!w-3 !h-3 !bg-cyan-500 !border-2 !border-white dark:!border-zinc-800\"\n style={{ top: \"65%\" }}\n title=\"Selection (from vision/text)\"\n />\n\n <div className=\"floimg-node__header\">\n <div className=\"floimg-node__icon bg-amber-500/10\">\n <svg\n className=\"w-2.5 h-2.5 text-amber-500\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M13 5l7 7-7 7M5 5l7 7-7 7\"\n />\n </svg>\n </div>\n <span className=\"floimg-node__title text-amber-600 dark:text-amber-400\">Router</span>\n </div>\n <div className=\"floimg-node__content\">\n <div className=\"space-y-1\">\n <div className=\"floimg-node__param flex items-center gap-1\">\n <span className=\"w-1 h-1 rounded-full bg-amber-400\"></span>\n candidates\n </div>\n <div className=\"floimg-node__param flex items-center gap-1\">\n <span className=\"w-1 h-1 rounded-full bg-cyan-400\"></span>\n selection.{data.selectionProperty || \"winner\"}\n </div>\n </div>\n {hasContextOutput && (\n <div className=\"mt-2 pt-2 border-t border-zinc-100 dark:border-zinc-700/50\">\n <div className=\"text-[10px] text-amber-500/80 dark:text-amber-400/80\">\n + context: {data.contextProperty}\n </div>\n </div>\n )}\n </div>\n\n {/* Winner output */}\n <Handle\n type=\"source\"\n position={Position.Right}\n id=\"winner\"\n className=\"!w-3 !h-3 !bg-amber-500 !border-2 !border-white dark:!border-zinc-800\"\n style={{ top: hasContextOutput ? \"35%\" : \"50%\" }}\n title=\"Selected item\"\n />\n {/* Context output (optional) */}\n {hasContextOutput && (\n <Handle\n type=\"source\"\n position={Position.Right}\n id=\"context\"\n className=\"!w-3 !h-3 !bg-pink-500 !border-2 !border-white dark:!border-zinc-800\"\n style={{ top: \"65%\" }}\n title={`Context: ${data.contextProperty}`}\n />\n )}\n </div>\n );\n});\n\nexport const nodeTypes = {\n generator: GeneratorNode,\n transform: TransformNode,\n save: SaveNode,\n input: InputNode,\n vision: VisionNode,\n text: TextNode,\n // Iterative workflow nodes\n fanout: FanOutNode,\n collect: CollectNode,\n router: RouterNode,\n};\n","import { useCallback, useMemo } from \"react\";\nimport ReactFlow, {\n Background,\n BackgroundVariant,\n Controls,\n MiniMap,\n MarkerType,\n type Connection,\n type NodeMouseHandler,\n type OnNodesChange,\n type OnEdgesChange,\n type DefaultEdgeOptions,\n applyNodeChanges,\n applyEdgeChanges,\n} from \"reactflow\";\nimport \"reactflow/dist/style.css\";\nimport \"./studio-theme.css\";\nimport type { GeneratorNodeData } from \"@teamflojo/floimg-studio-shared\";\nimport { useWorkflowStore } from \"../stores/workflowStore\";\nimport { nodeTypes } from \"./nodeTypes\";\n\n// Premium edge styling with refined colors\nconst defaultEdgeOptions: DefaultEdgeOptions = {\n type: \"smoothstep\",\n animated: false,\n markerEnd: {\n type: MarkerType.ArrowClosed,\n color: \"#71717a\",\n width: 18,\n height: 18,\n },\n style: {\n stroke: \"#71717a\",\n strokeWidth: 2,\n strokeLinecap: \"round\",\n },\n // Make edges easier to select\n interactionWidth: 20,\n};\n\nexport function WorkflowEditor() {\n const nodes = useWorkflowStore((s) => s.nodes);\n const edges = useWorkflowStore((s) => s.edges);\n const setNodes = useWorkflowStore((s) => s.setNodes);\n const setEdges = useWorkflowStore((s) => s.setEdges);\n const addEdge = useWorkflowStore((s) => s.addEdge);\n const setSelectedNode = useWorkflowStore((s) => s.setSelectedNode);\n\n // Memoize nodeTypes to prevent React Flow warning during HMR\n // The nodeTypes object is defined outside, but HMR can cause module re-evaluation\n const memoizedNodeTypes = useMemo(() => nodeTypes, []);\n\n // Validate connections based on node types\n const isValidConnection = useCallback(\n (connection: Connection) => {\n const { source, target, targetHandle } = connection;\n if (!source || !target) return false;\n\n const sourceNode = nodes.find((n) => n.id === source);\n const targetNode = nodes.find((n) => n.id === target);\n\n if (!sourceNode || !targetNode) return false;\n\n // Rule 1: Cannot connect FROM a save node (no output)\n if (sourceNode.type === \"save\") return false;\n\n // Rule 2: Cannot connect TO a generator UNLESS it has specific input handles\n // AI generators have \"text\" (for prompts) and \"references\" (for reference images) handles\n if (targetNode.type === \"generator\") {\n const data = targetNode.data as GeneratorNodeData;\n // Allow connections to text handle if it's an AI generator\n if (targetHandle === \"text\" && data.isAI) return true;\n // Allow connections to references handle if it accepts reference images\n if (targetHandle === \"references\" && data.acceptsReferenceImages) return true;\n // Block all other connections to generators\n return false;\n }\n\n // Rule 3: Cannot connect TO an input node (no input port)\n if (targetNode.type === \"input\") return false;\n\n // Rule 4: No self-connections\n if (source === target) return false;\n\n // Note: We allow replacing existing connections - handled in onConnect\n return true;\n },\n [nodes]\n );\n\n const onNodesChange: OnNodesChange = useCallback(\n (changes) => {\n setNodes(applyNodeChanges(changes, nodes));\n },\n [nodes, setNodes]\n );\n\n const onEdgesChange: OnEdgesChange = useCallback(\n (changes) => {\n setEdges(applyEdgeChanges(changes, edges));\n },\n [edges, setEdges]\n );\n\n const onConnect = useCallback(\n (connection: Connection) => {\n // \"references\" handles accept multiple connections (for reference images)\n // All other handles (text, image, default) are single-connection and auto-replace\n const isMultiConnectionHandle = connection.targetHandle === \"references\";\n\n if (!isMultiConnectionHandle) {\n // Remove any existing connection to the same target handle before adding new one\n // Handle edge creation inconsistencies from AI generation or YAML import\n const edgesToRemove = edges.filter((e) => {\n if (e.target !== connection.target) return false;\n\n // Exact handle match (including both being null/undefined)\n const existingHandle = e.targetHandle || null;\n const newHandle = connection.targetHandle || null;\n if (existingHandle === newHandle) return true;\n\n // For \"text\" or \"image\" handle connections, also remove edges with no targetHandle\n // These are the primary single-input handles that should auto-replace\n if (\n (connection.targetHandle === \"text\" || connection.targetHandle === \"image\") &&\n !e.targetHandle\n ) {\n return true;\n }\n\n // If connecting to default handle (no targetHandle), remove edges to \"image\" handle\n // since that's the main input for transforms\n if (!connection.targetHandle && e.targetHandle === \"image\") {\n return true;\n }\n\n return false;\n });\n\n if (edgesToRemove.length > 0) {\n const removeIds = new Set(edgesToRemove.map((e) => e.id));\n setEdges(edges.filter((e) => !removeIds.has(e.id)));\n }\n }\n addEdge(connection);\n },\n [addEdge, edges, setEdges]\n );\n\n const onNodeClick: NodeMouseHandler = useCallback(\n (_event, node) => {\n setSelectedNode(node.id);\n },\n [setSelectedNode]\n );\n\n const onPaneClick = useCallback(() => {\n setSelectedNode(null);\n }, [setSelectedNode]);\n\n return (\n <div className=\"h-full w-full\">\n <ReactFlow\n nodes={nodes}\n edges={edges}\n onNodesChange={onNodesChange}\n onEdgesChange={onEdgesChange}\n onConnect={onConnect}\n onNodeClick={onNodeClick}\n onPaneClick={onPaneClick}\n nodeTypes={memoizedNodeTypes}\n defaultEdgeOptions={defaultEdgeOptions}\n isValidConnection={isValidConnection}\n nodesDraggable={true}\n nodesConnectable={true}\n elementsSelectable={true}\n edgesFocusable={true}\n deleteKeyCode={[\"Backspace\", \"Delete\"]}\n proOptions={{ hideAttribution: true }}\n fitView\n snapToGrid\n snapGrid={[15, 15]}\n >\n <Background variant={BackgroundVariant.Dots} gap={20} size={1.5} />\n <Controls showInteractive={false} />\n <MiniMap\n nodeStrokeWidth={2}\n nodeColor=\"#71717a\"\n maskColor=\"rgba(0, 0, 0, 0.1)\"\n zoomable\n pannable\n />\n </ReactFlow>\n </div>\n );\n}\n","import { useState, useEffect } from \"react\";\nimport { listUploads, deleteUpload, getUploadBlobUrl, type UploadInfo } from \"../api/client\";\n\ninterface UploadGalleryProps {\n onSelect?: (upload: UploadInfo) => void;\n}\n\nexport function UploadGallery({ onSelect }: UploadGalleryProps) {\n const [uploads, setUploads] = useState<UploadInfo[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n const fetchUploads = async () => {\n try {\n setLoading(true);\n const data = await listUploads();\n setUploads(data);\n setError(null);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to load uploads\");\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n fetchUploads();\n }, []);\n\n const handleDelete = async (id: string, e: React.MouseEvent) => {\n e.stopPropagation();\n if (!confirm(\"Delete this upload?\")) return;\n\n try {\n await deleteUpload(id);\n setUploads((prev) => prev.filter((u) => u.id !== id));\n } catch (err) {\n console.error(\"Failed to delete:\", err);\n }\n };\n\n const formatSize = (bytes: number) => {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n };\n\n if (loading) {\n return (\n <div className=\"p-4 text-center text-gray-500 dark:text-zinc-400\">Loading uploads...</div>\n );\n }\n\n if (error) {\n return (\n <div className=\"p-4 text-center text-red-500 dark:text-red-400\">\n {error}\n <button\n onClick={fetchUploads}\n className=\"ml-2 text-teal-500 dark:text-teal-400 hover:underline\"\n >\n Retry\n </button>\n </div>\n );\n }\n\n if (uploads.length === 0) {\n return (\n <div className=\"p-4 text-center text-gray-500 dark:text-zinc-400\">\n No uploads yet. Drag an image onto an Input node to upload.\n </div>\n );\n }\n\n return (\n <div className=\"p-2\">\n <div className=\"grid grid-cols-2 gap-2\">\n {uploads.map((upload) => (\n <div\n key={upload.id}\n className=\"relative group rounded border border-gray-200 dark:border-zinc-700 overflow-hidden cursor-pointer hover:border-amber-400 dark:hover:border-amber-500 transition-colors\"\n onClick={() => onSelect?.(upload)}\n >\n <img\n src={getUploadBlobUrl(upload.id)}\n alt={upload.filename}\n className=\"w-full h-20 object-cover\"\n />\n <div className=\"absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center\">\n <button\n onClick={(e) => handleDelete(upload.id, e)}\n className=\"p-1 bg-red-500 rounded text-white text-xs hover:bg-red-600\"\n >\n Delete\n </button>\n </div>\n <div className=\"p-1 text-xs truncate bg-white dark:bg-zinc-800 text-gray-800 dark:text-zinc-200\">\n {upload.filename}\n </div>\n <div className=\"px-1 pb-1 text-xs text-gray-400 dark:text-zinc-500 bg-white dark:bg-zinc-800\">\n {formatSize(upload.size)}\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport type { NodeDefinition } from \"@teamflojo/floimg-studio-shared\";\nimport { getGenerators, getTransforms, getTextProviders, getVisionProviders } from \"../api/client\";\nimport { useWorkflowStore } from \"../stores/workflowStore\";\nimport { UploadGallery } from \"./UploadGallery\";\n\nexport function NodePalette() {\n const setGenerators = useWorkflowStore((s) => s.setGenerators);\n const setTransforms = useWorkflowStore((s) => s.setTransforms);\n const setTextProviders = useWorkflowStore((s) => s.setTextProviders);\n const setVisionProviders = useWorkflowStore((s) => s.setVisionProviders);\n const generators = useWorkflowStore((s) => s.generators);\n const transforms = useWorkflowStore((s) => s.transforms);\n const textProviders = useWorkflowStore((s) => s.textProviders);\n const visionProviders = useWorkflowStore((s) => s.visionProviders);\n const addNode = useWorkflowStore((s) => s.addNode);\n const [showUploads, setShowUploads] = useState(false);\n\n // Fetch node definitions\n const { data: fetchedGenerators } = useQuery({\n queryKey: [\"generators\"],\n queryFn: getGenerators,\n });\n\n const { data: fetchedTransforms } = useQuery({\n queryKey: [\"transforms\"],\n queryFn: getTransforms,\n });\n\n const { data: fetchedTextProviders } = useQuery({\n queryKey: [\"textProviders\"],\n queryFn: getTextProviders,\n });\n\n const { data: fetchedVisionProviders } = useQuery({\n queryKey: [\"visionProviders\"],\n queryFn: getVisionProviders,\n });\n\n useEffect(() => {\n if (fetchedGenerators) setGenerators(fetchedGenerators);\n }, [fetchedGenerators, setGenerators]);\n\n useEffect(() => {\n if (fetchedTransforms) setTransforms(fetchedTransforms);\n }, [fetchedTransforms, setTransforms]);\n\n useEffect(() => {\n if (fetchedTextProviders) setTextProviders(fetchedTextProviders);\n }, [fetchedTextProviders, setTextProviders]);\n\n useEffect(() => {\n if (fetchedVisionProviders) setVisionProviders(fetchedVisionProviders);\n }, [fetchedVisionProviders, setVisionProviders]);\n\n const handleDragStart = (e: React.DragEvent, definition: NodeDefinition) => {\n e.dataTransfer.setData(\"application/json\", JSON.stringify(definition));\n e.dataTransfer.effectAllowed = \"move\";\n };\n\n const handleDoubleClick = (definition: NodeDefinition) => {\n // Add node at center of canvas\n addNode(definition, { x: 250, y: 150 + Math.random() * 100 });\n };\n\n // Input node definition (special case - for uploaded images)\n const inputDefinition: NodeDefinition = {\n id: \"input:upload\",\n type: \"input\",\n name: \"upload\",\n label: \"Upload Image\",\n description: \"Use an uploaded image\",\n category: \"Input\",\n params: {\n type: \"object\",\n properties: {},\n },\n };\n\n // Save node definition (special case)\n const saveDefinition: NodeDefinition = {\n id: \"save:filesystem\",\n type: \"save\",\n name: \"save\",\n label: \"Save\",\n description: \"Save image to file\",\n category: \"Output\",\n params: {\n type: \"object\",\n properties: {\n destination: {\n type: \"string\",\n title: \"Destination\",\n default: \"./output/image.png\",\n },\n provider: {\n type: \"string\",\n default: \"filesystem\",\n },\n },\n },\n };\n\n // Flow control node definitions (iterative workflows)\n const fanOutDefinition: NodeDefinition = {\n id: \"fanout:default\",\n type: \"fanout\",\n name: \"fanout\",\n label: \"Fan-Out\",\n description: \"Distribute to parallel branches\",\n category: \"Flow Control\",\n params: {\n type: \"object\",\n properties: {\n mode: {\n type: \"string\",\n title: \"Mode\",\n description: \"How to fan out\",\n enum: [\"array\", \"count\"],\n default: \"count\",\n },\n count: {\n type: \"number\",\n title: \"Count\",\n description: \"Number of parallel branches (count mode)\",\n default: 3,\n minimum: 2,\n maximum: 10,\n },\n arrayProperty: {\n type: \"string\",\n title: \"Array Property\",\n description: \"Property name to iterate over (array mode)\",\n },\n },\n },\n };\n\n const collectDefinition: NodeDefinition = {\n id: \"collect:default\",\n type: \"collect\",\n name: \"collect\",\n label: \"Collect\",\n description: \"Gather parallel outputs\",\n category: \"Flow Control\",\n params: {\n type: \"object\",\n properties: {\n expectedInputs: {\n type: \"number\",\n title: \"Expected Inputs\",\n description: \"Number of inputs to collect\",\n default: 3,\n minimum: 2,\n maximum: 10,\n },\n waitMode: {\n type: \"string\",\n title: \"Wait Mode\",\n description: \"When to output\",\n enum: [\"all\", \"available\"],\n default: \"all\",\n },\n },\n },\n };\n\n const routerDefinition: NodeDefinition = {\n id: \"router:default\",\n type: \"router\",\n name: \"router\",\n label: \"Router\",\n description: \"Route based on AI selection\",\n category: \"Flow Control\",\n params: {\n type: \"object\",\n properties: {\n selectionProperty: {\n type: \"string\",\n title: \"Selection Property\",\n description: \"JSON property with selection (e.g., 'winner')\",\n default: \"winner\",\n },\n selectionType: {\n type: \"string\",\n title: \"Selection Type\",\n description: \"How to interpret selection\",\n enum: [\"index\", \"value\"],\n default: \"index\",\n },\n outputCount: {\n type: \"number\",\n title: \"Output Count\",\n description: \"How many items to route\",\n default: 1,\n minimum: 1,\n maximum: 5,\n },\n contextProperty: {\n type: \"string\",\n title: \"Context Property\",\n description: \"Optional property to pass through (e.g., 'refinement')\",\n },\n },\n },\n };\n\n // Group generators by category\n const generatorsByCategory = generators.reduce(\n (acc, g) => {\n const cat = g.category || \"Other\";\n if (!acc[cat]) acc[cat] = [];\n acc[cat].push(g);\n return acc;\n },\n {} as Record<string, NodeDefinition[]>\n );\n\n // Group transforms by category\n const transformsByCategory = transforms.reduce(\n (acc, t) => {\n const cat = t.category || \"Other\";\n if (!acc[cat]) acc[cat] = [];\n acc[cat].push(t);\n return acc;\n },\n {} as Record<string, NodeDefinition[]>\n );\n\n return (\n <div className=\"floimg-sidebar w-64 border-r border-gray-200 dark:border-zinc-700 overflow-y-auto\">\n <div className=\"p-4\">\n <h2 className=\"floimg-sidebar__header text-lg !normal-case !tracking-normal\">Nodes</h2>\n\n {/* Input */}\n <div className=\"floimg-sidebar__section\">\n <div className=\"flex items-center justify-between mb-2\">\n <h3 className=\"floimg-sidebar__header !text-amber-600 dark:!text-amber-400 !mb-0\">\n Input\n </h3>\n <button\n onClick={() => setShowUploads(!showUploads)}\n className=\"text-xs text-amber-600 dark:text-amber-400 hover:text-amber-700 dark:hover:text-amber-300\"\n >\n {showUploads ? \"Hide\" : \"Browse\"} Uploads\n </button>\n </div>\n <div\n draggable\n onDragStart={(e) => handleDragStart(e, inputDefinition)}\n onDoubleClick={() => handleDoubleClick(inputDefinition)}\n className=\"floimg-palette-item floimg-palette-item--amber\"\n >\n <div className=\"floimg-palette-item__title\">Upload Image</div>\n <div className=\"floimg-palette-item__desc\">Start with your image</div>\n </div>\n {showUploads && (\n <div className=\"mt-2 border border-amber-200 dark:border-amber-700 rounded bg-white dark:bg-zinc-900 max-h-64 overflow-y-auto\">\n <UploadGallery />\n </div>\n )}\n </div>\n\n {/* Generators */}\n <div className=\"floimg-sidebar__section\">\n <h3 className=\"floimg-sidebar__header !text-blue-600 dark:!text-blue-400\">Generators</h3>\n {Object.entries(generatorsByCategory).map(([category, nodes]) => (\n <div key={category} className=\"mb-3\">\n <div className=\"floimg-sidebar__category\">{category}</div>\n {nodes.map((def) => (\n <div\n key={def.id}\n draggable\n onDragStart={(e) => handleDragStart(e, def)}\n onDoubleClick={() => handleDoubleClick(def)}\n className=\"floimg-palette-item floimg-palette-item--blue\"\n >\n <div className=\"floimg-palette-item__title\">{def.label}</div>\n {def.description && (\n <div className=\"floimg-palette-item__desc\">{def.description}</div>\n )}\n </div>\n ))}\n </div>\n ))}\n </div>\n\n {/* Transforms */}\n <div className=\"floimg-sidebar__section\">\n <h3 className=\"floimg-sidebar__header !text-teal-600 dark:!text-teal-400\">Transforms</h3>\n {Object.entries(transformsByCategory).map(([category, nodes]) => (\n <div key={category} className=\"mb-3\">\n <div className=\"floimg-sidebar__category\">{category}</div>\n {nodes.map((def) => (\n <div\n key={def.id}\n draggable\n onDragStart={(e) => handleDragStart(e, def)}\n onDoubleClick={() => handleDoubleClick(def)}\n className=\"floimg-palette-item floimg-palette-item--teal\"\n >\n <div className=\"floimg-palette-item__title\">{def.label}</div>\n {def.description && (\n <div className=\"floimg-palette-item__desc\">{def.description}</div>\n )}\n </div>\n ))}\n </div>\n ))}\n </div>\n\n {/* AI Text */}\n {textProviders.length > 0 && (\n <div className=\"floimg-sidebar__section\">\n <h3 className=\"floimg-sidebar__header !text-pink-600 dark:!text-pink-400\">AI Text</h3>\n {textProviders.map((def) => (\n <div\n key={def.id}\n draggable\n onDragStart={(e) => handleDragStart(e, def)}\n onDoubleClick={() => handleDoubleClick(def)}\n className=\"floimg-palette-item floimg-palette-item--pink\"\n >\n <div className=\"floimg-palette-item__title\">{def.label}</div>\n {def.description && (\n <div className=\"floimg-palette-item__desc\">{def.description}</div>\n )}\n </div>\n ))}\n </div>\n )}\n\n {/* AI Vision */}\n {visionProviders.length > 0 && (\n <div className=\"floimg-sidebar__section\">\n <h3 className=\"floimg-sidebar__header !text-cyan-600 dark:!text-cyan-400\">AI Vision</h3>\n {visionProviders.map((def) => (\n <div\n key={def.id}\n draggable\n onDragStart={(e) => handleDragStart(e, def)}\n onDoubleClick={() => handleDoubleClick(def)}\n className=\"floimg-palette-item floimg-palette-item--cyan\"\n >\n <div className=\"floimg-palette-item__title\">{def.label}</div>\n {def.description && (\n <div className=\"floimg-palette-item__desc\">{def.description}</div>\n )}\n </div>\n ))}\n </div>\n )}\n\n {/* Flow Control */}\n <div className=\"floimg-sidebar__section\">\n <h3 className=\"floimg-sidebar__header !text-orange-600 dark:!text-orange-400\">\n Flow Control\n </h3>\n <div\n draggable\n onDragStart={(e) => handleDragStart(e, fanOutDefinition)}\n onDoubleClick={() => handleDoubleClick(fanOutDefinition)}\n className=\"floimg-palette-item floimg-palette-item--orange\"\n >\n <div className=\"floimg-palette-item__title\">Fan-Out</div>\n <div className=\"floimg-palette-item__desc\">Distribute to parallel branches</div>\n </div>\n <div\n draggable\n onDragStart={(e) => handleDragStart(e, collectDefinition)}\n onDoubleClick={() => handleDoubleClick(collectDefinition)}\n className=\"floimg-palette-item floimg-palette-item--orange\"\n >\n <div className=\"floimg-palette-item__title\">Collect</div>\n <div className=\"floimg-palette-item__desc\">Gather parallel outputs</div>\n </div>\n <div\n draggable\n onDragStart={(e) => handleDragStart(e, routerDefinition)}\n onDoubleClick={() => handleDoubleClick(routerDefinition)}\n className=\"floimg-palette-item floimg-palette-item--amber\"\n >\n <div className=\"floimg-palette-item__title\">Router</div>\n <div className=\"floimg-palette-item__desc\">Route based on AI selection</div>\n </div>\n </div>\n\n {/* Output */}\n <div className=\"floimg-sidebar__section\">\n <h3 className=\"floimg-sidebar__header !text-emerald-600 dark:!text-emerald-400\">\n Output\n </h3>\n <div\n draggable\n onDragStart={(e) => handleDragStart(e, saveDefinition)}\n onDoubleClick={() => handleDoubleClick(saveDefinition)}\n className=\"floimg-palette-item floimg-palette-item--emerald\"\n >\n <div className=\"floimg-palette-item__title\">Save</div>\n <div className=\"floimg-palette-item__desc\">Save to file</div>\n </div>\n </div>\n </div>\n </div>\n );\n}\n","import { useState } from \"react\";\nimport type {\n GeneratorNodeData,\n TransformNodeData,\n SaveNodeData,\n TextNodeData,\n VisionNodeData,\n FanOutNodeData,\n CollectNodeData,\n RouterNodeData,\n ParamField,\n OutputSchema,\n OutputProperty,\n} from \"@teamflojo/floimg-studio-shared\";\nimport { useWorkflowStore } from \"../stores/workflowStore\";\n\nexport function NodeInspector() {\n const selectedNodeId = useWorkflowStore((s) => s.selectedNodeId);\n const nodes = useWorkflowStore((s) => s.nodes);\n const generators = useWorkflowStore((s) => s.generators);\n const transforms = useWorkflowStore((s) => s.transforms);\n const textProviders = useWorkflowStore((s) => s.textProviders);\n const visionProviders = useWorkflowStore((s) => s.visionProviders);\n const updateNodeData = useWorkflowStore((s) => s.updateNodeData);\n const deleteNode = useWorkflowStore((s) => s.deleteNode);\n\n const selectedNode = nodes.find((n) => n.id === selectedNodeId);\n\n // Don't render if no node selected (parent handles visibility)\n if (!selectedNode) {\n return null;\n }\n\n // Get schema for the selected node\n let schema: Record<string, ParamField> | undefined;\n let nodeLabel = \"\";\n\n if (selectedNode.type === \"generator\") {\n const data = selectedNode.data as GeneratorNodeData;\n const def = generators.find((g) => g.name === data.generatorName);\n schema = def?.params?.properties;\n nodeLabel = def?.label || data.generatorName;\n } else if (selectedNode.type === \"transform\") {\n const data = selectedNode.data as TransformNodeData;\n const def = transforms.find((t) => t.name === data.operation);\n schema = def?.params?.properties;\n nodeLabel = def?.label || data.operation;\n } else if (selectedNode.type === \"save\") {\n const data = selectedNode.data as SaveNodeData;\n const isCloudSave = data.provider === \"cloud\";\n\n nodeLabel = isCloudSave ? \"Save to FloImg Cloud\" : \"Save\";\n schema = {\n destination: {\n type: \"string\",\n title: isCloudSave ? \"Filename\" : \"Destination\",\n description: isCloudSave ? \"Filename for cloud storage\" : \"File path to save the image\",\n },\n };\n } else if (selectedNode.type === \"text\") {\n const data = selectedNode.data as TextNodeData;\n const def = textProviders.find((t) => t.name === data.providerName);\n schema = def?.params?.properties;\n nodeLabel = def?.label || data.providerName;\n } else if (selectedNode.type === \"vision\") {\n const data = selectedNode.data as VisionNodeData;\n const def = visionProviders.find((v) => v.name === data.providerName);\n schema = def?.params?.properties;\n nodeLabel = def?.label || data.providerName;\n } else if (selectedNode.type === \"fanout\") {\n nodeLabel = \"Fan-Out\";\n schema = {\n mode: {\n type: \"string\",\n title: \"Mode\",\n description: \"How to distribute inputs\",\n enum: [\"count\", \"array\"],\n },\n count: {\n type: \"number\",\n title: \"Branch Count\",\n description: \"Number of parallel branches (count mode)\",\n minimum: 2,\n maximum: 10,\n },\n arrayProperty: {\n type: \"string\",\n title: \"Array Property\",\n description: \"Property name to iterate over (array mode)\",\n },\n };\n } else if (selectedNode.type === \"collect\") {\n nodeLabel = \"Collect\";\n schema = {\n expectedInputs: {\n type: \"number\",\n title: \"Expected Inputs\",\n description: \"Number of inputs to collect\",\n minimum: 2,\n maximum: 10,\n },\n waitMode: {\n type: \"string\",\n title: \"Wait Mode\",\n description: \"When to output results\",\n enum: [\"all\", \"available\"],\n },\n };\n } else if (selectedNode.type === \"router\") {\n nodeLabel = \"Router\";\n schema = {\n selectionProperty: {\n type: \"string\",\n title: \"Selection Property\",\n description: \"JSON property containing selection (e.g., 'winner')\",\n },\n selectionType: {\n type: \"string\",\n title: \"Selection Type\",\n description: \"How to interpret selection value\",\n enum: [\"index\", \"value\"],\n },\n outputCount: {\n type: \"number\",\n title: \"Output Count\",\n description: \"How many items to route (1 = single winner)\",\n minimum: 1,\n maximum: 5,\n },\n contextProperty: {\n type: \"string\",\n title: \"Context Property\",\n description: \"Optional property to pass through (e.g., 'refinement')\",\n },\n };\n }\n\n const handleParamChange = (key: string, value: unknown) => {\n if (selectedNode.type === \"generator\") {\n const data = selectedNode.data as GeneratorNodeData;\n updateNodeData(selectedNode.id, {\n params: { ...data.params, [key]: value },\n });\n } else if (selectedNode.type === \"transform\") {\n const data = selectedNode.data as TransformNodeData;\n updateNodeData(selectedNode.id, {\n params: { ...data.params, [key]: value },\n });\n } else if (selectedNode.type === \"save\") {\n updateNodeData(selectedNode.id, { [key]: value });\n } else if (selectedNode.type === \"text\") {\n const data = selectedNode.data as TextNodeData;\n updateNodeData(selectedNode.id, {\n params: { ...data.params, [key]: value },\n });\n } else if (selectedNode.type === \"vision\") {\n const data = selectedNode.data as VisionNodeData;\n updateNodeData(selectedNode.id, {\n params: { ...data.params, [key]: value },\n });\n } else if (\n selectedNode.type === \"fanout\" ||\n selectedNode.type === \"collect\" ||\n selectedNode.type === \"router\"\n ) {\n // Flow control nodes store data directly (not in params)\n updateNodeData(selectedNode.id, { [key]: value });\n }\n };\n\n const getParamValue = (key: string): unknown => {\n if (selectedNode.type === \"generator\") {\n return (selectedNode.data as GeneratorNodeData).params[key];\n } else if (selectedNode.type === \"transform\") {\n return (selectedNode.data as TransformNodeData).params[key];\n } else if (selectedNode.type === \"save\") {\n return (selectedNode.data as SaveNodeData)[key as keyof SaveNodeData];\n } else if (selectedNode.type === \"text\") {\n return (selectedNode.data as TextNodeData).params[key];\n } else if (selectedNode.type === \"vision\") {\n return (selectedNode.data as VisionNodeData).params[key];\n } else if (selectedNode.type === \"fanout\") {\n return (selectedNode.data as FanOutNodeData)[key as keyof FanOutNodeData];\n } else if (selectedNode.type === \"collect\") {\n return (selectedNode.data as CollectNodeData)[key as keyof CollectNodeData];\n } else if (selectedNode.type === \"router\") {\n return (selectedNode.data as RouterNodeData)[key as keyof RouterNodeData];\n }\n return undefined;\n };\n\n // Determine which fields should be visible based on current parameter values\n const isFieldVisible = (key: string, _field: ParamField): boolean => {\n // For shapes generator, apply conditional visibility\n if (\n selectedNode.type === \"generator\" &&\n (selectedNode.data as GeneratorNodeData).generatorName === \"shapes\"\n ) {\n const shapeType = getParamValue(\"shapeType\") || \"rectangle\";\n const fillType = getParamValue(\"fillType\") || \"solid\";\n\n // Shape-specific parameters\n if (key === \"sides\") return shapeType === \"polygon\";\n if (key === \"points\" || key === \"innerRadius\") return shapeType === \"star\";\n if (key === \"cornerRadius\") return shapeType === \"rectangle\";\n\n // Fill-specific parameters\n if (key === \"fillColor\") return fillType === \"solid\";\n if (\n key === \"gradientType\" ||\n key === \"gradientColor1\" ||\n key === \"gradientColor2\" ||\n key === \"gradientAngle\"\n ) {\n return fillType === \"gradient\";\n }\n if (\n key === \"patternType\" ||\n key === \"patternColor\" ||\n key === \"patternBackground\" ||\n key === \"patternScale\"\n ) {\n return fillType === \"pattern\";\n }\n }\n\n // For fan-out, show count in count mode, arrayProperty in array mode\n if (selectedNode.type === \"fanout\") {\n const mode = (selectedNode.data as FanOutNodeData).mode || \"count\";\n if (key === \"count\") return mode === \"count\";\n if (key === \"arrayProperty\") return mode === \"array\";\n }\n\n return true;\n };\n\n return (\n <div className=\"floimg-inspector w-80 border-l border-gray-200 dark:border-zinc-700 overflow-y-auto\">\n <div className=\"p-4\">\n <div className=\"floimg-inspector__header\">\n <h2 className=\"floimg-inspector__title\">{nodeLabel}</h2>\n <button onClick={() => deleteNode(selectedNode.id)} className=\"floimg-inspector__delete\">\n Delete\n </button>\n </div>\n\n <div className=\"space-y-4\">\n {schema &&\n Object.entries(schema)\n .filter(([key, field]) => isFieldVisible(key, field))\n .map(([key, field]) => (\n <FieldEditor\n key={key}\n name={key}\n field={field}\n value={getParamValue(key)}\n onChange={(value) => handleParamChange(key, value)}\n />\n ))}\n </div>\n\n {/* Output Schema Editor for text/vision nodes */}\n {(selectedNode.type === \"text\" || selectedNode.type === \"vision\") && (\n <OutputSchemaEditor\n nodeId={selectedNode.id}\n outputSchema={(selectedNode.data as TextNodeData | VisionNodeData).outputSchema}\n updateNodeData={updateNodeData}\n />\n )}\n </div>\n </div>\n );\n}\n\ninterface FieldEditorProps {\n name: string;\n field: ParamField;\n value: unknown;\n onChange: (value: unknown) => void;\n}\n\nfunction FieldEditor({ name, field, value, onChange }: FieldEditorProps) {\n const label = field.title || name;\n\n // Enum -> select dropdown\n if (field.enum) {\n return (\n <div className=\"floimg-field\">\n <label className=\"floimg-field__label\">{label}</label>\n <select\n value={String(value || \"\")}\n onChange={(e) => onChange(e.target.value)}\n className=\"floimg-field__input\"\n >\n <option value=\"\">Select...</option>\n {field.enum.map((opt) => (\n <option key={opt} value={opt}>\n {opt}\n </option>\n ))}\n </select>\n {field.description && <p className=\"floimg-field__hint\">{field.description}</p>}\n </div>\n );\n }\n\n // Number input\n if (field.type === \"number\") {\n return (\n <div className=\"floimg-field\">\n <label className=\"floimg-field__label\">{label}</label>\n <input\n type=\"number\"\n value={value !== undefined ? Number(value) : \"\"}\n onChange={(e) => onChange(Number(e.target.value))}\n min={field.minimum}\n max={field.maximum}\n className=\"floimg-field__input\"\n />\n {field.description && <p className=\"floimg-field__hint\">{field.description}</p>}\n </div>\n );\n }\n\n // Boolean -> checkbox\n if (field.type === \"boolean\") {\n return (\n <div className=\"floimg-field flex items-center gap-2\">\n <input\n type=\"checkbox\"\n checked={Boolean(value)}\n onChange={(e) => onChange(e.target.checked)}\n className=\"h-4 w-4 text-teal-600 focus:ring-teal-500 border-gray-300 dark:border-zinc-600 rounded bg-white dark:bg-zinc-900\"\n />\n <label className=\"floimg-field__label !mb-0\">{label}</label>\n </div>\n );\n }\n\n // Color picker for color-related fields\n if (name.toLowerCase().includes(\"color\") && typeof value === \"string\" && value.startsWith(\"#\")) {\n return (\n <div className=\"floimg-field\">\n <label className=\"floimg-field__label\">{label}</label>\n <div className=\"flex gap-2\">\n <input\n type=\"color\"\n value={String(value || \"#000000\")}\n onChange={(e) => onChange(e.target.value)}\n className=\"h-10 w-14 p-1 border border-gray-300 dark:border-zinc-600 rounded-lg\"\n />\n <input\n type=\"text\"\n value={String(value || \"\")}\n onChange={(e) => onChange(e.target.value)}\n className=\"floimg-field__input flex-1\"\n />\n </div>\n </div>\n );\n }\n\n // Default: text input (also for objects as JSON)\n if (field.type === \"object\") {\n return (\n <div className=\"floimg-field\">\n <label className=\"floimg-field__label\">{label}</label>\n <textarea\n value={value ? JSON.stringify(value, null, 2) : \"{}\"}\n onChange={(e) => {\n try {\n onChange(JSON.parse(e.target.value));\n } catch {\n // Invalid JSON, ignore\n }\n }}\n rows={4}\n className=\"floimg-field__input font-mono text-xs\"\n />\n {field.description && <p className=\"floimg-field__hint\">{field.description}</p>}\n </div>\n );\n }\n\n // String input (default)\n return (\n <div className=\"floimg-field\">\n <label className=\"floimg-field__label\">{label}</label>\n {name === \"prompt\" || name === \"code\" || name === \"text\" ? (\n <textarea\n value={String(value || \"\")}\n onChange={(e) => onChange(e.target.value)}\n rows={3}\n className=\"floimg-field__input\"\n />\n ) : (\n <input\n type=\"text\"\n value={String(value || \"\")}\n onChange={(e) => onChange(e.target.value)}\n className=\"floimg-field__input\"\n />\n )}\n {field.description && <p className=\"floimg-field__hint\">{field.description}</p>}\n </div>\n );\n}\n\n// ============================================================================\n// Output Schema Editor for text/vision nodes\n// ============================================================================\n\ninterface OutputSchemaEditorProps {\n nodeId: string;\n outputSchema?: OutputSchema;\n updateNodeData: (id: string, data: Partial<TextNodeData | VisionNodeData>) => void;\n}\n\nfunction OutputSchemaEditor({ nodeId, outputSchema, updateNodeData }: OutputSchemaEditorProps) {\n const [newPropertyName, setNewPropertyName] = useState(\"\");\n\n const properties = outputSchema?.properties || {};\n const propertyEntries = Object.entries(properties);\n\n const handleAddProperty = () => {\n if (!newPropertyName.trim()) return;\n\n const newSchema: OutputSchema = {\n type: \"object\",\n properties: {\n ...properties,\n [newPropertyName.trim()]: { type: \"string\" },\n },\n };\n\n updateNodeData(nodeId, { outputSchema: newSchema });\n setNewPropertyName(\"\");\n };\n\n const handleRemoveProperty = (key: string) => {\n const newProperties = { ...properties };\n delete newProperties[key];\n\n if (Object.keys(newProperties).length === 0) {\n updateNodeData(nodeId, { outputSchema: undefined });\n } else {\n updateNodeData(nodeId, {\n outputSchema: { type: \"object\", properties: newProperties },\n });\n }\n };\n\n const handleTypeChange = (key: string, type: OutputProperty[\"type\"]) => {\n updateNodeData(nodeId, {\n outputSchema: {\n type: \"object\",\n properties: {\n ...properties,\n [key]: { ...properties[key], type },\n },\n },\n });\n };\n\n const handleDescriptionChange = (key: string, description: string) => {\n updateNodeData(nodeId, {\n outputSchema: {\n type: \"object\",\n properties: {\n ...properties,\n [key]: { ...properties[key], description: description || undefined },\n },\n },\n });\n };\n\n return (\n <div className=\"mt-6 pt-4 border-t border-gray-200 dark:border-zinc-700\">\n <div className=\"flex items-center justify-between mb-3\">\n <h3 className=\"text-sm font-medium text-gray-700 dark:text-zinc-300\">Output Schema</h3>\n <span className=\"text-xs text-gray-500 dark:text-zinc-500\">\n {propertyEntries.length > 0\n ? `${propertyEntries.length} output${propertyEntries.length > 1 ? \"s\" : \"\"}`\n : \"No outputs defined\"}\n </span>\n </div>\n\n <p className=\"text-xs text-gray-500 dark:text-zinc-400 mb-3\">\n Define output properties to enable connecting individual JSON fields to other nodes.\n </p>\n\n {/* Existing properties */}\n {propertyEntries.length > 0 && (\n <div className=\"space-y-2 mb-3\">\n {propertyEntries.map(([key, prop]) => (\n <div\n key={key}\n className=\"flex items-center gap-2 p-2 bg-pink-50 dark:bg-pink-900/20 rounded border border-pink-200 dark:border-pink-800\"\n >\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium text-pink-700 dark:text-pink-300 truncate\">\n {key}\n </span>\n <select\n value={prop.type}\n onChange={(e) =>\n handleTypeChange(key, e.target.value as OutputProperty[\"type\"])\n }\n className=\"text-xs px-1.5 py-0.5 rounded border border-pink-300 dark:border-pink-700 bg-white dark:bg-zinc-800 text-gray-700 dark:text-zinc-300\"\n >\n <option value=\"string\">string</option>\n <option value=\"number\">number</option>\n <option value=\"boolean\">boolean</option>\n <option value=\"object\">object</option>\n <option value=\"array\">array</option>\n </select>\n </div>\n <input\n type=\"text\"\n value={prop.description || \"\"}\n onChange={(e) => handleDescriptionChange(key, e.target.value)}\n placeholder=\"Description (optional)\"\n className=\"mt-1 w-full text-xs px-2 py-1 rounded border border-pink-200 dark:border-pink-700 bg-white dark:bg-zinc-800 text-gray-600 dark:text-zinc-400 placeholder-gray-400 dark:placeholder-zinc-500\"\n />\n </div>\n <button\n onClick={() => handleRemoveProperty(key)}\n className=\"text-pink-500 hover:text-pink-700 dark:text-pink-400 dark:hover:text-pink-300 p-1\"\n title=\"Remove property\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n </div>\n ))}\n </div>\n )}\n\n {/* Add new property */}\n <div className=\"flex gap-2\">\n <input\n type=\"text\"\n value={newPropertyName}\n onChange={(e) => setNewPropertyName(e.target.value)}\n onKeyDown={(e) => e.key === \"Enter\" && handleAddProperty()}\n placeholder=\"Property name...\"\n className=\"flex-1 px-2 py-1.5 text-sm border border-gray-300 dark:border-zinc-600 rounded bg-white dark:bg-zinc-900 text-gray-900 dark:text-zinc-100 placeholder-gray-400 dark:placeholder-zinc-500\"\n />\n <button\n onClick={handleAddProperty}\n disabled={!newPropertyName.trim()}\n className=\"px-3 py-1.5 text-sm font-medium text-white bg-pink-500 rounded hover:bg-pink-600 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n Add\n </button>\n </div>\n\n {/* Hint about usage */}\n {propertyEntries.length > 0 && (\n <p className=\"mt-3 text-xs text-gray-500 dark:text-zinc-500\">\n Connect from the small pink handles on the right of the node to route individual\n properties.\n </p>\n )}\n </div>\n );\n}\n","import { createContext as T, useContext as M, useState as A, useCallback as w, useRef as S, useLayoutEffect as z, useEffect as J } from \"react\";\nimport { jsx as b } from \"react/jsx-runtime\";\nconst j = [\"shift\", \"alt\", \"meta\", \"mod\", \"ctrl\", \"control\"], Q = {\n esc: \"escape\",\n return: \"enter\",\n left: \"arrowleft\",\n right: \"arrowright\",\n up: \"arrowup\",\n down: \"arrowdown\",\n ShiftLeft: \"shift\",\n ShiftRight: \"shift\",\n AltLeft: \"alt\",\n AltRight: \"alt\",\n MetaLeft: \"meta\",\n MetaRight: \"meta\",\n OSLeft: \"meta\",\n OSRight: \"meta\",\n ControlLeft: \"ctrl\",\n ControlRight: \"ctrl\"\n};\nfunction K(e) {\n return (Q[e.trim()] || e.trim()).toLowerCase().replace(/key|digit|numpad/, \"\");\n}\nfunction D(e) {\n return j.includes(e);\n}\nfunction H(e, r = \",\") {\n return e.toLowerCase().split(r);\n}\nfunction P(e, r = \"+\", o = \">\", i = !1, u) {\n let n = [], c = !1;\n e = e.trim(), e.includes(o) ? (c = !0, n = e.toLocaleLowerCase().split(o).map((f) => K(f))) : n = e.toLocaleLowerCase().split(r).map((f) => K(f));\n const y = {\n alt: n.includes(\"alt\"),\n ctrl: n.includes(\"ctrl\") || n.includes(\"control\"),\n shift: n.includes(\"shift\"),\n meta: n.includes(\"meta\"),\n mod: n.includes(\"mod\"),\n useKey: i\n }, d = n.filter((f) => !j.includes(f));\n return {\n ...y,\n keys: d,\n description: u,\n isSequence: c,\n hotkey: e\n };\n}\ntypeof document < \"u\" && (document.addEventListener(\"keydown\", (e) => {\n e.code !== void 0 && I([K(e.code)]);\n}), document.addEventListener(\"keyup\", (e) => {\n e.code !== void 0 && _([K(e.code)]);\n})), typeof window < \"u\" && (window.addEventListener(\"blur\", () => {\n L.clear();\n}), window.addEventListener(\"contextmenu\", () => {\n setTimeout(() => {\n L.clear();\n }, 0);\n}));\nconst L = /* @__PURE__ */ new Set();\nfunction R(e) {\n return Array.isArray(e);\n}\nfunction U(e, r = \",\") {\n return (R(e) ? e : e.split(r)).every((i) => L.has(i.trim().toLowerCase()));\n}\nfunction I(e) {\n const r = Array.isArray(e) ? e : [e];\n L.has(\"meta\") && L.forEach((o) => !D(o) && L.delete(o.toLowerCase())), r.forEach((o) => L.add(o.toLowerCase()));\n}\nfunction _(e) {\n const r = Array.isArray(e) ? e : [e];\n e === \"meta\" ? L.clear() : r.forEach((o) => L.delete(o.toLowerCase()));\n}\nfunction V(e, r, o) {\n (typeof o == \"function\" && o(e, r) || o === !0) && e.preventDefault();\n}\nfunction X(e, r, o) {\n return typeof o == \"function\" ? o(e, r) : o === !0 || o === void 0;\n}\nconst Y = [\n \"input\",\n \"textarea\",\n \"select\",\n \"searchbox\",\n \"slider\",\n \"spinbutton\",\n \"menuitem\",\n \"menuitemcheckbox\",\n \"menuitemradio\",\n \"option\",\n \"radio\",\n \"textbox\"\n];\nfunction Z(e) {\n return F(e, Y);\n}\nfunction F(e, r = !1) {\n const { target: o, composed: i } = e;\n let u, n;\n return ee(o) && i ? (u = e.composedPath()[0] && e.composedPath()[0].tagName, n = e.composedPath()[0] && e.composedPath()[0].role) : (u = o && o.tagName, n = o && o.role), R(r) ? !!(u && r && r.some((c) => c.toLowerCase() === u.toLowerCase() || c === n)) : !!(u && r && r);\n}\nfunction ee(e) {\n return !!e.tagName && !e.tagName.startsWith(\"-\") && e.tagName.includes(\"-\");\n}\nfunction te(e, r) {\n return e.length === 0 && r ? (console.warn(\n 'A hotkey has the \"scopes\" option set, however no active scopes were found. If you want to use the global scopes feature, you need to wrap your app in a <HotkeysProvider>'\n ), !0) : r ? e.some((o) => r.includes(o)) || e.includes(\"*\") : !0;\n}\nconst re = (e, r, o = !1) => {\n const { alt: i, meta: u, mod: n, shift: c, ctrl: y, keys: d, useKey: f } = r, { code: p, key: t, ctrlKey: a, metaKey: l, shiftKey: g, altKey: k } = e, m = K(p);\n if (f && d?.length === 1 && d.includes(t))\n return !0;\n if (!d?.includes(m) && ![\"ctrl\", \"control\", \"unknown\", \"meta\", \"alt\", \"shift\", \"os\"].includes(m))\n return !1;\n if (!o) {\n if (i !== k && m !== \"alt\" || c !== g && m !== \"shift\")\n return !1;\n if (n) {\n if (!l && !a)\n return !1;\n } else if (u !== l && m !== \"meta\" && m !== \"os\" || y !== a && m !== \"ctrl\" && m !== \"control\")\n return !1;\n }\n return d && d.length === 1 && d.includes(m) ? !0 : d ? U(d) : !d;\n}, $ = T(void 0), oe = () => M($);\nfunction ne({ addHotkey: e, removeHotkey: r, children: o }) {\n return /* @__PURE__ */ b($.Provider, { value: { addHotkey: e, removeHotkey: r }, children: o });\n}\nfunction x(e, r) {\n return e && r && typeof e == \"object\" && typeof r == \"object\" ? Object.keys(e).length === Object.keys(r).length && // @ts-expect-error TS7053\n Object.keys(e).reduce((o, i) => o && x(e[i], r[i]), !0) : e === r;\n}\nconst W = T({\n hotkeys: [],\n activeScopes: [],\n // This array has to be empty instead of containing '*' as default, to check if the provider is set or not\n toggleScope: () => {\n },\n enableScope: () => {\n },\n disableScope: () => {\n }\n}), se = () => M(W), de = ({ initiallyActiveScopes: e = [\"*\"], children: r }) => {\n const [o, i] = A(e), [u, n] = A([]), c = w((t) => {\n i((a) => a.includes(\"*\") ? [t] : Array.from(/* @__PURE__ */ new Set([...a, t])));\n }, []), y = w((t) => {\n i((a) => a.filter((l) => l !== t));\n }, []), d = w((t) => {\n i((a) => a.includes(t) ? a.filter((l) => l !== t) : a.includes(\"*\") ? [t] : Array.from(/* @__PURE__ */ new Set([...a, t])));\n }, []), f = w((t) => {\n n((a) => [...a, t]);\n }, []), p = w((t) => {\n n((a) => a.filter((l) => !x(l, t)));\n }, []);\n return /* @__PURE__ */ b(\n W.Provider,\n {\n value: { activeScopes: o, hotkeys: u, enableScope: c, disableScope: y, toggleScope: d },\n children: /* @__PURE__ */ b(ne, { addHotkey: f, removeHotkey: p, children: r })\n }\n );\n};\nfunction ie(e) {\n const r = S(void 0);\n return x(r.current, e) || (r.current = e), r.current;\n}\nconst N = (e) => {\n e.stopPropagation(), e.preventDefault(), e.stopImmediatePropagation();\n}, ue = typeof window < \"u\" ? z : J;\nfunction fe(e, r, o, i) {\n const u = S(null), n = S(!1), c = Array.isArray(o) ? Array.isArray(i) ? void 0 : i : o, y = R(e) ? e.join(c?.delimiter) : e, d = Array.isArray(o) ? o : Array.isArray(i) ? i : void 0, f = w(r, d ?? []), p = S(f);\n d ? p.current = f : p.current = r;\n const t = ie(c), { activeScopes: a } = se(), l = oe();\n return ue(() => {\n if (t?.enabled === !1 || !te(a, t?.scopes))\n return;\n let g = [], k;\n const m = (s, B = !1) => {\n if (!(Z(s) && !F(s, t?.enableOnFormTags))) {\n if (u.current !== null) {\n const v = u.current.getRootNode();\n if ((v instanceof Document || v instanceof ShadowRoot) && v.activeElement !== u.current && !u.current.contains(v.activeElement)) {\n N(s);\n return;\n }\n }\n s.target?.isContentEditable && !t?.enableOnContentEditable || H(y, t?.delimiter).forEach((v) => {\n if (v.includes(t?.splitKey ?? \"+\") && v.includes(t?.sequenceSplitKey ?? \">\")) {\n console.warn(\n `Hotkey ${v} contains both ${t?.splitKey ?? \"+\"} and ${t?.sequenceSplitKey ?? \">\"} which is not supported.`\n );\n return;\n }\n const h = P(\n v,\n t?.splitKey,\n t?.sequenceSplitKey,\n t?.useKey,\n t?.description\n );\n if (h.isSequence) {\n k = setTimeout(() => {\n g = [];\n }, t?.sequenceTimeoutMs ?? 1e3);\n const C = h.useKey ? s.key : K(s.code);\n if (D(C.toLowerCase()))\n return;\n g.push(C);\n const G = h.keys?.[g.length - 1];\n if (C !== G) {\n g = [], k && clearTimeout(k);\n return;\n }\n g.length === h.keys?.length && (p.current(s, h), k && clearTimeout(k), g = []);\n } else if (re(s, h, t?.ignoreModifiers) || h.keys?.includes(\"*\")) {\n if (t?.ignoreEventWhen?.(s) || B && n.current)\n return;\n if (V(s, h, t?.preventDefault), !X(s, h, t?.enabled)) {\n N(s);\n return;\n }\n p.current(s, h), B || (n.current = !0);\n }\n });\n }\n }, O = (s) => {\n s.code !== void 0 && (I(K(s.code)), (t?.keydown === void 0 && t?.keyup !== !0 || t?.keydown) && m(s));\n }, q = (s) => {\n s.code !== void 0 && (_(K(s.code)), n.current = !1, t?.keyup && m(s, !0));\n }, E = u.current || c?.document || document;\n return E.addEventListener(\"keyup\", q, c?.eventListenerOptions), E.addEventListener(\"keydown\", O, c?.eventListenerOptions), l && H(y, t?.delimiter).forEach(\n (s) => l.addHotkey(\n P(\n s,\n t?.splitKey,\n t?.sequenceSplitKey,\n t?.useKey,\n t?.description\n )\n )\n ), () => {\n E.removeEventListener(\"keyup\", q, c?.eventListenerOptions), E.removeEventListener(\"keydown\", O, c?.eventListenerOptions), l && H(y, t?.delimiter).forEach(\n (s) => l.removeHotkey(\n P(\n s,\n t?.splitKey,\n t?.sequenceSplitKey,\n t?.useKey,\n t?.description\n )\n )\n ), g = [], k && clearTimeout(k);\n };\n }, [y, t, a]), u;\n}\nfunction le(e = !1) {\n const [r, o] = A(/* @__PURE__ */ new Set()), [i, u] = A(!1), n = w(\n (f) => {\n f.code !== void 0 && (f.preventDefault(), f.stopPropagation(), o((p) => {\n const t = new Set(p);\n return t.add(K(e ? f.key : f.code)), t;\n }));\n },\n [e]\n ), c = w(() => {\n typeof document < \"u\" && (document.removeEventListener(\"keydown\", n), u(!1));\n }, [n]), y = w(() => {\n o(/* @__PURE__ */ new Set()), typeof document < \"u\" && (c(), document.addEventListener(\"keydown\", n), u(!0));\n }, [n, c]), d = w(() => {\n o(/* @__PURE__ */ new Set());\n }, []);\n return [r, { start: y, stop: c, resetKeys: d, isRecording: i }];\n}\nexport {\n de as HotkeysProvider,\n U as isHotkeyPressed,\n fe as useHotkeys,\n se as useHotkeysContext,\n le as useRecordHotkeys\n};\n","/**\n * Global keyboard shortcuts hook\n * Centralizes all keyboard shortcut handling for FloImg Studio\n */\n\nimport { useCallback } from \"react\";\nimport { useHotkeys, Options } from \"react-hotkeys-hook\";\nimport { useReactFlow } from \"reactflow\";\nimport { useWorkflowStore } from \"../../stores/workflowStore\";\nimport { useSettingsStore } from \"../../stores/settingsStore\";\nimport type { ShortcutAction } from \"./types\";\nimport { SHORTCUT_DEFINITIONS } from \"./shortcuts\";\n\n/** Default options for shortcuts - skip when typing in inputs */\nconst DEFAULT_OPTIONS: Options = {\n enableOnFormTags: false,\n preventDefault: true,\n};\n\n/**\n * Get the effective binding for an action (user override or default)\n */\nfunction useEffectiveBinding(action: ShortcutAction): string | null {\n const keyboardSettings = useSettingsStore((s) => s.keyboard);\n const def = SHORTCUT_DEFINITIONS.find((d) => d.action === action);\n\n if (!def) return null;\n\n // User override takes precedence\n if (keyboardSettings?.shortcuts?.[action] !== undefined) {\n return keyboardSettings.shortcuts[action] ?? null;\n }\n\n return def.defaultBinding;\n}\n\n/**\n * Hook to register a single keyboard shortcut\n */\nfunction useShortcut(action: ShortcutAction, handler: () => void, options: Options = {}): void {\n const binding = useEffectiveBinding(action);\n const keyboardEnabled = useSettingsStore((s) => s.keyboard?.enabled ?? true);\n\n useHotkeys(\n binding || \"\",\n handler,\n {\n ...DEFAULT_OPTIONS,\n ...options,\n enabled: keyboardEnabled && !!binding,\n },\n [handler, binding, keyboardEnabled]\n );\n}\n\n/** Props for configuring the keyboard shortcuts hook */\nexport interface UseKeyboardShortcutsProps {\n /** Callback to toggle AI Chat panel */\n onToggleAIChat?: () => void;\n}\n\n/**\n * Global keyboard shortcuts provider hook\n * Call this once in App.tsx to register all shortcuts\n */\nexport function useKeyboardShortcuts(props: UseKeyboardShortcutsProps = {}) {\n const { onToggleAIChat } = props;\n const reactFlowInstance = useReactFlow();\n\n // Workflow store actions\n const nodes = useWorkflowStore((s) => s.nodes);\n const selectedNodeId = useWorkflowStore((s) => s.selectedNodeId);\n const execution = useWorkflowStore((s) => s.execution);\n const hasUnsavedChanges = useWorkflowStore((s) => s.hasUnsavedChanges);\n const saveWorkflow = useWorkflowStore((s) => s.saveWorkflow);\n const execute = useWorkflowStore((s) => s.execute);\n const cancelExecution = useWorkflowStore((s) => s.cancelExecution);\n const duplicateNode = useWorkflowStore((s) => s.duplicateNode);\n const setSelectedNode = useWorkflowStore((s) => s.setSelectedNode);\n const toggleLibrary = useWorkflowStore((s) => s.toggleLibrary);\n const newWorkflow = useWorkflowStore((s) => s.newWorkflow);\n\n // Settings store actions\n const openSettings = useSettingsStore((s) => s.openSettings);\n const openShortcutsModal = useSettingsStore((s) => s.openShortcutsModal);\n const openCommandPalette = useSettingsStore((s) => s.openCommandPalette);\n const closeCommandPalette = useSettingsStore((s) => s.closeCommandPalette);\n const closeShortcutsModal = useSettingsStore((s) => s.closeShortcutsModal);\n const closeSettings = useSettingsStore((s) => s.closeSettings);\n const showCommandPalette = useSettingsStore((s) => s.showCommandPalette);\n const openExport = useSettingsStore((s) => s.openExport);\n const openImport = useSettingsStore((s) => s.openImport);\n const requestNewWorkflow = useSettingsStore((s) => s.requestNewWorkflow);\n\n // Workflow shortcuts\n const handleSave = useCallback(() => {\n if (nodes.length === 0) return;\n saveWorkflow();\n }, [nodes.length, saveWorkflow]);\n\n const handleExecute = useCallback(() => {\n if (nodes.length === 0 || execution.status === \"running\") return;\n execute();\n }, [nodes.length, execution.status, execute]);\n\n const handleNewWorkflow = useCallback(() => {\n requestNewWorkflow(hasUnsavedChanges, newWorkflow);\n }, [requestNewWorkflow, hasUnsavedChanges, newWorkflow]);\n\n const handleExport = useCallback(() => {\n if (nodes.length === 0) return;\n openExport?.();\n }, [nodes.length, openExport]);\n\n const handleImport = useCallback(() => {\n openImport?.();\n }, [openImport]);\n\n const handleCancelExecution = useCallback(() => {\n if (execution.status === \"running\") {\n cancelExecution();\n }\n }, [execution.status, cancelExecution]);\n\n // Editing shortcuts\n const handleDuplicate = useCallback(() => {\n if (selectedNodeId) {\n duplicateNode(selectedNodeId);\n }\n }, [selectedNodeId, duplicateNode]);\n\n const handleSelectAll = useCallback(() => {\n // Select all nodes using React Flow\n // React Flow handles multi-select via its own state\n reactFlowInstance?.setNodes((nds) =>\n nds.map((node) => ({\n ...node,\n selected: true,\n }))\n );\n }, [reactFlowInstance]);\n\n const handleDeselect = useCallback(() => {\n // Close any open modals first\n closeCommandPalette?.();\n closeShortcutsModal?.();\n closeSettings?.();\n\n // Deselect all nodes\n setSelectedNode(null);\n reactFlowInstance?.setNodes((nds) =>\n nds.map((node) => ({\n ...node,\n selected: false,\n }))\n );\n }, [setSelectedNode, reactFlowInstance, closeCommandPalette, closeShortcutsModal, closeSettings]);\n\n // Canvas shortcuts\n const handleZoomIn = useCallback(() => {\n reactFlowInstance?.zoomIn();\n }, [reactFlowInstance]);\n\n const handleZoomOut = useCallback(() => {\n reactFlowInstance?.zoomOut();\n }, [reactFlowInstance]);\n\n const handleZoomFit = useCallback(() => {\n reactFlowInstance?.fitView({ padding: 0.2 });\n }, [reactFlowInstance]);\n\n // UI shortcuts\n const handleCommandPalette = useCallback(() => {\n if (showCommandPalette) {\n closeCommandPalette?.();\n } else {\n openCommandPalette?.();\n }\n }, [showCommandPalette, openCommandPalette, closeCommandPalette]);\n\n const handleShowShortcuts = useCallback(() => {\n openShortcutsModal?.();\n }, [openShortcutsModal]);\n\n const handleToggleAIChat = useCallback(() => {\n onToggleAIChat?.();\n }, [onToggleAIChat]);\n\n const handleToggleLibrary = useCallback(() => {\n toggleLibrary();\n }, [toggleLibrary]);\n\n const handleSettings = useCallback(() => {\n openSettings();\n }, [openSettings]);\n\n // Register all shortcuts\n useShortcut(\"save\", handleSave);\n useShortcut(\"execute\", handleExecute);\n useShortcut(\"newWorkflow\", handleNewWorkflow);\n useShortcut(\"exportWorkflow\", handleExport);\n useShortcut(\"importWorkflow\", handleImport);\n useShortcut(\"cancelExecution\", handleCancelExecution);\n useShortcut(\"duplicate\", handleDuplicate);\n useShortcut(\"selectAll\", handleSelectAll);\n useShortcut(\"deselect\", handleDeselect);\n useShortcut(\"zoomIn\", handleZoomIn);\n useShortcut(\"zoomOut\", handleZoomOut);\n useShortcut(\"zoomFit\", handleZoomFit);\n useShortcut(\"commandPalette\", handleCommandPalette);\n useShortcut(\"showShortcuts\", handleShowShortcuts);\n useShortcut(\"toggleAIChat\", handleToggleAIChat);\n useShortcut(\"toggleLibrary\", handleToggleLibrary);\n useShortcut(\"settings\", handleSettings);\n\n // Return bound handlers for external use\n return {\n handleSave,\n handleExecute,\n handleNewWorkflow,\n handleExport,\n handleImport,\n handleDuplicate,\n handleSelectAll,\n handleDeselect,\n handleZoomIn,\n handleZoomOut,\n handleZoomFit,\n handleCommandPalette,\n handleShowShortcuts,\n handleToggleAIChat,\n handleToggleLibrary,\n handleSettings,\n };\n}\n\n/**\n * Hook to get the current shortcut binding for display\n */\nexport function useShortcutBinding(action: ShortcutAction): string | null {\n return useEffectiveBinding(action);\n}\n","/**\n * Platform detection and key display utilities\n */\n\n/** Check if running on macOS */\nexport function isMac(): boolean {\n if (typeof navigator === \"undefined\") return false;\n return navigator.platform.toLowerCase().includes(\"mac\");\n}\n\n/** Get the modifier key name for display */\nexport function getModifierKey(): string {\n return isMac() ? \"⌘\" : \"Ctrl\";\n}\n\n/** Get the option/alt key name for display */\nexport function getOptionKey(): string {\n return isMac() ? \"⌥\" : \"Alt\";\n}\n\n/** Get the shift key symbol for display */\nexport function getShiftKey(): string {\n return \"⇧\";\n}\n\n/** Symbol mappings for display */\nconst KEY_SYMBOLS: Record<string, string> = {\n enter: \"⏎\",\n return: \"⏎\",\n escape: \"Esc\",\n backspace: \"⌫\",\n delete: \"Del\",\n arrowup: \"↑\",\n arrowdown: \"↓\",\n arrowleft: \"←\",\n arrowright: \"→\",\n space: \"Space\",\n tab: \"Tab\",\n comma: \",\",\n slash: \"/\",\n equal: \"=\",\n minus: \"-\",\n plus: \"+\",\n period: \".\",\n};\n\n/**\n * Convert a binding string (e.g., 'mod+s') to display format (e.g., '⌘S')\n */\nexport function bindingToDisplay(binding: string): string {\n if (!binding) return \"\";\n\n const parts = binding.toLowerCase().split(\"+\");\n const displayParts: string[] = [];\n\n for (const part of parts) {\n if (part === \"mod\") {\n displayParts.push(getModifierKey());\n } else if (part === \"ctrl\" || part === \"control\") {\n displayParts.push(isMac() ? \"⌃\" : \"Ctrl\");\n } else if (part === \"alt\" || part === \"option\") {\n displayParts.push(getOptionKey());\n } else if (part === \"shift\") {\n displayParts.push(getShiftKey());\n } else if (part === \"meta\" || part === \"cmd\" || part === \"command\") {\n displayParts.push(\"⌘\");\n } else if (KEY_SYMBOLS[part]) {\n displayParts.push(KEY_SYMBOLS[part]);\n } else {\n // Regular key - uppercase for display\n displayParts.push(part.toUpperCase());\n }\n }\n\n return displayParts.join(\"\");\n}\n\n/**\n * Convert a binding to an array of display keys (for KeyBadge)\n */\nexport function bindingToKeys(binding: string): string[] {\n if (!binding) return [];\n\n const parts = binding.toLowerCase().split(\"+\");\n const keys: string[] = [];\n\n for (const part of parts) {\n if (part === \"mod\") {\n keys.push(getModifierKey());\n } else if (part === \"ctrl\" || part === \"control\") {\n keys.push(isMac() ? \"⌃\" : \"Ctrl\");\n } else if (part === \"alt\" || part === \"option\") {\n keys.push(getOptionKey());\n } else if (part === \"shift\") {\n keys.push(getShiftKey());\n } else if (part === \"meta\" || part === \"cmd\" || part === \"command\") {\n keys.push(\"⌘\");\n } else if (KEY_SYMBOLS[part]) {\n keys.push(KEY_SYMBOLS[part]);\n } else {\n keys.push(part.toUpperCase());\n }\n }\n\n return keys;\n}\n\n/**\n * Convert a KeyboardEvent to a binding string\n */\nexport function keyEventToBinding(e: KeyboardEvent): string {\n const parts: string[] = [];\n\n // Use 'mod' for platform-independent modifier\n if (e.metaKey || e.ctrlKey) {\n parts.push(\"mod\");\n }\n if (e.altKey) {\n parts.push(\"alt\");\n }\n if (e.shiftKey) {\n parts.push(\"shift\");\n }\n\n // Get the key, normalizing special keys\n let key = e.key.toLowerCase();\n\n // Skip if only modifier keys\n if ([\"control\", \"meta\", \"alt\", \"shift\"].includes(key)) {\n return \"\";\n }\n\n // Normalize some key names\n if (key === \" \") key = \"space\";\n if (key === \",\") key = \"comma\";\n if (key === \"/\") key = \"slash\";\n if (key === \"=\") key = \"equal\";\n if (key === \"-\") key = \"minus\";\n if (key === \".\") key = \"period\";\n\n parts.push(key);\n\n return parts.join(\"+\");\n}\n\n/**\n * Convert a KeyboardEvent to a display string\n */\nexport function keyEventToDisplay(e: KeyboardEvent): string {\n const binding = keyEventToBinding(e);\n return bindingToDisplay(binding);\n}\n","import type { Node, Edge } from \"reactflow\";\nimport type {\n GeneratorNodeData,\n TransformNodeData,\n SaveNodeData,\n InputNodeData,\n VisionNodeData,\n TextNodeData,\n FanOutNodeData,\n CollectNodeData,\n RouterNodeData,\n} from \"@teamflojo/floimg-studio-shared\";\n\ntype NodeData =\n | GeneratorNodeData\n | TransformNodeData\n | SaveNodeData\n | InputNodeData\n | VisionNodeData\n | TextNodeData\n | FanOutNodeData\n | CollectNodeData\n | RouterNodeData;\n\n/**\n * Topologically sort nodes based on edges (dependencies)\n * Returns nodes in execution order\n */\nfunction topologicalSort(nodes: Node<NodeData>[], edges: Edge[]): Node<NodeData>[] {\n const nodeMap = new Map(nodes.map((n) => [n.id, n]));\n const inDegree = new Map<string, number>();\n const adjacency = new Map<string, string[]>();\n\n // Initialize\n for (const node of nodes) {\n inDegree.set(node.id, 0);\n adjacency.set(node.id, []);\n }\n\n // Build graph\n for (const edge of edges) {\n const targets = adjacency.get(edge.source) || [];\n targets.push(edge.target);\n adjacency.set(edge.source, targets);\n inDegree.set(edge.target, (inDegree.get(edge.target) || 0) + 1);\n }\n\n // Find nodes with no incoming edges (sources)\n const queue: string[] = [];\n for (const [id, degree] of inDegree) {\n if (degree === 0) {\n queue.push(id);\n }\n }\n\n // Process in order\n const sorted: Node<NodeData>[] = [];\n while (queue.length > 0) {\n const id = queue.shift()!;\n const node = nodeMap.get(id);\n if (node) {\n sorted.push(node);\n }\n\n const neighbors = adjacency.get(id) || [];\n for (const neighbor of neighbors) {\n const newDegree = (inDegree.get(neighbor) || 1) - 1;\n inDegree.set(neighbor, newDegree);\n if (newDegree === 0) {\n queue.push(neighbor);\n }\n }\n }\n\n return sorted;\n}\n\n/**\n * Get the variable name for a node\n */\nfunction getNodeVarName(node: Node<NodeData>): string {\n const type = node.type || \"node\";\n const suffix = node.id.replace(/[^a-zA-Z0-9]/g, \"_\");\n return `${type}_${suffix}`;\n}\n\n/**\n * Stringify a value for code generation\n */\nfunction stringify(value: unknown): string {\n if (typeof value === \"string\") {\n // Escape special characters and use template literal if multiline\n if (value.includes(\"\\n\")) {\n return \"`\" + value.replace(/`/g, \"\\\\`\").replace(/\\$/g, \"\\\\$\") + \"`\";\n }\n return JSON.stringify(value);\n }\n return JSON.stringify(value, null, 2);\n}\n\n/**\n * Generate JavaScript code for a single node\n */\nfunction generateNodeCode(\n node: Node<NodeData>,\n edges: Edge[],\n nodeVarNames: Map<string, string>\n): { code: string; imports: string[] } {\n const varName = nodeVarNames.get(node.id)!;\n const imports: string[] = [];\n\n // Find input node (source of edge pointing to this node)\n const inputEdge = edges.find((e) => e.target === node.id);\n const inputVarName = inputEdge ? nodeVarNames.get(inputEdge.source) : null;\n\n switch (node.type) {\n case \"generator\": {\n const data = node.data as GeneratorNodeData;\n imports.push(data.generatorName);\n\n const params = data.params || {};\n const paramStr = Object.entries(params)\n .filter(([, v]) => v !== undefined && v !== \"\")\n .map(([k, v]) => ` ${k}: ${stringify(v)}`)\n .join(\",\\n\");\n\n return {\n code: `// Generate image using ${data.generatorName}\nconst ${varName} = await ${data.generatorName}({\n${paramStr}\n});`,\n imports,\n };\n }\n\n case \"input\": {\n return {\n code: `// Load input image\nconst ${varName} = await flo.loadImage(\"./input.png\");`,\n imports: [],\n };\n }\n\n case \"transform\": {\n const data = node.data as TransformNodeData;\n const params = data.params || {};\n const paramStr = Object.entries(params)\n .filter(([, v]) => v !== undefined && v !== \"\")\n .map(([k, v]) => `${k}: ${stringify(v)}`)\n .join(\", \");\n\n const input = inputVarName || \"image\";\n return {\n code: `// Apply ${data.operation} transform\nconst ${varName} = await flo.transform(${input}, \"${data.operation}\"${paramStr ? `, { ${paramStr} }` : \"\"});`,\n imports: [],\n };\n }\n\n case \"vision\": {\n const data = node.data as VisionNodeData;\n imports.push(data.providerName);\n\n const params = data.params || {};\n const input = inputVarName || \"image\";\n const paramStr = Object.entries(params)\n .filter(([, v]) => v !== undefined && v !== \"\")\n .map(([k, v]) => ` ${k}: ${stringify(v)}`)\n .join(\",\\n\");\n\n return {\n code: `// Analyze image with ${data.providerName}\nconst ${varName} = await ${data.providerName}.analyze(${input}, {\n${paramStr}\n});`,\n imports,\n };\n }\n\n case \"text\": {\n const data = node.data as TextNodeData;\n imports.push(data.providerName);\n\n const params = data.params || {};\n const paramStr = Object.entries(params)\n .filter(([, v]) => v !== undefined && v !== \"\")\n .map(([k, v]) => ` ${k}: ${stringify(v)}`)\n .join(\",\\n\");\n\n return {\n code: `// Generate text with ${data.providerName}\nconst ${varName} = await ${data.providerName}.generate({\n${paramStr}\n});`,\n imports,\n };\n }\n\n case \"save\": {\n const data = node.data as SaveNodeData;\n const input = inputVarName || \"result\";\n return {\n code: `// Save result\nawait flo.save(${input}, ${stringify(data.destination)});`,\n imports: [],\n };\n }\n\n default:\n return {\n code: `// Unknown node type: ${node.type}`,\n imports: [],\n };\n }\n}\n\n/**\n * Generate JavaScript code from workflow nodes and edges\n */\nexport function generateJavaScript(nodes: Node<NodeData>[], edges: Edge[]): string {\n if (nodes.length === 0) {\n return `// Empty workflow\n// Add nodes to your canvas to generate code`;\n }\n\n // Sort nodes topologically\n const sortedNodes = topologicalSort(nodes, edges);\n\n // Generate variable names\n const nodeVarNames = new Map<string, string>();\n for (const node of sortedNodes) {\n nodeVarNames.set(node.id, getNodeVarName(node));\n }\n\n // Generate code for each node\n const allImports = new Set<string>();\n const codeBlocks: string[] = [];\n\n for (const node of sortedNodes) {\n const { code, imports } = generateNodeCode(node, edges, nodeVarNames);\n codeBlocks.push(code);\n for (const imp of imports) {\n allImports.add(imp);\n }\n }\n\n // Build final code\n const importLines: string[] = [];\n if (allImports.size > 0) {\n importLines.push(`import { ${Array.from(allImports).join(\", \")} } from \"@teamflojo/floimg\";`);\n }\n importLines.push(`import * as flo from \"@teamflojo/floimg\";`);\n\n const header = `/**\n * FloImg Workflow\n * Generated by FloImg Studio\n * https://floimg.com\n */\n\n`;\n\n const mainCode = `\nasync function runWorkflow() {\n${codeBlocks\n .map((block) =>\n block\n .split(\"\\n\")\n .map((line) => \" \" + line)\n .join(\"\\n\")\n )\n .join(\"\\n\\n\")}\n}\n\n// Run the workflow\nrunWorkflow().catch(console.error);\n`;\n\n return header + importLines.join(\"\\n\") + \"\\n\" + mainCode;\n}\n","import { useState, useCallback, type DragEvent } from \"react\";\nimport { importYaml, validateYaml } from \"../api/client\";\nimport type { StudioNode, StudioEdge } from \"@teamflojo/floimg-studio-shared\";\n\ninterface ImportModalProps {\n isOpen: boolean;\n onClose: () => void;\n onImport: (nodes: StudioNode[], edges: StudioEdge[], name?: string) => void;\n}\n\ninterface ValidationError {\n message: string;\n line?: number;\n column?: number;\n}\n\nexport function ImportModal({ isOpen, onClose, onImport }: ImportModalProps) {\n const [yamlContent, setYamlContent] = useState(\"\");\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<ValidationError | null>(null);\n const [isDragging, setIsDragging] = useState(false);\n\n const handleImport = useCallback(async () => {\n if (!yamlContent.trim()) {\n setError({ message: \"Please enter or paste YAML content\" });\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const result = await importYaml(yamlContent);\n\n if (result.success) {\n onImport(result.nodes, result.edges, result.name);\n setYamlContent(\"\");\n onClose();\n } else {\n setError({\n message: result.error || \"Import failed\",\n line: result.line,\n column: result.column,\n });\n }\n } catch (err) {\n setError({ message: err instanceof Error ? err.message : \"Import failed\" });\n } finally {\n setIsLoading(false);\n }\n }, [yamlContent, onImport, onClose]);\n\n const handleValidate = useCallback(async () => {\n if (!yamlContent.trim()) {\n setError({ message: \"Please enter or paste YAML content\" });\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const result = await validateYaml(yamlContent);\n\n if (result.valid) {\n setError(null);\n // Show success briefly\n setError({ message: \"Valid YAML!\" });\n setTimeout(() => setError(null), 2000);\n } else if (result.errors.length > 0) {\n setError(result.errors[0]);\n }\n } catch (err) {\n setError({ message: err instanceof Error ? err.message : \"Validation failed\" });\n } finally {\n setIsLoading(false);\n }\n }, [yamlContent]);\n\n const handleFileUpload = useCallback(async (file: File) => {\n if (!file.name.endsWith(\".yaml\") && !file.name.endsWith(\".yml\")) {\n setError({ message: \"Please upload a .yaml or .yml file\" });\n return;\n }\n\n try {\n const text = await file.text();\n setYamlContent(text);\n setError(null);\n } catch {\n setError({ message: \"Failed to read file\" });\n }\n }, []);\n\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault();\n setIsDragging(true);\n }, []);\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault();\n setIsDragging(false);\n }, []);\n\n const handleDrop = useCallback(\n (e: DragEvent) => {\n e.preventDefault();\n setIsDragging(false);\n\n const file = e.dataTransfer.files[0];\n if (file) {\n handleFileUpload(file);\n }\n },\n [handleFileUpload]\n );\n\n const handleFileInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (file) {\n handleFileUpload(file);\n }\n },\n [handleFileUpload]\n );\n\n if (!isOpen) return null;\n\n return (\n <div className=\"fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50\">\n <div className=\"bg-white dark:bg-zinc-800 rounded-lg shadow-xl max-w-2xl w-full mx-4 max-h-[80vh] flex flex-col\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-gray-200 dark:border-zinc-700\">\n <h3 className=\"text-lg font-semibold text-gray-900 dark:text-white\">Import Workflow</h3>\n <button\n onClick={onClose}\n className=\"text-gray-500 dark:text-zinc-400 hover:text-gray-700 dark:hover:text-zinc-200\"\n >\n <svg className=\"h-6 w-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n </div>\n\n {/* Content */}\n <div className=\"p-4 flex-1 overflow-auto\">\n <p className=\"text-sm text-gray-600 dark:text-zinc-400 mb-4\">\n Paste YAML content or drag and drop a .yaml file to import a workflow.\n </p>\n\n {/* File drop zone */}\n <div\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n className={`border-2 border-dashed rounded-lg p-4 mb-4 text-center transition-colors ${\n isDragging\n ? \"border-teal-500 bg-teal-50 dark:bg-teal-900/20\"\n : \"border-gray-300 dark:border-zinc-600\"\n }`}\n >\n <input\n type=\"file\"\n accept=\".yaml,.yml\"\n onChange={handleFileInputChange}\n className=\"hidden\"\n id=\"yaml-file-input\"\n />\n <label\n htmlFor=\"yaml-file-input\"\n className=\"cursor-pointer text-sm text-gray-600 dark:text-zinc-400\"\n >\n <svg\n className=\"h-8 w-8 mx-auto mb-2 text-gray-400 dark:text-zinc-500\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12\"\n />\n </svg>\n <span className=\"text-teal-600 dark:text-teal-400 hover:underline\">\n Click to upload\n </span>{\" \"}\n or drag and drop\n <br />\n <span className=\"text-xs\">.yaml or .yml files</span>\n </label>\n </div>\n\n {/* YAML textarea */}\n <textarea\n value={yamlContent}\n onChange={(e) => {\n setYamlContent(e.target.value);\n setError(null);\n }}\n placeholder={`name: My Workflow\nsteps:\n - kind: generate\n generator: quickchart\n params:\n type: bar\n data:\n labels: [Q1, Q2, Q3, Q4]\n datasets:\n - label: Revenue\n data: [12, 19, 8, 15]\n out: v0\n\n - kind: transform\n op: resize\n in: v0\n params:\n width: 800\n out: v1`}\n className=\"w-full h-64 p-3 font-mono text-sm bg-gray-100 dark:bg-zinc-900 border border-gray-300 dark:border-zinc-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-teal-500 text-gray-800 dark:text-zinc-200\"\n />\n\n {/* Error/Success message */}\n {error && (\n <div\n className={`mt-4 p-3 rounded-lg text-sm ${\n error.message === \"Valid YAML!\"\n ? \"bg-green-50 dark:bg-green-900/30 text-green-700 dark:text-green-400\"\n : \"bg-red-50 dark:bg-red-900/30 text-red-700 dark:text-red-400\"\n }`}\n >\n <span className=\"font-medium\">{error.message}</span>\n {error.line && (\n <span className=\"ml-2 text-xs\">\n (line {error.line}\n {error.column ? `, column ${error.column}` : \"\"})\n </span>\n )}\n </div>\n )}\n </div>\n\n {/* Footer */}\n <div className=\"flex justify-between items-center px-4 py-3 border-t border-gray-200 dark:border-zinc-700\">\n <span className=\"text-xs text-gray-500 dark:text-zinc-400\">\n Use with floimg CLI: floimg run workflow.yaml\n </span>\n <div className=\"flex gap-2\">\n <button\n onClick={handleValidate}\n disabled={isLoading || !yamlContent.trim()}\n className=\"px-4 py-2 text-sm font-medium text-gray-700 dark:text-zinc-200 bg-white dark:bg-zinc-700 border border-gray-300 dark:border-zinc-600 rounded-md hover:bg-gray-50 dark:hover:bg-zinc-600 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n Validate\n </button>\n <button\n onClick={handleImport}\n disabled={isLoading || !yamlContent.trim()}\n className=\"px-4 py-2 text-sm font-medium text-white bg-teal-600 rounded-md hover:bg-teal-700 disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2\"\n >\n {isLoading && (\n <svg className=\"animate-spin h-4 w-4\" viewBox=\"0 0 24 24\" fill=\"none\">\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\"\n />\n </svg>\n )}\n Import\n </button>\n </div>\n </div>\n </div>\n </div>\n );\n}\n","import { useState, useEffect, useCallback, type ReactNode } from \"react\";\nimport { useShortcutBinding } from \"../lib/keyboard/useKeyboardShortcuts\";\nimport { bindingToDisplay } from \"../lib/keyboard/platformUtils\";\nimport { useWorkflowStore } from \"../stores/workflowStore\";\nimport { useSettingsStore } from \"../stores/settingsStore\";\nimport { generateJavaScript } from \"../utils/codeGenerator\";\nimport { ImportModal } from \"./ImportModal\";\nimport type { StudioNode, StudioEdge } from \"@teamflojo/floimg-studio-shared\";\n\ntype ExportTab = \"yaml\" | \"javascript\";\n\n/**\n * Props for the Toolbar component.\n * All props are optional to maintain backward compatibility.\n */\nexport interface ToolbarProps {\n /** Slot rendered after the branding text (e.g., \"Cloud\" badge) */\n brandingSlot?: ReactNode;\n /** Slot rendered before the action buttons (e.g., usage counter) */\n beforeActionsSlot?: ReactNode;\n /** Slot rendered after all action buttons (e.g., auth/user menu) */\n afterActionsSlot?: ReactNode;\n /** Hide the \"by Flojo\" attribution link */\n hideAttribution?: boolean;\n /** Hide the \"My Workflows\" library toggle button (for wrappers providing custom workflow management) */\n hideWorkflowLibrary?: boolean;\n}\n\nexport function Toolbar({\n brandingSlot,\n beforeActionsSlot,\n afterActionsSlot,\n hideAttribution = false,\n hideWorkflowLibrary = false,\n}: ToolbarProps = {}) {\n const execution = useWorkflowStore((s) => s.execution);\n const execute = useWorkflowStore((s) => s.execute);\n const cancelExecution = useWorkflowStore((s) => s.cancelExecution);\n const exportToYaml = useWorkflowStore((s) => s.exportToYaml);\n const importFromYaml = useWorkflowStore((s) => s.importFromYaml);\n const nodes = useWorkflowStore((s) => s.nodes);\n const edges = useWorkflowStore((s) => s.edges);\n const openSettings = useSettingsStore((s) => s.openSettings);\n\n // Workflow persistence state\n const activeWorkflowName = useWorkflowStore((s) => s.activeWorkflowName);\n const hasUnsavedChanges = useWorkflowStore((s) => s.hasUnsavedChanges);\n const saveWorkflow = useWorkflowStore((s) => s.saveWorkflow);\n const toggleLibrary = useWorkflowStore((s) => s.toggleLibrary);\n const setActiveWorkflowName = useWorkflowStore((s) => s.setActiveWorkflowName);\n\n // Get shortcut bindings for tooltip hints\n const saveShortcut = useShortcutBinding(\"save\");\n\n const [showExport, setShowExport] = useState(false);\n const [showImport, setShowImport] = useState(false);\n const [exportTab, setExportTab] = useState<ExportTab>(\"yaml\");\n const [yamlContent, setYamlContent] = useState(\"\");\n const [jsContent, setJsContent] = useState(\"\");\n const [notification, setNotification] = useState<string | null>(null);\n const [isEditingName, setIsEditingName] = useState(false);\n const [editingName, setEditingName] = useState(\"\");\n\n // Listen for new workflow event\n useEffect(() => {\n const handleNewWorkflow = () => {\n setNotification(\"New workflow created\");\n setTimeout(() => setNotification(null), 2000);\n };\n window.addEventListener(\"new-workflow-created\", handleNewWorkflow);\n return () => window.removeEventListener(\"new-workflow-created\", handleNewWorkflow);\n }, []);\n\n // Handle save with Cmd+S / Ctrl+S\n const handleSave = useCallback(() => {\n if (nodes.length === 0) return;\n saveWorkflow();\n setNotification(\"Saved!\");\n setTimeout(() => setNotification(null), 2000);\n }, [nodes.length, saveWorkflow]);\n\n // Handle inline rename\n const handleStartRename = () => {\n setEditingName(activeWorkflowName);\n setIsEditingName(true);\n };\n\n const handleSaveRename = () => {\n const trimmed = editingName.trim();\n if (trimmed && trimmed !== activeWorkflowName) {\n setActiveWorkflowName(trimmed);\n }\n setIsEditingName(false);\n };\n\n const handleExecute = async () => {\n await execute();\n };\n\n const handleExport = async () => {\n const yaml = await exportToYaml();\n setYamlContent(yaml);\n const js = generateJavaScript(nodes, edges);\n setJsContent(js);\n setShowExport(true);\n };\n\n const handleCopy = () => {\n const content = exportTab === \"yaml\" ? yamlContent : jsContent;\n navigator.clipboard.writeText(content);\n };\n\n const handleImport = useCallback(\n (importedNodes: StudioNode[], importedEdges: StudioEdge[], name?: string) => {\n importFromYaml(importedNodes, importedEdges, name);\n setNotification(\"Workflow imported!\");\n setTimeout(() => setNotification(null), 2000);\n },\n [importFromYaml]\n );\n\n return (\n <>\n <div className=\"floimg-toolbar h-14 flex items-center justify-between px-4\">\n <div className=\"flex items-center gap-4\">\n {/* My Workflows button - can be hidden when custom workflow management is provided */}\n {!hideWorkflowLibrary && (\n <button onClick={toggleLibrary} className=\"floimg-toolbar__btn\" title=\"My Workflows\">\n <svg className=\"h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 6h16M4 12h16M4 18h7\"\n />\n </svg>\n </button>\n )}\n\n <div className=\"flex items-baseline gap-2\">\n <h1 className=\"floimg-toolbar__title\">FloImg Studio</h1>\n {brandingSlot}\n {!hideAttribution && (\n <a\n href=\"https://flojo.io\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-xs text-gray-400 dark:text-zinc-500 hover:text-gray-600 dark:hover:text-zinc-300\"\n >\n by Flojo\n </a>\n )}\n </div>\n\n {/* Workflow name and status - click to rename */}\n <div className=\"flex items-center gap-2\">\n {isEditingName ? (\n <input\n type=\"text\"\n value={editingName}\n onChange={(e) => setEditingName(e.target.value)}\n onBlur={handleSaveRename}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") handleSaveRename();\n if (e.key === \"Escape\") {\n setEditingName(activeWorkflowName);\n setIsEditingName(false);\n }\n }}\n className=\"w-48 px-2 py-1 text-sm font-medium bg-white dark:bg-zinc-900 border border-teal-500 rounded focus:outline-none focus:ring-1 focus:ring-teal-500 text-gray-900 dark:text-zinc-100\"\n autoFocus\n />\n ) : (\n <button\n onClick={handleStartRename}\n className=\"text-sm text-gray-700 dark:text-zinc-300 font-medium hover:text-gray-900 dark:hover:text-zinc-100 rounded px-2 py-1 -mx-2 hover:bg-gray-100 dark:hover:bg-zinc-700 transition-colors\"\n title=\"Click to rename\"\n >\n {activeWorkflowName}\n </button>\n )}\n {hasUnsavedChanges && (\n <span className=\"text-xs text-amber-600 dark:text-amber-400\">(unsaved)</span>\n )}\n {notification && (\n <span className=\"text-xs text-green-600 dark:text-green-400\">{notification}</span>\n )}\n </div>\n\n <span className=\"text-sm text-gray-500 dark:text-zinc-400\">\n {nodes.length} node{nodes.length !== 1 ? \"s\" : \"\"}\n </span>\n </div>\n\n <div className=\"flex items-center gap-3\">\n {beforeActionsSlot}\n <button onClick={openSettings} className=\"floimg-toolbar__btn\" title=\"AI Settings\">\n <svg className=\"h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z\"\n />\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z\"\n />\n </svg>\n </button>\n\n {/* Save button */}\n <button\n onClick={handleSave}\n disabled={nodes.length === 0}\n className=\"floimg-toolbar__btn disabled:opacity-50 disabled:cursor-not-allowed\"\n title={`Save Workflow${saveShortcut ? ` (${bindingToDisplay(saveShortcut)})` : \"\"}`}\n >\n <svg className=\"h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4\"\n />\n </svg>\n </button>\n\n <button onClick={() => setShowImport(true)} className=\"floimg-toolbar__btn-secondary\">\n Import\n </button>\n\n <button\n onClick={handleExport}\n disabled={nodes.length === 0}\n className=\"floimg-toolbar__btn-secondary disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n Export\n </button>\n\n {execution.status === \"running\" ? (\n <button\n onClick={cancelExecution}\n className=\"floimg-toolbar__btn-primary !bg-red-500 hover:!bg-red-600 flex items-center gap-2\"\n >\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n Cancel\n </button>\n ) : (\n <button\n onClick={handleExecute}\n disabled={nodes.length === 0}\n className=\"floimg-toolbar__btn-primary disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2\"\n >\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z\"\n />\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n Execute\n </button>\n )}\n {afterActionsSlot}\n </div>\n </div>\n\n {/* Execution result banner */}\n {execution.status === \"completed\" && execution.imageIds.length > 0 && (\n <div className=\"bg-green-50 dark:bg-green-900/30 border-b border-green-200 dark:border-green-800 px-4 py-3\">\n <div className=\"flex items-center gap-4\">\n <span className=\"text-green-700 dark:text-green-400 font-medium\">\n Generated {execution.imageIds.length} image\n {execution.imageIds.length !== 1 ? \"s\" : \"\"}\n </span>\n <div className=\"flex gap-2\">\n {execution.imageUrls.slice(0, 4).map((url, idx) => (\n <a key={idx} href={url} target=\"_blank\" rel=\"noopener noreferrer\" className=\"block\">\n <img\n src={url}\n alt=\"Generated\"\n className=\"h-12 w-12 object-cover rounded border border-green-300 dark:border-green-700\"\n />\n </a>\n ))}\n </div>\n </div>\n </div>\n )}\n\n {execution.status === \"error\" && (\n <div className=\"bg-red-50 dark:bg-red-900/30 border-b border-red-200 dark:border-red-800 px-4 py-3\">\n <span className=\"text-red-700 dark:text-red-400\">Error: {execution.error}</span>\n </div>\n )}\n\n {/* Export modal with tabs */}\n {showExport && (\n <div className=\"fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50\">\n <div className=\"bg-white dark:bg-zinc-800 rounded-lg shadow-xl max-w-2xl w-full mx-4 max-h-[80vh] flex flex-col\">\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-gray-200 dark:border-zinc-700\">\n <div className=\"flex items-center gap-4\">\n <h3 className=\"text-lg font-semibold text-gray-900 dark:text-white\">\n Export Workflow\n </h3>\n {/* Tabs */}\n <div className=\"flex gap-1 bg-gray-100 dark:bg-zinc-700 rounded-lg p-1\">\n <button\n onClick={() => setExportTab(\"yaml\")}\n className={`px-3 py-1 text-sm font-medium rounded-md transition-colors ${\n exportTab === \"yaml\"\n ? \"bg-white dark:bg-zinc-600 text-gray-900 dark:text-white shadow-sm\"\n : \"text-gray-600 dark:text-zinc-400 hover:text-gray-900 dark:hover:text-white\"\n }`}\n >\n YAML\n </button>\n <button\n onClick={() => setExportTab(\"javascript\")}\n className={`px-3 py-1 text-sm font-medium rounded-md transition-colors ${\n exportTab === \"javascript\"\n ? \"bg-white dark:bg-zinc-600 text-gray-900 dark:text-white shadow-sm\"\n : \"text-gray-600 dark:text-zinc-400 hover:text-gray-900 dark:hover:text-white\"\n }`}\n >\n JavaScript\n </button>\n </div>\n </div>\n <button\n onClick={() => setShowExport(false)}\n className=\"text-gray-500 dark:text-zinc-400 hover:text-gray-700 dark:hover:text-zinc-200\"\n >\n <svg className=\"h-6 w-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n </div>\n <div className=\"p-4 overflow-auto flex-1\">\n <pre className=\"bg-gray-100 dark:bg-zinc-900 p-4 rounded text-sm font-mono whitespace-pre-wrap text-gray-800 dark:text-zinc-200\">\n {exportTab === \"yaml\" ? yamlContent : jsContent}\n </pre>\n </div>\n <div className=\"flex justify-between items-center px-4 py-3 border-t border-gray-200 dark:border-zinc-700\">\n <span className=\"text-xs text-gray-500 dark:text-zinc-400\">\n {exportTab === \"yaml\"\n ? \"Use with floimg CLI: floimg run workflow.yaml\"\n : \"Run with Node.js or Bun\"}\n </span>\n <div className=\"flex gap-2\">\n <button\n onClick={handleCopy}\n className=\"px-4 py-2 text-sm font-medium text-gray-700 dark:text-zinc-200 bg-white dark:bg-zinc-700 border border-gray-300 dark:border-zinc-600 rounded-md hover:bg-gray-50 dark:hover:bg-zinc-600\"\n >\n Copy to Clipboard\n </button>\n <button\n onClick={() => setShowExport(false)}\n className=\"px-4 py-2 text-sm font-medium text-white bg-teal-600 rounded-md hover:bg-teal-700\"\n >\n Close\n </button>\n </div>\n </div>\n </div>\n </div>\n )}\n\n {/* Import modal */}\n <ImportModal\n isOpen={showImport}\n onClose={() => setShowImport(false)}\n onImport={handleImport}\n />\n </>\n );\n}\n","import { useState } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { listImages, getImageUrl, getImageWorkflow, type ImageInfo } from \"../api/client\";\nimport { useWorkflowStore } from \"../stores/workflowStore\";\nimport type { Template } from \"@teamflojo/floimg-templates\";\n\nexport function Gallery() {\n const loadTemplate = useWorkflowStore((s) => s.loadTemplate);\n const [loadingWorkflow, setLoadingWorkflow] = useState<string | null>(null);\n\n const {\n data: images,\n isLoading,\n error,\n refetch,\n } = useQuery({\n queryKey: [\"images\"],\n queryFn: listImages,\n refetchInterval: 5000, // Auto-refresh every 5 seconds\n });\n\n const handleLoadWorkflow = async (imageId: string) => {\n setLoadingWorkflow(imageId);\n try {\n const metadata = await getImageWorkflow(imageId);\n if (metadata?.workflow) {\n // Convert to Template format for loading\n const template: Template = {\n id: `image-${imageId}`,\n name: `Workflow from ${imageId}`,\n description: \"Loaded from gallery image\",\n category: \"Utilities\",\n generator: \"unknown\",\n workflow: {\n nodes: metadata.workflow.nodes,\n edges: metadata.workflow.edges,\n },\n };\n loadTemplate(template);\n // Navigate to editor tab (parent handles this via URL or state)\n window.dispatchEvent(new CustomEvent(\"workflow-loaded\"));\n } else {\n alert(\"No workflow metadata available for this image\");\n }\n } catch (err) {\n console.error(\"Failed to load workflow:\", err);\n alert(\"Failed to load workflow\");\n } finally {\n setLoadingWorkflow(null);\n }\n };\n\n if (isLoading) {\n return (\n <div className=\"p-8 text-center text-gray-500 dark:text-zinc-400\">Loading images...</div>\n );\n }\n\n if (error) {\n return (\n <div className=\"p-8 text-center text-red-500 dark:text-red-400\">\n Error loading images: {error instanceof Error ? error.message : \"Unknown error\"}\n </div>\n );\n }\n\n if (!images || images.length === 0) {\n return (\n <div className=\"p-8 text-center text-gray-500 dark:text-zinc-400\">\n <div className=\"text-lg mb-2\">No images yet</div>\n <div className=\"text-sm\">Create a workflow and click Execute to generate images</div>\n </div>\n );\n }\n\n return (\n <div className=\"p-4 bg-gray-100 dark:bg-zinc-900 min-h-full\">\n <div className=\"flex items-center justify-between mb-4\">\n <div>\n <h2 className=\"text-lg font-semibold text-gray-800 dark:text-white\">\n Images ({images.length})\n </h2>\n <p className=\"text-xs text-gray-500 dark:text-zinc-500\">Your generated images</p>\n </div>\n <button\n onClick={() => refetch()}\n className=\"text-sm text-teal-600 dark:text-teal-400 hover:text-teal-700 dark:hover:text-violet-300\"\n >\n Refresh\n </button>\n </div>\n\n <div className=\"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4\">\n {images.map((image) => (\n <ImageCard\n key={image.id}\n image={image}\n onLoadWorkflow={() => handleLoadWorkflow(image.id)}\n isLoading={loadingWorkflow === image.id}\n />\n ))}\n </div>\n </div>\n );\n}\n\ninterface ImageCardProps {\n image: ImageInfo;\n onLoadWorkflow: () => void;\n isLoading: boolean;\n}\n\nfunction ImageCard({ image, onLoadWorkflow, isLoading }: ImageCardProps) {\n const formatDate = (timestamp: number) => {\n return new Date(timestamp).toLocaleString();\n };\n\n const formatSize = (bytes: number) => {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n };\n\n return (\n <div className=\"bg-white dark:bg-zinc-800 rounded-lg border border-gray-200 dark:border-zinc-700 overflow-hidden shadow-sm hover:shadow-md transition-shadow group\">\n <div className=\"relative\">\n <a\n href={getImageUrl(image.id)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"block aspect-square bg-gray-100 dark:bg-zinc-900\"\n >\n <img\n src={getImageUrl(image.id)}\n alt={image.filename}\n className=\"w-full h-full object-cover\"\n loading=\"lazy\"\n />\n </a>\n {/* Hover overlay with action buttons */}\n <div className=\"absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center gap-2\">\n <button\n onClick={(e) => {\n e.preventDefault();\n onLoadWorkflow();\n }}\n disabled={isLoading}\n className=\"px-3 py-1.5 bg-teal-600 text-white text-sm rounded-lg hover:bg-teal-700 disabled:opacity-50\"\n >\n {isLoading ? \"Loading...\" : \"Load Workflow\"}\n </button>\n <a\n href={getImageUrl(image.id)}\n download={image.filename}\n onClick={(e) => e.stopPropagation()}\n className=\"p-1.5 bg-zinc-700 text-white rounded-lg hover:bg-zinc-600\"\n title=\"Download image\"\n >\n <svg className=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\"\n />\n </svg>\n </a>\n </div>\n </div>\n <div className=\"p-3\">\n <div className=\"text-sm font-medium text-gray-800 dark:text-white truncate\">\n {image.filename}\n </div>\n <div className=\"text-xs text-gray-500 dark:text-zinc-400 mt-1\">\n {image.mime} • {formatSize(image.size)}\n </div>\n <div className=\"text-xs text-gray-400 dark:text-zinc-500 mt-1\">\n {formatDate(image.createdAt)}\n </div>\n </div>\n </div>\n );\n}\n","/**\n * Data Visualization Templates\n *\n * Charts, graphs, and diagrams using QuickChart and Mermaid generators.\n * All templates in this category work offline (OSS-compatible).\n */\n/**\n * Revenue Dashboard Pipeline\n * Canonical ID: revenue-chart\n *\n * Multi-step workflow: Generate chart → Resize → Add caption → WebP export\n * Demonstrates: chart generation with professional output formatting\n */\nexport const revenueChart = {\n id: \"revenue-chart\",\n name: \"Revenue Dashboard\",\n description: \"Quarterly revenue chart with caption and web-optimized export\",\n category: \"Data Viz\",\n generator: \"quickchart\",\n tags: [\"bar\", \"revenue\", \"quarterly\", \"dashboard\", \"sales\", \"pipeline\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"chart\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/revenue-chart.png\",\n },\n codeExample: `const chart = await floimg\n .generate('quickchart', {\n chart: {\n type: 'bar',\n data: {\n labels: ['Q1', 'Q2', 'Q3', 'Q4'],\n datasets: [{ label: 'Revenue ($K)', data: [120, 190, 175, 240] }]\n }\n }\n })\n .transform('resize', { width: 800, height: 500, fit: 'inside' })\n .transform('addCaption', {\n text: 'Source: Finance Dashboard',\n position: 'bottom-right',\n fontSize: 12\n })\n .transform('convert', { to: 'image/webp', quality: 90 })\n .toBlob();`,\n seo: {\n title: \"Revenue Dashboard Chart Template\",\n description: \"Generate professional quarterly revenue bar charts with caption and optimization\",\n keywords: [\"revenue chart\", \"bar chart\", \"quarterly report\", \"dashboard\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"quickchart\",\n params: {\n chart: {\n type: \"bar\",\n data: {\n labels: [\"Q1\", \"Q2\", \"Q3\", \"Q4\"],\n datasets: [\n {\n label: \"Revenue ($K)\",\n data: [120, 190, 175, 240],\n backgroundColor: [\n \"rgba(99, 102, 241, 0.8)\",\n \"rgba(139, 92, 246, 0.8)\",\n \"rgba(168, 85, 247, 0.8)\",\n \"rgba(192, 132, 252, 0.8)\",\n ],\n },\n ],\n },\n options: {\n plugins: {\n title: {\n display: true,\n text: \"Quarterly Revenue 2024\",\n },\n },\n },\n },\n width: 600,\n height: 400,\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 800,\n height: 500,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-caption\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"addCaption\",\n params: {\n text: \"Source: Finance Dashboard\",\n position: \"bottom-right\",\n fontSize: 12,\n color: \"#6B7280\",\n padding: 8,\n },\n },\n },\n {\n id: \"transform-webp\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/webp\",\n quality: 90,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-caption\" },\n { id: \"e3\", source: \"transform-caption\", target: \"transform-webp\" },\n ],\n },\n};\n/**\n * User Growth Chart for Investor Updates\n * Canonical ID: monthly-users\n *\n * Multi-step workflow: Generate chart → Resize for slides → Round corners for modern look → PNG export\n * JTBD: Create polished growth charts for investor decks and board presentations\n */\nexport const monthlyUsers = {\n id: \"monthly-users\",\n name: \"User Growth Chart\",\n description: \"Polished user growth chart ready for investor decks and presentations\",\n category: \"Data Viz\",\n generator: \"quickchart\",\n tags: [\"line\", \"growth\", \"users\", \"monthly\", \"analytics\", \"pipeline\", \"investor\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"chart\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/monthly-users.png\",\n },\n codeExample: `const chart = await floimg\n .generate('quickchart', {\n chart: {\n type: 'line',\n data: {\n labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],\n datasets: [{ label: 'Active Users', data: [1200, 1900, 3000, 5000, 6200, 8100] }]\n }\n }\n })\n .transform('resize', { width: 1200, height: 675 }) // 16:9 for slides\n .transform('roundCorners', { radius: 16 })\n .transform('convert', { to: 'image/png' })\n .toBlob();`,\n seo: {\n title: \"User Growth Chart Template\",\n description: \"Visualize monthly user growth with smooth bezier curves for investor presentations\",\n keywords: [\"user growth\", \"line chart\", \"analytics\", \"investor deck\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"quickchart\",\n params: {\n chart: {\n type: \"line\",\n data: {\n labels: [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\"],\n datasets: [\n {\n label: \"Active Users\",\n data: [1200, 1900, 3000, 5000, 6200, 8100],\n borderColor: \"rgb(99, 102, 241)\",\n backgroundColor: \"rgba(99, 102, 241, 0.1)\",\n fill: true,\n tension: 0.4,\n },\n ],\n },\n options: {\n plugins: {\n title: {\n display: true,\n text: \"User Growth 2024\",\n },\n },\n },\n },\n width: 600,\n height: 400,\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 1200,\n height: 675,\n fit: \"contain\",\n background: \"#ffffff\",\n },\n },\n },\n {\n id: \"transform-corners\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"roundCorners\",\n params: {\n radius: 16,\n },\n },\n },\n {\n id: \"transform-png\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/png\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-corners\" },\n { id: \"e3\", source: \"transform-corners\", target: \"transform-png\" },\n ],\n },\n};\n/**\n * Framework Comparison for Blog Posts\n * Canonical ID: framework-usage\n *\n * Multi-step workflow: Generate chart → Resize for blog → Add padding → WebP for fast loading\n * JTBD: Create comparison charts for technical blog posts and documentation\n */\nexport const frameworkUsage = {\n id: \"framework-usage\",\n name: \"Framework Usage Stats\",\n description: \"Blog-ready comparison chart with optimized sizing and fast web loading\",\n category: \"Data Viz\",\n generator: \"quickchart\",\n tags: [\"bar\", \"comparison\", \"stats\", \"horizontal\", \"frameworks\", \"pipeline\", \"blog\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"chart\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/framework-usage.png\",\n },\n codeExample: `const chart = await floimg\n .generate('quickchart', {\n chart: {\n type: 'horizontalBar',\n data: {\n labels: ['React', 'Vue', 'Angular', 'Svelte', 'Solid'],\n datasets: [{ label: 'Usage %', data: [42, 18, 15, 8, 4] }]\n }\n }\n })\n .transform('resize', { width: 800, height: 450 }) // Blog content width\n .transform('extend', { top: 16, bottom: 16, left: 16, right: 16, background: '#ffffff' })\n .transform('convert', { to: 'image/webp', quality: 85 })\n .toBlob();`,\n seo: {\n title: \"Framework Comparison Chart Template\",\n description: \"Generate comparison charts for technical blog posts with optimized web delivery\",\n keywords: [\"framework comparison\", \"bar chart\", \"tech blog\", \"documentation\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"quickchart\",\n params: {\n chart: {\n type: \"horizontalBar\",\n data: {\n labels: [\"React\", \"Vue\", \"Angular\", \"Svelte\", \"Solid\"],\n datasets: [\n {\n label: \"Usage %\",\n data: [42, 18, 15, 8, 4],\n backgroundColor: [\n \"rgba(97, 218, 251, 0.8)\",\n \"rgba(65, 184, 131, 0.8)\",\n \"rgba(221, 0, 49, 0.8)\",\n \"rgba(255, 62, 0, 0.8)\",\n \"rgba(68, 107, 158, 0.8)\",\n ],\n },\n ],\n },\n options: {\n plugins: {\n title: {\n display: true,\n text: \"Frontend Framework Usage 2024\",\n },\n },\n },\n },\n width: 600,\n height: 400,\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 800,\n height: 450,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-padding\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"extend\",\n params: {\n top: 16,\n bottom: 16,\n left: 16,\n right: 16,\n background: \"#ffffff\",\n },\n },\n },\n {\n id: \"transform-webp\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/webp\",\n quality: 85,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-padding\" },\n { id: \"e3\", source: \"transform-padding\", target: \"transform-webp\" },\n ],\n },\n};\n/**\n * Traffic Breakdown for Slack/Reports\n * Canonical ID: traffic-breakdown\n *\n * Multi-step workflow: Generate chart → Square format for Slack → Add date annotation → PNG\n * JTBD: Share analytics breakdowns in Slack channels and weekly reports\n */\nexport const trafficBreakdown = {\n id: \"traffic-breakdown\",\n name: \"Traffic by Device\",\n description: \"Analytics breakdown optimized for Slack sharing and weekly reports\",\n category: \"Data Viz\",\n generator: \"quickchart\",\n tags: [\"doughnut\", \"traffic\", \"analytics\", \"pie\", \"devices\", \"pipeline\", \"slack\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"chart\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/traffic-breakdown.png\",\n },\n codeExample: `const chart = await floimg\n .generate('quickchart', {\n chart: {\n type: 'doughnut',\n data: {\n labels: ['Desktop', 'Mobile', 'Tablet'],\n datasets: [{ data: [55, 35, 10] }]\n }\n }\n })\n .transform('resize', { width: 500, height: 500 }) // Square for Slack preview\n .transform('addCaption', {\n text: 'Week of Jan 1, 2026',\n position: 'bottom-center',\n fontSize: 14,\n color: '#6B7280'\n })\n .transform('convert', { to: 'image/png' })\n .toBlob();`,\n seo: {\n title: \"Traffic Breakdown Chart Template\",\n description: \"Generate analytics breakdown charts optimized for Slack sharing and reports\",\n keywords: [\"traffic analytics\", \"doughnut chart\", \"slack\", \"weekly report\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"quickchart\",\n params: {\n chart: {\n type: \"doughnut\",\n data: {\n labels: [\"Desktop\", \"Mobile\", \"Tablet\"],\n datasets: [\n {\n data: [55, 35, 10],\n backgroundColor: [\n \"rgba(99, 102, 241, 0.8)\",\n \"rgba(34, 197, 94, 0.8)\",\n \"rgba(249, 115, 22, 0.8)\",\n ],\n },\n ],\n },\n options: {\n plugins: {\n title: {\n display: true,\n text: \"Traffic by Device Type\",\n },\n },\n },\n },\n width: 400,\n height: 400,\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 500,\n height: 500,\n fit: \"contain\",\n background: \"#ffffff\",\n },\n },\n },\n {\n id: \"transform-caption\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"addCaption\",\n params: {\n text: \"Week of Jan 1, 2026\",\n position: \"bottom-center\",\n fontSize: 14,\n color: \"#6B7280\",\n padding: 12,\n },\n },\n },\n {\n id: \"transform-png\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/png\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-caption\" },\n { id: \"e3\", source: \"transform-caption\", target: \"transform-png\" },\n ],\n },\n};\n/**\n * API Documentation Sequence Diagram\n * Canonical ID: api-flow\n *\n * Multi-step workflow: Generate diagram → Resize for docs → Add padding → PNG for docs\n * JTBD: Create API flow diagrams for technical documentation and README files\n */\nexport const apiFlow = {\n id: \"api-flow\",\n name: \"API Request Flow\",\n description: \"Sequence diagram ready for API documentation and README files\",\n category: \"Data Viz\",\n generator: \"mermaid\",\n tags: [\"sequence\", \"api\", \"authentication\", \"diagram\", \"flow\", \"pipeline\", \"docs\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"diagram\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/api-flow.png\",\n },\n codeExample: `const diagram = await floimg\n .generate('mermaid', {\n code: \\`sequenceDiagram\n participant Client\n participant API\n participant Auth\n Client->>API: POST /login\n API->>Auth: Validate\n Auth-->>API: JWT token\n API-->>Client: 200 OK\\`\n })\n .transform('resize', { width: 800, fit: 'inside' })\n .transform('extend', { top: 24, bottom: 24, left: 24, right: 24, background: '#ffffff' })\n .transform('convert', { to: 'image/png' })\n .toBlob();`,\n seo: {\n title: \"API Flow Diagram Template\",\n description: \"Generate sequence diagrams for API documentation and README files\",\n keywords: [\"api diagram\", \"sequence diagram\", \"documentation\", \"readme\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"mermaid\",\n params: {\n code: `sequenceDiagram\n participant Client\n participant API\n participant Auth\n participant DB\n\n Client->>API: POST /login\n API->>Auth: Validate credentials\n Auth->>DB: Query user\n DB-->>Auth: User data\n Auth-->>API: JWT token\n API-->>Client: 200 OK + token\n\n Client->>API: GET /data (+ JWT)\n API->>Auth: Verify token\n Auth-->>API: Valid\n API->>DB: Fetch data\n DB-->>API: Data\n API-->>Client: 200 OK + data`,\n theme: \"default\",\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 800,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-padding\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"extend\",\n params: {\n top: 24,\n bottom: 24,\n left: 24,\n right: 24,\n background: \"#ffffff\",\n },\n },\n },\n {\n id: \"transform-png\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/png\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-padding\" },\n { id: \"e3\", source: \"transform-padding\", target: \"transform-png\" },\n ],\n },\n};\n/**\n * System Architecture for Technical Docs\n * Canonical ID: system-architecture\n *\n * Multi-step workflow: Generate diagram → Resize for wiki → Add padding → WebP for fast loading\n * JTBD: Create architecture diagrams for Confluence/Notion/README documentation\n */\nexport const systemArchitecture = {\n id: \"system-architecture\",\n name: \"System Architecture\",\n description: \"Architecture diagram optimized for Confluence, Notion, and technical documentation\",\n category: \"Data Viz\",\n generator: \"mermaid\",\n tags: [\n \"architecture\",\n \"microservices\",\n \"flowchart\",\n \"system\",\n \"infrastructure\",\n \"pipeline\",\n \"confluence\",\n ],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"diagram\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/system-architecture.png\",\n },\n codeExample: `const diagram = await floimg\n .generate('mermaid', {\n code: \\`flowchart TB\n subgraph Gateway\n LB[Load Balancer]\n API[API Gateway]\n end\n subgraph Services\n Auth[Auth]\n Users[Users]\n end\n LB --> API --> Auth & Users\\`\n })\n .transform('resize', { width: 1000, fit: 'inside' })\n .transform('extend', { top: 32, bottom: 32, left: 32, right: 32, background: '#ffffff' })\n .transform('convert', { to: 'image/webp', quality: 90 })\n .toBlob();`,\n seo: {\n title: \"System Architecture Diagram Template\",\n description: \"Generate architecture diagrams for Confluence, Notion, and technical documentation\",\n keywords: [\"architecture diagram\", \"microservices\", \"confluence\", \"notion\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"mermaid\",\n params: {\n code: `flowchart TB\n subgraph Client\n Web[Web App]\n Mobile[Mobile App]\n end\n\n subgraph Gateway\n LB[Load Balancer]\n API[API Gateway]\n end\n\n subgraph Services\n Auth[Auth Service]\n Users[User Service]\n Orders[Order Service]\n Notify[Notification Service]\n end\n\n subgraph Data\n PG[(PostgreSQL)]\n Redis[(Redis Cache)]\n S3[(S3 Storage)]\n end\n\n Web --> LB\n Mobile --> LB\n LB --> API\n API --> Auth\n API --> Users\n API --> Orders\n API --> Notify\n Auth --> Redis\n Users --> PG\n Orders --> PG\n Notify --> Redis`,\n theme: \"default\",\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 1000,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-padding\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"extend\",\n params: {\n top: 32,\n bottom: 32,\n left: 32,\n right: 32,\n background: \"#ffffff\",\n },\n },\n },\n {\n id: \"transform-webp\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/webp\",\n quality: 90,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-padding\" },\n { id: \"e3\", source: \"transform-padding\", target: \"transform-webp\" },\n ],\n },\n};\n/**\n * Git Workflow for Team Onboarding\n * Canonical ID: git-workflow\n *\n * Multi-step workflow: Generate diagram → Resize for wiki → Add caption → PNG for docs\n * JTBD: Create git workflow diagrams for team onboarding and CONTRIBUTING.md files\n */\nexport const gitWorkflow = {\n id: \"git-workflow\",\n name: \"Git Branch Workflow\",\n description: \"Git branching diagram for team onboarding and CONTRIBUTING.md\",\n category: \"Data Viz\",\n generator: \"mermaid\",\n tags: [\n \"git\",\n \"branching\",\n \"workflow\",\n \"development\",\n \"version-control\",\n \"pipeline\",\n \"onboarding\",\n ],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"diagram\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/git-workflow.png\",\n },\n codeExample: `const diagram = await floimg\n .generate('mermaid', {\n code: \\`gitGraph\n commit id: \"Initial\"\n branch develop\n commit id: \"Setup\"\n branch feature/auth\n commit id: \"Add login\"\n checkout develop\n merge feature/auth tag: \"v1.0.0\"\\`\n })\n .transform('resize', { width: 900, fit: 'inside' })\n .transform('addCaption', {\n text: 'Our Git Branching Strategy',\n position: 'top-center',\n fontSize: 16\n })\n .transform('convert', { to: 'image/png' })\n .toBlob();`,\n seo: {\n title: \"Git Workflow Diagram Template\",\n description: \"Generate git branching diagrams for team onboarding and CONTRIBUTING.md\",\n keywords: [\"git workflow\", \"branching strategy\", \"team onboarding\", \"contributing\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"mermaid\",\n params: {\n code: `gitGraph\n commit id: \"Initial\"\n branch develop\n checkout develop\n commit id: \"Setup\"\n branch feature/auth\n checkout feature/auth\n commit id: \"Add login\"\n commit id: \"Add signup\"\n checkout develop\n merge feature/auth\n branch feature/dashboard\n checkout feature/dashboard\n commit id: \"Add charts\"\n checkout develop\n merge feature/dashboard\n checkout main\n merge develop tag: \"v1.0.0\"\n checkout develop\n commit id: \"Post-release\"`,\n theme: \"default\",\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 900,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-caption\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"addCaption\",\n params: {\n text: \"Our Git Branching Strategy\",\n position: \"top-center\",\n fontSize: 16,\n color: \"#374151\",\n padding: 16,\n },\n },\n },\n {\n id: \"transform-png\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/png\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-caption\" },\n { id: \"e3\", source: \"transform-caption\", target: \"transform-png\" },\n ],\n },\n};\n/**\n * All data visualization templates\n */\nexport const dataVizTemplates = [\n revenueChart,\n monthlyUsers,\n frameworkUsage,\n trafficBreakdown,\n apiFlow,\n systemArchitecture,\n gitWorkflow,\n];\n//# sourceMappingURL=data-viz.js.map","/**\n * AI Workflow Templates\n *\n * Templates that use AI image generation (OpenAI DALL-E, etc.)\n * These require API keys (cloud deployment) to execute.\n */\n/**\n * AI Product Photography for E-commerce\n * Canonical ID: ai-product-shot\n *\n * Multi-step workflow: AI generate → Remove background → Resize for listing → Add watermark\n * JTBD: Create e-commerce-ready product photos with transparent backgrounds and consistent sizing\n */\nexport const aiProductShot = {\n id: \"ai-product-shot\",\n name: \"AI Product Photography\",\n description: \"Generate AI product photos with background removal and e-commerce-ready sizing\",\n category: \"AI Workflows\",\n generator: \"openai\",\n tags: [\"product\", \"ecommerce\", \"photography\", \"dall-e\", \"ai\", \"pipeline\", \"background-removal\"],\n requiresCloud: true,\n requiresAuth: true,\n usesAI: true,\n aiCreditsNeeded: 1,\n capabilities: {\n pipeline: true,\n },\n icon: \"sparkles\",\n valueProp: \"E-commerce-ready product photos in seconds\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/ai-product-shot.png\",\n },\n codeExample: `const product = await floimg\n .generate('openai', {\n prompt: 'Professional product photo of headphones on white background',\n model: 'dall-e-3',\n size: '1024x1024'\n })\n .transform('removeBackground')\n .transform('resize', { width: 800, height: 800, fit: 'contain', background: '#ffffff' })\n .transform('addCaption', { text: 'SKU-12345', position: 'bottom-right', fontSize: 12 })\n .toBlob();`,\n seo: {\n title: \"AI Product Photography Template\",\n description: \"Generate e-commerce-ready product photos with AI and background removal\",\n keywords: [\"product photography\", \"ai generation\", \"ecommerce\", \"background removal\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-ai\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"openai\",\n params: {\n prompt: \"Professional product photo of modern wireless headphones on a clean white background, studio lighting, high-end commercial photography style\",\n model: \"dall-e-3\",\n size: \"1024x1024\",\n quality: \"hd\",\n },\n },\n },\n {\n id: \"transform-bg\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"removeBackground\",\n params: {},\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 800,\n height: 800,\n fit: \"contain\",\n background: \"#ffffff\",\n },\n },\n },\n {\n id: \"transform-caption\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"addCaption\",\n params: {\n text: \"SKU-12345\",\n position: \"bottom-right\",\n fontSize: 12,\n color: \"#9CA3AF\",\n padding: 8,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-ai\", target: \"transform-bg\" },\n { id: \"e2\", source: \"transform-bg\", target: \"transform-resize\" },\n { id: \"e3\", source: \"transform-resize\", target: \"transform-caption\" },\n ],\n },\n};\n/**\n * AI Hero Image for Landing Pages\n * Canonical ID: ai-hero-image\n *\n * Multi-step workflow: AI generate → Resize to OG dimensions → Round corners → WebP for fast loading\n * JTBD: Create landing page hero images optimized for web performance and social sharing\n */\nexport const aiHeroImage = {\n id: \"ai-hero-image\",\n name: \"AI Hero Image\",\n description: \"Generate landing page hero images optimized for web and social sharing\",\n category: \"AI Workflows\",\n generator: \"openai\",\n tags: [\"hero\", \"landing-page\", \"marketing\", \"dall-e\", \"ai\", \"pipeline\", \"og-image\"],\n requiresCloud: true,\n requiresAuth: true,\n usesAI: true,\n aiCreditsNeeded: 1,\n capabilities: {\n pipeline: true,\n },\n icon: \"sparkles\",\n valueProp: \"Landing page hero images in seconds\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/ai-hero-image.png\",\n },\n codeExample: `const hero = await floimg\n .generate('openai', {\n prompt: 'Futuristic city skyline at sunset, cinematic lighting',\n model: 'dall-e-3',\n size: '1792x1024'\n })\n .transform('resize', { width: 1200, height: 630 }) // OG image dimensions\n .transform('roundCorners', { radius: 8 })\n .transform('convert', { to: 'image/webp', quality: 85 })\n .toBlob();`,\n seo: {\n title: \"AI Hero Image Generator\",\n description: \"Generate landing page hero images optimized for web and social sharing\",\n keywords: [\"hero image\", \"landing page\", \"og image\", \"social sharing\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-ai\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"openai\",\n params: {\n prompt: \"Futuristic city skyline at golden hour sunset, cinematic wide angle, volumetric lighting, sci-fi architecture, dramatic clouds, professional photography\",\n model: \"dall-e-3\",\n size: \"1792x1024\",\n quality: \"hd\",\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 1200,\n height: 630,\n fit: \"cover\",\n },\n },\n },\n {\n id: \"transform-corners\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"roundCorners\",\n params: {\n radius: 8,\n },\n },\n },\n {\n id: \"transform-webp\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/webp\",\n quality: 85,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-ai\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-corners\" },\n { id: \"e3\", source: \"transform-corners\", target: \"transform-webp\" },\n ],\n },\n};\n/**\n * AI Mascot with Brand Kit Export\n * Canonical ID: ai-mascot\n *\n * Multi-step workflow: AI generate → Remove background → Export multiple sizes for different uses\n * JTBD: Create mascot assets ready for favicon, social avatars, and website use\n */\nexport const aiMascot = {\n id: \"ai-mascot\",\n name: \"AI Mascot Generator\",\n description: \"Generate mascot with transparent background and multiple export sizes\",\n category: \"AI Workflows\",\n generator: \"openai\",\n tags: [\"mascot\", \"character\", \"branding\", \"dall-e\", \"ai\", \"pipeline\", \"favicon\", \"avatar\"],\n requiresCloud: true,\n requiresAuth: true,\n usesAI: true,\n aiCreditsNeeded: 1,\n capabilities: {\n pipeline: true,\n },\n icon: \"sparkles\",\n valueProp: \"Brand-ready mascot assets in seconds\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/ai-mascot.png\",\n },\n codeExample: `const mascot = await floimg\n .generate('openai', {\n prompt: 'Friendly robot mascot, modern flat design, teal colors, white background',\n model: 'dall-e-3',\n size: '1024x1024'\n })\n .transform('removeBackground')\n .transform('resize', { width: 512, height: 512, fit: 'contain' })\n .transform('convert', { to: 'image/png' })\n .toBlob();`,\n seo: {\n title: \"AI Mascot Generator\",\n description: \"Create brand mascots with transparent backgrounds ready for any use\",\n keywords: [\"mascot design\", \"character design\", \"branding\", \"favicon\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-ai\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"openai\",\n params: {\n prompt: \"Friendly robot mascot character, modern flat design style, vibrant teal and purple colors, simple geometric shapes, suitable for tech company branding, white background\",\n model: \"dall-e-3\",\n size: \"1024x1024\",\n quality: \"hd\",\n },\n },\n },\n {\n id: \"transform-bg\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"removeBackground\",\n params: {},\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 512,\n height: 512,\n fit: \"contain\",\n },\n },\n },\n {\n id: \"transform-png\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/png\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-ai\", target: \"transform-bg\" },\n { id: \"e2\", source: \"transform-bg\", target: \"transform-resize\" },\n { id: \"e3\", source: \"transform-resize\", target: \"transform-png\" },\n ],\n },\n};\n/**\n * AI Logo to Brand Kit (Cloud Onboarding)\n * Canonical ID: cloud-ai-logo-brand\n */\nexport const aiLogoBrandKit = {\n id: \"cloud-ai-logo-brand\",\n name: \"AI Logo to Brand Kit\",\n description: \"Generate a logo with AI, then create production-ready brand assets\",\n category: \"AI Workflows\",\n generator: \"openai\",\n tags: [\"ai\", \"logo\", \"branding\", \"dall-e\", \"pipeline\"],\n requiresCloud: true,\n requiresAuth: true,\n usesAI: true,\n aiCreditsNeeded: 1,\n capabilities: {\n pipeline: true,\n },\n icon: \"sparkles\",\n valueProp: \"From idea to brand kit in seconds\",\n seo: {\n title: \"AI Logo to Brand Kit\",\n description: \"Generate a logo with AI and create production-ready brand assets\",\n keywords: [\"logo design\", \"brand kit\", \"ai generation\", \"branding\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-ai\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"openai\",\n params: {\n prompt: \"A modern minimalist logo for a tech startup called 'Nexus', clean geometric lines, professional, suitable for business cards and websites, white background\",\n model: \"dall-e-3\",\n size: \"1024x1024\",\n quality: \"standard\",\n },\n },\n },\n {\n id: \"transform-bg\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"removeBackground\",\n params: {},\n },\n },\n {\n id: \"transform-watermark\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"addCaption\",\n params: {\n text: \"Nexus Inc.\",\n position: \"bottom-right\",\n fontSize: 14,\n color: \"#6B7280\",\n padding: 16,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-ai\", target: \"transform-bg\" },\n { id: \"e2\", source: \"transform-bg\", target: \"transform-watermark\" },\n ],\n },\n};\n/**\n * Product Photo Enhancement (Cloud Onboarding)\n * Canonical ID: cloud-product-enhance\n */\nexport const productPhotoEnhancement = {\n id: \"cloud-product-enhance\",\n name: \"Product Photo Enhancement\",\n description: \"Remove background and add professional product labeling\",\n category: \"AI Workflows\",\n generator: \"input\",\n tags: [\"product\", \"ecommerce\", \"background-removal\", \"pipeline\"],\n requiresCloud: true,\n requiresAuth: true,\n usesAI: false, // Uses AI transforms but not AI generation\n aiCreditsNeeded: 0,\n capabilities: {\n pipeline: true,\n },\n icon: \"image\",\n valueProp: \"E-commerce ready in one click\",\n workflow: {\n nodes: [\n {\n id: \"input-1\",\n type: \"input\",\n position: { x: 100, y: 150 },\n data: {},\n },\n {\n id: \"transform-bg\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"removeBackground\",\n params: {},\n },\n },\n {\n id: \"transform-caption\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"addCaption\",\n params: {\n text: \"Premium Quality\",\n position: \"bottom-center\",\n fontSize: 24,\n color: \"#18181B\",\n padding: 20,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"input-1\", target: \"transform-bg\" },\n { id: \"e2\", source: \"transform-bg\", target: \"transform-caption\" },\n ],\n },\n};\n/**\n * AI Art to Social Post (Cloud Onboarding)\n * Canonical ID: cloud-ai-social\n */\nexport const aiArtSocialPost = {\n id: \"cloud-ai-social\",\n name: \"AI Art to Social Post\",\n description: \"Generate creative AI art, optimize for social media\",\n category: \"AI Workflows\",\n generator: \"openai\",\n tags: [\"ai\", \"art\", \"social-media\", \"dall-e\", \"pipeline\"],\n requiresCloud: true,\n requiresAuth: true,\n usesAI: true,\n aiCreditsNeeded: 1,\n capabilities: {\n pipeline: true,\n },\n icon: \"share\",\n valueProp: \"Creative content for your feed\",\n workflow: {\n nodes: [\n {\n id: \"gen-ai\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"openai\",\n params: {\n prompt: \"Abstract colorful digital art with flowing gradients, trending on artstation, vibrant neon colors, perfect for social media\",\n model: \"dall-e-3\",\n size: \"1024x1024\",\n style: \"vivid\",\n },\n },\n },\n {\n id: \"transform-corners\",\n type: \"transform\",\n position: { x: 400, y: 100 },\n data: {\n operation: \"roundCorners\",\n params: {\n radius: 24,\n },\n },\n },\n {\n id: \"transform-caption\",\n type: \"transform\",\n position: { x: 700, y: 100 },\n data: {\n operation: \"addCaption\",\n params: {\n text: \"@floimg\",\n position: \"bottom-right\",\n fontSize: 18,\n color: \"#FFFFFF\",\n padding: 16,\n },\n },\n },\n {\n id: \"transform-webp\",\n type: \"transform\",\n position: { x: 1000, y: 100 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/webp\",\n quality: 85,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-ai\", target: \"transform-corners\" },\n { id: \"e2\", source: \"transform-corners\", target: \"transform-caption\" },\n { id: \"e3\", source: \"transform-caption\", target: \"transform-webp\" },\n ],\n },\n};\n/**\n * All AI workflow templates\n */\nexport const aiWorkflowTemplates = [\n aiProductShot,\n aiHeroImage,\n aiMascot,\n aiLogoBrandKit,\n productPhotoEnhancement,\n aiArtSocialPost,\n];\n//# sourceMappingURL=ai-workflows.js.map","/**\n * Marketing Templates\n *\n * Social media kits, branding, and promotional asset workflows.\n * Most are pipeline templates that work offline (OSS-compatible).\n */\n/**\n * Social Media Kit\n * Canonical ID: social-media-kit\n */\nexport const socialMediaKit = {\n id: \"social-media-kit\",\n name: \"Social Media Kit\",\n description: \"Generate optimized images for all social platforms from one source\",\n category: \"Marketing\",\n generator: \"pipeline\",\n tags: [\"social\", \"og-image\", \"twitter\", \"instagram\", \"resize\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"share\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/social-media-kit.png\",\n },\n codeExample: `// One source -> all platforms\nconst socialKit = await floimg.pipeline(heroImage, [\n { op: 'resize', params: { width: 1200, height: 630 }, save: 'og-image.png' },\n { op: 'resize', params: { width: 800, height: 418 }, save: 'twitter-card.png' },\n { op: 'resize', params: { width: 1080, height: 1080 }, save: 'instagram.png' },\n]);`,\n seo: {\n title: \"Social Media Kit Generator\",\n description: \"Generate optimized images for all social platforms from one source image\",\n keywords: [\"social media\", \"og image\", \"twitter card\", \"instagram\", \"image resize\"],\n },\n workflow: {\n nodes: [\n {\n id: \"input-1\",\n type: \"input\",\n position: { x: 100, y: 200 },\n data: {},\n },\n {\n id: \"transform-og\",\n type: \"transform\",\n position: { x: 400, y: 100 },\n data: {\n operation: \"resize\",\n params: {\n width: 1200,\n height: 630,\n fit: \"cover\",\n },\n },\n },\n {\n id: \"transform-twitter\",\n type: \"transform\",\n position: { x: 400, y: 200 },\n data: {\n operation: \"resize\",\n params: {\n width: 800,\n height: 418,\n fit: \"cover\",\n },\n },\n },\n {\n id: \"transform-instagram\",\n type: \"transform\",\n position: { x: 400, y: 300 },\n data: {\n operation: \"resize\",\n params: {\n width: 1080,\n height: 1080,\n fit: \"cover\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"input-1\", target: \"transform-og\" },\n { id: \"e2\", source: \"input-1\", target: \"transform-twitter\" },\n { id: \"e3\", source: \"input-1\", target: \"transform-instagram\" },\n ],\n },\n};\n/**\n * Avatar Processing Pipeline\n * Canonical ID: avatar-pipeline\n */\nexport const avatarPipeline = {\n id: \"avatar-pipeline\",\n name: \"Avatar Processing\",\n description: \"Generate consistent avatar sizes with circular crop and optimization\",\n category: \"Marketing\",\n generator: \"pipeline\",\n tags: [\"avatar\", \"profile\", \"resize\", \"crop\", \"user\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"image\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/avatar-pipeline.png\",\n },\n codeExample: `const avatars = await floimg.pipeline(photo, [\n { op: 'crop', params: { shape: 'circle' } },\n { op: 'resize', params: { width: 256 }, save: 'avatar-256.png' },\n { op: 'resize', params: { width: 128 }, save: 'avatar-128.png' },\n { op: 'resize', params: { width: 64 }, save: 'avatar-64.png' },\n]);`,\n seo: {\n title: \"Avatar Processing Pipeline\",\n description: \"Generate consistent avatar sizes with circular crop and optimization\",\n keywords: [\"avatar\", \"profile picture\", \"image resize\", \"circular crop\"],\n },\n workflow: {\n nodes: [\n {\n id: \"input-1\",\n type: \"input\",\n position: { x: 100, y: 200 },\n data: {},\n },\n {\n id: \"transform-crop\",\n type: \"transform\",\n position: { x: 350, y: 200 },\n data: {\n operation: \"crop\",\n params: {\n shape: \"circle\",\n },\n },\n },\n {\n id: \"transform-256\",\n type: \"transform\",\n position: { x: 600, y: 100 },\n data: {\n operation: \"resize\",\n params: {\n width: 256,\n height: 256,\n },\n },\n },\n {\n id: \"transform-128\",\n type: \"transform\",\n position: { x: 600, y: 200 },\n data: {\n operation: \"resize\",\n params: {\n width: 128,\n height: 128,\n },\n },\n },\n {\n id: \"transform-64\",\n type: \"transform\",\n position: { x: 600, y: 300 },\n data: {\n operation: \"resize\",\n params: {\n width: 64,\n height: 64,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"input-1\", target: \"transform-crop\" },\n { id: \"e2\", source: \"transform-crop\", target: \"transform-256\" },\n { id: \"e3\", source: \"transform-crop\", target: \"transform-128\" },\n { id: \"e4\", source: \"transform-crop\", target: \"transform-64\" },\n ],\n },\n};\n/**\n * Branded Watermark\n * Canonical ID: watermark-branding\n */\nexport const watermarkBranding = {\n id: \"watermark-branding\",\n name: \"Branded Watermark\",\n description: \"Add your logo watermark to images automatically\",\n category: \"Marketing\",\n generator: \"pipeline\",\n tags: [\"watermark\", \"branding\", \"logo\", \"protection\", \"copyright\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"image\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/watermark-branding.png\",\n },\n seo: {\n title: \"Branded Watermark Template\",\n description: \"Add professional watermarks to protect and brand your images\",\n keywords: [\"watermark\", \"branding\", \"image protection\", \"logo overlay\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 100 },\n data: {\n generatorName: \"quickchart\",\n params: {\n chart: {\n type: \"bar\",\n data: {\n labels: [\"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\"],\n datasets: [\n {\n label: \"Sales\",\n data: [45, 62, 38, 71, 55],\n backgroundColor: \"rgba(99, 102, 241, 0.8)\",\n },\n ],\n },\n },\n width: 600,\n height: 400,\n },\n },\n },\n {\n id: \"transform-1\",\n type: \"transform\",\n position: { x: 400, y: 100 },\n data: {\n operation: \"addCaption\",\n params: {\n text: \"floimg.com\",\n position: \"bottom-right\",\n fontSize: 14,\n color: \"#9ca3af\",\n padding: 10,\n },\n },\n },\n {\n id: \"transform-2\",\n type: \"transform\",\n position: { x: 700, y: 100 },\n data: {\n operation: \"roundCorners\",\n params: {\n radius: 16,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-1\" },\n { id: \"e2\", source: \"transform-1\", target: \"transform-2\" },\n ],\n },\n};\n/**\n * Image Filters\n * Canonical ID: filter-showcase\n */\nexport const filterShowcase = {\n id: \"filter-showcase\",\n name: \"Image Filters\",\n description: \"Apply artistic filters: vintage, dramatic, vibrant, and more\",\n category: \"Marketing\",\n generator: \"pipeline\",\n tags: [\"filter\", \"vintage\", \"effects\", \"artistic\", \"photo\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"image\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/filter-showcase.png\",\n },\n seo: {\n title: \"Image Filter Effects\",\n description: \"Apply artistic filters like vintage, dramatic, and vibrant effects\",\n keywords: [\"image filter\", \"photo effects\", \"vintage filter\", \"artistic\"],\n },\n workflow: {\n nodes: [\n {\n id: \"input-1\",\n type: \"input\",\n position: { x: 100, y: 200 },\n data: {},\n },\n {\n id: \"transform-vintage\",\n type: \"transform\",\n position: { x: 400, y: 100 },\n data: {\n operation: \"adjustColors\",\n params: {\n saturation: 0.7,\n brightness: 0.9,\n sepia: 0.3,\n },\n },\n },\n {\n id: \"transform-vibrant\",\n type: \"transform\",\n position: { x: 400, y: 200 },\n data: {\n operation: \"adjustColors\",\n params: {\n saturation: 1.4,\n contrast: 1.2,\n },\n },\n },\n {\n id: \"transform-dramatic\",\n type: \"transform\",\n position: { x: 400, y: 300 },\n data: {\n operation: \"adjustColors\",\n params: {\n contrast: 1.5,\n brightness: 0.8,\n saturation: 0.9,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"input-1\", target: \"transform-vintage\" },\n { id: \"e2\", source: \"input-1\", target: \"transform-vibrant\" },\n { id: \"e3\", source: \"input-1\", target: \"transform-dramatic\" },\n ],\n },\n};\n/**\n * Responsive Image Pipeline\n * Canonical ID: responsive-images\n *\n * Multi-step workflow: Input → 5 parallel resize branches for responsive web\n * JTBD: Generate all responsive image sizes from one source for web performance\n */\nexport const responsiveImages = {\n id: \"responsive-images\",\n name: \"Responsive Image Pipeline\",\n description: \"Generate thumbnail, mobile, tablet, desktop, and retina sizes from one source\",\n category: \"Marketing\",\n generator: \"pipeline\",\n tags: [\"responsive\", \"web\", \"performance\", \"srcset\", \"resize\", \"pipeline\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"image\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/responsive-images.png\",\n },\n codeExample: `// One source → all responsive sizes\nconst responsive = await floimg.from(source)\n .transform('resize', { width: 320 }) // Mobile\n .transform('resize', { width: 768 }) // Tablet\n .transform('resize', { width: 1024 }) // Desktop\n .transform('resize', { width: 2048 }) // Retina\n .toBlob();`,\n seo: {\n title: \"Responsive Image Pipeline\",\n description: \"Generate all responsive image sizes for web srcset from one source\",\n keywords: [\"responsive images\", \"srcset\", \"web performance\", \"image optimization\"],\n },\n workflow: {\n nodes: [\n {\n id: \"input-1\",\n type: \"input\",\n position: { x: 100, y: 250 },\n data: {},\n },\n {\n id: \"transform-thumb\",\n type: \"transform\",\n position: { x: 400, y: 50 },\n data: {\n operation: \"resize\",\n params: {\n width: 150,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-mobile\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 320,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-tablet\",\n type: \"transform\",\n position: { x: 400, y: 250 },\n data: {\n operation: \"resize\",\n params: {\n width: 768,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-desktop\",\n type: \"transform\",\n position: { x: 400, y: 350 },\n data: {\n operation: \"resize\",\n params: {\n width: 1024,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-retina\",\n type: \"transform\",\n position: { x: 400, y: 450 },\n data: {\n operation: \"resize\",\n params: {\n width: 2048,\n fit: \"inside\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"input-1\", target: \"transform-thumb\" },\n { id: \"e2\", source: \"input-1\", target: \"transform-mobile\" },\n { id: \"e3\", source: \"input-1\", target: \"transform-tablet\" },\n { id: \"e4\", source: \"input-1\", target: \"transform-desktop\" },\n { id: \"e5\", source: \"input-1\", target: \"transform-retina\" },\n ],\n },\n};\n/**\n * Team Headshot Standardizer\n * Canonical ID: team-headshots\n *\n * Multi-step workflow: Input → Crop square → Resize → Grayscale → PNG export\n * JTBD: Standardize team photos for about pages and directories\n */\nexport const teamHeadshots = {\n id: \"team-headshots\",\n name: \"Team Headshot Standardizer\",\n description: \"Standardize team photos with consistent sizing and professional styling\",\n category: \"Marketing\",\n generator: \"pipeline\",\n tags: [\"headshot\", \"team\", \"about-page\", \"profile\", \"standardize\", \"pipeline\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"image\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/team-headshots.png\",\n },\n codeExample: `const headshot = await floimg.from(photo)\n .transform('extract', { width: 400, height: 400, gravity: 'face' })\n .transform('resize', { width: 300, height: 300 })\n .transform('grayscale')\n .transform('convert', { to: 'image/png' })\n .toBlob();`,\n seo: {\n title: \"Team Headshot Standardizer\",\n description: \"Standardize team photos with consistent sizing for about pages\",\n keywords: [\"headshot\", \"team photo\", \"about page\", \"profile picture\"],\n },\n workflow: {\n nodes: [\n {\n id: \"input-1\",\n type: \"input\",\n position: { x: 100, y: 150 },\n data: {},\n },\n {\n id: \"transform-crop\",\n type: \"transform\",\n position: { x: 350, y: 150 },\n data: {\n operation: \"extract\",\n params: {\n width: 400,\n height: 400,\n gravity: \"center\",\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 600, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 300,\n height: 300,\n fit: \"cover\",\n },\n },\n },\n {\n id: \"transform-grayscale\",\n type: \"transform\",\n position: { x: 850, y: 150 },\n data: {\n operation: \"grayscale\",\n params: {},\n },\n },\n {\n id: \"transform-png\",\n type: \"transform\",\n position: { x: 1100, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/png\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"input-1\", target: \"transform-crop\" },\n { id: \"e2\", source: \"transform-crop\", target: \"transform-resize\" },\n { id: \"e3\", source: \"transform-resize\", target: \"transform-grayscale\" },\n { id: \"e4\", source: \"transform-grayscale\", target: \"transform-png\" },\n ],\n },\n};\n/**\n * Screenshot to Documentation Asset\n * Canonical ID: screenshot-docs\n *\n * Multi-step workflow: Screenshot URL → Resize → Add border/shadow → Optimize\n * JTBD: Prepare screenshots for documentation and README files\n */\nexport const screenshotDocs = {\n id: \"screenshot-docs\",\n name: \"Screenshot to Docs\",\n description: \"Prepare screenshots for documentation with borders and optimization\",\n category: \"Marketing\",\n generator: \"screenshot\",\n tags: [\"screenshot\", \"documentation\", \"readme\", \"border\", \"pipeline\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"image\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/screenshot-docs.png\",\n },\n codeExample: `const docImage = await floimg\n .generate('screenshot', { url: 'https://example.com', width: 1280 })\n .transform('resize', { width: 800, fit: 'inside' })\n .transform('extend', { top: 16, bottom: 16, left: 16, right: 16, background: '#f3f4f6' })\n .transform('roundCorners', { radius: 8 })\n .transform('convert', { to: 'image/png' })\n .toBlob();`,\n seo: {\n title: \"Screenshot to Documentation Asset\",\n description: \"Prepare screenshots for documentation with professional styling\",\n keywords: [\"screenshot\", \"documentation\", \"readme\", \"developer tools\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"screenshot\",\n params: {\n url: \"https://floimg.com\",\n width: 1280,\n height: 800,\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 800,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-border\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"extend\",\n params: {\n top: 16,\n bottom: 16,\n left: 16,\n right: 16,\n background: \"#f3f4f6\",\n },\n },\n },\n {\n id: \"transform-corners\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"roundCorners\",\n params: {\n radius: 8,\n },\n },\n },\n {\n id: \"transform-png\",\n type: \"transform\",\n position: { x: 1300, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/png\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-border\" },\n { id: \"e3\", source: \"transform-border\", target: \"transform-corners\" },\n { id: \"e4\", source: \"transform-corners\", target: \"transform-png\" },\n ],\n },\n};\n/**\n * Blog Post OG Image\n * Canonical ID: blog-og-image\n *\n * Multi-step workflow: Input → Resize to OG → Add title overlay → WebP export\n * JTBD: Create social sharing images for blog posts with title overlay\n */\nexport const blogOgImage = {\n id: \"blog-og-image\",\n name: \"Blog Post OG Image\",\n description: \"Create social sharing images for blog posts with title overlay\",\n category: \"Marketing\",\n generator: \"pipeline\",\n tags: [\"blog\", \"og-image\", \"social\", \"title\", \"overlay\", \"pipeline\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"share\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/blog-og-image.png\",\n },\n codeExample: `const ogImage = await floimg.from(heroImage)\n .transform('resize', { width: 1200, height: 630, fit: 'cover' })\n .transform('addCaption', {\n text: 'How to Build Image Pipelines',\n position: 'center',\n fontSize: 48,\n color: '#ffffff'\n })\n .transform('convert', { to: 'image/webp', quality: 85 })\n .toBlob();`,\n seo: {\n title: \"Blog Post OG Image Generator\",\n description: \"Create social sharing images for blog posts with title overlay\",\n keywords: [\"og image\", \"blog\", \"social sharing\", \"title overlay\"],\n },\n workflow: {\n nodes: [\n {\n id: \"input-1\",\n type: \"input\",\n position: { x: 100, y: 150 },\n data: {},\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 1200,\n height: 630,\n fit: \"cover\",\n },\n },\n },\n {\n id: \"transform-caption\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"addCaption\",\n params: {\n text: \"Your Blog Post Title\",\n position: \"center\",\n fontSize: 48,\n color: \"#ffffff\",\n padding: 32,\n },\n },\n },\n {\n id: \"transform-webp\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/webp\",\n quality: 85,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"input-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-caption\" },\n { id: \"e3\", source: \"transform-caption\", target: \"transform-webp\" },\n ],\n },\n};\n/**\n * Email Banner\n * Canonical ID: email-banner\n *\n * Multi-step workflow: Input → Resize 600x200 → Add CTA text → PNG export\n * JTBD: Create email header banners with consistent dimensions for newsletters\n */\nexport const emailBanner = {\n id: \"email-banner\",\n name: \"Email Banner\",\n description: \"Create email header banners with consistent dimensions for newsletters\",\n category: \"Marketing\",\n generator: \"pipeline\",\n tags: [\"email\", \"banner\", \"newsletter\", \"header\", \"marketing\", \"pipeline\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"share\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/email-banner.png\",\n },\n codeExample: `const banner = await floimg.from(image)\n .transform('resize', { width: 600, height: 200, fit: 'cover' })\n .transform('addCaption', {\n text: 'Weekly Newsletter',\n position: 'center',\n fontSize: 32,\n color: '#ffffff'\n })\n .transform('convert', { to: 'image/png' })\n .toBlob();`,\n seo: {\n title: \"Email Banner Generator\",\n description: \"Create email header banners with consistent dimensions\",\n keywords: [\"email banner\", \"newsletter\", \"email marketing\", \"header image\"],\n },\n workflow: {\n nodes: [\n {\n id: \"input-1\",\n type: \"input\",\n position: { x: 100, y: 150 },\n data: {},\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 600,\n height: 200,\n fit: \"cover\",\n },\n },\n },\n {\n id: \"transform-caption\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"addCaption\",\n params: {\n text: \"Weekly Newsletter\",\n position: \"center\",\n fontSize: 32,\n color: \"#ffffff\",\n padding: 16,\n },\n },\n },\n {\n id: \"transform-png\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/png\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"input-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-caption\" },\n { id: \"e3\", source: \"transform-caption\", target: \"transform-png\" },\n ],\n },\n};\n/**\n * App Icon Generator\n * Canonical ID: app-icons\n *\n * Multi-step workflow: Input → Remove background → Multiple iOS/Android sizes\n * JTBD: Generate all required app icon sizes for iOS and Android from one source\n */\nexport const appIcons = {\n id: \"app-icons\",\n name: \"App Icon Generator\",\n description: \"Generate iOS and Android app icon sizes from one source image\",\n category: \"Marketing\",\n generator: \"pipeline\",\n tags: [\"app-icon\", \"ios\", \"android\", \"mobile\", \"resize\", \"pipeline\"],\n requiresCloud: true,\n requiresAuth: true,\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"image\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/app-icons.png\",\n },\n codeExample: `const icons = await floimg.from(logo)\n .transform('removeBackground')\n .transform('resize', { width: 180, height: 180 }) // iOS\n .transform('resize', { width: 192, height: 192 }) // Android\n .transform('resize', { width: 512, height: 512 }) // Store\n .toBlob();`,\n seo: {\n title: \"App Icon Generator\",\n description: \"Generate all required iOS and Android app icon sizes\",\n keywords: [\"app icon\", \"ios icon\", \"android icon\", \"mobile app\"],\n },\n workflow: {\n nodes: [\n {\n id: \"input-1\",\n type: \"input\",\n position: { x: 100, y: 200 },\n data: {},\n },\n {\n id: \"transform-bg\",\n type: \"transform\",\n position: { x: 350, y: 200 },\n data: {\n operation: \"removeBackground\",\n params: {},\n },\n },\n {\n id: \"transform-ios-60\",\n type: \"transform\",\n position: { x: 600, y: 50 },\n data: {\n operation: \"resize\",\n params: {\n width: 60,\n height: 60,\n fit: \"contain\",\n },\n },\n },\n {\n id: \"transform-ios-180\",\n type: \"transform\",\n position: { x: 600, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 180,\n height: 180,\n fit: \"contain\",\n },\n },\n },\n {\n id: \"transform-android-192\",\n type: \"transform\",\n position: { x: 600, y: 250 },\n data: {\n operation: \"resize\",\n params: {\n width: 192,\n height: 192,\n fit: \"contain\",\n },\n },\n },\n {\n id: \"transform-store-512\",\n type: \"transform\",\n position: { x: 600, y: 350 },\n data: {\n operation: \"resize\",\n params: {\n width: 512,\n height: 512,\n fit: \"contain\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"input-1\", target: \"transform-bg\" },\n { id: \"e2\", source: \"transform-bg\", target: \"transform-ios-60\" },\n { id: \"e3\", source: \"transform-bg\", target: \"transform-ios-180\" },\n { id: \"e4\", source: \"transform-bg\", target: \"transform-android-192\" },\n { id: \"e5\", source: \"transform-bg\", target: \"transform-store-512\" },\n ],\n },\n};\n/**\n * All marketing templates\n */\nexport const marketingTemplates = [\n socialMediaKit,\n avatarPipeline,\n watermarkBranding,\n filterShowcase,\n responsiveImages,\n teamHeadshots,\n screenshotDocs,\n blogOgImage,\n emailBanner,\n appIcons,\n];\n//# sourceMappingURL=marketing.js.map","/**\n * Utility Templates\n *\n * QR codes, format conversion, and general-purpose utilities.\n * All templates in this category work offline (OSS-compatible).\n */\n/**\n * Branded QR Code Pipeline\n * Canonical ID: branded-qr\n *\n * Multi-step workflow: Generate QR → Resize → Add rounded corners → Convert to PNG\n * Demonstrates: composable transforms on generated content\n */\nexport const brandedQR = {\n id: \"branded-qr\",\n name: \"Branded QR Code\",\n description: \"QR code with custom colors, rounded corners, and optimized for print or digital\",\n category: \"Utilities\",\n generator: \"qr\",\n tags: [\"qr\", \"branded\", \"link\", \"custom\", \"url\", \"pipeline\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"qr\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/branded-qr.png\",\n },\n codeExample: `const qr = await floimg\n .generate('qr', {\n text: 'https://floimg.com',\n color: { dark: '#0d9488', light: '#ffffff' }\n })\n .transform('resize', { width: 300, height: 300 })\n .transform('roundCorners', { radius: 16 })\n .transform('convert', { to: 'image/png' })\n .toBlob();`,\n seo: {\n title: \"Branded QR Code Generator\",\n description: \"Generate QR codes with custom colors, rounded corners, and professional styling\",\n keywords: [\"qr code\", \"branded qr\", \"custom qr\", \"marketing\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"qr\",\n params: {\n text: \"https://floimg.com\",\n width: 400,\n margin: 2,\n color: { dark: \"#0d9488\", light: \"#ffffff\" },\n errorCorrectionLevel: \"M\",\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 300,\n height: 300,\n fit: \"contain\",\n },\n },\n },\n {\n id: \"transform-corners\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"roundCorners\",\n params: {\n radius: 16,\n },\n },\n },\n {\n id: \"transform-convert\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/png\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-corners\" },\n { id: \"e3\", source: \"transform-corners\", target: \"transform-convert\" },\n ],\n },\n};\n/**\n * Dark Mode QR Code Pipeline\n * Canonical ID: dark-qr\n *\n * Multi-step workflow: Generate inverted QR → Resize → Add subtle border → WebP export\n * Demonstrates: transforms for dark UI integration\n */\nexport const darkQR = {\n id: \"dark-qr\",\n name: \"Dark Mode QR\",\n description: \"QR code optimized for dark backgrounds with subtle border and web-optimized export\",\n category: \"Utilities\",\n generator: \"qr\",\n tags: [\"qr\", \"dark-mode\", \"link\", \"inverted\", \"pipeline\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"qr\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/dark-qr.png\",\n },\n codeExample: `const qr = await floimg\n .generate('qr', {\n text: 'https://floimg.com',\n color: { dark: '#ffffff', light: '#18181b' }\n })\n .transform('resize', { width: 300, height: 300 })\n .transform('extend', {\n top: 8, bottom: 8, left: 8, right: 8,\n background: '#27272a'\n })\n .transform('convert', { to: 'image/webp', quality: 90 })\n .toBlob();`,\n seo: {\n title: \"Dark Mode QR Code\",\n description: \"QR codes optimized for dark backgrounds and dark mode UIs\",\n keywords: [\"qr code\", \"dark mode\", \"inverted qr\", \"night mode\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"qr\",\n params: {\n text: \"https://floimg.com\",\n width: 400,\n margin: 2,\n color: { dark: \"#ffffff\", light: \"#18181b\" },\n errorCorrectionLevel: \"M\",\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 300,\n height: 300,\n fit: \"contain\",\n },\n },\n },\n {\n id: \"transform-border\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"extend\",\n params: {\n top: 8,\n bottom: 8,\n left: 8,\n right: 8,\n background: \"#27272a\",\n },\n },\n },\n {\n id: \"transform-webp\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/webp\",\n quality: 90,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-border\" },\n { id: \"e3\", source: \"transform-border\", target: \"transform-webp\" },\n ],\n },\n};\n/**\n * WiFi QR Code Pipeline\n * Canonical ID: wifi-qr\n *\n * Multi-step workflow: Generate WiFi QR → Resize → Add caption label → Rounded corners\n * Demonstrates: adding context/labels to generated content\n */\nexport const wifiQR = {\n id: \"wifi-qr\",\n name: \"WiFi QR Code\",\n description: \"Scannable WiFi QR code with network name label and professional styling\",\n category: \"Utilities\",\n generator: \"qr\",\n tags: [\"qr\", \"wifi\", \"network\", \"guest\", \"access\", \"pipeline\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"qr\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/wifi-qr.png\",\n },\n codeExample: `const qr = await floimg\n .generate('qr', {\n text: 'WIFI:T:WPA;S:GuestNetwork;P:welcome123;;',\n color: { dark: '#059669', light: '#ffffff' }\n })\n .transform('resize', { width: 300, height: 300 })\n .transform('addCaption', {\n text: 'Scan for WiFi',\n position: 'bottom-center',\n fontSize: 18,\n color: '#059669'\n })\n .transform('roundCorners', { radius: 12 })\n .toBlob();`,\n seo: {\n title: \"WiFi QR Code Generator\",\n description: \"Generate scannable QR codes for easy WiFi network access sharing\",\n keywords: [\"wifi qr\", \"network access\", \"guest wifi\", \"qr code\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 150 },\n data: {\n generatorName: \"qr\",\n params: {\n text: \"WIFI:T:WPA;S:GuestNetwork;P:welcome123;;\",\n width: 400,\n margin: 2,\n color: { dark: \"#059669\", light: \"#ffffff\" },\n errorCorrectionLevel: \"H\",\n },\n },\n },\n {\n id: \"transform-resize\",\n type: \"transform\",\n position: { x: 400, y: 150 },\n data: {\n operation: \"resize\",\n params: {\n width: 300,\n height: 300,\n fit: \"contain\",\n },\n },\n },\n {\n id: \"transform-caption\",\n type: \"transform\",\n position: { x: 700, y: 150 },\n data: {\n operation: \"addCaption\",\n params: {\n text: \"Scan for WiFi\",\n position: \"bottom-center\",\n fontSize: 18,\n color: \"#059669\",\n padding: 16,\n },\n },\n },\n {\n id: \"transform-corners\",\n type: \"transform\",\n position: { x: 1000, y: 150 },\n data: {\n operation: \"roundCorners\",\n params: {\n radius: 12,\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"gen-1\", target: \"transform-resize\" },\n { id: \"e2\", source: \"transform-resize\", target: \"transform-caption\" },\n { id: \"e3\", source: \"transform-caption\", target: \"transform-corners\" },\n ],\n },\n};\n/**\n * Thumbnail Generator\n * Canonical ID: thumbnail-generator\n */\nexport const thumbnailGenerator = {\n id: \"thumbnail-generator\",\n name: \"Thumbnail Generator\",\n description: \"Create multiple thumbnail sizes with automatic optimization\",\n category: \"Utilities\",\n generator: \"pipeline\",\n tags: [\"thumbnail\", \"resize\", \"optimize\", \"batch\", \"responsive\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"image\",\n preview: {\n imageUrl: \"https://floimg.com/images/templates/thumbnail-generator.png\",\n },\n seo: {\n title: \"Thumbnail Generator\",\n description: \"Generate multiple thumbnail sizes with automatic optimization\",\n keywords: [\"thumbnail\", \"image resize\", \"responsive images\", \"optimization\"],\n },\n workflow: {\n nodes: [\n {\n id: \"input-1\",\n type: \"input\",\n position: { x: 100, y: 200 },\n data: {},\n },\n {\n id: \"transform-800\",\n type: \"transform\",\n position: { x: 400, y: 100 },\n data: {\n operation: \"resize\",\n params: {\n width: 800,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-400\",\n type: \"transform\",\n position: { x: 400, y: 200 },\n data: {\n operation: \"resize\",\n params: {\n width: 400,\n fit: \"inside\",\n },\n },\n },\n {\n id: \"transform-200\",\n type: \"transform\",\n position: { x: 400, y: 300 },\n data: {\n operation: \"resize\",\n params: {\n width: 200,\n fit: \"inside\",\n },\n },\n },\n ],\n edges: [\n { id: \"e1\", source: \"input-1\", target: \"transform-800\" },\n { id: \"e2\", source: \"input-1\", target: \"transform-400\" },\n { id: \"e3\", source: \"input-1\", target: \"transform-200\" },\n ],\n },\n};\n/**\n * Diagram to WebP Conversion\n * Canonical ID: diagram-webp\n */\nexport const diagramWebp = {\n id: \"diagram-webp\",\n name: \"Diagram to WebP\",\n description: \"Mermaid diagram converted to optimized WebP format\",\n category: \"Utilities\",\n generator: \"mermaid\",\n tags: [\"mermaid\", \"webp\", \"optimize\", \"pipeline\", \"conversion\"],\n capabilities: {\n claudeCodeReady: true,\n pipeline: true,\n },\n icon: \"diagram\",\n seo: {\n title: \"Diagram to WebP Converter\",\n description: \"Convert Mermaid diagrams to optimized WebP format\",\n keywords: [\"mermaid diagram\", \"webp conversion\", \"image optimization\"],\n },\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 100 },\n data: {\n generatorName: \"mermaid\",\n params: {\n code: `graph LR\n A[Start] --> B{Decision}\n B -->|Yes| C[Action 1]\n B -->|No| D[Action 2]\n C --> E[End]\n D --> E`,\n theme: \"neutral\",\n },\n },\n },\n {\n id: \"transform-1\",\n type: \"transform\",\n position: { x: 400, y: 100 },\n data: {\n operation: \"convert\",\n params: {\n to: \"image/webp\",\n quality: 90,\n },\n },\n },\n ],\n edges: [{ id: \"e1\", source: \"gen-1\", target: \"transform-1\" }],\n },\n};\n/**\n * All utility templates\n */\nexport const utilityTemplates = [\n brandedQR,\n darkQR,\n wifiQR,\n thumbnailGenerator,\n diagramWebp,\n];\n//# sourceMappingURL=utilities.js.map","/**\n * @teamflojo/floimg-templates\n *\n * Official workflow templates for FloImg Studio.\n * Single source of truth for template definitions.\n *\n * @example\n * ```typescript\n * // Self-hosted: Get only templates that work offline\n * import { getCoreTemplates } from '@teamflojo/floimg-templates';\n * const templates = getCoreTemplates();\n *\n * // Cloud/full: Get all templates including those requiring API keys\n * import { getAllTemplates } from '@teamflojo/floimg-templates';\n * const templates = getAllTemplates();\n *\n * // Get specific template with metadata\n * import { getTemplateById } from '@teamflojo/floimg-templates';\n * const template = getTemplateById('revenue-chart');\n * ```\n */\n// Import all template categories\nimport { dataVizTemplates } from \"./templates/data-viz.js\";\nimport { aiWorkflowTemplates } from \"./templates/ai-workflows.js\";\nimport { marketingTemplates } from \"./templates/marketing.js\";\nimport { utilityTemplates } from \"./templates/utilities.js\";\n// Re-export individual templates for direct imports\nexport * from \"./templates/data-viz.js\";\nexport * from \"./templates/ai-workflows.js\";\nexport * from \"./templates/marketing.js\";\nexport * from \"./templates/utilities.js\";\n// ============================================\n// Template Registry\n// ============================================\n/**\n * All templates combined\n */\nexport const allTemplates = [\n ...dataVizTemplates,\n ...aiWorkflowTemplates,\n ...marketingTemplates,\n ...utilityTemplates,\n];\n/**\n * Core templates that work offline (no cloud required)\n * For FloImg Studio OSS and self-hosted deployments\n */\nexport const coreTemplates = allTemplates.filter((t) => !t.requiresCloud);\n/**\n * Cloud-only templates (require API keys like OpenAI, etc.)\n */\nexport const cloudTemplates = allTemplates.filter((t) => t.requiresCloud);\n// ============================================\n// Query Functions\n// ============================================\n/**\n * Get all templates (includes cloud-only templates)\n */\nexport function getAllTemplates() {\n return allTemplates;\n}\n/**\n * Get only core templates that work offline (for OSS Studio)\n */\nexport function getCoreTemplates() {\n return coreTemplates;\n}\n/**\n * Get cloud-only templates (require API keys)\n */\nexport function getCloudTemplates() {\n return cloudTemplates;\n}\n/**\n * Get a template by ID (searches all templates)\n */\nexport function getTemplateById(id) {\n return allTemplates.find((t) => t.id === id);\n}\n/**\n * Get a core template by ID (OSS-compatible only)\n */\nexport function getCoreTemplateById(id) {\n return coreTemplates.find((t) => t.id === id);\n}\n/**\n * Get all unique categories (from all templates)\n */\nexport function getCategories() {\n const categories = new Set(allTemplates.map((t) => t.category));\n return Array.from(categories);\n}\n/**\n * Get categories available in core templates (OSS-compatible)\n */\nexport function getCoreCategories() {\n const categories = new Set(coreTemplates.map((t) => t.category));\n return Array.from(categories);\n}\n/**\n * Get templates by category (from all templates)\n */\nexport function getTemplatesByCategory(category) {\n return allTemplates.filter((t) => t.category === category);\n}\n/**\n * Get core templates by category (OSS-compatible)\n */\nexport function getCoreTemplatesByCategory(category) {\n return coreTemplates.filter((t) => t.category === category);\n}\n/**\n * Get templates by generator type\n */\nexport function getTemplatesByGenerator(generator) {\n return allTemplates.filter((t) => t.generator === generator);\n}\n/**\n * Search templates by query (searches name, description, tags)\n */\nexport function searchTemplates(query) {\n const q = query.toLowerCase();\n return allTemplates.filter((t) => t.name.toLowerCase().includes(q) ||\n t.description.toLowerCase().includes(q) ||\n t.category.toLowerCase().includes(q) ||\n t.generator.toLowerCase().includes(q) ||\n t.tags?.some((tag) => tag.toLowerCase().includes(q)));\n}\n/**\n * Search core templates by query (OSS-compatible)\n */\nexport function searchCoreTemplates(query) {\n const q = query.toLowerCase();\n return coreTemplates.filter((t) => t.name.toLowerCase().includes(q) ||\n t.description.toLowerCase().includes(q) ||\n t.category.toLowerCase().includes(q) ||\n t.generator.toLowerCase().includes(q) ||\n t.tags?.some((tag) => tag.toLowerCase().includes(q)));\n}\n/**\n * Get templates that require authentication\n */\nexport function getAuthRequiredTemplates() {\n return allTemplates.filter((t) => t.requiresAuth);\n}\n/**\n * Get templates by capability\n */\nexport function getTemplatesByCapability(capability) {\n return allTemplates.filter((t) => t.capabilities?.[capability]);\n}\n// ============================================\n// Studio URL Helpers\n// ============================================\n/**\n * Get the Studio URL for a template\n * @param templateId - The template ID\n * @param baseUrl - Base URL (defaults to studio.floimg.com for cloud, or can be overridden for self-hosted)\n */\nexport function getStudioUrl(templateId, baseUrl = \"https://studio.floimg.com\") {\n return `${baseUrl}/?template=${templateId}`;\n}\n/**\n * Get the OSS Studio URL for a template (localhost default)\n * @param templateId - The template ID\n * @param port - Port number (defaults to 5173)\n */\nexport function getOSSStudioUrl(templateId, port = 5173) {\n return `http://localhost:${port}/?template=${templateId}`;\n}\n/**\n * Resolve a template by ID\n * @param id - Template ID\n * @returns The template or undefined\n */\nexport function resolveTemplate(id) {\n return getTemplateById(id);\n}\n// ============================================\n// Computed Metadata Helpers\n// ============================================\n/**\n * Get the node count for a template\n * Uses explicit nodeCount if set, otherwise computes from workflow.nodes.length\n */\nexport function getNodeCount(template) {\n if (template.nodeCount !== undefined) {\n return template.nodeCount;\n }\n return template.workflow.nodes.length;\n}\n/**\n * Get all templates with computed nodeCount added\n * Useful for consumers that want to display node count\n */\nexport function getAllTemplatesWithNodeCount() {\n return allTemplates.map((t) => ({\n ...t,\n nodeCount: getNodeCount(t),\n }));\n}\n/**\n * Get templates that are true pipelines (2+ nodes)\n */\nexport function getPipelineTemplates() {\n return allTemplates.filter((t) => getNodeCount(t) >= 2);\n}\n/**\n * Get templates sorted by complexity (node count, descending)\n */\nexport function getTemplatesByComplexity() {\n return [...allTemplates].sort((a, b) => getNodeCount(b) - getNodeCount(a));\n}\n//# sourceMappingURL=index.js.map","import { useState, useMemo } from \"react\";\nimport {\n coreTemplates as templates,\n getCoreCategories as getCategories,\n type Template,\n} from \"@teamflojo/floimg-templates\";\n\ninterface TemplateGalleryProps {\n onSelect: (templateId: string) => void;\n}\n\nexport function TemplateGallery({ onSelect }: TemplateGalleryProps) {\n const [selectedCategory, setSelectedCategory] = useState<string | null>(null);\n const [searchQuery, setSearchQuery] = useState(\"\");\n\n const categories = useMemo(() => getCategories(), []);\n\n const filteredTemplates = useMemo(() => {\n let result = templates;\n\n // Filter by category\n if (selectedCategory) {\n result = result.filter((t) => t.category === selectedCategory);\n }\n\n // Filter by search query\n if (searchQuery) {\n const q = searchQuery.toLowerCase();\n result = result.filter(\n (t) =>\n t.name.toLowerCase().includes(q) ||\n t.description.toLowerCase().includes(q) ||\n t.generator.toLowerCase().includes(q) ||\n t.tags?.some((tag) => tag.toLowerCase().includes(q))\n );\n }\n\n return result;\n }, [selectedCategory, searchQuery]);\n\n return (\n <div className=\"p-6\">\n <div className=\"mb-6\">\n <h2 className=\"text-2xl font-bold text-gray-900 dark:text-white mb-2\">Templates</h2>\n <p className=\"text-gray-600 dark:text-zinc-400\">\n Start with a pre-built workflow. Click any template to load it into the editor.\n </p>\n </div>\n\n {/* Search and filters */}\n <div className=\"flex flex-wrap gap-4 mb-6\">\n <input\n type=\"text\"\n placeholder=\"Search templates...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"px-4 py-2 border border-gray-300 dark:border-zinc-600 rounded-lg bg-white dark:bg-zinc-800 text-gray-900 dark:text-white focus:ring-2 focus:ring-teal-500 focus:border-transparent w-64\"\n />\n\n <div className=\"flex gap-2 flex-wrap\">\n <button\n onClick={() => setSelectedCategory(null)}\n className={`px-3 py-1.5 rounded-full text-sm font-medium transition-colors ${\n selectedCategory === null\n ? \"bg-teal-600 text-white\"\n : \"bg-gray-200 dark:bg-zinc-700 text-gray-700 dark:text-zinc-300 hover:bg-gray-300 dark:hover:bg-zinc-600\"\n }`}\n >\n All\n </button>\n {categories.map((category) => (\n <button\n key={category}\n onClick={() => setSelectedCategory(category)}\n className={`px-3 py-1.5 rounded-full text-sm font-medium transition-colors ${\n selectedCategory === category\n ? \"bg-teal-600 text-white\"\n : \"bg-gray-200 dark:bg-zinc-700 text-gray-700 dark:text-zinc-300 hover:bg-gray-300 dark:hover:bg-zinc-600\"\n }`}\n >\n {category}\n </button>\n ))}\n </div>\n </div>\n\n {/* Template grid */}\n {filteredTemplates.length === 0 ? (\n <div className=\"text-center py-12 text-gray-500 dark:text-zinc-400\">\n No templates found matching your criteria.\n </div>\n ) : (\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6\">\n {filteredTemplates.map((template) => (\n <TemplateCard\n key={template.id}\n template={template}\n onSelect={() => onSelect(template.id)}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\ninterface TemplateCardProps {\n template: Template;\n onSelect: () => void;\n}\n\nfunction TemplateCard({ template, onSelect }: TemplateCardProps) {\n const nodeCount = template.workflow.nodes.length;\n const edgeCount = template.workflow.edges.length;\n\n // Generator badge colors\n const generatorColors: Record<string, string> = {\n quickchart: \"bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300\",\n mermaid: \"bg-pink-100 text-pink-800 dark:bg-pink-900/30 dark:text-pink-300\",\n qr: \"bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300\",\n d3: \"bg-orange-100 text-orange-800 dark:bg-orange-900/30 dark:text-orange-300\",\n };\n\n return (\n <div className=\"bg-white dark:bg-zinc-800 rounded-lg border border-gray-200 dark:border-zinc-700 overflow-hidden hover:shadow-lg transition-shadow\">\n {/* Preview area */}\n <div className=\"aspect-video bg-gray-100 dark:bg-zinc-900 flex items-center justify-center p-4\">\n {template.preview ? (\n <img\n src={template.preview.imageUrl}\n alt={template.name}\n className=\"max-w-full max-h-full object-contain\"\n />\n ) : (\n <div className=\"text-center text-gray-400 dark:text-zinc-500\">\n <svg\n className=\"w-12 h-12 mx-auto mb-2\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={1.5}\n d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\"\n />\n </svg>\n <span className=\"text-sm\">No preview</span>\n </div>\n )}\n </div>\n\n {/* Content */}\n <div className=\"p-4\">\n <div className=\"flex items-start justify-between mb-2\">\n <h3 className=\"text-lg font-semibold text-gray-900 dark:text-white\">{template.name}</h3>\n <span\n className={`px-2 py-0.5 rounded text-xs font-medium ${\n generatorColors[template.generator] ||\n \"bg-gray-100 text-gray-800 dark:bg-zinc-700 dark:text-zinc-300\"\n }`}\n >\n {template.generator}\n </span>\n </div>\n\n <p className=\"text-sm text-gray-600 dark:text-zinc-400 mb-3\">{template.description}</p>\n\n {/* Metadata */}\n <div className=\"flex items-center gap-4 text-xs text-gray-500 dark:text-zinc-500 mb-4\">\n <span className=\"flex items-center gap-1\">\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 6h16M4 12h16M4 18h7\"\n />\n </svg>\n {nodeCount} node{nodeCount !== 1 ? \"s\" : \"\"}\n </span>\n {edgeCount > 0 && (\n <span className=\"flex items-center gap-1\">\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M13 7l5 5m0 0l-5 5m5-5H6\"\n />\n </svg>\n {edgeCount} edge{edgeCount !== 1 ? \"s\" : \"\"}\n </span>\n )}\n </div>\n\n {/* Tags */}\n {template.tags && template.tags.length > 0 && (\n <div className=\"flex flex-wrap gap-1 mb-4\">\n {template.tags.slice(0, 4).map((tag) => (\n <span\n key={tag}\n className=\"px-2 py-0.5 bg-gray-100 dark:bg-zinc-700 text-gray-600 dark:text-zinc-400 rounded text-xs\"\n >\n {tag}\n </span>\n ))}\n </div>\n )}\n\n {/* Action button */}\n <button\n onClick={onSelect}\n className=\"w-full py-2 px-4 bg-teal-600 hover:bg-teal-700 text-white rounded-lg font-medium transition-colors\"\n >\n Use Template\n </button>\n </div>\n </div>\n );\n}\n","import { useState } from \"react\";\nimport { useWorkflowStore, type SavedWorkflow } from \"../stores/workflowStore\";\n\ninterface WorkflowItemProps {\n workflow: SavedWorkflow;\n isActive: boolean;\n onLoad: () => void;\n onDelete: () => void;\n onRename: (name: string) => void;\n onDuplicate: () => void;\n}\n\nfunction WorkflowItem({\n workflow,\n isActive,\n onLoad,\n onDelete,\n onRename,\n onDuplicate,\n}: WorkflowItemProps) {\n const [isEditing, setIsEditing] = useState(false);\n const [editName, setEditName] = useState(workflow.name);\n const [showMenu, setShowMenu] = useState(false);\n\n const handleRename = () => {\n if (editName.trim() && editName !== workflow.name) {\n onRename(editName.trim());\n }\n setIsEditing(false);\n };\n\n const formatDate = (timestamp: number) => {\n const date = new Date(timestamp);\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffMins = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMs / 3600000);\n const diffDays = Math.floor(diffMs / 86400000);\n\n if (diffMins < 1) return \"Just now\";\n if (diffMins < 60) return `${diffMins}m ago`;\n if (diffHours < 24) return `${diffHours}h ago`;\n if (diffDays < 7) return `${diffDays}d ago`;\n return date.toLocaleDateString();\n };\n\n return (\n <div\n className={`group relative p-3 rounded-lg border transition-colors ${\n isActive\n ? \"bg-teal-50 dark:bg-teal-900/20 border-teal-200 dark:border-teal-800\"\n : \"bg-white dark:bg-zinc-800 border-zinc-200 dark:border-zinc-700 hover:border-zinc-300 dark:hover:border-zinc-600\"\n }`}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <button onClick={onLoad} className=\"flex-1 text-left min-w-0\">\n {isEditing ? (\n <input\n type=\"text\"\n value={editName}\n onChange={(e) => setEditName(e.target.value)}\n onBlur={handleRename}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") handleRename();\n if (e.key === \"Escape\") {\n setEditName(workflow.name);\n setIsEditing(false);\n }\n }}\n className=\"w-full px-1 py-0.5 text-sm font-medium bg-white dark:bg-zinc-900 border border-teal-500 rounded focus:outline-none focus:ring-1 focus:ring-teal-500\"\n autoFocus\n onClick={(e) => e.stopPropagation()}\n />\n ) : (\n <span className=\"block text-sm font-medium text-zinc-900 dark:text-zinc-100 truncate\">\n {workflow.name}\n </span>\n )}\n <span className=\"block text-xs text-zinc-500 dark:text-zinc-400 mt-0.5\">\n {workflow.nodes.length} nodes · Updated {formatDate(workflow.updatedAt)}\n </span>\n </button>\n\n <div className=\"relative\">\n <button\n onClick={(e) => {\n e.stopPropagation();\n setShowMenu(!showMenu);\n }}\n className=\"p-1 text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300 rounded opacity-0 group-hover:opacity-100 transition-opacity\"\n >\n <svg className=\"w-4 h-4\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path d=\"M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z\" />\n </svg>\n </button>\n\n {showMenu && (\n <>\n <div className=\"fixed inset-0 z-10\" onClick={() => setShowMenu(false)} />\n <div className=\"absolute right-0 top-full mt-1 w-36 bg-white dark:bg-zinc-800 rounded-lg shadow-lg border border-zinc-200 dark:border-zinc-700 py-1 z-20\">\n <button\n onClick={(e) => {\n e.stopPropagation();\n setIsEditing(true);\n setShowMenu(false);\n }}\n className=\"w-full px-3 py-1.5 text-left text-sm text-zinc-700 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-700\"\n >\n Rename\n </button>\n <button\n onClick={(e) => {\n e.stopPropagation();\n onDuplicate();\n setShowMenu(false);\n }}\n className=\"w-full px-3 py-1.5 text-left text-sm text-zinc-700 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-700\"\n >\n Duplicate\n </button>\n <button\n onClick={(e) => {\n e.stopPropagation();\n if (window.confirm(\"Delete this workflow?\")) {\n onDelete();\n }\n setShowMenu(false);\n }}\n className=\"w-full px-3 py-1.5 text-left text-sm text-red-600 dark:text-red-400 hover:bg-zinc-100 dark:hover:bg-zinc-700\"\n >\n Delete\n </button>\n </div>\n </>\n )}\n </div>\n </div>\n\n {isActive && <span className=\"absolute top-2 right-2 w-2 h-2 bg-teal-500 rounded-full\" />}\n </div>\n );\n}\n\nexport function WorkflowLibrary() {\n const showLibrary = useWorkflowStore((s) => s.showLibrary);\n const toggleLibrary = useWorkflowStore((s) => s.toggleLibrary);\n const savedWorkflows = useWorkflowStore((s) => s.savedWorkflows);\n const activeWorkflowId = useWorkflowStore((s) => s.activeWorkflowId);\n const loadWorkflow = useWorkflowStore((s) => s.loadWorkflow);\n const deleteWorkflow = useWorkflowStore((s) => s.deleteWorkflow);\n const renameWorkflow = useWorkflowStore((s) => s.renameWorkflow);\n const duplicateWorkflow = useWorkflowStore((s) => s.duplicateWorkflow);\n const newWorkflow = useWorkflowStore((s) => s.newWorkflow);\n\n if (!showLibrary) return null;\n\n // Sort by most recently updated\n const sortedWorkflows = [...savedWorkflows].sort((a, b) => b.updatedAt - a.updatedAt);\n\n return (\n <>\n {/* Backdrop */}\n <div className=\"fixed inset-0 bg-black/20 dark:bg-black/40 z-40\" onClick={toggleLibrary} />\n\n {/* Panel */}\n <div className=\"fixed left-0 top-0 bottom-0 w-80 bg-zinc-50 dark:bg-zinc-900 border-r border-zinc-200 dark:border-zinc-700 z-50 flex flex-col shadow-xl\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-zinc-200 dark:border-zinc-700\">\n <h2 className=\"text-lg font-semibold text-zinc-900 dark:text-zinc-100\">My Workflows</h2>\n <button\n onClick={toggleLibrary}\n className=\"p-1 text-zinc-500 hover:text-zinc-700 dark:hover:text-zinc-300 rounded\"\n >\n <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n </div>\n\n {/* New Workflow Button */}\n <div className=\"p-4 border-b border-zinc-200 dark:border-zinc-700\">\n <button\n onClick={() => {\n newWorkflow();\n toggleLibrary();\n window.dispatchEvent(new window.CustomEvent(\"new-workflow-created\"));\n }}\n className=\"w-full flex items-center justify-center gap-2 px-4 py-2 text-sm font-medium text-white bg-teal-600 rounded-lg hover:bg-teal-700 transition-colors\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 4v16m8-8H4\"\n />\n </svg>\n New Workflow\n </button>\n </div>\n\n {/* Workflow List */}\n <div className=\"flex-1 overflow-y-auto p-4\">\n {sortedWorkflows.length === 0 ? (\n <div className=\"text-center py-8\">\n <div className=\"w-12 h-12 mx-auto mb-3 rounded-full bg-zinc-200 dark:bg-zinc-700 flex items-center justify-center\">\n <svg\n className=\"w-6 h-6 text-zinc-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10\"\n />\n </svg>\n </div>\n <p className=\"text-sm text-zinc-500 dark:text-zinc-400\">No saved workflows yet</p>\n <p className=\"text-xs text-zinc-400 dark:text-zinc-500 mt-1\">\n Build a workflow and save it to see it here\n </p>\n </div>\n ) : (\n <div className=\"space-y-2\">\n {sortedWorkflows.map((workflow) => (\n <WorkflowItem\n key={workflow.id}\n workflow={workflow}\n isActive={workflow.id === activeWorkflowId}\n onLoad={() => {\n loadWorkflow(workflow.id);\n toggleLibrary();\n }}\n onDelete={() => deleteWorkflow(workflow.id)}\n onRename={(name) => renameWorkflow(workflow.id, name)}\n onDuplicate={() => duplicateWorkflow(workflow.id)}\n />\n ))}\n </div>\n )}\n </div>\n\n {/* Footer */}\n <div className=\"px-4 py-3 border-t border-zinc-200 dark:border-zinc-700 text-xs text-zinc-500 dark:text-zinc-400\">\n {savedWorkflows.length} workflow{savedWorkflows.length !== 1 ? \"s\" : \"\"} saved locally\n </div>\n </div>\n </>\n );\n}\n","import { useState } from \"react\";\nimport { useSettingsStore } from \"../stores/settingsStore\";\n\n// Provider metadata\nconst CLOUD_PROVIDERS = [\n {\n id: \"openai\" as const,\n name: \"OpenAI\",\n description: \"GPT-4 Vision, GPT-4 Text, DALL-E 3\",\n placeholder: \"sk-...\",\n docsUrl: \"https://platform.openai.com/api-keys\",\n },\n {\n id: \"anthropic\" as const,\n name: \"Anthropic\",\n description: \"Claude Vision, Claude Text\",\n placeholder: \"sk-ant-...\",\n docsUrl: \"https://console.anthropic.com/settings/keys\",\n },\n {\n id: \"gemini\" as const,\n name: \"Google AI\",\n description: \"Gemini Vision, Gemini Text, Gemini Edit\",\n placeholder: \"AIza...\",\n docsUrl: \"https://aistudio.google.com/apikey\",\n },\n {\n id: \"grok\" as const,\n name: \"xAI (Grok)\",\n description: \"Grok Vision, Grok Text\",\n placeholder: \"xai-...\",\n docsUrl: \"https://console.x.ai/\",\n },\n {\n id: \"openrouter\" as const,\n name: \"OpenRouter\",\n description: \"Access multiple models with one API key\",\n placeholder: \"sk-or-...\",\n docsUrl: \"https://openrouter.ai/keys\",\n },\n];\n\nconst LOCAL_PROVIDERS = [\n {\n id: \"ollama\" as const,\n name: \"Ollama\",\n description: \"Local LLaVA Vision, Llama/Mistral Text\",\n defaultUrl: \"http://localhost:11434\",\n docsUrl: \"https://ollama.ai\",\n },\n {\n id: \"lmstudio\" as const,\n name: \"LM Studio\",\n description: \"Local models via OpenAI-compatible API\",\n defaultUrl: \"http://localhost:1234\",\n docsUrl: \"https://lmstudio.ai\",\n },\n];\n\nfunction CloudProviderRow({ provider }: { provider: (typeof CLOUD_PROVIDERS)[number] }) {\n const ai = useSettingsStore((s) => s.ai);\n const setAIProvider = useSettingsStore((s) => s.setAIProvider);\n\n const config = ai[provider.id];\n const isEnabled = config?.enabled ?? false;\n const apiKey = (config as { apiKey?: string })?.apiKey ?? \"\";\n\n const [localKey, setLocalKey] = useState(apiKey);\n const [showKey, setShowKey] = useState(false);\n\n const handleToggle = () => {\n setAIProvider(provider.id, {\n apiKey: localKey,\n enabled: !isEnabled,\n });\n };\n\n const handleKeyChange = (value: string) => {\n setLocalKey(value);\n setAIProvider(provider.id, {\n apiKey: value,\n enabled: isEnabled,\n });\n };\n\n return (\n <div className=\"flex items-start gap-4 p-4 border border-gray-200 dark:border-zinc-700 rounded-lg\">\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium text-gray-900 dark:text-white\">{provider.name}</span>\n <a\n href={provider.docsUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-xs text-teal-600 dark:text-teal-400 hover:underline\"\n >\n Get API key\n </a>\n </div>\n <p className=\"text-sm text-gray-500 dark:text-zinc-400 mt-0.5\">{provider.description}</p>\n <div className=\"mt-2 flex items-center gap-2\">\n <div className=\"relative flex-1\">\n <input\n type={showKey ? \"text\" : \"password\"}\n value={localKey}\n onChange={(e) => handleKeyChange(e.target.value)}\n placeholder={provider.placeholder}\n className=\"w-full px-3 py-1.5 text-sm border border-gray-300 dark:border-zinc-600 rounded bg-white dark:bg-zinc-800 text-gray-900 dark:text-white placeholder-gray-400 dark:placeholder-zinc-500\"\n />\n <button\n type=\"button\"\n onClick={() => setShowKey(!showKey)}\n className=\"absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-zinc-300\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n {showKey ? (\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21\"\n />\n ) : (\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z\"\n />\n )}\n </svg>\n </button>\n </div>\n </div>\n </div>\n <div className=\"flex items-center\">\n <button\n onClick={handleToggle}\n className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${\n isEnabled ? \"bg-teal-600\" : \"bg-gray-300 dark:bg-zinc-600\"\n }`}\n >\n <span\n className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${\n isEnabled ? \"translate-x-6\" : \"translate-x-1\"\n }`}\n />\n </button>\n </div>\n </div>\n );\n}\n\nfunction LocalProviderRow({ provider }: { provider: (typeof LOCAL_PROVIDERS)[number] }) {\n const ai = useSettingsStore((s) => s.ai);\n const setAIProvider = useSettingsStore((s) => s.setAIProvider);\n\n const config = ai[provider.id];\n const isEnabled = config?.enabled ?? false;\n const baseUrl = (config as { baseUrl?: string })?.baseUrl ?? provider.defaultUrl;\n\n const [localUrl, setLocalUrl] = useState(baseUrl);\n\n const handleToggle = () => {\n setAIProvider(provider.id, {\n baseUrl: localUrl,\n enabled: !isEnabled,\n });\n };\n\n const handleUrlChange = (value: string) => {\n setLocalUrl(value);\n setAIProvider(provider.id, {\n baseUrl: value,\n enabled: isEnabled,\n });\n };\n\n return (\n <div className=\"flex items-start gap-4 p-4 border border-gray-200 dark:border-zinc-700 rounded-lg\">\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium text-gray-900 dark:text-white\">{provider.name}</span>\n <a\n href={provider.docsUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-xs text-teal-600 dark:text-teal-400 hover:underline\"\n >\n Docs\n </a>\n <span className=\"text-xs bg-green-100 dark:bg-green-900/50 text-green-700 dark:text-green-400 px-1.5 py-0.5 rounded\">\n Local\n </span>\n </div>\n <p className=\"text-sm text-gray-500 dark:text-zinc-400 mt-0.5\">{provider.description}</p>\n <div className=\"mt-2\">\n <input\n type=\"text\"\n value={localUrl}\n onChange={(e) => handleUrlChange(e.target.value)}\n placeholder={provider.defaultUrl}\n className=\"w-full px-3 py-1.5 text-sm border border-gray-300 dark:border-zinc-600 rounded bg-white dark:bg-zinc-800 text-gray-900 dark:text-white placeholder-gray-400 dark:placeholder-zinc-500\"\n />\n </div>\n </div>\n <div className=\"flex items-center\">\n <button\n onClick={handleToggle}\n className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${\n isEnabled ? \"bg-teal-600\" : \"bg-gray-300 dark:bg-zinc-600\"\n }`}\n >\n <span\n className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${\n isEnabled ? \"translate-x-6\" : \"translate-x-1\"\n }`}\n />\n </button>\n </div>\n </div>\n );\n}\n\nexport function AISettings() {\n const showSettings = useSettingsStore((s) => s.showSettings);\n const closeSettings = useSettingsStore((s) => s.closeSettings);\n\n if (!showSettings) return null;\n\n return (\n <div className=\"fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50\">\n <div className=\"bg-white dark:bg-zinc-800 rounded-lg shadow-xl max-w-xl w-full mx-4 max-h-[85vh] flex flex-col\">\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-gray-200 dark:border-zinc-700\">\n <div>\n <h2 className=\"text-lg font-semibold text-gray-900 dark:text-white\">\n AI Provider Settings\n </h2>\n <p className=\"text-sm text-gray-500 dark:text-zinc-400 mt-0.5\">\n Configure your AI providers for vision and text generation\n </p>\n </div>\n <button\n onClick={closeSettings}\n className=\"text-gray-500 dark:text-zinc-400 hover:text-gray-700 dark:hover:text-zinc-200\"\n >\n <svg className=\"h-6 w-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n </div>\n\n <div className=\"flex-1 overflow-y-auto p-6 space-y-6\">\n {/* Cloud Providers */}\n <section>\n <h3 className=\"text-sm font-medium text-gray-700 dark:text-zinc-300 mb-3\">\n Cloud Providers\n </h3>\n <div className=\"space-y-3\">\n {CLOUD_PROVIDERS.map((provider) => (\n <CloudProviderRow key={provider.id} provider={provider} />\n ))}\n </div>\n </section>\n\n {/* Local Providers */}\n <section>\n <h3 className=\"text-sm font-medium text-gray-700 dark:text-zinc-300 mb-3\">\n Local Providers\n </h3>\n <div className=\"space-y-3\">\n {LOCAL_PROVIDERS.map((provider) => (\n <LocalProviderRow key={provider.id} provider={provider} />\n ))}\n </div>\n </section>\n\n {/* Privacy Notice */}\n <div className=\"bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4\">\n <div className=\"flex items-start gap-3\">\n <svg\n className=\"w-5 h-5 text-blue-600 dark:text-blue-400 mt-0.5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z\"\n />\n </svg>\n <div>\n <p className=\"text-sm font-medium text-blue-900 dark:text-blue-300\">\n Your keys stay local\n </p>\n <p className=\"text-sm text-blue-700 dark:text-blue-400 mt-1\">\n API keys are stored in your browser only and sent directly to providers. They\n never pass through our servers.\n </p>\n </div>\n </div>\n </div>\n </div>\n\n <div className=\"flex justify-end px-6 py-4 border-t border-gray-200 dark:border-zinc-700\">\n <button\n onClick={closeSettings}\n className=\"px-4 py-2 text-sm font-medium text-white bg-teal-600 rounded-md hover:bg-teal-700\"\n >\n Done\n </button>\n </div>\n </div>\n </div>\n );\n}\n","import { useState, useRef, useEffect, useCallback } from \"react\";\nimport type {\n GenerateWorkflowMessage,\n GeneratedWorkflowData,\n GenerateStatusReason,\n GenerationPhase,\n GenerationSSEEvent,\n} from \"@teamflojo/floimg-studio-shared\";\nimport { getGenerateStatus } from \"../api/client\";\nimport { createSSEConnection, type SSEConnection } from \"../api/sse\";\n\n// Module-level connection reference for cancellation\n// (Not in component state because SSEConnection is not serializable)\nlet activeGenerationConnection: SSEConnection | null = null;\n\ninterface AIChatProps {\n isOpen: boolean;\n onClose: () => void;\n onApplyWorkflow: (workflow: GeneratedWorkflowData) => void;\n}\n\nexport function AIChat({ isOpen, onClose, onApplyWorkflow }: AIChatProps) {\n const [messages, setMessages] = useState<GenerateWorkflowMessage[]>([]);\n const [input, setInput] = useState(\"\");\n const [isLoading, setIsLoading] = useState(false);\n const [generationPhase, setGenerationPhase] = useState<GenerationPhase | null>(null);\n const [generationMessage, setGenerationMessage] = useState(\"\");\n const [error, setError] = useState<string | null>(null);\n const [isAvailable, setIsAvailable] = useState<boolean | null>(null);\n const [statusMessage, setStatusMessage] = useState(\"\");\n const [statusReason, setStatusReason] = useState<GenerateStatusReason | undefined>();\n const [isCloudDeployment, setIsCloudDeployment] = useState(false);\n const [supportUrl, setSupportUrl] = useState<string | undefined>();\n const messagesEndRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLTextAreaElement>(null);\n\n // Check if generation is available on mount\n useEffect(() => {\n if (isOpen && isAvailable === null) {\n getGenerateStatus()\n .then((status) => {\n setIsAvailable(status.available);\n setStatusMessage(status.message);\n setStatusReason(status.reason);\n setIsCloudDeployment(status.isCloudDeployment ?? false);\n setSupportUrl(status.supportUrl);\n })\n .catch(() => {\n setIsAvailable(false);\n setStatusMessage(\"Failed to check AI availability\");\n setStatusReason(\"service_unavailable\");\n });\n }\n }, [isOpen, isAvailable]);\n\n // Focus input when opened\n useEffect(() => {\n if (isOpen && inputRef.current) {\n inputRef.current.focus();\n }\n }, [isOpen]);\n\n // Scroll to bottom on new messages\n useEffect(() => {\n messagesEndRef.current?.scrollIntoView({ behavior: \"smooth\" });\n }, [messages]);\n\n const handleSubmit = useCallback(() => {\n if (!input.trim() || isLoading) return;\n\n const userMessage: GenerateWorkflowMessage = {\n role: \"user\",\n content: input.trim(),\n timestamp: Date.now(),\n };\n\n setMessages((prev) => [...prev, userMessage]);\n setInput(\"\");\n setIsLoading(true);\n setError(null);\n setGenerationPhase(null);\n setGenerationMessage(\"\");\n\n let receivedWorkflow: GeneratedWorkflowData | undefined;\n\n activeGenerationConnection = createSSEConnection<GenerationSSEEvent>(\n \"/api/generate/workflow/stream\",\n { prompt: userMessage.content, history: messages },\n {\n onMessage: (event) => {\n if (event.type === \"generation.started\") {\n // Started - no visible change needed\n }\n\n if (event.type === \"generation.progress\") {\n setGenerationPhase(event.data.phase);\n setGenerationMessage(event.data.message);\n }\n\n if (event.type === \"generation.completed\") {\n receivedWorkflow = event.data;\n }\n\n if (event.type === \"generation.error\") {\n setError(event.data.error);\n }\n },\n onError: (err) => {\n activeGenerationConnection = null;\n setError(err.message || \"Failed to generate workflow\");\n setIsLoading(false);\n setGenerationPhase(null);\n },\n onClose: () => {\n activeGenerationConnection = null;\n // Stream completed - add the assistant message\n const assistantMessage: GenerateWorkflowMessage = {\n role: \"assistant\",\n content: receivedWorkflow\n ? \"I've created a workflow based on your description. Click 'Apply to Canvas' to use it.\"\n : \"I couldn't generate a workflow. Please try a different description.\",\n workflow: receivedWorkflow,\n timestamp: Date.now(),\n };\n\n setMessages((prev) => [...prev, assistantMessage]);\n setIsLoading(false);\n setGenerationPhase(null);\n setGenerationMessage(\"\");\n },\n }\n );\n }, [input, isLoading, messages]);\n\n const handleCancelGeneration = useCallback(() => {\n if (activeGenerationConnection) {\n activeGenerationConnection.abort();\n activeGenerationConnection = null;\n }\n setIsLoading(false);\n setGenerationPhase(null);\n setGenerationMessage(\"\");\n }, []);\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n handleSubmit();\n }\n };\n\n const handleApply = (workflow: GeneratedWorkflowData) => {\n onApplyWorkflow(workflow);\n onClose();\n };\n\n const handleNewChat = () => {\n setMessages([]);\n setError(null);\n };\n\n if (!isOpen) return null;\n\n return (\n <div className=\"fixed inset-0 bg-black/50 flex items-center justify-center z-50\">\n <div className=\"bg-white dark:bg-zinc-800 rounded-lg shadow-xl w-full max-w-2xl mx-4 h-[80vh] flex flex-col\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-gray-200 dark:border-zinc-700\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex items-center gap-2\">\n <svg\n className=\"h-5 w-5 text-teal-600\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z\"\n />\n </svg>\n <h3 className=\"text-lg font-semibold text-gray-900 dark:text-white\">\n AI Workflow Generator\n </h3>\n </div>\n <span className=\"text-xs bg-teal-100 dark:bg-teal-900 text-teal-700 dark:text-teal-300 px-2 py-0.5 rounded\">\n Gemini 3 Pro\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n {messages.length > 0 && (\n <button\n onClick={handleNewChat}\n className=\"p-2 text-gray-500 dark:text-zinc-400 hover:text-gray-700 dark:hover:text-zinc-200 hover:bg-gray-100 dark:hover:bg-zinc-700 rounded\"\n title=\"New Chat\"\n >\n <svg className=\"h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 4v16m8-8H4\"\n />\n </svg>\n </button>\n )}\n <button\n onClick={onClose}\n className=\"p-2 text-gray-500 dark:text-zinc-400 hover:text-gray-700 dark:hover:text-zinc-200 hover:bg-gray-100 dark:hover:bg-zinc-700 rounded\"\n >\n <svg className=\"h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n </div>\n </div>\n\n {/* Messages */}\n <div className=\"flex-1 overflow-auto p-4 space-y-4\">\n {isAvailable === false && (\n <div className=\"bg-amber-50 dark:bg-amber-900/30 border border-amber-200 dark:border-amber-800 rounded-lg p-4\">\n <div className=\"flex items-start gap-3\">\n {/* Icon varies by reason */}\n {statusReason === \"tier_limit\" ? (\n <svg\n className=\"h-5 w-5 text-amber-600 dark:text-amber-400 mt-0.5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z\"\n />\n </svg>\n ) : (\n <svg\n className=\"h-5 w-5 text-amber-600 dark:text-amber-400 mt-0.5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n )}\n <div>\n <p className=\"font-medium text-amber-800 dark:text-amber-200\">\n {statusReason === \"tier_limit\"\n ? \"AI Workflow Generation Not Available\"\n : \"AI Generation Not Available\"}\n </p>\n <p className=\"text-sm text-amber-700 dark:text-amber-300 mt-1\">{statusMessage}</p>\n\n {/* Context-aware actions */}\n <div className=\"flex flex-col sm:flex-row gap-2 mt-3\">\n {statusReason === \"tier_limit\" && (\n <a\n href=\"/pricing\"\n className=\"text-sm font-medium text-teal-600 hover:text-teal-700 dark:text-teal-400 dark:hover:text-teal-300\"\n >\n View Plans\n </a>\n )}\n {statusReason === \"service_unavailable\" && supportUrl && (\n <a\n href={supportUrl}\n className=\"text-sm font-medium text-amber-700 hover:text-amber-800 dark:text-amber-400 dark:hover:text-amber-300\"\n >\n Contact Support\n </a>\n )}\n {statusReason === \"not_configured\" && !isCloudDeployment && (\n <a\n href=\"https://floimg.com/docs/studio/ai-workflows\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm font-medium text-teal-600 hover:text-teal-700 dark:text-teal-400 dark:hover:text-teal-300\"\n >\n View Setup Guide\n </a>\n )}\n </div>\n </div>\n </div>\n </div>\n )}\n\n {messages.length === 0 && isAvailable !== false && (\n <div className=\"text-center py-8\">\n <div className=\"inline-flex items-center justify-center w-16 h-16 bg-teal-100 dark:bg-teal-900/50 rounded-full mb-4\">\n <svg\n className=\"h-8 w-8 text-teal-600 dark:text-teal-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z\"\n />\n </svg>\n </div>\n <h4 className=\"text-lg font-medium text-gray-900 dark:text-white mb-2\">\n Describe your workflow\n </h4>\n <p className=\"text-sm text-gray-500 dark:text-zinc-400 max-w-md mx-auto\">\n Tell me what you want to create and I&apos;ll generate a workflow for you. For\n example:\n </p>\n <div className=\"mt-4 space-y-2\">\n {[\n \"Generate an image of a sunset and resize it to 800x600\",\n \"Use Gemini text to generate 3 creative image prompts about space exploration, then generate images from each prompt\",\n \"Generate an image with Gemini, then use it as a reference to create a variation with different lighting\",\n \"Create a product mockup: generate a minimalist logo, then composite it onto a t-shirt image\",\n \"Build an AI art pipeline: generate a base image, apply artistic style transfer, then upscale to 4K\",\n ].map((example, i) => (\n <button\n key={i}\n onClick={() => setInput(example)}\n className=\"block w-full text-left text-sm px-4 py-2 bg-gray-100 dark:bg-zinc-700 hover:bg-gray-200 dark:hover:bg-zinc-600 rounded-lg text-gray-700 dark:text-zinc-300 transition-colors\"\n >\n &quot;{example}&quot;\n </button>\n ))}\n </div>\n </div>\n )}\n\n {messages.map((msg, idx) => (\n <div\n key={idx}\n className={`flex ${msg.role === \"user\" ? \"justify-end\" : \"justify-start\"}`}\n >\n <div\n className={`max-w-[80%] rounded-lg px-4 py-3 ${\n msg.role === \"user\"\n ? \"bg-teal-600 text-white\"\n : \"bg-gray-100 dark:bg-zinc-700 text-gray-900 dark:text-white\"\n }`}\n >\n <p className=\"text-sm whitespace-pre-wrap\">{msg.content}</p>\n\n {/* Workflow preview for assistant messages */}\n {msg.role === \"assistant\" && msg.workflow && (\n <div className=\"mt-3 pt-3 border-t border-gray-200 dark:border-zinc-600\">\n <div className=\"flex items-center justify-between mb-2\">\n <span className=\"text-xs font-medium text-gray-500 dark:text-zinc-400\">\n Generated Workflow\n </span>\n <button\n onClick={() => handleApply(msg.workflow!)}\n className=\"text-xs px-3 py-1 bg-teal-600 hover:bg-teal-700 text-white rounded transition-colors\"\n >\n Apply to Canvas\n </button>\n </div>\n <div className=\"bg-white dark:bg-zinc-800 rounded p-2 text-xs\">\n <div className=\"space-y-1\">\n {msg.workflow.nodes.map((node, nodeIdx) => (\n <div\n key={nodeIdx}\n className=\"flex items-center gap-2 text-gray-600 dark:text-zinc-300\"\n >\n <span className=\"font-mono bg-gray-100 dark:bg-zinc-700 px-1.5 py-0.5 rounded\">\n {node.nodeType.split(\":\").pop()}\n </span>\n {node.label && <span className=\"text-gray-400\">({node.label})</span>}\n </div>\n ))}\n {msg.workflow.edges.length > 0 && (\n <div className=\"text-gray-400 dark:text-zinc-500 pt-1\">\n {msg.workflow.edges.length} connection\n {msg.workflow.edges.length !== 1 ? \"s\" : \"\"}\n </div>\n )}\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n ))}\n\n {isLoading && (\n <div className=\"flex justify-start\">\n <div className=\"bg-gray-100 dark:bg-zinc-700 rounded-lg px-4 py-3\">\n <div className=\"flex items-center gap-3\">\n {/* Phase indicator */}\n <div className=\"flex items-center gap-2\">\n {generationPhase === \"analyzing\" && (\n <svg\n className=\"h-4 w-4 text-teal-500 animate-pulse\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"\n />\n </svg>\n )}\n {generationPhase === \"selecting_nodes\" && (\n <svg\n className=\"h-4 w-4 text-teal-500 animate-pulse\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z\"\n />\n </svg>\n )}\n {generationPhase === \"generating\" && (\n <svg\n className=\"h-4 w-4 text-teal-500 animate-spin\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"\n />\n </svg>\n )}\n {generationPhase === \"validating\" && (\n <svg\n className=\"h-4 w-4 text-teal-500 animate-pulse\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n )}\n {!generationPhase && (\n <div className=\"flex space-x-1\">\n <div className=\"w-2 h-2 bg-teal-400 rounded-full animate-bounce\" />\n <div\n className=\"w-2 h-2 bg-teal-400 rounded-full animate-bounce\"\n style={{ animationDelay: \"0.1s\" }}\n />\n <div\n className=\"w-2 h-2 bg-teal-400 rounded-full animate-bounce\"\n style={{ animationDelay: \"0.2s\" }}\n />\n </div>\n )}\n </div>\n <span className=\"text-sm text-gray-600 dark:text-zinc-300\">\n {generationMessage || \"Connecting...\"}\n </span>\n {/* Cancel button */}\n <button\n onClick={handleCancelGeneration}\n className=\"ml-2 px-2 py-1 text-xs font-medium text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/30 rounded transition-colors\"\n title=\"Cancel generation\"\n >\n Cancel\n </button>\n </div>\n {/* Progress steps */}\n {generationPhase && (\n <div className=\"flex items-center gap-1 mt-2\">\n <div\n className={`h-1 w-8 rounded-full ${generationPhase === \"analyzing\" || generationPhase === \"selecting_nodes\" || generationPhase === \"generating\" || generationPhase === \"validating\" ? \"bg-teal-500\" : \"bg-gray-300 dark:bg-zinc-600\"}`}\n />\n <div\n className={`h-1 w-8 rounded-full ${generationPhase === \"selecting_nodes\" || generationPhase === \"generating\" || generationPhase === \"validating\" ? \"bg-teal-500\" : \"bg-gray-300 dark:bg-zinc-600\"}`}\n />\n <div\n className={`h-1 w-8 rounded-full ${generationPhase === \"generating\" || generationPhase === \"validating\" ? \"bg-teal-500\" : \"bg-gray-300 dark:bg-zinc-600\"}`}\n />\n <div\n className={`h-1 w-8 rounded-full ${generationPhase === \"validating\" ? \"bg-teal-500\" : \"bg-gray-300 dark:bg-zinc-600\"}`}\n />\n </div>\n )}\n </div>\n </div>\n )}\n\n {error && (\n <div className=\"bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 rounded-lg p-3\">\n <p className=\"text-sm text-red-700 dark:text-red-300\">{error}</p>\n </div>\n )}\n\n <div ref={messagesEndRef} />\n </div>\n\n {/* Input */}\n <div className=\"border-t border-gray-200 dark:border-zinc-700 p-4\">\n <div className=\"flex gap-2\">\n <textarea\n ref={inputRef}\n value={input}\n onChange={(e) => setInput(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={\n isAvailable === false\n ? \"AI generation not available\"\n : \"Describe what workflow you want to create...\"\n }\n disabled={isLoading || isAvailable === false}\n rows={2}\n className=\"flex-1 resize-none rounded-lg border border-gray-300 dark:border-zinc-600 bg-white dark:bg-zinc-900 px-4 py-2 text-sm text-gray-900 dark:text-white placeholder-gray-400 dark:placeholder-zinc-500 focus:border-teal-500 focus:outline-none focus:ring-1 focus:ring-teal-500 disabled:opacity-50 disabled:cursor-not-allowed\"\n />\n <button\n onClick={handleSubmit}\n disabled={!input.trim() || isLoading || isAvailable === false}\n className=\"self-end px-4 py-2 bg-teal-600 hover:bg-teal-700 disabled:opacity-50 disabled:cursor-not-allowed text-white rounded-lg transition-colors\"\n >\n <svg className=\"h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 19l9 2-9-18-9 18 9-2zm0 0v-8\"\n />\n </svg>\n </button>\n </div>\n <p className=\"text-xs text-gray-400 dark:text-zinc-500 mt-2\">\n Press Enter to send, Shift+Enter for new line\n </p>\n </div>\n </div>\n </div>\n );\n}\n","import { useState, useCallback } from \"react\";\n\n// Size/depth limits to prevent browser freeze on large outputs\nconst MAX_JSON_DEPTH = 20;\nconst MAX_ARRAY_ITEMS = 500;\nconst LARGE_OUTPUT_THRESHOLD = 100_000; // 100KB\n\ninterface DataOutput {\n dataType: \"text\" | \"json\";\n content: string;\n parsed?: Record<string, unknown>;\n}\n\ninterface OutputInspectorProps {\n isOpen: boolean;\n onClose: () => void;\n nodeId: string;\n nodeLabel: string;\n output: DataOutput;\n}\n\nexport function OutputInspector({ isOpen, onClose, nodeLabel, output }: OutputInspectorProps) {\n const [viewMode, setViewMode] = useState<\"formatted\" | \"raw\">(\"formatted\");\n const [copied, setCopied] = useState(false);\n\n const handleCopy = useCallback(() => {\n const textToCopy =\n viewMode === \"formatted\" && output.parsed\n ? JSON.stringify(output.parsed, null, 2)\n : output.content;\n\n navigator.clipboard.writeText(textToCopy).then(() => {\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n });\n }, [viewMode, output]);\n\n if (!isOpen) return null;\n\n const hasFormattedView = output.dataType === \"json\" && output.parsed;\n\n return (\n <div className=\"fixed inset-0 bg-black/50 flex items-center justify-center z-50\">\n <div className=\"bg-white dark:bg-zinc-800 rounded-lg shadow-xl w-full max-w-3xl mx-4 max-h-[85vh] flex flex-col\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-gray-200 dark:border-zinc-700\">\n <div className=\"flex items-center gap-3\">\n <svg\n className=\"h-5 w-5 text-pink-500\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"\n />\n </svg>\n <div>\n <h3 className=\"text-lg font-semibold text-gray-900 dark:text-white\">\n {nodeLabel} Output\n </h3>\n <span className=\"text-xs text-gray-500 dark:text-zinc-400\">\n {output.dataType === \"json\" ? \"Structured JSON\" : \"Text\"}\n </span>\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n {/* View mode toggle */}\n {hasFormattedView && (\n <div className=\"flex bg-gray-100 dark:bg-zinc-700 rounded-lg p-0.5\">\n <button\n onClick={() => setViewMode(\"formatted\")}\n className={`px-3 py-1 text-sm rounded-md transition-colors ${\n viewMode === \"formatted\"\n ? \"bg-white dark:bg-zinc-600 text-gray-900 dark:text-white shadow-sm\"\n : \"text-gray-600 dark:text-zinc-400 hover:text-gray-900 dark:hover:text-white\"\n }`}\n >\n Formatted\n </button>\n <button\n onClick={() => setViewMode(\"raw\")}\n className={`px-3 py-1 text-sm rounded-md transition-colors ${\n viewMode === \"raw\"\n ? \"bg-white dark:bg-zinc-600 text-gray-900 dark:text-white shadow-sm\"\n : \"text-gray-600 dark:text-zinc-400 hover:text-gray-900 dark:hover:text-white\"\n }`}\n >\n Raw\n </button>\n </div>\n )}\n {/* Close button */}\n <button\n onClick={onClose}\n className=\"p-2 text-gray-500 dark:text-zinc-400 hover:text-gray-700 dark:hover:text-zinc-200 hover:bg-gray-100 dark:hover:bg-zinc-700 rounded\"\n >\n <svg className=\"h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n </div>\n </div>\n\n {/* Large output warning */}\n {output.content.length > LARGE_OUTPUT_THRESHOLD && (\n <div className=\"px-4 py-2 bg-amber-50 dark:bg-amber-900/20 border-b border-amber-200 dark:border-amber-800 flex items-center gap-2\">\n <svg\n className=\"h-4 w-4 text-amber-600 dark:text-amber-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n <span className=\"text-sm text-amber-700 dark:text-amber-300\">\n Large output ({Math.round(output.content.length / 1024)}KB) - rendering may be slow\n </span>\n </div>\n )}\n\n {/* Content */}\n <div className=\"flex-1 overflow-auto p-4\">\n {viewMode === \"formatted\" && hasFormattedView ? (\n <JsonTree data={output.parsed!} />\n ) : (\n <pre className=\"whitespace-pre-wrap font-mono text-sm text-gray-800 dark:text-zinc-200 bg-gray-50 dark:bg-zinc-900 rounded-lg p-4 overflow-auto\">\n {output.content}\n </pre>\n )}\n </div>\n\n {/* Footer */}\n <div className=\"flex items-center justify-between px-4 py-3 border-t border-gray-200 dark:border-zinc-700\">\n <span className=\"text-xs text-gray-500 dark:text-zinc-400\">\n {output.content.length.toLocaleString()} characters\n </span>\n <button\n onClick={handleCopy}\n className=\"flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-teal-600 dark:text-teal-400 hover:bg-teal-50 dark:hover:bg-teal-900/30 rounded-lg transition-colors\"\n >\n {copied ? (\n <>\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M5 13l4 4L19 7\"\n />\n </svg>\n Copied!\n </>\n ) : (\n <>\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\"\n />\n </svg>\n Copy to Clipboard\n </>\n )}\n </button>\n </div>\n </div>\n </div>\n );\n}\n\n// Simple JSON tree viewer component with depth/size limits\nfunction JsonTree({ data }: { data: Record<string, unknown> }) {\n return (\n <div className=\"font-mono text-sm\">\n <JsonNode value={data} depth={0} maxDepth={MAX_JSON_DEPTH} />\n </div>\n );\n}\n\ninterface JsonNodeProps {\n value: unknown;\n depth: number;\n keyName?: string;\n maxDepth: number;\n}\n\nfunction JsonNode({ value, depth, keyName, maxDepth }: JsonNodeProps) {\n const indent = depth * 16;\n\n // Check depth limit\n if (depth >= maxDepth) {\n return (\n <div style={{ marginLeft: indent }} className=\"py-0.5\">\n {keyName && <span className=\"text-pink-600 dark:text-pink-400\">&quot;{keyName}&quot;</span>}\n {keyName && <span className=\"text-gray-600 dark:text-zinc-400\">: </span>}\n <span className=\"text-zinc-500 italic\">[max depth reached]</span>\n </div>\n );\n }\n\n if (value === null) {\n return (\n <div style={{ marginLeft: indent }} className=\"py-0.5\">\n {keyName && <span className=\"text-pink-600 dark:text-pink-400\">&quot;{keyName}&quot;</span>}\n {keyName && <span className=\"text-gray-600 dark:text-zinc-400\">: </span>}\n <span className=\"text-gray-500 dark:text-zinc-500\">null</span>\n </div>\n );\n }\n\n if (typeof value === \"boolean\") {\n return (\n <div style={{ marginLeft: indent }} className=\"py-0.5\">\n {keyName && <span className=\"text-pink-600 dark:text-pink-400\">&quot;{keyName}&quot;</span>}\n {keyName && <span className=\"text-gray-600 dark:text-zinc-400\">: </span>}\n <span className=\"text-blue-600 dark:text-blue-400\">{value.toString()}</span>\n </div>\n );\n }\n\n if (typeof value === \"number\") {\n return (\n <div style={{ marginLeft: indent }} className=\"py-0.5\">\n {keyName && <span className=\"text-pink-600 dark:text-pink-400\">&quot;{keyName}&quot;</span>}\n {keyName && <span className=\"text-gray-600 dark:text-zinc-400\">: </span>}\n <span className=\"text-green-600 dark:text-green-400\">{value}</span>\n </div>\n );\n }\n\n if (typeof value === \"string\") {\n // Truncate long strings in the tree view\n const displayValue = value.length > 100 ? value.slice(0, 100) + \"...\" : value;\n return (\n <div style={{ marginLeft: indent }} className=\"py-0.5\">\n {keyName && <span className=\"text-pink-600 dark:text-pink-400\">&quot;{keyName}&quot;</span>}\n {keyName && <span className=\"text-gray-600 dark:text-zinc-400\">: </span>}\n <span className=\"text-amber-600 dark:text-amber-400\">&quot;{displayValue}&quot;</span>\n </div>\n );\n }\n\n if (Array.isArray(value)) {\n const itemsToRender = value.slice(0, MAX_ARRAY_ITEMS);\n const hiddenCount = value.length - itemsToRender.length;\n\n return (\n <div style={{ marginLeft: indent }}>\n {keyName && (\n <div className=\"py-0.5\">\n <span className=\"text-pink-600 dark:text-pink-400\">&quot;{keyName}&quot;</span>\n <span className=\"text-gray-600 dark:text-zinc-400\">: </span>\n <span className=\"text-gray-500 dark:text-zinc-500\">[{value.length} items]</span>\n </div>\n )}\n {!keyName && <span className=\"text-gray-500 dark:text-zinc-500 py-0.5 block\">[</span>}\n {itemsToRender.map((item, index) => (\n <JsonNode key={index} value={item} depth={depth + 1} maxDepth={maxDepth} />\n ))}\n {hiddenCount > 0 && (\n <div style={{ marginLeft: (depth + 1) * 16 }} className=\"py-0.5 text-zinc-500 italic\">\n ...and {hiddenCount} more items\n </div>\n )}\n {!keyName && <span className=\"text-gray-500 dark:text-zinc-500 py-0.5 block\">]</span>}\n </div>\n );\n }\n\n if (typeof value === \"object\") {\n const entries = Object.entries(value);\n return (\n <div style={{ marginLeft: indent }}>\n {keyName && (\n <div className=\"py-0.5\">\n <span className=\"text-pink-600 dark:text-pink-400\">&quot;{keyName}&quot;</span>\n <span className=\"text-gray-600 dark:text-zinc-400\">: </span>\n <span className=\"text-gray-500 dark:text-zinc-500\">{\"{\"}</span>\n </div>\n )}\n {!keyName && <span className=\"text-gray-500 dark:text-zinc-500 py-0.5 block\">{\"{\"}</span>}\n {entries.map(([key, val]) => (\n <JsonNode key={key} value={val} depth={depth + 1} keyName={key} maxDepth={maxDepth} />\n ))}\n <div style={{ marginLeft: keyName ? 0 : indent }} className=\"py-0.5\">\n <span className=\"text-gray-500 dark:text-zinc-500\">{\"}\"}</span>\n </div>\n </div>\n );\n }\n\n return null;\n}\n","/**\n * KeyBadge - Displays keyboard shortcut keys as styled badges\n * Platform-aware (shows ⌘ on Mac, Ctrl on Windows)\n */\n\nimport { bindingToKeys } from \"../lib/keyboard/platformUtils\";\n\ninterface KeyBadgeProps {\n /** Shortcut binding string (e.g., 'mod+s', 'mod+shift+k') */\n binding: string | null;\n /** Optional additional className */\n className?: string;\n /** Size variant */\n size?: \"sm\" | \"md\";\n}\n\n/**\n * Displays a keyboard shortcut as styled key badges\n * Automatically converts platform-agnostic bindings to platform-specific display\n */\nexport function KeyBadge({ binding, className = \"\", size = \"md\" }: KeyBadgeProps) {\n if (!binding) return null;\n\n const keys = bindingToKeys(binding);\n\n if (keys.length === 0) return null;\n\n const sizeClasses = {\n sm: \"px-1 py-0.5 text-[10px] min-w-[16px]\",\n md: \"px-1.5 py-0.5 text-xs min-w-[20px]\",\n };\n\n return (\n <span className={`inline-flex items-center gap-0.5 ${className}`}>\n {keys.map((key, index) => (\n <kbd\n key={index}\n className={`\n ${sizeClasses[size]}\n inline-flex items-center justify-center\n font-mono font-medium\n bg-zinc-200 dark:bg-zinc-700\n text-zinc-600 dark:text-zinc-300\n border border-zinc-300 dark:border-zinc-600\n rounded\n shadow-sm\n `}\n >\n {key}\n </kbd>\n ))}\n </span>\n );\n}\n\n/**\n * Displays a shortcut inline with action text\n * Example: \"Save Workflow\" with \"⌘S\" badge\n */\ninterface ShortcutLabelProps {\n /** Action name */\n label: string;\n /** Shortcut binding */\n binding: string | null;\n /** Optional additional className for the container */\n className?: string;\n}\n\nexport function ShortcutLabel({ label, binding, className = \"\" }: ShortcutLabelProps) {\n return (\n <span className={`inline-flex items-center gap-2 ${className}`}>\n <span>{label}</span>\n {binding && <KeyBadge binding={binding} size=\"sm\" />}\n </span>\n );\n}\n","/**\n * Focus trap hook for modals and dialogs\n * Keeps focus within the modal when tab navigating\n */\n\nimport { useEffect, useRef, useCallback } from \"react\";\n\nconst FOCUSABLE_SELECTORS = [\n \"a[href]\",\n \"button:not([disabled])\",\n \"input:not([disabled])\",\n \"select:not([disabled])\",\n \"textarea:not([disabled])\",\n '[tabindex]:not([tabindex=\"-1\"])',\n].join(\", \");\n\nexport function useFocusTrap(isActive: boolean) {\n const containerRef = useRef<HTMLDivElement>(null);\n const previousActiveElement = useRef<HTMLElement | null>(null);\n\n // Get all focusable elements within the container\n const getFocusableElements = useCallback(() => {\n if (!containerRef.current) return [];\n return Array.from(\n containerRef.current.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTORS)\n ).filter((el) => el.offsetParent !== null); // Filter out hidden elements\n }, []);\n\n useEffect(() => {\n if (!isActive) return;\n\n // Save the currently focused element to restore later\n previousActiveElement.current = document.activeElement as HTMLElement;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key !== \"Tab\") return;\n\n const focusableElements = getFocusableElements();\n if (focusableElements.length === 0) return;\n\n const firstElement = focusableElements[0];\n const lastElement = focusableElements[focusableElements.length - 1];\n\n // Shift + Tab from first element -> go to last\n if (e.shiftKey && document.activeElement === firstElement) {\n e.preventDefault();\n lastElement.focus();\n return;\n }\n\n // Tab from last element -> go to first\n if (!e.shiftKey && document.activeElement === lastElement) {\n e.preventDefault();\n firstElement.focus();\n return;\n }\n };\n\n document.addEventListener(\"keydown\", handleKeyDown);\n\n // Focus the first focusable element\n const focusableElements = getFocusableElements();\n if (focusableElements.length > 0) {\n // Defer to allow modal to render\n window.requestAnimationFrame(() => {\n focusableElements[0].focus();\n });\n }\n\n return () => {\n document.removeEventListener(\"keydown\", handleKeyDown);\n // Restore focus to the previously focused element\n if (previousActiveElement.current?.focus) {\n previousActiveElement.current.focus();\n }\n };\n }, [isActive, getFocusableElements]);\n\n return containerRef;\n}\n","/**\n * CommandPalette - Raycast/Linear-style command palette\n * Triggered by Cmd+K for quick action discovery and execution\n */\n\nimport { useState, useCallback, useEffect, useMemo, useDeferredValue, useId, useRef } from \"react\";\nimport { useSettingsStore } from \"../stores/settingsStore\";\nimport { useWorkflowStore } from \"../stores/workflowStore\";\nimport { KeyBadge } from \"./KeyBadge\";\nimport { SHORTCUT_DEFINITIONS, CATEGORY_NAMES } from \"../lib/keyboard/shortcuts\";\nimport type { ShortcutAction, ShortcutCategory, Command } from \"../lib/keyboard/types\";\nimport { useFocusTrap } from \"../lib/useFocusTrap\";\n\n/** Get reason why a command is disabled */\nfunction getDisabledReason(\n cmd: Command,\n nodes: unknown[],\n selectedNodeId: string | null,\n executionStatus: string\n): string | null {\n switch (cmd.id) {\n case \"save\":\n case \"exportWorkflow\":\n return nodes.length === 0 ? \"Add nodes to your workflow first\" : null;\n case \"execute\":\n if (nodes.length === 0) return \"Add nodes to your workflow first\";\n if (executionStatus === \"running\") return \"Workflow is already running\";\n return null;\n case \"duplicate\":\n return !selectedNodeId ? \"Select a node first\" : null;\n default:\n return null;\n }\n}\n\ninterface CommandPaletteProps {\n /** Callback to toggle AI Chat (since it's local state in App) */\n onToggleAIChat?: () => void;\n}\n\nexport function CommandPalette({ onToggleAIChat }: CommandPaletteProps) {\n const showPalette = useSettingsStore((s) => s.showCommandPalette);\n const closePalette = useSettingsStore((s) => s.closeCommandPalette);\n const keyboardSettings = useSettingsStore((s) => s.keyboard);\n\n const [searchQuery, setSearchQuery] = useState(\"\");\n const deferredSearchQuery = useDeferredValue(searchQuery);\n const [selectedIndex, setSelectedIndex] = useState(0);\n const titleId = useId();\n const focusTrapRef = useFocusTrap(showPalette);\n const listRef = useRef<HTMLDivElement>(null);\n\n // Get workflow store actions for commands\n const nodes = useWorkflowStore((s) => s.nodes);\n const selectedNodeId = useWorkflowStore((s) => s.selectedNodeId);\n const execution = useWorkflowStore((s) => s.execution);\n const saveWorkflow = useWorkflowStore((s) => s.saveWorkflow);\n const execute = useWorkflowStore((s) => s.execute);\n const duplicateNode = useWorkflowStore((s) => s.duplicateNode);\n const toggleLibrary = useWorkflowStore((s) => s.toggleLibrary);\n const newWorkflow = useWorkflowStore((s) => s.newWorkflow);\n const openSettings = useSettingsStore((s) => s.openSettings);\n const openShortcutsModal = useSettingsStore((s) => s.openShortcutsModal);\n const openExport = useSettingsStore((s) => s.openExport);\n const openImport = useSettingsStore((s) => s.openImport);\n const requestNewWorkflow = useSettingsStore((s) => s.requestNewWorkflow);\n const hasUnsavedChanges = useWorkflowStore((s) => s.hasUnsavedChanges);\n\n // Get effective binding for an action\n const getEffectiveBinding = useCallback(\n (action: ShortcutAction): string | null => {\n const def = SHORTCUT_DEFINITIONS.find((d) => d.action === action);\n if (!def) return null;\n if (keyboardSettings?.shortcuts?.[action] !== undefined) {\n return keyboardSettings.shortcuts[action] ?? null;\n }\n return def.defaultBinding;\n },\n [keyboardSettings]\n );\n\n // Build command list\n const commands: Command[] = useMemo(() => {\n return [\n // Workflow commands\n {\n id: \"save\",\n name: \"Save Workflow\",\n category: \"workflow\",\n shortcut: getEffectiveBinding(\"save\") ?? undefined,\n action: () => {\n if (nodes.length > 0) saveWorkflow();\n },\n enabled: () => nodes.length > 0,\n keywords: [\"save\", \"commit\"],\n },\n {\n id: \"execute\",\n name: \"Execute Workflow\",\n category: \"workflow\",\n shortcut: getEffectiveBinding(\"execute\") ?? undefined,\n action: () => {\n if (nodes.length > 0 && execution.status !== \"running\") execute();\n },\n enabled: () => nodes.length > 0 && execution.status !== \"running\",\n keywords: [\"run\", \"execute\", \"start\"],\n },\n {\n id: \"newWorkflow\",\n name: \"New Workflow\",\n category: \"workflow\",\n shortcut: getEffectiveBinding(\"newWorkflow\") ?? undefined,\n action: () => {\n closePalette?.();\n requestNewWorkflow(hasUnsavedChanges, newWorkflow);\n },\n keywords: [\"new\", \"create\", \"blank\"],\n },\n {\n id: \"exportWorkflow\",\n name: \"Export Workflow\",\n category: \"workflow\",\n shortcut: getEffectiveBinding(\"exportWorkflow\") ?? undefined,\n action: () => {\n if (nodes.length > 0) openExport?.();\n },\n enabled: () => nodes.length > 0,\n keywords: [\"export\", \"download\", \"yaml\", \"javascript\"],\n },\n {\n id: \"importWorkflow\",\n name: \"Import Workflow\",\n category: \"workflow\",\n shortcut: getEffectiveBinding(\"importWorkflow\") ?? undefined,\n action: () => openImport?.(),\n keywords: [\"import\", \"upload\", \"load\"],\n },\n\n // Editing commands\n {\n id: \"duplicate\",\n name: \"Duplicate Node\",\n category: \"editing\",\n shortcut: getEffectiveBinding(\"duplicate\") ?? undefined,\n action: () => {\n if (selectedNodeId) duplicateNode(selectedNodeId);\n },\n enabled: () => !!selectedNodeId,\n keywords: [\"duplicate\", \"copy\", \"clone\"],\n },\n\n // UI commands\n {\n id: \"toggleLibrary\",\n name: \"Toggle Workflow Library\",\n category: \"ui\",\n shortcut: getEffectiveBinding(\"toggleLibrary\") ?? undefined,\n action: () => toggleLibrary(),\n keywords: [\"library\", \"workflows\", \"saved\"],\n },\n {\n id: \"toggleAIChat\",\n name: \"Toggle AI Chat\",\n category: \"ui\",\n shortcut: getEffectiveBinding(\"toggleAIChat\") ?? undefined,\n action: () => onToggleAIChat?.(),\n keywords: [\"ai\", \"chat\", \"generate\", \"assistant\"],\n },\n {\n id: \"settings\",\n name: \"Open Settings\",\n category: \"ui\",\n shortcut: getEffectiveBinding(\"settings\") ?? undefined,\n action: () => openSettings(),\n keywords: [\"settings\", \"preferences\", \"api\", \"keys\"],\n },\n {\n id: \"showShortcuts\",\n name: \"Show Keyboard Shortcuts\",\n category: \"ui\",\n shortcut: getEffectiveBinding(\"showShortcuts\") ?? undefined,\n action: () => openShortcutsModal?.(),\n keywords: [\"shortcuts\", \"keyboard\", \"hotkeys\", \"help\"],\n },\n ];\n }, [\n nodes.length,\n selectedNodeId,\n execution.status,\n hasUnsavedChanges,\n saveWorkflow,\n execute,\n newWorkflow,\n duplicateNode,\n toggleLibrary,\n openSettings,\n openShortcutsModal,\n openExport,\n openImport,\n onToggleAIChat,\n getEffectiveBinding,\n closePalette,\n requestNewWorkflow,\n ]);\n\n // Filter commands by search query (using deferred value for smooth typing)\n const filteredCommands = useMemo(() => {\n if (!deferredSearchQuery.trim()) return commands;\n\n const query = deferredSearchQuery.toLowerCase();\n return commands.filter((cmd) => {\n const nameMatch = cmd.name.toLowerCase().includes(query);\n const keywordMatch = cmd.keywords?.some((kw) => kw.toLowerCase().includes(query));\n return nameMatch || keywordMatch;\n });\n }, [commands, deferredSearchQuery]);\n\n // Group filtered commands by category\n const groupedCommands = useMemo(() => {\n const groups: Record<ShortcutCategory | \"nodes\", Command[]> = {\n workflow: [],\n editing: [],\n canvas: [],\n ui: [],\n nodes: [],\n };\n\n for (const cmd of filteredCommands) {\n groups[cmd.category].push(cmd);\n }\n\n return groups;\n }, [filteredCommands]);\n\n // Reset selection when search changes\n useEffect(() => {\n setSelectedIndex(0);\n }, [deferredSearchQuery]);\n\n // Reset search when opening\n useEffect(() => {\n if (showPalette) {\n setSearchQuery(\"\");\n setSelectedIndex(0);\n }\n }, [showPalette]);\n\n // Keyboard navigation\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === \"Escape\") {\n closePalette?.();\n return;\n }\n\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setSelectedIndex((i) => Math.min(i + 1, filteredCommands.length - 1));\n return;\n }\n\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setSelectedIndex((i) => Math.max(i - 1, 0));\n return;\n }\n\n if (e.key === \"Enter\") {\n e.preventDefault();\n const cmd = filteredCommands[selectedIndex];\n if (cmd && (!cmd.enabled || cmd.enabled())) {\n cmd.action();\n closePalette?.();\n }\n return;\n }\n },\n [filteredCommands, selectedIndex, closePalette]\n );\n\n // Scroll selected item into view\n useEffect(() => {\n if (listRef.current) {\n const selectedEl = listRef.current.querySelector(`[data-index=\"${selectedIndex}\"]`);\n if (selectedEl) {\n selectedEl.scrollIntoView({ block: \"nearest\" });\n }\n }\n }, [selectedIndex]);\n\n if (!showPalette) return null;\n\n const categoryOrder: (ShortcutCategory | \"nodes\")[] = [\n \"workflow\",\n \"editing\",\n \"ui\",\n \"canvas\",\n \"nodes\",\n ];\n\n // Calculate flat index for each command\n let flatIndex = 0;\n const getCommandIndex = () => flatIndex++;\n\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-start justify-center pt-[15vh] bg-black/50\"\n onClick={(e) => {\n if (e.target === e.currentTarget) closePalette?.();\n }}\n >\n <div\n ref={focusTrapRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n className=\"bg-white dark:bg-zinc-800 rounded-xl shadow-2xl max-w-xl w-full mx-4 overflow-hidden\"\n >\n {/* Search input */}\n <div className=\"flex items-center gap-3 px-4 py-3 border-b border-zinc-200 dark:border-zinc-700\">\n <svg\n className=\"w-5 h-5 text-zinc-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"\n />\n </svg>\n <label id={titleId} className=\"sr-only\">\n Command palette\n </label>\n <input\n type=\"text\"\n placeholder=\"Type a command or search...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n onKeyDown={handleKeyDown}\n aria-label=\"Search commands\"\n autoFocus\n className=\"flex-1 bg-transparent text-zinc-900 dark:text-zinc-100 placeholder-zinc-500 focus:outline-none text-sm\"\n />\n <kbd className=\"px-1.5 py-0.5 text-xs font-mono bg-zinc-100 dark:bg-zinc-700 text-zinc-500 border border-zinc-200 dark:border-zinc-600 rounded\">\n Esc\n </kbd>\n </div>\n\n {/* Command list */}\n <div ref={listRef} className=\"max-h-80 overflow-y-auto py-2\">\n {filteredCommands.length === 0 ? (\n <div className=\"px-4 py-8 text-center text-zinc-500 dark:text-zinc-400 text-sm\">\n No commands found\n </div>\n ) : (\n categoryOrder.map((category) => {\n const cmds = groupedCommands[category];\n if (cmds.length === 0) return null;\n\n return (\n <div key={category} className=\"mb-2\">\n <div className=\"px-4 py-1 text-xs font-semibold text-zinc-500 dark:text-zinc-400 uppercase tracking-wider\">\n {CATEGORY_NAMES[category as ShortcutCategory] || category}\n </div>\n {cmds.map((cmd) => {\n const index = getCommandIndex();\n const isSelected = index === selectedIndex;\n const isEnabled = !cmd.enabled || cmd.enabled();\n const disabledReason = !isEnabled\n ? getDisabledReason(cmd, nodes, selectedNodeId, execution.status)\n : null;\n\n return (\n <button\n key={cmd.id}\n data-index={index}\n onClick={() => {\n if (isEnabled) {\n cmd.action();\n closePalette?.();\n }\n }}\n disabled={!isEnabled}\n title={disabledReason ?? undefined}\n className={`\n w-full flex items-center justify-between px-4 py-2 text-left\n ${isSelected ? \"bg-teal-50 dark:bg-teal-900/30\" : \"hover:bg-zinc-50 dark:hover:bg-zinc-700/50\"}\n ${!isEnabled ? \"opacity-50 cursor-not-allowed\" : \"cursor-pointer\"}\n `}\n >\n <span\n className={`text-sm ${isSelected ? \"text-teal-700 dark:text-teal-300\" : \"text-zinc-800 dark:text-zinc-200\"}`}\n >\n {cmd.name}\n </span>\n {cmd.shortcut && <KeyBadge binding={cmd.shortcut} size=\"sm\" />}\n </button>\n );\n })}\n </div>\n );\n })\n )}\n </div>\n\n {/* Footer hint */}\n <div className=\"px-4 py-2 border-t border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-800/50\">\n <div className=\"flex items-center gap-4 text-xs text-zinc-500 dark:text-zinc-400\">\n <span className=\"flex items-center gap-1\">\n <kbd className=\"px-1 py-0.5 bg-zinc-200 dark:bg-zinc-700 rounded text-[10px]\">↑</kbd>\n <kbd className=\"px-1 py-0.5 bg-zinc-200 dark:bg-zinc-700 rounded text-[10px]\">↓</kbd>\n <span>navigate</span>\n </span>\n <span className=\"flex items-center gap-1\">\n <kbd className=\"px-1 py-0.5 bg-zinc-200 dark:bg-zinc-700 rounded text-[10px]\">↵</kbd>\n <span>select</span>\n </span>\n <span className=\"flex items-center gap-1\">\n <kbd className=\"px-1 py-0.5 bg-zinc-200 dark:bg-zinc-700 rounded text-[10px]\">\n esc\n </kbd>\n <span>close</span>\n </span>\n </div>\n </div>\n </div>\n </div>\n );\n}\n","/**\n * KeyboardShortcutsModal - Shows all available keyboard shortcuts\n * Triggered by Cmd+? or clicking help\n */\n\nimport { useState, useMemo, useId } from \"react\";\nimport { useSettingsStore } from \"../stores/settingsStore\";\nimport { KeyBadge } from \"./KeyBadge\";\nimport {\n SHORTCUT_DEFINITIONS,\n getShortcutsByCategory,\n CATEGORY_NAMES,\n} from \"../lib/keyboard/shortcuts\";\nimport type { ShortcutAction, ShortcutCategory } from \"../lib/keyboard/types\";\nimport { useFocusTrap } from \"../lib/useFocusTrap\";\n\nexport function KeyboardShortcutsModal() {\n const showModal = useSettingsStore((s) => s.showShortcutsModal);\n const closeModal = useSettingsStore((s) => s.closeShortcutsModal);\n const keyboardSettings = useSettingsStore((s) => s.keyboard);\n\n const [searchQuery, setSearchQuery] = useState(\"\");\n const titleId = useId();\n const focusTrapRef = useFocusTrap(showModal);\n\n // Get effective binding for an action\n const getEffectiveBinding = (action: ShortcutAction): string | null => {\n const def = SHORTCUT_DEFINITIONS.find((d) => d.action === action);\n if (!def) return null;\n\n // User override takes precedence\n if (keyboardSettings?.shortcuts?.[action] !== undefined) {\n return keyboardSettings.shortcuts[action] ?? null;\n }\n\n return def.defaultBinding;\n };\n\n // Group shortcuts by category\n const groupedShortcuts = useMemo(() => {\n const groups = getShortcutsByCategory();\n\n // Filter by search query\n if (searchQuery.trim()) {\n const query = searchQuery.toLowerCase();\n const filtered: Record<ShortcutCategory, typeof SHORTCUT_DEFINITIONS> = {\n workflow: [],\n editing: [],\n canvas: [],\n ui: [],\n };\n\n for (const category of Object.keys(groups) as ShortcutCategory[]) {\n filtered[category] = groups[category].filter(\n (def) =>\n def.name.toLowerCase().includes(query) || def.description.toLowerCase().includes(query)\n );\n }\n\n return filtered;\n }\n\n return groups;\n }, [searchQuery]);\n\n if (!showModal) return null;\n\n const categoryOrder: ShortcutCategory[] = [\"workflow\", \"editing\", \"canvas\", \"ui\"];\n\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50\"\n onClick={(e) => {\n if (e.target === e.currentTarget) closeModal();\n }}\n >\n <div\n ref={focusTrapRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n className=\"bg-white dark:bg-zinc-800 rounded-xl shadow-2xl max-w-lg w-full mx-4 max-h-[80vh] flex flex-col overflow-hidden\"\n >\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-zinc-200 dark:border-zinc-700\">\n <h2 id={titleId} className=\"text-lg font-semibold text-zinc-900 dark:text-zinc-100\">\n Keyboard Shortcuts\n </h2>\n <button\n onClick={closeModal}\n aria-label=\"Close keyboard shortcuts\"\n className=\"p-1 text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200 rounded-lg hover:bg-zinc-100 dark:hover:bg-zinc-700\"\n >\n <svg\n className=\"w-5 h-5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n </div>\n\n {/* Search */}\n <div className=\"px-4 py-2 border-b border-zinc-200 dark:border-zinc-700\">\n <input\n type=\"text\"\n placeholder=\"Search shortcuts...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n aria-label=\"Search shortcuts\"\n autoFocus\n className=\"w-full px-3 py-2 text-sm bg-zinc-100 dark:bg-zinc-700 border border-zinc-200 dark:border-zinc-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-teal-500 focus:border-transparent text-zinc-900 dark:text-zinc-100 placeholder-zinc-500\"\n />\n </div>\n\n {/* Shortcuts list */}\n <div className=\"flex-1 overflow-y-auto px-4 py-2\">\n {categoryOrder.map((category) => {\n const shortcuts = groupedShortcuts[category];\n if (shortcuts.length === 0) return null;\n\n return (\n <div key={category} className=\"mb-4\">\n <h3 className=\"text-xs font-semibold text-zinc-500 dark:text-zinc-400 uppercase tracking-wider mb-2\">\n {CATEGORY_NAMES[category]}\n </h3>\n <div className=\"space-y-1\">\n {shortcuts.map((def) => {\n const binding = getEffectiveBinding(def.action);\n return (\n <div\n key={def.action}\n className=\"flex items-center justify-between py-1.5 px-2 rounded hover:bg-zinc-100 dark:hover:bg-zinc-700/50\"\n >\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm font-medium text-zinc-800 dark:text-zinc-200\">\n {def.name}\n </div>\n <div className=\"text-xs text-zinc-500 dark:text-zinc-400 truncate\">\n {def.description}\n </div>\n </div>\n <div className=\"ml-4 flex-shrink-0\">\n {binding ? (\n <KeyBadge binding={binding} size=\"sm\" />\n ) : (\n <span className=\"text-xs text-zinc-400 dark:text-zinc-500\">\n Not set\n </span>\n )}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n })}\n </div>\n\n {/* Footer */}\n <div className=\"px-4 py-3 border-t border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-800/50\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-xs text-zinc-500 dark:text-zinc-400\">\n Customize in Settings → Keyboard\n </span>\n <button\n onClick={closeModal}\n className=\"px-3 py-1.5 text-sm font-medium text-white bg-teal-600 hover:bg-teal-700 rounded-lg\"\n >\n Done\n </button>\n </div>\n </div>\n </div>\n </div>\n );\n}\n","/**\n * ConfirmationDialog - Accessible confirmation modal\n * Used for destructive actions like creating a new workflow with unsaved changes\n */\n\nimport { useId, useEffect, useCallback } from \"react\";\nimport { useFocusTrap } from \"../lib/useFocusTrap\";\n\ninterface ConfirmationDialogProps {\n /** Whether the dialog is open */\n isOpen: boolean;\n /** Title of the dialog */\n title: string;\n /** Message/description */\n message: string;\n /** Confirm button text */\n confirmText?: string;\n /** Cancel button text */\n cancelText?: string;\n /** Callback when confirmed */\n onConfirm: () => void;\n /** Callback when cancelled */\n onCancel: () => void;\n /** Whether the action is destructive (changes button styling) */\n destructive?: boolean;\n}\n\nexport function ConfirmationDialog({\n isOpen,\n title,\n message,\n confirmText = \"Confirm\",\n cancelText = \"Cancel\",\n onConfirm,\n onCancel,\n destructive = false,\n}: ConfirmationDialogProps) {\n const titleId = useId();\n const descId = useId();\n const focusTrapRef = useFocusTrap(isOpen);\n\n // Handle escape key\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n onCancel();\n }\n },\n [onCancel]\n );\n\n useEffect(() => {\n if (isOpen) {\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }\n }, [isOpen, handleKeyDown]);\n\n if (!isOpen) return null;\n\n return (\n <div\n className=\"fixed inset-0 z-[60] flex items-center justify-center bg-black/50\"\n onClick={(e) => {\n if (e.target === e.currentTarget) onCancel();\n }}\n >\n <div\n ref={focusTrapRef}\n role=\"alertdialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n aria-describedby={descId}\n className=\"bg-white dark:bg-zinc-800 rounded-xl shadow-2xl max-w-sm w-full mx-4 overflow-hidden\"\n >\n <div className=\"px-6 py-4\">\n <h2 id={titleId} className=\"text-lg font-semibold text-zinc-900 dark:text-zinc-100\">\n {title}\n </h2>\n <p id={descId} className=\"mt-2 text-sm text-zinc-600 dark:text-zinc-400\">\n {message}\n </p>\n </div>\n\n <div className=\"flex items-center justify-end gap-3 px-6 py-4 border-t border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-800/50\">\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"px-4 py-2 text-sm font-medium text-zinc-700 dark:text-zinc-300 bg-white dark:bg-zinc-700 border border-zinc-300 dark:border-zinc-600 rounded-lg hover:bg-zinc-50 dark:hover:bg-zinc-600 focus:outline-none focus:ring-2 focus:ring-teal-500 focus:ring-offset-2 dark:focus:ring-offset-zinc-800\"\n >\n {cancelText}\n </button>\n <button\n type=\"button\"\n onClick={onConfirm}\n autoFocus\n className={`px-4 py-2 text-sm font-medium rounded-lg focus:outline-none focus:ring-2 focus:ring-offset-2 dark:focus:ring-offset-zinc-800 ${\n destructive\n ? \"text-white bg-red-600 hover:bg-red-700 focus:ring-red-500\"\n : \"text-white bg-teal-600 hover:bg-teal-700 focus:ring-teal-500\"\n }`}\n >\n {confirmText}\n </button>\n </div>\n </div>\n </div>\n );\n}\n","import { useState, useCallback, useEffect, DragEvent } from \"react\";\nimport { ReactFlowProvider, useReactFlow } from \"reactflow\";\nimport { WorkflowEditor } from \"./editor/WorkflowEditor\";\nimport { NodePalette } from \"./components/NodePalette\";\nimport { NodeInspector } from \"./components/NodeInspector\";\nimport { Toolbar } from \"./components/Toolbar\";\nimport { Gallery } from \"./components/Gallery\";\nimport { TemplateGallery } from \"./components/TemplateGallery\";\nimport { WorkflowLibrary } from \"./components/WorkflowLibrary\";\nimport { AISettings } from \"./components/AISettings\";\nimport { AIChat } from \"./components/AIChat\";\nimport { OutputInspector } from \"./components/OutputInspector\";\nimport { CommandPalette } from \"./components/CommandPalette\";\nimport { KeyboardShortcutsModal } from \"./components/KeyboardShortcutsModal\";\nimport { ConfirmationDialog } from \"./components/ConfirmationDialog\";\nimport { useKeyboardShortcuts } from \"./lib/keyboard/useKeyboardShortcuts\";\nimport { useWorkflowStore } from \"./stores/workflowStore\";\nimport { useSettingsStore } from \"./stores/settingsStore\";\nimport { resolveTemplate } from \"@teamflojo/floimg-templates\";\nimport type { NodeDefinition, GeneratedWorkflowData } from \"@teamflojo/floimg-studio-shared\";\n\n// KeyboardShortcutsProvider - registers global keyboard shortcuts\n// Must be inside ReactFlowProvider to access useReactFlow hook\nfunction KeyboardShortcutsProvider({ onToggleAIChat }: { onToggleAIChat: () => void }) {\n useKeyboardShortcuts({ onToggleAIChat });\n return null;\n}\n\n// EditorDropZone - handles node drops with correct coordinate conversion\n// Must be inside ReactFlowProvider to access useReactFlow hook\nfunction EditorDropZone() {\n const { screenToFlowPosition } = useReactFlow();\n const addNode = useWorkflowStore((s) => s.addNode);\n\n const handleDrop = useCallback(\n (event: DragEvent<HTMLDivElement>) => {\n event.preventDefault();\n\n const data = event.dataTransfer.getData(\"application/json\");\n if (!data) return;\n\n try {\n const definition: NodeDefinition = JSON.parse(data);\n\n // Use screenToFlowPosition to correctly convert screen coordinates\n // to flow coordinates, accounting for zoom and pan\n const position = screenToFlowPosition({\n x: event.clientX,\n y: event.clientY,\n });\n\n addNode(definition, position);\n } catch (e) {\n console.error(\"Failed to parse dropped node:\", e);\n }\n },\n [addNode, screenToFlowPosition]\n );\n\n const handleDragOver = useCallback((event: DragEvent<HTMLDivElement>) => {\n event.preventDefault();\n event.dataTransfer.dropEffect = \"move\";\n }, []);\n\n return (\n <div className=\"flex-1\" onDrop={handleDrop} onDragOver={handleDragOver}>\n <WorkflowEditor />\n </div>\n );\n}\n\ntype TabType = \"editor\" | \"gallery\" | \"templates\";\n\nfunction App() {\n const [activeTab, setActiveTab] = useState<TabType>(\"editor\");\n const [showAIChat, setShowAIChat] = useState(false);\n const loadTemplate = useWorkflowStore((s) => s.loadTemplate);\n const loadGeneratedWorkflow = useWorkflowStore((s) => s.loadGeneratedWorkflow);\n\n // Output inspector state\n const inspectedNodeId = useWorkflowStore((s) => s.inspectedNodeId);\n const executionDataOutputs = useWorkflowStore((s) => s.execution.dataOutputs);\n const closeOutputInspector = useWorkflowStore((s) => s.closeOutputInspector);\n const nodes = useWorkflowStore((s) => s.nodes);\n const selectedNodeId = useWorkflowStore((s) => s.selectedNodeId);\n\n // Get inspected node info\n const inspectedNode = inspectedNodeId ? nodes.find((n) => n.id === inspectedNodeId) : null;\n const inspectedOutput = inspectedNodeId ? executionDataOutputs[inspectedNodeId] : null;\n\n // Handle ?template=<id> URL parameter\n useEffect(() => {\n const params = new URLSearchParams(window.location.search);\n const templateId = params.get(\"template\");\n\n if (templateId) {\n // resolveTemplate handles both canonical IDs and legacy IDs\n const template = resolveTemplate(templateId);\n if (template) {\n loadTemplate(template);\n // Clean up URL without reload\n window.history.replaceState({}, \"\", window.location.pathname);\n }\n }\n }, [loadTemplate]);\n\n // Listen for workflow-loaded event (from Gallery)\n useEffect(() => {\n const handleWorkflowLoaded = () => {\n setActiveTab(\"editor\");\n };\n window.addEventListener(\"workflow-loaded\", handleWorkflowLoaded);\n return () => {\n window.removeEventListener(\"workflow-loaded\", handleWorkflowLoaded);\n };\n }, []);\n\n // Handler for template selection (from TemplateGallery)\n const handleTemplateSelect = useCallback(\n (templateId: string) => {\n const template = resolveTemplate(templateId);\n if (template) {\n loadTemplate(template);\n setActiveTab(\"editor\");\n }\n },\n [loadTemplate]\n );\n\n // Handler for AI-generated workflow\n const handleApplyWorkflow = useCallback(\n (workflow: GeneratedWorkflowData) => {\n loadGeneratedWorkflow(workflow);\n setActiveTab(\"editor\");\n },\n [loadGeneratedWorkflow]\n );\n\n // Toggle AI chat handler for keyboard shortcuts\n const handleToggleAIChat = useCallback(() => {\n setShowAIChat((prev) => !prev);\n }, []);\n\n // New workflow confirmation dialog\n const showNewWorkflowConfirm = useSettingsStore((s) => s.showNewWorkflowConfirm);\n const confirmNewWorkflow = useSettingsStore((s) => s.confirmNewWorkflow);\n const cancelNewWorkflow = useSettingsStore((s) => s.cancelNewWorkflow);\n\n return (\n <ReactFlowProvider>\n {/* Global Keyboard Shortcuts - must be inside ReactFlowProvider */}\n <KeyboardShortcutsProvider onToggleAIChat={handleToggleAIChat} />\n\n {/* Command Palette (Cmd+K) */}\n <CommandPalette onToggleAIChat={handleToggleAIChat} />\n\n {/* Keyboard Shortcuts Help Modal (Cmd+?) */}\n <KeyboardShortcutsModal />\n\n {/* New Workflow Confirmation Dialog */}\n <ConfirmationDialog\n isOpen={showNewWorkflowConfirm}\n title=\"Unsaved Changes\"\n message=\"You have unsaved changes. Creating a new workflow will discard them. Are you sure you want to continue?\"\n confirmText=\"Create New\"\n cancelText=\"Keep Editing\"\n onConfirm={confirmNewWorkflow}\n onCancel={cancelNewWorkflow}\n destructive\n />\n\n {/* AI Settings Modal */}\n <AISettings />\n\n {/* AI Chat Modal */}\n <AIChat\n isOpen={showAIChat}\n onClose={() => setShowAIChat(false)}\n onApplyWorkflow={handleApplyWorkflow}\n />\n\n {/* Output Inspector Modal */}\n {inspectedNode && inspectedOutput && (\n <OutputInspector\n isOpen={true}\n onClose={closeOutputInspector}\n nodeId={inspectedNodeId!}\n nodeLabel={\n (inspectedNode.data as { providerLabel?: string }).providerLabel ||\n inspectedNode.type ||\n \"Node\"\n }\n output={inspectedOutput}\n />\n )}\n\n {/* Workflow Library slide-out panel */}\n <WorkflowLibrary />\n\n <div className=\"floimg-studio h-screen flex flex-col bg-gray-100 dark:bg-zinc-900\">\n <Toolbar />\n\n {/* Tab navigation */}\n <div className=\"floimg-tabs\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex\">\n <button\n onClick={() => setActiveTab(\"editor\")}\n className={`floimg-tab ${activeTab === \"editor\" ? \"floimg-tab--active\" : \"\"}`}\n >\n Editor\n </button>\n <button\n onClick={() => setActiveTab(\"gallery\")}\n className={`floimg-tab ${activeTab === \"gallery\" ? \"floimg-tab--active\" : \"\"}`}\n >\n Images\n </button>\n <button\n onClick={() => setActiveTab(\"templates\")}\n className={`floimg-tab ${activeTab === \"templates\" ? \"floimg-tab--active\" : \"\"}`}\n >\n Templates\n </button>\n </div>\n\n {/* AI Generate button */}\n <button onClick={() => setShowAIChat(true)} className=\"floimg-ai-btn mr-4\">\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z\"\n />\n </svg>\n AI Generate\n </button>\n </div>\n </div>\n\n {/* Main content */}\n <div className=\"flex-1 flex overflow-hidden\">\n {activeTab === \"editor\" && (\n <>\n <NodePalette />\n <EditorDropZone />\n {selectedNodeId && <NodeInspector />}\n </>\n )}\n {activeTab === \"gallery\" && (\n <div className=\"flex-1 overflow-auto\">\n <Gallery />\n </div>\n )}\n {activeTab === \"templates\" && (\n <div className=\"flex-1 overflow-auto\">\n <TemplateGallery onSelect={handleTemplateSelect} />\n </div>\n )}\n </div>\n </div>\n </ReactFlowProvider>\n );\n}\n\nexport default App;\n"],"names":["createJSONStorage","getStorage","options","storage","name","_a","parse","str2","str","newValue","toThenable","fn","input","result","onFulfilled","_onRejected","e","_onFulfilled","onRejected","persistImpl","config","baseOptions","set","get","api","state","persistedState","currentState","hasHydrated","hydrationListeners","finishHydrationListeners","args","setItem","savedSetState","replace","configResult","stateFromStorage","hydrate","_b","cb","_a2","postRehydrationCallback","deserializedStorageValue","migration","migrationResult","migrated","migratedState","newOptions","persist","API_BASE","fetchJson","url","response","error","getGenerators","getTransforms","getTextProviders","getVisionProviders","exportYaml","nodes","edges","listImages","getImageUrl","id","getImageWorkflow","uploadImage","file","formData","listUploads","deleteUpload","getUploadBlobUrl","importYaml","yaml","validateYaml","getGenerateStatus","createSSEConnection","body","handlers","controller","errorBody","reader","decoder","buffer","done","value","processBuffer","messages","message","processSSEMessage","lines","data","line","parsed","VALID_SHORTCUT_ACTIONS","SHORTCUT_DEFINITIONS","getDefaultShortcuts","defaults","def","getShortcutsByCategory","grouped","CATEGORY_NAMES","BROWSER_RESERVED","REACT_FLOW_DEFAULTS","isBrowserReserved","binding","normalized","isReactFlowDefault","b","checkShortcutConflict","currentShortcuts","excludeAction","action","existingBinding","existingNormalized","newBindings","existingBindings","nb","eb","d","isValidBinding","parts","modifiers","nonModifiers","p","validKeys","key","DEFAULT_OLLAMA_URL","DEFAULT_LMSTUDIO_URL","validateKeyboardSettings","stored","defaultSettings","settings","enabled","validatedShortcuts","shortcuts","useSettingsStore","create","provider","newAI","newShortcuts","keyboard","defaultBinding","userBinding","hasUnsavedChanges","onConfirm","callback","ai","_c","_d","_e","_f","_g","persisted","activeExecutionConnection","nodeIdCounter","generateNodeId","generateWorkflowId","timestamp","random","useWorkflowStore","enrichNodeData","studioNode","g","t","nodeId","template","idMap","newId","studioEdge","newSource","newTarget","generators","transforms","textProviders","visionProviders","definition","position","getDefaultParams","props","newNode","node","n","nodeToDuplicate","connection","handleSuffix","newEdge","studioNodes","studioEdges","aiProviders","initialNodeStatus","resolve","reject","event","step","newNodeStatus","newPreviews","newDataOutputs","finalNodeStatus","errorNodeStatus","activeWorkflowId","activeWorkflowName","savedWorkflows","currentTemplateId","now","updated","wf","newWorkflow","workflow","enrichedNodes","filtered","duplicate","COLUMN_SPACING","ROW_SPACING","incomingEdges","outgoingEdges","edge","nodeDepth","visited","computeDepth","incoming","depth","nodesByDepth","nodePositions","nodeIds","columnHeight","startY","verticalIndex","genNode","flowNodeType","nodeType","generatorName","generatorDef","providerName","operation","transformDef","jsonSchema","outputSchema","prop","genEdge","params","field","getExecutionClass","nodeStatus","PreviewToggle","color","previewVisible","s","togglePreview","jsx","GeneratorNode","memo","selected","preview","executionClass","isAI","acceptsReferences","jsxs","Handle","Position","TransformNode","SaveNode","InputNode","updateNodeData","fileInputRef","useRef","handleFileSelect","useCallback","handleDrop","handleDragOver","handleInputChange","previewUrl","VisionNode","dataOutput","openOutputInspector","outputProperties","hasMultiOutput","Fragment","index","TextNode","FanOutNode","outputCount","_","i","CollectNode","inputCount","RouterNode","hasContextOutput","nodeTypes","defaultEdgeOptions","MarkerType","WorkflowEditor","setNodes","setEdges","addEdge","setSelectedNode","memoizedNodeTypes","useMemo","isValidConnection","source","target","targetHandle","sourceNode","targetNode","onNodesChange","changes","applyNodeChanges","onEdgesChange","applyEdgeChanges","onConnect","edgesToRemove","existingHandle","newHandle","removeIds","onNodeClick","_event","onPaneClick","ReactFlow","Background","BackgroundVariant","Controls","MiniMap","UploadGallery","onSelect","uploads","setUploads","useState","loading","setLoading","setError","fetchUploads","err","useEffect","handleDelete","prev","u","formatSize","bytes","upload","NodePalette","setGenerators","setTransforms","setTextProviders","setVisionProviders","addNode","showUploads","setShowUploads","fetchedGenerators","useQuery","fetchedTransforms","fetchedTextProviders","fetchedVisionProviders","handleDragStart","handleDoubleClick","inputDefinition","saveDefinition","fanOutDefinition","collectDefinition","routerDefinition","generatorsByCategory","acc","cat","transformsByCategory","category","NodeInspector","selectedNodeId","deleteNode","selectedNode","schema","nodeLabel","isCloudSave","v","handleParamChange","getParamValue","isFieldVisible","_field","shapeType","fillType","mode","FieldEditor","OutputSchemaEditor","onChange","label","opt","newPropertyName","setNewPropertyName","properties","propertyEntries","handleAddProperty","newSchema","handleRemoveProperty","newProperties","handleTypeChange","type","handleDescriptionChange","description","j","Q","K","D","H","r","P","o","f","y","I","L","R","U","V","X","Y","Z","F","ee","te","re","a","l","k","m","$","T","oe","M","x","W","se","ie","S","N","ue","z","J","fe","w","B","h","C","G","O","q","E","DEFAULT_OPTIONS","useEffectiveBinding","keyboardSettings","useShortcut","handler","keyboardEnabled","useHotkeys","useKeyboardShortcuts","onToggleAIChat","reactFlowInstance","useReactFlow","execution","saveWorkflow","execute","cancelExecution","duplicateNode","toggleLibrary","openSettings","openShortcutsModal","openCommandPalette","closeCommandPalette","closeShortcutsModal","closeSettings","showCommandPalette","openExport","openImport","requestNewWorkflow","handleSave","handleExecute","handleNewWorkflow","handleExport","handleImport","handleCancelExecution","handleDuplicate","handleSelectAll","nds","handleDeselect","handleZoomIn","handleZoomOut","handleZoomFit","handleCommandPalette","handleShowShortcuts","handleToggleAIChat","handleToggleLibrary","handleSettings","useShortcutBinding","isMac","getModifierKey","getOptionKey","getShiftKey","KEY_SYMBOLS","bindingToDisplay","displayParts","part","bindingToKeys","keys","topologicalSort","nodeMap","inDegree","adjacency","targets","queue","degree","sorted","neighbors","neighbor","newDegree","getNodeVarName","suffix","stringify","generateNodeCode","nodeVarNames","varName","imports","inputEdge","inputVarName","paramStr","generateJavaScript","sortedNodes","allImports","codeBlocks","code","imp","importLines","header","mainCode","block","ImportModal","isOpen","onClose","onImport","yamlContent","setYamlContent","isLoading","setIsLoading","isDragging","setIsDragging","handleValidate","handleFileUpload","text","handleDragLeave","handleFileInputChange","Toolbar","brandingSlot","beforeActionsSlot","afterActionsSlot","hideAttribution","hideWorkflowLibrary","exportToYaml","importFromYaml","setActiveWorkflowName","saveShortcut","showExport","setShowExport","showImport","setShowImport","exportTab","setExportTab","jsContent","setJsContent","notification","setNotification","isEditingName","setIsEditingName","editingName","setEditingName","handleStartRename","handleSaveRename","trimmed","js","handleCopy","content","importedNodes","importedEdges","idx","Gallery","loadTemplate","loadingWorkflow","setLoadingWorkflow","images","refetch","handleLoadWorkflow","imageId","metadata","image","ImageCard","onLoadWorkflow","formatDate","revenueChart","monthlyUsers","frameworkUsage","trafficBreakdown","apiFlow","systemArchitecture","gitWorkflow","dataVizTemplates","aiProductShot","aiHeroImage","aiMascot","aiLogoBrandKit","productPhotoEnhancement","aiArtSocialPost","aiWorkflowTemplates","socialMediaKit","avatarPipeline","watermarkBranding","filterShowcase","responsiveImages","teamHeadshots","screenshotDocs","blogOgImage","emailBanner","appIcons","marketingTemplates","brandedQR","darkQR","wifiQR","thumbnailGenerator","diagramWebp","utilityTemplates","allTemplates","coreTemplates","getTemplateById","getCoreTemplateById","getCoreCategories","categories","getCoreTemplatesByCategory","searchCoreTemplates","query","tag","resolveTemplate","TemplateGallery","selectedCategory","setSelectedCategory","searchQuery","setSearchQuery","getCategories","filteredTemplates","templates","TemplateCard","nodeCount","edgeCount","generatorColors","WorkflowItem","isActive","onLoad","onDelete","onRename","onDuplicate","isEditing","setIsEditing","editName","setEditName","showMenu","setShowMenu","handleRename","date","diffMs","diffMins","diffHours","diffDays","WorkflowLibrary","showLibrary","loadWorkflow","deleteWorkflow","renameWorkflow","duplicateWorkflow","sortedWorkflows","CLOUD_PROVIDERS","LOCAL_PROVIDERS","CloudProviderRow","setAIProvider","isEnabled","apiKey","localKey","setLocalKey","showKey","setShowKey","handleToggle","handleKeyChange","LocalProviderRow","baseUrl","localUrl","setLocalUrl","handleUrlChange","AISettings","showSettings","activeGenerationConnection","AIChat","onApplyWorkflow","setMessages","setInput","generationPhase","setGenerationPhase","generationMessage","setGenerationMessage","isAvailable","setIsAvailable","statusMessage","setStatusMessage","statusReason","setStatusReason","isCloudDeployment","setIsCloudDeployment","supportUrl","setSupportUrl","messagesEndRef","inputRef","status","handleSubmit","userMessage","receivedWorkflow","assistantMessage","handleCancelGeneration","handleKeyDown","handleApply","handleNewChat","example","msg","nodeIdx","MAX_JSON_DEPTH","MAX_ARRAY_ITEMS","LARGE_OUTPUT_THRESHOLD","OutputInspector","output","viewMode","setViewMode","copied","setCopied","textToCopy","hasFormattedView","JsonTree","JsonNode","keyName","maxDepth","indent","displayValue","itemsToRender","hiddenCount","item","entries","val","KeyBadge","className","size","sizeClasses","FOCUSABLE_SELECTORS","useFocusTrap","containerRef","previousActiveElement","getFocusableElements","el","focusableElements","firstElement","lastElement","getDisabledReason","cmd","executionStatus","CommandPalette","showPalette","closePalette","deferredSearchQuery","useDeferredValue","selectedIndex","setSelectedIndex","titleId","useId","focusTrapRef","listRef","getEffectiveBinding","commands","filteredCommands","nameMatch","keywordMatch","kw","groupedCommands","groups","selectedEl","categoryOrder","flatIndex","getCommandIndex","cmds","isSelected","disabledReason","KeyboardShortcutsModal","showModal","closeModal","groupedShortcuts","ConfirmationDialog","title","confirmText","cancelText","onCancel","destructive","descId","KeyboardShortcutsProvider","EditorDropZone","screenToFlowPosition","App","activeTab","setActiveTab","showAIChat","setShowAIChat","loadGeneratedWorkflow","inspectedNodeId","executionDataOutputs","closeOutputInspector","inspectedNode","inspectedOutput","templateId","handleWorkflowLoaded","handleTemplateSelect","handleApplyWorkflow","showNewWorkflowConfirm","confirmNewWorkflow","cancelNewWorkflow","ReactFlowProvider"],"mappings":"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","x_google_ignoreList":[0,13]}