@teamflojo/floimg-studio-ui 0.2.1 → 0.2.3

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/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","../src/templates/index.ts","../src/components/TemplateGallery.tsx","../src/components/WorkflowLibrary.tsx","../src/components/AISettings.tsx","../src/components/AIChat.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} 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<{\n available: boolean;\n model: string;\n message: string;\n}> {\n return fetchJson(`${API_BASE}/generate/status`);\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 GalleryTemplate,\n GeneratedWorkflowData,\n StudioNodeType,\n} from \"@teamflojo/floimg-studio-shared\";\nimport { executeWorkflow, exportYaml } from \"../api/client\";\nimport type { StudioNode, StudioEdge } 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\" | \"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: GalleryTemplate) => 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\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\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 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 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: studioNode.data as NodeData,\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 \"running\" status\n const initialNodeStatus: Record<string, NodeExecutionStatus> = {};\n for (const node of nodes) {\n initialNodeStatus[node.id] = \"running\";\n }\n\n set({\n execution: {\n status: \"running\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: initialNodeStatus,\n },\n });\n\n try {\n const result = await executeWorkflow(studioNodes, studioEdges, aiProviders);\n\n // Set all nodes to completed or error based on result\n const finalNodeStatus: Record<string, NodeExecutionStatus> = {};\n for (const node of nodes) {\n finalNodeStatus[node.id] = result.status === \"completed\" ? \"completed\" : \"error\";\n }\n\n if (result.status === \"completed\") {\n set({\n execution: {\n status: \"completed\",\n imageIds: result.imageIds,\n imageUrls: result.imageUrls || [],\n previews: result.previews || {},\n dataOutputs: result.dataOutputs || {},\n nodeStatus: finalNodeStatus,\n },\n });\n } else {\n set({\n execution: {\n status: \"error\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: finalNodeStatus,\n error: result.error,\n },\n });\n }\n } catch (error) {\n // Set all nodes to error status\n const errorNodeStatus: Record<string, NodeExecutionStatus> = {};\n for (const node of nodes) {\n errorNodeStatus[node.id] = \"error\";\n }\n\n set({\n execution: {\n status: \"error\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: errorNodeStatus,\n error: error instanceof Error ? error.message : \"Unknown error\",\n },\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: studioNode.data as NodeData,\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 set({\n nodes: workflow.nodes,\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 data = {\n generatorName,\n params: genNode.parameters,\n isAI: true, // Assume AI since we're generating from AI\n } as GeneratorNodeData;\n } else if (nodeType === \"transform\") {\n const providerName = parts[1];\n const operation = parts.slice(2).join(\":\");\n data = {\n operation,\n providerName,\n params: genNode.parameters,\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 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 === \"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\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 </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\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 </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 } 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 { 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};\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 // Validate connections based on node types\n const isValidConnection = useCallback(\n (connection: Connection) => {\n const { source, target } = 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 or input (no input port)\n if (targetNode.type === \"generator\" || targetNode.type === \"input\") return false;\n\n // Rule 3: Each input handle only accepts one connection\n // (allow multiple connections to same node if targeting different handles)\n const existingInputConnection = edges.find(\n (e) => e.target === target && e.targetHandle === connection.targetHandle\n );\n if (existingInputConnection) return false;\n\n // Rule 4: No self-connections\n if (source === target) return false;\n\n return true;\n },\n [nodes, edges]\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 addEdge(connection);\n },\n [addEdge]\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={nodeTypes}\n defaultEdgeOptions={defaultEdgeOptions}\n isValidConnection={isValidConnection}\n nodesDraggable={true}\n nodesConnectable={true}\n elementsSelectable={true}\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 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).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}\n\nexport function Toolbar({\n brandingSlot,\n beforeActionsSlot,\n afterActionsSlot,\n hideAttribution = false,\n}: ToolbarProps = {}) {\n const execution = useWorkflowStore((s) => s.execution);\n const execute = useWorkflowStore((s) => s.execute);\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 */}\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 <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 <button\n onClick={handleExecute}\n disabled={nodes.length === 0 || execution.status === \"running\"}\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 {execution.status === \"running\" ? (\n <>\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 Running...\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=\"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 </>\n )}\n </button>\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 { GalleryTemplate } from \"@teamflojo/floimg-studio-shared\";\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 GalleryTemplate format\n const template: GalleryTemplate = {\n id: `image-${imageId}`,\n name: `Workflow from ${imageId}`,\n description: \"Loaded from gallery image\",\n category: \"Gallery\",\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 Load Workflow button */}\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) => {\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 </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 * Template Registry\n *\n * All bundled templates that ship with floimg-studio.\n * These work offline and for self-hosted deployments.\n */\n\nimport type { GalleryTemplate } from \"@teamflojo/floimg-studio-shared\";\n\n// ============================================\n// Chart Templates (QuickChart)\n// ============================================\n\nexport const salesDashboard: GalleryTemplate = {\n id: \"sales-dashboard\",\n name: \"Sales Dashboard\",\n description: \"Quarterly revenue bar chart with gradient styling\",\n category: \"Charts\",\n generator: \"quickchart\",\n tags: [\"bar\", \"sales\", \"revenue\", \"quarterly\"],\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: [\"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 edges: [],\n },\n};\n\nexport const userGrowth: GalleryTemplate = {\n id: \"user-growth\",\n name: \"User Growth Line Chart\",\n description: \"Monthly user growth with smooth bezier curves\",\n category: \"Charts\",\n generator: \"quickchart\",\n tags: [\"line\", \"growth\", \"users\", \"monthly\"],\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: \"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 edges: [],\n },\n};\n\n// ============================================\n// Diagram Templates (Mermaid)\n// ============================================\n\nexport const apiFlowDiagram: GalleryTemplate = {\n id: \"api-flow\",\n name: \"API Request Flow\",\n description: \"Sequence diagram showing API authentication flow\",\n category: \"Diagrams\",\n generator: \"mermaid\",\n tags: [\"sequence\", \"api\", \"authentication\", \"flow\"],\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: `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 edges: [],\n },\n};\n\nexport const systemArchitecture: GalleryTemplate = {\n id: \"system-architecture\",\n name: \"System Architecture\",\n description: \"Microservices architecture diagram\",\n category: \"Diagrams\",\n generator: \"mermaid\",\n tags: [\"architecture\", \"microservices\", \"system\", \"flowchart\"],\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: `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 edges: [],\n },\n};\n\nexport const gitWorkflow: GalleryTemplate = {\n id: \"git-workflow\",\n name: \"Git Branch Workflow\",\n description: \"Git branching strategy with feature and release branches\",\n category: \"Diagrams\",\n generator: \"mermaid\",\n tags: [\"git\", \"branching\", \"workflow\", \"development\"],\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: `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 edges: [],\n },\n};\n\n// ============================================\n// QR Code Templates\n// ============================================\n\nexport const websiteQR: GalleryTemplate = {\n id: \"website-qr\",\n name: \"Website QR Code\",\n description: \"QR code linking to your website with custom styling\",\n category: \"QR Codes\",\n generator: \"qr\",\n tags: [\"qr\", \"website\", \"link\", \"url\"],\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 100 },\n data: {\n generatorName: \"qr\",\n params: {\n data: \"https://floimg.com\",\n size: 400,\n margin: 2,\n dark: \"#4f46e5\",\n light: \"#ffffff\",\n errorCorrectionLevel: \"M\",\n },\n },\n },\n ],\n edges: [],\n },\n};\n\nexport const wifiQR: GalleryTemplate = {\n id: \"wifi-qr\",\n name: \"WiFi QR Code\",\n description: \"Scannable QR code for WiFi network access\",\n category: \"QR Codes\",\n generator: \"qr\",\n tags: [\"qr\", \"wifi\", \"network\", \"guest\"],\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 100 },\n data: {\n generatorName: \"qr\",\n params: {\n data: \"WIFI:T:WPA;S:GuestNetwork;P:welcome123;;\",\n size: 400,\n margin: 2,\n dark: \"#059669\",\n light: \"#ffffff\",\n errorCorrectionLevel: \"H\",\n },\n },\n },\n ],\n edges: [],\n },\n};\n\n// ============================================\n// Transform Pipeline Templates\n// ============================================\n\nexport const chartWithWatermark: GalleryTemplate = {\n id: \"chart-watermark\",\n name: \"Chart with Watermark\",\n description: \"Bar chart with company watermark and rounded corners\",\n category: \"Pipelines\",\n generator: \"quickchart\",\n tags: [\"chart\", \"watermark\", \"branded\", \"pipeline\"],\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\nexport const diagramToWebP: GalleryTemplate = {\n id: \"diagram-webp\",\n name: \"Diagram to WebP\",\n description: \"Mermaid diagram converted to optimized WebP format\",\n category: \"Pipelines\",\n generator: \"mermaid\",\n tags: [\"mermaid\", \"webp\", \"optimize\", \"pipeline\"],\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// ============================================\n// Template Registry\n// ============================================\n\n/**\n * All available templates, organized by category\n */\nexport const templates: GalleryTemplate[] = [\n // Charts\n salesDashboard,\n userGrowth,\n // Diagrams\n apiFlowDiagram,\n systemArchitecture,\n gitWorkflow,\n // QR Codes\n websiteQR,\n wifiQR,\n // Pipelines\n chartWithWatermark,\n diagramToWebP,\n];\n\n/**\n * Get all unique categories\n */\nexport function getCategories(): string[] {\n const categories = new Set(templates.map((t) => t.category));\n return Array.from(categories).sort();\n}\n\n/**\n * Get templates by category\n */\nexport function getTemplatesByCategory(category: string): GalleryTemplate[] {\n return templates.filter((t) => t.category === category);\n}\n\n/**\n * Get a template by ID\n */\nexport function getTemplateById(id: string): GalleryTemplate | undefined {\n return templates.find((t) => t.id === id);\n}\n\n/**\n * Search templates by query\n */\nexport function searchTemplates(query: string): GalleryTemplate[] {\n const q = query.toLowerCase();\n return templates.filter(\n (t) =>\n 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","import { useState, useMemo } from \"react\";\nimport { templates, getCategories } from \"../templates\";\nimport type { GalleryTemplate } from \"@teamflojo/floimg-studio-shared\";\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: GalleryTemplate;\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} from \"@teamflojo/floimg-studio-shared\";\nimport { generateWorkflow, getGenerateStatus } from \"../api/client\";\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 [error, setError] = useState<string | null>(null);\n const [isAvailable, setIsAvailable] = useState<boolean | null>(null);\n const [statusMessage, setStatusMessage] = useState(\"\");\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 })\n .catch(() => {\n setIsAvailable(false);\n setStatusMessage(\"Failed to check AI availability\");\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(async () => {\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\n try {\n const response = await generateWorkflow({\n prompt: userMessage.content,\n history: messages,\n });\n\n const assistantMessage: GenerateWorkflowMessage = {\n role: \"assistant\",\n content: response.message,\n workflow: response.workflow,\n timestamp: Date.now(),\n };\n\n setMessages((prev) => [...prev, assistantMessage]);\n\n if (!response.success && response.error) {\n setError(response.error);\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to generate workflow\");\n } finally {\n setIsLoading(false);\n }\n }, [input, isLoading, messages]);\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 <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 <div>\n <p className=\"font-medium text-amber-800 dark:text-amber-200\">\n AI Generation Not Available\n </p>\n <p className=\"text-sm text-amber-700 dark:text-amber-300 mt-1\">{statusMessage}</p>\n <p className=\"text-xs text-amber-600 dark:text-amber-400 mt-2\">\n Set GEMINI_API_KEY in your environment to enable this feature.\n </p>\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-2\">\n <div className=\"flex space-x-1\">\n <div className=\"w-2 h-2 bg-gray-400 dark:bg-zinc-500 rounded-full animate-bounce\" />\n <div\n className=\"w-2 h-2 bg-gray-400 dark:bg-zinc-500 rounded-full animate-bounce\"\n style={{ animationDelay: \"0.1s\" }}\n />\n <div\n className=\"w-2 h-2 bg-gray-400 dark:bg-zinc-500 rounded-full animate-bounce\"\n style={{ animationDelay: \"0.2s\" }}\n />\n </div>\n <span className=\"text-sm text-gray-500 dark:text-zinc-400\">\n Generating workflow...\n </span>\n </div>\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, 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 { useWorkflowStore } from \"./stores/workflowStore\";\nimport { getTemplateById } from \"./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 // 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 const template = getTemplateById(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 = getTemplateById(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 {/* 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","executeWorkflow","nodes","edges","aiProviders","exportYaml","listImages","getImageUrl","id","getImageWorkflow","uploadImage","file","formData","listUploads","deleteUpload","getUploadBlobUrl","importYaml","yaml","validateYaml","generateWorkflow","request","getGenerateStatus","DEFAULT_OLLAMA_URL","DEFAULT_LMSTUDIO_URL","useSettingsStore","create","provider","newAI","ai","_c","_d","_e","_f","_g","nodeIdCounter","generateNodeId","generateWorkflowId","timestamp","random","useWorkflowStore","template","idMap","studioNode","newId","studioEdge","newSource","newTarget","generators","transforms","textProviders","visionProviders","definition","position","data","getDefaultParams","props","newNode","node","n","nodeToDuplicate","connection","handleSuffix","newEdge","studioNodes","studioEdges","initialNodeStatus","finalNodeStatus","errorNodeStatus","activeWorkflowId","activeWorkflowName","savedWorkflows","currentTemplateId","now","updated","wf","newWorkflow","workflow","filtered","duplicate","GRID_SPACING_X","GRID_SPACING_Y","NODES_PER_ROW","genNode","index","parts","nodeType","row","providerName","jsonSchema","outputSchema","key","prop","genEdge","params","field","getExecutionClass","nodeStatus","PreviewToggle","nodeId","color","previewVisible","s","togglePreview","jsx","GeneratorNode","memo","selected","preview","borderClass","isAI","acceptsReferences","jsxs","Handle","Position","value","TransformNode","SaveNode","InputNode","updateNodeData","fileInputRef","useRef","handleFileSelect","useCallback","handleDrop","handleDragOver","handleInputChange","previewUrl","VisionNode","dataOutput","outputProperties","hasMultiOutput","Fragment","TextNode","nodeTypes","defaultEdgeOptions","MarkerType","WorkflowEditor","setNodes","setEdges","addEdge","setSelectedNode","isValidConnection","source","target","sourceNode","targetNode","onNodesChange","changes","applyNodeChanges","onEdgesChange","applyEdgeChanges","onConnect","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","g","cat","transformsByCategory","t","category","def","NodeInspector","selectedNodeId","deleteNode","selectedNode","schema","nodeLabel","isCloudSave","v","handleParamChange","getParamValue","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","line","ImportModal","isOpen","onClose","onImport","yamlContent","setYamlContent","isLoading","setIsLoading","isDragging","setIsDragging","handleImport","handleValidate","handleFileUpload","text","handleDragLeave","handleFileInputChange","Toolbar","brandingSlot","beforeActionsSlot","afterActionsSlot","hideAttribution","execution","execute","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","salesDashboard","userGrowth","apiFlowDiagram","systemArchitecture","gitWorkflow","websiteQR","wifiQR","chartWithWatermark","diagramToWebP","templates","getCategories","categories","getTemplatesByCategory","getTemplateById","searchTemplates","query","q","tag","TemplateGallery","selectedCategory","setSelectedCategory","searchQuery","setSearchQuery","useMemo","filteredTemplates","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","AIChat","onApplyWorkflow","messages","setMessages","setInput","isAvailable","setIsAvailable","statusMessage","setStatusMessage","messagesEndRef","inputRef","status","handleSubmit","userMessage","assistantMessage","handleApply","handleNewChat","example","i","msg","nodeIdx","EditorDropZone","screenToFlowPosition","useReactFlow","event","App","activeTab","setActiveTab","showAIChat","setShowAIChat","loadGeneratedWorkflow","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/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","../src/templates/index.ts","../src/components/TemplateGallery.tsx","../src/components/WorkflowLibrary.tsx","../src/components/AISettings.tsx","../src/components/AIChat.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} 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<{\n available: boolean;\n model: string;\n message: string;\n}> {\n return fetchJson(`${API_BASE}/generate/status`);\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 GalleryTemplate,\n GeneratedWorkflowData,\n StudioNodeType,\n} from \"@teamflojo/floimg-studio-shared\";\nimport { executeWorkflow, exportYaml } from \"../api/client\";\nimport type { StudioNode, StudioEdge } 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\" | \"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: GalleryTemplate) => 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\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\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 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 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: studioNode.data as NodeData,\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 \"running\" status\n const initialNodeStatus: Record<string, NodeExecutionStatus> = {};\n for (const node of nodes) {\n initialNodeStatus[node.id] = \"running\";\n }\n\n set({\n execution: {\n status: \"running\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: initialNodeStatus,\n },\n });\n\n try {\n const result = await executeWorkflow(studioNodes, studioEdges, aiProviders);\n\n // Set all nodes to completed or error based on result\n const finalNodeStatus: Record<string, NodeExecutionStatus> = {};\n for (const node of nodes) {\n finalNodeStatus[node.id] = result.status === \"completed\" ? \"completed\" : \"error\";\n }\n\n if (result.status === \"completed\") {\n set({\n execution: {\n status: \"completed\",\n imageIds: result.imageIds,\n imageUrls: result.imageUrls || [],\n previews: result.previews || {},\n dataOutputs: result.dataOutputs || {},\n nodeStatus: finalNodeStatus,\n },\n });\n } else {\n set({\n execution: {\n status: \"error\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: finalNodeStatus,\n error: result.error,\n },\n });\n }\n } catch (error) {\n // Set all nodes to error status\n const errorNodeStatus: Record<string, NodeExecutionStatus> = {};\n for (const node of nodes) {\n errorNodeStatus[node.id] = \"error\";\n }\n\n set({\n execution: {\n status: \"error\",\n imageIds: [],\n imageUrls: [],\n previews: {},\n dataOutputs: {},\n nodeStatus: errorNodeStatus,\n error: error instanceof Error ? error.message : \"Unknown error\",\n },\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: studioNode.data as NodeData,\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 set({\n nodes: workflow.nodes,\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 data = {\n generatorName,\n params: genNode.parameters,\n isAI: true, // Assume AI since we're generating from AI\n } as GeneratorNodeData;\n } else if (nodeType === \"transform\") {\n const providerName = parts[1];\n const operation = parts.slice(2).join(\":\");\n data = {\n operation,\n providerName,\n params: genNode.parameters,\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 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 === \"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\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 </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\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 </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 } 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 { 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};\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 // Validate connections based on node types\n const isValidConnection = useCallback(\n (connection: Connection) => {\n const { source, target } = 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 or input (no input port)\n if (targetNode.type === \"generator\" || targetNode.type === \"input\") return false;\n\n // Rule 3: Each input handle only accepts one connection\n // (allow multiple connections to same node if targeting different handles)\n const existingInputConnection = edges.find(\n (e) => e.target === target && e.targetHandle === connection.targetHandle\n );\n if (existingInputConnection) return false;\n\n // Rule 4: No self-connections\n if (source === target) return false;\n\n return true;\n },\n [nodes, edges]\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 addEdge(connection);\n },\n [addEdge]\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={nodeTypes}\n defaultEdgeOptions={defaultEdgeOptions}\n isValidConnection={isValidConnection}\n nodesDraggable={true}\n nodesConnectable={true}\n elementsSelectable={true}\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 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).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 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 <button\n onClick={handleExecute}\n disabled={nodes.length === 0 || execution.status === \"running\"}\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 {execution.status === \"running\" ? (\n <>\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 Running...\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=\"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 </>\n )}\n </button>\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 { GalleryTemplate } from \"@teamflojo/floimg-studio-shared\";\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 GalleryTemplate format\n const template: GalleryTemplate = {\n id: `image-${imageId}`,\n name: `Workflow from ${imageId}`,\n description: \"Loaded from gallery image\",\n category: \"Gallery\",\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 Load Workflow button */}\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) => {\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 </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 * Template Registry\n *\n * All bundled templates that ship with floimg-studio.\n * These work offline and for self-hosted deployments.\n */\n\nimport type { GalleryTemplate } from \"@teamflojo/floimg-studio-shared\";\n\n// ============================================\n// Chart Templates (QuickChart)\n// ============================================\n\nexport const salesDashboard: GalleryTemplate = {\n id: \"sales-dashboard\",\n name: \"Sales Dashboard\",\n description: \"Quarterly revenue bar chart with gradient styling\",\n category: \"Charts\",\n generator: \"quickchart\",\n tags: [\"bar\", \"sales\", \"revenue\", \"quarterly\"],\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: [\"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 edges: [],\n },\n};\n\nexport const userGrowth: GalleryTemplate = {\n id: \"user-growth\",\n name: \"User Growth Line Chart\",\n description: \"Monthly user growth with smooth bezier curves\",\n category: \"Charts\",\n generator: \"quickchart\",\n tags: [\"line\", \"growth\", \"users\", \"monthly\"],\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: \"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 edges: [],\n },\n};\n\n// ============================================\n// Diagram Templates (Mermaid)\n// ============================================\n\nexport const apiFlowDiagram: GalleryTemplate = {\n id: \"api-flow\",\n name: \"API Request Flow\",\n description: \"Sequence diagram showing API authentication flow\",\n category: \"Diagrams\",\n generator: \"mermaid\",\n tags: [\"sequence\", \"api\", \"authentication\", \"flow\"],\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: `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 edges: [],\n },\n};\n\nexport const systemArchitecture: GalleryTemplate = {\n id: \"system-architecture\",\n name: \"System Architecture\",\n description: \"Microservices architecture diagram\",\n category: \"Diagrams\",\n generator: \"mermaid\",\n tags: [\"architecture\", \"microservices\", \"system\", \"flowchart\"],\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: `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 edges: [],\n },\n};\n\nexport const gitWorkflow: GalleryTemplate = {\n id: \"git-workflow\",\n name: \"Git Branch Workflow\",\n description: \"Git branching strategy with feature and release branches\",\n category: \"Diagrams\",\n generator: \"mermaid\",\n tags: [\"git\", \"branching\", \"workflow\", \"development\"],\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: `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 edges: [],\n },\n};\n\n// ============================================\n// QR Code Templates\n// ============================================\n\nexport const websiteQR: GalleryTemplate = {\n id: \"website-qr\",\n name: \"Website QR Code\",\n description: \"QR code linking to your website with custom styling\",\n category: \"QR Codes\",\n generator: \"qr\",\n tags: [\"qr\", \"website\", \"link\", \"url\"],\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 100 },\n data: {\n generatorName: \"qr\",\n params: {\n data: \"https://floimg.com\",\n size: 400,\n margin: 2,\n dark: \"#4f46e5\",\n light: \"#ffffff\",\n errorCorrectionLevel: \"M\",\n },\n },\n },\n ],\n edges: [],\n },\n};\n\nexport const wifiQR: GalleryTemplate = {\n id: \"wifi-qr\",\n name: \"WiFi QR Code\",\n description: \"Scannable QR code for WiFi network access\",\n category: \"QR Codes\",\n generator: \"qr\",\n tags: [\"qr\", \"wifi\", \"network\", \"guest\"],\n workflow: {\n nodes: [\n {\n id: \"gen-1\",\n type: \"generator\",\n position: { x: 100, y: 100 },\n data: {\n generatorName: \"qr\",\n params: {\n data: \"WIFI:T:WPA;S:GuestNetwork;P:welcome123;;\",\n size: 400,\n margin: 2,\n dark: \"#059669\",\n light: \"#ffffff\",\n errorCorrectionLevel: \"H\",\n },\n },\n },\n ],\n edges: [],\n },\n};\n\n// ============================================\n// Transform Pipeline Templates\n// ============================================\n\nexport const chartWithWatermark: GalleryTemplate = {\n id: \"chart-watermark\",\n name: \"Chart with Watermark\",\n description: \"Bar chart with company watermark and rounded corners\",\n category: \"Pipelines\",\n generator: \"quickchart\",\n tags: [\"chart\", \"watermark\", \"branded\", \"pipeline\"],\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\nexport const diagramToWebP: GalleryTemplate = {\n id: \"diagram-webp\",\n name: \"Diagram to WebP\",\n description: \"Mermaid diagram converted to optimized WebP format\",\n category: \"Pipelines\",\n generator: \"mermaid\",\n tags: [\"mermaid\", \"webp\", \"optimize\", \"pipeline\"],\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// ============================================\n// Template Registry\n// ============================================\n\n/**\n * All available templates, organized by category\n */\nexport const templates: GalleryTemplate[] = [\n // Charts\n salesDashboard,\n userGrowth,\n // Diagrams\n apiFlowDiagram,\n systemArchitecture,\n gitWorkflow,\n // QR Codes\n websiteQR,\n wifiQR,\n // Pipelines\n chartWithWatermark,\n diagramToWebP,\n];\n\n/**\n * Get all unique categories\n */\nexport function getCategories(): string[] {\n const categories = new Set(templates.map((t) => t.category));\n return Array.from(categories).sort();\n}\n\n/**\n * Get templates by category\n */\nexport function getTemplatesByCategory(category: string): GalleryTemplate[] {\n return templates.filter((t) => t.category === category);\n}\n\n/**\n * Get a template by ID\n */\nexport function getTemplateById(id: string): GalleryTemplate | undefined {\n return templates.find((t) => t.id === id);\n}\n\n/**\n * Search templates by query\n */\nexport function searchTemplates(query: string): GalleryTemplate[] {\n const q = query.toLowerCase();\n return templates.filter(\n (t) =>\n 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","import { useState, useMemo } from \"react\";\nimport { templates, getCategories } from \"../templates\";\nimport type { GalleryTemplate } from \"@teamflojo/floimg-studio-shared\";\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: GalleryTemplate;\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} from \"@teamflojo/floimg-studio-shared\";\nimport { generateWorkflow, getGenerateStatus } from \"../api/client\";\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 [error, setError] = useState<string | null>(null);\n const [isAvailable, setIsAvailable] = useState<boolean | null>(null);\n const [statusMessage, setStatusMessage] = useState(\"\");\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 })\n .catch(() => {\n setIsAvailable(false);\n setStatusMessage(\"Failed to check AI availability\");\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(async () => {\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\n try {\n const response = await generateWorkflow({\n prompt: userMessage.content,\n history: messages,\n });\n\n const assistantMessage: GenerateWorkflowMessage = {\n role: \"assistant\",\n content: response.message,\n workflow: response.workflow,\n timestamp: Date.now(),\n };\n\n setMessages((prev) => [...prev, assistantMessage]);\n\n if (!response.success && response.error) {\n setError(response.error);\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to generate workflow\");\n } finally {\n setIsLoading(false);\n }\n }, [input, isLoading, messages]);\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 <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 <div>\n <p className=\"font-medium text-amber-800 dark:text-amber-200\">\n AI Generation Not Available\n </p>\n <p className=\"text-sm text-amber-700 dark:text-amber-300 mt-1\">{statusMessage}</p>\n <p className=\"text-xs text-amber-600 dark:text-amber-400 mt-2\">\n Set GEMINI_API_KEY in your environment to enable this feature.\n </p>\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-2\">\n <div className=\"flex space-x-1\">\n <div className=\"w-2 h-2 bg-gray-400 dark:bg-zinc-500 rounded-full animate-bounce\" />\n <div\n className=\"w-2 h-2 bg-gray-400 dark:bg-zinc-500 rounded-full animate-bounce\"\n style={{ animationDelay: \"0.1s\" }}\n />\n <div\n className=\"w-2 h-2 bg-gray-400 dark:bg-zinc-500 rounded-full animate-bounce\"\n style={{ animationDelay: \"0.2s\" }}\n />\n </div>\n <span className=\"text-sm text-gray-500 dark:text-zinc-400\">\n Generating workflow...\n </span>\n </div>\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, 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 { useWorkflowStore } from \"./stores/workflowStore\";\nimport { getTemplateById } from \"./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 // 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 const template = getTemplateById(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 = getTemplateById(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 {/* 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","executeWorkflow","nodes","edges","aiProviders","exportYaml","listImages","getImageUrl","id","getImageWorkflow","uploadImage","file","formData","listUploads","deleteUpload","getUploadBlobUrl","importYaml","yaml","validateYaml","generateWorkflow","request","getGenerateStatus","DEFAULT_OLLAMA_URL","DEFAULT_LMSTUDIO_URL","useSettingsStore","create","provider","newAI","ai","_c","_d","_e","_f","_g","nodeIdCounter","generateNodeId","generateWorkflowId","timestamp","random","useWorkflowStore","template","idMap","studioNode","newId","studioEdge","newSource","newTarget","generators","transforms","textProviders","visionProviders","definition","position","data","getDefaultParams","props","newNode","node","n","nodeToDuplicate","connection","handleSuffix","newEdge","studioNodes","studioEdges","initialNodeStatus","finalNodeStatus","errorNodeStatus","activeWorkflowId","activeWorkflowName","savedWorkflows","currentTemplateId","now","updated","wf","newWorkflow","workflow","filtered","duplicate","GRID_SPACING_X","GRID_SPACING_Y","NODES_PER_ROW","genNode","index","parts","nodeType","row","providerName","jsonSchema","outputSchema","key","prop","genEdge","params","field","getExecutionClass","nodeStatus","PreviewToggle","nodeId","color","previewVisible","s","togglePreview","jsx","GeneratorNode","memo","selected","preview","borderClass","isAI","acceptsReferences","jsxs","Handle","Position","value","TransformNode","SaveNode","InputNode","updateNodeData","fileInputRef","useRef","handleFileSelect","useCallback","handleDrop","handleDragOver","handleInputChange","previewUrl","VisionNode","dataOutput","outputProperties","hasMultiOutput","Fragment","TextNode","nodeTypes","defaultEdgeOptions","MarkerType","WorkflowEditor","setNodes","setEdges","addEdge","setSelectedNode","isValidConnection","source","target","sourceNode","targetNode","onNodesChange","changes","applyNodeChanges","onEdgesChange","applyEdgeChanges","onConnect","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","g","cat","transformsByCategory","t","category","def","NodeInspector","selectedNodeId","deleteNode","selectedNode","schema","nodeLabel","isCloudSave","v","handleParamChange","getParamValue","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","line","ImportModal","isOpen","onClose","onImport","yamlContent","setYamlContent","isLoading","setIsLoading","isDragging","setIsDragging","handleImport","handleValidate","handleFileUpload","text","handleDragLeave","handleFileInputChange","Toolbar","brandingSlot","beforeActionsSlot","afterActionsSlot","hideAttribution","hideWorkflowLibrary","execution","execute","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","salesDashboard","userGrowth","apiFlowDiagram","systemArchitecture","gitWorkflow","websiteQR","wifiQR","chartWithWatermark","diagramToWebP","templates","getCategories","categories","getTemplatesByCategory","getTemplateById","searchTemplates","query","q","tag","TemplateGallery","selectedCategory","setSelectedCategory","searchQuery","setSearchQuery","useMemo","filteredTemplates","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","AIChat","onApplyWorkflow","messages","setMessages","setInput","isAvailable","setIsAvailable","statusMessage","setStatusMessage","messagesEndRef","inputRef","status","handleSubmit","userMessage","assistantMessage","handleApply","handleNewChat","example","i","msg","nodeIdx","EditorDropZone","screenToFlowPosition","useReactFlow","event","App","activeTab","setActiveTab","showAIChat","setShowAIChat","loadGeneratedWorkflow","templateId","handleWorkflowLoaded","handleTemplateSelect","handleApplyWorkflow","ReactFlowProvider"],"mappings":";;;;;AAkRA,SAASA,GAAkBC,GAAYC,GAAS;AAC9C,MAAIC;AACJ,MAAI;AACF,IAAAA,IAAUF,EAAA;AAAA,EACZ,QAAY;AACV;AAAA,EACF;AAmBA,SAlBuB;AAAA,IACrB,SAAS,CAACG,MAAS;AACjB,UAAIC;AACJ,YAAMC,IAAQ,CAACC,MACTA,MAAS,OACJ,OAEF,KAAK,MAAMA,GAAwB,MAAwB,GAE9DC,KAAOH,IAAKF,EAAQ,QAAQC,CAAI,MAAM,OAAOC,IAAK;AACxD,aAAIG,aAAe,UACVA,EAAI,KAAKF,CAAK,IAEhBA,EAAME,CAAG;AAAA,IAClB;AAAA,IACA,SAAS,CAACJ,GAAMK,MAAaN,EAAQ,QAAQC,GAAM,KAAK,UAAUK,GAA4B,MAAyB,CAAC;AAAA,IACxH,YAAY,CAACL,MAASD,EAAQ,WAAWC,CAAI;AAAA,EAAA;AAGjD;AACA,MAAMM,IAAa,CAACC,MAAO,CAACC,MAAU;AACpC,MAAI;AACF,UAAMC,IAASF,EAAGC,CAAK;AACvB,WAAIC,aAAkB,UACbA,IAEF;AAAA,MACL,KAAKC,GAAa;AAChB,eAAOJ,EAAWI,CAAW,EAAED,CAAM;AAAA,MACvC;AAAA,MACA,MAAME,GAAa;AACjB,eAAO;AAAA,MACT;AAAA,IAAA;AAAA,EAEJ,SAASC,GAAG;AACV,WAAO;AAAA,MACL,KAAKC,GAAc;AACjB,eAAO;AAAA,MACT;AAAA,MACA,MAAMC,GAAY;AAChB,eAAOR,EAAWQ,CAAU,EAAEF,CAAC;AAAA,MACjC;AAAA,IAAA;AAAA,EAEJ;AACF,GACMG,KAAc,CAACC,GAAQC,MAAgB,CAACC,GAAKC,GAAKC,MAAQ;AAC9D,MAAItB,IAAU;AAAA,IACZ,SAASF,GAAkB,MAAM,YAAY;AAAA,IAC7C,YAAY,CAACyB,MAAUA;AAAA,IACvB,SAAS;AAAA,IACT,OAAO,CAACC,GAAgBC,OAAkB;AAAA,MACxC,GAAGA;AAAA,MACH,GAAGD;AAAA,IAAA;AAAA,IAEL,GAAGL;AAAA,EAAA,GAEDO,IAAc;AAClB,QAAMC,wBAAyC,IAAA,GACzCC,wBAA+C,IAAA;AACrD,MAAI3B,IAAUD,EAAQ;AACtB,MAAI,CAACC;AACH,WAAOiB;AAAA,MACL,IAAIW,MAAS;AACX,gBAAQ;AAAA,UACN,uDAAuD7B,EAAQ,IAAI;AAAA,QAAA,GAErEoB,EAAI,GAAGS,CAAI;AAAA,MACb;AAAA,MACAR;AAAA,MACAC;AAAA,IAAA;AAGJ,QAAMQ,IAAU,MAAM;AACpB,UAAMP,IAAQvB,EAAQ,WAAW,EAAE,GAAGqB,EAAA,GAAO;AAC7C,WAAOpB,EAAQ,QAAQD,EAAQ,MAAM;AAAA,MACnC,OAAAuB;AAAA,MACA,SAASvB,EAAQ;AAAA,IAAA,CAClB;AAAA,EACH,GACM+B,IAAgBT,EAAI;AAC1B,EAAAA,EAAI,WAAW,CAACC,GAAOS,OACrBD,EAAcR,GAAOS,CAAO,GACrBF,EAAA;AAET,QAAMG,IAAef;AAAA,IACnB,IAAIW,OACFT,EAAI,GAAGS,CAAI,GACJC,EAAA;AAAA,IAETT;AAAA,IACAC;AAAA,EAAA;AAEF,EAAAA,EAAI,kBAAkB,MAAMW;AAC5B,MAAIC;AACJ,QAAMC,IAAU,MAAM;AACpB,QAAIhC,GAAIiC;AACR,QAAI,CAACnC,EAAS;AACd,IAAAyB,IAAc,IACdC,EAAmB,QAAQ,CAACU,MAAO;AACjC,UAAIC;AACJ,aAAOD,GAAIC,IAAMjB,EAAA,MAAU,OAAOiB,IAAML,CAAY;AAAA,IACtD,CAAC;AACD,UAAMM,MAA4BH,IAAKpC,EAAQ,uBAAuB,OAAO,SAASoC,EAAG,KAAKpC,IAAUG,IAAKkB,EAAA,MAAU,OAAOlB,IAAK8B,CAAY,MAAM;AACrJ,WAAOzB,EAAWP,EAAQ,QAAQ,KAAKA,CAAO,CAAC,EAAED,EAAQ,IAAI,EAAE,KAAK,CAACwC,MAA6B;AAChG,UAAIA;AACF,YAAI,OAAOA,EAAyB,WAAY,YAAYA,EAAyB,YAAYxC,EAAQ,SAAS;AAChH,cAAIA,EAAQ,SAAS;AACnB,kBAAMyC,IAAYzC,EAAQ;AAAA,cACxBwC,EAAyB;AAAA,cACzBA,EAAyB;AAAA,YAAA;AAE3B,mBAAIC,aAAqB,UAChBA,EAAU,KAAK,CAAC9B,MAAW,CAAC,IAAMA,CAAM,CAAC,IAE3C,CAAC,IAAM8B,CAAS;AAAA,UACzB;AACA,kBAAQ;AAAA,YACN;AAAA,UAAA;AAAA,QAEJ;AACE,iBAAO,CAAC,IAAOD,EAAyB,KAAK;AAGjD,aAAO,CAAC,IAAO,MAAM;AAAA,IACvB,CAAC,EAAE,KAAK,CAACE,MAAoB;AAC3B,UAAIJ;AACJ,YAAM,CAACK,GAAUC,CAAa,IAAIF;AAMlC,UALAR,IAAmBlC,EAAQ;AAAA,QACzB4C;AAAA,SACCN,IAAMjB,QAAU,OAAOiB,IAAML;AAAA,MAAA,GAEhCb,EAAIc,GAAkB,EAAI,GACtBS;AACF,eAAOb,EAAA;AAAA,IAEX,CAAC,EAAE,KAAK,MAAM;AACZ,MAAAS,KAA2B,QAAgBA,EAAwBL,GAAkB,MAAM,GAC3FA,IAAmBb,EAAA,GACnBK,IAAc,IACdE,EAAyB,QAAQ,CAACS,MAAOA,EAAGH,CAAgB,CAAC;AAAA,IAC/D,CAAC,EAAE,MAAM,CAACpB,MAAM;AACd,MAAAyB,KAA2B,QAAgBA,EAAwB,QAAQzB,CAAC;AAAA,IAC9E,CAAC;AAAA,EACH;AACA,SAAAQ,EAAI,UAAU;AAAA,IACZ,YAAY,CAACuB,MAAe;AAC1B,MAAA7C,IAAU;AAAA,QACR,GAAGA;AAAA,QACH,GAAG6C;AAAA,MAAA,GAEDA,EAAW,YACb5C,IAAU4C,EAAW;AAAA,IAEzB;AAAA,IACA,cAAc,MAAM;AAClB,MAAA5C,KAAW,QAAgBA,EAAQ,WAAWD,EAAQ,IAAI;AAAA,IAC5D;AAAA,IACA,YAAY,MAAMA;AAAA,IAClB,WAAW,MAAMmC,EAAA;AAAA,IACjB,aAAa,MAAMT;AAAA,IACnB,WAAW,CAACW,OACVV,EAAmB,IAAIU,CAAE,GAClB,MAAM;AACX,MAAAV,EAAmB,OAAOU,CAAE;AAAA,IAC9B;AAAA,IAEF,mBAAmB,CAACA,OAClBT,EAAyB,IAAIS,CAAE,GACxB,MAAM;AACX,MAAAT,EAAyB,OAAOS,CAAE;AAAA,IACpC;AAAA,EACF,GAEGrC,EAAQ,iBACXmC,EAAA,GAEKD,KAAoBD;AAC7B,GACMa,KAAU7B,IClcV8B,IAAW;AAEjB,eAAeC,EAAaC,GAAajD,GAAmC;AAC1E,QAAMkD,IAAW,MAAM,MAAMD,GAAK;AAAA,IAChC,GAAGjD;AAAA,IACH,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,GAAGA,KAAA,gBAAAA,EAAS;AAAA,IAAA;AAAA,EACd,CACD;AAED,MAAI,CAACkD,EAAS,IAAI;AAChB,UAAMC,IAAQ,MAAMD,EAAS,KAAA,EAAO,MAAM,OAAO,EAAE,OAAO,gBAAA,EAAkB;AAC5E,UAAM,IAAI,MAAMC,EAAM,SAAS,QAAQD,EAAS,MAAM,EAAE;AAAA,EAC1D;AAEA,SAAOA,EAAS,KAAA;AAClB;AAGA,eAAsBE,KAA2C;AAC/D,SAAOJ,EAAU,GAAGD,CAAQ,mBAAmB;AACjD;AAEA,eAAsBM,KAA2C;AAC/D,SAAOL,EAAU,GAAGD,CAAQ,mBAAmB;AACjD;AAEA,eAAsBO,KAA8C;AAClE,SAAON,EAAU,GAAGD,CAAQ,aAAa;AAC3C;AAEA,eAAsBQ,KAAgD;AACpE,SAAOP,EAAU,GAAGD,CAAQ,eAAe;AAC7C;AAcA,eAAsBS,GACpBC,GACAC,GACAC,GAWC;AACD,SAAOX,EAAU,GAAGD,CAAQ,iBAAiB;AAAA,IAC3C,QAAQ;AAAA,IACR,MAAM,KAAK,UAAU,EAAE,OAAAU,GAAO,OAAAC,GAAO,aAAAC,GAAa;AAAA,EAAA,CACnD;AACH;AAGA,eAAsBC,GACpBH,GACAC,GAC2B;AAC3B,SAAOV,EAAU,GAAGD,CAAQ,gBAAgB;AAAA,IAC1C,QAAQ;AAAA,IACR,MAAM,KAAK,UAAU,EAAE,OAAAU,GAAO,OAAAC,GAAO;AAAA,EAAA,CACtC;AACH;AAWA,eAAsBG,KAAmC;AACvD,SAAOb,EAAU,GAAGD,CAAQ,SAAS;AACvC;AAEO,SAASe,GAAYC,GAAoB;AAC9C,SAAO,GAAGhB,CAAQ,WAAWgB,CAAE;AACjC;AAEA,eAAsBC,GAAiBD,GAA2C;AAChF,MAAI;AACF,WAAO,MAAMf,EAAU,GAAGD,CAAQ,WAAWgB,CAAE,WAAW;AAAA,EAC5D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAWA,eAAsBE,GAAYC,GAAiC;AACjE,QAAMC,IAAW,IAAI,SAAA;AACrB,EAAAA,EAAS,OAAO,QAAQD,CAAI;AAE5B,QAAMhB,IAAW,MAAM,MAAM,GAAGH,CAAQ,YAAY;AAAA,IAClD,QAAQ;AAAA,IACR,MAAMoB;AAAA,EAAA,CACP;AAED,MAAI,CAACjB,EAAS,IAAI;AAChB,UAAMC,IAAQ,MAAMD,EAAS,KAAA,EAAO,MAAM,OAAO,EAAE,OAAO,gBAAA,EAAkB;AAC5E,UAAM,IAAI,MAAMC,EAAM,SAAS,QAAQD,EAAS,MAAM,EAAE;AAAA,EAC1D;AAEA,SAAOA,EAAS,KAAA;AAClB;AAEA,eAAsBkB,KAAqC;AACzD,SAAOpB,EAAU,GAAGD,CAAQ,UAAU;AACxC;AAMA,eAAsBsB,GAAaN,GAA2B;AAC5D,QAAMb,IAAW,MAAM,MAAM,GAAGH,CAAQ,YAAYgB,CAAE,IAAI;AAAA,IACxD,QAAQ;AAAA,EAAA,CACT;AACD,MAAI,CAACb,EAAS;AACZ,UAAM,IAAI,MAAM,4BAA4BA,EAAS,MAAM,EAAE;AAEjE;AAEO,SAASoB,GAAiBP,GAAoB;AACnD,SAAO,GAAGhB,CAAQ,YAAYgB,CAAE;AAClC;AAuBA,eAAsBQ,GAAWC,GAAqC;AACpE,SAAOxB,EAAU,GAAGD,CAAQ,WAAW;AAAA,IACrC,QAAQ;AAAA,IACR,MAAM,KAAK,UAAU,EAAE,MAAAyB,GAAM;AAAA,EAAA,CAC9B;AACH;AAEA,eAAsBC,GAAaD,GAA+C;AAChF,SAAOxB,EAAU,GAAGD,CAAQ,oBAAoB;AAAA,IAC9C,QAAQ;AAAA,IACR,MAAM,KAAK,UAAU,EAAE,MAAAyB,GAAM;AAAA,EAAA,CAC9B;AACH;AAGA,eAAsBE,GACpBC,GACmC;AACnC,SAAO3B,EAAU,GAAGD,CAAQ,sBAAsB;AAAA,IAChD,QAAQ;AAAA,IACR,MAAM,KAAK,UAAU4B,CAAO;AAAA,EAAA,CAC7B;AACH;AAEA,eAAsBC,KAInB;AACD,SAAO5B,EAAU,GAAGD,CAAQ,kBAAkB;AAChD;AC/JA,MAAM8B,KAAqB,0BACrBC,KAAuB,yBAEhBC,IAAmBC,GAAA;AAAA,EAC9BlC;AAAA,IACE,CAAC1B,GAAKC,OAAS;AAAA,MACb,IAAI;AAAA,QACF,QAAQ;AAAA,UACN,SAASwD;AAAA,UACT,SAAS;AAAA,QAAA;AAAA,QAEX,UAAU;AAAA,UACR,SAASC;AAAA,UACT,SAAS;AAAA,QAAA;AAAA,MACX;AAAA,MAEF,cAAc;AAAA,MAEd,eAAe,CAACG,GAAU/D,MAAW;AACnC,QAAAE,EAAI,CAACG,OAAW;AAAA,UACd,IAAI;AAAA,YACF,GAAGA,EAAM;AAAA,YACT,CAAC0D,CAAQ,GAAG/D;AAAA,UAAA;AAAA,QACd,EACA;AAAA,MACJ;AAAA,MAEA,iBAAiB,CAAC+D,MAAa;AAC7B,QAAA7D,EAAI,CAACG,MAAU;AACb,gBAAM2D,IAAQ,EAAE,GAAG3D,EAAM,GAAA;AACzB,wBAAO2D,EAAMD,CAAQ,GACd,EAAE,IAAIC,EAAA;AAAA,QACf,CAAC;AAAA,MACH;AAAA,MAEA,cAAc,MAAM9D,EAAI,EAAE,cAAc,IAAM;AAAA,MAC9C,eAAe,MAAMA,EAAI,EAAE,cAAc,IAAO;AAAA,MAEhD,wBAAwB,MAAM;;AAC5B,cAAM,EAAE,IAAA+D,EAAA,IAAO9D,EAAA,GACTV,IAA8D,CAAA;AAGpE,gBAAIR,IAAAgF,EAAG,WAAH,QAAAhF,EAAW,WAAWgF,EAAG,OAAO,WAClCxE,EAAO,SAAS,EAAE,QAAQwE,EAAG,OAAO,OAAA,KAElC/C,IAAA+C,EAAG,cAAH,QAAA/C,EAAc,WAAW+C,EAAG,UAAU,WACxCxE,EAAO,YAAY,EAAE,QAAQwE,EAAG,UAAU,OAAA,KAExCC,IAAAD,EAAG,WAAH,QAAAC,EAAW,WAAWD,EAAG,OAAO,WAClCxE,EAAO,SAAS,EAAE,QAAQwE,EAAG,OAAO,OAAA,KAElCE,IAAAF,EAAG,SAAH,QAAAE,EAAS,WAAWF,EAAG,KAAK,WAC9BxE,EAAO,OAAO,EAAE,QAAQwE,EAAG,KAAK,OAAA,KAE9BG,IAAAH,EAAG,eAAH,QAAAG,EAAe,WAAWH,EAAG,WAAW,WAC1CxE,EAAO,aAAa,EAAE,QAAQwE,EAAG,WAAW,OAAA,KAI1CI,IAAAJ,EAAG,WAAH,QAAAI,EAAW,YACb5E,EAAO,SAAS,EAAE,SAASwE,EAAG,OAAO,WAAWN,GAAA,KAE9CW,IAAAL,EAAG,aAAH,QAAAK,EAAa,YACf7E,EAAO,WAAW,EAAE,SAASwE,EAAG,SAAS,WAAWL,GAAA,IAG/CnE;AAAA,MACT;AAAA,IAAA;AAAA,IAEF;AAAA,MACE,MAAM;AAAA;AAAA,MAEN,YAAY,CAACY,OAAW,EAAE,IAAIA,EAAM,GAAA;AAAA,IAAG;AAAA,EACzC;AAEJ;ACDA,IAAIkE,KAAgB;AAEpB,SAASC,IAAyB;AAChC,SAAO,QAAQ,EAAED,EAAa;AAChC;AAGA,SAASE,KAA6B;AACpC,QAAMC,IAAY,KAAK,IAAA,GACjBC,IAAS,KAAK,SAAS,SAAS,EAAE,EAAE,UAAU,GAAG,CAAC;AACxD,SAAO,MAAMD,CAAS,IAAIC,CAAM;AAClC;AAEO,MAAMC,IAAmBd,GAAA;AAAA,EAC9BlC;AAAA,IACE,CAAC1B,GAAKC,OAAS;AAAA,MACb,OAAO,CAAA;AAAA,MACP,OAAO,CAAA;AAAA,MACP,gBAAgB;AAAA,MAChB,mBAAmB;AAAA,MACnB,gBAAgB,CAAA;AAAA,MAChB,YAAY,CAAA;AAAA,MACZ,YAAY,CAAA;AAAA,MACZ,eAAe,CAAA;AAAA,MACf,iBAAiB,CAAA;AAAA;AAAA,MAGjB,gBAAgB,CAAA;AAAA,MAChB,kBAAkB;AAAA,MAClB,oBAAoB;AAAA,MACpB,mBAAmB;AAAA,MACnB,aAAa;AAAA,MAEb,WAAW;AAAA,QACT,QAAQ;AAAA,QACR,UAAU,CAAA;AAAA,QACV,WAAW,CAAA;AAAA,QACX,UAAU,CAAA;AAAA,QACV,aAAa,CAAA;AAAA,QACb,YAAY,CAAA;AAAA,MAAC;AAAA,MAGf,cAAc,CAAC0E,MAAa;AAE1B,cAAMC,wBAAY,IAAA,GAEZvC,IAA0BsC,EAAS,SAAS,MAAM,IAAI,CAACE,MAAe;AAC1E,gBAAMC,IAAQR,EAAA;AACd,iBAAAM,EAAM,IAAIC,EAAW,IAAIC,CAAK,GAEvB;AAAA,YACL,IAAIA;AAAA,YACJ,MAAMD,EAAW;AAAA,YACjB,UAAUA,EAAW;AAAA,YACrB,MAAMA,EAAW;AAAA,UAAA;AAAA,QAErB,CAAC,GAGKvC,IAAgBqC,EAAS,SAAS,MAAM,IAAI,CAACI,MAAe;AAChE,gBAAMC,IAAYJ,EAAM,IAAIG,EAAW,MAAM,KAAKA,EAAW,QACvDE,IAAYL,EAAM,IAAIG,EAAW,MAAM,KAAKA,EAAW;AAE7D,iBAAO;AAAA,YACL,IAAI,QAAQC,CAAS,IAAIC,CAAS;AAAA,YAClC,QAAQD;AAAA,YACR,QAAQC;AAAA,UAAA;AAAA,QAEZ,CAAC;AAED,QAAAjF,EAAI;AAAA,UACF,OAAAqC;AAAA,UACA,OAAAC;AAAA,UACA,gBAAgB;AAAA,UAChB,mBAAmBqC,EAAS;AAAA,UAC5B,gBAAgB,CAAA;AAAA,UAChB,WAAW;AAAA,YACT,QAAQ;AAAA,YACR,UAAU,CAAA;AAAA,YACV,WAAW,CAAA;AAAA,YACX,UAAU,CAAA;AAAA,YACV,aAAa,CAAA;AAAA,YACb,YAAY,CAAA;AAAA,UAAC;AAAA,QACf,CACD;AAAA,MACH;AAAA,MAEA,eAAe,MAAM;AACnB,QAAA3E,EAAI;AAAA,UACF,OAAO,CAAA;AAAA,UACP,OAAO,CAAA;AAAA,UACP,gBAAgB;AAAA,UAChB,mBAAmB;AAAA,UACnB,gBAAgB,CAAA;AAAA,UAChB,WAAW;AAAA,YACT,QAAQ;AAAA,YACR,UAAU,CAAA;AAAA,YACV,WAAW,CAAA;AAAA,YACX,UAAU,CAAA;AAAA,YACV,aAAa,CAAA;AAAA,YACb,YAAY,CAAA;AAAA,UAAC;AAAA,QACf,CACD;AAAA,MACH;AAAA,MAEA,eAAe,CAAC2C,MAAO;AACrB,QAAA3C,EAAI,CAACG,OAAW;AAAA,UACd,gBAAgB;AAAA,YACd,GAAGA,EAAM;AAAA,YACT,CAACwC,CAAE,GAAGxC,EAAM,eAAewC,CAAE,MAAM;AAAA;AAAA,UAAe;AAAA,QACpD,EACA;AAAA,MACJ;AAAA,MAEA,eAAe,CAACuC,MAAelF,EAAI,EAAE,YAAAkF,GAAY;AAAA,MACjD,eAAe,CAACC,MAAenF,EAAI,EAAE,YAAAmF,GAAY;AAAA,MACjD,kBAAkB,CAACC,MAAkBpF,EAAI,EAAE,eAAAoF,GAAe;AAAA,MAC1D,oBAAoB,CAACC,MAAoBrF,EAAI,EAAE,iBAAAqF,GAAiB;AAAA,MAEhE,SAAS,CAACC,GAAYC,MAAa;;AACjC,cAAM5C,IAAK2B,EAAA;AACX,YAAIkB;AAEJ,YAAIF,EAAW,SAAS;AACtB,UAAAE,IAAO;AAAA,YACL,eAAeF,EAAW;AAAA,YAC1B,QAAQG,EAAiBH,CAAU;AAAA,YACnC,MAAMA,EAAW;AAAA;AAAA,YACjB,wBAAwBA,EAAW;AAAA,YACnC,oBAAoBA,EAAW;AAAA,UAAA;AAAA,iBAExBA,EAAW,SAAS;AAC7B,UAAAE,IAAO;AAAA,YACL,WAAWF,EAAW;AAAA,YACtB,cAAcA,EAAW;AAAA;AAAA,YACzB,MAAMA,EAAW;AAAA;AAAA,YACjB,QAAQG,EAAiBH,CAAU;AAAA,YACnC,wBAAwBA,EAAW;AAAA,YACnC,oBAAoBA,EAAW;AAAA,UAAA;AAAA,iBAExBA,EAAW,SAAS;AAC7B,UAAAE,IAAO;AAAA,YACL,UAAU;AAAA,YACV,UAAU;AAAA,YACV,MAAM;AAAA,UAAA;AAAA,iBAECF,EAAW,SAAS;AAC7B,UAAAE,IAAO;AAAA,YACL,cAAcF,EAAW;AAAA,YACzB,eAAeA,EAAW;AAAA;AAAA,YAC1B,QAAQG,EAAiBH,CAAU;AAAA,UAAA;AAAA,iBAE5BA,EAAW,SAAS;AAC7B,UAAAE,IAAO;AAAA,YACL,cAAcF,EAAW;AAAA,YACzB,eAAeA,EAAW;AAAA;AAAA,YAC1B,QAAQG,EAAiBH,CAAU;AAAA,UAAA;AAAA,aAEhC;AAEL,gBAAMI,MAAQ3G,IAAAuG,EAAW,WAAX,gBAAAvG,EAAmB,eAAc,CAAA,GACzC8E,MAAY7C,IAAA0E,EAAM,aAAN,gBAAA1E,EAAgB,YAAsB;AAExD,UAAAwE,IAAO;AAAA,YACL,eAFmBxB,IAAA0B,EAAM,gBAAN,gBAAA1B,EAAmB,YAAsB;AAAA,YAG5D,UAAAH;AAAA,UAAA;AAAA,QAEJ;AAEA,cAAM8B,IAA0B;AAAA,UAC9B,IAAAhD;AAAA,UACA,MAAM2C,EAAW;AAAA,UACjB,UAAAC;AAAA,UACA,MAAAC;AAAA,QAAA;AAGF,QAAAxF,EAAI,CAACG,OAAW;AAAA,UACd,OAAO,CAAC,GAAGA,EAAM,OAAOwF,CAAO;AAAA,QAAA,EAC/B;AAAA,MACJ;AAAA,MAEA,gBAAgB,CAAChD,GAAI6C,MAAS;AAC5B,QAAAxF,EAAI,CAACG,OAAW;AAAA,UACd,OAAOA,EAAM,MAAM;AAAA,YAAI,CAACyF,MACtBA,EAAK,OAAOjD,IAAK,EAAE,GAAGiD,GAAM,MAAM,EAAE,GAAGA,EAAK,MAAM,GAAGJ,EAAA,MAAWI;AAAA,UAAA;AAAA,QAClE,EACA;AAAA,MACJ;AAAA,MAEA,YAAY,CAACjD,MAAO;AAClB,QAAA3C,EAAI,CAACG,OAAW;AAAA,UACd,OAAOA,EAAM,MAAM,OAAO,CAAC0F,MAAMA,EAAE,OAAOlD,CAAE;AAAA,UAC5C,OAAOxC,EAAM,MAAM,OAAO,CAACT,MAAMA,EAAE,WAAWiD,KAAMjD,EAAE,WAAWiD,CAAE;AAAA,UACnE,gBAAgBxC,EAAM,mBAAmBwC,IAAK,OAAOxC,EAAM;AAAA,QAAA,EAC3D;AAAA,MACJ;AAAA,MAEA,eAAe,CAACwC,MAAO;AACrB,cAAMxC,IAAQF,EAAA,GACR6F,IAAkB3F,EAAM,MAAM,KAAK,CAAC0F,MAAMA,EAAE,OAAOlD,CAAE;AAC3D,YAAI,CAACmD,EAAiB;AAEtB,cAAMhB,IAAQR,EAAA,GACRqB,IAA0B;AAAA,UAC9B,GAAGG;AAAA,UACH,IAAIhB;AAAA,UACJ,UAAU;AAAA,YACR,GAAGgB,EAAgB,SAAS,IAAI;AAAA,YAChC,GAAGA,EAAgB,SAAS,IAAI;AAAA,UAAA;AAAA,UAElC,MAAM,KAAK,MAAM,KAAK,UAAUA,EAAgB,IAAI,CAAC;AAAA;AAAA,UACrD,UAAU;AAAA,QAAA;AAGZ,QAAA9F,EAAI;AAAA,UACF,OAAO,CAAC,GAAGG,EAAM,OAAOwF,CAAO;AAAA,UAC/B,gBAAgBb;AAAA;AAAA,QAAA,CACjB;AAAA,MACH;AAAA,MAEA,UAAU,CAACzC,MAAUrC,EAAI,EAAE,OAAAqC,GAAO;AAAA,MAElC,SAAS,CAAC0D,MAAe;AACvB,YAAI,CAACA,EAAW,UAAU,CAACA,EAAW,OAAQ;AAG9C,cAAMC,IAAe,CAACD,EAAW,cAAcA,EAAW,YAAY,EACnE,OAAO,OAAO,EACd,KAAK,GAAG,GAKLE,IAAgB;AAAA,UACpB,IALSD,IACP,QAAQD,EAAW,MAAM,IAAIA,EAAW,MAAM,IAAIC,CAAY,KAC9D,QAAQD,EAAW,MAAM,IAAIA,EAAW,MAAM;AAAA,UAIhD,QAAQA,EAAW;AAAA,UACnB,QAAQA,EAAW;AAAA,UACnB,cAAcA,EAAW,gBAAgB;AAAA,UACzC,cAAcA,EAAW,gBAAgB;AAAA,QAAA;AAG3C,QAAA/F,EAAI,CAACG,OAAW;AAAA,UACd,OAAO,CAAC,GAAGA,EAAM,OAAO8F,CAAO;AAAA,QAAA,EAC/B;AAAA,MACJ;AAAA,MAEA,YAAY,CAACtD,MAAO;AAClB,QAAA3C,EAAI,CAACG,OAAW;AAAA,UACd,OAAOA,EAAM,MAAM,OAAO,CAACT,MAAMA,EAAE,OAAOiD,CAAE;AAAA,QAAA,EAC5C;AAAA,MACJ;AAAA,MAEA,UAAU,CAACL,MAAUtC,EAAI,EAAE,OAAAsC,GAAO;AAAA,MAElC,iBAAiB,CAACK,MAAO3C,EAAI,EAAE,gBAAgB2C,GAAI;AAAA,MAEnD,SAAS,YAAY;AACnB,cAAM,EAAE,OAAAN,GAAO,OAAAC,EAAA,IAAUrC,EAAA,GAGnBiG,IAAc7D,EAAM,IAAI,CAACwD,OAAO;AAAA,UACpC,IAAIA,EAAE;AAAA,UACN,MAAMA,EAAE;AAAA,UACR,UAAUA,EAAE;AAAA,UACZ,MAAMA,EAAE;AAAA,QAAA,EACR,GAEIM,IAAc7D,EAAM,IAAI,CAAC5C,OAAO;AAAA,UACpC,IAAIA,EAAE;AAAA,UACN,QAAQA,EAAE;AAAA,UACV,QAAQA,EAAE;AAAA,UACV,cAAcA,EAAE,gBAAgB;AAAA,UAChC,cAAcA,EAAE,gBAAgB;AAAA,QAAA,EAChC,GAGI6C,IAAcoB,EAAiB,SAAA,EAAW,uBAAA,GAG1CyC,IAAyD,CAAA;AAC/D,mBAAWR,KAAQvD;AACjB,UAAA+D,EAAkBR,EAAK,EAAE,IAAI;AAG/B,QAAA5F,EAAI;AAAA,UACF,WAAW;AAAA,YACT,QAAQ;AAAA,YACR,UAAU,CAAA;AAAA,YACV,WAAW,CAAA;AAAA,YACX,UAAU,CAAA;AAAA,YACV,aAAa,CAAA;AAAA,YACb,YAAYoG;AAAA,UAAA;AAAA,QACd,CACD;AAED,YAAI;AACF,gBAAM7G,IAAS,MAAM6C,GAAgB8D,GAAaC,GAAa5D,CAAW,GAGpE8D,IAAuD,CAAA;AAC7D,qBAAWT,KAAQvD;AACjB,YAAAgE,EAAgBT,EAAK,EAAE,IAAIrG,EAAO,WAAW,cAAc,cAAc;AAG3E,UAAIA,EAAO,WAAW,cACpBS,EAAI;AAAA,YACF,WAAW;AAAA,cACT,QAAQ;AAAA,cACR,UAAUT,EAAO;AAAA,cACjB,WAAWA,EAAO,aAAa,CAAA;AAAA,cAC/B,UAAUA,EAAO,YAAY,CAAA;AAAA,cAC7B,aAAaA,EAAO,eAAe,CAAA;AAAA,cACnC,YAAY8G;AAAA,YAAA;AAAA,UACd,CACD,IAEDrG,EAAI;AAAA,YACF,WAAW;AAAA,cACT,QAAQ;AAAA,cACR,UAAU,CAAA;AAAA,cACV,WAAW,CAAA;AAAA,cACX,UAAU,CAAA;AAAA,cACV,aAAa,CAAA;AAAA,cACb,YAAYqG;AAAA,cACZ,OAAO9G,EAAO;AAAA,YAAA;AAAA,UAChB,CACD;AAAA,QAEL,SAASwC,GAAO;AAEd,gBAAMuE,IAAuD,CAAA;AAC7D,qBAAWV,KAAQvD;AACjB,YAAAiE,EAAgBV,EAAK,EAAE,IAAI;AAG7B,UAAA5F,EAAI;AAAA,YACF,WAAW;AAAA,cACT,QAAQ;AAAA,cACR,UAAU,CAAA;AAAA,cACV,WAAW,CAAA;AAAA,cACX,UAAU,CAAA;AAAA,cACV,aAAa,CAAA;AAAA,cACb,YAAYsG;AAAA,cACZ,OAAOvE,aAAiB,QAAQA,EAAM,UAAU;AAAA,YAAA;AAAA,UAClD,CACD;AAAA,QACH;AAAA,MACF;AAAA,MAEA,cAAc,YAAY;AACxB,cAAM,EAAE,OAAAM,GAAO,OAAAC,EAAA,IAAUrC,EAAA,GAEnBiG,IAAc7D,EAAM,IAAI,CAACwD,OAAO;AAAA,UACpC,IAAIA,EAAE;AAAA,UACN,MAAMA,EAAE;AAAA,UACR,UAAUA,EAAE;AAAA,UACZ,MAAMA,EAAE;AAAA,QAAA,EACR,GAEIM,IAAc7D,EAAM,IAAI,CAAC5C,OAAO;AAAA,UACpC,IAAIA,EAAE;AAAA,UACN,QAAQA,EAAE;AAAA,UACV,QAAQA,EAAE;AAAA,UACV,cAAcA,EAAE,gBAAgB;AAAA,UAChC,cAAcA,EAAE,gBAAgB;AAAA,QAAA,EAChC;AAGF,gBADe,MAAM8C,GAAW0D,GAAaC,CAAW,GAC1C;AAAA,MAChB;AAAA,MAEA,gBAAgB,CAACD,GAAaC,GAAarH,MAAS;AAElD,cAAM8F,wBAAY,IAAA,GAEZvC,IAA0B6D,EAAY,IAAI,CAACrB,MAAe;AAC9D,gBAAMC,IAAQR,EAAA;AACd,iBAAAM,EAAM,IAAIC,EAAW,IAAIC,CAAK,GAEvB;AAAA,YACL,IAAIA;AAAA,YACJ,MAAMD,EAAW;AAAA,YACjB,UAAUA,EAAW;AAAA,YACrB,MAAMA,EAAW;AAAA,UAAA;AAAA,QAErB,CAAC,GAGKvC,IAAgB6D,EAAY,IAAI,CAACpB,MAAe;AACpD,gBAAMC,IAAYJ,EAAM,IAAIG,EAAW,MAAM,KAAKA,EAAW,QACvDE,IAAYL,EAAM,IAAIG,EAAW,MAAM,KAAKA,EAAW;AAE7D,iBAAO;AAAA,YACL,IAAI,QAAQC,CAAS,IAAIC,CAAS;AAAA,YAClC,QAAQD;AAAA,YACR,QAAQC;AAAA,UAAA;AAAA,QAEZ,CAAC;AAED,QAAAjF,EAAI;AAAA,UACF,OAAAqC;AAAA,UACA,OAAAC;AAAA,UACA,gBAAgB;AAAA,UAChB,mBAAmB;AAAA,UACnB,gBAAgB,CAAA;AAAA,UAChB,kBAAkB;AAAA,UAClB,oBAAoBxD,KAAQ;AAAA,UAC5B,mBAAmB;AAAA,UACnB,WAAW;AAAA,YACT,QAAQ;AAAA,YACR,UAAU,CAAA;AAAA,YACV,WAAW,CAAA;AAAA,YACX,UAAU,CAAA;AAAA,YACV,aAAa,CAAA;AAAA,YACb,YAAY,CAAA;AAAA,UAAC;AAAA,QACf,CACD;AAAA,MACH;AAAA;AAAA,MAGA,WAAW,MAAMkB,EAAI,EAAE,mBAAmB,IAAM;AAAA,MAEhD,eAAe,MAAMA,EAAI,CAACG,OAAW,EAAE,aAAa,CAACA,EAAM,YAAA,EAAc;AAAA,MAEzE,uBAAuB,CAACrB,MAASkB,EAAI,EAAE,oBAAoBlB,GAAM,mBAAmB,IAAM;AAAA,MAE1F,aAAa,MAAM;AACjB,QAAAkB,EAAI;AAAA,UACF,OAAO,CAAA;AAAA,UACP,OAAO,CAAA;AAAA,UACP,gBAAgB;AAAA,UAChB,mBAAmB;AAAA,UACnB,gBAAgB,CAAA;AAAA,UAChB,kBAAkB;AAAA,UAClB,oBAAoB;AAAA,UACpB,mBAAmB;AAAA,UACnB,WAAW;AAAA,YACT,QAAQ;AAAA,YACR,UAAU,CAAA;AAAA,YACV,WAAW,CAAA;AAAA,YACX,UAAU,CAAA;AAAA,YACV,aAAa,CAAA;AAAA,YACb,YAAY,CAAA;AAAA,UAAC;AAAA,QACf,CACD;AAAA,MACH;AAAA,MAEA,cAAc,CAAClB,MAAS;AACtB,cAAM;AAAA,UACJ,OAAAuD;AAAA,UACA,OAAAC;AAAA,UACA,kBAAAiE;AAAA,UACA,oBAAAC;AAAA,UACA,gBAAAC;AAAA,UACA,mBAAAC;AAAA,QAAA,IACEzG,EAAA,GACE0G,IAAM,KAAK,IAAA;AAEjB,YAAIJ,GAAkB;AAEpB,gBAAMK,IAAUH,EAAe;AAAA,YAAI,CAACI,MAClCA,EAAG,OAAON,IACN,EAAE,GAAGM,GAAI,MAAM/H,KAAQ0H,GAAoB,OAAAnE,GAAO,OAAAC,GAAO,WAAWqE,MACpEE;AAAA,UAAA;AAEN,iBAAA7G,EAAI;AAAA,YACF,gBAAgB4G;AAAA,YAChB,oBAAoB9H,KAAQ0H;AAAA,YAC5B,mBAAmB;AAAA,UAAA,CACpB,GACMD;AAAA,QACT,OAAO;AAEL,gBAAM5D,IAAK4B,GAAA,GACLuC,IAA6B;AAAA,YACjC,IAAAnE;AAAA,YACA,MAAM7D,KAAQ0H;AAAA,YACd,OAAAnE;AAAA,YACA,OAAAC;AAAA,YACA,WAAWqE;AAAA,YACX,WAAWA;AAAA,YACX,YAAYD,KAAqB;AAAA,UAAA;AAEnC,iBAAA1G,EAAI;AAAA,YACF,gBAAgB,CAAC,GAAGyG,GAAgBK,CAAW;AAAA,YAC/C,kBAAkBnE;AAAA,YAClB,oBAAoB7D,KAAQ0H;AAAA,YAC5B,mBAAmB;AAAA,UAAA,CACpB,GACM7D;AAAA,QACT;AAAA,MACF;AAAA,MAEA,cAAc,CAACA,MAAO;AACpB,cAAM,EAAE,gBAAA8D,EAAA,IAAmBxG,EAAA,GACrB8G,IAAWN,EAAe,KAAK,CAACI,MAAOA,EAAG,OAAOlE,CAAE;AACzD,QAAKoE,KAEL/G,EAAI;AAAA,UACF,OAAO+G,EAAS;AAAA,UAChB,OAAOA,EAAS;AAAA,UAChB,gBAAgB;AAAA,UAChB,mBAAmBA,EAAS,cAAc;AAAA,UAC1C,gBAAgB,CAAA;AAAA,UAChB,kBAAkBpE;AAAA,UAClB,oBAAoBoE,EAAS;AAAA,UAC7B,mBAAmB;AAAA,UACnB,WAAW;AAAA,YACT,QAAQ;AAAA,YACR,UAAU,CAAA;AAAA,YACV,WAAW,CAAA;AAAA,YACX,UAAU,CAAA;AAAA,YACV,aAAa,CAAA;AAAA,YACb,YAAY,CAAA;AAAA,UAAC;AAAA,QACf,CACD;AAAA,MACH;AAAA,MAEA,gBAAgB,CAACpE,MAAO;AACtB,cAAM,EAAE,gBAAA8D,GAAgB,kBAAAF,EAAA,IAAqBtG,EAAA,GACvC+G,IAAWP,EAAe,OAAO,CAACI,MAAOA,EAAG,OAAOlE,CAAE;AAE3D,QAEE3C,EAFEuG,MAAqB5D,IAEnB;AAAA,UACF,gBAAgBqE;AAAA,UAChB,OAAO,CAAA;AAAA,UACP,OAAO,CAAA;AAAA,UACP,gBAAgB;AAAA,UAChB,mBAAmB;AAAA,UACnB,gBAAgB,CAAA;AAAA,UAChB,kBAAkB;AAAA,UAClB,oBAAoB;AAAA,UACpB,mBAAmB;AAAA,UACnB,WAAW;AAAA,YACT,QAAQ;AAAA,YACR,UAAU,CAAA;AAAA,YACV,WAAW,CAAA;AAAA,YACX,UAAU,CAAA;AAAA,YACV,aAAa,CAAA;AAAA,YACb,YAAY,CAAA;AAAA,UAAC;AAAA,QACf,IAGE,EAAE,gBAAgBA,GAFrB;AAAA,MAIL;AAAA,MAEA,gBAAgB,CAACrE,GAAI7D,MAAS;AAC5B,cAAM,EAAE,gBAAA2H,GAAgB,kBAAAF,EAAA,IAAqBtG,EAAA,GACvC2G,IAAUH,EAAe;AAAA,UAAI,CAACI,MAClCA,EAAG,OAAOlE,IAAK,EAAE,GAAGkE,GAAI,MAAA/H,GAAM,WAAW,KAAK,IAAA,MAAU+H;AAAA,QAAA;AAE1D,QAAA7G,EAAI;AAAA,UACF,gBAAgB4G;AAAA,UAChB,GAAIL,MAAqB5D,IAAK,EAAE,oBAAoB7D,EAAA,IAAS,CAAA;AAAA,QAAC,CAC/D;AAAA,MACH;AAAA,MAEA,mBAAmB,CAAC6D,MAAO;AACzB,cAAM,EAAE,gBAAA8D,EAAA,IAAmBxG,EAAA,GACrB8G,IAAWN,EAAe,KAAK,CAACI,MAAOA,EAAG,OAAOlE,CAAE;AACzD,YAAI,CAACoE,EAAU,QAAO;AAEtB,cAAMJ,IAAM,KAAK,IAAA,GACX7B,IAAQP,GAAA,GACR0C,IAA2B;AAAA,UAC/B,GAAGF;AAAA,UACH,IAAIjC;AAAA,UACJ,MAAM,GAAGiC,EAAS,IAAI;AAAA,UACtB,WAAWJ;AAAA,UACX,WAAWA;AAAA,QAAA;AAEb,eAAA3G,EAAI,EAAE,gBAAgB,CAAC,GAAGyG,GAAgBQ,CAAS,GAAG,GAC/CnC;AAAA,MACT;AAAA,MAEA,uBAAuB,CAACiC,MAAoC;AAE1D,cAAMnC,wBAAY,IAAA,GAGZsC,IAAiB,KACjBC,IAAiB,KACjBC,IAAgB,GAEhB/E,IAA0B0E,EAAS,MAAM,IAAI,CAACM,GAASC,MAAU;AACrE,gBAAMxC,IAAQR,EAAA;AACd,UAAAM,EAAM,IAAIyC,EAAQ,IAAIvC,CAAK;AAI3B,gBAAMyC,IAAQF,EAAQ,SAAS,MAAM,GAAG,GAClCG,IAAWD,EAAM,CAAC,GAGlBE,IAAM,KAAK,MAAMH,IAAQF,CAAa,GAEtC7B,IAAW;AAAA,YACf,GAAG,MAFO+B,IAAQF,IAEHF;AAAA,YACf,GAAG,MAAMO,IAAMN;AAAA,UAAA;AAIjB,cAAI3B;AAEJ,cAAIgC,MAAa;AAEf,YAAAhC,IAAO;AAAA,cACL,eAFoB+B,EAAM,MAAM,CAAC,EAAE,KAAK,GAAG;AAAA,cAG3C,QAAQF,EAAQ;AAAA,cAChB,MAAM;AAAA;AAAA,YAAA;AAAA,mBAECG,MAAa,aAAa;AACnC,kBAAME,IAAeH,EAAM,CAAC;AAE5B,YAAA/B,IAAO;AAAA,cACL,WAFgB+B,EAAM,MAAM,CAAC,EAAE,KAAK,GAAG;AAAA,cAGvC,cAAAG;AAAA,cACA,QAAQL,EAAQ;AAAA,YAAA;AAAA,UAEpB,WAAWG,MAAa;AACtB,YAAAhC,IAAO;AAAA,cACL,UAAU;AAAA,cACV,UAAU;AAAA,cACV,MAAM;AAAA,YAAA;AAAA,mBAECgC,MAAa;AAEtB,YAAAhC,IAAO;AAAA,cACL,cAFmB+B,EAAM,MAAM,CAAC,EAAE,KAAK,GAAG;AAAA,cAG1C,QAAQF,EAAQ;AAAA,YAAA;AAAA,mBAETG,MAAa,QAAQ;AAC9B,kBAAME,IAAeH,EAAM,MAAM,CAAC,EAAE,KAAK,GAAG,GAEtCI,IAAaN,EAAQ,WAAW,YAGhCO,IAAeD,KAAA,QAAAA,EAAY,aAC7B;AAAA,cACE,MAAM;AAAA,cACN,YAAY,OAAO;AAAA,gBACjB,OAAO,QAAQA,EAAW,UAAU,EAAE,IAAI,CAAC,CAACE,GAAKC,CAAI,MAAM;AAAA,kBACzDD;AAAA,kBACA;AAAA,oBACE,MACGC,EAAK,QACN;AAAA,oBACF,aAAaA,EAAK;AAAA,kBAAA;AAAA,gBACpB,CACD;AAAA,cAAA;AAAA,YACH,IAEF;AACJ,YAAAtC,IAAO;AAAA,cACL,cAAAkC;AAAA,cACA,QAAQL,EAAQ;AAAA,cAChB,cAAAO;AAAA,YAAA;AAAA,UAEJ;AAEE,YAAApC,IAAO;AAAA,cACL,aAAc6B,EAAQ,WAAW,eAA0B;AAAA,cAC3D,UAAWA,EAAQ,WAAW,YAAuB;AAAA,YAAA;AAIzD,iBAAO;AAAA,YACL,IAAIvC;AAAA,YACJ,MAAM0C;AAAA,YACN,UAAAjC;AAAA,YACA,MAAAC;AAAA,UAAA;AAAA,QAEJ,CAAC,GAGKlD,IAAgByE,EAAS,MAAM,IAAI,CAACgB,MAAY;AACpD,gBAAM/C,IAAYJ,EAAM,IAAImD,EAAQ,MAAM,KAAKA,EAAQ,QACjD9C,IAAYL,EAAM,IAAImD,EAAQ,MAAM,KAAKA,EAAQ,QAGjD/B,IAAe,CAAC+B,EAAQ,cAAcA,EAAQ,YAAY,EAC7D,OAAO,OAAO,EACd,KAAK,GAAG;AAKX,iBAAO;AAAA,YACL,IALa/B,IACX,QAAQhB,CAAS,IAAIC,CAAS,IAAIe,CAAY,KAC9C,QAAQhB,CAAS,IAAIC,CAAS;AAAA,YAIhC,QAAQD;AAAA,YACR,QAAQC;AAAA,YACR,cAAc8C,EAAQ,gBAAgB;AAAA,YACtC,cAAcA,EAAQ,gBAAgB;AAAA,UAAA;AAAA,QAE1C,CAAC;AAED,QAAA/H,EAAI;AAAA,UACF,OAAAqC;AAAA,UACA,OAAAC;AAAA,UACA,gBAAgB;AAAA,UAChB,mBAAmB;AAAA,UACnB,gBAAgB,CAAA;AAAA,UAChB,kBAAkB;AAAA,UAClB,oBAAoB;AAAA,UACpB,mBAAmB;AAAA,UACnB,WAAW;AAAA,YACT,QAAQ;AAAA,YACR,UAAU,CAAA;AAAA,YACV,WAAW,CAAA;AAAA,YACX,UAAU,CAAA;AAAA,YACV,aAAa,CAAA;AAAA,YACb,YAAY,CAAA;AAAA,UAAC;AAAA,QACf,CACD;AAAA,MACH;AAAA,IAAA;AAAA,IAEF;AAAA,MACE,MAAM;AAAA;AAAA,MAEN,YAAY,CAACnC,OAAW;AAAA,QACtB,gBAAgBA,EAAM;AAAA,MAAA;AAAA,IACxB;AAAA,EACF;AAEJ;AAGA,SAASsF,EAAiBH,GAAqD;;AAC7E,QAAM0C,IAAkC,CAAA;AAExC,OAAIjJ,IAAAuG,EAAW,WAAX,QAAAvG,EAAmB;AACrB,eAAW,CAAC8I,GAAKI,CAAK,KAAK,OAAO,QAAQ3C,EAAW,OAAO,UAAU;AACpE,MAAI2C,EAAM,YAAY,WACpBD,EAAOH,CAAG,IAAII,EAAM;AAK1B,SAAOD;AACT;ACv1BA,SAASE,EAAkBC,GAAwC;AACjE,SAAIA,MAAe,YACV,oCAELA,MAAe,cACV,qBAELA,MAAe,UACV,mBAEF;AACT;AAGA,SAASC,EAAc,EAAE,QAAAC,GAAQ,OAAAC,KAA4C;AAC3E,QAAMC,IAAiB7D,EAAiB,CAAC8D,MAAMA,EAAE,eAAeH,CAAM,MAAM,EAAK,GAC3EI,IAAgB/D,EAAiB,CAAC8D,MAAMA,EAAE,aAAa;AAE7D,SACE,gBAAAE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,SAAS,CAAChJ,MAAM;AACd,QAAAA,EAAE,gBAAA,GACF+I,EAAcJ,CAAM;AAAA,MACtB;AAAA,MACA,WAAW,kFAAkFE,IAAiB,gBAAgB,YAAY;AAAA,MAC1I,OAAOA,IAAiB,iBAAiB;AAAA,MAEzC,UAAA,gBAAAG,EAAC,OAAA,EAAI,WAAW,eAAeJ,CAAK,IAAI,MAAK,QAAO,QAAO,gBAAe,SAAQ,aAC/E,UAAAC,IACC,gBAAAG;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,eAAc;AAAA,UACd,gBAAe;AAAA,UACf,aAAa;AAAA,UACb,GAAE;AAAA,QAAA;AAAA,MAAA,IAGJ,gBAAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,eAAc;AAAA,UACd,gBAAe;AAAA,UACf,aAAa;AAAA,UACb,GAAE;AAAA,QAAA;AAAA,MAAA,EACJ,CAEJ;AAAA,IAAA;AAAA,EAAA;AAGN;AAIO,MAAMC,KAAgBC,EAAK,SAAuB;AAAA,EACvD,IAAAjG;AAAA,EACA,MAAA6C;AAAA,EACA,UAAAqD;AACF,GAAiC;AAC/B,QAAMC,IAAUpE,EAAiB,CAAC8D,MAAMA,EAAE,UAAU,SAAS7F,CAAE,CAAC,GAC1DwF,IAAazD,EAAiB,CAAC8D,MAAMA,EAAE,UAAU,WAAW7F,CAAE,CAAC,GAC/D4F,IAAiB7D,EAAiB,CAAC8D,MAAMA,EAAE,eAAe7F,CAAE,MAAM,EAAK,GAGvEoG,IADiBb,EAAkBC,CAAU,MACZU,IAAW,oBAAoB,oBAGhEG,IAAOxD,EAAK,MAEZyD,IAAoBzD,EAAK;AAE/B,SACE,gBAAA0D;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,yFAAyFH,CAAW;AAAA,MAG9G,UAAA;AAAA,QAAAC,KACC,gBAAAN;AAAA,UAACS;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,UAAUC,EAAS;AAAA,YACnB,IAAG;AAAA,YACH,WAAU;AAAA,YACV,OAAM;AAAA,UAAA;AAAA,QAAA;AAAA,QAITH,KACC,gBAAAP;AAAA,UAACS;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,UAAUC,EAAS;AAAA,YACnB,IAAG;AAAA,YACH,WAAU;AAAA,YACV,OAAO,EAAE,KAAK,MAAA;AAAA,YACd,OAAO,2BAA2B5D,EAAK,sBAAsB,EAAE;AAAA,UAAA;AAAA,QAAA;AAAA,QAGlEsD,KAAWP,KACV,gBAAAG,EAAC,OAAA,EAAI,WAAU,8EACb,UAAA,gBAAAA,EAAC,OAAA,EAAI,KAAKI,GAAS,KAAI,WAAU,WAAU,8BAA6B,GAC1E;AAAA,QAEF,gBAAAI,EAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,gCACb,UAAA;AAAA,YAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,mCAAA,CAAmC;AAAA,YAClD,gBAAAA,EAAC,QAAA,EAAK,WAAU,0DACb,YAAK,eACR;AAAA,YACA,gBAAAA,EAACN,GAAA,EAAc,QAAQzF,GAAI,OAAM,mCAAA,CAAmC;AAAA,UAAA,GACtE;AAAA,UACCqG,KACC,gBAAAN,EAAC,OAAA,EAAI,WAAU,qDAAoD,UAAA,0CAEnE;AAAA,UAEDO,KACC,gBAAAP,EAAC,OAAA,EAAI,WAAU,yDAAwD,UAAA,8BAEvE;AAAA,UAEF,gBAAAA,EAAC,OAAA,EAAI,WAAU,4CACZ,iBAAO,QAAQlD,EAAK,MAAM,EACxB,OAAO,CAAC,CAAA,EAAG6D,CAAK,MAAM,OAAOA,KAAU,YAAYA,MAAU,IAAI,EACjE,MAAM,GAAG,CAAC,EACV,IAAI,CAAC,CAACxB,GAAKwB,CAAK,MACf,gBAAAH,EAAC,OAAA,EAAc,WAAU,YACtB,UAAA;AAAA,YAAArB;AAAA,YAAI;AAAA,YAAG,OAAOwB,CAAK,EAAE,MAAM,GAAG,EAAE;AAAA,UAAA,EAAA,GADzBxB,CAEV,CACD,EAAA,CACL;AAAA,QAAA,GACF;AAAA,QACA,gBAAAa,EAACS,KAAO,MAAK,UAAS,UAAUC,EAAS,OAAO,WAAU,uBAAA,CAAuB;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGvF,CAAC,GAKYE,KAAgBV,EAAK,SAAuB;AAAA,EACvD,IAAAjG;AAAA,EACA,MAAA6C;AAAA,EACA,UAAAqD;AACF,GAAiC;AAC/B,QAAMC,IAAUpE,EAAiB,CAAC8D,MAAMA,EAAE,UAAU,SAAS7F,CAAE,CAAC,GAC1DwF,IAAazD,EAAiB,CAAC8D,MAAMA,EAAE,UAAU,WAAW7F,CAAE,CAAC,GAC/D4F,IAAiB7D,EAAiB,CAAC8D,MAAMA,EAAE,eAAe7F,CAAE,MAAM,EAAK,GAGvEoG,IADiBb,EAAkBC,CAAU,MACZU,IAAW,oBAAoB,oBAGhEG,IAAOxD,EAAK,MAEZyD,IAAoBzD,EAAK;AAE/B,SACE,gBAAA0D;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,yFAAyFH,CAAW;AAAA,MAG9G,UAAA;AAAA,QAAAC,KACC,gBAAAN;AAAA,UAACS;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,UAAUC,EAAS;AAAA,YACnB,IAAG;AAAA,YACH,WAAU;AAAA,YACV,OAAM;AAAA,UAAA;AAAA,QAAA;AAAA,QAIV,gBAAAV,EAACS,GAAA,EAAO,MAAK,UAAS,UAAUC,EAAS,MAAM,IAAG,SAAQ,WAAU,uBAAA,CAAuB;AAAA,QAE1FH,KACC,gBAAAP;AAAA,UAACS;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,UAAUC,EAAS;AAAA,YACnB,IAAG;AAAA,YACH,WAAU;AAAA,YACV,OAAO,2BAA2B5D,EAAK,sBAAsB,EAAE;AAAA,UAAA;AAAA,QAAA;AAAA,QAGlEsD,KAAWP,KACV,gBAAAG,EAAC,OAAA,EAAI,WAAU,8EACb,UAAA,gBAAAA,EAAC,OAAA,EAAI,KAAKI,GAAS,KAAI,WAAU,WAAU,8BAA6B,GAC1E;AAAA,QAEF,gBAAAI,EAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,gCACZ,UAAA;AAAA,YAAAF,sBACE,OAAA,EAAI,WAAU,2BAA0B,MAAK,gBAAe,SAAQ,aACnE,UAAA;AAAA,cAAA,gBAAAN,EAAC,QAAA,EAAK,GAAE,iBAAA,CAAiB;AAAA,cACzB,gBAAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,UAAS;AAAA,kBACT,GAAE;AAAA,kBACF,UAAS;AAAA,gBAAA;AAAA,cAAA;AAAA,YACX,EAAA,CACF,IAEA,gBAAAA,EAAC,OAAA,EAAI,WAAU,mCAAA,CAAmC;AAAA,YAEpD,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAW,yBAAyBM,IAAO,yCAAyC,kCAAkC;AAAA,gBAErH,UAAAxD,EAAK;AAAA,cAAA;AAAA,YAAA;AAAA,YAER,gBAAAkD;AAAA,cAACN;AAAA,cAAA;AAAA,gBACC,QAAQzF;AAAA,gBACR,OACEqG,IAAO,yCAAyC;AAAA,cAAA;AAAA,YAAA;AAAA,UAEpD,GACF;AAAA,UACCA,KACC,gBAAAN,EAAC,OAAA,EAAI,WAAU,qDAAoD,UAAA,0CAEnE;AAAA,UAEDO,KACC,gBAAAP,EAAC,OAAA,EAAI,WAAU,yDAAwD,UAAA,8BAEvE;AAAA,UAEF,gBAAAA,EAAC,OAAA,EAAI,WAAU,4CACZ,iBAAO,QAAQlD,EAAK,MAAM,EACxB,OAAO,CAAC,CAAA,EAAG6D,CAAK,MAAM,OAAOA,KAAU,YAAYA,MAAU,IAAI,EACjE,MAAM,GAAG,CAAC,EACV,IAAI,CAAC,CAACxB,GAAKwB,CAAK,MACf,gBAAAH,EAAC,OAAA,EAAc,WAAU,YACtB,UAAA;AAAA,YAAArB;AAAA,YAAI;AAAA,YAAG,OAAOwB,CAAK,EAAE,MAAM,GAAG,EAAE;AAAA,UAAA,EAAA,GADzBxB,CAEV,CACD,EAAA,CACL;AAAA,QAAA,GACF;AAAA,QACA,gBAAAa,EAACS,KAAO,MAAK,UAAS,UAAUC,EAAS,OAAO,WAAU,uBAAA,CAAuB;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGvF,CAAC,GAGYG,KAAWX,EAAK,SAAkB,EAAE,IAAAjG,GAAI,MAAA6C,GAAM,UAAAqD,KAAqC;AAC9F,QAAMV,IAAazD,EAAiB,CAAC8D,MAAMA,EAAE,UAAU,WAAW7F,CAAE,CAAC,GAG/DoG,IADiBb,EAAkBC,CAAU,MACZU,IAAW,qBAAqB;AAEvE,SACE,gBAAAK;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,mFAAmFH,CAAW;AAAA,MAEzG,UAAA;AAAA,QAAA,gBAAAL,EAACS,KAAO,MAAK,UAAS,UAAUC,EAAS,MAAM,WAAU,yBAAwB;AAAA,QACjF,gBAAAF,EAAC,OAAA,EAAI,WAAU,gCACb,UAAA;AAAA,UAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,oCAAA,CAAoC;AAAA,UACnD,gBAAAA,EAAC,QAAA,EAAK,WAAU,4DAA2D,UAAA,OAAA,CAAI;AAAA,QAAA,GACjF;AAAA,QACA,gBAAAA,EAAC,OAAA,EAAI,WAAU,qDAAqD,YAAK,YAAA,CAAY;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAG3F,CAAC,GAGYc,KAAYZ,EAAK,SAAmB,EAAE,IAAAjG,GAAI,MAAA6C,GAAM,UAAAqD,KAAsC;AACjG,QAAMC,IAAUpE,EAAiB,CAAC8D,MAAMA,EAAE,UAAU,SAAS7F,CAAE,CAAC,GAC1DwF,IAAazD,EAAiB,CAAC8D,MAAMA,EAAE,UAAU,WAAW7F,CAAE,CAAC,GAC/D4F,IAAiB7D,EAAiB,CAAC8D,MAAMA,EAAE,eAAe7F,CAAE,MAAM,EAAK,GACvE8G,IAAiB/E,EAAiB,CAAC8D,MAAMA,EAAE,cAAc,GACzDkB,IAAeC,EAAyB,IAAI,GAG5CZ,IADiBb,EAAkBC,CAAU,MACZU,IAAW,qBAAqB,qBAGjEe,IAAmBC;AAAA,IACvB,OAAO/G,MAAe;AACpB,UAAI;AACF,cAAMvD,IAAS,MAAMsD,GAAYC,CAAI;AACrC,QAAA2G,EAAe9G,GAAI;AAAA,UACjB,UAAUpD,EAAO;AAAA,UACjB,UAAUA,EAAO;AAAA,UACjB,MAAMA,EAAO;AAAA,QAAA,CACd;AAAA,MACH,SAASwC,GAAO;AACd,gBAAQ,MAAM,kBAAkBA,CAAK;AAAA,MACvC;AAAA,IACF;AAAA,IACA,CAACY,GAAI8G,CAAc;AAAA,EAAA,GAIfK,IAAaD;AAAA,IACjB,CAACnK,MAAuB;AACtB,MAAAA,EAAE,eAAA,GACFA,EAAE,gBAAA;AACF,YAAMoD,IAAOpD,EAAE,aAAa,MAAM,CAAC;AACnC,MAAIoD,KAAQA,EAAK,KAAK,WAAW,QAAQ,KACvC8G,EAAiB9G,CAAI;AAAA,IAEzB;AAAA,IACA,CAAC8G,CAAgB;AAAA,EAAA,GAGbG,IAAiBF,EAAY,CAACnK,MAAuB;AACzD,IAAAA,EAAE,eAAA,GACFA,EAAE,gBAAA;AAAA,EACJ,GAAG,CAAA,CAAE,GAGCsK,IAAoBH;AAAA,IACxB,CAACnK,MAA2C;;AAC1C,YAAMoD,KAAO/D,IAAAW,EAAE,OAAO,UAAT,gBAAAX,EAAiB;AAC9B,MAAI+D,KACF8G,EAAiB9G,CAAI;AAAA,IAEzB;AAAA,IACA,CAAC8G,CAAgB;AAAA,EAAA,GAIbK,IAAanB,MAAYtD,EAAK,WAAWtC,GAAiBsC,EAAK,QAAQ,IAAI;AAEjF,SACE,gBAAA0D;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,yFAAyFH,CAAW;AAAA,MAC/G,QAAQe;AAAA,MACR,YAAYC;AAAA,MAEX,UAAA;AAAA,QAAAE,KAAc1B,IACb,gBAAAG,EAAC,OAAA,EAAI,WAAU,8EACb,4BAAC,OAAA,EAAI,KAAKuB,GAAY,KAAI,YAAW,WAAU,6BAAA,CAA6B,EAAA,CAC9E,IACGA,IAUD,OATF,gBAAAvB;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,SAAS,MAAA;;AAAM,sBAAA3J,IAAA2K,EAAa,YAAb,gBAAA3K,EAAsB;AAAA;AAAA,YAErC,UAAA,gBAAAmK,EAAC,OAAA,EAAI,WAAU,kDACb,UAAA;AAAA,cAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,iBAAgB,UAAA,KAAC;AAAA,cAChC,gBAAAA,EAAC,OAAA,EAAI,WAAU,WAAU,UAAA,sBAAA,CAAmB;AAAA,YAAA,EAAA,CAC9C;AAAA,UAAA;AAAA,QAAA;AAAA,QAGJ,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,KAAKgB;AAAA,YACL,MAAK;AAAA,YACL,QAAO;AAAA,YACP,WAAU;AAAA,YACV,UAAUM;AAAA,UAAA;AAAA,QAAA;AAAA,QAEZ,gBAAAd,EAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,gCACb,UAAA;AAAA,YAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,oCAAA,CAAoC;AAAA,YACnD,gBAAAA,EAAC,QAAA,EAAK,WAAU,4DAA2D,UAAA,SAAK;AAAA,YAChF,gBAAAA,EAACN,GAAA,EAAc,QAAQzF,GAAI,OAAM,qCAAA,CAAqC;AAAA,UAAA,GACxE;AAAA,4BACC,OAAA,EAAI,WAAU,qDACZ,UAAA6C,EAAK,YAAY,oBAAA,CACpB;AAAA,QAAA,GACF;AAAA,QACA,gBAAAkD,EAACS,KAAO,MAAK,UAAS,UAAUC,EAAS,OAAO,WAAU,wBAAA,CAAwB;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGxF,CAAC,GAIYc,KAAatB,EAAK,SAAoB;AAAA,EACjD,IAAAjG;AAAA,EACA,MAAA6C;AAAA,EACA,UAAAqD;AACF,GAA8B;;AAC5B,QAAMV,IAAazD,EAAiB,CAAC8D,MAAMA,EAAE,UAAU,WAAW7F,CAAE,CAAC,GAC/DwH,IAAazF,EAAiB,CAAC8D,MAAA;;AAAM,YAAAzJ,IAAAyJ,EAAE,UAAU,gBAAZ,gBAAAzJ,EAA0B4D;AAAA,GAAG,GAGlEoG,IADiBb,EAAkBC,CAAU,MACZU,IAAW,oBAAoB,oBAGhEuB,KAAmBrL,IAAAyG,EAAK,iBAAL,QAAAzG,EAAmB,aACxC,OAAO,QAAQyG,EAAK,aAAa,UAAU,IAC3C,CAAA,GACE6E,IAAiBD,EAAiB,SAAS;AAEjD,SACE,gBAAAlB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,yFAAyFH,CAAW;AAAA,MAE/G,UAAA;AAAA,QAAA,gBAAAL,EAACS,KAAO,MAAK,UAAS,UAAUC,EAAS,MAAM,WAAU,wBAAuB;AAAA,QAC/Ee,uBACE,OAAA,EAAI,WAAU,2GACb,UAAA,gBAAAjB,EAAC,OAAA,EAAI,WAAU,gEACZ,UAAA;AAAA,WAAAlI,IAAAmJ,EAAW,YAAX,gBAAAnJ,EAAoB,MAAM,GAAG;AAAA,aAC5BgD,IAAAmG,EAAW,YAAX,gBAAAnG,EAAoB,WAAU,KAAK,OAAO;AAAA,QAAA,EAAA,CAC9C,EAAA,CACF;AAAA,QAEF,gBAAAkF,EAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,gCACb,UAAA;AAAA,YAAA,gBAAAA,EAAC,SAAI,WAAU,yBAAwB,MAAK,gBAAe,SAAQ,aACjE,UAAA;AAAA,cAAA,gBAAAR,EAAC,QAAA,EAAK,GAAE,kCAAA,CAAkC;AAAA,cAC1C,gBAAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,UAAS;AAAA,kBACT,GAAE;AAAA,kBACF,UAAS;AAAA,gBAAA;AAAA,cAAA;AAAA,YACX,GACF;AAAA,8BACC,QAAA,EAAK,WAAU,0DACb,UAAAlD,EAAK,iBAAiBA,EAAK,aAAA,CAC9B;AAAA,UAAA,GACF;AAAA,UACA,gBAAAkD,EAAC,OAAA,EAAI,WAAU,4CACZ,UAAAlD,EAAK,OAAO,SACX,gBAAA0D,EAAC,OAAA,EAAI,WAAU,YAAY,UAAA;AAAA,YAAA,OAAO1D,EAAK,OAAO,MAAM,EAAE,MAAM,GAAG,EAAE;AAAA,YAAE;AAAA,UAAA,EAAA,CAAG,IACpE,MACN;AAAA,UAEC6E,KACC,gBAAAnB,EAAC,OAAA,EAAI,WAAU,2DACb,UAAA;AAAA,YAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,iEAAgE,UAAA,YAE/E;AAAA,YACC0B,EAAiB,IAAI,CAAC,CAACvC,CAAG,MACzB,gBAAAqB;AAAA,cAAC;AAAA,cAAA;AAAA,gBAEC,WAAU;AAAA,gBAEV,UAAA;AAAA,kBAAA,gBAAAR,EAAC,QAAA,EAAK,WAAU,uCAAA,CAAuC;AAAA,kBACtDb;AAAA,gBAAA;AAAA,cAAA;AAAA,cAJIA;AAAA,YAAA,CAMR;AAAA,UAAA,EAAA,CACH;AAAA,QAAA,GAEJ;AAAA,QAECwC,IACC,gBAAAnB,EAAAoB,GAAA,EAEE,UAAA;AAAA,UAAA,gBAAA5B;AAAA,YAACS;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,UAAUC,EAAS;AAAA,cACnB,IAAG;AAAA,cACH,WAAU;AAAA,cACV,OAAO,EAAE,KAAK,MAAA;AAAA,cACd,OAAM;AAAA,YAAA;AAAA,UAAA;AAAA,UAGPgB,EAAiB,IAAI,CAAC,CAACvC,GAAKC,CAAI,GAAGR,MAClC,gBAAAoB;AAAA,YAACS;AAAA,YAAA;AAAA,cAEC,MAAK;AAAA,cACL,UAAUC,EAAS;AAAA,cACnB,IAAI,UAAUvB,CAAG;AAAA,cACjB,WAAU;AAAA,cACV,OAAO;AAAA,gBACL,KAAK,GAAG,KAAKP,IAAQ,EAAE;AAAA,cAAA;AAAA,cAEzB,OAAO,GAAGO,CAAG,KAAKC,EAAK,eAAeA,EAAK,IAAI;AAAA,YAAA;AAAA,YAR1CD;AAAA,UAAA,CAUR;AAAA,QAAA,EAAA,CACH,sBAECsB,GAAA,EAAO,MAAK,UAAS,UAAUC,EAAS,OAAO,WAAU,uBAAA,CAAuB;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAIzF,CAAC,GAIYmB,KAAW3B,EAAK,SAAkB,EAAE,IAAAjG,GAAI,MAAA6C,GAAM,UAAAqD,KAAqC;;AAC9F,QAAMV,IAAazD,EAAiB,CAAC8D,MAAMA,EAAE,UAAU,WAAW7F,CAAE,CAAC,GAC/DwH,IAAazF,EAAiB,CAAC8D,MAAA;;AAAM,YAAAzJ,IAAAyJ,EAAE,UAAU,gBAAZ,gBAAAzJ,EAA0B4D;AAAA,GAAG,GAGlEoG,IADiBb,EAAkBC,CAAU,MACZU,IAAW,oBAAoB,oBAGhEuB,KAAmBrL,IAAAyG,EAAK,iBAAL,QAAAzG,EAAmB,aACxC,OAAO,QAAQyG,EAAK,aAAa,UAAU,IAC3C,CAAA,GACE6E,IAAiBD,EAAiB,SAAS;AAEjD,SACE,gBAAAlB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,yFAAyFH,CAAW;AAAA,MAE/G,UAAA;AAAA,QAAA,gBAAAL,EAACS,KAAO,MAAK,UAAS,UAAUC,EAAS,MAAM,WAAU,wBAAuB;AAAA,QAC/Ee,uBACE,OAAA,EAAI,WAAU,2GACb,UAAA,gBAAAjB,EAAC,OAAA,EAAI,WAAU,gEACZ,UAAA;AAAA,WAAAlI,IAAAmJ,EAAW,YAAX,gBAAAnJ,EAAoB,MAAM,GAAG;AAAA,aAC5BgD,IAAAmG,EAAW,YAAX,gBAAAnG,EAAoB,WAAU,KAAK,OAAO;AAAA,QAAA,EAAA,CAC9C,EAAA,CACF;AAAA,QAEF,gBAAAkF,EAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,gCACb,UAAA;AAAA,YAAA,gBAAAR,EAAC,SAAI,WAAU,yBAAwB,MAAK,gBAAe,SAAQ,aACjE,UAAA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,UAAS;AAAA,gBACT,GAAE;AAAA,gBACF,UAAS;AAAA,cAAA;AAAA,YAAA,GAEb;AAAA,8BACC,QAAA,EAAK,WAAU,0DACb,UAAAlD,EAAK,iBAAiBA,EAAK,aAAA,CAC9B;AAAA,UAAA,GACF;AAAA,UACA,gBAAAkD,EAAC,OAAA,EAAI,WAAU,4CACZ,UAAAlD,EAAK,OAAO,SACX,gBAAA0D,EAAC,OAAA,EAAI,WAAU,YAAY,UAAA;AAAA,YAAA,OAAO1D,EAAK,OAAO,MAAM,EAAE,MAAM,GAAG,EAAE;AAAA,YAAE;AAAA,UAAA,EAAA,CAAG,IACpE,MACN;AAAA,UAEC6E,KACC,gBAAAnB,EAAC,OAAA,EAAI,WAAU,2DACb,UAAA;AAAA,YAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,iEAAgE,UAAA,YAE/E;AAAA,YACC0B,EAAiB,IAAI,CAAC,CAACvC,CAAG,MACzB,gBAAAqB;AAAA,cAAC;AAAA,cAAA;AAAA,gBAEC,WAAU;AAAA,gBAEV,UAAA;AAAA,kBAAA,gBAAAR,EAAC,QAAA,EAAK,WAAU,uCAAA,CAAuC;AAAA,kBACtDb;AAAA,gBAAA;AAAA,cAAA;AAAA,cAJIA;AAAA,YAAA,CAMR;AAAA,UAAA,EAAA,CACH;AAAA,QAAA,GAEJ;AAAA,QAECwC,IACC,gBAAAnB,EAAAoB,GAAA,EAEE,UAAA;AAAA,UAAA,gBAAA5B;AAAA,YAACS;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,UAAUC,EAAS;AAAA,cACnB,IAAG;AAAA,cACH,WAAU;AAAA,cACV,OAAO,EAAE,KAAK,MAAA;AAAA,cACd,OAAM;AAAA,YAAA;AAAA,UAAA;AAAA,UAGPgB,EAAiB,IAAI,CAAC,CAACvC,GAAKC,CAAI,GAAGR,MAClC,gBAAAoB;AAAA,YAACS;AAAA,YAAA;AAAA,cAEC,MAAK;AAAA,cACL,UAAUC,EAAS;AAAA,cACnB,IAAI,UAAUvB,CAAG;AAAA,cACjB,WAAU;AAAA,cACV,OAAO;AAAA,gBACL,KAAK,GAAG,KAAKP,IAAQ,EAAE;AAAA,cAAA;AAAA,cAEzB,OAAO,GAAGO,CAAG,KAAKC,EAAK,eAAeA,EAAK,IAAI;AAAA,YAAA;AAAA,YAR1CD;AAAA,UAAA,CAUR;AAAA,QAAA,EAAA,CACH,sBAECsB,GAAA,EAAO,MAAK,UAAS,UAAUC,EAAS,OAAO,WAAU,uBAAA,CAAuB;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAIzF,CAAC,GAEYoB,KAAY;AAAA,EACvB,WAAW7B;AAAA,EACX,WAAWW;AAAA,EACX,MAAMC;AAAA,EACN,OAAOC;AAAA,EACP,QAAQU;AAAA,EACR,MAAMK;AACR,GCjjBME,KAAyC;AAAA,EAC7C,MAAM;AAAA,EACN,UAAU;AAAA,EACV,WAAW;AAAA,IACT,MAAMC,GAAW;AAAA,IACjB,OAAO;AAAA,IACP,OAAO;AAAA,IACP,QAAQ;AAAA,EAAA;AAAA,EAEV,OAAO;AAAA,IACL,QAAQ;AAAA,IACR,aAAa;AAAA,EAAA;AAEjB;AAEO,SAASC,KAAiB;AAC/B,QAAMtI,IAAQqC,EAAiB,CAAC8D,MAAMA,EAAE,KAAK,GACvClG,IAAQoC,EAAiB,CAAC8D,MAAMA,EAAE,KAAK,GACvCoC,IAAWlG,EAAiB,CAAC8D,MAAMA,EAAE,QAAQ,GAC7CqC,IAAWnG,EAAiB,CAAC8D,MAAMA,EAAE,QAAQ,GAC7CsC,IAAUpG,EAAiB,CAAC8D,MAAMA,EAAE,OAAO,GAC3CuC,IAAkBrG,EAAiB,CAAC8D,MAAMA,EAAE,eAAe,GAG3DwC,IAAoBnB;AAAA,IACxB,CAAC9D,MAA2B;AAC1B,YAAM,EAAE,QAAAkF,GAAQ,QAAAC,EAAA,IAAWnF;AAC3B,UAAI,CAACkF,KAAU,CAACC,EAAQ,QAAO;AAE/B,YAAMC,IAAa9I,EAAM,KAAK,CAACwD,MAAMA,EAAE,OAAOoF,CAAM,GAC9CG,IAAa/I,EAAM,KAAK,CAACwD,MAAMA,EAAE,OAAOqF,CAAM;AAkBpD,aAhBI,GAACC,KAAc,CAACC,KAGhBD,EAAW,SAAS,UAGpBC,EAAW,SAAS,eAAeA,EAAW,SAAS,WAI3B9I,EAAM;AAAA,QACpC,CAAC5C,MAAMA,EAAE,WAAWwL,KAAUxL,EAAE,iBAAiBqG,EAAW;AAAA,MAAA,KAK1DkF,MAAWC;AAAA,IAGjB;AAAA,IACA,CAAC7I,GAAOC,CAAK;AAAA,EAAA,GAGT+I,IAA+BxB;AAAA,IACnC,CAACyB,MAAY;AACX,MAAAV,EAASW,GAAiBD,GAASjJ,CAAK,CAAC;AAAA,IAC3C;AAAA,IACA,CAACA,GAAOuI,CAAQ;AAAA,EAAA,GAGZY,IAA+B3B;AAAA,IACnC,CAACyB,MAAY;AACX,MAAAT,EAASY,GAAiBH,GAAShJ,CAAK,CAAC;AAAA,IAC3C;AAAA,IACA,CAACA,GAAOuI,CAAQ;AAAA,EAAA,GAGZa,IAAY7B;AAAA,IAChB,CAAC9D,MAA2B;AAC1B,MAAA+E,EAAQ/E,CAAU;AAAA,IACpB;AAAA,IACA,CAAC+E,CAAO;AAAA,EAAA,GAGJa,IAAgC9B;AAAA,IACpC,CAAC+B,GAAQhG,MAAS;AAChB,MAAAmF,EAAgBnF,EAAK,EAAE;AAAA,IACzB;AAAA,IACA,CAACmF,CAAe;AAAA,EAAA,GAGZc,IAAchC,EAAY,MAAM;AACpC,IAAAkB,EAAgB,IAAI;AAAA,EACtB,GAAG,CAACA,CAAe,CAAC;AAEpB,SACE,gBAAArC,EAAC,OAAA,EAAI,WAAU,iBACb,UAAA,gBAAAQ;AAAA,IAAC4C;AAAA,IAAA;AAAA,MACC,OAAAzJ;AAAA,MACA,OAAAC;AAAA,MACA,eAAA+I;AAAA,MACA,eAAAG;AAAA,MACA,WAAAE;AAAA,MACA,aAAAC;AAAA,MACA,aAAAE;AAAA,MACA,WAAArB;AAAA,MACA,oBAAAC;AAAA,MACA,mBAAAO;AAAA,MACA,gBAAgB;AAAA,MAChB,kBAAkB;AAAA,MAClB,oBAAoB;AAAA,MACpB,YAAY,EAAE,iBAAiB,GAAA;AAAA,MAC/B,SAAO;AAAA,MACP,YAAU;AAAA,MACV,UAAU,CAAC,IAAI,EAAE;AAAA,MAEjB,UAAA;AAAA,QAAA,gBAAAtC,EAACqD,IAAA,EAAW;AAAA,0BACXC,IAAA,EAAS;AAAA,0BACTC,IAAA,EAAQ,iBAAiB,GAAG,UAAQ,IAAC,UAAQ,GAAA,CAAC;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,GAEnD;AAEJ;AC9HO,SAASC,GAAc,EAAE,UAAAC,KAAgC;AAC9D,QAAM,CAACC,GAASC,CAAU,IAAIC,EAAuB,CAAA,CAAE,GACjD,CAACC,GAASC,CAAU,IAAIF,EAAS,EAAI,GACrC,CAACvK,GAAO0K,CAAQ,IAAIH,EAAwB,IAAI,GAEhDI,IAAe,YAAY;AAC/B,QAAI;AACF,MAAAF,EAAW,EAAI;AACf,YAAMhH,IAAO,MAAMxC,GAAA;AACnB,MAAAqJ,EAAW7G,CAAI,GACfiH,EAAS,IAAI;AAAA,IACf,SAASE,GAAK;AACZ,MAAAF,EAASE,aAAe,QAAQA,EAAI,UAAU,wBAAwB;AAAA,IACxE,UAAA;AACE,MAAAH,EAAW,EAAK;AAAA,IAClB;AAAA,EACF;AAEA,EAAAI,EAAU,MAAM;AACd,IAAAF,EAAA;AAAA,EACF,GAAG,CAAA,CAAE;AAEL,QAAMG,IAAe,OAAOlK,GAAYjD,MAAwB;AAE9D,QADAA,EAAE,gBAAA,GACE,EAAC,QAAQ,qBAAqB;AAElC,UAAI;AACF,cAAMuD,GAAaN,CAAE,GACrB0J,EAAW,CAACS,MAASA,EAAK,OAAO,CAACC,MAAMA,EAAE,OAAOpK,CAAE,CAAC;AAAA,MACtD,SAASgK,GAAK;AACZ,gBAAQ,MAAM,qBAAqBA,CAAG;AAAA,MACxC;AAAA,EACF,GAEMK,IAAa,CAACC,MACdA,IAAQ,OAAa,GAAGA,CAAK,OAC7BA,IAAQ,OAAO,OAAa,IAAIA,IAAQ,MAAM,QAAQ,CAAC,CAAC,QACrD,IAAIA,KAAS,OAAO,OAAO,QAAQ,CAAC,CAAC;AAG9C,SAAIV,IAEA,gBAAA7D,EAAC,OAAA,EAAI,WAAU,oDAAmD,UAAA,sBAAkB,IAIpF3G,IAEA,gBAAAmH,EAAC,OAAA,EAAI,WAAU,kDACZ,UAAA;AAAA,IAAAnH;AAAA,IACD,gBAAA2G;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,SAASgE;AAAA,QACT,WAAU;AAAA,QACX,UAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAED,GACF,IAIAN,EAAQ,WAAW,IAEnB,gBAAA1D,EAAC,OAAA,EAAI,WAAU,oDAAmD,UAAA,+DAElE,IAKF,gBAAAA,EAAC,OAAA,EAAI,WAAU,OACb,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,0BACZ,UAAA0D,EAAQ,IAAI,CAACc,MACZ,gBAAAhE;AAAA,IAAC;AAAA,IAAA;AAAA,MAEC,WAAU;AAAA,MACV,SAAS,MAAMiD,KAAA,gBAAAA,EAAWe;AAAA,MAE1B,UAAA;AAAA,QAAA,gBAAAxE;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,KAAKxF,GAAiBgK,EAAO,EAAE;AAAA,YAC/B,KAAKA,EAAO;AAAA,YACZ,WAAU;AAAA,UAAA;AAAA,QAAA;AAAA,QAEZ,gBAAAxE,EAAC,OAAA,EAAI,WAAU,sHACb,UAAA,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS,CAAChJ,MAAMmN,EAAaK,EAAO,IAAIxN,CAAC;AAAA,YACzC,WAAU;AAAA,YACX,UAAA;AAAA,UAAA;AAAA,QAAA,GAGH;AAAA,QACA,gBAAAgJ,EAAC,OAAA,EAAI,WAAU,mFACZ,YAAO,UACV;AAAA,0BACC,OAAA,EAAI,WAAU,gFACZ,UAAAsE,EAAWE,EAAO,IAAI,EAAA,CACzB;AAAA,MAAA;AAAA,IAAA;AAAA,IAtBKA,EAAO;AAAA,EAAA,CAwBf,GACH,EAAA,CACF;AAEJ;ACrGO,SAASC,KAAc;AAC5B,QAAMC,IAAgB1I,EAAiB,CAAC8D,MAAMA,EAAE,aAAa,GACvD6E,IAAgB3I,EAAiB,CAAC8D,MAAMA,EAAE,aAAa,GACvD8E,IAAmB5I,EAAiB,CAAC8D,MAAMA,EAAE,gBAAgB,GAC7D+E,IAAqB7I,EAAiB,CAAC8D,MAAMA,EAAE,kBAAkB,GACjEtD,IAAaR,EAAiB,CAAC8D,MAAMA,EAAE,UAAU,GACjDrD,IAAaT,EAAiB,CAAC8D,MAAMA,EAAE,UAAU,GACjDpD,IAAgBV,EAAiB,CAAC8D,MAAMA,EAAE,aAAa,GACvDnD,IAAkBX,EAAiB,CAAC8D,MAAMA,EAAE,eAAe,GAC3DgF,IAAU9I,EAAiB,CAAC8D,MAAMA,EAAE,OAAO,GAC3C,CAACiF,GAAaC,CAAc,IAAIpB,EAAS,EAAK,GAG9C,EAAE,MAAMqB,EAAA,IAAsBC,EAAS;AAAA,IAC3C,UAAU,CAAC,YAAY;AAAA,IACvB,SAAS5L;AAAA,EAAA,CACV,GAEK,EAAE,MAAM6L,EAAA,IAAsBD,EAAS;AAAA,IAC3C,UAAU,CAAC,YAAY;AAAA,IACvB,SAAS3L;AAAA,EAAA,CACV,GAEK,EAAE,MAAM6L,EAAA,IAAyBF,EAAS;AAAA,IAC9C,UAAU,CAAC,eAAe;AAAA,IAC1B,SAAS1L;AAAA,EAAA,CACV,GAEK,EAAE,MAAM6L,EAAA,IAA2BH,EAAS;AAAA,IAChD,UAAU,CAAC,iBAAiB;AAAA,IAC5B,SAASzL;AAAA,EAAA,CACV;AAED,EAAAyK,EAAU,MAAM;AACd,IAAIe,OAAiCA,CAAiB;AAAA,EACxD,GAAG,CAACA,GAAmBP,CAAa,CAAC,GAErCR,EAAU,MAAM;AACd,IAAIiB,OAAiCA,CAAiB;AAAA,EACxD,GAAG,CAACA,GAAmBR,CAAa,CAAC,GAErCT,EAAU,MAAM;AACd,IAAIkB,OAAuCA,CAAoB;AAAA,EACjE,GAAG,CAACA,GAAsBR,CAAgB,CAAC,GAE3CV,EAAU,MAAM;AACd,IAAImB,OAA2CA,CAAsB;AAAA,EACvE,GAAG,CAACA,GAAwBR,CAAkB,CAAC;AAE/C,QAAMS,IAAkB,CAACtO,GAAoB4F,MAA+B;AAC1E,IAAA5F,EAAE,aAAa,QAAQ,oBAAoB,KAAK,UAAU4F,CAAU,CAAC,GACrE5F,EAAE,aAAa,gBAAgB;AAAA,EACjC,GAEMuO,IAAoB,CAAC3I,MAA+B;AAExD,IAAAkI,EAAQlI,GAAY,EAAE,GAAG,KAAK,GAAG,MAAM,KAAK,WAAW,KAAK;AAAA,EAC9D,GAGM4I,IAAkC;AAAA,IACtC,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,IACV,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,YAAY,CAAA;AAAA,IAAC;AAAA,EACf,GAIIC,IAAiC;AAAA,IACrC,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,IACV,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,YAAY;AAAA,QACV,aAAa;AAAA,UACX,MAAM;AAAA,UACN,OAAO;AAAA,UACP,SAAS;AAAA,QAAA;AAAA,QAEX,UAAU;AAAA,UACR,MAAM;AAAA,UACN,SAAS;AAAA,QAAA;AAAA,MACX;AAAA,IACF;AAAA,EACF,GAIIC,IAAuBlJ,EAAW;AAAA,IACtC,CAACmJ,GAAKC,MAAM;AACV,YAAMC,IAAMD,EAAE,YAAY;AAC1B,aAAKD,EAAIE,CAAG,MAAGF,EAAIE,CAAG,IAAI,CAAA,IAC1BF,EAAIE,CAAG,EAAE,KAAKD,CAAC,GACRD;AAAA,IACT;AAAA,IACA,CAAA;AAAA,EAAC,GAIGG,IAAuBrJ,EAAW;AAAA,IACtC,CAACkJ,GAAKI,MAAM;AACV,YAAMF,IAAME,EAAE,YAAY;AAC1B,aAAKJ,EAAIE,CAAG,MAAGF,EAAIE,CAAG,IAAI,CAAA,IAC1BF,EAAIE,CAAG,EAAE,KAAKE,CAAC,GACRJ;AAAA,IACT;AAAA,IACA,CAAA;AAAA,EAAC;AAGH,2BACG,OAAA,EAAI,WAAU,kGACb,UAAA,gBAAAnF,EAAC,OAAA,EAAI,WAAU,OACb,UAAA;AAAA,IAAA,gBAAAR,EAAC,MAAA,EAAG,WAAU,4DAA2D,UAAA,SAAK;AAAA,IAG9E,gBAAAQ,EAAC,OAAA,EAAI,WAAU,QACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,0CACb,UAAA;AAAA,QAAA,gBAAAR,EAAC,MAAA,EAAG,WAAU,kFAAiF,UAAA,SAE/F;AAAA,QACA,gBAAAQ;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS,MAAMwE,EAAe,CAACD,CAAW;AAAA,YAC1C,WAAU;AAAA,YAET,UAAA;AAAA,cAAAA,IAAc,SAAS;AAAA,cAAS;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MACnC,GACF;AAAA,MACA,gBAAAvE;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAS;AAAA,UACT,aAAa,CAACxJ,MAAMsO,EAAgBtO,GAAGwO,CAAe;AAAA,UACtD,eAAe,MAAMD,EAAkBC,CAAe;AAAA,UACtD,WAAU;AAAA,UAEV,UAAA;AAAA,YAAA,gBAAAxF,EAAC,OAAA,EAAI,WAAU,0DAAyD,UAAA,gBAExE;AAAA,YACA,gBAAAA,EAAC,OAAA,EAAI,WAAU,4CAA2C,UAAA,wBAAA,CAAqB;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,MAEhF+E,KACC,gBAAA/E,EAAC,OAAA,EAAI,WAAU,iHACb,UAAA,gBAAAA,EAACwD,MAAc,EAAA,CACjB;AAAA,IAAA,GAEJ;AAAA,IAGA,gBAAAhD,EAAC,OAAA,EAAI,WAAU,QACb,UAAA;AAAA,MAAA,gBAAAR,EAAC,MAAA,EAAG,WAAU,qFAAoF,UAAA,cAElG;AAAA,MACC,OAAO,QAAQ0F,CAAoB,EAAE,IAAI,CAAC,CAACM,GAAUrM,CAAK,MACzD,gBAAA6G,EAAC,OAAA,EAAmB,WAAU,QAC5B,UAAA;AAAA,QAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,iDAAiD,UAAAgG,GAAS;AAAA,QACxErM,EAAM,IAAI,CAACsM,MACV,gBAAAzF;AAAA,UAAC;AAAA,UAAA;AAAA,YAEC,WAAS;AAAA,YACT,aAAa,CAACxJ,MAAMsO,EAAgBtO,GAAGiP,CAAG;AAAA,YAC1C,eAAe,MAAMV,EAAkBU,CAAG;AAAA,YAC1C,WAAU;AAAA,YAEV,UAAA;AAAA,cAAA,gBAAAjG,EAAC,OAAA,EAAI,WAAU,wDACZ,UAAAiG,EAAI,OACP;AAAA,cACCA,EAAI,eACH,gBAAAjG,EAAC,SAAI,WAAU,qDACZ,YAAI,YAAA,CACP;AAAA,YAAA;AAAA,UAAA;AAAA,UAZGiG,EAAI;AAAA,QAAA,CAeZ;AAAA,MAAA,EAAA,GAnBOD,CAoBV,CACD;AAAA,IAAA,GACH;AAAA,IAGA,gBAAAxF,EAAC,OAAA,EAAI,WAAU,QACb,UAAA;AAAA,MAAA,gBAAAR,EAAC,MAAA,EAAG,WAAU,qFAAoF,UAAA,cAElG;AAAA,MACC,OAAO,QAAQ8F,CAAoB,EAAE,IAAI,CAAC,CAACE,GAAUrM,CAAK,MACzD,gBAAA6G,EAAC,OAAA,EAAmB,WAAU,QAC5B,UAAA;AAAA,QAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,iDAAiD,UAAAgG,GAAS;AAAA,QACxErM,EAAM,IAAI,CAACsM,MACV,gBAAAzF;AAAA,UAAC;AAAA,UAAA;AAAA,YAEC,WAAS;AAAA,YACT,aAAa,CAACxJ,MAAMsO,EAAgBtO,GAAGiP,CAAG;AAAA,YAC1C,eAAe,MAAMV,EAAkBU,CAAG;AAAA,YAC1C,WAAU;AAAA,YAEV,UAAA;AAAA,cAAA,gBAAAjG,EAAC,OAAA,EAAI,WAAU,wDACZ,UAAAiG,EAAI,OACP;AAAA,cACCA,EAAI,eACH,gBAAAjG,EAAC,SAAI,WAAU,qDACZ,YAAI,YAAA,CACP;AAAA,YAAA;AAAA,UAAA;AAAA,UAZGiG,EAAI;AAAA,QAAA,CAeZ;AAAA,MAAA,EAAA,GAnBOD,CAoBV,CACD;AAAA,IAAA,GACH;AAAA,IAGCtJ,EAAc,SAAS,KACtB,gBAAA8D,EAAC,OAAA,EAAI,WAAU,QACb,UAAA;AAAA,MAAA,gBAAAR,EAAC,MAAA,EAAG,WAAU,qFAAoF,UAAA,WAElG;AAAA,MACCtD,EAAc,IAAI,CAACuJ,MAClB,gBAAAzF;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,WAAS;AAAA,UACT,aAAa,CAACxJ,MAAMsO,EAAgBtO,GAAGiP,CAAG;AAAA,UAC1C,eAAe,MAAMV,EAAkBU,CAAG;AAAA,UAC1C,WAAU;AAAA,UAEV,UAAA;AAAA,YAAA,gBAAAjG,EAAC,OAAA,EAAI,WAAU,wDACZ,UAAAiG,EAAI,OACP;AAAA,YACCA,EAAI,eACH,gBAAAjG,EAAC,SAAI,WAAU,qDACZ,YAAI,YAAA,CACP;AAAA,UAAA;AAAA,QAAA;AAAA,QAZGiG,EAAI;AAAA,MAAA,CAeZ;AAAA,IAAA,GACH;AAAA,IAIDtJ,EAAgB,SAAS,KACxB,gBAAA6D,EAAC,OAAA,EAAI,WAAU,QACb,UAAA;AAAA,MAAA,gBAAAR,EAAC,MAAA,EAAG,WAAU,qFAAoF,UAAA,aAElG;AAAA,MACCrD,EAAgB,IAAI,CAACsJ,MACpB,gBAAAzF;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,WAAS;AAAA,UACT,aAAa,CAACxJ,MAAMsO,EAAgBtO,GAAGiP,CAAG;AAAA,UAC1C,eAAe,MAAMV,EAAkBU,CAAG;AAAA,UAC1C,WAAU;AAAA,UAEV,UAAA;AAAA,YAAA,gBAAAjG,EAAC,OAAA,EAAI,WAAU,wDACZ,UAAAiG,EAAI,OACP;AAAA,YACCA,EAAI,eACH,gBAAAjG,EAAC,SAAI,WAAU,qDACZ,YAAI,YAAA,CACP;AAAA,UAAA;AAAA,QAAA;AAAA,QAZGiG,EAAI;AAAA,MAAA,CAeZ;AAAA,IAAA,GACH;AAAA,IAIF,gBAAAzF,EAAC,OAAA,EAAI,WAAU,QACb,UAAA;AAAA,MAAA,gBAAAR,EAAC,MAAA,EAAG,WAAU,uFAAsF,UAAA,UAEpG;AAAA,MACA,gBAAAQ;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAS;AAAA,UACT,aAAa,CAACxJ,MAAMsO,EAAgBtO,GAAGyO,CAAc;AAAA,UACrD,eAAe,MAAMF,EAAkBE,CAAc;AAAA,UACrD,WAAU;AAAA,UAEV,UAAA;AAAA,YAAA,gBAAAzF,EAAC,OAAA,EAAI,WAAU,0DAAyD,UAAA,QAAI;AAAA,YAC5E,gBAAAA,EAAC,OAAA,EAAI,WAAU,4CAA2C,UAAA,eAAA,CAAY;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IACxE,EAAA,CACF;AAAA,EAAA,EAAA,CACF,EAAA,CACF;AAEJ;ACzRO,SAASkG,KAAgB;;AAC9B,QAAMC,IAAiBnK,EAAiB,CAAC8D,MAAMA,EAAE,cAAc,GACzDnG,IAAQqC,EAAiB,CAAC8D,MAAMA,EAAE,KAAK,GACvCtD,IAAaR,EAAiB,CAAC8D,MAAMA,EAAE,UAAU,GACjDrD,IAAaT,EAAiB,CAAC8D,MAAMA,EAAE,UAAU,GACjDpD,IAAgBV,EAAiB,CAAC8D,MAAMA,EAAE,aAAa,GACvDnD,IAAkBX,EAAiB,CAAC8D,MAAMA,EAAE,eAAe,GAC3DiB,IAAiB/E,EAAiB,CAAC8D,MAAMA,EAAE,cAAc,GACzDsG,IAAapK,EAAiB,CAAC8D,MAAMA,EAAE,UAAU,GAEjDuG,IAAe1M,EAAM,KAAK,CAACwD,MAAMA,EAAE,OAAOgJ,CAAc;AAE9D,MAAI,CAACE;AACH,WACE,gBAAArG,EAAC,SAAI,WAAU,sFACb,4BAAC,OAAA,EAAI,WAAU,4CAA2C,UAAA,uCAAA,CAE1D,EAAA,CACF;AAKJ,MAAIsG,GACAC,IAAY;AAEhB,MAAIF,EAAa,SAAS,aAAa;AACrC,UAAMvJ,IAAOuJ,EAAa,MACpBJ,IAAMzJ,EAAW,KAAK,CAACoJ,MAAMA,EAAE,SAAS9I,EAAK,aAAa;AAChE,IAAAwJ,KAASjQ,IAAA4P,KAAA,gBAAAA,EAAK,WAAL,gBAAA5P,EAAa,YACtBkQ,KAAYN,KAAA,gBAAAA,EAAK,UAASnJ,EAAK;AAAA,EACjC,WAAWuJ,EAAa,SAAS,aAAa;AAC5C,UAAMvJ,IAAOuJ,EAAa,MACpBJ,IAAMxJ,EAAW,KAAK,CAACsJ,MAAMA,EAAE,SAASjJ,EAAK,SAAS;AAC5D,IAAAwJ,KAAShO,IAAA2N,KAAA,gBAAAA,EAAK,WAAL,gBAAA3N,EAAa,YACtBiO,KAAYN,KAAA,gBAAAA,EAAK,UAASnJ,EAAK;AAAA,EACjC,WAAWuJ,EAAa,SAAS,QAAQ;AAEvC,UAAMG,IADOH,EAAa,KACD,aAAa;AAEtC,IAAAE,IAAYC,IAAc,yBAAyB,QACnDF,IAAS;AAAA,MACP,aAAa;AAAA,QACX,MAAM;AAAA,QACN,OAAOE,IAAc,aAAa;AAAA,QAClC,aAAaA,IAAc,+BAA+B;AAAA,MAAA;AAAA,IAC5D;AAAA,EAEJ,WAAWH,EAAa,SAAS,QAAQ;AACvC,UAAMvJ,IAAOuJ,EAAa,MACpBJ,IAAMvJ,EAAc,KAAK,CAACqJ,MAAMA,EAAE,SAASjJ,EAAK,YAAY;AAClE,IAAAwJ,KAAShL,IAAA2K,KAAA,gBAAAA,EAAK,WAAL,gBAAA3K,EAAa,YACtBiL,KAAYN,KAAA,gBAAAA,EAAK,UAASnJ,EAAK;AAAA,EACjC,WAAWuJ,EAAa,SAAS,UAAU;AACzC,UAAMvJ,IAAOuJ,EAAa,MACpBJ,IAAMtJ,EAAgB,KAAK,CAAC8J,MAAMA,EAAE,SAAS3J,EAAK,YAAY;AACpE,IAAAwJ,KAAS/K,IAAA0K,KAAA,gBAAAA,EAAK,WAAL,gBAAA1K,EAAa,YACtBgL,KAAYN,KAAA,gBAAAA,EAAK,UAASnJ,EAAK;AAAA,EACjC;AAEA,QAAM4J,IAAoB,CAACvH,GAAawB,MAAmB;AACzD,QAAI0F,EAAa,SAAS,aAAa;AACrC,YAAMvJ,IAAOuJ,EAAa;AAC1B,MAAAtF,EAAesF,EAAa,IAAI;AAAA,QAC9B,QAAQ,EAAE,GAAGvJ,EAAK,QAAQ,CAACqC,CAAG,GAAGwB,EAAA;AAAA,MAAM,CACxC;AAAA,IACH,WAAW0F,EAAa,SAAS,aAAa;AAC5C,YAAMvJ,IAAOuJ,EAAa;AAC1B,MAAAtF,EAAesF,EAAa,IAAI;AAAA,QAC9B,QAAQ,EAAE,GAAGvJ,EAAK,QAAQ,CAACqC,CAAG,GAAGwB,EAAA;AAAA,MAAM,CACxC;AAAA,IACH,WAAW0F,EAAa,SAAS;AAC/B,MAAAtF,EAAesF,EAAa,IAAI,EAAE,CAAClH,CAAG,GAAGwB,GAAO;AAAA,aACvC0F,EAAa,SAAS,QAAQ;AACvC,YAAMvJ,IAAOuJ,EAAa;AAC1B,MAAAtF,EAAesF,EAAa,IAAI;AAAA,QAC9B,QAAQ,EAAE,GAAGvJ,EAAK,QAAQ,CAACqC,CAAG,GAAGwB,EAAA;AAAA,MAAM,CACxC;AAAA,IACH,WAAW0F,EAAa,SAAS,UAAU;AACzC,YAAMvJ,IAAOuJ,EAAa;AAC1B,MAAAtF,EAAesF,EAAa,IAAI;AAAA,QAC9B,QAAQ,EAAE,GAAGvJ,EAAK,QAAQ,CAACqC,CAAG,GAAGwB,EAAA;AAAA,MAAM,CACxC;AAAA,IACH;AAAA,EACF,GAEMgG,IAAgB,CAACxH,MAAyB;AAC9C,QAAIkH,EAAa,SAAS;AACxB,aAAQA,EAAa,KAA2B,OAAOlH,CAAG;AAC5D,QAAWkH,EAAa,SAAS;AAC/B,aAAQA,EAAa,KAA2B,OAAOlH,CAAG;AAC5D,QAAWkH,EAAa,SAAS;AAC/B,aAAQA,EAAa,KAAsBlH,CAAyB;AACtE,QAAWkH,EAAa,SAAS;AAC/B,aAAQA,EAAa,KAAsB,OAAOlH,CAAG;AACvD,QAAWkH,EAAa,SAAS;AAC/B,aAAQA,EAAa,KAAwB,OAAOlH,CAAG;AAAA,EAG3D;AAEA,2BACG,OAAA,EAAI,WAAU,kGACb,UAAA,gBAAAqB,EAAC,OAAA,EAAI,WAAU,OACb,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,0CACb,UAAA;AAAA,MAAA,gBAAAR,EAAC,MAAA,EAAG,WAAU,uDAAuD,UAAAuG,GAAU;AAAA,MAC/E,gBAAAvG;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,SAAS,MAAMoG,EAAWC,EAAa,EAAE;AAAA,UACzC,WAAU;AAAA,UACX,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAED,GACF;AAAA,IAEA,gBAAArG,EAAC,OAAA,EAAI,WAAU,aACZ,eACC,OAAO,QAAQsG,CAAM,EAAE,IAAI,CAAC,CAACnH,GAAKI,CAAK,MACrC,gBAAAS;AAAA,MAAC4G;AAAA,MAAA;AAAA,QAEC,MAAMzH;AAAA,QACN,OAAAI;AAAA,QACA,OAAOoH,EAAcxH,CAAG;AAAA,QACxB,UAAU,CAACwB,MAAU+F,EAAkBvH,GAAKwB,CAAK;AAAA,MAAA;AAAA,MAJ5CxB;AAAA,IAAA,CAMR,GACL;AAAA,KAGEkH,EAAa,SAAS,UAAUA,EAAa,SAAS,aACtD,gBAAArG;AAAA,MAAC6G;AAAA,MAAA;AAAA,QACC,QAAQR,EAAa;AAAA,QACrB,cAAeA,EAAa,KAAuC;AAAA,QACnE,gBAAAtF;AAAA,MAAA;AAAA,IAAA;AAAA,EACF,EAAA,CAEJ,EAAA,CACF;AAEJ;AASA,SAAS6F,GAAY,EAAE,MAAAxQ,GAAM,OAAAmJ,GAAO,OAAAoB,GAAO,UAAAmG,KAA8B;AACvE,QAAMC,IAAQxH,EAAM,SAASnJ,GACvB4Q,IACJ;AAGF,SAAIzH,EAAM,yBAEL,OAAA,EACC,UAAA;AAAA,IAAA,gBAAAS,EAAC,SAAA,EAAM,WAAU,mEACd,UAAA+G,GACH;AAAA,IACA,gBAAAvG;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,OAAO,OAAOG,KAAS,EAAE;AAAA,QACzB,UAAU,CAAC3J,MAAM8P,EAAS9P,EAAE,OAAO,KAAK;AAAA,QACxC,WAAWgQ;AAAA,QAEX,UAAA;AAAA,UAAA,gBAAAhH,EAAC,UAAA,EAAO,OAAM,IAAG,UAAA,aAAS;AAAA,UACzBT,EAAM,KAAK,IAAI,CAAC0H,MACf,gBAAAjH,EAAC,UAAA,EAAiB,OAAOiH,GACtB,UAAAA,EAAA,GADUA,CAEb,CACD;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,IAEF1H,EAAM,eACL,gBAAAS,EAAC,OAAE,WAAU,iDAAiD,YAAM,YAAA,CAAY;AAAA,EAAA,GAEpF,IAKAT,EAAM,SAAS,6BAEd,OAAA,EACC,UAAA;AAAA,IAAA,gBAAAS,EAAC,SAAA,EAAM,WAAU,mEACd,UAAA+G,GACH;AAAA,IACA,gBAAA/G;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,OAAOW,MAAU,SAAY,OAAOA,CAAK,IAAI;AAAA,QAC7C,UAAU,CAAC3J,MAAM8P,EAAS,OAAO9P,EAAE,OAAO,KAAK,CAAC;AAAA,QAChD,KAAKuI,EAAM;AAAA,QACX,KAAKA,EAAM;AAAA,QACX,WAAWyH;AAAA,MAAA;AAAA,IAAA;AAAA,IAEZzH,EAAM,eACL,gBAAAS,EAAC,OAAE,WAAU,iDAAiD,YAAM,YAAA,CAAY;AAAA,EAAA,GAEpF,IAKAT,EAAM,SAAS,YAEf,gBAAAiB,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,IAAA,gBAAAR;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,EAAQW;AAAA,QACjB,UAAU,CAAC3J,MAAM8P,EAAS9P,EAAE,OAAO,OAAO;AAAA,QAC1C,WAAU;AAAA,MAAA;AAAA,IAAA;AAAA,IAEZ,gBAAAgJ,EAAC,SAAA,EAAM,WAAU,wDAAwD,UAAA+G,EAAA,CAAM;AAAA,EAAA,GACjF,IAKA3Q,EAAK,cAAc,SAAS,OAAO,KAAK,OAAOuK,KAAU,YAAYA,EAAM,WAAW,GAAG,sBAExF,OAAA,EACC,UAAA;AAAA,IAAA,gBAAAX,EAAC,SAAA,EAAM,WAAU,mEACd,UAAA+G,GACH;AAAA,IACA,gBAAAvG,EAAC,OAAA,EAAI,WAAU,cACb,UAAA;AAAA,MAAA,gBAAAR;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,OAAO,OAAOW,KAAS,SAAS;AAAA,UAChC,UAAU,CAAC3J,MAAM8P,EAAS9P,EAAE,OAAO,KAAK;AAAA,UACxC,WAAU;AAAA,QAAA;AAAA,MAAA;AAAA,MAEZ,gBAAAgJ;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,OAAO,OAAOW,KAAS,EAAE;AAAA,UACzB,UAAU,CAAC3J,MAAM8P,EAAS9P,EAAE,OAAO,KAAK;AAAA,UACxC,WAAWgQ,IAAe;AAAA,QAAA;AAAA,MAAA;AAAA,IAC5B,EAAA,CACF;AAAA,EAAA,GACF,IAKAzH,EAAM,SAAS,6BAEd,OAAA,EACC,UAAA;AAAA,IAAA,gBAAAS,EAAC,SAAA,EAAM,WAAU,mEACd,UAAA+G,GACH;AAAA,IACA,gBAAA/G;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,OAAOW,IAAQ,KAAK,UAAUA,GAAO,MAAM,CAAC,IAAI;AAAA,QAChD,UAAU,CAAC3J,MAAM;AACf,cAAI;AACF,YAAA8P,EAAS,KAAK,MAAM9P,EAAE,OAAO,KAAK,CAAC;AAAA,UACrC,QAAQ;AAAA,UAER;AAAA,QACF;AAAA,QACA,MAAM;AAAA,QACN,WAAWgQ,IAAe;AAAA,MAAA;AAAA,IAAA;AAAA,IAE3BzH,EAAM,eACL,gBAAAS,EAAC,OAAE,WAAU,iDAAiD,YAAM,YAAA,CAAY;AAAA,EAAA,GAEpF,sBAMD,OAAA,EACC,UAAA;AAAA,IAAA,gBAAAA,EAAC,SAAA,EAAM,WAAU,mEACd,UAAA+G,GACH;AAAA,IACC3Q,MAAS,YAAYA,MAAS,UAAUA,MAAS,SAChD,gBAAA4J;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,OAAO,OAAOW,KAAS,EAAE;AAAA,QACzB,UAAU,CAAC3J,MAAM8P,EAAS9P,EAAE,OAAO,KAAK;AAAA,QACxC,MAAM;AAAA,QACN,WAAWgQ;AAAA,MAAA;AAAA,IAAA,IAGb,gBAAAhH;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,OAAO,OAAOW,KAAS,EAAE;AAAA,QACzB,UAAU,CAAC3J,MAAM8P,EAAS9P,EAAE,OAAO,KAAK;AAAA,QACxC,WAAWgQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAGdzH,EAAM,eACL,gBAAAS,EAAC,OAAE,WAAU,iDAAiD,YAAM,YAAA,CAAY;AAAA,EAAA,GAEpF;AAEJ;AAYA,SAAS6G,GAAmB,EAAE,QAAAlH,GAAQ,cAAAT,GAAc,gBAAA6B,KAA2C;AAC7F,QAAM,CAACmG,GAAiBC,CAAkB,IAAIvD,EAAS,EAAE,GAEnDwD,KAAalI,KAAA,gBAAAA,EAAc,eAAc,CAAA,GACzCmI,IAAkB,OAAO,QAAQD,CAAU,GAE3CE,IAAoB,MAAM;AAC9B,QAAI,CAACJ,EAAgB,OAAQ;AAE7B,UAAMK,IAA0B;AAAA,MAC9B,MAAM;AAAA,MACN,YAAY;AAAA,QACV,GAAGH;AAAA,QACH,CAACF,EAAgB,MAAM,GAAG,EAAE,MAAM,SAAA;AAAA,MAAS;AAAA,IAC7C;AAGF,IAAAnG,EAAepB,GAAQ,EAAE,cAAc4H,EAAA,CAAW,GAClDJ,EAAmB,EAAE;AAAA,EACvB,GAEMK,IAAuB,CAACrI,MAAgB;AAC5C,UAAMsI,IAAgB,EAAE,GAAGL,EAAA;AAC3B,WAAOK,EAActI,CAAG,GAEpB,OAAO,KAAKsI,CAAa,EAAE,WAAW,IACxC1G,EAAepB,GAAQ,EAAE,cAAc,OAAA,CAAW,IAElDoB,EAAepB,GAAQ;AAAA,MACrB,cAAc,EAAE,MAAM,UAAU,YAAY8H,EAAA;AAAA,IAAc,CAC3D;AAAA,EAEL,GAEMC,IAAmB,CAACvI,GAAawI,MAAiC;AACtE,IAAA5G,EAAepB,GAAQ;AAAA,MACrB,cAAc;AAAA,QACZ,MAAM;AAAA,QACN,YAAY;AAAA,UACV,GAAGyH;AAAA,UACH,CAACjI,CAAG,GAAG,EAAE,GAAGiI,EAAWjI,CAAG,GAAG,MAAAwI,EAAA;AAAA,QAAK;AAAA,MACpC;AAAA,IACF,CACD;AAAA,EACH,GAEMC,IAA0B,CAACzI,GAAa0I,MAAwB;AACpE,IAAA9G,EAAepB,GAAQ;AAAA,MACrB,cAAc;AAAA,QACZ,MAAM;AAAA,QACN,YAAY;AAAA,UACV,GAAGyH;AAAA,UACH,CAACjI,CAAG,GAAG,EAAE,GAAGiI,EAAWjI,CAAG,GAAG,aAAa0I,KAAe,OAAA;AAAA,QAAU;AAAA,MACrE;AAAA,IACF,CACD;AAAA,EACH;AAEA,SACE,gBAAArH,EAAC,OAAA,EAAI,WAAU,2DACb,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,0CACb,UAAA;AAAA,MAAA,gBAAAR,EAAC,MAAA,EAAG,WAAU,wDAAuD,UAAA,iBAAa;AAAA,wBACjF,QAAA,EAAK,WAAU,4CACb,UAAAqH,EAAgB,SAAS,IACtB,GAAGA,EAAgB,MAAM,UAAUA,EAAgB,SAAS,IAAI,MAAM,EAAE,KACxE,qBAAA,CACN;AAAA,IAAA,GACF;AAAA,IAEA,gBAAArH,EAAC,KAAA,EAAE,WAAU,iDAAgD,UAAA,wFAE7D;AAAA,IAGCqH,EAAgB,SAAS,KACxB,gBAAArH,EAAC,OAAA,EAAI,WAAU,kBACZ,UAAAqH,EAAgB,IAAI,CAAC,CAAClI,GAAKC,CAAI,MAC9B,gBAAAoB;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,WAAU;AAAA,QAEV,UAAA;AAAA,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,YAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,cAAA,gBAAAR,EAAC,QAAA,EAAK,WAAU,iEACb,UAAAb,GACH;AAAA,cACA,gBAAAqB;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,OAAOpB,EAAK;AAAA,kBACZ,UAAU,CAACpI,MACT0Q,EAAiBvI,GAAKnI,EAAE,OAAO,KAA+B;AAAA,kBAEhE,WAAU;AAAA,kBAEV,UAAA;AAAA,oBAAA,gBAAAgJ,EAAC,UAAA,EAAO,OAAM,UAAS,UAAA,UAAM;AAAA,oBAC7B,gBAAAA,EAAC,UAAA,EAAO,OAAM,UAAS,UAAA,UAAM;AAAA,oBAC7B,gBAAAA,EAAC,UAAA,EAAO,OAAM,WAAU,UAAA,WAAO;AAAA,oBAC/B,gBAAAA,EAAC,UAAA,EAAO,OAAM,UAAS,UAAA,UAAM;AAAA,oBAC7B,gBAAAA,EAAC,UAAA,EAAO,OAAM,SAAQ,UAAA,QAAA,CAAK;AAAA,kBAAA;AAAA,gBAAA;AAAA,cAAA;AAAA,YAC7B,GACF;AAAA,YACA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,OAAOZ,EAAK,eAAe;AAAA,gBAC3B,UAAU,CAACpI,MAAM4Q,EAAwBzI,GAAKnI,EAAE,OAAO,KAAK;AAAA,gBAC5D,aAAY;AAAA,gBACZ,WAAU;AAAA,cAAA;AAAA,YAAA;AAAA,UACZ,GACF;AAAA,UACA,gBAAAgJ;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SAAS,MAAMwH,EAAqBrI,CAAG;AAAA,cACvC,WAAU;AAAA,cACV,OAAM;AAAA,cAEN,UAAA,gBAAAa,EAAC,SAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAC9D,UAAA,gBAAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,eAAc;AAAA,kBACd,gBAAe;AAAA,kBACf,aAAa;AAAA,kBACb,GAAE;AAAA,gBAAA;AAAA,cAAA,EACJ,CACF;AAAA,YAAA;AAAA,UAAA;AAAA,QACF;AAAA,MAAA;AAAA,MA3CKb;AAAA,IAAA,CA6CR,GACH;AAAA,IAIF,gBAAAqB,EAAC,OAAA,EAAI,WAAU,cACb,UAAA;AAAA,MAAA,gBAAAR;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,OAAOkH;AAAA,UACP,UAAU,CAAClQ,MAAMmQ,EAAmBnQ,EAAE,OAAO,KAAK;AAAA,UAClD,WAAW,CAACA,MAAMA,EAAE,QAAQ,WAAWsQ,EAAA;AAAA,UACvC,aAAY;AAAA,UACZ,WAAU;AAAA,QAAA;AAAA,MAAA;AAAA,MAEZ,gBAAAtH;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,SAASsH;AAAA,UACT,UAAU,CAACJ,EAAgB,KAAA;AAAA,UAC3B,WAAU;AAAA,UACX,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAED,GACF;AAAA,IAGCG,EAAgB,SAAS,uBACvB,KAAA,EAAE,WAAU,iDAAgD,UAAA,+FAAA,CAG7D;AAAA,EAAA,GAEJ;AAEJ;AClcA,SAASS,GAAgBnO,GAAyBC,GAAiC;AACjF,QAAMmO,IAAU,IAAI,IAAIpO,EAAM,IAAI,CAACwD,MAAM,CAACA,EAAE,IAAIA,CAAC,CAAC,CAAC,GAC7C6K,wBAAe,IAAA,GACfC,wBAAgB,IAAA;AAGtB,aAAW/K,KAAQvD;AACjB,IAAAqO,EAAS,IAAI9K,EAAK,IAAI,CAAC,GACvB+K,EAAU,IAAI/K,EAAK,IAAI,CAAA,CAAE;AAI3B,aAAWgL,KAAQtO,GAAO;AACxB,UAAMuO,IAAUF,EAAU,IAAIC,EAAK,MAAM,KAAK,CAAA;AAC9C,IAAAC,EAAQ,KAAKD,EAAK,MAAM,GACxBD,EAAU,IAAIC,EAAK,QAAQC,CAAO,GAClCH,EAAS,IAAIE,EAAK,SAASF,EAAS,IAAIE,EAAK,MAAM,KAAK,KAAK,CAAC;AAAA,EAChE;AAGA,QAAME,IAAkB,CAAA;AACxB,aAAW,CAACnO,GAAIoO,CAAM,KAAKL;AACzB,IAAIK,MAAW,KACbD,EAAM,KAAKnO,CAAE;AAKjB,QAAMqO,IAA2B,CAAA;AACjC,SAAOF,EAAM,SAAS,KAAG;AACvB,UAAMnO,IAAKmO,EAAM,MAAA,GACXlL,IAAO6K,EAAQ,IAAI9N,CAAE;AAC3B,IAAIiD,KACFoL,EAAO,KAAKpL,CAAI;AAGlB,UAAMqL,IAAYN,EAAU,IAAIhO,CAAE,KAAK,CAAA;AACvC,eAAWuO,KAAYD,GAAW;AAChC,YAAME,KAAaT,EAAS,IAAIQ,CAAQ,KAAK,KAAK;AAClD,MAAAR,EAAS,IAAIQ,GAAUC,CAAS,GAC5BA,MAAc,KAChBL,EAAM,KAAKI,CAAQ;AAAA,IAEvB;AAAA,EACF;AAEA,SAAOF;AACT;AAKA,SAASI,GAAexL,GAA8B;AACpD,QAAMyK,IAAOzK,EAAK,QAAQ,QACpByL,IAASzL,EAAK,GAAG,QAAQ,iBAAiB,GAAG;AACnD,SAAO,GAAGyK,CAAI,IAAIgB,CAAM;AAC1B;AAKA,SAASC,EAAUjI,GAAwB;AACzC,SAAI,OAAOA,KAAU,WAEfA,EAAM,SAAS;AAAA,CAAI,IACd,MAAMA,EAAM,QAAQ,MAAM,KAAK,EAAE,QAAQ,OAAO,KAAK,IAAI,MAE3D,KAAK,UAAUA,CAAK,IAEtB,KAAK,UAAUA,GAAO,MAAM,CAAC;AACtC;AAKA,SAASkI,GACP3L,GACAtD,GACAkP,GACqC;AACrC,QAAMC,IAAUD,EAAa,IAAI5L,EAAK,EAAE,GAClC8L,IAAoB,CAAA,GAGpBC,IAAYrP,EAAM,KAAK,CAAC5C,MAAMA,EAAE,WAAWkG,EAAK,EAAE,GAClDgM,IAAeD,IAAYH,EAAa,IAAIG,EAAU,MAAM,IAAI;AAEtE,UAAQ/L,EAAK,MAAA;AAAA,IACX,KAAK,aAAa;AAChB,YAAMJ,IAAOI,EAAK;AAClB,MAAA8L,EAAQ,KAAKlM,EAAK,aAAa;AAE/B,YAAMwC,IAASxC,EAAK,UAAU,CAAA,GACxBqM,IAAW,OAAO,QAAQ7J,CAAM,EACnC,OAAO,CAAC,CAAA,EAAGmH,CAAC,MAAMA,MAAM,UAAaA,MAAM,EAAE,EAC7C,IAAI,CAAC,CAAC2C,GAAG3C,CAAC,MAAM,KAAK2C,CAAC,KAAKR,EAAUnC,CAAC,CAAC,EAAE,EACzC,KAAK;AAAA,CAAK;AAEb,aAAO;AAAA,QACL,MAAM,2BAA2B3J,EAAK,aAAa;AAAA,QACnDiM,CAAO,YAAYjM,EAAK,aAAa;AAAA,EAC3CqM,CAAQ;AAAA;AAAA,QAEF,SAAAH;AAAA,MAAA;AAAA,IAEJ;AAAA,IAEA,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACND,CAAO;AAAA,QACP,SAAS,CAAA;AAAA,MAAC;AAAA,IAId,KAAK,aAAa;AAChB,YAAMjM,IAAOI,EAAK,MACZoC,IAASxC,EAAK,UAAU,CAAA,GACxBqM,IAAW,OAAO,QAAQ7J,CAAM,EACnC,OAAO,CAAC,CAAA,EAAGmH,CAAC,MAAMA,MAAM,UAAaA,MAAM,EAAE,EAC7C,IAAI,CAAC,CAAC2C,GAAG3C,CAAC,MAAM,GAAG2C,CAAC,KAAKR,EAAUnC,CAAC,CAAC,EAAE,EACvC,KAAK,IAAI,GAEN7P,IAAQsS,KAAgB;AAC9B,aAAO;AAAA,QACL,MAAM,YAAYpM,EAAK,SAAS;AAAA,QAChCiM,CAAO,0BAA0BnS,CAAK,MAAMkG,EAAK,SAAS,IAAIqM,IAAW,OAAOA,CAAQ,OAAO,EAAE;AAAA,QACjG,SAAS,CAAA;AAAA,MAAC;AAAA,IAEd;AAAA,IAEA,KAAK,UAAU;AACb,YAAMrM,IAAOI,EAAK;AAClB,MAAA8L,EAAQ,KAAKlM,EAAK,YAAY;AAE9B,YAAMwC,IAASxC,EAAK,UAAU,CAAA,GACxBlG,IAAQsS,KAAgB,SACxBC,IAAW,OAAO,QAAQ7J,CAAM,EACnC,OAAO,CAAC,CAAA,EAAGmH,CAAC,MAAMA,MAAM,UAAaA,MAAM,EAAE,EAC7C,IAAI,CAAC,CAAC2C,GAAG3C,CAAC,MAAM,KAAK2C,CAAC,KAAKR,EAAUnC,CAAC,CAAC,EAAE,EACzC,KAAK;AAAA,CAAK;AAEb,aAAO;AAAA,QACL,MAAM,yBAAyB3J,EAAK,YAAY;AAAA,QAChDiM,CAAO,YAAYjM,EAAK,YAAY,YAAYlG,CAAK;AAAA,EAC3DuS,CAAQ;AAAA;AAAA,QAEF,SAAAH;AAAA,MAAA;AAAA,IAEJ;AAAA,IAEA,KAAK,QAAQ;AACX,YAAMlM,IAAOI,EAAK;AAClB,MAAA8L,EAAQ,KAAKlM,EAAK,YAAY;AAE9B,YAAMwC,IAASxC,EAAK,UAAU,CAAA,GACxBqM,IAAW,OAAO,QAAQ7J,CAAM,EACnC,OAAO,CAAC,CAAA,EAAGmH,CAAC,MAAMA,MAAM,UAAaA,MAAM,EAAE,EAC7C,IAAI,CAAC,CAAC2C,GAAG3C,CAAC,MAAM,KAAK2C,CAAC,KAAKR,EAAUnC,CAAC,CAAC,EAAE,EACzC,KAAK;AAAA,CAAK;AAEb,aAAO;AAAA,QACL,MAAM,yBAAyB3J,EAAK,YAAY;AAAA,QAChDiM,CAAO,YAAYjM,EAAK,YAAY;AAAA,EAC1CqM,CAAQ;AAAA;AAAA,QAEF,SAAAH;AAAA,MAAA;AAAA,IAEJ;AAAA,IAEA,KAAK,QAAQ;AACX,YAAMlM,IAAOI,EAAK;AAElB,aAAO;AAAA,QACL,MAAM;AAAA,iBAFMgM,KAAgB,QAGd,KAAKN,EAAU9L,EAAK,WAAW,CAAC;AAAA,QAC9C,SAAS,CAAA;AAAA,MAAC;AAAA,IAEd;AAAA,IAEA;AACE,aAAO;AAAA,QACL,MAAM,yBAAyBI,EAAK,IAAI;AAAA,QACxC,SAAS,CAAA;AAAA,MAAC;AAAA,EACZ;AAEN;AAKO,SAASmM,GAAmB1P,GAAyBC,GAAuB;AACjF,MAAID,EAAM,WAAW;AACnB,WAAO;AAAA;AAKT,QAAM2P,IAAcxB,GAAgBnO,GAAOC,CAAK,GAG1CkP,wBAAmB,IAAA;AACzB,aAAW5L,KAAQoM;AACjB,IAAAR,EAAa,IAAI5L,EAAK,IAAIwL,GAAexL,CAAI,CAAC;AAIhD,QAAMqM,wBAAiB,IAAA,GACjBC,IAAuB,CAAA;AAE7B,aAAWtM,KAAQoM,GAAa;AAC9B,UAAM,EAAE,MAAAG,GAAM,SAAAT,EAAA,IAAYH,GAAiB3L,GAAMtD,GAAOkP,CAAY;AACpE,IAAAU,EAAW,KAAKC,CAAI;AACpB,eAAWC,KAAOV;AAChB,MAAAO,EAAW,IAAIG,CAAG;AAAA,EAEtB;AAGA,QAAMC,IAAwB,CAAA;AAC9B,EAAIJ,EAAW,OAAO,KACpBI,EAAY,KAAK,YAAY,MAAM,KAAKJ,CAAU,EAAE,KAAK,IAAI,CAAC,8BAA8B,GAE9FI,EAAY,KAAK,2CAA2C;AAE5D,QAAMC,IAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAQTC,IAAW;AAAA;AAAA,EAEjBL,EACC;AAAA,IAAI,CAACM,MACJA,EACG,MAAM;AAAA,CAAI,EACV,IAAI,CAACC,MAAS,OAAOA,CAAI,EACzB,KAAK;AAAA,CAAI;AAAA,EAAA,EAEb,KAAK;AAAA;AAAA,CAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAOb,SAAOH,IAASD,EAAY,KAAK;AAAA,CAAI,IAAI;AAAA,IAAOE;AAClD;AChQO,SAASG,GAAY,EAAE,QAAAC,GAAQ,SAAAC,GAAS,UAAAC,KAA8B;AAC3E,QAAM,CAACC,GAAaC,CAAc,IAAIzG,EAAS,EAAE,GAC3C,CAAC0G,GAAWC,CAAY,IAAI3G,EAAS,EAAK,GAC1C,CAACvK,GAAO0K,CAAQ,IAAIH,EAAiC,IAAI,GACzD,CAAC4G,GAAYC,CAAa,IAAI7G,EAAS,EAAK,GAE5C8G,IAAevJ,EAAY,YAAY;AAC3C,QAAI,CAACiJ,EAAY,QAAQ;AACvB,MAAArG,EAAS,EAAE,SAAS,sCAAsC;AAC1D;AAAA,IACF;AAEA,IAAAwG,EAAa,EAAI,GACjBxG,EAAS,IAAI;AAEb,QAAI;AACF,YAAMlN,IAAS,MAAM4D,GAAW2P,CAAW;AAE3C,MAAIvT,EAAO,WACTsT,EAAStT,EAAO,OAAOA,EAAO,OAAOA,EAAO,IAAI,GAChDwT,EAAe,EAAE,GACjBH,EAAA,KAEAnG,EAAS;AAAA,QACP,SAASlN,EAAO,SAAS;AAAA,QACzB,MAAMA,EAAO;AAAA,QACb,QAAQA,EAAO;AAAA,MAAA,CAChB;AAAA,IAEL,SAASoN,GAAK;AACZ,MAAAF,EAAS,EAAE,SAASE,aAAe,QAAQA,EAAI,UAAU,iBAAiB;AAAA,IAC5E,UAAA;AACE,MAAAsG,EAAa,EAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAACH,GAAaD,GAAUD,CAAO,CAAC,GAE7BS,IAAiBxJ,EAAY,YAAY;AAC7C,QAAI,CAACiJ,EAAY,QAAQ;AACvB,MAAArG,EAAS,EAAE,SAAS,sCAAsC;AAC1D;AAAA,IACF;AAEA,IAAAwG,EAAa,EAAI,GACjBxG,EAAS,IAAI;AAEb,QAAI;AACF,YAAMlN,IAAS,MAAM8D,GAAayP,CAAW;AAE7C,MAAIvT,EAAO,SACTkN,EAAS,IAAI,GAEbA,EAAS,EAAE,SAAS,eAAe,GACnC,WAAW,MAAMA,EAAS,IAAI,GAAG,GAAI,KAC5BlN,EAAO,OAAO,SAAS,KAChCkN,EAASlN,EAAO,OAAO,CAAC,CAAC;AAAA,IAE7B,SAASoN,GAAK;AACZ,MAAAF,EAAS,EAAE,SAASE,aAAe,QAAQA,EAAI,UAAU,qBAAqB;AAAA,IAChF,UAAA;AACE,MAAAsG,EAAa,EAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAACH,CAAW,CAAC,GAEVQ,IAAmBzJ,EAAY,OAAO/G,MAAe;AACzD,QAAI,CAACA,EAAK,KAAK,SAAS,OAAO,KAAK,CAACA,EAAK,KAAK,SAAS,MAAM,GAAG;AAC/D,MAAA2J,EAAS,EAAE,SAAS,sCAAsC;AAC1D;AAAA,IACF;AAEA,QAAI;AACF,YAAM8G,IAAO,MAAMzQ,EAAK,KAAA;AACxB,MAAAiQ,EAAeQ,CAAI,GACnB9G,EAAS,IAAI;AAAA,IACf,QAAQ;AACN,MAAAA,EAAS,EAAE,SAAS,uBAAuB;AAAA,IAC7C;AAAA,EACF,GAAG,CAAA,CAAE,GAEC1C,IAAiBF,EAAY,CAACnK,MAAiB;AACnD,IAAAA,EAAE,eAAA,GACFyT,EAAc,EAAI;AAAA,EACpB,GAAG,CAAA,CAAE,GAECK,IAAkB3J,EAAY,CAACnK,MAAiB;AACpD,IAAAA,EAAE,eAAA,GACFyT,EAAc,EAAK;AAAA,EACrB,GAAG,CAAA,CAAE,GAECrJ,IAAaD;AAAA,IACjB,CAACnK,MAAiB;AAChB,MAAAA,EAAE,eAAA,GACFyT,EAAc,EAAK;AAEnB,YAAMrQ,IAAOpD,EAAE,aAAa,MAAM,CAAC;AACnC,MAAIoD,KACFwQ,EAAiBxQ,CAAI;AAAA,IAEzB;AAAA,IACA,CAACwQ,CAAgB;AAAA,EAAA,GAGbG,IAAwB5J;AAAA,IAC5B,CAACnK,MAA2C;;AAC1C,YAAMoD,KAAO/D,IAAAW,EAAE,OAAO,UAAT,gBAAAX,EAAiB;AAC9B,MAAI+D,KACFwQ,EAAiBxQ,CAAI;AAAA,IAEzB;AAAA,IACA,CAACwQ,CAAgB;AAAA,EAAA;AAGnB,SAAKX,sBAGF,OAAA,EAAI,WAAU,8EACb,UAAA,gBAAAzJ,EAAC,OAAA,EAAI,WAAU,mGAEb,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,6FACb,UAAA;AAAA,MAAA,gBAAAR,EAAC,MAAA,EAAG,WAAU,uDAAsD,UAAA,mBAAe;AAAA,MACnF,gBAAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,SAASkK;AAAA,UACT,WAAU;AAAA,UAEV,UAAA,gBAAAlK,EAAC,SAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAC9D,UAAA,gBAAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,eAAc;AAAA,cACd,gBAAe;AAAA,cACf,aAAa;AAAA,cACb,GAAE;AAAA,YAAA;AAAA,UAAA,EACJ,CACF;AAAA,QAAA;AAAA,MAAA;AAAA,IACF,GACF;AAAA,IAGA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,4BACb,UAAA;AAAA,MAAA,gBAAAR,EAAC,KAAA,EAAE,WAAU,iDAAgD,UAAA,0EAE7D;AAAA,MAGA,gBAAAQ;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,YAAYa;AAAA,UACZ,aAAayJ;AAAA,UACb,QAAQ1J;AAAA,UACR,WAAW,4EACToJ,IACI,mDACA,sCACN;AAAA,UAEA,UAAA;AAAA,YAAA,gBAAAxK;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,QAAO;AAAA,gBACP,UAAU+K;AAAA,gBACV,WAAU;AAAA,gBACV,IAAG;AAAA,cAAA;AAAA,YAAA;AAAA,YAEL,gBAAAvK;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,SAAQ;AAAA,gBACR,WAAU;AAAA,gBAEV,UAAA;AAAA,kBAAA,gBAAAR;AAAA,oBAAC;AAAA,oBAAA;AAAA,sBACC,WAAU;AAAA,sBACV,MAAK;AAAA,sBACL,SAAQ;AAAA,sBACR,QAAO;AAAA,sBAEP,UAAA,gBAAAA;AAAA,wBAAC;AAAA,wBAAA;AAAA,0BACC,eAAc;AAAA,0BACd,gBAAe;AAAA,0BACf,aAAa;AAAA,0BACb,GAAE;AAAA,wBAAA;AAAA,sBAAA;AAAA,oBACJ;AAAA,kBAAA;AAAA,kBAEF,gBAAAA,EAAC,QAAA,EAAK,WAAU,oDAAmD,UAAA,mBAEnE;AAAA,kBAAQ;AAAA,kBAAI;AAAA,oCAEX,MAAA,EAAG;AAAA,kBACJ,gBAAAA,EAAC,QAAA,EAAK,WAAU,WAAU,UAAA,sBAAA,CAAmB;AAAA,gBAAA;AAAA,cAAA;AAAA,YAAA;AAAA,UAC/C;AAAA,QAAA;AAAA,MAAA;AAAA,MAIF,gBAAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,OAAOoK;AAAA,UACP,UAAU,CAACpT,MAAM;AACf,YAAAqT,EAAerT,EAAE,OAAO,KAAK,GAC7B+M,EAAS,IAAI;AAAA,UACf;AAAA,UACA,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAmBb,WAAU;AAAA,QAAA;AAAA,MAAA;AAAA,MAIX1K,KACC,gBAAAmH;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAW,+BACTnH,EAAM,YAAY,gBACd,wEACA,6DACN;AAAA,UAEA,UAAA;AAAA,YAAA,gBAAA2G,EAAC,QAAA,EAAK,WAAU,eAAe,UAAA3G,EAAM,SAAQ;AAAA,YAC5CA,EAAM,QACL,gBAAAmH,EAAC,QAAA,EAAK,WAAU,gBAAe,UAAA;AAAA,cAAA;AAAA,cACtBnH,EAAM;AAAA,cACZA,EAAM,SAAS,YAAYA,EAAM,MAAM,KAAK;AAAA,cAAG;AAAA,YAAA,EAAA,CAClD;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAEJ,GAEJ;AAAA,IAGA,gBAAAmH,EAAC,OAAA,EAAI,WAAU,6FACb,UAAA;AAAA,MAAA,gBAAAR,EAAC,QAAA,EAAK,WAAU,4CAA2C,UAAA,iDAE3D;AAAA,MACA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,cACb,UAAA;AAAA,QAAA,gBAAAR;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS2K;AAAA,YACT,UAAUL,KAAa,CAACF,EAAY,KAAA;AAAA,YACpC,WAAU;AAAA,YACX,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAGD,gBAAA5J;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAASkK;AAAA,YACT,UAAUJ,KAAa,CAACF,EAAY,KAAA;AAAA,YACpC,WAAU;AAAA,YAET,UAAA;AAAA,cAAAE,uBACE,OAAA,EAAI,WAAU,wBAAuB,SAAQ,aAAY,MAAK,QAC7D,UAAA;AAAA,gBAAA,gBAAAtK;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,WAAU;AAAA,oBACV,IAAG;AAAA,oBACH,IAAG;AAAA,oBACH,GAAE;AAAA,oBACF,QAAO;AAAA,oBACP,aAAY;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAEd,gBAAAA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,WAAU;AAAA,oBACV,MAAK;AAAA,oBACL,GAAE;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACJ,GACF;AAAA,cACA;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAEJ,EAAA,CACF;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,EAAA,CACF,EAAA,CACF,IAlKkB;AAoKtB;ACzQO,SAASgL,GAAQ;AAAA,EACtB,cAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,iBAAAC,IAAkB;AAAA,EAClB,qBAAAC,IAAsB;AACxB,IAAkB,IAAI;AACpB,QAAMC,IAAYtP,EAAiB,CAAC8D,MAAMA,EAAE,SAAS,GAC/CyL,IAAUvP,EAAiB,CAAC8D,MAAMA,EAAE,OAAO,GAC3C0L,IAAexP,EAAiB,CAAC8D,MAAMA,EAAE,YAAY,GACrD2L,IAAiBzP,EAAiB,CAAC8D,MAAMA,EAAE,cAAc,GACzDnG,IAAQqC,EAAiB,CAAC8D,MAAMA,EAAE,KAAK,GACvClG,IAAQoC,EAAiB,CAAC8D,MAAMA,EAAE,KAAK,GACvC4L,IAAezQ,EAAiB,CAAC6E,MAAMA,EAAE,YAAY,GAGrDhC,IAAqB9B,EAAiB,CAAC8D,MAAMA,EAAE,kBAAkB,GACjE6L,IAAoB3P,EAAiB,CAAC8D,MAAMA,EAAE,iBAAiB,GAC/D8L,IAAe5P,EAAiB,CAAC8D,MAAMA,EAAE,YAAY,GACrD+L,IAAgB7P,EAAiB,CAAC8D,MAAMA,EAAE,aAAa,GACvDgM,IAAwB9P,EAAiB,CAAC8D,MAAMA,EAAE,qBAAqB,GAGvEqG,IAAiBnK,EAAiB,CAAC8D,MAAMA,EAAE,cAAc,GACzDiM,IAAgB/P,EAAiB,CAAC8D,MAAMA,EAAE,aAAa,GAEvD,CAACkM,GAAYC,CAAa,IAAIrI,EAAS,EAAK,GAC5C,CAACsI,GAAYC,CAAa,IAAIvI,EAAS,EAAK,GAC5C,CAACwI,GAAWC,CAAY,IAAIzI,EAAoB,MAAM,GACtD,CAACwG,GAAaC,EAAc,IAAIzG,EAAS,EAAE,GAC3C,CAAC0I,IAAWC,EAAY,IAAI3I,EAAS,EAAE,GACvC,CAAC4I,IAAcC,CAAe,IAAI7I,EAAwB,IAAI,GAC9D,CAAC8I,IAAeC,CAAgB,IAAI/I,EAAS,EAAK,GAClD,CAACgJ,IAAaC,CAAc,IAAIjJ,EAAS,EAAE;AAGjD,EAAAM,EAAU,MAAM;AACd,UAAM4I,IAAoB,MAAM;AAC9B,MAAAL,EAAgB,sBAAsB,GACtC,WAAW,MAAMA,EAAgB,IAAI,GAAG,GAAI;AAAA,IAC9C;AACA,kBAAO,iBAAiB,wBAAwBK,CAAiB,GAC1D,MAAM,OAAO,oBAAoB,wBAAwBA,CAAiB;AAAA,EACnF,GAAG,CAAA,CAAE;AAGL,QAAMC,IAAa5L,EAAY,MAAM;AACnC,IAAIxH,EAAM,WAAW,MACrBiS,EAAA,GACAa,EAAgB,QAAQ,GACxB,WAAW,MAAMA,EAAgB,IAAI,GAAG,GAAI;AAAA,EAC9C,GAAG,CAAC9S,EAAM,QAAQiS,CAAY,CAAC,GAGzBoB,KAAoB,MAAM;AAC9B,IAAAH,EAAe/O,CAAkB,GACjC6O,EAAiB,EAAI;AAAA,EACvB,GAEMM,KAAmB,MAAM;AAC7B,UAAMC,IAAUN,GAAY,KAAA;AAC5B,IAAIM,KAAWA,MAAYpP,KACzBgO,EAAsBoB,CAAO,GAE/BP,EAAiB,EAAK;AAAA,EACxB,GAGMQ,KAAkBhM,EAAY,MAAM;AACxC,IAAIgF,KACF4F,EAAc5F,CAAc;AAAA,EAEhC,GAAG,CAACA,GAAgB4F,CAAa,CAAC;AAGlC,EAAA7H,EAAU,MAAM;AACd,aAASkJ,EAAcpW,GAAkB;AACvC,OAAKA,EAAE,WAAWA,EAAE,YAAYA,EAAE,QAAQ,QACxCA,EAAE,eAAA,GACF+V,EAAA,KAEG/V,EAAE,WAAWA,EAAE,YAAYA,EAAE,QAAQ,QACxCA,EAAE,eAAA,GACFmW,GAAA;AAAA,IAEJ;AACA,oBAAS,iBAAiB,WAAWC,CAAa,GAC3C,MAAM,SAAS,oBAAoB,WAAWA,CAAa;AAAA,EACpE,GAAG,CAACL,GAAYI,EAAe,CAAC;AAEhC,QAAME,KAAgB,YAAY;AAChC,UAAM9B,EAAA;AAAA,EACR,GAEM+B,KAAe,YAAY;AAC/B,UAAM5S,IAAO,MAAM8Q,EAAA;AACnB,IAAAnB,GAAe3P,CAAI;AACnB,UAAM6S,IAAKlE,GAAmB1P,GAAOC,CAAK;AAC1C,IAAA2S,GAAagB,CAAE,GACftB,EAAc,EAAI;AAAA,EACpB,GAEMuB,KAAa,MAAM;AACvB,UAAMC,IAAUrB,MAAc,SAAShC,IAAckC;AACrD,cAAU,UAAU,UAAUmB,CAAO;AAAA,EACvC,GAEM/C,KAAevJ;AAAA,IACnB,CAACuM,GAA6BC,GAA6BvX,OAAkB;AAC3E,MAAAqV,EAAeiC,GAAeC,GAAevX,EAAI,GACjDqW,EAAgB,oBAAoB,GACpC,WAAW,MAAMA,EAAgB,IAAI,GAAG,GAAI;AAAA,IAC9C;AAAA,IACA,CAAChB,CAAc;AAAA,EAAA;AAGjB,SACE,gBAAAjL,EAAAoB,GAAA,EACE,UAAA;AAAA,IAAA,gBAAApB,EAAC,OAAA,EAAI,WAAU,uHACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,2BAEZ,UAAA;AAAA,QAAA,CAAC6K,KACA,gBAAArL;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS6L;AAAA,YACT,WAAU;AAAA,YACV,OAAM;AAAA,YAEN,UAAA,gBAAA7L,EAAC,SAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAC9D,UAAA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAc;AAAA,gBACd,gBAAe;AAAA,gBACf,aAAa;AAAA,gBACb,GAAE;AAAA,cAAA;AAAA,YAAA,EACJ,CACF;AAAA,UAAA;AAAA,QAAA;AAAA,QAIJ,gBAAAQ,EAAC,OAAA,EAAI,WAAU,6BACb,UAAA;AAAA,UAAA,gBAAAR,EAAC,MAAA,EAAG,WAAU,mDAAkD,UAAA,iBAAa;AAAA,UAC5EiL;AAAA,UACA,CAACG,KACA,gBAAApL;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,QAAO;AAAA,cACP,KAAI;AAAA,cACJ,WAAU;AAAA,cACX,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QAED,GAEJ;AAAA,QAGA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,UAAAkM,KACC,gBAAA1M;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,OAAO4M;AAAA,cACP,UAAU,CAAC5V,MAAM6V,EAAe7V,EAAE,OAAO,KAAK;AAAA,cAC9C,QAAQiW;AAAA,cACR,WAAW,CAACjW,MAAM;AAChB,gBAAIA,EAAE,QAAQ,WAASiW,GAAA,GACnBjW,EAAE,QAAQ,aACZ6V,EAAe/O,CAAkB,GACjC6O,EAAiB,EAAK;AAAA,cAE1B;AAAA,cACA,WAAU;AAAA,cACV,WAAS;AAAA,YAAA;AAAA,UAAA,IAGX,gBAAA3M;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SAASgN;AAAA,cACT,WAAU;AAAA,cACV,OAAM;AAAA,cAEL,UAAAlP;AAAA,YAAA;AAAA,UAAA;AAAA,UAGJ6N,KACC,gBAAA3L,EAAC,QAAA,EAAK,WAAU,8CAA6C,UAAA,aAAS;AAAA,UAEvEwM,MACC,gBAAAxM,EAAC,QAAA,EAAK,WAAU,8CAA8C,UAAAwM,GAAA,CAAa;AAAA,QAAA,GAE/E;AAAA,QAEA,gBAAAhM,EAAC,QAAA,EAAK,WAAU,4CACb,UAAA;AAAA,UAAA7G,EAAM;AAAA,UAAO;AAAA,UAAMA,EAAM,WAAW,IAAI,MAAM;AAAA,QAAA,EAAA,CACjD;AAAA,MAAA,GACF;AAAA,MAEA,gBAAA6G,EAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,QAAA0K;AAAA,QACD,gBAAAlL;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS0L;AAAA,YACT,WAAU;AAAA,YACV,OAAM;AAAA,YAEN,UAAA,gBAAAlL,EAAC,SAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAC9D,UAAA;AAAA,cAAA,gBAAAR;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,eAAc;AAAA,kBACd,gBAAe;AAAA,kBACf,aAAa;AAAA,kBACb,GAAE;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEJ,gBAAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,eAAc;AAAA,kBACd,gBAAe;AAAA,kBACf,aAAa;AAAA,kBACb,GAAE;AAAA,gBAAA;AAAA,cAAA;AAAA,YACJ,EAAA,CACF;AAAA,UAAA;AAAA,QAAA;AAAA,QAIF,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS+M;AAAA,YACT,UAAUpT,EAAM,WAAW;AAAA,YAC3B,WAAU;AAAA,YACV,OAAM;AAAA,YAEN,UAAA,gBAAAqG,EAAC,SAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAC9D,UAAA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAc;AAAA,gBACd,gBAAe;AAAA,gBACf,aAAa;AAAA,gBACb,GAAE;AAAA,cAAA;AAAA,YAAA,EACJ,CACF;AAAA,UAAA;AAAA,QAAA;AAAA,QAGF,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS,MAAMmM,EAAc,EAAI;AAAA,YACjC,WAAU;AAAA,YACX,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAID,gBAAAnM;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAASsN;AAAA,YACT,UAAU3T,EAAM,WAAW;AAAA,YAC3B,WAAU;AAAA,YACX,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAID,gBAAAqG;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAASqN;AAAA,YACT,UAAU1T,EAAM,WAAW,KAAK2R,EAAU,WAAW;AAAA,YACrD,WAAU;AAAA,YAET,UAAAA,EAAU,WAAW,YACpB,gBAAA9K,EAAAoB,GAAA,EACE,UAAA;AAAA,cAAA,gBAAApB,EAAC,SAAI,WAAU,wBAAuB,SAAQ,aAAY,MAAK,QAC7D,UAAA;AAAA,gBAAA,gBAAAR;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,WAAU;AAAA,oBACV,IAAG;AAAA,oBACH,IAAG;AAAA,oBACH,GAAE;AAAA,oBACF,QAAO;AAAA,oBACP,aAAY;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAEd,gBAAAA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,WAAU;AAAA,oBACV,MAAK;AAAA,oBACL,GAAE;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACJ,GACF;AAAA,cAAM;AAAA,YAAA,EAAA,CAER,IAEA,gBAAAQ,EAAAoB,GAAA,EACE,UAAA;AAAA,cAAA,gBAAApB,EAAC,OAAA,EAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAC9D,UAAA;AAAA,gBAAA,gBAAAR;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,eAAc;AAAA,oBACd,gBAAe;AAAA,oBACf,aAAa;AAAA,oBACb,GAAE;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAEJ,gBAAAA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,eAAc;AAAA,oBACd,gBAAe;AAAA,oBACf,aAAa;AAAA,oBACb,GAAE;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACJ,GACF;AAAA,cAAM;AAAA,YAAA,EAAA,CAER;AAAA,UAAA;AAAA,QAAA;AAAA,QAGHmL;AAAA,MAAA,EAAA,CACH;AAAA,IAAA,GACF;AAAA,IAGCG,EAAU,WAAW,eAAeA,EAAU,SAAS,SAAS,KAC/D,gBAAAtL,EAAC,OAAA,EAAI,WAAU,8FACb,UAAA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,QAAA,EAAK,WAAU,kDAAiD,UAAA;AAAA,QAAA;AAAA,QACpD8K,EAAU,SAAS;AAAA,QAAO;AAAA,QACpCA,EAAU,SAAS,WAAW,IAAI,MAAM;AAAA,MAAA,GAC3C;AAAA,MACA,gBAAAtL,EAAC,SAAI,WAAU,cACZ,YAAU,UAAU,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC7G,GAAKyU,MACzC,gBAAA5N,EAAC,KAAA,EAAY,MAAM7G,GAAK,QAAO,UAAS,KAAI,uBAAsB,WAAU,SAC1E,UAAA,gBAAA6G;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAK7G;AAAA,UACL,KAAI;AAAA,UACJ,WAAU;AAAA,QAAA;AAAA,MAAA,EACZ,GALMyU,CAMR,CACD,EAAA,CACH;AAAA,IAAA,EAAA,CACF,EAAA,CACF;AAAA,IAGDtC,EAAU,WAAW,WACpB,gBAAAtL,EAAC,OAAA,EAAI,WAAU,sFACb,UAAA,gBAAAQ,EAAC,QAAA,EAAK,WAAU,kCAAiC,UAAA;AAAA,MAAA;AAAA,MAAQ8K,EAAU;AAAA,IAAA,EAAA,CAAM,EAAA,CAC3E;AAAA,IAIDU,uBACE,OAAA,EAAI,WAAU,8EACb,UAAA,gBAAAxL,EAAC,OAAA,EAAI,WAAU,mGACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,6FACb,UAAA;AAAA,QAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,UAAA,gBAAAR,EAAC,MAAA,EAAG,WAAU,uDAAsD,UAAA,mBAEpE;AAAA,UAEA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,0DACb,UAAA;AAAA,YAAA,gBAAAR;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,SAAS,MAAMqM,EAAa,MAAM;AAAA,gBAClC,WAAW,8DACTD,MAAc,SACV,sEACA,4EACN;AAAA,gBACD,UAAA;AAAA,cAAA;AAAA,YAAA;AAAA,YAGD,gBAAApM;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,SAAS,MAAMqM,EAAa,YAAY;AAAA,gBACxC,WAAW,8DACTD,MAAc,eACV,sEACA,4EACN;AAAA,gBACD,UAAA;AAAA,cAAA;AAAA,YAAA;AAAA,UAED,EAAA,CACF;AAAA,QAAA,GACF;AAAA,QACA,gBAAApM;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS,MAAMiM,EAAc,EAAK;AAAA,YAClC,WAAU;AAAA,YAEV,UAAA,gBAAAjM,EAAC,SAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAC9D,UAAA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAc;AAAA,gBACd,gBAAe;AAAA,gBACf,aAAa;AAAA,gBACb,GAAE;AAAA,cAAA;AAAA,YAAA,EACJ,CACF;AAAA,UAAA;AAAA,QAAA;AAAA,MACF,GACF;AAAA,MACA,gBAAAA,EAAC,OAAA,EAAI,WAAU,4BACb,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,mHACZ,UAAAoM,MAAc,SAAShC,IAAckC,GAAA,CACxC,GACF;AAAA,MACA,gBAAA9L,EAAC,OAAA,EAAI,WAAU,6FACb,UAAA;AAAA,QAAA,gBAAAR,EAAC,UAAK,WAAU,4CACb,UAAAoM,MAAc,SACX,kDACA,2BACN;AAAA,QACA,gBAAA5L,EAAC,OAAA,EAAI,WAAU,cACb,UAAA;AAAA,UAAA,gBAAAR;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SAASwN;AAAA,cACT,WAAU;AAAA,cACX,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAGD,gBAAAxN;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SAAS,MAAMiM,EAAc,EAAK;AAAA,cAClC,WAAU;AAAA,cACX,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QAED,EAAA,CACF;AAAA,MAAA,EAAA,CACF;AAAA,IAAA,EAAA,CACF,EAAA,CACF;AAAA,IAIF,gBAAAjM;AAAA,MAACgK;AAAA,MAAA;AAAA,QACC,QAAQkC;AAAA,QACR,SAAS,MAAMC,EAAc,EAAK;AAAA,QAClC,UAAUzB;AAAA,MAAA;AAAA,IAAA;AAAA,EACZ,GACF;AAEJ;AC9aO,SAASmD,KAAU;AACxB,QAAMC,IAAe9R,EAAiB,CAAC8D,MAAMA,EAAE,YAAY,GACrD,CAACiO,GAAiBC,CAAkB,IAAIpK,EAAwB,IAAI,GAEpE;AAAA,IACJ,MAAMqK;AAAA,IACN,WAAA3D;AAAA,IACA,OAAAjR;AAAA,IACA,SAAA6U;AAAA,EAAA,IACEhJ,EAAS;AAAA,IACX,UAAU,CAAC,QAAQ;AAAA,IACnB,SAASnL;AAAA,IACT,iBAAiB;AAAA;AAAA,EAAA,CAClB,GAEKoU,IAAqB,OAAOC,MAAoB;AACpD,IAAAJ,EAAmBI,CAAO;AAC1B,QAAI;AACF,YAAMC,IAAW,MAAMnU,GAAiBkU,CAAO;AAC/C,UAAIC,KAAA,QAAAA,EAAU,UAAU;AAEtB,cAAMpS,IAA4B;AAAA,UAChC,IAAI,SAASmS,CAAO;AAAA,UACpB,MAAM,iBAAiBA,CAAO;AAAA,UAC9B,aAAa;AAAA,UACb,UAAU;AAAA,UACV,WAAW;AAAA,UACX,UAAU;AAAA,YACR,OAAOC,EAAS,SAAS;AAAA,YACzB,OAAOA,EAAS,SAAS;AAAA,UAAA;AAAA,QAC3B;AAEF,QAAAP,EAAa7R,CAAQ,GAErB,OAAO,cAAc,IAAI,YAAY,iBAAiB,CAAC;AAAA,MACzD;AACE,cAAM,+CAA+C;AAAA,IAEzD,SAASgI,GAAK;AACZ,cAAQ,MAAM,4BAA4BA,CAAG,GAC7C,MAAM,yBAAyB;AAAA,IACjC,UAAA;AACE,MAAA+J,EAAmB,IAAI;AAAA,IACzB;AAAA,EACF;AAEA,SAAI1D,IAEA,gBAAAtK,EAAC,OAAA,EAAI,WAAU,oDAAmD,UAAA,qBAAiB,IAInF3G,IAEA,gBAAAmH,EAAC,OAAA,EAAI,WAAU,kDAAiD,UAAA;AAAA,IAAA;AAAA,IACvCnH,aAAiB,QAAQA,EAAM,UAAU;AAAA,EAAA,GAClE,IAIA,CAAC4U,KAAUA,EAAO,WAAW,IAE7B,gBAAAzN,EAAC,OAAA,EAAI,WAAU,oDACb,UAAA;AAAA,IAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,gBAAe,UAAA,iBAAa;AAAA,IAC3C,gBAAAA,EAAC,OAAA,EAAI,WAAU,WAAU,UAAA,yDAAA,CAAsD;AAAA,EAAA,GACjF,IAKF,gBAAAQ,EAAC,OAAA,EAAI,WAAU,+CACb,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,0CACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EACC,UAAA;AAAA,QAAA,gBAAAA,EAAC,MAAA,EAAG,WAAU,uDAAsD,UAAA;AAAA,UAAA;AAAA,UACzDyN,EAAO;AAAA,UAAO;AAAA,QAAA,GACzB;AAAA,QACA,gBAAAjO,EAAC,KAAA,EAAE,WAAU,4CAA2C,UAAA,wBAAA,CAAqB;AAAA,MAAA,GAC/E;AAAA,MACA,gBAAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,SAAS,MAAMkO,EAAA;AAAA,UACf,WAAU;AAAA,UACX,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAED,GACF;AAAA,sBAEC,OAAA,EAAI,WAAU,wDACZ,UAAAD,EAAO,IAAI,CAACK,MACX,gBAAAtO;AAAA,MAACuO;AAAA,MAAA;AAAA,QAEC,OAAAD;AAAA,QACA,gBAAgB,MAAMH,EAAmBG,EAAM,EAAE;AAAA,QACjD,WAAWP,MAAoBO,EAAM;AAAA,MAAA;AAAA,MAHhCA,EAAM;AAAA,IAAA,CAKd,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;AAQA,SAASC,GAAU,EAAE,OAAAD,GAAO,gBAAAE,GAAgB,WAAAlE,KAA6B;AACvE,QAAMmE,IAAa,CAAC3S,MACX,IAAI,KAAKA,CAAS,EAAE,eAAA,GAGvBwI,IAAa,CAACC,MACdA,IAAQ,OAAa,GAAGA,CAAK,OAC7BA,IAAQ,UAAoB,IAAIA,IAAQ,MAAM,QAAQ,CAAC,CAAC,QACrD,IAAIA,IAAS,SAAc,QAAQ,CAAC,CAAC;AAG9C,SACE,gBAAA/D,EAAC,OAAA,EAAI,WAAU,sJACb,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,YACb,UAAA;AAAA,MAAA,gBAAAR;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAMhG,GAAYsU,EAAM,EAAE;AAAA,UAC1B,QAAO;AAAA,UACP,KAAI;AAAA,UACJ,WAAU;AAAA,UAEV,UAAA,gBAAAtO;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,KAAKhG,GAAYsU,EAAM,EAAE;AAAA,cACzB,KAAKA,EAAM;AAAA,cACX,WAAU;AAAA,cACV,SAAQ;AAAA,YAAA;AAAA,UAAA;AAAA,QACV;AAAA,MAAA;AAAA,MAGF,gBAAAtO,EAAC,OAAA,EAAI,WAAU,sHACb,UAAA,gBAAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,SAAS,CAAChJ,MAAM;AACd,YAAAA,EAAE,eAAA,GACFwX,EAAA;AAAA,UACF;AAAA,UACA,UAAUlE;AAAA,UACV,WAAU;AAAA,UAET,cAAY,eAAe;AAAA,QAAA;AAAA,MAAA,EAC9B,CACF;AAAA,IAAA,GACF;AAAA,IACA,gBAAA9J,EAAC,OAAA,EAAI,WAAU,OACb,UAAA;AAAA,MAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,8DACZ,UAAAsO,EAAM,UACT;AAAA,MACA,gBAAA9N,EAAC,OAAA,EAAI,WAAU,iDACZ,UAAA;AAAA,QAAA8N,EAAM;AAAA,QAAK;AAAA,QAAIhK,EAAWgK,EAAM,IAAI;AAAA,MAAA,GACvC;AAAA,wBACC,OAAA,EAAI,WAAU,iDACZ,UAAAG,EAAWH,EAAM,SAAS,EAAA,CAC7B;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,GACF;AAEJ;ACzJO,MAAMI,KAAkC;AAAA,EAC7C,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,aAAa;AAAA,EACb,UAAU;AAAA,EACV,WAAW;AAAA,EACX,MAAM,CAAC,OAAO,SAAS,WAAW,WAAW;AAAA,EAC7C,UAAU;AAAA,IACR,OAAO;AAAA,MACL;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU,EAAE,GAAG,KAAK,GAAG,IAAA;AAAA,QACvB,MAAM;AAAA,UACJ,eAAe;AAAA,UACf,QAAQ;AAAA,YACN,OAAO;AAAA,cACL,MAAM;AAAA,cACN,MAAM;AAAA,gBACJ,QAAQ,CAAC,MAAM,MAAM,MAAM,IAAI;AAAA,gBAC/B,UAAU;AAAA,kBACR;AAAA,oBACE,OAAO;AAAA,oBACP,MAAM,CAAC,KAAK,KAAK,KAAK,GAAG;AAAA,oBACzB,iBAAiB;AAAA,sBACf;AAAA,sBACA;AAAA,sBACA;AAAA,sBACA;AAAA,oBAAA;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAAA,cAEF,SAAS;AAAA,gBACP,SAAS;AAAA,kBACP,OAAO;AAAA,oBACL,SAAS;AAAA,oBACT,MAAM;AAAA,kBAAA;AAAA,gBACR;AAAA,cACF;AAAA,YACF;AAAA,YAEF,OAAO;AAAA,YACP,QAAQ;AAAA,UAAA;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAAA,IAEF,OAAO,CAAA;AAAA,EAAC;AAEZ,GAEaC,KAA8B;AAAA,EACzC,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,aAAa;AAAA,EACb,UAAU;AAAA,EACV,WAAW;AAAA,EACX,MAAM,CAAC,QAAQ,UAAU,SAAS,SAAS;AAAA,EAC3C,UAAU;AAAA,IACR,OAAO;AAAA,MACL;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU,EAAE,GAAG,KAAK,GAAG,IAAA;AAAA,QACvB,MAAM;AAAA,UACJ,eAAe;AAAA,UACf,QAAQ;AAAA,YACN,OAAO;AAAA,cACL,MAAM;AAAA,cACN,MAAM;AAAA,gBACJ,QAAQ,CAAC,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK;AAAA,gBACjD,UAAU;AAAA,kBACR;AAAA,oBACE,OAAO;AAAA,oBACP,MAAM,CAAC,MAAM,MAAM,KAAM,KAAM,MAAM,IAAI;AAAA,oBACzC,aAAa;AAAA,oBACb,iBAAiB;AAAA,oBACjB,MAAM;AAAA,oBACN,SAAS;AAAA,kBAAA;AAAA,gBACX;AAAA,cACF;AAAA,cAEF,SAAS;AAAA,gBACP,SAAS;AAAA,kBACP,OAAO;AAAA,oBACL,SAAS;AAAA,oBACT,MAAM;AAAA,kBAAA;AAAA,gBACR;AAAA,cACF;AAAA,YACF;AAAA,YAEF,OAAO;AAAA,YACP,QAAQ;AAAA,UAAA;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAAA,IAEF,OAAO,CAAA;AAAA,EAAC;AAEZ,GAMaC,KAAkC;AAAA,EAC7C,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,aAAa;AAAA,EACb,UAAU;AAAA,EACV,WAAW;AAAA,EACX,MAAM,CAAC,YAAY,OAAO,kBAAkB,MAAM;AAAA,EAClD,UAAU;AAAA,IACR,OAAO;AAAA,MACL;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU,EAAE,GAAG,KAAK,GAAG,IAAA;AAAA,QACvB,MAAM;AAAA,UACJ,eAAe;AAAA,UACf,QAAQ;AAAA,YACN,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAmBN,OAAO;AAAA,UAAA;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,IAEF,OAAO,CAAA;AAAA,EAAC;AAEZ,GAEaC,KAAsC;AAAA,EACjD,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,aAAa;AAAA,EACb,UAAU;AAAA,EACV,WAAW;AAAA,EACX,MAAM,CAAC,gBAAgB,iBAAiB,UAAU,WAAW;AAAA,EAC7D,UAAU;AAAA,IACR,OAAO;AAAA,MACL;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU,EAAE,GAAG,KAAK,GAAG,IAAA;AAAA,QACvB,MAAM;AAAA,UACJ,eAAe;AAAA,UACf,QAAQ;AAAA,YACN,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAmCN,OAAO;AAAA,UAAA;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,IAEF,OAAO,CAAA;AAAA,EAAC;AAEZ,GAEaC,KAA+B;AAAA,EAC1C,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,aAAa;AAAA,EACb,UAAU;AAAA,EACV,WAAW;AAAA,EACX,MAAM,CAAC,OAAO,aAAa,YAAY,aAAa;AAAA,EACpD,UAAU;AAAA,IACR,OAAO;AAAA,MACL;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU,EAAE,GAAG,KAAK,GAAG,IAAA;AAAA,QACvB,MAAM;AAAA,UACJ,eAAe;AAAA,UACf,QAAQ;AAAA,YACN,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAoBN,OAAO;AAAA,UAAA;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,IAEF,OAAO,CAAA;AAAA,EAAC;AAEZ,GAMaC,KAA6B;AAAA,EACxC,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,aAAa;AAAA,EACb,UAAU;AAAA,EACV,WAAW;AAAA,EACX,MAAM,CAAC,MAAM,WAAW,QAAQ,KAAK;AAAA,EACrC,UAAU;AAAA,IACR,OAAO;AAAA,MACL;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU,EAAE,GAAG,KAAK,GAAG,IAAA;AAAA,QACvB,MAAM;AAAA,UACJ,eAAe;AAAA,UACf,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,MAAM;AAAA,YACN,OAAO;AAAA,YACP,sBAAsB;AAAA,UAAA;AAAA,QACxB;AAAA,MACF;AAAA,IACF;AAAA,IAEF,OAAO,CAAA;AAAA,EAAC;AAEZ,GAEaC,KAA0B;AAAA,EACrC,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,aAAa;AAAA,EACb,UAAU;AAAA,EACV,WAAW;AAAA,EACX,MAAM,CAAC,MAAM,QAAQ,WAAW,OAAO;AAAA,EACvC,UAAU;AAAA,IACR,OAAO;AAAA,MACL;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU,EAAE,GAAG,KAAK,GAAG,IAAA;AAAA,QACvB,MAAM;AAAA,UACJ,eAAe;AAAA,UACf,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,MAAM;AAAA,YACN,OAAO;AAAA,YACP,sBAAsB;AAAA,UAAA;AAAA,QACxB;AAAA,MACF;AAAA,IACF;AAAA,IAEF,OAAO,CAAA;AAAA,EAAC;AAEZ,GAMaC,KAAsC;AAAA,EACjD,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,aAAa;AAAA,EACb,UAAU;AAAA,EACV,WAAW;AAAA,EACX,MAAM,CAAC,SAAS,aAAa,WAAW,UAAU;AAAA,EAClD,UAAU;AAAA,IACR,OAAO;AAAA,MACL;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU,EAAE,GAAG,KAAK,GAAG,IAAA;AAAA,QACvB,MAAM;AAAA,UACJ,eAAe;AAAA,UACf,QAAQ;AAAA,YACN,OAAO;AAAA,cACL,MAAM;AAAA,cACN,MAAM;AAAA,gBACJ,QAAQ,CAAC,OAAO,OAAO,OAAO,OAAO,KAAK;AAAA,gBAC1C,UAAU;AAAA,kBACR;AAAA,oBACE,OAAO;AAAA,oBACP,MAAM,CAAC,IAAI,IAAI,IAAI,IAAI,EAAE;AAAA,oBACzB,iBAAiB;AAAA,kBAAA;AAAA,gBACnB;AAAA,cACF;AAAA,YACF;AAAA,YAEF,OAAO;AAAA,YACP,QAAQ;AAAA,UAAA;AAAA,QACV;AAAA,MACF;AAAA,MAEF;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU,EAAE,GAAG,KAAK,GAAG,IAAA;AAAA,QACvB,MAAM;AAAA,UACJ,WAAW;AAAA,UACX,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,UAAU;AAAA,YACV,UAAU;AAAA,YACV,OAAO;AAAA,YACP,SAAS;AAAA,UAAA;AAAA,QACX;AAAA,MACF;AAAA,MAEF;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU,EAAE,GAAG,KAAK,GAAG,IAAA;AAAA,QACvB,MAAM;AAAA,UACJ,WAAW;AAAA,UACX,QAAQ;AAAA,YACN,QAAQ;AAAA,UAAA;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAAA,IAEF,OAAO;AAAA,MACL,EAAE,IAAI,MAAM,QAAQ,SAAS,QAAQ,cAAA;AAAA,MACrC,EAAE,IAAI,MAAM,QAAQ,eAAe,QAAQ,cAAA;AAAA,IAAc;AAAA,EAC3D;AAEJ,GAEaC,KAAiC;AAAA,EAC5C,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,aAAa;AAAA,EACb,UAAU;AAAA,EACV,WAAW;AAAA,EACX,MAAM,CAAC,WAAW,QAAQ,YAAY,UAAU;AAAA,EAChD,UAAU;AAAA,IACR,OAAO;AAAA,MACL;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU,EAAE,GAAG,KAAK,GAAG,IAAA;AAAA,QACvB,MAAM;AAAA,UACJ,eAAe;AAAA,UACf,QAAQ;AAAA,YACN,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAMN,OAAO;AAAA,UAAA;AAAA,QACT;AAAA,MACF;AAAA,MAEF;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU,EAAE,GAAG,KAAK,GAAG,IAAA;AAAA,QACvB,MAAM;AAAA,UACJ,WAAW;AAAA,UACX,QAAQ;AAAA,YACN,IAAI;AAAA,YACJ,SAAS;AAAA,UAAA;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAAA,IAEF,OAAO,CAAC,EAAE,IAAI,MAAM,QAAQ,SAAS,QAAQ,cAAA,CAAe;AAAA,EAAA;AAEhE,GASaC,IAA+B;AAAA;AAAA,EAE1CT;AAAA,EACAC;AAAA;AAAA,EAEAC;AAAA,EACAC;AAAA,EACAC;AAAA;AAAA,EAEAC;AAAA,EACAC;AAAA;AAAA,EAEAC;AAAA,EACAC;AACF;AAKO,SAASE,KAA0B;AACxC,QAAMC,IAAa,IAAI,IAAIF,EAAU,IAAI,CAACpJ,MAAMA,EAAE,QAAQ,CAAC;AAC3D,SAAO,MAAM,KAAKsJ,CAAU,EAAE,KAAA;AAChC;AAKO,SAASC,GAAuBtJ,GAAqC;AAC1E,SAAOmJ,EAAU,OAAO,CAACpJ,MAAMA,EAAE,aAAaC,CAAQ;AACxD;AAKO,SAASuJ,GAAgBtV,GAAyC;AACvE,SAAOkV,EAAU,KAAK,CAACpJ,MAAMA,EAAE,OAAO9L,CAAE;AAC1C;AAKO,SAASuV,GAAgBC,GAAkC;AAChE,QAAMC,IAAID,EAAM,YAAA;AAChB,SAAON,EAAU;AAAA,IACf,CAAC,MAAA;;AACC,eAAE,KAAK,YAAA,EAAc,SAASO,CAAC,KAC/B,EAAE,YAAY,cAAc,SAASA,CAAC,KACtC,EAAE,SAAS,YAAA,EAAc,SAASA,CAAC,KACnC,EAAE,UAAU,cAAc,SAASA,CAAC,OACpCrZ,IAAA,EAAE,SAAF,gBAAAA,EAAQ,KAAK,CAACsZ,MAAQA,EAAI,cAAc,SAASD,CAAC;AAAA;AAAA,EAAC;AAEzD;ACjfO,SAASE,GAAgB,EAAE,UAAAnM,KAAkC;AAClE,QAAM,CAACoM,GAAkBC,CAAmB,IAAIlM,EAAwB,IAAI,GACtE,CAACmM,GAAaC,CAAc,IAAIpM,EAAS,EAAE,GAE3CyL,IAAaY,GAAQ,MAAMb,GAAA,GAAiB,CAAA,CAAE,GAE9Cc,IAAoBD,GAAQ,MAAM;AACtC,QAAIpZ,IAASsY;AAQb,QALIU,MACFhZ,IAASA,EAAO,OAAO,CAACkP,MAAMA,EAAE,aAAa8J,CAAgB,IAI3DE,GAAa;AACf,YAAML,IAAIK,EAAY,YAAA;AACtB,MAAAlZ,IAASA,EAAO;AAAA,QACd,CAACkP,MAAA;;AACC,iBAAAA,EAAE,KAAK,cAAc,SAAS2J,CAAC,KAC/B3J,EAAE,YAAY,YAAA,EAAc,SAAS2J,CAAC,KACtC3J,EAAE,UAAU,YAAA,EAAc,SAAS2J,CAAC,OACpCrZ,IAAA0P,EAAE,SAAF,gBAAA1P,EAAQ,KAAK,CAACsZ,MAAQA,EAAI,YAAA,EAAc,SAASD,CAAC;AAAA;AAAA,MAAC;AAAA,IAEzD;AAEA,WAAO7Y;AAAA,EACT,GAAG,CAACgZ,GAAkBE,CAAW,CAAC;AAElC,SACE,gBAAAvP,EAAC,OAAA,EAAI,WAAU,OACb,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,QACb,UAAA;AAAA,MAAA,gBAAAR,EAAC,MAAA,EAAG,WAAU,yDAAwD,UAAA,aAAS;AAAA,MAC/E,gBAAAA,EAAC,KAAA,EAAE,WAAU,oCAAmC,UAAA,kFAAA,CAEhD;AAAA,IAAA,GACF;AAAA,IAGA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,6BACb,UAAA;AAAA,MAAA,gBAAAR;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,aAAY;AAAA,UACZ,OAAO+P;AAAA,UACP,UAAU,CAAC/Y,MAAMgZ,EAAehZ,EAAE,OAAO,KAAK;AAAA,UAC9C,WAAU;AAAA,QAAA;AAAA,MAAA;AAAA,MAGZ,gBAAAwJ,EAAC,OAAA,EAAI,WAAU,wBACb,UAAA;AAAA,QAAA,gBAAAR;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS,MAAM8P,EAAoB,IAAI;AAAA,YACvC,WAAW,kEACTD,MAAqB,OACjB,2BACA,wGACN;AAAA,YACD,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAGAR,EAAW,IAAI,CAACrJ,MACf,gBAAAhG;AAAA,UAAC;AAAA,UAAA;AAAA,YAEC,SAAS,MAAM8P,EAAoB9J,CAAQ;AAAA,YAC3C,WAAW,kEACT6J,MAAqB7J,IACjB,2BACA,wGACN;AAAA,YAEC,UAAAA;AAAA,UAAA;AAAA,UARIA;AAAA,QAAA,CAUR;AAAA,MAAA,EAAA,CACH;AAAA,IAAA,GACF;AAAA,IAGCkK,EAAkB,WAAW,IAC5B,gBAAAlQ,EAAC,OAAA,EAAI,WAAU,sDAAqD,UAAA,6CAAA,CAEpE,IAEA,gBAAAA,EAAC,SAAI,WAAU,wDACZ,UAAAkQ,EAAkB,IAAI,CAACjU,MACtB,gBAAA+D;AAAA,MAACmQ;AAAA,MAAA;AAAA,QAEC,UAAAlU;AAAA,QACA,UAAU,MAAMwH,EAASxH,EAAS,EAAE;AAAA,MAAA;AAAA,MAF/BA,EAAS;AAAA,IAAA,CAIjB,EAAA,CACH;AAAA,EAAA,GAEJ;AAEJ;AAOA,SAASkU,GAAa,EAAE,UAAAlU,GAAU,UAAAwH,KAA+B;AAC/D,QAAM2M,IAAYnU,EAAS,SAAS,MAAM,QACpCoU,IAAYpU,EAAS,SAAS,MAAM,QAGpCqU,IAA0C;AAAA,IAC9C,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,IAAI;AAAA,IACJ,IAAI;AAAA,EAAA;AAGN,SACE,gBAAA9P,EAAC,OAAA,EAAI,WAAU,sIAEb,UAAA;AAAA,IAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,kFACZ,UAAA/D,EAAS,UACR,gBAAA+D;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAK/D,EAAS,QAAQ;AAAA,QACtB,KAAKA,EAAS;AAAA,QACd,WAAU;AAAA,MAAA;AAAA,IAAA,IAGZ,gBAAAuE,EAAC,OAAA,EAAI,WAAU,gDACb,UAAA;AAAA,MAAA,gBAAAR;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UACV,MAAK;AAAA,UACL,QAAO;AAAA,UACP,SAAQ;AAAA,UAER,UAAA,gBAAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,eAAc;AAAA,cACd,gBAAe;AAAA,cACf,aAAa;AAAA,cACb,GAAE;AAAA,YAAA;AAAA,UAAA;AAAA,QACJ;AAAA,MAAA;AAAA,MAEF,gBAAAA,EAAC,QAAA,EAAK,WAAU,WAAU,UAAA,aAAA,CAAU;AAAA,IAAA,EAAA,CACtC,EAAA,CAEJ;AAAA,IAGA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,OACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,yCACb,UAAA;AAAA,QAAA,gBAAAR,EAAC,MAAA,EAAG,WAAU,uDAAuD,UAAA/D,EAAS,MAAK;AAAA,QACnF,gBAAA+D;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAW,2CACTsQ,EAAgBrU,EAAS,SAAS,KAClC,+DACF;AAAA,YAEC,UAAAA,EAAS;AAAA,UAAA;AAAA,QAAA;AAAA,MACZ,GACF;AAAA,MAEA,gBAAA+D,EAAC,KAAA,EAAE,WAAU,iDAAiD,YAAS,aAAY;AAAA,MAGnF,gBAAAQ,EAAC,OAAA,EAAI,WAAU,yEACb,UAAA;AAAA,QAAA,gBAAAA,EAAC,QAAA,EAAK,WAAU,2BACd,UAAA;AAAA,UAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,WAAU,MAAK,QAAO,QAAO,gBAAe,SAAQ,aACjE,UAAA,gBAAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,eAAc;AAAA,cACd,gBAAe;AAAA,cACf,aAAa;AAAA,cACb,GAAE;AAAA,YAAA;AAAA,UAAA,GAEN;AAAA,UACCoQ;AAAA,UAAU;AAAA,UAAMA,MAAc,IAAI,MAAM;AAAA,QAAA,GAC3C;AAAA,QACCC,IAAY,KACX,gBAAA7P,EAAC,QAAA,EAAK,WAAU,2BACd,UAAA;AAAA,UAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,WAAU,MAAK,QAAO,QAAO,gBAAe,SAAQ,aACjE,UAAA,gBAAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,eAAc;AAAA,cACd,gBAAe;AAAA,cACf,aAAa;AAAA,cACb,GAAE;AAAA,YAAA;AAAA,UAAA,GAEN;AAAA,UACCqQ;AAAA,UAAU;AAAA,UAAMA,MAAc,IAAI,MAAM;AAAA,QAAA,EAAA,CAC3C;AAAA,MAAA,GAEJ;AAAA,MAGCpU,EAAS,QAAQA,EAAS,KAAK,SAAS,uBACtC,OAAA,EAAI,WAAU,6BACZ,UAAAA,EAAS,KAAK,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC0T,MAC9B,gBAAA3P;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,WAAU;AAAA,UAET,UAAA2P;AAAA,QAAA;AAAA,QAHIA;AAAA,MAAA,CAKR,GACH;AAAA,MAIF,gBAAA3P;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,SAASyD;AAAA,UACT,WAAU;AAAA,UACX,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAED,EAAA,CACF;AAAA,EAAA,GACF;AAEJ;AC9MA,SAAS8M,GAAa;AAAA,EACpB,UAAAlS;AAAA,EACA,UAAAmS;AAAA,EACA,QAAAC;AAAA,EACA,UAAAC;AAAA,EACA,UAAAC;AAAA,EACA,aAAAC;AACF,GAAsB;AACpB,QAAM,CAACC,GAAWC,CAAY,IAAIlN,EAAS,EAAK,GAC1C,CAACmN,GAAUC,CAAW,IAAIpN,EAASvF,EAAS,IAAI,GAChD,CAAC4S,GAAUC,CAAW,IAAItN,EAAS,EAAK,GAExCuN,IAAe,MAAM;AACzB,IAAIJ,EAAS,KAAA,KAAUA,MAAa1S,EAAS,QAC3CsS,EAASI,EAAS,MAAM,GAE1BD,EAAa,EAAK;AAAA,EACpB,GAEMrC,IAAa,CAAC3S,MAAsB;AACxC,UAAMsV,IAAO,IAAI,KAAKtV,CAAS,GAEzBuV,yBADU,KAAA,GACG,QAAA,IAAYD,EAAK,QAAA,GAC9BE,IAAW,KAAK,MAAMD,IAAS,GAAK,GACpCE,IAAY,KAAK,MAAMF,IAAS,IAAO,GACvCG,IAAW,KAAK,MAAMH,IAAS,KAAQ;AAE7C,WAAIC,IAAW,IAAU,aACrBA,IAAW,KAAW,GAAGA,CAAQ,UACjCC,IAAY,KAAW,GAAGA,CAAS,UACnCC,IAAW,IAAU,GAAGA,CAAQ,UAC7BJ,EAAK,mBAAA;AAAA,EACd;AAEA,SACE,gBAAA5Q;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,0DACTgQ,IACI,wEACA,iHACN;AAAA,MAEA,UAAA;AAAA,QAAA,gBAAAhQ,EAAC,OAAA,EAAI,WAAU,0CACb,UAAA;AAAA,UAAA,gBAAAA,EAAC,UAAA,EAAO,SAASiQ,GAAQ,WAAU,4BAChC,UAAA;AAAA,YAAAI,IACC,gBAAA7Q;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,OAAO+Q;AAAA,gBACP,UAAU,CAAC/Z,MAAMga,EAAYha,EAAE,OAAO,KAAK;AAAA,gBAC3C,QAAQma;AAAA,gBACR,WAAW,CAACna,MAAM;AAChB,kBAAIA,EAAE,QAAQ,WAASma,EAAA,GACnBna,EAAE,QAAQ,aACZga,EAAY3S,EAAS,IAAI,GACzByS,EAAa,EAAK;AAAA,gBAEtB;AAAA,gBACA,WAAU;AAAA,gBACV,WAAS;AAAA,gBACT,SAAS,CAAC9Z,MAAMA,EAAE,gBAAA;AAAA,cAAgB;AAAA,YAAA,IAGpC,gBAAAgJ,EAAC,QAAA,EAAK,WAAU,uEACb,YAAS,MACZ;AAAA,YAEF,gBAAAQ,EAAC,QAAA,EAAK,WAAU,yDACb,UAAA;AAAA,cAAAnC,EAAS,MAAM;AAAA,cAAO;AAAA,cAAkBoQ,EAAWpQ,EAAS,SAAS;AAAA,YAAA,EAAA,CACxE;AAAA,UAAA,GACF;AAAA,UAEA,gBAAAmC,EAAC,OAAA,EAAI,WAAU,YACb,UAAA;AAAA,YAAA,gBAAAR;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,SAAS,CAAChJ,MAAM;AACd,kBAAAA,EAAE,gBAAA,GACFka,EAAY,CAACD,CAAQ;AAAA,gBACvB;AAAA,gBACA,WAAU;AAAA,gBAEV,UAAA,gBAAAjR,EAAC,OAAA,EAAI,WAAU,WAAU,MAAK,gBAAe,SAAQ,aACnD,UAAA,gBAAAA,EAAC,QAAA,EAAK,GAAE,+FAAA,CAA+F,EAAA,CACzG;AAAA,cAAA;AAAA,YAAA;AAAA,YAGDiR,KACC,gBAAAzQ,EAAAoB,GAAA,EACE,UAAA;AAAA,cAAA,gBAAA5B,EAAC,SAAI,WAAU,sBAAqB,SAAS,MAAMkR,EAAY,EAAK,GAAG;AAAA,cACvE,gBAAA1Q,EAAC,OAAA,EAAI,WAAU,4IACb,UAAA;AAAA,gBAAA,gBAAAR;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,SAAS,CAAChJ,MAAM;AACd,sBAAAA,EAAE,gBAAA,GACF8Z,EAAa,EAAI,GACjBI,EAAY,EAAK;AAAA,oBACnB;AAAA,oBACA,WAAU;AAAA,oBACX,UAAA;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAGD,gBAAAlR;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,SAAS,CAAChJ,MAAM;AACd,sBAAAA,EAAE,gBAAA,GACF4Z,EAAA,GACAM,EAAY,EAAK;AAAA,oBACnB;AAAA,oBACA,WAAU;AAAA,oBACX,UAAA;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAGD,gBAAAlR;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,SAAS,CAAChJ,MAAM;AACd,sBAAAA,EAAE,gBAAA,GACE,OAAO,QAAQ,uBAAuB,KACxC0Z,EAAA,GAEFQ,EAAY,EAAK;AAAA,oBACnB;AAAA,oBACA,WAAU;AAAA,oBACX,UAAA;AAAA,kBAAA;AAAA,gBAAA;AAAA,cAED,EAAA,CACF;AAAA,YAAA,EAAA,CACF;AAAA,UAAA,EAAA,CAEJ;AAAA,QAAA,GACF;AAAA,QAECV,KAAY,gBAAAxQ,EAAC,QAAA,EAAK,WAAU,0DAAA,CAA0D;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAG7F;AAEO,SAASyR,KAAkB;AAChC,QAAMC,IAAc1V,EAAiB,CAAC8D,MAAMA,EAAE,WAAW,GACnD+L,IAAgB7P,EAAiB,CAAC8D,MAAMA,EAAE,aAAa,GACvD/B,IAAiB/B,EAAiB,CAAC8D,MAAMA,EAAE,cAAc,GACzDjC,IAAmB7B,EAAiB,CAAC8D,MAAMA,EAAE,gBAAgB,GAC7D6R,IAAe3V,EAAiB,CAAC8D,MAAMA,EAAE,YAAY,GACrD8R,IAAiB5V,EAAiB,CAAC8D,MAAMA,EAAE,cAAc,GACzD+R,IAAiB7V,EAAiB,CAAC8D,MAAMA,EAAE,cAAc,GACzDgS,IAAoB9V,EAAiB,CAAC8D,MAAMA,EAAE,iBAAiB,GAC/D1B,IAAcpC,EAAiB,CAAC8D,MAAMA,EAAE,WAAW;AAEzD,MAAI,CAAC4R,EAAa,QAAO;AAGzB,QAAMK,IAAkB,CAAC,GAAGhU,CAAc,EAAE,KAAK,CAACiU,GAAGC,MAAMA,EAAE,YAAYD,EAAE,SAAS;AAEpF,SACE,gBAAAxR,EAAAoB,GAAA,EAEE,UAAA;AAAA,IAAA,gBAAA5B,EAAC,OAAA,EAAI,WAAU,mDAAkD,SAAS6L,GAAe;AAAA,IAGzF,gBAAArL,EAAC,OAAA,EAAI,WAAU,2IAEb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,6FACb,UAAA;AAAA,QAAA,gBAAAR,EAAC,MAAA,EAAG,WAAU,0DAAyD,UAAA,gBAAY;AAAA,QACnF,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS6L;AAAA,YACT,WAAU;AAAA,YAEV,UAAA,gBAAA7L,EAAC,SAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAC9D,UAAA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAc;AAAA,gBACd,gBAAe;AAAA,gBACf,aAAa;AAAA,gBACb,GAAE;AAAA,cAAA;AAAA,YAAA,EACJ,CACF;AAAA,UAAA;AAAA,QAAA;AAAA,MACF,GACF;AAAA,MAGA,gBAAAA,EAAC,OAAA,EAAI,WAAU,qDACb,UAAA,gBAAAQ;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,SAAS,MAAM;AACb,YAAApC,EAAA,GACAyN,EAAA,GACA,OAAO,cAAc,IAAI,OAAO,YAAY,sBAAsB,CAAC;AAAA,UACrE;AAAA,UACA,WAAU;AAAA,UAEV,UAAA;AAAA,YAAA,gBAAA7L,EAAC,OAAA,EAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAC9D,UAAA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAc;AAAA,gBACd,gBAAe;AAAA,gBACf,aAAa;AAAA,gBACb,GAAE;AAAA,cAAA;AAAA,YAAA,GAEN;AAAA,YAAM;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA,GAGV;AAAA,MAGA,gBAAAA,EAAC,OAAA,EAAI,WAAU,8BACZ,UAAA+R,EAAgB,WAAW,IAC1B,gBAAAvR,EAAC,OAAA,EAAI,WAAU,oBACb,UAAA;AAAA,QAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,qGACb,UAAA,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,QAAO;AAAA,YAEP,UAAA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAc;AAAA,gBACd,gBAAe;AAAA,gBACf,aAAa;AAAA,gBACb,GAAE;AAAA,cAAA;AAAA,YAAA;AAAA,UACJ;AAAA,QAAA,GAEJ;AAAA,QACA,gBAAAA,EAAC,KAAA,EAAE,WAAU,4CAA2C,UAAA,0BAAsB;AAAA,QAC9E,gBAAAA,EAAC,KAAA,EAAE,WAAU,iDAAgD,UAAA,8CAAA,CAE7D;AAAA,MAAA,EAAA,CACF,sBAEC,OAAA,EAAI,WAAU,aACZ,UAAA+R,EAAgB,IAAI,CAAC1T,MACpB,gBAAA2B;AAAA,QAACuQ;AAAA,QAAA;AAAA,UAEC,UAAAlS;AAAA,UACA,UAAUA,EAAS,OAAOR;AAAA,UAC1B,QAAQ,MAAM;AACZ,YAAA8T,EAAatT,EAAS,EAAE,GACxBwN,EAAA;AAAA,UACF;AAAA,UACA,UAAU,MAAM+F,EAAevT,EAAS,EAAE;AAAA,UAC1C,UAAU,CAACjI,MAASyb,EAAexT,EAAS,IAAIjI,CAAI;AAAA,UACpD,aAAa,MAAM0b,EAAkBzT,EAAS,EAAE;AAAA,QAAA;AAAA,QAT3CA,EAAS;AAAA,MAAA,CAWjB,GACH,EAAA,CAEJ;AAAA,MAGA,gBAAAmC,EAAC,OAAA,EAAI,WAAU,oGACZ,UAAA;AAAA,QAAAzC,EAAe;AAAA,QAAO;AAAA,QAAUA,EAAe,WAAW,IAAI,MAAM;AAAA,QAAG;AAAA,MAAA,EAAA,CAC1E;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,GACF;AAEJ;AC7PA,MAAMmU,KAAkB;AAAA,EACtB;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,SAAS;AAAA,EAAA;AAAA,EAEX;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,SAAS;AAAA,EAAA;AAAA,EAEX;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,SAAS;AAAA,EAAA;AAAA,EAEX;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,SAAS;AAAA,EAAA;AAAA,EAEX;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,SAAS;AAAA,EAAA;AAEb,GAEMC,KAAkB;AAAA,EACtB;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,SAAS;AAAA,EAAA;AAAA,EAEX;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,SAAS;AAAA,EAAA;AAEb;AAEA,SAASC,GAAiB,EAAE,UAAAjX,KAA4D;AACtF,QAAME,IAAKJ,EAAiB,CAAC6E,MAAMA,EAAE,EAAE,GACjCuS,IAAgBpX,EAAiB,CAAC6E,MAAMA,EAAE,aAAa,GAEvD1I,IAASiE,EAAGF,EAAS,EAAE,GACvBmX,KAAYlb,KAAA,gBAAAA,EAAQ,YAAW,IAC/Bmb,KAAUnb,KAAA,gBAAAA,EAAgC,WAAU,IAEpD,CAACob,GAAUC,CAAW,IAAI7O,EAAS2O,CAAM,GACzC,CAACG,GAASC,CAAU,IAAI/O,EAAS,EAAK,GAEtCgP,IAAe,MAAM;AACzB,IAAAP,EAAclX,EAAS,IAAI;AAAA,MACzB,QAAQqX;AAAA,MACR,SAAS,CAACF;AAAA,IAAA,CACX;AAAA,EACH,GAEMO,IAAkB,CAAClS,MAAkB;AACzC,IAAA8R,EAAY9R,CAAK,GACjB0R,EAAclX,EAAS,IAAI;AAAA,MACzB,QAAQwF;AAAA,MACR,SAAS2R;AAAA,IAAA,CACV;AAAA,EACH;AAEA,SACE,gBAAA9R,EAAC,OAAA,EAAI,WAAU,qFACb,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,QAAA,gBAAAR,EAAC,QAAA,EAAK,WAAU,6CAA6C,UAAA7E,EAAS,MAAK;AAAA,QAC3E,gBAAA6E;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAM7E,EAAS;AAAA,YACf,QAAO;AAAA,YACP,KAAI;AAAA,YACJ,WAAU;AAAA,YACX,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAED,GACF;AAAA,MACA,gBAAA6E,EAAC,KAAA,EAAE,WAAU,mDAAmD,YAAS,aAAY;AAAA,wBACpF,OAAA,EAAI,WAAU,gCACb,UAAA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,mBACb,UAAA;AAAA,QAAA,gBAAAR;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAM0S,IAAU,SAAS;AAAA,YACzB,OAAOF;AAAA,YACP,UAAU,CAACxb,MAAM6b,EAAgB7b,EAAE,OAAO,KAAK;AAAA,YAC/C,aAAamE,EAAS;AAAA,YACtB,WAAU;AAAA,UAAA;AAAA,QAAA;AAAA,QAEZ,gBAAA6E;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS,MAAM2S,EAAW,CAACD,CAAO;AAAA,YAClC,WAAU;AAAA,YAEV,UAAA,gBAAA1S,EAAC,OAAA,EAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAC7D,UAAA0S,IACC,gBAAA1S;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAc;AAAA,gBACd,gBAAe;AAAA,gBACf,aAAa;AAAA,gBACb,GAAE;AAAA,cAAA;AAAA,YAAA,IAGJ,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAc;AAAA,gBACd,gBAAe;AAAA,gBACf,aAAa;AAAA,gBACb,GAAE;AAAA,cAAA;AAAA,YAAA,EACJ,CAEJ;AAAA,UAAA;AAAA,QAAA;AAAA,MACF,EAAA,CACF,EAAA,CACF;AAAA,IAAA,GACF;AAAA,IACA,gBAAAA,EAAC,OAAA,EAAI,WAAU,qBACb,UAAA,gBAAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,SAAS4S;AAAA,QACT,WAAW,6EACTN,IAAY,gBAAgB,8BAC9B;AAAA,QAEA,UAAA,gBAAAtS;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAW,6EACTsS,IAAY,kBAAkB,eAChC;AAAA,UAAA;AAAA,QAAA;AAAA,MACF;AAAA,IAAA,EACF,CACF;AAAA,EAAA,GACF;AAEJ;AAEA,SAASQ,GAAiB,EAAE,UAAA3X,KAA4D;AACtF,QAAME,IAAKJ,EAAiB,CAAC6E,MAAMA,EAAE,EAAE,GACjCuS,IAAgBpX,EAAiB,CAAC6E,MAAMA,EAAE,aAAa,GAEvD1I,IAASiE,EAAGF,EAAS,EAAE,GACvBmX,KAAYlb,KAAA,gBAAAA,EAAQ,YAAW,IAC/B2b,KAAW3b,KAAA,gBAAAA,EAAiC,YAAW+D,EAAS,YAEhE,CAAC6X,GAAUC,CAAW,IAAIrP,EAASmP,CAAO,GAE1CH,IAAe,MAAM;AACzB,IAAAP,EAAclX,EAAS,IAAI;AAAA,MACzB,SAAS6X;AAAA,MACT,SAAS,CAACV;AAAA,IAAA,CACX;AAAA,EACH,GAEMY,IAAkB,CAACvS,MAAkB;AACzC,IAAAsS,EAAYtS,CAAK,GACjB0R,EAAclX,EAAS,IAAI;AAAA,MACzB,SAASwF;AAAA,MACT,SAAS2R;AAAA,IAAA,CACV;AAAA,EACH;AAEA,SACE,gBAAA9R,EAAC,OAAA,EAAI,WAAU,qFACb,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,QAAA,gBAAAR,EAAC,QAAA,EAAK,WAAU,6CAA6C,UAAA7E,EAAS,MAAK;AAAA,QAC3E,gBAAA6E;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAM7E,EAAS;AAAA,YACf,QAAO;AAAA,YACP,KAAI;AAAA,YACJ,WAAU;AAAA,YACX,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAGD,gBAAA6E,EAAC,QAAA,EAAK,WAAU,sGAAqG,UAAA,QAAA,CAErH;AAAA,MAAA,GACF;AAAA,MACA,gBAAAA,EAAC,KAAA,EAAE,WAAU,mDAAmD,YAAS,aAAY;AAAA,MACrF,gBAAAA,EAAC,OAAA,EAAI,WAAU,QACb,UAAA,gBAAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,OAAOgT;AAAA,UACP,UAAU,CAAChc,MAAMkc,EAAgBlc,EAAE,OAAO,KAAK;AAAA,UAC/C,aAAamE,EAAS;AAAA,UACtB,WAAU;AAAA,QAAA;AAAA,MAAA,EACZ,CACF;AAAA,IAAA,GACF;AAAA,IACA,gBAAA6E,EAAC,OAAA,EAAI,WAAU,qBACb,UAAA,gBAAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,SAAS4S;AAAA,QACT,WAAW,6EACTN,IAAY,gBAAgB,8BAC9B;AAAA,QAEA,UAAA,gBAAAtS;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAW,6EACTsS,IAAY,kBAAkB,eAChC;AAAA,UAAA;AAAA,QAAA;AAAA,MACF;AAAA,IAAA,EACF,CACF;AAAA,EAAA,GACF;AAEJ;AAEO,SAASa,KAAa;AAC3B,QAAMC,IAAenY,EAAiB,CAAC6E,MAAMA,EAAE,YAAY,GACrDuT,IAAgBpY,EAAiB,CAAC6E,MAAMA,EAAE,aAAa;AAE7D,SAAKsT,sBAGF,OAAA,EAAI,WAAU,8EACb,UAAA,gBAAA5S,EAAC,OAAA,EAAI,WAAU,kGACb,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,6FACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EACC,UAAA;AAAA,QAAA,gBAAAR,EAAC,MAAA,EAAG,WAAU,uDAAsD,UAAA,wBAEpE;AAAA,QACA,gBAAAA,EAAC,KAAA,EAAE,WAAU,mDAAkD,UAAA,6DAAA,CAE/D;AAAA,MAAA,GACF;AAAA,MACA,gBAAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,SAASqT;AAAA,UACT,WAAU;AAAA,UAEV,UAAA,gBAAArT,EAAC,SAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAC9D,UAAA,gBAAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,eAAc;AAAA,cACd,gBAAe;AAAA,cACf,aAAa;AAAA,cACb,GAAE;AAAA,YAAA;AAAA,UAAA,EACJ,CACF;AAAA,QAAA;AAAA,MAAA;AAAA,IACF,GACF;AAAA,IAEA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,wCAEb,UAAA;AAAA,MAAA,gBAAAA,EAAC,WAAA,EACC,UAAA;AAAA,QAAA,gBAAAR,EAAC,MAAA,EAAG,WAAU,6DAA4D,UAAA,mBAE1E;AAAA,QACA,gBAAAA,EAAC,OAAA,EAAI,WAAU,aACZ,aAAgB,IAAI,CAAC7E,MACpB,gBAAA6E,EAACoS,IAAA,EAAmC,UAAAjX,EAAA,GAAbA,EAAS,EAAwB,CACzD,EAAA,CACH;AAAA,MAAA,GACF;AAAA,wBAGC,WAAA,EACC,UAAA;AAAA,QAAA,gBAAA6E,EAAC,MAAA,EAAG,WAAU,6DAA4D,UAAA,mBAE1E;AAAA,QACA,gBAAAA,EAAC,OAAA,EAAI,WAAU,aACZ,aAAgB,IAAI,CAAC7E,MACpB,gBAAA6E,EAAC8S,IAAA,EAAmC,UAAA3X,EAAA,GAAbA,EAAS,EAAwB,CACzD,EAAA,CACH;AAAA,MAAA,GACF;AAAA,wBAGC,OAAA,EAAI,WAAU,6FACb,UAAA,gBAAAqF,EAAC,OAAA,EAAI,WAAU,0BACb,UAAA;AAAA,QAAA,gBAAAR;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,QAAO;AAAA,YAEP,UAAA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAc;AAAA,gBACd,gBAAe;AAAA,gBACf,aAAa;AAAA,gBACb,GAAE;AAAA,cAAA;AAAA,YAAA;AAAA,UACJ;AAAA,QAAA;AAAA,0BAED,OAAA,EACC,UAAA;AAAA,UAAA,gBAAAA,EAAC,KAAA,EAAE,WAAU,wDAAuD,UAAA,wBAEpE;AAAA,UACA,gBAAAA,EAAC,KAAA,EAAE,WAAU,iDAAgD,UAAA,gHAAA,CAG7D;AAAA,QAAA,EAAA,CACF;AAAA,MAAA,EAAA,CACF,EAAA,CACF;AAAA,IAAA,GACF;AAAA,IAEA,gBAAAA,EAAC,OAAA,EAAI,WAAU,4EACb,UAAA,gBAAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,SAASqT;AAAA,QACT,WAAU;AAAA,QACX,UAAA;AAAA,MAAA;AAAA,IAAA,EAED,CACF;AAAA,EAAA,EAAA,CACF,EAAA,CACF,IA5FwB;AA8F5B;ACrTO,SAASC,GAAO,EAAE,QAAArJ,GAAQ,SAAAC,GAAS,iBAAAqJ,KAAgC;AACxE,QAAM,CAACC,GAAUC,CAAW,IAAI7P,EAAoC,CAAA,CAAE,GAChE,CAAChN,GAAO8c,CAAQ,IAAI9P,EAAS,EAAE,GAC/B,CAAC0G,GAAWC,CAAY,IAAI3G,EAAS,EAAK,GAC1C,CAACvK,GAAO0K,CAAQ,IAAIH,EAAwB,IAAI,GAChD,CAAC+P,GAAaC,CAAc,IAAIhQ,EAAyB,IAAI,GAC7D,CAACiQ,GAAeC,CAAgB,IAAIlQ,EAAS,EAAE,GAC/CmQ,IAAiB9S,EAAuB,IAAI,GAC5C+S,IAAW/S,EAA4B,IAAI;AAGjD,EAAAiD,EAAU,MAAM;AACd,IAAI+F,KAAU0J,MAAgB,QAC5B7Y,GAAA,EACG,KAAK,CAACmZ,MAAW;AAChB,MAAAL,EAAeK,EAAO,SAAS,GAC/BH,EAAiBG,EAAO,OAAO;AAAA,IACjC,CAAC,EACA,MAAM,MAAM;AACX,MAAAL,EAAe,EAAK,GACpBE,EAAiB,iCAAiC;AAAA,IACpD,CAAC;AAAA,EAEP,GAAG,CAAC7J,GAAQ0J,CAAW,CAAC,GAGxBzP,EAAU,MAAM;AACd,IAAI+F,KAAU+J,EAAS,WACrBA,EAAS,QAAQ,MAAA;AAAA,EAErB,GAAG,CAAC/J,CAAM,CAAC,GAGX/F,EAAU,MAAM;;AACd,KAAA7N,IAAA0d,EAAe,YAAf,QAAA1d,EAAwB,eAAe,EAAE,UAAU;EACrD,GAAG,CAACmd,CAAQ,CAAC;AAEb,QAAMU,IAAe/S,EAAY,YAAY;AAC3C,QAAI,CAACvK,EAAM,KAAA,KAAU0T,EAAW;AAEhC,UAAM6J,IAAuC;AAAA,MAC3C,MAAM;AAAA,MACN,SAASvd,EAAM,KAAA;AAAA,MACf,WAAW,KAAK,IAAA;AAAA,IAAI;AAGtB,IAAA6c,EAAY,CAACrP,MAAS,CAAC,GAAGA,GAAM+P,CAAW,CAAC,GAC5CT,EAAS,EAAE,GACXnJ,EAAa,EAAI,GACjBxG,EAAS,IAAI;AAEb,QAAI;AACF,YAAM3K,IAAW,MAAMwB,GAAiB;AAAA,QACtC,QAAQuZ,EAAY;AAAA,QACpB,SAASX;AAAA,MAAA,CACV,GAEKY,IAA4C;AAAA,QAChD,MAAM;AAAA,QACN,SAAShb,EAAS;AAAA,QAClB,UAAUA,EAAS;AAAA,QACnB,WAAW,KAAK,IAAA;AAAA,MAAI;AAGtB,MAAAqa,EAAY,CAACrP,MAAS,CAAC,GAAGA,GAAMgQ,CAAgB,CAAC,GAE7C,CAAChb,EAAS,WAAWA,EAAS,SAChC2K,EAAS3K,EAAS,KAAK;AAAA,IAE3B,SAAS6K,GAAK;AACZ,MAAAF,EAASE,aAAe,QAAQA,EAAI,UAAU,6BAA6B;AAAA,IAC7E,UAAA;AACE,MAAAsG,EAAa,EAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAAC3T,GAAO0T,GAAWkJ,CAAQ,CAAC,GAEzBpG,IAAgB,CAACpW,MAA2B;AAChD,IAAIA,EAAE,QAAQ,WAAW,CAACA,EAAE,aAC1BA,EAAE,eAAA,GACFkd,EAAA;AAAA,EAEJ,GAEMG,IAAc,CAAChW,MAAoC;AACvD,IAAAkV,EAAgBlV,CAAQ,GACxB6L,EAAA;AAAA,EACF,GAEMoK,IAAgB,MAAM;AAC1B,IAAAb,EAAY,CAAA,CAAE,GACd1P,EAAS,IAAI;AAAA,EACf;AAEA,SAAKkG,sBAGF,OAAA,EAAI,WAAU,mEACb,UAAA,gBAAAzJ,EAAC,OAAA,EAAI,WAAU,+FAEb,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,6FACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,QAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,UAAA,gBAAAR;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,QAAO;AAAA,cAEP,UAAA,gBAAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,eAAc;AAAA,kBACd,gBAAe;AAAA,kBACf,aAAa;AAAA,kBACb,GAAE;AAAA,gBAAA;AAAA,cAAA;AAAA,YACJ;AAAA,UAAA;AAAA,UAEF,gBAAAA,EAAC,MAAA,EAAG,WAAU,uDAAsD,UAAA,wBAAA,CAEpE;AAAA,QAAA,GACF;AAAA,QACA,gBAAAA,EAAC,QAAA,EAAK,WAAU,6FAA4F,UAAA,eAAA,CAE5G;AAAA,MAAA,GACF;AAAA,MACA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,QAAAgT,EAAS,SAAS,KACjB,gBAAAxT;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAASsU;AAAA,YACT,WAAU;AAAA,YACV,OAAM;AAAA,YAEN,UAAA,gBAAAtU,EAAC,SAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAC9D,UAAA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAc;AAAA,gBACd,gBAAe;AAAA,gBACf,aAAa;AAAA,gBACb,GAAE;AAAA,cAAA;AAAA,YAAA,EACJ,CACF;AAAA,UAAA;AAAA,QAAA;AAAA,QAGJ,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAASkK;AAAA,YACT,WAAU;AAAA,YAEV,UAAA,gBAAAlK,EAAC,SAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAC9D,UAAA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAc;AAAA,gBACd,gBAAe;AAAA,gBACf,aAAa;AAAA,gBACb,GAAE;AAAA,cAAA;AAAA,YAAA,EACJ,CACF;AAAA,UAAA;AAAA,QAAA;AAAA,MACF,EAAA,CACF;AAAA,IAAA,GACF;AAAA,IAGA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,sCACZ,UAAA;AAAA,MAAAmT,MAAgB,wBACd,OAAA,EAAI,WAAU,iGACb,UAAA,gBAAAnT,EAAC,OAAA,EAAI,WAAU,0BACb,UAAA;AAAA,QAAA,gBAAAR;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,QAAO;AAAA,YAEP,UAAA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAc;AAAA,gBACd,gBAAe;AAAA,gBACf,aAAa;AAAA,gBACb,GAAE;AAAA,cAAA;AAAA,YAAA;AAAA,UACJ;AAAA,QAAA;AAAA,0BAED,OAAA,EACC,UAAA;AAAA,UAAA,gBAAAA,EAAC,KAAA,EAAE,WAAU,kDAAiD,UAAA,+BAE9D;AAAA,UACA,gBAAAA,EAAC,KAAA,EAAE,WAAU,mDAAmD,UAAA6T,GAAc;AAAA,UAC9E,gBAAA7T,EAAC,KAAA,EAAE,WAAU,mDAAkD,UAAA,iEAAA,CAE/D;AAAA,QAAA,EAAA,CACF;AAAA,MAAA,EAAA,CACF,EAAA,CACF;AAAA,MAGDwT,EAAS,WAAW,KAAKG,MAAgB,MACxC,gBAAAnT,EAAC,OAAA,EAAI,WAAU,oBACb,UAAA;AAAA,QAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,uGACb,UAAA,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,QAAO;AAAA,YAEP,UAAA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAc;AAAA,gBACd,gBAAe;AAAA,gBACf,aAAa;AAAA,gBACb,GAAE;AAAA,cAAA;AAAA,YAAA;AAAA,UACJ;AAAA,QAAA,GAEJ;AAAA,QACA,gBAAAA,EAAC,MAAA,EAAG,WAAU,0DAAyD,UAAA,0BAEvE;AAAA,QACA,gBAAAA,EAAC,KAAA,EAAE,WAAU,6DAA4D,UAAA,sFAGzE;AAAA,QACA,gBAAAA,EAAC,OAAA,EAAI,WAAU,kBACZ,UAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA,EACA,IAAI,CAACuU,GAASC,MACd,gBAAAhU;AAAA,UAAC;AAAA,UAAA;AAAA,YAEC,SAAS,MAAMkT,EAASa,CAAO;AAAA,YAC/B,WAAU;AAAA,YACX,UAAA;AAAA,cAAA;AAAA,cACQA;AAAA,cAAQ;AAAA,YAAA;AAAA,UAAA;AAAA,UAJVC;AAAA,QAAA,CAMR,EAAA,CACH;AAAA,MAAA,GACF;AAAA,MAGDhB,EAAS,IAAI,CAACiB,GAAK7G,MAClB,gBAAA5N;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,WAAW,QAAQyU,EAAI,SAAS,SAAS,gBAAgB,eAAe;AAAA,UAExE,UAAA,gBAAAjU;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAW,oCACTiU,EAAI,SAAS,SACT,2BACA,4DACN;AAAA,cAEA,UAAA;AAAA,gBAAA,gBAAAzU,EAAC,KAAA,EAAE,WAAU,+BAA+B,UAAAyU,EAAI,SAAQ;AAAA,gBAGvDA,EAAI,SAAS,eAAeA,EAAI,YAC/B,gBAAAjU,EAAC,OAAA,EAAI,WAAU,2DACb,UAAA;AAAA,kBAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,0CACb,UAAA;AAAA,oBAAA,gBAAAR,EAAC,QAAA,EAAK,WAAU,wDAAuD,UAAA,sBAEvE;AAAA,oBACA,gBAAAA;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACC,SAAS,MAAMqU,EAAYI,EAAI,QAAS;AAAA,wBACxC,WAAU;AAAA,wBACX,UAAA;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBAED,GACF;AAAA,oCACC,OAAA,EAAI,WAAU,iDACb,UAAA,gBAAAjU,EAAC,OAAA,EAAI,WAAU,aACZ,UAAA;AAAA,oBAAAiU,EAAI,SAAS,MAAM,IAAI,CAACvX,GAAMwX,MAC7B,gBAAAlU;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBAEC,WAAU;AAAA,wBAEV,UAAA;AAAA,0BAAA,gBAAAR,EAAC,QAAA,EAAK,WAAU,gEACb,UAAA9C,EAAK,SAAS,MAAM,GAAG,EAAE,IAAA,EAAI,CAChC;AAAA,0BACCA,EAAK,SAAS,gBAAAsD,EAAC,QAAA,EAAK,WAAU,iBAAgB,UAAA;AAAA,4BAAA;AAAA,4BAAEtD,EAAK;AAAA,4BAAM;AAAA,0BAAA,EAAA,CAAC;AAAA,wBAAA;AAAA,sBAAA;AAAA,sBANxDwX;AAAA,oBAAA,CAQR;AAAA,oBACAD,EAAI,SAAS,MAAM,SAAS,KAC3B,gBAAAjU,EAAC,OAAA,EAAI,WAAU,yCACZ,UAAA;AAAA,sBAAAiU,EAAI,SAAS,MAAM;AAAA,sBAAO;AAAA,sBAC1BA,EAAI,SAAS,MAAM,WAAW,IAAI,MAAM;AAAA,oBAAA,EAAA,CAC3C;AAAA,kBAAA,EAAA,CAEJ,EAAA,CACF;AAAA,gBAAA,EAAA,CACF;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QAEJ;AAAA,QAjDK7G;AAAA,MAAA,CAmDR;AAAA,MAEAtD,KACC,gBAAAtK,EAAC,OAAA,EAAI,WAAU,sBACb,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,qDACb,UAAA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,QAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,UAAA,gBAAAR,EAAC,OAAA,EAAI,WAAU,mEAAA,CAAmE;AAAA,UAClF,gBAAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO,EAAE,gBAAgB,OAAA;AAAA,YAAO;AAAA,UAAA;AAAA,UAElC,gBAAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO,EAAE,gBAAgB,OAAA;AAAA,YAAO;AAAA,UAAA;AAAA,QAClC,GACF;AAAA,QACA,gBAAAA,EAAC,QAAA,EAAK,WAAU,4CAA2C,UAAA,yBAAA,CAE3D;AAAA,MAAA,EAAA,CACF,GACF,GACF;AAAA,MAGD3G,KACC,gBAAA2G,EAAC,OAAA,EAAI,WAAU,yFACb,4BAAC,KAAA,EAAE,WAAU,0CAA0C,UAAA3G,EAAA,CAAM,EAAA,CAC/D;AAAA,MAGF,gBAAA2G,EAAC,OAAA,EAAI,KAAK+T,EAAA,CAAgB;AAAA,IAAA,GAC5B;AAAA,IAGA,gBAAAvT,EAAC,OAAA,EAAI,WAAU,qDACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,cACb,UAAA;AAAA,QAAA,gBAAAR;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,KAAKgU;AAAA,YACL,OAAOpd;AAAA,YACP,UAAU,CAACI,MAAM0c,EAAS1c,EAAE,OAAO,KAAK;AAAA,YACxC,WAAWoW;AAAA,YACX,aACEuG,MAAgB,KACZ,gCACA;AAAA,YAEN,UAAUrJ,KAAaqJ,MAAgB;AAAA,YACvC,MAAM;AAAA,YACN,WAAU;AAAA,UAAA;AAAA,QAAA;AAAA,QAEZ,gBAAA3T;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAASkU;AAAA,YACT,UAAU,CAACtd,EAAM,KAAA,KAAU0T,KAAaqJ,MAAgB;AAAA,YACxD,WAAU;AAAA,YAEV,UAAA,gBAAA3T,EAAC,SAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAC9D,UAAA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAc;AAAA,gBACd,gBAAe;AAAA,gBACf,aAAa;AAAA,gBACb,GAAE;AAAA,cAAA;AAAA,YAAA,EACJ,CACF;AAAA,UAAA;AAAA,QAAA;AAAA,MACF,GACF;AAAA,MACA,gBAAAA,EAAC,KAAA,EAAE,WAAU,iDAAgD,UAAA,gDAAA,CAE7D;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,EAAA,CACF,EAAA,CACF,IAtQkB;AAwQtB;ACjWA,SAAS2U,KAAiB;AACxB,QAAM,EAAE,sBAAAC,EAAA,IAAyBC,GAAA,GAC3B/P,IAAU9I,EAAiB,CAAC8D,MAAMA,EAAE,OAAO,GAE3CsB,IAAaD;AAAA,IACjB,CAAC2T,MAAqC;AACpC,MAAAA,EAAM,eAAA;AAEN,YAAMhY,IAAOgY,EAAM,aAAa,QAAQ,kBAAkB;AAC1D,UAAKhY;AAEL,YAAI;AACF,gBAAMF,IAA6B,KAAK,MAAME,CAAI,GAI5CD,IAAW+X,EAAqB;AAAA,YACpC,GAAGE,EAAM;AAAA,YACT,GAAGA,EAAM;AAAA,UAAA,CACV;AAED,UAAAhQ,EAAQlI,GAAYC,CAAQ;AAAA,QAC9B,SAAS7F,GAAG;AACV,kBAAQ,MAAM,iCAAiCA,CAAC;AAAA,QAClD;AAAA,IACF;AAAA,IACA,CAAC8N,GAAS8P,CAAoB;AAAA,EAAA,GAG1BvT,IAAiBF,EAAY,CAAC2T,MAAqC;AACvE,IAAAA,EAAM,eAAA,GACNA,EAAM,aAAa,aAAa;AAAA,EAClC,GAAG,CAAA,CAAE;AAEL,SACE,gBAAA9U,EAAC,OAAA,EAAI,WAAU,UAAS,QAAQoB,GAAY,YAAYC,GACtD,UAAA,gBAAArB,EAACiC,IAAA,CAAA,CAAe,EAAA,CAClB;AAEJ;AAIA,SAAS8S,KAAM;AACb,QAAM,CAACC,GAAWC,CAAY,IAAIrR,EAAkB,QAAQ,GACtD,CAACsR,GAAYC,CAAa,IAAIvR,EAAS,EAAK,GAC5CkK,IAAe9R,EAAiB,CAAC8D,MAAMA,EAAE,YAAY,GACrDsV,IAAwBpZ,EAAiB,CAAC8D,MAAMA,EAAE,qBAAqB;AAG7E,EAAAoE,EAAU,MAAM;AAEd,UAAMmR,IADS,IAAI,gBAAgB,OAAO,SAAS,MAAM,EAC/B,IAAI,UAAU;AAExC,QAAIA,GAAY;AACd,YAAMpZ,IAAWsT,GAAgB8F,CAAU;AAC3C,MAAIpZ,MACF6R,EAAa7R,CAAQ,GAErB,OAAO,QAAQ,aAAa,CAAA,GAAI,IAAI,OAAO,SAAS,QAAQ;AAAA,IAEhE;AAAA,EACF,GAAG,CAAC6R,CAAY,CAAC,GAGjB5J,EAAU,MAAM;AACd,UAAMoR,IAAuB,MAAM;AACjC,MAAAL,EAAa,QAAQ;AAAA,IACvB;AACA,kBAAO,iBAAiB,mBAAmBK,CAAoB,GACxD,MAAM;AACX,aAAO,oBAAoB,mBAAmBA,CAAoB;AAAA,IACpE;AAAA,EACF,GAAG,CAAA,CAAE;AAGL,QAAMC,IAAuBpU;AAAA,IAC3B,CAACkU,MAAuB;AACtB,YAAMpZ,IAAWsT,GAAgB8F,CAAU;AAC3C,MAAIpZ,MACF6R,EAAa7R,CAAQ,GACrBgZ,EAAa,QAAQ;AAAA,IAEzB;AAAA,IACA,CAACnH,CAAY;AAAA,EAAA,GAIT0H,IAAsBrU;AAAA,IAC1B,CAAC9C,MAAoC;AACnC,MAAA+W,EAAsB/W,CAAQ,GAC9B4W,EAAa,QAAQ;AAAA,IACvB;AAAA,IACA,CAACG,CAAqB;AAAA,EAAA;AAGxB,2BACGK,IAAA,EAEC,UAAA;AAAA,IAAA,gBAAAzV,EAACmT,IAAA,EAAW;AAAA,IAGZ,gBAAAnT;AAAA,MAACsT;AAAA,MAAA;AAAA,QACC,QAAQ4B;AAAA,QACR,SAAS,MAAMC,EAAc,EAAK;AAAA,QAClC,iBAAiBK;AAAA,MAAA;AAAA,IAAA;AAAA,sBAIlB/D,IAAA,EAAgB;AAAA,IAEjB,gBAAAjR,EAAC,OAAA,EAAI,WAAU,uDACb,UAAA;AAAA,MAAA,gBAAAR,EAACgL,IAAA,EAAQ;AAAA,wBAGR,OAAA,EAAI,WAAU,2EACb,UAAA,gBAAAxK,EAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,QAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,QACb,UAAA;AAAA,UAAA,gBAAAR;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SAAS,MAAMiV,EAAa,QAAQ;AAAA,cACpC,WAAW,8DACTD,MAAc,WACV,qDACA,kGACN;AAAA,cACD,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAGD,gBAAAhV;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SAAS,MAAMiV,EAAa,SAAS;AAAA,cACrC,WAAW,8DACTD,MAAc,YACV,qDACA,kGACN;AAAA,cACD,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAGD,gBAAAhV;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SAAS,MAAMiV,EAAa,WAAW;AAAA,cACvC,WAAW,8DACTD,MAAc,cACV,qDACA,kGACN;AAAA,cACD,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QAED,GACF;AAAA,QAGA,gBAAAxU;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS,MAAM2U,EAAc,EAAI;AAAA,YACjC,WAAU;AAAA,YAEV,UAAA;AAAA,cAAA,gBAAAnV,EAAC,OAAA,EAAI,WAAU,WAAU,MAAK,QAAO,SAAQ,aAAY,QAAO,gBAC9D,UAAA,gBAAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,eAAc;AAAA,kBACd,gBAAe;AAAA,kBACf,aAAa;AAAA,kBACb,GAAE;AAAA,gBAAA;AAAA,cAAA,GAEN;AAAA,cAAM;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAER,EAAA,CACF,EAAA,CACF;AAAA,MAGA,gBAAAQ,EAAC,OAAA,EAAI,WAAU,+BACZ,UAAA;AAAA,QAAAwU,MAAc,YACb,gBAAAxU,EAAAoB,GAAA,EACE,UAAA;AAAA,UAAA,gBAAA5B,EAACyE,IAAA,EAAY;AAAA,4BACZkQ,IAAA,EAAe;AAAA,4BACfzO,IAAA,CAAA,CAAc;AAAA,QAAA,GACjB;AAAA,QAED8O,MAAc,aACb,gBAAAhV,EAAC,OAAA,EAAI,WAAU,wBACb,UAAA,gBAAAA,EAAC6N,MAAQ,EAAA,CACX;AAAA,QAEDmH,MAAc,eACb,gBAAAhV,EAAC,OAAA,EAAI,WAAU,wBACb,UAAA,gBAAAA,EAAC4P,IAAA,EAAgB,UAAU2F,EAAA,CAAsB,EAAA,CACnD;AAAA,MAAA,EAAA,CAEJ;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,GACF;AAEJ;","x_google_ignoreList":[0]}