@rslsp1/fa-app-tools 0.1.11 → 0.1.12
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 +52 -36
- package/dist/index.d.ts +52 -36
- package/dist/index.js +61 -19
- package/dist/index.mjs +41 -2
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -4,6 +4,57 @@ import { Node, Edge } from '@xyflow/react';
|
|
|
4
4
|
|
|
5
5
|
declare function useOnClickOutside(ref: RefObject<HTMLElement | null>, handler: (e: MouseEvent | TouchEvent) => void): void;
|
|
6
6
|
|
|
7
|
+
interface WorkspaceTags {
|
|
8
|
+
by_category: Record<string, string[]>;
|
|
9
|
+
all: Array<{
|
|
10
|
+
label: string;
|
|
11
|
+
value: string;
|
|
12
|
+
category: string;
|
|
13
|
+
}>;
|
|
14
|
+
}
|
|
15
|
+
interface Generation {
|
|
16
|
+
id: string;
|
|
17
|
+
nodeId: string;
|
|
18
|
+
base64?: string;
|
|
19
|
+
mediaId?: string;
|
|
20
|
+
prompt?: string;
|
|
21
|
+
hierarchy?: string;
|
|
22
|
+
seed?: number;
|
|
23
|
+
model?: string;
|
|
24
|
+
timestamp: number;
|
|
25
|
+
status: 'processing' | 'done' | 'error';
|
|
26
|
+
step?: string;
|
|
27
|
+
tags: string[];
|
|
28
|
+
type?: 'generation' | 'import';
|
|
29
|
+
error?: {
|
|
30
|
+
message: string;
|
|
31
|
+
details?: string;
|
|
32
|
+
};
|
|
33
|
+
selectedForExport?: boolean;
|
|
34
|
+
}
|
|
35
|
+
interface ProjectSettings {
|
|
36
|
+
aspectRatio: string;
|
|
37
|
+
selectedModel: string;
|
|
38
|
+
seed: number;
|
|
39
|
+
seedMode: 'random' | 'fixed';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Hook für die Tastaturnavigation im Detailview.
|
|
44
|
+
* Rechts = Index + 1 (älter), Links = Index - 1 (neuer).
|
|
45
|
+
*/
|
|
46
|
+
declare function useKeyboardNavigation(history: Generation[], currentResult: Generation | null, setCurrentResult: (gen: Generation) => void): void;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Erstellt einen lesbaren Zeitstempel im Format YYYYMMDD_HHMMSS.
|
|
50
|
+
* Dies ist das vom User explizit gewünschte Format für Exporte.
|
|
51
|
+
*/
|
|
52
|
+
declare const getFormattedTimestamp: () => string;
|
|
53
|
+
/**
|
|
54
|
+
* Hilfskonstante für CSS-Styles (Dark Scrollbar etc.)
|
|
55
|
+
*/
|
|
56
|
+
declare const GLOBAL_STYLES = "\n .dark-scrollbar::-webkit-scrollbar { width: 4px; height: 4px; }\n .dark-scrollbar::-webkit-scrollbar-track { background: transparent; }\n .dark-scrollbar::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 10px; }\n html, body, #root { margin: 0; padding: 0; width: 100%; height: 100%; background: #0e0e0e; font-family: 'Google Sans Text', sans-serif; overflow: hidden; }\n @keyframes prompt-shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } }\n .prompt-loading { background: linear-gradient(90deg, rgba(255,255,255,0.02) 25%, rgba(255,255,255,0.05) 50%, rgba(255,255,255,0.02) 75%); background-size: 200% 100%; animation: prompt-shimmer 2s infinite linear; }\n @keyframes dropdown-enter { from { opacity: 0; transform: scale(0.95) translateY(-5px); } to { opacity: 1; transform: scale(1) translateY(0); } }\n .animate-dropdown { animation: dropdown-enter 0.1s ease-out forwards; }\n";
|
|
57
|
+
|
|
7
58
|
declare function injectXMPMetadata(base64: string, prompt: string, seed?: number, model?: string, id?: string, tags?: string[], hierarchy?: string): string;
|
|
8
59
|
|
|
9
60
|
/**
|
|
@@ -59,41 +110,6 @@ interface CompactDropdownProps {
|
|
|
59
110
|
}
|
|
60
111
|
declare const CompactDropdown: React.FC<CompactDropdownProps>;
|
|
61
112
|
|
|
62
|
-
interface WorkspaceTags {
|
|
63
|
-
by_category: Record<string, string[]>;
|
|
64
|
-
all: Array<{
|
|
65
|
-
label: string;
|
|
66
|
-
value: string;
|
|
67
|
-
category: string;
|
|
68
|
-
}>;
|
|
69
|
-
}
|
|
70
|
-
interface Generation {
|
|
71
|
-
id: string;
|
|
72
|
-
nodeId: string;
|
|
73
|
-
base64?: string;
|
|
74
|
-
mediaId?: string;
|
|
75
|
-
prompt?: string;
|
|
76
|
-
hierarchy?: string;
|
|
77
|
-
seed?: number;
|
|
78
|
-
model?: string;
|
|
79
|
-
timestamp: number;
|
|
80
|
-
status: 'processing' | 'done' | 'error';
|
|
81
|
-
step?: string;
|
|
82
|
-
tags: string[];
|
|
83
|
-
type?: 'generation' | 'import';
|
|
84
|
-
error?: {
|
|
85
|
-
message: string;
|
|
86
|
-
details?: string;
|
|
87
|
-
};
|
|
88
|
-
selectedForExport?: boolean;
|
|
89
|
-
}
|
|
90
|
-
interface ProjectSettings {
|
|
91
|
-
aspectRatio: string;
|
|
92
|
-
selectedModel: string;
|
|
93
|
-
seed: number;
|
|
94
|
-
seedMode: 'random' | 'fixed';
|
|
95
|
-
}
|
|
96
|
-
|
|
97
113
|
interface HistoryPanelProps {
|
|
98
114
|
history: Generation[];
|
|
99
115
|
currentResultId: string | null;
|
|
@@ -150,4 +166,4 @@ interface ListViewProps {
|
|
|
150
166
|
}
|
|
151
167
|
declare function ListView({ nodes, edges, onNodeChange, onAddChild, onDeleteNode, onMoveNode, onIndentNode, onOutdentNode, onAddSibling, focusedNodeId, onFocus, activePath, onGenerate, onGenerateBranch, onGenerateSubtree, isGeneratingNodeId }: ListViewProps): react_jsx_runtime.JSX.Element;
|
|
152
168
|
|
|
153
|
-
export { CompactDropdown, type ExtractedCharacter, FaToolsBadge, type Generation, HistoryPanel, InspectPanel, ListView, MediaLibrary, PillButton, type ProjectSettings, SectionLabel, SetupPanel, type WorkspaceTags, exportProjectToZip, formatTreeToMarkdown, importProjectFromZip, injectXMPMetadata, parsePromptFile, useOnClickOutside };
|
|
169
|
+
export { CompactDropdown, type ExtractedCharacter, FaToolsBadge, GLOBAL_STYLES, type Generation, HistoryPanel, InspectPanel, ListView, MediaLibrary, PillButton, type ProjectSettings, SectionLabel, SetupPanel, type WorkspaceTags, exportProjectToZip, formatTreeToMarkdown, getFormattedTimestamp, importProjectFromZip, injectXMPMetadata, parsePromptFile, useKeyboardNavigation, useOnClickOutside };
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,57 @@ import { Node, Edge } from '@xyflow/react';
|
|
|
4
4
|
|
|
5
5
|
declare function useOnClickOutside(ref: RefObject<HTMLElement | null>, handler: (e: MouseEvent | TouchEvent) => void): void;
|
|
6
6
|
|
|
7
|
+
interface WorkspaceTags {
|
|
8
|
+
by_category: Record<string, string[]>;
|
|
9
|
+
all: Array<{
|
|
10
|
+
label: string;
|
|
11
|
+
value: string;
|
|
12
|
+
category: string;
|
|
13
|
+
}>;
|
|
14
|
+
}
|
|
15
|
+
interface Generation {
|
|
16
|
+
id: string;
|
|
17
|
+
nodeId: string;
|
|
18
|
+
base64?: string;
|
|
19
|
+
mediaId?: string;
|
|
20
|
+
prompt?: string;
|
|
21
|
+
hierarchy?: string;
|
|
22
|
+
seed?: number;
|
|
23
|
+
model?: string;
|
|
24
|
+
timestamp: number;
|
|
25
|
+
status: 'processing' | 'done' | 'error';
|
|
26
|
+
step?: string;
|
|
27
|
+
tags: string[];
|
|
28
|
+
type?: 'generation' | 'import';
|
|
29
|
+
error?: {
|
|
30
|
+
message: string;
|
|
31
|
+
details?: string;
|
|
32
|
+
};
|
|
33
|
+
selectedForExport?: boolean;
|
|
34
|
+
}
|
|
35
|
+
interface ProjectSettings {
|
|
36
|
+
aspectRatio: string;
|
|
37
|
+
selectedModel: string;
|
|
38
|
+
seed: number;
|
|
39
|
+
seedMode: 'random' | 'fixed';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Hook für die Tastaturnavigation im Detailview.
|
|
44
|
+
* Rechts = Index + 1 (älter), Links = Index - 1 (neuer).
|
|
45
|
+
*/
|
|
46
|
+
declare function useKeyboardNavigation(history: Generation[], currentResult: Generation | null, setCurrentResult: (gen: Generation) => void): void;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Erstellt einen lesbaren Zeitstempel im Format YYYYMMDD_HHMMSS.
|
|
50
|
+
* Dies ist das vom User explizit gewünschte Format für Exporte.
|
|
51
|
+
*/
|
|
52
|
+
declare const getFormattedTimestamp: () => string;
|
|
53
|
+
/**
|
|
54
|
+
* Hilfskonstante für CSS-Styles (Dark Scrollbar etc.)
|
|
55
|
+
*/
|
|
56
|
+
declare const GLOBAL_STYLES = "\n .dark-scrollbar::-webkit-scrollbar { width: 4px; height: 4px; }\n .dark-scrollbar::-webkit-scrollbar-track { background: transparent; }\n .dark-scrollbar::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 10px; }\n html, body, #root { margin: 0; padding: 0; width: 100%; height: 100%; background: #0e0e0e; font-family: 'Google Sans Text', sans-serif; overflow: hidden; }\n @keyframes prompt-shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } }\n .prompt-loading { background: linear-gradient(90deg, rgba(255,255,255,0.02) 25%, rgba(255,255,255,0.05) 50%, rgba(255,255,255,0.02) 75%); background-size: 200% 100%; animation: prompt-shimmer 2s infinite linear; }\n @keyframes dropdown-enter { from { opacity: 0; transform: scale(0.95) translateY(-5px); } to { opacity: 1; transform: scale(1) translateY(0); } }\n .animate-dropdown { animation: dropdown-enter 0.1s ease-out forwards; }\n";
|
|
57
|
+
|
|
7
58
|
declare function injectXMPMetadata(base64: string, prompt: string, seed?: number, model?: string, id?: string, tags?: string[], hierarchy?: string): string;
|
|
8
59
|
|
|
9
60
|
/**
|
|
@@ -59,41 +110,6 @@ interface CompactDropdownProps {
|
|
|
59
110
|
}
|
|
60
111
|
declare const CompactDropdown: React.FC<CompactDropdownProps>;
|
|
61
112
|
|
|
62
|
-
interface WorkspaceTags {
|
|
63
|
-
by_category: Record<string, string[]>;
|
|
64
|
-
all: Array<{
|
|
65
|
-
label: string;
|
|
66
|
-
value: string;
|
|
67
|
-
category: string;
|
|
68
|
-
}>;
|
|
69
|
-
}
|
|
70
|
-
interface Generation {
|
|
71
|
-
id: string;
|
|
72
|
-
nodeId: string;
|
|
73
|
-
base64?: string;
|
|
74
|
-
mediaId?: string;
|
|
75
|
-
prompt?: string;
|
|
76
|
-
hierarchy?: string;
|
|
77
|
-
seed?: number;
|
|
78
|
-
model?: string;
|
|
79
|
-
timestamp: number;
|
|
80
|
-
status: 'processing' | 'done' | 'error';
|
|
81
|
-
step?: string;
|
|
82
|
-
tags: string[];
|
|
83
|
-
type?: 'generation' | 'import';
|
|
84
|
-
error?: {
|
|
85
|
-
message: string;
|
|
86
|
-
details?: string;
|
|
87
|
-
};
|
|
88
|
-
selectedForExport?: boolean;
|
|
89
|
-
}
|
|
90
|
-
interface ProjectSettings {
|
|
91
|
-
aspectRatio: string;
|
|
92
|
-
selectedModel: string;
|
|
93
|
-
seed: number;
|
|
94
|
-
seedMode: 'random' | 'fixed';
|
|
95
|
-
}
|
|
96
|
-
|
|
97
113
|
interface HistoryPanelProps {
|
|
98
114
|
history: Generation[];
|
|
99
115
|
currentResultId: string | null;
|
|
@@ -150,4 +166,4 @@ interface ListViewProps {
|
|
|
150
166
|
}
|
|
151
167
|
declare function ListView({ nodes, edges, onNodeChange, onAddChild, onDeleteNode, onMoveNode, onIndentNode, onOutdentNode, onAddSibling, focusedNodeId, onFocus, activePath, onGenerate, onGenerateBranch, onGenerateSubtree, isGeneratingNodeId }: ListViewProps): react_jsx_runtime.JSX.Element;
|
|
152
168
|
|
|
153
|
-
export { CompactDropdown, type ExtractedCharacter, FaToolsBadge, type Generation, HistoryPanel, InspectPanel, ListView, MediaLibrary, PillButton, type ProjectSettings, SectionLabel, SetupPanel, type WorkspaceTags, exportProjectToZip, formatTreeToMarkdown, importProjectFromZip, injectXMPMetadata, parsePromptFile, useOnClickOutside };
|
|
169
|
+
export { CompactDropdown, type ExtractedCharacter, FaToolsBadge, GLOBAL_STYLES, type Generation, HistoryPanel, InspectPanel, ListView, MediaLibrary, PillButton, type ProjectSettings, SectionLabel, SetupPanel, type WorkspaceTags, exportProjectToZip, formatTreeToMarkdown, getFormattedTimestamp, importProjectFromZip, injectXMPMetadata, parsePromptFile, useKeyboardNavigation, useOnClickOutside };
|
package/dist/index.js
CHANGED
|
@@ -32,6 +32,7 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
CompactDropdown: () => CompactDropdown,
|
|
34
34
|
FaToolsBadge: () => FaToolsBadge,
|
|
35
|
+
GLOBAL_STYLES: () => GLOBAL_STYLES,
|
|
35
36
|
HistoryPanel: () => HistoryPanel,
|
|
36
37
|
InspectPanel: () => InspectPanel,
|
|
37
38
|
ListView: () => ListView,
|
|
@@ -41,9 +42,11 @@ __export(index_exports, {
|
|
|
41
42
|
SetupPanel: () => SetupPanel,
|
|
42
43
|
exportProjectToZip: () => exportProjectToZip,
|
|
43
44
|
formatTreeToMarkdown: () => formatTreeToMarkdown,
|
|
45
|
+
getFormattedTimestamp: () => getFormattedTimestamp,
|
|
44
46
|
importProjectFromZip: () => importProjectFromZip,
|
|
45
47
|
injectXMPMetadata: () => injectXMPMetadata,
|
|
46
48
|
parsePromptFile: () => parsePromptFile,
|
|
49
|
+
useKeyboardNavigation: () => useKeyboardNavigation,
|
|
47
50
|
useOnClickOutside: () => useOnClickOutside
|
|
48
51
|
});
|
|
49
52
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -65,6 +68,42 @@ function useOnClickOutside(ref, handler) {
|
|
|
65
68
|
}, [ref, handler]);
|
|
66
69
|
}
|
|
67
70
|
|
|
71
|
+
// src/hooks/useKeyboardNavigation.ts
|
|
72
|
+
var import_react2 = require("react");
|
|
73
|
+
function useKeyboardNavigation(history, currentResult, setCurrentResult) {
|
|
74
|
+
(0, import_react2.useEffect)(() => {
|
|
75
|
+
const handleKeyDown = (e) => {
|
|
76
|
+
if (e.target instanceof HTMLTextAreaElement || e.target instanceof HTMLInputElement) return;
|
|
77
|
+
if (!currentResult || history.length === 0) return;
|
|
78
|
+
const currentIndex = history.findIndex((h) => h.id === currentResult.id);
|
|
79
|
+
if (e.key === "ArrowRight" && currentIndex < history.length - 1) {
|
|
80
|
+
setCurrentResult(history[currentIndex + 1]);
|
|
81
|
+
} else if (e.key === "ArrowLeft" && currentIndex > 0) {
|
|
82
|
+
setCurrentResult(history[currentIndex - 1]);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
86
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
87
|
+
}, [currentResult, history, setCurrentResult]);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// src/lib/utils.ts
|
|
91
|
+
var getFormattedTimestamp = () => {
|
|
92
|
+
const d = /* @__PURE__ */ new Date();
|
|
93
|
+
const pad = (n) => n.toString().padStart(2, "0");
|
|
94
|
+
return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}_${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
|
|
95
|
+
};
|
|
96
|
+
var GLOBAL_STYLES = `
|
|
97
|
+
.dark-scrollbar::-webkit-scrollbar { width: 4px; height: 4px; }
|
|
98
|
+
.dark-scrollbar::-webkit-scrollbar-track { background: transparent; }
|
|
99
|
+
.dark-scrollbar::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 10px; }
|
|
100
|
+
html, body, #root { margin: 0; padding: 0; width: 100%; height: 100%; background: #0e0e0e; font-family: 'Google Sans Text', sans-serif; overflow: hidden; }
|
|
101
|
+
@keyframes prompt-shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } }
|
|
102
|
+
.prompt-loading { background: linear-gradient(90deg, rgba(255,255,255,0.02) 25%, rgba(255,255,255,0.05) 50%, rgba(255,255,255,0.02) 75%); background-size: 200% 100%; animation: prompt-shimmer 2s infinite linear; }
|
|
103
|
+
@keyframes dropdown-enter { from { opacity: 0; transform: scale(0.95) translateY(-5px); } to { opacity: 1; transform: scale(1) translateY(0); } }
|
|
104
|
+
.animate-dropdown { animation: dropdown-enter 0.1s ease-out forwards; }
|
|
105
|
+
`;
|
|
106
|
+
|
|
68
107
|
// src/lib/metadata.ts
|
|
69
108
|
var crcTable = (() => {
|
|
70
109
|
let c;
|
|
@@ -381,7 +420,7 @@ var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
|
381
420
|
var SectionLabel = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "flex items-center px-2", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-[9px] font-bold text-white/30 uppercase tracking-widest text-nowrap", children }) });
|
|
382
421
|
|
|
383
422
|
// src/components/CompactDropdown.tsx
|
|
384
|
-
var
|
|
423
|
+
var import_react3 = require("react");
|
|
385
424
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
386
425
|
var CompactDropdown = ({
|
|
387
426
|
value,
|
|
@@ -390,8 +429,8 @@ var CompactDropdown = ({
|
|
|
390
429
|
onChange,
|
|
391
430
|
className = ""
|
|
392
431
|
}) => {
|
|
393
|
-
const [isOpen, setIsOpen] = (0,
|
|
394
|
-
const ref = (0,
|
|
432
|
+
const [isOpen, setIsOpen] = (0, import_react3.useState)(false);
|
|
433
|
+
const ref = (0, import_react3.useRef)(null);
|
|
395
434
|
useOnClickOutside(ref, () => setIsOpen(false));
|
|
396
435
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { ref, className: `relative shrink-0 ${className}`, children: [
|
|
397
436
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
@@ -423,7 +462,7 @@ var CompactDropdown = ({
|
|
|
423
462
|
};
|
|
424
463
|
|
|
425
464
|
// src/components/HistoryPanel.tsx
|
|
426
|
-
var
|
|
465
|
+
var import_react4 = require("motion/react");
|
|
427
466
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
428
467
|
var formatFriendlyTimestamp = (timestamp) => {
|
|
429
468
|
const date = new Date(timestamp);
|
|
@@ -443,7 +482,7 @@ var HistoryPanel = ({ history, currentResultId, onSelect, onDelete }) => {
|
|
|
443
482
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-[10px] font-bold uppercase tracking-widest", children: "Keine Historie" })
|
|
444
483
|
] });
|
|
445
484
|
}
|
|
446
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
485
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react4.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, className: "absolute inset-0 p-4 flex flex-col gap-3 overflow-y-auto dark-scrollbar", children: history.map((gen) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
447
486
|
"div",
|
|
448
487
|
{
|
|
449
488
|
className: `flex gap-3 p-2 bg-white/5 border rounded-2xl cursor-pointer group transition-all relative ${currentResultId === gen.id ? "border-white/40 bg-white/10 shadow-lg" : "border-white/5 hover:border-white/20"}`,
|
|
@@ -472,7 +511,7 @@ var HistoryPanel = ({ history, currentResultId, onSelect, onDelete }) => {
|
|
|
472
511
|
};
|
|
473
512
|
|
|
474
513
|
// src/components/InspectPanel.tsx
|
|
475
|
-
var
|
|
514
|
+
var import_react5 = require("motion/react");
|
|
476
515
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
477
516
|
var InspectPanel = ({ currentResult, history, onSelect, workspaceTags, onTagToggle }) => {
|
|
478
517
|
if (!currentResult) {
|
|
@@ -482,7 +521,7 @@ var InspectPanel = ({ currentResult, history, onSelect, workspaceTags, onTagTogg
|
|
|
482
521
|
] });
|
|
483
522
|
}
|
|
484
523
|
const fullDateStr = new Date(currentResult.timestamp).toLocaleString([], { day: "2-digit", month: "2-digit", year: "numeric", hour: "2-digit", minute: "2-digit", second: "2-digit" });
|
|
485
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
524
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react5.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, className: "absolute inset-0 flex flex-col overflow-hidden", children: [
|
|
486
525
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex-shrink-0 border-b border-white/5 bg-black/20 py-3 px-4", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex gap-2 overflow-x-auto no-scrollbar pb-1", children: history.map((gen) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { onClick: () => onSelect(gen), className: `w-10 h-10 rounded-lg overflow-hidden border shrink-0 transition-all ${currentResult.id === gen.id ? "border-white scale-105 shadow-lg" : "border-white/5 opacity-40 hover:opacity-100"}`, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("img", { src: gen.base64 ? gen.base64.startsWith("data:") ? gen.base64 : `data:image/png;base64,${gen.base64}` : "", className: "w-full h-full object-cover", alt: "Thumbnail" }) }, gen.id)) }) }),
|
|
487
526
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex-1 overflow-y-auto p-4 flex flex-col gap-6 dark-scrollbar pb-10", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-col gap-4", children: [
|
|
488
527
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SectionLabel, { children: "Vorschau" }),
|
|
@@ -524,13 +563,13 @@ var InspectPanel = ({ currentResult, history, onSelect, workspaceTags, onTagTogg
|
|
|
524
563
|
};
|
|
525
564
|
|
|
526
565
|
// src/components/SetupPanel.tsx
|
|
527
|
-
var
|
|
528
|
-
var
|
|
566
|
+
var import_react6 = require("react");
|
|
567
|
+
var import_react7 = require("motion/react");
|
|
529
568
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
530
569
|
var SetupPanel = ({ onWorkspaceImport, onProjectExport, onProjectImport, projectActionState }) => {
|
|
531
|
-
const workspaceInputRef = (0,
|
|
532
|
-
const projectInputRef = (0,
|
|
533
|
-
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
570
|
+
const workspaceInputRef = (0, import_react6.useRef)(null);
|
|
571
|
+
const projectInputRef = (0, import_react6.useRef)(null);
|
|
572
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react7.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, className: "absolute inset-0 p-6 flex flex-col gap-10", children: [
|
|
534
573
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-4", children: [
|
|
535
574
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
536
575
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SectionLabel, { children: "Workspace Management" }),
|
|
@@ -573,7 +612,7 @@ var SetupPanel = ({ onWorkspaceImport, onProjectExport, onProjectImport, project
|
|
|
573
612
|
};
|
|
574
613
|
|
|
575
614
|
// src/components/MediaLibrary.tsx
|
|
576
|
-
var
|
|
615
|
+
var import_react8 = require("motion/react");
|
|
577
616
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
578
617
|
var MediaLibrary = ({ items, onImport, onDelete, onSelect, onToggleSelection, onBatchDownload, onGenerateReference }) => {
|
|
579
618
|
const selectedCount = items.filter((i) => i.selectedForExport).length;
|
|
@@ -592,7 +631,7 @@ var MediaLibrary = ({ items, onImport, onDelete, onSelect, onToggleSelection, on
|
|
|
592
631
|
"Laden"
|
|
593
632
|
] })
|
|
594
633
|
] }),
|
|
595
|
-
selectedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
634
|
+
selectedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react8.motion.div, { initial: { opacity: 0, y: -10 }, animate: { opacity: 1, y: 0 }, className: "flex items-center justify-between bg-blue-500/10 border border-blue-500/20 p-2 rounded-xl", children: [
|
|
596
635
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "text-[9px] font-bold uppercase text-blue-400 ml-1", children: [
|
|
597
636
|
selectedCount,
|
|
598
637
|
" ausgew\xE4hlt"
|
|
@@ -609,7 +648,7 @@ var MediaLibrary = ({ items, onImport, onDelete, onSelect, onToggleSelection, on
|
|
|
609
648
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-[12px] font-bold uppercase tracking-widest", children: "Keine Medien" }),
|
|
610
649
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-[10px] italic", children: "Importiere Assets aus deinem Projekt." })
|
|
611
650
|
] })
|
|
612
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "grid grid-cols-2 gap-3 pb-10", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
651
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "grid grid-cols-2 gap-3 pb-10", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react8.motion.div, { initial: { opacity: 0, scale: 0.9 }, animate: { opacity: 1, scale: 1 }, className: `relative aspect-square group/item rounded-xl overflow-hidden border transition-all bg-white/5 cursor-pointer shadow-lg ${item.selectedForExport ? "border-blue-500 shadow-[0_0_15px_rgba(59,130,246,0.2)]" : "border-white/10 opacity-70 hover:opacity-100"}`, onClick: () => onSelect?.(item), children: [
|
|
613
652
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("img", { src: item.base64 ? item.base64.startsWith("data:") ? item.base64 : `data:image/png;base64,${item.base64}` : "", className: "w-full h-full object-cover transition-transform duration-500 group-hover/item:scale-110", alt: item.prompt }),
|
|
614
653
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", className: `absolute top-2 left-2 w-5 h-5 rounded-md border flex items-center justify-center transition-all z-30 pointer-events-auto ${item.selectedForExport ? "bg-blue-500 border-blue-400" : "bg-black/60 border-white/20"}`, onClick: (e) => {
|
|
615
654
|
e.stopPropagation();
|
|
@@ -634,10 +673,10 @@ var MediaLibrary = ({ items, onImport, onDelete, onSelect, onToggleSelection, on
|
|
|
634
673
|
};
|
|
635
674
|
|
|
636
675
|
// src/components/ListView.tsx
|
|
637
|
-
var
|
|
676
|
+
var import_react9 = require("react");
|
|
638
677
|
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
639
678
|
var ListNode = ({ node, depth, onNodeChange, onAddChild, onDeleteNode, onMoveNode, onIndentNode, onOutdentNode, onAddSibling, isActive, isInPath, onFocus, onGenerate, onGenerateBranch, onGenerateSubtree, isGenerating, isCollapsed, toggleCollapse, renderNode, children }) => {
|
|
640
|
-
const inputRef = (0,
|
|
679
|
+
const inputRef = (0, import_react9.useRef)(null);
|
|
641
680
|
const hasChildren = children && children.length > 0;
|
|
642
681
|
const handleKeyDown = (e) => {
|
|
643
682
|
if (e.key === "Tab") {
|
|
@@ -665,7 +704,7 @@ var ListNode = ({ node, depth, onNodeChange, onAddChild, onDeleteNode, onMoveNod
|
|
|
665
704
|
onMoveNode(node.id, "down");
|
|
666
705
|
}
|
|
667
706
|
};
|
|
668
|
-
(0,
|
|
707
|
+
(0, import_react9.useEffect)(() => {
|
|
669
708
|
if (isActive && inputRef.current) inputRef.current.focus();
|
|
670
709
|
}, [isActive]);
|
|
671
710
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-col w-full", children: [
|
|
@@ -699,7 +738,7 @@ var ListNode = ({ node, depth, onNodeChange, onAddChild, onDeleteNode, onMoveNod
|
|
|
699
738
|
] });
|
|
700
739
|
};
|
|
701
740
|
function ListView({ nodes, edges, onNodeChange, onAddChild, onDeleteNode, onMoveNode, onIndentNode, onOutdentNode, onAddSibling, focusedNodeId, onFocus, activePath, onGenerate, onGenerateBranch, onGenerateSubtree, isGeneratingNodeId }) {
|
|
702
|
-
const [collapsed, setCollapsed] = (0,
|
|
741
|
+
const [collapsed, setCollapsed] = (0, import_react9.useState)(/* @__PURE__ */ new Set());
|
|
703
742
|
const toggleCollapse = (id) => {
|
|
704
743
|
setCollapsed((prev) => {
|
|
705
744
|
const next = new Set(prev);
|
|
@@ -729,6 +768,7 @@ function ListView({ nodes, edges, onNodeChange, onAddChild, onDeleteNode, onMove
|
|
|
729
768
|
0 && (module.exports = {
|
|
730
769
|
CompactDropdown,
|
|
731
770
|
FaToolsBadge,
|
|
771
|
+
GLOBAL_STYLES,
|
|
732
772
|
HistoryPanel,
|
|
733
773
|
InspectPanel,
|
|
734
774
|
ListView,
|
|
@@ -738,8 +778,10 @@ function ListView({ nodes, edges, onNodeChange, onAddChild, onDeleteNode, onMove
|
|
|
738
778
|
SetupPanel,
|
|
739
779
|
exportProjectToZip,
|
|
740
780
|
formatTreeToMarkdown,
|
|
781
|
+
getFormattedTimestamp,
|
|
741
782
|
importProjectFromZip,
|
|
742
783
|
injectXMPMetadata,
|
|
743
784
|
parsePromptFile,
|
|
785
|
+
useKeyboardNavigation,
|
|
744
786
|
useOnClickOutside
|
|
745
787
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -15,6 +15,42 @@ function useOnClickOutside(ref, handler) {
|
|
|
15
15
|
}, [ref, handler]);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
// src/hooks/useKeyboardNavigation.ts
|
|
19
|
+
import { useEffect as useEffect2 } from "react";
|
|
20
|
+
function useKeyboardNavigation(history, currentResult, setCurrentResult) {
|
|
21
|
+
useEffect2(() => {
|
|
22
|
+
const handleKeyDown = (e) => {
|
|
23
|
+
if (e.target instanceof HTMLTextAreaElement || e.target instanceof HTMLInputElement) return;
|
|
24
|
+
if (!currentResult || history.length === 0) return;
|
|
25
|
+
const currentIndex = history.findIndex((h) => h.id === currentResult.id);
|
|
26
|
+
if (e.key === "ArrowRight" && currentIndex < history.length - 1) {
|
|
27
|
+
setCurrentResult(history[currentIndex + 1]);
|
|
28
|
+
} else if (e.key === "ArrowLeft" && currentIndex > 0) {
|
|
29
|
+
setCurrentResult(history[currentIndex - 1]);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
33
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
34
|
+
}, [currentResult, history, setCurrentResult]);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// src/lib/utils.ts
|
|
38
|
+
var getFormattedTimestamp = () => {
|
|
39
|
+
const d = /* @__PURE__ */ new Date();
|
|
40
|
+
const pad = (n) => n.toString().padStart(2, "0");
|
|
41
|
+
return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}_${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
|
|
42
|
+
};
|
|
43
|
+
var GLOBAL_STYLES = `
|
|
44
|
+
.dark-scrollbar::-webkit-scrollbar { width: 4px; height: 4px; }
|
|
45
|
+
.dark-scrollbar::-webkit-scrollbar-track { background: transparent; }
|
|
46
|
+
.dark-scrollbar::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.1); border-radius: 10px; }
|
|
47
|
+
html, body, #root { margin: 0; padding: 0; width: 100%; height: 100%; background: #0e0e0e; font-family: 'Google Sans Text', sans-serif; overflow: hidden; }
|
|
48
|
+
@keyframes prompt-shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } }
|
|
49
|
+
.prompt-loading { background: linear-gradient(90deg, rgba(255,255,255,0.02) 25%, rgba(255,255,255,0.05) 50%, rgba(255,255,255,0.02) 75%); background-size: 200% 100%; animation: prompt-shimmer 2s infinite linear; }
|
|
50
|
+
@keyframes dropdown-enter { from { opacity: 0; transform: scale(0.95) translateY(-5px); } to { opacity: 1; transform: scale(1) translateY(0); } }
|
|
51
|
+
.animate-dropdown { animation: dropdown-enter 0.1s ease-out forwards; }
|
|
52
|
+
`;
|
|
53
|
+
|
|
18
54
|
// src/lib/metadata.ts
|
|
19
55
|
var crcTable = (() => {
|
|
20
56
|
let c;
|
|
@@ -584,7 +620,7 @@ var MediaLibrary = ({ items, onImport, onDelete, onSelect, onToggleSelection, on
|
|
|
584
620
|
};
|
|
585
621
|
|
|
586
622
|
// src/components/ListView.tsx
|
|
587
|
-
import { useEffect as
|
|
623
|
+
import { useEffect as useEffect3, useRef as useRef3, useState as useState2 } from "react";
|
|
588
624
|
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
589
625
|
var ListNode = ({ node, depth, onNodeChange, onAddChild, onDeleteNode, onMoveNode, onIndentNode, onOutdentNode, onAddSibling, isActive, isInPath, onFocus, onGenerate, onGenerateBranch, onGenerateSubtree, isGenerating, isCollapsed, toggleCollapse, renderNode, children }) => {
|
|
590
626
|
const inputRef = useRef3(null);
|
|
@@ -615,7 +651,7 @@ var ListNode = ({ node, depth, onNodeChange, onAddChild, onDeleteNode, onMoveNod
|
|
|
615
651
|
onMoveNode(node.id, "down");
|
|
616
652
|
}
|
|
617
653
|
};
|
|
618
|
-
|
|
654
|
+
useEffect3(() => {
|
|
619
655
|
if (isActive && inputRef.current) inputRef.current.focus();
|
|
620
656
|
}, [isActive]);
|
|
621
657
|
return /* @__PURE__ */ jsxs7("div", { className: "flex flex-col w-full", children: [
|
|
@@ -678,6 +714,7 @@ function ListView({ nodes, edges, onNodeChange, onAddChild, onDeleteNode, onMove
|
|
|
678
714
|
export {
|
|
679
715
|
CompactDropdown,
|
|
680
716
|
FaToolsBadge,
|
|
717
|
+
GLOBAL_STYLES,
|
|
681
718
|
HistoryPanel,
|
|
682
719
|
InspectPanel,
|
|
683
720
|
ListView,
|
|
@@ -687,8 +724,10 @@ export {
|
|
|
687
724
|
SetupPanel,
|
|
688
725
|
exportProjectToZip,
|
|
689
726
|
formatTreeToMarkdown,
|
|
727
|
+
getFormattedTimestamp,
|
|
690
728
|
importProjectFromZip,
|
|
691
729
|
injectXMPMetadata,
|
|
692
730
|
parsePromptFile,
|
|
731
|
+
useKeyboardNavigation,
|
|
693
732
|
useOnClickOutside
|
|
694
733
|
};
|