@rslsp1/fa-app-tools 2.0.57 → 2.0.61

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.mjs CHANGED
@@ -353,10 +353,8 @@ var CompactDropdown = ({
353
353
  };
354
354
 
355
355
  // src/components/HistoryPanel.tsx
356
- import { useState as useState2 } from "react";
357
356
  import { motion } from "motion/react";
358
357
  import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
359
- var PAGE_SIZE = 20;
360
358
  var formatFriendlyTimestamp = (timestamp) => {
361
359
  const date = new Date(timestamp);
362
360
  const now = /* @__PURE__ */ new Date();
@@ -368,8 +366,7 @@ var formatFriendlyTimestamp = (timestamp) => {
368
366
  if (date.toDateString() === yesterday.toDateString()) return `Gestern, ${timeStr}`;
369
367
  return `${date.toLocaleDateString([], { day: "2-digit", month: "2-digit" })}, ${timeStr}`;
370
368
  };
371
- var HistoryPanel = ({ history, currentResultId, onSelect, onDelete }) => {
372
- const [visibleCount, setVisibleCount] = useState2(PAGE_SIZE);
369
+ var HistoryPanel = ({ history, currentResultId, onSelect, onDelete, visibleCount, onLoadMore }) => {
373
370
  const visibleHistory = history.slice(0, visibleCount);
374
371
  if (history.length === 0) {
375
372
  return /* @__PURE__ */ jsxs3("div", { className: "flex flex-col items-center justify-center py-20 text-center gap-4 opacity-10", children: [
@@ -413,7 +410,7 @@ var HistoryPanel = ({ history, currentResultId, onSelect, onDelete }) => {
413
410
  },
414
411
  gen.id
415
412
  )),
416
- visibleCount < history.length && /* @__PURE__ */ jsxs3("button", { type: "button", onClick: () => setVisibleCount((c) => c + PAGE_SIZE), className: "w-full py-2 bg-white/5 hover:bg-white/10 border border-white/10 rounded-xl text-[10px] font-bold uppercase text-white/60 hover:text-white transition-all", children: [
413
+ visibleCount < history.length && /* @__PURE__ */ jsxs3("button", { type: "button", onClick: onLoadMore, className: "w-full py-2 bg-white/5 hover:bg-white/10 border border-white/10 rounded-xl text-[10px] font-bold uppercase text-white/60 hover:text-white transition-all", children: [
417
414
  history.length - visibleCount,
418
415
  " weitere laden"
419
416
  ] })
@@ -486,7 +483,7 @@ var InspectPanel = ({ currentResult, history, onSelect, workspaceTags, onTagTogg
486
483
  };
487
484
 
488
485
  // src/components/SetupPanel.tsx
489
- import { useRef as useRef2, useState as useState3 } from "react";
486
+ import { useRef as useRef2, useState as useState2 } from "react";
490
487
  import { motion as motion3 } from "motion/react";
491
488
  import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
492
489
  var PRESET_URLS = [
@@ -496,11 +493,11 @@ var PRESET_URLS = [
496
493
  ];
497
494
  var SetupPanel = ({ onWorkspaceImport, buildInfo }) => {
498
495
  const workspaceInputRef = useRef2(null);
499
- const [urlInput, setUrlInput] = useState3("");
500
- const [tokenInput, setTokenInput] = useState3("");
501
- const [testStatus, setTestStatus] = useState3("idle");
502
- const [result, setResult] = useState3(null);
503
- const [fetchError, setFetchError] = useState3(null);
496
+ const [urlInput, setUrlInput] = useState2("");
497
+ const [tokenInput, setTokenInput] = useState2("");
498
+ const [testStatus, setTestStatus] = useState2("idle");
499
+ const [result, setResult] = useState2(null);
500
+ const [fetchError, setFetchError] = useState2(null);
504
501
  const runTest = async (url) => {
505
502
  if (!url.trim()) return;
506
503
  setTestStatus("loading");
@@ -663,7 +660,6 @@ var SetupPanel = ({ onWorkspaceImport, buildInfo }) => {
663
660
  };
664
661
 
665
662
  // src/components/MediaLibrary.tsx
666
- import { useState as useState4 } from "react";
667
663
  import { motion as motion4 } from "motion/react";
668
664
 
669
665
  // src/lib/grouping.ts
@@ -689,9 +685,7 @@ function groupByPrompt(items) {
689
685
 
690
686
  // src/components/MediaLibrary.tsx
691
687
  import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
692
- var PAGE_SIZE2 = 20;
693
- var MediaLibrary = ({ items, onImport, onDelete, onSelect, onToggleSelection, onBatchDownload, onGenerateReference }) => {
694
- const [visibleCount, setVisibleCount] = useState4(PAGE_SIZE2);
688
+ var MediaLibrary = ({ items, onImport, onDelete, onSelect, onToggleSelection, onBatchDownload, onGenerateReference, visibleCount, onLoadMore }) => {
695
689
  const selectedCount = items.filter((i) => i.selectedForExport).length;
696
690
  const groups = groupByPrompt(items);
697
691
  const visibleGroups = groups.slice(0, visibleCount);
@@ -764,7 +758,7 @@ var MediaLibrary = ({ items, onImport, onDelete, onSelect, onToggleSelection, on
764
758
  rep.id
765
759
  );
766
760
  }),
767
- visibleCount < groups.length && /* @__PURE__ */ jsx8("div", { className: "col-span-2 flex justify-center pt-2 pb-4", children: /* @__PURE__ */ jsxs6("button", { type: "button", onClick: () => setVisibleCount((c) => c + PAGE_SIZE2), className: "px-4 py-2 bg-white/5 hover:bg-white/10 border border-white/10 rounded-lg text-[10px] font-bold uppercase text-white/60 hover:text-white transition-all", children: [
761
+ visibleCount < groups.length && /* @__PURE__ */ jsx8("div", { className: "col-span-2 flex justify-center pt-2 pb-4", children: /* @__PURE__ */ jsxs6("button", { type: "button", onClick: onLoadMore, className: "px-4 py-2 bg-white/5 hover:bg-white/10 border border-white/10 rounded-lg text-[10px] font-bold uppercase text-white/60 hover:text-white transition-all", children: [
768
762
  groups.length - visibleCount,
769
763
  " weitere laden"
770
764
  ] }) })
@@ -773,7 +767,7 @@ var MediaLibrary = ({ items, onImport, onDelete, onSelect, onToggleSelection, on
773
767
  };
774
768
 
775
769
  // src/components/ListView.tsx
776
- import { useEffect as useEffect3, useRef as useRef3, useState as useState5 } from "react";
770
+ import { useEffect as useEffect3, useRef as useRef3, useState as useState3 } from "react";
777
771
  import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
778
772
  var ListNode = ({ node, depth, onNodeChange, onAddChild, onDeleteNode, onMoveNode, onIndentNode, onOutdentNode, onAddSibling, isActive, isInPath, onFocus, onGenerate, onGenerateBranch, onGenerateSubtree, isGenerating, isCollapsed, toggleCollapse, renderNode, children }) => {
779
773
  const inputRef = useRef3(null);
@@ -838,7 +832,7 @@ var ListNode = ({ node, depth, onNodeChange, onAddChild, onDeleteNode, onMoveNod
838
832
  ] });
839
833
  };
840
834
  function ListView({ nodes, edges, onNodeChange, onAddChild, onDeleteNode, onMoveNode, onIndentNode, onOutdentNode, onAddSibling, focusedNodeId, onFocus, activePath, onGenerate, onGenerateBranch, onGenerateSubtree, isGeneratingNodeId }) {
841
- const [collapsed, setCollapsed] = useState5(/* @__PURE__ */ new Set());
835
+ const [collapsed, setCollapsed] = useState3(/* @__PURE__ */ new Set());
842
836
  const toggleCollapse = (id) => {
843
837
  setCollapsed((prev) => {
844
838
  const next = new Set(prev);
@@ -866,13 +860,13 @@ function ListView({ nodes, edges, onNodeChange, onAddChild, onDeleteNode, onMove
866
860
  }
867
861
 
868
862
  // src/components/AvatarArchitectApp.tsx
869
- import { useState as useState20, useCallback as useCallback3, useMemo as useMemo2, useEffect as useEffect7, useRef as useRef8 } from "react";
863
+ import { useState as useState18, useCallback as useCallback3, useMemo as useMemo2, useEffect as useEffect7, useRef as useRef8 } from "react";
870
864
 
871
865
  // src/components/PromptTab.tsx
872
- import { useRef as useRef4, useState as useState7 } from "react";
866
+ import { useRef as useRef4, useState as useState5 } from "react";
873
867
 
874
868
  // src/components/CollapsibleCard.tsx
875
- import { useState as useState6 } from "react";
869
+ import { useState as useState4 } from "react";
876
870
  import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
877
871
  var CollapsibleCard = ({
878
872
  title,
@@ -883,7 +877,7 @@ var CollapsibleCard = ({
883
877
  collapsible = true,
884
878
  className = ""
885
879
  }) => {
886
- const [isOpen, setIsOpen] = useState6(defaultOpen);
880
+ const [isOpen, setIsOpen] = useState4(defaultOpen);
887
881
  return /* @__PURE__ */ jsxs8("div", { className: `border border-neutral-800 rounded-lg ${className}`, children: [
888
882
  /* @__PURE__ */ jsxs8(
889
883
  "div",
@@ -930,18 +924,18 @@ var PromptTab = ({
930
924
  onTagUpdate,
931
925
  onTagDelete
932
926
  }) => {
933
- const [selectedLabels, setSelectedLabels] = useState7(/* @__PURE__ */ new Set());
934
- const [instructions, setInstructions] = useState7("");
935
- const [rules, setRules] = useState7("");
936
- const [activeCategory, setActiveCategory] = useState7(null);
937
- const [copied, setCopied] = useState7(false);
927
+ const [selectedLabels, setSelectedLabels] = useState5(/* @__PURE__ */ new Set());
928
+ const [instructions, setInstructions] = useState5("");
929
+ const [rules, setRules] = useState5("");
930
+ const [activeCategory, setActiveCategory] = useState5(null);
931
+ const [copied, setCopied] = useState5(false);
938
932
  const imgInputRef = useRef4(null);
939
- const [addingInCat, setAddingInCat] = useState7(null);
940
- const [newLabel, setNewLabel] = useState7("");
941
- const [newValue, setNewValue] = useState7("");
942
- const [editingTag, setEditingTag] = useState7(null);
943
- const [editLabel, setEditLabel] = useState7("");
944
- const [editValue, setEditValue] = useState7("");
933
+ const [addingInCat, setAddingInCat] = useState5(null);
934
+ const [newLabel, setNewLabel] = useState5("");
935
+ const [newValue, setNewValue] = useState5("");
936
+ const [editingTag, setEditingTag] = useState5(null);
937
+ const [editLabel, setEditLabel] = useState5("");
938
+ const [editValue, setEditValue] = useState5("");
945
939
  const longPressTimer = useRef4(null);
946
940
  const longPressActivated = useRef4(false);
947
941
  const toggleTag = (label) => {
@@ -1390,7 +1384,7 @@ var PromptTab = ({
1390
1384
  };
1391
1385
 
1392
1386
  // src/components/ProjectSyncTab.tsx
1393
- import { useRef as useRef5, useState as useState8, useEffect as useEffect4 } from "react";
1387
+ import { useRef as useRef5, useState as useState6, useEffect as useEffect4 } from "react";
1394
1388
  import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
1395
1389
  var ProjectSyncTab = ({
1396
1390
  topSlot,
@@ -1412,12 +1406,12 @@ var ProjectSyncTab = ({
1412
1406
  }) => {
1413
1407
  const projectInputRef = useRef5(null);
1414
1408
  const workspaceInputRef = useRef5(null);
1415
- const [saveName, setSaveName] = useState8("");
1416
- const [isSaving, setIsSaving] = useState8(false);
1417
- const [isExporting, setIsExporting] = useState8(false);
1418
- const [syncState, setSyncState] = useState8("idle");
1419
- const [syncDiff, setSyncDiff] = useState8(null);
1420
- const [selectedLocalIds, setSelectedLocalIds] = useState8(/* @__PURE__ */ new Set());
1409
+ const [saveName, setSaveName] = useState6("");
1410
+ const [isSaving, setIsSaving] = useState6(false);
1411
+ const [isExporting, setIsExporting] = useState6(false);
1412
+ const [syncState, setSyncState] = useState6("idle");
1413
+ const [syncDiff, setSyncDiff] = useState6(null);
1414
+ const [selectedLocalIds, setSelectedLocalIds] = useState6(/* @__PURE__ */ new Set());
1421
1415
  const handleExport = async () => {
1422
1416
  if (!onProjectExport) return;
1423
1417
  setIsExporting(true);
@@ -1463,13 +1457,13 @@ var ProjectSyncTab = ({
1463
1457
  });
1464
1458
  };
1465
1459
  const isWorking = projectActionState === "working" || projectActionState === "working-full";
1466
- const [hfProjects, setHfProjects] = useState8([]);
1467
- const [hfLoading, setHfLoading] = useState8(false);
1468
- const [hfSaving, setHfSaving] = useState8(false);
1469
- const [hfError, setHfError] = useState8(null);
1470
- const [hfSaveName, setHfSaveName] = useState8("");
1471
- const [hfSyncProgress, setHfSyncProgress] = useState8(null);
1472
- const [hfSyncing, setHfSyncing] = useState8(false);
1460
+ const [hfProjects, setHfProjects] = useState6([]);
1461
+ const [hfLoading, setHfLoading] = useState6(false);
1462
+ const [hfSaving, setHfSaving] = useState6(false);
1463
+ const [hfError, setHfError] = useState6(null);
1464
+ const [hfSaveName, setHfSaveName] = useState6("");
1465
+ const [hfSyncProgress, setHfSyncProgress] = useState6(null);
1466
+ const [hfSyncing, setHfSyncing] = useState6(false);
1473
1467
  const loadHfProjects = async (token) => {
1474
1468
  setHfLoading(true);
1475
1469
  setHfError(null);
@@ -1888,7 +1882,7 @@ function toPromptImages(images) {
1888
1882
  }
1889
1883
 
1890
1884
  // src/hooks/useHFState.ts
1891
- import { useState as useState9, useEffect as useEffect5, useRef as useRef6, useCallback } from "react";
1885
+ import { useState as useState7, useEffect as useEffect5, useRef as useRef6, useCallback } from "react";
1892
1886
 
1893
1887
  // src/lib/hfReducer.ts
1894
1888
  function applyEvent(state, event) {
@@ -2020,15 +2014,15 @@ function writeOfflineBuffer(events) {
2020
2014
  }
2021
2015
  }
2022
2016
  function useHFState(token, namespace) {
2023
- const [state, setState] = useState9(null);
2024
- const [isLoading, setIsLoading] = useState9(false);
2025
- const [error, setError] = useState9(null);
2026
- const [eventCount, setEventCount] = useState9(0);
2027
- const [localOnlyCount, setLocalOnlyCount] = useState9(0);
2028
- const [forks, setForks] = useState9([]);
2029
- const [pendingBufferCount, setPendingBufferCount] = useState9(readOfflineBuffer().length);
2030
- const [lastEventTs, setLastEventTs] = useState9(0);
2031
- const [hasStateZip, setHasStateZip] = useState9(false);
2017
+ const [state, setState] = useState7(null);
2018
+ const [isLoading, setIsLoading] = useState7(false);
2019
+ const [error, setError] = useState7(null);
2020
+ const [eventCount, setEventCount] = useState7(0);
2021
+ const [localOnlyCount, setLocalOnlyCount] = useState7(0);
2022
+ const [forks, setForks] = useState7([]);
2023
+ const [pendingBufferCount, setPendingBufferCount] = useState7(readOfflineBuffer().length);
2024
+ const [lastEventTs, setLastEventTs] = useState7(0);
2025
+ const [hasStateZip, setHasStateZip] = useState7(false);
2032
2026
  const knownEventPaths = useRef6(/* @__PURE__ */ new Set());
2033
2027
  const knownFilePaths = useRef6(/* @__PURE__ */ new Set());
2034
2028
  const allEventsRef = useRef6([]);
@@ -2166,13 +2160,13 @@ function useHFState(token, namespace) {
2166
2160
  }
2167
2161
 
2168
2162
  // src/components/labs/LabsTab.tsx
2169
- import { useState as useState16 } from "react";
2163
+ import { useState as useState14 } from "react";
2170
2164
 
2171
2165
  // src/components/labs/LabRemix.tsx
2172
- import { useState as useState11 } from "react";
2166
+ import { useState as useState9 } from "react";
2173
2167
 
2174
2168
  // src/components/labs/LabImagePicker.tsx
2175
- import { useState as useState10 } from "react";
2169
+ import { useState as useState8 } from "react";
2176
2170
  import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
2177
2171
  var LabImagePicker = ({
2178
2172
  availableItems,
@@ -2181,8 +2175,8 @@ var LabImagePicker = ({
2181
2175
  onClose,
2182
2176
  title = "Bild w\xE4hlen"
2183
2177
  }) => {
2184
- const [search, setSearch] = useState10("");
2185
- const [drillItem, setDrillItem] = useState10(null);
2178
+ const [search, setSearch] = useState8("");
2179
+ const [drillItem, setDrillItem] = useState8(null);
2186
2180
  const filtered = availableItems.filter(
2187
2181
  (item) => !search || item.prompt.toLowerCase().includes(search.toLowerCase())
2188
2182
  );
@@ -2284,13 +2278,13 @@ var LabImagePicker = ({
2284
2278
  // src/components/labs/LabRemix.tsx
2285
2279
  import { Fragment as Fragment5, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
2286
2280
  var LabRemix = ({ services, onResult }) => {
2287
- const [showPicker, setShowPicker] = useState11(false);
2288
- const [selected, setSelected] = useState11(null);
2289
- const [instruction, setInstruction] = useState11("");
2290
- const [generatedPrompt, setGeneratedPrompt] = useState11("");
2291
- const [resultImage, setResultImage] = useState11(null);
2292
- const [isGeneratingPrompt, setIsGeneratingPrompt] = useState11(false);
2293
- const [isGeneratingImage, setIsGeneratingImage] = useState11(false);
2281
+ const [showPicker, setShowPicker] = useState9(false);
2282
+ const [selected, setSelected] = useState9(null);
2283
+ const [instruction, setInstruction] = useState9("");
2284
+ const [generatedPrompt, setGeneratedPrompt] = useState9("");
2285
+ const [resultImage, setResultImage] = useState9(null);
2286
+ const [isGeneratingPrompt, setIsGeneratingPrompt] = useState9(false);
2287
+ const [isGeneratingImage, setIsGeneratingImage] = useState9(false);
2294
2288
  const handleSelectImage = (item, frame) => {
2295
2289
  services.onItemUsed(item);
2296
2290
  setSelected({
@@ -2473,16 +2467,16 @@ var LabRemix = ({ services, onResult }) => {
2473
2467
  };
2474
2468
 
2475
2469
  // src/components/labs/LabBlend.tsx
2476
- import { useState as useState12 } from "react";
2470
+ import { useState as useState10 } from "react";
2477
2471
  import { Fragment as Fragment6, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
2478
2472
  var LabBlend = ({ services, onResult }) => {
2479
- const [showPickerFor, setShowPickerFor] = useState12(null);
2480
- const [selectedImages, setSelectedImages] = useState12([]);
2481
- const [instruction, setInstruction] = useState12("");
2482
- const [generatedPrompt, setGeneratedPrompt] = useState12("");
2483
- const [resultImage, setResultImage] = useState12(null);
2484
- const [isGeneratingPrompt, setIsGeneratingPrompt] = useState12(false);
2485
- const [isGeneratingImage, setIsGeneratingImage] = useState12(false);
2473
+ const [showPickerFor, setShowPickerFor] = useState10(null);
2474
+ const [selectedImages, setSelectedImages] = useState10([]);
2475
+ const [instruction, setInstruction] = useState10("");
2476
+ const [generatedPrompt, setGeneratedPrompt] = useState10("");
2477
+ const [resultImage, setResultImage] = useState10(null);
2478
+ const [isGeneratingPrompt, setIsGeneratingPrompt] = useState10(false);
2479
+ const [isGeneratingImage, setIsGeneratingImage] = useState10(false);
2486
2480
  const handleSelectImage = (index, item, frame) => {
2487
2481
  services.onItemUsed(item);
2488
2482
  const newImg = {
@@ -2669,17 +2663,17 @@ var LabBlend = ({ services, onResult }) => {
2669
2663
  };
2670
2664
 
2671
2665
  // src/components/labs/LabCompare.tsx
2672
- import { useState as useState13 } from "react";
2666
+ import { useState as useState11 } from "react";
2673
2667
  import { Fragment as Fragment7, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
2674
2668
  var LabCompare = ({ services, onResult }) => {
2675
- const [showPickerFor, setShowPickerFor] = useState13(null);
2676
- const [selectedImages, setSelectedImages] = useState13([]);
2677
- const [instruction, setInstruction] = useState13("");
2678
- const [analysis, setAnalysis] = useState13("");
2679
- const [generatedPrompt, setGeneratedPrompt] = useState13("");
2680
- const [resultImage, setResultImage] = useState13(null);
2681
- const [isAnalyzing, setIsAnalyzing] = useState13(false);
2682
- const [isGeneratingImage, setIsGeneratingImage] = useState13(false);
2669
+ const [showPickerFor, setShowPickerFor] = useState11(null);
2670
+ const [selectedImages, setSelectedImages] = useState11([]);
2671
+ const [instruction, setInstruction] = useState11("");
2672
+ const [analysis, setAnalysis] = useState11("");
2673
+ const [generatedPrompt, setGeneratedPrompt] = useState11("");
2674
+ const [resultImage, setResultImage] = useState11(null);
2675
+ const [isAnalyzing, setIsAnalyzing] = useState11(false);
2676
+ const [isGeneratingImage, setIsGeneratingImage] = useState11(false);
2683
2677
  const handleSelectImage = (index, item, frame) => {
2684
2678
  services.onItemUsed(item);
2685
2679
  const newImg = {
@@ -2842,14 +2836,14 @@ var LabCompare = ({ services, onResult }) => {
2842
2836
  };
2843
2837
 
2844
2838
  // src/components/labs/LabLoop.tsx
2845
- import { useState as useState14 } from "react";
2839
+ import { useState as useState12 } from "react";
2846
2840
  import { Fragment as Fragment8, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
2847
2841
  var LabLoop = ({ services, onResult }) => {
2848
- const [rounds, setRounds] = useState14([]);
2849
- const [currentInstruction, setCurrentInstruction] = useState14("");
2850
- const [showPickerForRound, setShowPickerForRound] = useState14(null);
2851
- const [pendingImages, setPendingImages] = useState14([]);
2852
- const [isGenerating, setIsGenerating] = useState14(false);
2842
+ const [rounds, setRounds] = useState12([]);
2843
+ const [currentInstruction, setCurrentInstruction] = useState12("");
2844
+ const [showPickerForRound, setShowPickerForRound] = useState12(null);
2845
+ const [pendingImages, setPendingImages] = useState12([]);
2846
+ const [isGenerating, setIsGenerating] = useState12(false);
2853
2847
  const currentPrompt = rounds.length > 0 ? rounds[rounds.length - 1].prompt : "";
2854
2848
  const handleAddImage = (item, frame) => {
2855
2849
  services.onItemUsed(item);
@@ -3005,7 +2999,7 @@ var LabLoop = ({ services, onResult }) => {
3005
2999
  };
3006
3000
 
3007
3001
  // src/components/labs/LabFrameExtractor.tsx
3008
- import { useRef as useRef7, useState as useState15, useCallback as useCallback2 } from "react";
3002
+ import { useRef as useRef7, useState as useState13, useCallback as useCallback2 } from "react";
3009
3003
  import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
3010
3004
  var formatTime = (s) => {
3011
3005
  const m = Math.floor(s / 60);
@@ -3022,12 +3016,12 @@ var LabFrameExtractor = ({
3022
3016
  const videoRef = useRef7(null);
3023
3017
  const canvasRef = useRef7(null);
3024
3018
  const cancelledRef = useRef7(false);
3025
- const [selectedItem, setSelectedItem] = useState15(null);
3026
- const [videoSrc, setVideoSrc] = useState15(null);
3027
- const [videoReady, setVideoReady] = useState15(false);
3028
- const [frames, setFrames] = useState15([]);
3029
- const [isExtracting, setIsExtracting] = useState15(false);
3030
- const [intervalSec, setIntervalSec] = useState15("1");
3019
+ const [selectedItem, setSelectedItem] = useState13(null);
3020
+ const [videoSrc, setVideoSrc] = useState13(null);
3021
+ const [videoReady, setVideoReady] = useState13(false);
3022
+ const [frames, setFrames] = useState13([]);
3023
+ const [isExtracting, setIsExtracting] = useState13(false);
3024
+ const [intervalSec, setIntervalSec] = useState13("1");
3031
3025
  const handleVideoSelect = (item) => {
3032
3026
  const mediaId = item.frames[0]?.mediaId;
3033
3027
  if (!mediaId) return;
@@ -3264,7 +3258,7 @@ var BASE_TABS = [
3264
3258
  ];
3265
3259
  var FRAMES_TAB = { key: "frames", label: "Frames", icon: "crop_original" };
3266
3260
  var LabsTab = ({ services, onResult, videoItems, resolveVideoUrl }) => {
3267
- const [activeTab, setActiveTab] = useState16("remix");
3261
+ const [activeTab, setActiveTab] = useState14("remix");
3268
3262
  const showFrames = !!(videoItems && resolveVideoUrl);
3269
3263
  const tabs = showFrames ? [...BASE_TABS, FRAMES_TAB] : BASE_TABS;
3270
3264
  return /* @__PURE__ */ jsxs17("div", { className: "flex flex-col h-full overflow-hidden", children: [
@@ -3298,19 +3292,19 @@ var LabsTab = ({ services, onResult, videoItems, resolveVideoUrl }) => {
3298
3292
  };
3299
3293
 
3300
3294
  // src/components/TagManagerPanel.tsx
3301
- import { useState as useState17 } from "react";
3295
+ import { useState as useState15 } from "react";
3302
3296
  import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
3303
3297
  function TagManagerPanel({ workspaceTags, onTagCreate, onTagUpdate, onTagDelete, onTagReorder, onTagMove }) {
3304
3298
  const categories = Object.keys(workspaceTags.by_category).filter(
3305
3299
  (cat) => (workspaceTags.by_category[cat] || []).some((t) => !t.is_deleted)
3306
3300
  );
3307
- const [selectedCategory, setSelectedCategory] = useState17(categories[0] || "");
3301
+ const [selectedCategory, setSelectedCategory] = useState15(categories[0] || "");
3308
3302
  const effectiveCategory = categories.includes(selectedCategory) ? selectedCategory : categories[0] || "";
3309
- const [editingLabel, setEditingLabel] = useState17(null);
3310
- const [editState, setEditState] = useState17({ label: "", value: "" });
3311
- const [newTag, setNewTag] = useState17({ label: "", value: "" });
3312
- const [movingLabel, setMovingLabel] = useState17(null);
3313
- const [moveTarget, setMoveTarget] = useState17("");
3303
+ const [editingLabel, setEditingLabel] = useState15(null);
3304
+ const [editState, setEditState] = useState15({ label: "", value: "" });
3305
+ const [newTag, setNewTag] = useState15({ label: "", value: "" });
3306
+ const [movingLabel, setMovingLabel] = useState15(null);
3307
+ const [moveTarget, setMoveTarget] = useState15("");
3314
3308
  const tags = (workspaceTags.by_category[effectiveCategory] || []).filter((t) => !t.is_deleted);
3315
3309
  const otherCategories = categories.filter((c) => c !== effectiveCategory);
3316
3310
  const startEdit = (tag) => {
@@ -3506,7 +3500,7 @@ function TagManagerPanel({ workspaceTags, onTagCreate, onTagUpdate, onTagDelete,
3506
3500
  }
3507
3501
 
3508
3502
  // src/components/HFTestTab.tsx
3509
- import { useState as useState18 } from "react";
3503
+ import { useState as useState16 } from "react";
3510
3504
  import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
3511
3505
  var HF_BASE = "https://huggingface.co";
3512
3506
  var HF_REPO = "RolandSch/fa-app-state";
@@ -3699,7 +3693,7 @@ function tryFmt(s) {
3699
3693
  }
3700
3694
  }
3701
3695
  function CopyBtn({ text }) {
3702
- const [done, setDone] = useState18(false);
3696
+ const [done, setDone] = useState16(false);
3703
3697
  return /* @__PURE__ */ jsxs19(
3704
3698
  "button",
3705
3699
  {
@@ -3871,9 +3865,9 @@ function EventMonitor({ events, confirmedEventKeys, galleryItems, imageUploadSta
3871
3865
  ] });
3872
3866
  }
3873
3867
  function HFTestTab({ token, namespace, galleryItems, allEvents = [], confirmedEventKeys = /* @__PURE__ */ new Set(), imageUploadStatus = /* @__PURE__ */ new Map(), missingImages = [] }) {
3874
- const [selected, setSelected] = useState18(null);
3875
- const [results, setResults] = useState18({});
3876
- const [expanded, setExpanded] = useState18({});
3868
+ const [selected, setSelected] = useState16(null);
3869
+ const [results, setResults] = useState16({});
3870
+ const [expanded, setExpanded] = useState16({});
3877
3871
  const withResults = galleryItems.filter((g) => g.base64 && g.status === "done");
3878
3872
  const setRunning = (id) => setResults((r) => ({ ...r, [id]: { status: "running", steps: [], totalMs: 0 } }));
3879
3873
  const setDone = (id, steps, t0) => {
@@ -4071,7 +4065,7 @@ function HFTestTab({ token, namespace, galleryItems, allEvents = [], confirmedEv
4071
4065
  }
4072
4066
 
4073
4067
  // src/components/ServerTab.tsx
4074
- import { useState as useState19, useEffect as useEffect6 } from "react";
4068
+ import { useState as useState17, useEffect as useEffect6 } from "react";
4075
4069
  import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
4076
4070
  function StarRating({ rating = 0 }) {
4077
4071
  return /* @__PURE__ */ jsx22("div", { className: "flex gap-[2px]", children: [1, 2, 3, 4, 5].map((i) => /* @__PURE__ */ jsx22("span", { className: `material-symbols-outlined text-[12px] ${i <= rating ? "text-yellow-400" : "text-white/15"}`, children: "star" }, i)) });
@@ -4084,20 +4078,20 @@ async function serverGet(baseUrl, path) {
4084
4078
  return json && typeof json === "object" && "data" in json ? json.data : json;
4085
4079
  }
4086
4080
  function ServerTab({ serverBaseUrl }) {
4087
- const [step, setStep] = useState19("user");
4088
- const [users, setUsers] = useState19([]);
4089
- const [usersLoading, setUsersLoading] = useState19(false);
4090
- const [usersError, setUsersError] = useState19(null);
4091
- const [selectedUser, setSelectedUser] = useState19(null);
4092
- const [contexts, setContexts] = useState19([]);
4093
- const [contextsLoading, setContextsLoading] = useState19(false);
4094
- const [selectedContext, setSelectedContext] = useState19(null);
4095
- const [tags, setTags] = useState19([]);
4096
- const [items, setItems] = useState19([]);
4097
- const [libLoading, setLibLoading] = useState19(false);
4098
- const [libError, setLibError] = useState19(null);
4099
- const [activeTag, setActiveTag] = useState19(null);
4100
- const [preview, setPreview] = useState19(null);
4081
+ const [step, setStep] = useState17("user");
4082
+ const [users, setUsers] = useState17([]);
4083
+ const [usersLoading, setUsersLoading] = useState17(false);
4084
+ const [usersError, setUsersError] = useState17(null);
4085
+ const [selectedUser, setSelectedUser] = useState17(null);
4086
+ const [contexts, setContexts] = useState17([]);
4087
+ const [contextsLoading, setContextsLoading] = useState17(false);
4088
+ const [selectedContext, setSelectedContext] = useState17(null);
4089
+ const [tags, setTags] = useState17([]);
4090
+ const [items, setItems] = useState17([]);
4091
+ const [libLoading, setLibLoading] = useState17(false);
4092
+ const [libError, setLibError] = useState17(null);
4093
+ const [activeTag, setActiveTag] = useState17(null);
4094
+ const [preview, setPreview] = useState17(null);
4101
4095
  useEffect6(() => {
4102
4096
  if (!serverBaseUrl) return;
4103
4097
  setUsersLoading(true);
@@ -4260,19 +4254,19 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4260
4254
  document.head.appendChild(style);
4261
4255
  }
4262
4256
  }, []);
4263
- const [showStart, setShowStart] = useState20(true);
4264
- const [layoutChoice, setLayoutChoice] = useState20(() => {
4257
+ const [showStart, setShowStart] = useState18(true);
4258
+ const [layoutChoice, setLayoutChoice] = useState18(() => {
4265
4259
  try {
4266
4260
  return localStorage.getItem("aa-layout") || null;
4267
4261
  } catch {
4268
4262
  return null;
4269
4263
  }
4270
4264
  });
4271
- const [projectLoaded, setProjectLoaded] = useState20(false);
4272
- const [hfToken, setHfToken] = useState20(initialHfToken || "");
4273
- const [hfTokenInput, setHfTokenInput] = useState20(initialHfToken || "");
4274
- const [isLoadingFromHF, setIsLoadingFromHF] = useState20(false);
4275
- const [hfNamespaceLocal, setHfNamespaceLocal] = useState20(() => {
4265
+ const [projectLoaded, setProjectLoaded] = useState18(false);
4266
+ const [hfToken, setHfToken] = useState18(initialHfToken || "");
4267
+ const [hfTokenInput, setHfTokenInput] = useState18(initialHfToken || "");
4268
+ const [isLoadingFromHF, setIsLoadingFromHF] = useState18(false);
4269
+ const [hfNamespaceLocal, setHfNamespaceLocal] = useState18(() => {
4276
4270
  const KNOWN = ["app.art-by-rolands.de/", "dev-app.art-by-rolands.de/"];
4277
4271
  const DEFAULT = "app.art-by-rolands.de/";
4278
4272
  try {
@@ -4284,7 +4278,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4284
4278
  return DEFAULT;
4285
4279
  }
4286
4280
  });
4287
- const [hfNamespaceFromServer, setHfNamespaceFromServer] = useState20(null);
4281
+ const [hfNamespaceFromServer, setHfNamespaceFromServer] = useState18(null);
4288
4282
  useEffect7(() => {
4289
4283
  if (hfNamespace !== void 0) return;
4290
4284
  const backendUrl = typeof window !== "undefined" ? window.BACKEND_URL || window.location.origin : null;
@@ -4307,10 +4301,10 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4307
4301
  refresh: refreshHF,
4308
4302
  hasStateZip
4309
4303
  } = useHFState(hfToken, effectiveNamespace);
4310
- const [imageUploadStatus, setImageUploadStatus] = useState20(/* @__PURE__ */ new Map());
4311
- const [bootstrapLog, setBootstrapLog] = useState20([]);
4312
- const [isBootstrapping, setIsBootstrapping] = useState20(false);
4313
- const [hfMissingImages, setHfMissingImages] = useState20([]);
4304
+ const [imageUploadStatus, setImageUploadStatus] = useState18(/* @__PURE__ */ new Map());
4305
+ const [bootstrapLog, setBootstrapLog] = useState18([]);
4306
+ const [isBootstrapping, setIsBootstrapping] = useState18(false);
4307
+ const [hfMissingImages, setHfMissingImages] = useState18([]);
4314
4308
  const syncTopSlot = /* @__PURE__ */ jsxs21(Fragment9, { children: [
4315
4309
  localOnlyCount > 0 && /* @__PURE__ */ jsxs21("div", { style: { background: "rgba(234,179,8,0.15)", border: "1px solid rgba(234,179,8,0.3)", padding: "4px 10px", fontSize: 11, color: "#fbbf24", borderRadius: 4, marginBottom: 4 }, children: [
4316
4310
  "\u26A0 ",
@@ -4369,15 +4363,36 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4369
4363
  setLayoutChoice(choice);
4370
4364
  setShowStart(false);
4371
4365
  };
4372
- const [nodes, setNodes] = useState20([{ id: "1", type: "custom", position: { x: 0, y: 0 }, data: { label: "Fine Art Project", placeholder: "Name..." } }]);
4373
- const [edges, setEdges] = useState20([]);
4374
- const [history, setHistory] = useState20([]);
4375
- const [galleryItems, setGalleryItems] = useState20([]);
4366
+ const [nodes, setNodes] = useState18([{ id: "1", type: "custom", position: { x: 0, y: 0 }, data: { label: "Fine Art Project", placeholder: "Name..." } }]);
4367
+ const [edges, setEdges] = useState18([]);
4368
+ const [history, setHistory] = useState18([]);
4369
+ const [galleryItems, setGalleryItems] = useState18([]);
4376
4370
  const galleryItemsRef = useRef8([]);
4377
4371
  useEffect7(() => {
4378
4372
  galleryItemsRef.current = galleryItems;
4379
4373
  }, [galleryItems]);
4380
4374
  const hfImageNotFoundRef = useRef8(/* @__PURE__ */ new Map());
4375
+ const [galleryVisibleCount, setGalleryVisibleCount] = useState18(20);
4376
+ const [historyVisibleCount, setHistoryVisibleCount] = useState18(20);
4377
+ const loadThumbnailsForEntries = useCallback3(async (entries) => {
4378
+ for (const entry of entries) {
4379
+ if (galleryItemsRef.current.find((g) => g.id === entry.id)?.base64) continue;
4380
+ if (hfImageNotFoundRef.current.has(entry.id)) continue;
4381
+ try {
4382
+ const b64 = await hfLoadImageAsBase64(entry.id, hfToken, effectiveNamespace, entry.filename, void 0, entry.mimeType, entry.hasThumb);
4383
+ if (!b64) {
4384
+ hfImageNotFoundRef.current.set(entry.id, Date.now());
4385
+ setHfMissingImages((prev) => prev.find((e) => e.id === entry.id) ? prev : [...prev, { id: entry.id, filename: entry.filename, mimeType: entry.mimeType ?? "image/jpeg", timestamp: entry.timestamp ?? 0 }]);
4386
+ continue;
4387
+ }
4388
+ const prefix = `data:${entry.mimeType || "image/jpeg"};base64,`;
4389
+ setGalleryItems((prev) => prev.map((g) => g.id === entry.id && !g.base64 ? { ...g, base64: prefix + b64 } : g));
4390
+ setHistory((prev) => prev.map((g) => g.id === entry.id && !g.base64 ? { ...g, base64: prefix + b64 } : g));
4391
+ } catch {
4392
+ hfImageNotFoundRef.current.set(entry.id, Date.now());
4393
+ }
4394
+ }
4395
+ }, [hfToken, effectiveNamespace]);
4381
4396
  useEffect7(() => {
4382
4397
  if (!hfState) return;
4383
4398
  if (hfState.tags?.by_category) setWorkspaceTags(hfState.tags);
@@ -4404,87 +4419,94 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4404
4419
  const merged = skeletons.map((s) => prev.find((g) => g.id === s.id) ?? s);
4405
4420
  return [...localOnly, ...merged].sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0));
4406
4421
  });
4407
- const sortedEntries = [...hfState.metadata].sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0));
4408
- const galleryRepIds = new Set(groupByPrompt(skeletons).slice(0, 20).map((g) => g.representative.id));
4409
- const historyIds = new Set(sortedEntries.slice(0, 20).map((e) => e.id));
4410
- const initialIds = /* @__PURE__ */ new Set([...galleryRepIds, ...historyIds]);
4411
- const toLoad = sortedEntries.filter((e) => initialIds.has(e.id));
4412
- (async () => {
4413
- for (const entry of toLoad) {
4414
- if (galleryItemsRef.current.find((g) => g.id === entry.id)?.base64) continue;
4415
- if (hfImageNotFoundRef.current.has(entry.id)) continue;
4416
- try {
4417
- const b64 = await hfLoadImageAsBase64(entry.id, hfToken, effectiveNamespace, entry.filename, void 0, entry.mimeType, entry.hasThumb);
4418
- if (!b64) {
4419
- hfImageNotFoundRef.current.set(entry.id, Date.now());
4420
- setHfMissingImages((prev) => {
4421
- if (prev.find((e) => e.id === entry.id)) return prev;
4422
- return [...prev, { id: entry.id, filename: entry.filename, mimeType: entry.mimeType, timestamp: entry.timestamp }];
4423
- });
4424
- continue;
4425
- }
4426
- const prefix = `data:${entry.mimeType || "image/jpeg"};base64,`;
4427
- setGalleryItems((prev) => prev.map((g) => g.id === entry.id && !g.base64 ? { ...g, base64: prefix + b64 } : g));
4428
- setHistory((prev) => prev.map((g) => g.id === entry.id && !g.base64 ? { ...g, base64: prefix + b64 } : g));
4429
- } catch {
4430
- hfImageNotFoundRef.current.set(entry.id, Date.now());
4431
- }
4432
- }
4433
- })();
4434
4422
  }, [hfState]);
4435
- const [activePrompt, setActivePrompt] = useState20("");
4436
- const [isSynthesizing, setIsSynthesizing] = useState20(false);
4437
- const [activeGenerationsCount, setActiveGenerationsCount] = useState20(0);
4438
- const [currentResult, setCurrentResult] = useState20(null);
4439
- const [focusedNodeId, setFocusedNodeId] = useState20(null);
4440
- const [leftTab, setLeftTab] = useState20("prompt");
4441
- const [promptFeedback, setPromptFeedback] = useState20(null);
4442
- const [lastPromptPayload, setLastPromptPayload] = useState20(null);
4443
- const [isPromptTabGenerating, setIsPromptTabGenerating] = useState20(false);
4444
- const [activeTab, setActiveTab] = useState20("history");
4445
- const [mobileTab, setMobileTab] = useState20("stage");
4446
- const [middlePanel, setMiddlePanel] = useState20("stage");
4447
- const [recentLabItems, setRecentLabItems] = useState20([]);
4448
- const [aspectRatio, setAspectRatio] = useState20("1:1");
4449
- const [selectedModel, setSelectedModel] = useState20("\u{1F34C} Nano Banana Pro");
4450
- const [seed, setSeed] = useState20(Math.floor(Math.random() * 1e6));
4451
- const [seedMode, setSeedMode] = useState20("random");
4452
- const [isLeftCollapsed, setIsLeftCollapsed] = useState20(false);
4453
- const [isRightCollapsed, setIsRightCollapsed] = useState20(false);
4454
- const [leftPanelWidth, setLeftPanelWidth] = useState20(() => {
4423
+ useEffect7(() => {
4424
+ if (!hfState) return;
4425
+ const sortedMeta = [...hfState.metadata].sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0));
4426
+ const skeletons = sortedMeta.map((m) => ({ id: m.id, prompt: m.prompt, timestamp: m.timestamp, status: "done", nodeId: m.id, tags: m.tags || [] }));
4427
+ const repIds = new Set(groupByPrompt(skeletons).slice(0, galleryVisibleCount).map((g) => g.representative.id));
4428
+ loadThumbnailsForEntries(sortedMeta.filter((e) => repIds.has(e.id)));
4429
+ }, [hfState, galleryVisibleCount, loadThumbnailsForEntries]);
4430
+ useEffect7(() => {
4431
+ if (!hfState) return;
4432
+ const sortedMeta = [...hfState.metadata].sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0));
4433
+ loadThumbnailsForEntries(sortedMeta.slice(0, historyVisibleCount));
4434
+ }, [hfState, historyVisibleCount, loadThumbnailsForEntries]);
4435
+ const [activePrompt, setActivePrompt] = useState18("");
4436
+ const [isSynthesizing, setIsSynthesizing] = useState18(false);
4437
+ const [activeGenerationsCount, setActiveGenerationsCount] = useState18(0);
4438
+ const [currentResult, setCurrentResult] = useState18(null);
4439
+ const [focusedNodeId, setFocusedNodeId] = useState18(null);
4440
+ const [leftTab, setLeftTab] = useState18("prompt");
4441
+ const [promptFeedback, setPromptFeedback] = useState18(null);
4442
+ const [lastPromptPayload, setLastPromptPayload] = useState18(null);
4443
+ const [isPromptTabGenerating, setIsPromptTabGenerating] = useState18(false);
4444
+ const [activeTab, setActiveTab] = useState18("history");
4445
+ const [mobileTab, setMobileTab] = useState18("stage");
4446
+ const [middlePanel, setMiddlePanel] = useState18("stage");
4447
+ const [recentLabItems, setRecentLabItems] = useState18([]);
4448
+ const [aspectRatio, setAspectRatio] = useState18("1:1");
4449
+ const [selectedModel, setSelectedModel] = useState18("\u{1F34C} Nano Banana Pro");
4450
+ const [seed, setSeed] = useState18(Math.floor(Math.random() * 1e6));
4451
+ const [seedMode, setSeedMode] = useState18("random");
4452
+ const [imageCount, setImageCount] = useState18(() => {
4453
+ try {
4454
+ const v = parseInt(localStorage.getItem("aa-image-count") || "", 10);
4455
+ return v >= 1 && v <= 8 ? v : 4;
4456
+ } catch {
4457
+ return 4;
4458
+ }
4459
+ });
4460
+ const updateImageCount = (val) => {
4461
+ const n = Math.max(1, Math.min(8, parseInt(val, 10) || 4));
4462
+ setImageCount(n);
4463
+ try {
4464
+ localStorage.setItem("aa-image-count", String(n));
4465
+ } catch {
4466
+ }
4467
+ };
4468
+ const imageCountOptions = [
4469
+ { label: "1 Bild", value: "1" },
4470
+ { label: "2 Bilder", value: "2" },
4471
+ { label: "4 Bilder", value: "4" },
4472
+ { label: "8 Bilder", value: "8" }
4473
+ ];
4474
+ const [isLeftCollapsed, setIsLeftCollapsed] = useState18(false);
4475
+ const [isRightCollapsed, setIsRightCollapsed] = useState18(false);
4476
+ const [leftPanelWidth, setLeftPanelWidth] = useState18(() => {
4455
4477
  try {
4456
4478
  return parseInt(localStorage.getItem("aa-left-width") || "260", 10);
4457
4479
  } catch {
4458
4480
  return 260;
4459
4481
  }
4460
4482
  });
4461
- const [rightPanelWidth, setRightPanelWidth] = useState20(() => {
4483
+ const [rightPanelWidth, setRightPanelWidth] = useState18(() => {
4462
4484
  try {
4463
4485
  return parseInt(localStorage.getItem("aa-right-width") || "320", 10);
4464
4486
  } catch {
4465
4487
  return 320;
4466
4488
  }
4467
4489
  });
4468
- const [isPromptCollapsed, setIsPromptCollapsed] = useState20(false);
4469
- const [projectActionState, setProjectActionState] = useState20("idle");
4490
+ const [isPromptCollapsed, setIsPromptCollapsed] = useState18(false);
4491
+ const [projectActionState, setProjectActionState] = useState18("idle");
4470
4492
  const syncServerDataRef = useRef8(null);
4471
- const [workspaceTags, setWorkspaceTags] = useState20(null);
4472
- const [serverProjects, setServerProjects] = useState20([]);
4473
- const [isLoadingFromServer, setIsLoadingFromServer] = useState20(false);
4474
- const [highContrast, setHighContrast] = useState20(() => {
4493
+ const [workspaceTags, setWorkspaceTags] = useState18(null);
4494
+ const [serverProjects, setServerProjects] = useState18([]);
4495
+ const [isLoadingFromServer, setIsLoadingFromServer] = useState18(false);
4496
+ const [highContrast, setHighContrast] = useState18(() => {
4475
4497
  try {
4476
4498
  return localStorage.getItem("aa-contrast") === "high";
4477
4499
  } catch {
4478
4500
  return false;
4479
4501
  }
4480
4502
  });
4481
- const [activeReferenceId, setActiveReferenceId] = useState20(null);
4482
- const [activeReferenceThumbnail, setActiveReferenceThumbnail] = useState20(null);
4483
- const [isScanningImage, setIsScanningImage] = useState20(false);
4484
- const [touchStartX, setTouchStartX] = useState20(null);
4485
- const [isFullscreen, setIsFullscreen] = useState20(false);
4486
- const [zoomScale, setZoomScale] = useState20(1);
4487
- const [zoomOffset, setZoomOffset] = useState20({ x: 0, y: 0 });
4503
+ const [activeReferenceId, setActiveReferenceId] = useState18(null);
4504
+ const [activeReferenceThumbnail, setActiveReferenceThumbnail] = useState18(null);
4505
+ const [isScanningImage, setIsScanningImage] = useState18(false);
4506
+ const [touchStartX, setTouchStartX] = useState18(null);
4507
+ const [isFullscreen, setIsFullscreen] = useState18(false);
4508
+ const [zoomScale, setZoomScale] = useState18(1);
4509
+ const [zoomOffset, setZoomOffset] = useState18({ x: 0, y: 0 });
4488
4510
  const lastPinchDist = useRef8(null);
4489
4511
  const lastTapTime = useRef8(0);
4490
4512
  const dragStart = useRef8(null);
@@ -4640,7 +4662,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4640
4662
  const handleGallerySelect = useCallback3((g) => {
4641
4663
  setCurrentResult(g);
4642
4664
  setMobileTab("stage");
4643
- if (g.filename && hfToken && !g.fullBase64) {
4665
+ if (g.hasThumb && g.filename && hfToken && !g.fullBase64) {
4644
4666
  hfLoadImageAsBase64(g.id, hfToken, effectiveNamespace, g.filename, void 0, g.mimeType, false).then((b64) => {
4645
4667
  if (!b64) return;
4646
4668
  const full = `data:${g.mimeType || "image/jpeg"};base64,${b64}`;
@@ -4691,7 +4713,18 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4691
4713
  })();
4692
4714
  }, [currentResult?.id, currentResult?.prompt]);
4693
4715
  const hcStyle = highContrast ? { filter: "brightness(1.6) contrast(1.05)" } : void 0;
4694
- const isGenerating = activeGenerationsCount > 0;
4716
+ const runningBadge = activeGenerationsCount > 0 ? /* @__PURE__ */ jsxs21(
4717
+ "div",
4718
+ {
4719
+ className: "flex items-center gap-1 rounded-full bg-sky-500/15 border border-sky-400/30 px-2 shrink-0",
4720
+ style: { height: 24 },
4721
+ title: `${activeGenerationsCount} Generierung${activeGenerationsCount === 1 ? "" : "en"} l\xE4uft gerade`,
4722
+ children: [
4723
+ /* @__PURE__ */ jsx23("span", { className: "material-symbols-outlined text-sky-300", style: { fontSize: 14, lineHeight: 1 }, children: "autorenew" }),
4724
+ /* @__PURE__ */ jsx23("span", { className: "text-[11px] font-bold text-sky-300 tabular-nums", children: activeGenerationsCount })
4725
+ ]
4726
+ }
4727
+ ) : null;
4695
4728
  useKeyboardNavigation(history, currentResult, setCurrentResult);
4696
4729
  const getSubtreeFormat = useCallback3((nodeId, depth = 0) => {
4697
4730
  const node = nodes.find((n) => n.id === nodeId);
@@ -4764,6 +4797,15 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4764
4797
  setActiveGenerationsCount((prev) => Math.max(0, prev - 1));
4765
4798
  }
4766
4799
  };
4800
+ const handleGenerateBatch = (customPrompt, useReferenceId, overrideNodeId, options = { silent: false }) => {
4801
+ const count = Math.max(1, Math.min(8, imageCount));
4802
+ return Promise.all(
4803
+ Array.from(
4804
+ { length: count },
4805
+ (_, i) => handleGenerateImage(customPrompt, useReferenceId, overrideNodeId, { silent: options.silent || i > 0 })
4806
+ )
4807
+ );
4808
+ };
4767
4809
  const handleSynthesizePrompt = async (nodeId, autoGenerate = false) => {
4768
4810
  setIsSynthesizing(true);
4769
4811
  try {
@@ -5337,7 +5379,9 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5337
5379
  /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-2 px-3 border-b border-white/5 bg-black/30 shrink-0", style: { height: 52 }, children: [
5338
5380
  /* @__PURE__ */ jsx23(CompactDropdown, { value: aspectRatio, onChange: setAspectRatio, options: [{ label: "1:1", value: "1:1" }, { label: "16:9", value: "16:9" }, { label: "9:16", value: "9:16" }] }),
5339
5381
  /* @__PURE__ */ jsx23(CompactDropdown, { value: selectedModel, onChange: setSelectedModel, options: [{ value: "\u{1F34C} Nano Banana Pro", label: "\u{1F34C} Nano Banana Pro" }, { value: "\u{1F34C} Nano Banana 2", label: "\u{1F34C} Nano Banana 2" }, { value: "Imagen 4", label: "Imagen 4" }] }),
5382
+ /* @__PURE__ */ jsx23(CompactDropdown, { value: String(imageCount), displayValue: `${imageCount}\xD7`, onChange: updateImageCount, options: imageCountOptions }),
5340
5383
  /* @__PURE__ */ jsx23("div", { className: "flex-1" }),
5384
+ runningBadge,
5341
5385
  activeReferenceThumbnail ? /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-1 rounded-lg border border-white/20 bg-white/5 overflow-hidden mr-2", style: { height: 28 }, children: [
5342
5386
  /* @__PURE__ */ jsx23("img", { src: activeReferenceThumbnail, className: "h-full aspect-square object-cover" }),
5343
5387
  /* @__PURE__ */ jsx23("span", { className: "text-[10px] text-white/60 font-bold uppercase tracking-wide px-1", children: "Ref" }),
@@ -5359,20 +5403,17 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5359
5403
  ),
5360
5404
  activePrompt && !isSynthesizing && /* @__PURE__ */ jsx23("button", { onClick: () => setActivePrompt(""), className: "absolute top-2 right-2 w-8 h-8 flex items-center justify-center text-white/20 active:text-white transition-colors", children: /* @__PURE__ */ jsx23("span", { className: "material-symbols-outlined text-[18px]", children: "close" }) })
5361
5405
  ] }) }),
5362
- /* @__PURE__ */ jsx23("div", { className: "px-3 pb-3 shrink-0", children: /* @__PURE__ */ jsx23(
5406
+ /* @__PURE__ */ jsx23("div", { className: "px-3 pb-3 shrink-0", children: /* @__PURE__ */ jsxs21(
5363
5407
  "button",
5364
5408
  {
5365
- onClick: () => handleGenerateImage(),
5366
- disabled: !activePrompt.trim() || isGenerating,
5409
+ onClick: () => handleGenerateBatch(),
5410
+ disabled: !activePrompt.trim(),
5367
5411
  className: "w-full flex items-center justify-center gap-2 rounded-xl font-bold text-[14px] uppercase tracking-wide transition-all disabled:opacity-30 active:scale-95",
5368
- style: { height: 48, background: activePrompt.trim() && !isGenerating ? "#0284c7" : void 0, border: "1px solid rgba(255,255,255,0.1)" },
5369
- children: isGenerating ? /* @__PURE__ */ jsxs21(Fragment9, { children: [
5370
- /* @__PURE__ */ jsx23("div", { className: "w-4 h-4 border-t-2 border-white rounded-full animate-spin" }),
5371
- /* @__PURE__ */ jsx23("span", { children: "Generiere..." })
5372
- ] }) : /* @__PURE__ */ jsxs21(Fragment9, { children: [
5412
+ style: { height: 48, background: activePrompt.trim() ? "#0284c7" : void 0, border: "1px solid rgba(255,255,255,0.1)" },
5413
+ children: [
5373
5414
  /* @__PURE__ */ jsx23("span", { className: "material-symbols-outlined text-[20px]", children: "bolt" }),
5374
5415
  /* @__PURE__ */ jsx23("span", { children: "Generieren" })
5375
- ] })
5416
+ ]
5376
5417
  }
5377
5418
  ) }),
5378
5419
  /* @__PURE__ */ jsxs21("div", { className: "flex-1 min-h-0 px-3 pb-3 flex flex-col", children: [
@@ -5390,9 +5431,9 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5390
5431
  setTouchStartX(null);
5391
5432
  },
5392
5433
  children: [
5393
- currentResult?.status === "processing" && /* @__PURE__ */ jsxs21("div", { className: "flex flex-col items-center gap-3", children: [
5394
- /* @__PURE__ */ jsx23("div", { className: "w-10 h-10 border-t-2 border-white rounded-full animate-spin" }),
5395
- /* @__PURE__ */ jsx23("span", { className: "text-[11px] text-white/40 uppercase font-bold tracking-widest", children: "Erstelle Bild..." })
5434
+ currentResult?.status === "processing" && /* @__PURE__ */ jsxs21("div", { className: "flex flex-col items-center gap-3 opacity-40", children: [
5435
+ /* @__PURE__ */ jsx23("span", { className: "material-symbols-outlined text-[40px]", children: "hourglass_top" }),
5436
+ /* @__PURE__ */ jsx23("span", { className: "text-[11px] uppercase font-bold tracking-widest", children: "Erstelle Bild..." })
5396
5437
  ] }),
5397
5438
  currentResult?.status === "error" && /* @__PURE__ */ jsxs21("div", { className: "p-6 text-center flex flex-col items-center gap-3", children: [
5398
5439
  /* @__PURE__ */ jsx23("span", { className: "material-symbols-outlined text-red-400 text-[36px]", children: "warning" }),
@@ -5465,7 +5506,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5465
5506
  /* @__PURE__ */ jsx23("span", { className: "material-symbols-outlined text-[18px] text-white/60", children: "replay" }),
5466
5507
  /* @__PURE__ */ jsx23("span", { className: "text-[12px] text-white/60", children: "Prompt" })
5467
5508
  ] }),
5468
- /* @__PURE__ */ jsxs21("button", { onClick: () => handleGenerateImage(currentResult.prompt || activePrompt, currentResult.mediaId, void 0, { silent: true }), className: "flex-1 flex items-center justify-center gap-1.5 rounded-xl bg-white/10 active:bg-white/15 transition-colors", style: { height: 44 }, children: [
5509
+ /* @__PURE__ */ jsxs21("button", { onClick: () => handleGenerateBatch(currentResult.prompt || activePrompt, currentResult.mediaId, void 0, { silent: true }), className: "flex-1 flex items-center justify-center gap-1.5 rounded-xl bg-white/10 active:bg-white/15 transition-colors", style: { height: 44 }, children: [
5469
5510
  /* @__PURE__ */ jsx23("span", { className: "material-symbols-outlined text-[18px] text-white/80", children: "auto_fix_high" }),
5470
5511
  /* @__PURE__ */ jsx23("span", { className: "text-[12px] text-white/80 font-bold", children: "Referenz" })
5471
5512
  ] }),
@@ -5482,7 +5523,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5482
5523
  hfToken && /* @__PURE__ */ jsx23("button", { onClick: () => refreshHF(), disabled: isHfRefreshing, className: "w-12 flex items-center justify-center text-white/20 active:text-white transition-colors disabled:opacity-30", children: /* @__PURE__ */ jsx23("span", { className: `material-symbols-outlined text-[20px]${isHfRefreshing ? " animate-spin" : ""}`, children: "sync" }) })
5483
5524
  ] }),
5484
5525
  /* @__PURE__ */ jsxs21("div", { className: "flex-1 overflow-hidden relative", children: [
5485
- activeTab === "history" && /* @__PURE__ */ jsx23(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)) }),
5526
+ activeTab === "history" && /* @__PURE__ */ jsx23(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)), visibleCount: historyVisibleCount, onLoadMore: () => setHistoryVisibleCount((c) => c + 20) }),
5486
5527
  activeTab === "gallery" && /* @__PURE__ */ jsx23(
5487
5528
  MediaLibrary,
5488
5529
  {
@@ -5495,9 +5536,11 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5495
5536
  onDelete: (id) => setGalleryItems((g) => g.filter((x) => x.id !== id)),
5496
5537
  onSelect: handleGallerySelect,
5497
5538
  onGenerateReference: (item) => {
5498
- handleGenerateImage(item.prompt || activePrompt, item.mediaId, void 0, { silent: true });
5539
+ handleGenerateBatch(item.prompt || activePrompt, item.mediaId, void 0, { silent: true });
5499
5540
  setMobileTab("stage");
5500
- }
5541
+ },
5542
+ visibleCount: galleryVisibleCount,
5543
+ onLoadMore: () => setGalleryVisibleCount((c) => c + 20)
5501
5544
  }
5502
5545
  ),
5503
5546
  activeTab === "inspect" && /* @__PURE__ */ jsx23(InspectPanel, { currentResult, history, onSelect: (g) => {
@@ -5569,7 +5612,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5569
5612
  }
5570
5613
  ) }),
5571
5614
  workspaceTags && /* @__PURE__ */ jsx23("div", { style: { display: leftTab === "prompt" && activeTab !== "setup" && activeTab !== "sync" && activeTab !== "hftest" ? "flex" : "none" }, className: "absolute inset-0 flex-col", children: /* @__PURE__ */ jsx23(PromptTab, { workspaceTags, onGenerate: handlePromptTabGenerate, isGenerating: isPromptTabGenerating, feedback: promptFeedback, promptResult: activePrompt || null, lastPayload: lastPromptPayload, onGenerateImage: (prompt) => {
5572
- handleGenerateImage(prompt);
5615
+ handleGenerateBatch(prompt);
5573
5616
  setMobileTab("stage");
5574
5617
  }, onTagCreate: handleTagCreate, onTagUpdate: handleTagUpdate, onTagDelete: handleTagDelete, onScanImage: handleScanImage, isScanning: isScanningImage }) }),
5575
5618
  activeTab === "setup" && /* @__PURE__ */ jsx23(SetupPanel, { onWorkspaceImport: handleWorkspaceImport, buildInfo }),
@@ -5649,7 +5692,9 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5649
5692
  /* @__PURE__ */ jsxs21("div", { style: { height: 52, borderBottom: "1px solid rgba(255,255,255,0.05)", display: "flex", alignItems: "center", gap: 8, padding: "0 12px", flexShrink: 0 }, children: [
5650
5693
  /* @__PURE__ */ jsx23(CompactDropdown, { value: aspectRatio, onChange: setAspectRatio, options: [{ label: "1:1", value: "1:1" }, { label: "16:9", value: "16:9" }, { label: "9:16", value: "9:16" }] }),
5651
5694
  /* @__PURE__ */ jsx23(CompactDropdown, { value: selectedModel, onChange: setSelectedModel, options: [{ value: "\u{1F34C} Nano Banana Pro", label: "\u{1F34C} Nano Banana Pro" }, { value: "\u{1F34C} Nano Banana 2", label: "\u{1F34C} Nano Banana 2" }, { value: "Imagen 4", label: "Imagen 4" }] }),
5695
+ /* @__PURE__ */ jsx23(CompactDropdown, { value: String(imageCount), displayValue: `${imageCount}\xD7`, onChange: updateImageCount, options: imageCountOptions }),
5652
5696
  /* @__PURE__ */ jsx23("div", { style: { flex: 1 } }),
5697
+ runningBadge,
5653
5698
  /* @__PURE__ */ jsx23("button", { onClick: toggleContrast, style: { color: "rgba(255,255,255,0.2)", background: "none", border: "none", cursor: "pointer", padding: 4, lineHeight: 0 }, children: /* @__PURE__ */ jsx23("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: highContrast ? "light_mode" : "dark_mode" }) }),
5654
5699
  /* @__PURE__ */ jsx23("button", { onClick: () => setShowStart(true), style: { color: "rgba(255,255,255,0.2)", background: "none", border: "none", cursor: "pointer", padding: 4, lineHeight: 0 }, children: /* @__PURE__ */ jsx23("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: "apps" }) })
5655
5700
  ] }),
@@ -5665,22 +5710,19 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5665
5710
  ),
5666
5711
  activePrompt && /* @__PURE__ */ jsx23("button", { onClick: () => setActivePrompt(""), style: { position: "absolute", top: 6, right: 6, width: 22, height: 22, display: "flex", alignItems: "center", justifyContent: "center", color: "rgba(255,255,255,0.2)", background: "none", border: "none", cursor: "pointer", padding: 0 }, children: /* @__PURE__ */ jsx23("span", { className: "material-symbols-outlined", style: { fontSize: 15 }, children: "close" }) })
5667
5712
  ] }) }),
5668
- /* @__PURE__ */ jsx23("div", { style: { padding: "0 12px 10px", flexShrink: 0 }, children: /* @__PURE__ */ jsx23(
5713
+ /* @__PURE__ */ jsx23("div", { style: { padding: "0 12px 10px", flexShrink: 0 }, children: /* @__PURE__ */ jsxs21(
5669
5714
  "button",
5670
5715
  {
5671
- onClick: () => handleGenerateImage(),
5672
- disabled: !activePrompt.trim() || isGenerating,
5673
- style: { width: "100%", height: 42, display: "flex", alignItems: "center", justifyContent: "center", gap: 8, borderRadius: 10, fontWeight: "bold", fontSize: 13, textTransform: "uppercase", letterSpacing: "0.05em", border: "1px solid rgba(255,255,255,0.1)", background: activePrompt.trim() && !isGenerating ? "#0284c7" : "transparent", color: "#fff", cursor: activePrompt.trim() && !isGenerating ? "pointer" : "default", opacity: !activePrompt.trim() || isGenerating ? 0.3 : 1, fontFamily: "inherit", transition: "background 0.2s" },
5674
- children: isGenerating ? /* @__PURE__ */ jsxs21(Fragment9, { children: [
5675
- /* @__PURE__ */ jsx23("div", { style: { width: 14, height: 14, borderTop: "2px solid #fff", borderRadius: "50%", animation: "spin 1s linear infinite" } }),
5676
- /* @__PURE__ */ jsx23("span", { children: "Generiere..." })
5677
- ] }) : /* @__PURE__ */ jsxs21(Fragment9, { children: [
5716
+ onClick: () => handleGenerateBatch(),
5717
+ disabled: !activePrompt.trim(),
5718
+ style: { width: "100%", height: 42, display: "flex", alignItems: "center", justifyContent: "center", gap: 8, borderRadius: 10, fontWeight: "bold", fontSize: 13, textTransform: "uppercase", letterSpacing: "0.05em", border: "1px solid rgba(255,255,255,0.1)", background: activePrompt.trim() ? "#0284c7" : "transparent", color: "#fff", cursor: activePrompt.trim() ? "pointer" : "default", opacity: !activePrompt.trim() ? 0.3 : 1, fontFamily: "inherit", transition: "background 0.2s" },
5719
+ children: [
5678
5720
  /* @__PURE__ */ jsx23("span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: "bolt" }),
5679
5721
  /* @__PURE__ */ jsx23("span", { children: "Generieren" })
5680
- ] })
5722
+ ]
5681
5723
  }
5682
5724
  ) }),
5683
- /* @__PURE__ */ jsx23("div", { style: { flex: 1, overflow: "hidden", position: "relative" }, children: /* @__PURE__ */ jsx23(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)) }) })
5725
+ /* @__PURE__ */ jsx23("div", { style: { flex: 1, overflow: "hidden", position: "relative" }, children: /* @__PURE__ */ jsx23(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)), visibleCount: historyVisibleCount, onLoadMore: () => setHistoryVisibleCount((c) => c + 20) }) })
5684
5726
  ] }),
5685
5727
  /* @__PURE__ */ jsxs21("div", { style: { flex: 1, height: tlH, display: "flex", flexDirection: "column", background: "#0b0b0b" }, children: [
5686
5728
  /* @__PURE__ */ jsx23(
@@ -5696,9 +5738,9 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5696
5738
  setTouchStartX(null);
5697
5739
  },
5698
5740
  children: /* @__PURE__ */ jsxs21("div", { style: { height: "100%", width: "100%", borderRadius: 20, border: "1px solid rgba(255,255,255,0.05)", background: "rgba(0,0,0,0.4)", position: "relative", overflow: "hidden", display: "flex", alignItems: "center", justifyContent: "center" }, children: [
5699
- currentResult?.status === "processing" && /* @__PURE__ */ jsxs21("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 12 }, children: [
5700
- /* @__PURE__ */ jsx23("div", { style: { width: 36, height: 36, borderTop: "2px solid #fff", borderRadius: "50%", animation: "spin 1s linear infinite" } }),
5701
- /* @__PURE__ */ jsx23("span", { style: { fontSize: 10, color: "rgba(255,255,255,0.4)", textTransform: "uppercase", fontWeight: "bold", letterSpacing: "0.15em" }, children: "Erstelle Bild..." })
5741
+ currentResult?.status === "processing" && /* @__PURE__ */ jsxs21("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 12, opacity: 0.4 }, children: [
5742
+ /* @__PURE__ */ jsx23("span", { className: "material-symbols-outlined", style: { fontSize: 36 }, children: "hourglass_top" }),
5743
+ /* @__PURE__ */ jsx23("span", { style: { fontSize: 10, color: "rgba(255,255,255,0.6)", textTransform: "uppercase", fontWeight: "bold", letterSpacing: "0.15em" }, children: "Erstelle Bild..." })
5702
5744
  ] }),
5703
5745
  currentResult?.status === "error" && /* @__PURE__ */ jsxs21("div", { style: { padding: 24, textAlign: "center", display: "flex", flexDirection: "column", alignItems: "center", gap: 12 }, children: [
5704
5746
  /* @__PURE__ */ jsx23("span", { className: "material-symbols-outlined", style: { fontSize: 32, color: "#f87171" }, children: "warning" }),
@@ -5728,7 +5770,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5728
5770
  /* @__PURE__ */ jsx23("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "replay" }),
5729
5771
  /* @__PURE__ */ jsx23("span", { children: "Prompt" })
5730
5772
  ] }),
5731
- /* @__PURE__ */ jsxs21("button", { onClick: () => handleGenerateImage(currentResult.prompt || activePrompt, currentResult.mediaId, void 0, { silent: true }), style: { flex: 1, height: 40, display: "flex", alignItems: "center", justifyContent: "center", gap: 6, borderRadius: 10, border: "none", background: "rgba(255,255,255,0.1)", color: "rgba(255,255,255,0.8)", fontSize: 11, fontWeight: "bold", cursor: "pointer", fontFamily: "inherit" }, children: [
5773
+ /* @__PURE__ */ jsxs21("button", { onClick: () => handleGenerateBatch(currentResult.prompt || activePrompt, currentResult.mediaId, void 0, { silent: true }), style: { flex: 1, height: 40, display: "flex", alignItems: "center", justifyContent: "center", gap: 6, borderRadius: 10, border: "none", background: "rgba(255,255,255,0.1)", color: "rgba(255,255,255,0.8)", fontSize: 11, fontWeight: "bold", cursor: "pointer", fontFamily: "inherit" }, children: [
5732
5774
  /* @__PURE__ */ jsx23("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "auto_fix_high" }),
5733
5775
  /* @__PURE__ */ jsx23("span", { children: "Referenz" })
5734
5776
  ] }),
@@ -5798,7 +5840,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5798
5840
  isGeneratingNodeId: (id) => isSynthesizing && focusedNodeId === id
5799
5841
  }
5800
5842
  ) }),
5801
- leftTab === "prompt" && workspaceTags && activeTab !== "tags" && /* @__PURE__ */ jsx23(PromptTab, { workspaceTags, onGenerate: handlePromptTabGenerate, isGenerating: isPromptTabGenerating, feedback: promptFeedback, promptResult: activePrompt || null, lastPayload: lastPromptPayload, onGenerateImage: (prompt) => handleGenerateImage(prompt), onTagCreate: handleTagCreate, onTagUpdate: handleTagUpdate, onTagDelete: handleTagDelete, onScanImage: handleScanImage, isScanning: isScanningImage })
5843
+ leftTab === "prompt" && workspaceTags && activeTab !== "tags" && /* @__PURE__ */ jsx23(PromptTab, { workspaceTags, onGenerate: handlePromptTabGenerate, isGenerating: isPromptTabGenerating, feedback: promptFeedback, promptResult: activePrompt || null, lastPayload: lastPromptPayload, onGenerateImage: (prompt) => handleGenerateBatch(prompt), onTagCreate: handleTagCreate, onTagUpdate: handleTagUpdate, onTagDelete: handleTagDelete, onScanImage: handleScanImage, isScanning: isScanningImage })
5802
5844
  ] })
5803
5845
  ] }),
5804
5846
  !isLeftCollapsed && /* @__PURE__ */ jsx23("div", { onMouseDown: startLeftResize, className: "w-1 shrink-0 cursor-col-resize hover:bg-white/20 active:bg-white/30 transition-colors", style: { background: "transparent" } }),
@@ -5806,7 +5848,8 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5806
5848
  /* @__PURE__ */ jsxs21("div", { className: "h-14 border-b border-white/5 flex items-center px-4 gap-2 justify-between shrink-0 bg-black/20", children: [
5807
5849
  /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-1.5", children: [
5808
5850
  /* @__PURE__ */ jsx23(CompactDropdown, { value: aspectRatio, onChange: setAspectRatio, options: [{ label: "1:1", value: "1:1" }, { label: "16:9", value: "16:9" }, { label: "9:16", value: "9:16" }] }),
5809
- /* @__PURE__ */ jsx23(CompactDropdown, { value: selectedModel, onChange: setSelectedModel, options: [{ value: "\u{1F34C} Nano Banana Pro", label: "\u{1F34C} Nano Banana Pro" }, { value: "\u{1F34C} Nano Banana 2", label: "\u{1F34C} Nano Banana 2" }, { value: "Imagen 4", label: "Imagen 4" }] })
5851
+ /* @__PURE__ */ jsx23(CompactDropdown, { value: selectedModel, onChange: setSelectedModel, options: [{ value: "\u{1F34C} Nano Banana Pro", label: "\u{1F34C} Nano Banana Pro" }, { value: "\u{1F34C} Nano Banana 2", label: "\u{1F34C} Nano Banana 2" }, { value: "Imagen 4", label: "Imagen 4" }] }),
5852
+ /* @__PURE__ */ jsx23(CompactDropdown, { value: String(imageCount), displayValue: `${imageCount}\xD7`, onChange: updateImageCount, options: imageCountOptions })
5810
5853
  ] }),
5811
5854
  /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-1 mx-auto", children: [
5812
5855
  /* @__PURE__ */ jsx23(
@@ -5836,7 +5879,8 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5836
5879
  /* @__PURE__ */ jsx23("span", { children: "Ref" })
5837
5880
  ] }),
5838
5881
  /* @__PURE__ */ jsx23("button", { onClick: () => setIsPromptCollapsed(!isPromptCollapsed), className: "text-white/40 hover:text-white transition-colors", children: /* @__PURE__ */ jsx23("span", { className: "material-symbols-outlined", children: isPromptCollapsed ? "expand_more" : "expand_less" }) }),
5839
- /* @__PURE__ */ jsx23(PillButton, { variant: "solid", icon: "bolt", loading: isGenerating, disabled: !activePrompt.trim(), onClick: () => handleGenerateImage(), children: "Generieren" })
5882
+ runningBadge,
5883
+ /* @__PURE__ */ jsx23(PillButton, { variant: "solid", icon: "bolt", disabled: !activePrompt.trim(), onClick: () => handleGenerateBatch(), children: "Generieren" })
5840
5884
  ] })
5841
5885
  ] }),
5842
5886
  /* @__PURE__ */ jsxs21("div", { className: "flex-1 flex flex-col overflow-hidden relative", children: [
@@ -5848,33 +5892,27 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5848
5892
  const frame = item.frames[0];
5849
5893
  if (frame?.base64) setCurrentResult(frameToGeneration(frame, item));
5850
5894
  } }) }) : /* @__PURE__ */ jsxs21("div", { className: "flex-1 overflow-hidden flex flex-col", children: [
5851
- /* @__PURE__ */ jsx23("div", { className: "flex-1 p-6 overflow-hidden flex items-center justify-center", children: /* @__PURE__ */ jsxs21("div", { className: "h-full w-full max-w-4xl aspect-square rounded-3xl border border-white/5 bg-black/40 relative overflow-hidden flex items-center justify-center group shadow-2xl", children: [
5852
- isGenerating && currentResult?.status === "done" && /* @__PURE__ */ jsxs21("div", { className: "absolute top-6 right-6 z-30 bg-black/60 backdrop-blur-md px-4 py-2 rounded-full border border-white/10 flex items-center gap-3", children: [
5853
- /* @__PURE__ */ jsx23("div", { className: "w-3 h-3 border-t-2 border-white rounded-full animate-spin" }),
5854
- /* @__PURE__ */ jsx23("span", { className: "text-[10px] text-white/60 uppercase font-bold tracking-widest", children: "Neue Referenz..." })
5895
+ /* @__PURE__ */ jsx23("div", { className: "flex-1 p-6 overflow-hidden flex items-center justify-center", children: /* @__PURE__ */ jsx23("div", { className: "h-full w-full max-w-4xl aspect-square rounded-3xl border border-white/5 bg-black/40 relative overflow-hidden flex items-center justify-center group shadow-2xl", children: currentResult ? currentResult.status === "processing" ? /* @__PURE__ */ jsxs21("div", { className: "flex flex-col items-center gap-4 opacity-40", children: [
5896
+ /* @__PURE__ */ jsx23("span", { className: "material-symbols-outlined text-[40px]", children: "hourglass_top" }),
5897
+ /* @__PURE__ */ jsx23("span", { className: "text-[10px] uppercase font-bold tracking-widest", children: "Erstelle Bild..." })
5898
+ ] }) : currentResult.status === "error" ? /* @__PURE__ */ jsxs21("div", { className: "p-10 text-center flex flex-col items-center gap-5 max-w-md", children: [
5899
+ /* @__PURE__ */ jsx23("div", { className: "w-16 h-16 rounded-full bg-red-500/10 flex items-center justify-center", children: /* @__PURE__ */ jsx23("span", { className: "material-symbols-outlined text-red-500 text-[32px]", children: "warning" }) }),
5900
+ /* @__PURE__ */ jsxs21("div", { className: "flex flex-col gap-2", children: [
5901
+ /* @__PURE__ */ jsx23("h3", { className: "text-[11px] font-bold uppercase tracking-widest text-red-400", children: "Generierungsfehler" }),
5902
+ /* @__PURE__ */ jsx23("p", { className: "text-white/60 text-[12px] leading-relaxed", children: currentResult.error?.message })
5855
5903
  ] }),
5856
- currentResult ? currentResult.status === "processing" ? /* @__PURE__ */ jsxs21("div", { className: "flex flex-col items-center gap-4", children: [
5857
- /* @__PURE__ */ jsx23("div", { className: "w-10 h-10 border-t-2 border-white rounded-full animate-spin" }),
5858
- /* @__PURE__ */ jsx23("span", { className: "text-[10px] text-white/40 uppercase font-bold tracking-widest", children: "Erstelle Bild..." })
5859
- ] }) : currentResult.status === "error" ? /* @__PURE__ */ jsxs21("div", { className: "p-10 text-center flex flex-col items-center gap-5 max-w-md", children: [
5860
- /* @__PURE__ */ jsx23("div", { className: "w-16 h-16 rounded-full bg-red-500/10 flex items-center justify-center", children: /* @__PURE__ */ jsx23("span", { className: "material-symbols-outlined text-red-500 text-[32px]", children: "warning" }) }),
5861
- /* @__PURE__ */ jsxs21("div", { className: "flex flex-col gap-2", children: [
5862
- /* @__PURE__ */ jsx23("h3", { className: "text-[11px] font-bold uppercase tracking-widest text-red-400", children: "Generierungsfehler" }),
5863
- /* @__PURE__ */ jsx23("p", { className: "text-white/60 text-[12px] leading-relaxed", children: currentResult.error?.message })
5864
- ] }),
5865
- /* @__PURE__ */ jsx23(PillButton, { variant: "outline", icon: "refresh", onClick: () => handleGenerateImage(currentResult.prompt), children: "Erneut versuchen" })
5866
- ] }) : /* @__PURE__ */ jsxs21("div", { className: "h-full w-full relative flex items-center justify-center", children: [
5867
- /* @__PURE__ */ jsx23("img", { src: currentResult.fullBase64 || currentResult.base64, className: "max-h-full max-w-full object-contain rounded-xl shadow-2xl" }),
5868
- /* @__PURE__ */ jsxs21("div", { className: "absolute bottom-6 flex gap-2 opacity-0 group-hover:opacity-100 transition-all translate-y-4 group-hover:translate-y-0 z-20", children: [
5869
- /* @__PURE__ */ jsx23(PillButton, { variant: "outline", icon: "replay", onClick: () => setActivePrompt(currentResult.prompt || ""), children: "Prompt" }),
5870
- /* @__PURE__ */ jsx23(PillButton, { variant: "solid", icon: "auto_fix_high", onClick: () => handleGenerateImage(currentResult.prompt || activePrompt, currentResult.mediaId, void 0, { silent: true }), children: "Referenz" }),
5871
- /* @__PURE__ */ jsx23(PillButton, { variant: "outline", icon: "download", onClick: handleDownloadSingle, children: "Speichern" })
5872
- ] })
5873
- ] }) : /* @__PURE__ */ jsxs21("div", { className: "flex flex-col items-center gap-2 opacity-10", children: [
5874
- /* @__PURE__ */ jsx23("span", { className: "material-symbols-outlined text-[100px]", children: "palette" }),
5875
- /* @__PURE__ */ jsx23("span", { className: "text-[12px] font-bold uppercase tracking-[0.2em]", children: "Avatar Architect" })
5904
+ /* @__PURE__ */ jsx23(PillButton, { variant: "outline", icon: "refresh", onClick: () => handleGenerateImage(currentResult.prompt), children: "Erneut versuchen" })
5905
+ ] }) : /* @__PURE__ */ jsxs21("div", { className: "h-full w-full relative flex items-center justify-center", children: [
5906
+ /* @__PURE__ */ jsx23("img", { src: currentResult.fullBase64 || currentResult.base64, className: "max-h-full max-w-full object-contain rounded-xl shadow-2xl" }),
5907
+ /* @__PURE__ */ jsxs21("div", { className: "absolute bottom-6 flex gap-2 opacity-0 group-hover:opacity-100 transition-all translate-y-4 group-hover:translate-y-0 z-20", children: [
5908
+ /* @__PURE__ */ jsx23(PillButton, { variant: "outline", icon: "replay", onClick: () => setActivePrompt(currentResult.prompt || ""), children: "Prompt" }),
5909
+ /* @__PURE__ */ jsx23(PillButton, { variant: "solid", icon: "auto_fix_high", onClick: () => handleGenerateBatch(currentResult.prompt || activePrompt, currentResult.mediaId, void 0, { silent: true }), children: "Referenz" }),
5910
+ /* @__PURE__ */ jsx23(PillButton, { variant: "outline", icon: "download", onClick: handleDownloadSingle, children: "Speichern" })
5876
5911
  ] })
5877
- ] }) }),
5912
+ ] }) : /* @__PURE__ */ jsxs21("div", { className: "flex flex-col items-center gap-2 opacity-10", children: [
5913
+ /* @__PURE__ */ jsx23("span", { className: "material-symbols-outlined text-[100px]", children: "palette" }),
5914
+ /* @__PURE__ */ jsx23("span", { className: "text-[12px] font-bold uppercase tracking-[0.2em]", children: "Avatar Architect" })
5915
+ ] }) }) }),
5878
5916
  currentResult?.status === "done" && currentGroup.length > 1 && /* @__PURE__ */ jsx23("div", { className: "px-6 pb-4 shrink-0 flex gap-2 overflow-x-auto", style: { scrollbarWidth: "none" }, children: currentGroup.map((item) => /* @__PURE__ */ jsxs21("div", { style: { position: "relative", flexShrink: 0 }, children: [
5879
5917
  /* @__PURE__ */ jsx23(
5880
5918
  "div",
@@ -5956,7 +5994,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5956
5994
  /* @__PURE__ */ jsx23("span", { className: "material-symbols-outlined text-[40px] text-white/10 block mb-3", children: "label_off" }),
5957
5995
  /* @__PURE__ */ jsx23("p", { className: "text-[11px] text-white/20", children: "Erst Workspace importieren um Tags zu verwalten." })
5958
5996
  ] }) }),
5959
- activeTab === "history" && /* @__PURE__ */ jsx23(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)) }),
5997
+ activeTab === "history" && /* @__PURE__ */ jsx23(HistoryPanel, { history, currentResultId: currentResult?.id || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)), visibleCount: historyVisibleCount, onLoadMore: () => setHistoryVisibleCount((c) => c + 20) }),
5960
5998
  activeTab === "gallery" && /* @__PURE__ */ jsx23(
5961
5999
  MediaLibrary,
5962
6000
  {
@@ -5968,7 +6006,9 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5968
6006
  },
5969
6007
  onDelete: (id) => setGalleryItems((g) => g.filter((x) => x.id !== id)),
5970
6008
  onSelect: handleGallerySelect,
5971
- onGenerateReference: (item) => handleGenerateImage(item.prompt || activePrompt, item.mediaId, void 0, { silent: true })
6009
+ onGenerateReference: (item) => handleGenerateBatch(item.prompt || activePrompt, item.mediaId, void 0, { silent: true }),
6010
+ visibleCount: galleryVisibleCount,
6011
+ onLoadMore: () => setGalleryVisibleCount((c) => c + 20)
5972
6012
  }
5973
6013
  ),
5974
6014
  activeTab === "inspect" && /* @__PURE__ */ jsx23(InspectPanel, { currentResult, history, onSelect: setCurrentResult }),
@@ -6004,7 +6044,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6004
6044
  }
6005
6045
 
6006
6046
  // src/components/FaApp.tsx
6007
- import { useState as useState21, useEffect as useEffect8 } from "react";
6047
+ import { useState as useState19, useEffect as useEffect8 } from "react";
6008
6048
  import { jsx as jsx24 } from "react/jsx-runtime";
6009
6049
  function FaApp({
6010
6050
  onGenerateImage,
@@ -6024,7 +6064,7 @@ function FaApp({
6024
6064
  onServerDelete,
6025
6065
  buildInfo
6026
6066
  }) {
6027
- const [hfNamespace, setHfNamespace] = useState21(void 0);
6067
+ const [hfNamespace, setHfNamespace] = useState19(void 0);
6028
6068
  useEffect8(() => {
6029
6069
  if (!serverBaseUrl) return;
6030
6070
  fetch(`${serverBaseUrl}/api/status`).then((r) => r.json()).then((d) => {
@@ -6057,7 +6097,7 @@ function FaApp({
6057
6097
  }
6058
6098
 
6059
6099
  // src/index.ts
6060
- var LIB_VERSION = "2.0.57";
6100
+ var LIB_VERSION = "2.0.61";
6061
6101
  export {
6062
6102
  AvatarArchitectApp,
6063
6103
  CollapsibleCard,