@rslsp1/fa-app-tools 1.2.1 → 1.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.d.mts CHANGED
@@ -445,6 +445,6 @@ declare function buildLoopInstruction(rounds: Array<{
445
445
  declare function autoLabel(index: number): string;
446
446
  declare function buildReferenceImageMediaIds(images: SelectedLabImage[]): string[];
447
447
 
448
- declare const LIB_VERSION = "1.2.1";
448
+ declare const LIB_VERSION = "1.2.3";
449
449
 
450
450
  export { AvatarArchitectApp, type AvatarArchitectAppProps, CollapsibleCard, CompactDropdown, type ExtractedCharacter, FaToolsBadge, type FlowSdk, GLOBAL_STYLES, type Generation, HistoryPanel, InspectPanel, LIB_VERSION, LabBlend, LabCompare, type LabFrame, LabImagePicker, type LabItem, LabLoop, LabRemix, type LabServices, LabsTab, ListView, type MediaItem, MediaLibrary, PillButton, type ProjectMeta, type ProjectSettings, ProjectSyncTab, PromptTab, SectionLabel, type SelectedLabImage, type SelectedTag, SetupPanel, type SyncDiff, TagManagerPanel, type TagOption, type WorkspaceTags, autoLabel, buildBlendInstruction, buildCompareInstruction, buildFallbackPrompt, buildGenerationPrompt, buildImageGenerationOptions, buildLoopInstruction, buildPromptTabPayload, buildReferenceImageMediaIds, buildRemixInstruction, buildScanInstruction, cleanAiResponse, createFlowServices, exportProjectToZip, formatTreeToMarkdown, frameToGeneration, getFormattedTimestamp, groupGenerationsToLabItems, importProjectFromZip, injectXMPMetadata, interpretSdkError, parsePromptFile, parsePromptResponse, useKeyboardNavigation, useOnClickOutside };
package/dist/index.d.ts CHANGED
@@ -445,6 +445,6 @@ declare function buildLoopInstruction(rounds: Array<{
445
445
  declare function autoLabel(index: number): string;
446
446
  declare function buildReferenceImageMediaIds(images: SelectedLabImage[]): string[];
447
447
 
448
- declare const LIB_VERSION = "1.2.1";
448
+ declare const LIB_VERSION = "1.2.3";
449
449
 
450
450
  export { AvatarArchitectApp, type AvatarArchitectAppProps, CollapsibleCard, CompactDropdown, type ExtractedCharacter, FaToolsBadge, type FlowSdk, GLOBAL_STYLES, type Generation, HistoryPanel, InspectPanel, LIB_VERSION, LabBlend, LabCompare, type LabFrame, LabImagePicker, type LabItem, LabLoop, LabRemix, type LabServices, LabsTab, ListView, type MediaItem, MediaLibrary, PillButton, type ProjectMeta, type ProjectSettings, ProjectSyncTab, PromptTab, SectionLabel, type SelectedLabImage, type SelectedTag, SetupPanel, type SyncDiff, TagManagerPanel, type TagOption, type WorkspaceTags, autoLabel, buildBlendInstruction, buildCompareInstruction, buildFallbackPrompt, buildGenerationPrompt, buildImageGenerationOptions, buildLoopInstruction, buildPromptTabPayload, buildReferenceImageMediaIds, buildRemixInstruction, buildScanInstruction, cleanAiResponse, createFlowServices, exportProjectToZip, formatTreeToMarkdown, frameToGeneration, getFormattedTimestamp, groupGenerationsToLabItems, importProjectFromZip, injectXMPMetadata, interpretSdkError, parsePromptFile, parsePromptResponse, useKeyboardNavigation, useOnClickOutside };
package/dist/index.js CHANGED
@@ -738,33 +738,52 @@ var InspectPanel = ({ currentResult, history, onSelect, workspaceTags, onTagTogg
738
738
  var import_react7 = require("react");
739
739
  var import_react8 = require("motion/react");
740
740
  var import_jsx_runtime7 = require("react/jsx-runtime");
741
+ var PRESET_URLS = [
742
+ "https://jsonplaceholder.typicode.com/todos/1",
743
+ "https://huggingface.co/api/whoami-v2",
744
+ "https://esm.sh/@rslsp1/fa-app-tools@latest"
745
+ ];
741
746
  var SetupPanel = ({ onWorkspaceImport, buildInfo }) => {
742
747
  const workspaceInputRef = (0, import_react7.useRef)(null);
743
748
  const [urlInput, setUrlInput] = (0, import_react7.useState)("");
744
- const [urlStatus, setUrlStatus] = (0, import_react7.useState)("idle");
745
- const [urlThumb, setUrlThumb] = (0, import_react7.useState)(null);
746
- const [urlError, setUrlError] = (0, import_react7.useState)(null);
747
- const handleUrlTest = async () => {
748
- if (!urlInput.trim()) return;
749
- setUrlStatus("loading");
750
- setUrlThumb(null);
751
- setUrlError(null);
749
+ const [testStatus, setTestStatus] = (0, import_react7.useState)("idle");
750
+ const [result, setResult] = (0, import_react7.useState)(null);
751
+ const [fetchError, setFetchError] = (0, import_react7.useState)(null);
752
+ const runTest = async (url) => {
753
+ if (!url.trim()) return;
754
+ setTestStatus("loading");
755
+ setResult(null);
756
+ setFetchError(null);
757
+ const t0 = Date.now();
752
758
  try {
753
- const res = await fetch(urlInput.trim());
754
- if (!res.ok) throw new Error(`HTTP ${res.status} ${res.statusText}`);
755
- const blob = await res.blob();
756
- const mimeType = blob.type || "image/jpeg";
757
- const dataUrl = await new Promise((resolve, reject) => {
758
- const reader = new FileReader();
759
- reader.onload = () => resolve(reader.result);
760
- reader.onerror = () => reject(new Error("FileReader failed"));
761
- reader.readAsDataURL(blob);
759
+ const res = await fetch(url.trim());
760
+ const durationMs = Date.now() - t0;
761
+ const contentType = res.headers.get("content-type") || "";
762
+ const headers = {};
763
+ res.headers.forEach((v, k) => {
764
+ headers[k] = v;
762
765
  });
763
- setUrlThumb(dataUrl);
764
- setUrlStatus("ok");
766
+ const blob = await res.blob();
767
+ const bodySize = blob.size;
768
+ const isImage = contentType.startsWith("image/");
769
+ let bodyPreview = "";
770
+ let imageDataUrl;
771
+ if (isImage) {
772
+ imageDataUrl = await new Promise((resolve, reject) => {
773
+ const reader = new FileReader();
774
+ reader.onload = () => resolve(reader.result);
775
+ reader.onerror = reject;
776
+ reader.readAsDataURL(blob);
777
+ });
778
+ } else {
779
+ const text = await blob.text();
780
+ bodyPreview = text.slice(0, 500);
781
+ }
782
+ setResult({ status: res.status, statusText: res.statusText, contentType, headers, bodyPreview, isImage, imageDataUrl, bodySize, durationMs });
783
+ setTestStatus("ok");
765
784
  } catch (e) {
766
- setUrlError(e.message || String(e));
767
- setUrlStatus("error");
785
+ setFetchError(e.message || String(e));
786
+ setTestStatus("error");
768
787
  }
769
788
  };
770
789
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react8.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, className: "absolute inset-0 p-6 flex flex-col gap-10 overflow-y-auto", children: [
@@ -782,40 +801,87 @@ var SetupPanel = ({ onWorkspaceImport, buildInfo }) => {
782
801
  ] }),
783
802
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-3", children: [
784
803
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-1", children: [
785
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SectionLabel, { children: "URL-Fetch Test" }),
786
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-[9px] text-white/30 px-2 italic", children: "Pr\xFCft ob externe URLs als Bild geladen werden k\xF6nnen." })
804
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SectionLabel, { children: "URL Fetch Diagnose" }),
805
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-[9px] text-white/30 px-2 italic", children: "Testet ob fetch() auf externe URLs funktioniert." })
787
806
  ] }),
807
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex flex-col gap-1", children: PRESET_URLS.map((u) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
808
+ "button",
809
+ {
810
+ onClick: () => {
811
+ setUrlInput(u);
812
+ runTest(u);
813
+ },
814
+ className: "text-left px-2 py-1 rounded bg-white/3 border border-white/5 text-[9px] text-white/40 hover:text-white/70 hover:bg-white/6 font-mono truncate transition",
815
+ children: u
816
+ },
817
+ u
818
+ )) }),
788
819
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex gap-2", children: [
789
820
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
790
821
  "input",
791
822
  {
792
823
  value: urlInput,
793
824
  onChange: (e) => setUrlInput(e.target.value),
794
- onKeyDown: (e) => e.key === "Enter" && handleUrlTest(),
795
- placeholder: "https://example.com/image.jpg",
796
- className: "flex-1 bg-white/5 border border-white/10 rounded-xl px-3 py-2 text-[11px] text-white/80 outline-none focus:border-white/20 placeholder:text-white/20"
825
+ onKeyDown: (e) => e.key === "Enter" && runTest(urlInput),
826
+ placeholder: "https://...",
827
+ className: "flex-1 bg-white/5 border border-white/10 rounded-xl px-3 py-2 text-[11px] text-white/80 outline-none focus:border-white/20 placeholder:text-white/20 font-mono"
797
828
  }
798
829
  ),
799
830
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
800
831
  "button",
801
832
  {
802
- onClick: handleUrlTest,
803
- disabled: urlStatus === "loading" || !urlInput.trim(),
804
- className: "px-3 py-2 bg-white/10 hover:bg-white/15 border border-white/10 rounded-xl text-[11px] font-bold text-white/60 transition disabled:opacity-40 shrink-0",
805
- children: urlStatus === "loading" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "material-symbols-outlined text-[16px] animate-spin", children: "sync" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "download" })
833
+ onClick: () => runTest(urlInput),
834
+ disabled: testStatus === "loading" || !urlInput.trim(),
835
+ className: "px-3 py-2 bg-white/10 hover:bg-white/15 border border-white/10 rounded-xl text-white/60 transition disabled:opacity-40 shrink-0",
836
+ children: testStatus === "loading" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "material-symbols-outlined text-[16px] animate-spin", children: "sync" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "material-symbols-outlined text-[16px]", children: "send" })
806
837
  }
807
838
  )
808
839
  ] }),
809
- urlStatus === "ok" && urlThumb && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-2", children: [
810
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { src: urlThumb, alt: "URL Test", className: "w-full max-h-48 object-contain rounded-xl border border-white/10 bg-black/40" }),
811
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: "text-[10px] text-green-400 font-mono flex items-center gap-1", children: [
812
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "material-symbols-outlined text-[14px]", children: "check_circle" }),
813
- "Fetch erfolgreich"
840
+ testStatus === "ok" && result && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-2 bg-white/3 border border-white/8 rounded-xl p-3 text-[10px] font-mono", children: [
841
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", children: [
842
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: `font-bold ${result.status < 400 ? "text-green-400" : "text-red-400"}`, children: [
843
+ result.status,
844
+ " ",
845
+ result.statusText
846
+ ] }),
847
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-white/30", children: "\xB7" }),
848
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "text-white/50", children: [
849
+ result.durationMs,
850
+ "ms"
851
+ ] }),
852
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-white/30", children: "\xB7" }),
853
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "text-white/50", children: [
854
+ (result.bodySize / 1024).toFixed(1),
855
+ " KB"
856
+ ] })
857
+ ] }),
858
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "text-white/40", children: [
859
+ "Content-Type: ",
860
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-white/70", children: result.contentType })
861
+ ] }),
862
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("details", { className: "cursor-pointer", children: [
863
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("summary", { className: "text-white/30 hover:text-white/60 transition", children: [
864
+ "Headers (",
865
+ Object.keys(result.headers).length,
866
+ ")"
867
+ ] }),
868
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "mt-1 space-y-0.5 pl-2 border-l border-white/10", children: Object.entries(result.headers).map(([k, v]) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "text-white/30", children: [
869
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "text-white/50", children: [
870
+ k,
871
+ ":"
872
+ ] }),
873
+ " ",
874
+ v
875
+ ] }, k)) })
876
+ ] }),
877
+ result.isImage && result.imageDataUrl ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { src: result.imageDataUrl, alt: "response", className: "w-full max-h-40 object-contain rounded-lg border border-white/10 bg-black/40 mt-1" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("pre", { className: "text-white/60 whitespace-pre-wrap break-all bg-black/30 rounded-lg p-2 max-h-40 overflow-y-auto text-[9px]", children: [
878
+ result.bodyPreview,
879
+ result.bodySize > 500 ? "\n\u2026" : ""
814
880
  ] })
815
881
  ] }),
816
- urlStatus === "error" && urlError && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: "text-[10px] text-red-400 font-mono flex items-start gap-1", children: [
817
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "material-symbols-outlined text-[14px] shrink-0", children: "error" }),
818
- urlError
882
+ testStatus === "error" && fetchError && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "bg-red-900/20 border border-red-700/30 rounded-xl p-3 text-[10px] font-mono text-red-400 flex items-start gap-2", children: [
883
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "material-symbols-outlined text-[14px] shrink-0 mt-0.5", children: "error" }),
884
+ fetchError
819
885
  ] })
820
886
  ] }),
821
887
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "mt-auto p-4 bg-white/5 rounded-2xl border border-white/5 flex flex-col gap-2 opacity-50", children: [
@@ -4177,7 +4243,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4177
4243
  }
4178
4244
 
4179
4245
  // src/index.ts
4180
- var LIB_VERSION = "1.2.1";
4246
+ var LIB_VERSION = "1.2.3";
4181
4247
  // Annotate the CommonJS export names for ESM import in node:
4182
4248
  0 && (module.exports = {
4183
4249
  AvatarArchitectApp,
package/dist/index.mjs CHANGED
@@ -656,33 +656,52 @@ var InspectPanel = ({ currentResult, history, onSelect, workspaceTags, onTagTogg
656
656
  import { useRef as useRef2, useState as useState2 } from "react";
657
657
  import { motion as motion3 } from "motion/react";
658
658
  import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
659
+ var PRESET_URLS = [
660
+ "https://jsonplaceholder.typicode.com/todos/1",
661
+ "https://huggingface.co/api/whoami-v2",
662
+ "https://esm.sh/@rslsp1/fa-app-tools@latest"
663
+ ];
659
664
  var SetupPanel = ({ onWorkspaceImport, buildInfo }) => {
660
665
  const workspaceInputRef = useRef2(null);
661
666
  const [urlInput, setUrlInput] = useState2("");
662
- const [urlStatus, setUrlStatus] = useState2("idle");
663
- const [urlThumb, setUrlThumb] = useState2(null);
664
- const [urlError, setUrlError] = useState2(null);
665
- const handleUrlTest = async () => {
666
- if (!urlInput.trim()) return;
667
- setUrlStatus("loading");
668
- setUrlThumb(null);
669
- setUrlError(null);
667
+ const [testStatus, setTestStatus] = useState2("idle");
668
+ const [result, setResult] = useState2(null);
669
+ const [fetchError, setFetchError] = useState2(null);
670
+ const runTest = async (url) => {
671
+ if (!url.trim()) return;
672
+ setTestStatus("loading");
673
+ setResult(null);
674
+ setFetchError(null);
675
+ const t0 = Date.now();
670
676
  try {
671
- const res = await fetch(urlInput.trim());
672
- if (!res.ok) throw new Error(`HTTP ${res.status} ${res.statusText}`);
673
- const blob = await res.blob();
674
- const mimeType = blob.type || "image/jpeg";
675
- const dataUrl = await new Promise((resolve, reject) => {
676
- const reader = new FileReader();
677
- reader.onload = () => resolve(reader.result);
678
- reader.onerror = () => reject(new Error("FileReader failed"));
679
- reader.readAsDataURL(blob);
677
+ const res = await fetch(url.trim());
678
+ const durationMs = Date.now() - t0;
679
+ const contentType = res.headers.get("content-type") || "";
680
+ const headers = {};
681
+ res.headers.forEach((v, k) => {
682
+ headers[k] = v;
680
683
  });
681
- setUrlThumb(dataUrl);
682
- setUrlStatus("ok");
684
+ const blob = await res.blob();
685
+ const bodySize = blob.size;
686
+ const isImage = contentType.startsWith("image/");
687
+ let bodyPreview = "";
688
+ let imageDataUrl;
689
+ if (isImage) {
690
+ imageDataUrl = await new Promise((resolve, reject) => {
691
+ const reader = new FileReader();
692
+ reader.onload = () => resolve(reader.result);
693
+ reader.onerror = reject;
694
+ reader.readAsDataURL(blob);
695
+ });
696
+ } else {
697
+ const text = await blob.text();
698
+ bodyPreview = text.slice(0, 500);
699
+ }
700
+ setResult({ status: res.status, statusText: res.statusText, contentType, headers, bodyPreview, isImage, imageDataUrl, bodySize, durationMs });
701
+ setTestStatus("ok");
683
702
  } catch (e) {
684
- setUrlError(e.message || String(e));
685
- setUrlStatus("error");
703
+ setFetchError(e.message || String(e));
704
+ setTestStatus("error");
686
705
  }
687
706
  };
688
707
  return /* @__PURE__ */ jsxs5(motion3.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, className: "absolute inset-0 p-6 flex flex-col gap-10 overflow-y-auto", children: [
@@ -700,40 +719,87 @@ var SetupPanel = ({ onWorkspaceImport, buildInfo }) => {
700
719
  ] }),
701
720
  /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-3", children: [
702
721
  /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-1", children: [
703
- /* @__PURE__ */ jsx7(SectionLabel, { children: "URL-Fetch Test" }),
704
- /* @__PURE__ */ jsx7("p", { className: "text-[9px] text-white/30 px-2 italic", children: "Pr\xFCft ob externe URLs als Bild geladen werden k\xF6nnen." })
722
+ /* @__PURE__ */ jsx7(SectionLabel, { children: "URL Fetch Diagnose" }),
723
+ /* @__PURE__ */ jsx7("p", { className: "text-[9px] text-white/30 px-2 italic", children: "Testet ob fetch() auf externe URLs funktioniert." })
705
724
  ] }),
725
+ /* @__PURE__ */ jsx7("div", { className: "flex flex-col gap-1", children: PRESET_URLS.map((u) => /* @__PURE__ */ jsx7(
726
+ "button",
727
+ {
728
+ onClick: () => {
729
+ setUrlInput(u);
730
+ runTest(u);
731
+ },
732
+ className: "text-left px-2 py-1 rounded bg-white/3 border border-white/5 text-[9px] text-white/40 hover:text-white/70 hover:bg-white/6 font-mono truncate transition",
733
+ children: u
734
+ },
735
+ u
736
+ )) }),
706
737
  /* @__PURE__ */ jsxs5("div", { className: "flex gap-2", children: [
707
738
  /* @__PURE__ */ jsx7(
708
739
  "input",
709
740
  {
710
741
  value: urlInput,
711
742
  onChange: (e) => setUrlInput(e.target.value),
712
- onKeyDown: (e) => e.key === "Enter" && handleUrlTest(),
713
- placeholder: "https://example.com/image.jpg",
714
- className: "flex-1 bg-white/5 border border-white/10 rounded-xl px-3 py-2 text-[11px] text-white/80 outline-none focus:border-white/20 placeholder:text-white/20"
743
+ onKeyDown: (e) => e.key === "Enter" && runTest(urlInput),
744
+ placeholder: "https://...",
745
+ className: "flex-1 bg-white/5 border border-white/10 rounded-xl px-3 py-2 text-[11px] text-white/80 outline-none focus:border-white/20 placeholder:text-white/20 font-mono"
715
746
  }
716
747
  ),
717
748
  /* @__PURE__ */ jsx7(
718
749
  "button",
719
750
  {
720
- onClick: handleUrlTest,
721
- disabled: urlStatus === "loading" || !urlInput.trim(),
722
- className: "px-3 py-2 bg-white/10 hover:bg-white/15 border border-white/10 rounded-xl text-[11px] font-bold text-white/60 transition disabled:opacity-40 shrink-0",
723
- children: urlStatus === "loading" ? /* @__PURE__ */ jsx7("span", { className: "material-symbols-outlined text-[16px] animate-spin", children: "sync" }) : /* @__PURE__ */ jsx7("span", { className: "material-symbols-outlined text-[16px]", children: "download" })
751
+ onClick: () => runTest(urlInput),
752
+ disabled: testStatus === "loading" || !urlInput.trim(),
753
+ className: "px-3 py-2 bg-white/10 hover:bg-white/15 border border-white/10 rounded-xl text-white/60 transition disabled:opacity-40 shrink-0",
754
+ children: testStatus === "loading" ? /* @__PURE__ */ jsx7("span", { className: "material-symbols-outlined text-[16px] animate-spin", children: "sync" }) : /* @__PURE__ */ jsx7("span", { className: "material-symbols-outlined text-[16px]", children: "send" })
724
755
  }
725
756
  )
726
757
  ] }),
727
- urlStatus === "ok" && urlThumb && /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-2", children: [
728
- /* @__PURE__ */ jsx7("img", { src: urlThumb, alt: "URL Test", className: "w-full max-h-48 object-contain rounded-xl border border-white/10 bg-black/40" }),
729
- /* @__PURE__ */ jsxs5("p", { className: "text-[10px] text-green-400 font-mono flex items-center gap-1", children: [
730
- /* @__PURE__ */ jsx7("span", { className: "material-symbols-outlined text-[14px]", children: "check_circle" }),
731
- "Fetch erfolgreich"
758
+ testStatus === "ok" && result && /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-2 bg-white/3 border border-white/8 rounded-xl p-3 text-[10px] font-mono", children: [
759
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
760
+ /* @__PURE__ */ jsxs5("span", { className: `font-bold ${result.status < 400 ? "text-green-400" : "text-red-400"}`, children: [
761
+ result.status,
762
+ " ",
763
+ result.statusText
764
+ ] }),
765
+ /* @__PURE__ */ jsx7("span", { className: "text-white/30", children: "\xB7" }),
766
+ /* @__PURE__ */ jsxs5("span", { className: "text-white/50", children: [
767
+ result.durationMs,
768
+ "ms"
769
+ ] }),
770
+ /* @__PURE__ */ jsx7("span", { className: "text-white/30", children: "\xB7" }),
771
+ /* @__PURE__ */ jsxs5("span", { className: "text-white/50", children: [
772
+ (result.bodySize / 1024).toFixed(1),
773
+ " KB"
774
+ ] })
775
+ ] }),
776
+ /* @__PURE__ */ jsxs5("div", { className: "text-white/40", children: [
777
+ "Content-Type: ",
778
+ /* @__PURE__ */ jsx7("span", { className: "text-white/70", children: result.contentType })
779
+ ] }),
780
+ /* @__PURE__ */ jsxs5("details", { className: "cursor-pointer", children: [
781
+ /* @__PURE__ */ jsxs5("summary", { className: "text-white/30 hover:text-white/60 transition", children: [
782
+ "Headers (",
783
+ Object.keys(result.headers).length,
784
+ ")"
785
+ ] }),
786
+ /* @__PURE__ */ jsx7("div", { className: "mt-1 space-y-0.5 pl-2 border-l border-white/10", children: Object.entries(result.headers).map(([k, v]) => /* @__PURE__ */ jsxs5("div", { className: "text-white/30", children: [
787
+ /* @__PURE__ */ jsxs5("span", { className: "text-white/50", children: [
788
+ k,
789
+ ":"
790
+ ] }),
791
+ " ",
792
+ v
793
+ ] }, k)) })
794
+ ] }),
795
+ result.isImage && result.imageDataUrl ? /* @__PURE__ */ jsx7("img", { src: result.imageDataUrl, alt: "response", className: "w-full max-h-40 object-contain rounded-lg border border-white/10 bg-black/40 mt-1" }) : /* @__PURE__ */ jsxs5("pre", { className: "text-white/60 whitespace-pre-wrap break-all bg-black/30 rounded-lg p-2 max-h-40 overflow-y-auto text-[9px]", children: [
796
+ result.bodyPreview,
797
+ result.bodySize > 500 ? "\n\u2026" : ""
732
798
  ] })
733
799
  ] }),
734
- urlStatus === "error" && urlError && /* @__PURE__ */ jsxs5("p", { className: "text-[10px] text-red-400 font-mono flex items-start gap-1", children: [
735
- /* @__PURE__ */ jsx7("span", { className: "material-symbols-outlined text-[14px] shrink-0", children: "error" }),
736
- urlError
800
+ testStatus === "error" && fetchError && /* @__PURE__ */ jsxs5("div", { className: "bg-red-900/20 border border-red-700/30 rounded-xl p-3 text-[10px] font-mono text-red-400 flex items-start gap-2", children: [
801
+ /* @__PURE__ */ jsx7("span", { className: "material-symbols-outlined text-[14px] shrink-0 mt-0.5", children: "error" }),
802
+ fetchError
737
803
  ] })
738
804
  ] }),
739
805
  /* @__PURE__ */ jsxs5("div", { className: "mt-auto p-4 bg-white/5 rounded-2xl border border-white/5 flex flex-col gap-2 opacity-50", children: [
@@ -4095,7 +4161,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4095
4161
  }
4096
4162
 
4097
4163
  // src/index.ts
4098
- var LIB_VERSION = "1.2.1";
4164
+ var LIB_VERSION = "1.2.3";
4099
4165
  export {
4100
4166
  AvatarArchitectApp,
4101
4167
  CollapsibleCard,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rslsp1/fa-app-tools",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
4
4
  "description": "Shared tools and hooks for Fine Art flow apps",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",