dsh-image-gen 0.7.0 → 0.8.0
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/lib/client.js +2599 -333
- package/lib/client.js.map +1 -1
- package/lib/index.js +7177 -155
- package/lib/types/baoyu-compose.d.ts +61 -0
- package/lib/types/client/gallery-store.d.ts +40 -1
- package/lib/types/client/gallery-view.d.ts +12 -0
- package/lib/types/client/index.d.ts +1 -1
- package/lib/types/client/inspiration-image-cache.d.ts +2 -2
- package/lib/types/client/inspiration-style.d.ts +1 -1
- package/lib/types/client/inspiration-view.d.ts +1 -0
- package/lib/types/client/studio-style.d.ts +1 -1
- package/lib/types/client/studio-view.d.ts +3 -0
- package/lib/types/client/tl/tl-brand-theme.d.ts +7 -0
- package/lib/types/config.d.ts +19 -6
- package/lib/types/import-route.d.ts +16 -0
- package/lib/types/index.d.ts +1 -0
- package/lib/types/inspiration.d.ts +40 -1
- package/lib/types/openai-compatible.d.ts +1 -1
- package/lib/types/shared.d.ts +2 -0
- package/lib/types/studio-route.d.ts +2 -0
- package/lib/types/studio.d.ts +24 -0
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -75,6 +75,8 @@ window.__ModuleLoader__.load({
|
|
|
75
75
|
//#region lib/types/shared.js
|
|
76
76
|
/** Browser route used by the generated-image card. */
|
|
77
77
|
const IMAGE_ROUTE = "/plugins/dsh-image-gen/image";
|
|
78
|
+
/** Browser route that uploads user-picked images as DSH attachments. */
|
|
79
|
+
const IMPORT_ROUTE = "/plugins/dsh-image-gen/import";
|
|
78
80
|
/** Browser route used for deleting generated images and workspace files. */
|
|
79
81
|
const DELETE_ROUTE = "/plugins/dsh-image-gen/delete";
|
|
80
82
|
/** Same-origin route used by the browser image workbench. */
|
|
@@ -300,9 +302,11 @@ window.__ModuleLoader__.load({
|
|
|
300
302
|
//#endregion
|
|
301
303
|
//#region lib/types/client/gallery-store.js
|
|
302
304
|
const DB_NAME$2 = "dsh_image_gen_db";
|
|
303
|
-
const DB_VERSION =
|
|
305
|
+
const DB_VERSION = 4;
|
|
304
306
|
const STORE_NAME = "gallery_history";
|
|
305
307
|
const TOMBSTONE_STORE = "gallery_tombstones";
|
|
308
|
+
const FAV_PROMPT_STORE = "favorite_prompts";
|
|
309
|
+
const FAV_FOLDER_STORE = "favorite_folders";
|
|
306
310
|
let dbPromise = null;
|
|
307
311
|
let tombstonesCache = null;
|
|
308
312
|
function getDB() {
|
|
@@ -317,14 +321,25 @@ window.__ModuleLoader__.load({
|
|
|
317
321
|
const db = event.target.result;
|
|
318
322
|
if (!db.objectStoreNames.contains(STORE_NAME)) db.createObjectStore(STORE_NAME, { keyPath: "id" }).createIndex("createdAt", "createdAt", { unique: false });
|
|
319
323
|
if (!db.objectStoreNames.contains(TOMBSTONE_STORE)) db.createObjectStore(TOMBSTONE_STORE, { keyPath: "id" });
|
|
324
|
+
if (!db.objectStoreNames.contains(FAV_PROMPT_STORE)) db.createObjectStore(FAV_PROMPT_STORE, { keyPath: "id" });
|
|
325
|
+
if (!db.objectStoreNames.contains(FAV_FOLDER_STORE)) db.createObjectStore(FAV_FOLDER_STORE, { keyPath: "id" });
|
|
320
326
|
};
|
|
321
327
|
request.onsuccess = () => {
|
|
322
|
-
|
|
328
|
+
const db = request.result;
|
|
329
|
+
db.onversionchange = () => {
|
|
330
|
+
db.close();
|
|
331
|
+
dbPromise = null;
|
|
332
|
+
};
|
|
333
|
+
resolve(db);
|
|
323
334
|
};
|
|
324
335
|
request.onerror = () => {
|
|
325
336
|
dbPromise = null;
|
|
326
337
|
reject(request.error);
|
|
327
338
|
};
|
|
339
|
+
request.onblocked = () => {
|
|
340
|
+
dbPromise = null;
|
|
341
|
+
reject(/* @__PURE__ */ new Error("IndexedDB upgrade blocked. Close other open Studio tabs and retry."));
|
|
342
|
+
};
|
|
328
343
|
});
|
|
329
344
|
return dbPromise;
|
|
330
345
|
}
|
|
@@ -551,6 +566,7 @@ window.__ModuleLoader__.load({
|
|
|
551
566
|
*/
|
|
552
567
|
function isItemInWorkspace(item, workspace) {
|
|
553
568
|
if (!workspace || !workspace.workspaceId && !workspace.path && (!workspace.sessionIds || workspace.sessionIds.length === 0)) return true;
|
|
569
|
+
if (!item.workspaceId && !item.sessionId && !item.workspacePath && !item.savedTo) return true;
|
|
554
570
|
if (item.workspaceId && workspace.workspaceId && item.workspaceId === workspace.workspaceId) return true;
|
|
555
571
|
if (item.sessionId && Array.isArray(workspace.sessionIds) && workspace.sessionIds.includes(item.sessionId)) return true;
|
|
556
572
|
if (item.workspacePath && workspace.path) {
|
|
@@ -563,6 +579,234 @@ window.__ModuleLoader__.load({
|
|
|
563
579
|
}
|
|
564
580
|
return false;
|
|
565
581
|
}
|
|
582
|
+
const favoriteListeners = /* @__PURE__ */ new Set();
|
|
583
|
+
function notifyFavorites() {
|
|
584
|
+
for (const listener of favoriteListeners) try {
|
|
585
|
+
listener();
|
|
586
|
+
} catch (err) {
|
|
587
|
+
console.error("[dsh-image-gen] Favorites listener error:", err);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
/** Subscribe to favorites mutations (insert/delete). */
|
|
591
|
+
function subscribeFavorites(listener) {
|
|
592
|
+
favoriteListeners.add(listener);
|
|
593
|
+
return () => {
|
|
594
|
+
favoriteListeners.delete(listener);
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
/** Stable base36 id for a favorite prompt; identical trimmed text dedupes. */
|
|
598
|
+
function promptIdOf(text) {
|
|
599
|
+
let hash = 5381;
|
|
600
|
+
for (let i = 0; i < text.length; i++) hash = (hash << 5) + hash + text.charCodeAt(i) | 0;
|
|
601
|
+
return `p${(hash >>> 0).toString(36)}-${text.length.toString(36)}`;
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* Collision-free prompt id. Distinct texts can share the djb2 hash and the
|
|
605
|
+
* length, which would silently overwrite an unrelated saved prompt; suffix
|
|
606
|
+
* until the id is free or already owned by the same text.
|
|
607
|
+
*/
|
|
608
|
+
async function uniquePromptId(db, text) {
|
|
609
|
+
const rows = await readAll(db, FAV_PROMPT_STORE);
|
|
610
|
+
const byId = new Map(rows.map((row) => [row.id, row]));
|
|
611
|
+
const base = promptIdOf(text);
|
|
612
|
+
let candidate = base;
|
|
613
|
+
let suffix = 1;
|
|
614
|
+
while (byId.has(candidate) && byId.get(candidate)?.text !== text) {
|
|
615
|
+
suffix++;
|
|
616
|
+
candidate = `${base}-${suffix}`;
|
|
617
|
+
}
|
|
618
|
+
return candidate;
|
|
619
|
+
}
|
|
620
|
+
function readAll(db, storeName) {
|
|
621
|
+
return new Promise((resolve, reject) => {
|
|
622
|
+
const req = db.transaction(storeName, "readonly").objectStore(storeName).openCursor();
|
|
623
|
+
const rows = [];
|
|
624
|
+
req.onsuccess = (event) => {
|
|
625
|
+
const cursor = event.target.result;
|
|
626
|
+
if (cursor) {
|
|
627
|
+
rows.push(cursor.value);
|
|
628
|
+
cursor.continue();
|
|
629
|
+
} else resolve(rows);
|
|
630
|
+
};
|
|
631
|
+
req.onerror = () => reject(req.error);
|
|
632
|
+
});
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Keep one prompt in the favorites rail; identical trimmed text overwrites
|
|
636
|
+
* (one record per distinct prompt).
|
|
637
|
+
* @returns false when the write failed.
|
|
638
|
+
*/
|
|
639
|
+
async function saveFavoritePrompt(text) {
|
|
640
|
+
const trimmed = text.trim();
|
|
641
|
+
if (trimmed.length === 0) return false;
|
|
642
|
+
try {
|
|
643
|
+
const db = await getDB();
|
|
644
|
+
const id = await uniquePromptId(db, trimmed);
|
|
645
|
+
await new Promise((resolve, reject) => {
|
|
646
|
+
const req = db.transaction(FAV_PROMPT_STORE, "readwrite").objectStore(FAV_PROMPT_STORE).put({
|
|
647
|
+
id,
|
|
648
|
+
text: trimmed,
|
|
649
|
+
addedAt: Date.now()
|
|
650
|
+
});
|
|
651
|
+
req.onsuccess = () => resolve();
|
|
652
|
+
req.onerror = () => reject(req.error);
|
|
653
|
+
});
|
|
654
|
+
notifyFavorites();
|
|
655
|
+
return true;
|
|
656
|
+
} catch (err) {
|
|
657
|
+
console.warn("[dsh-image-gen] Failed to save favorite prompt:", err);
|
|
658
|
+
return false;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
/** Prompt favorites, newest first. */
|
|
662
|
+
async function getFavoritePrompts() {
|
|
663
|
+
try {
|
|
664
|
+
return (await readAll(await getDB(), FAV_PROMPT_STORE)).sort((a, b) => b.addedAt - a.addedAt);
|
|
665
|
+
} catch (err) {
|
|
666
|
+
console.warn("[dsh-image-gen] Failed to read favorite prompts:", err);
|
|
667
|
+
return [];
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
/** Drop one prompt favorite. */
|
|
671
|
+
async function deleteFavoritePrompt(id) {
|
|
672
|
+
try {
|
|
673
|
+
const db = await getDB();
|
|
674
|
+
await new Promise((resolve, reject) => {
|
|
675
|
+
const req = db.transaction(FAV_PROMPT_STORE, "readwrite").objectStore(FAV_PROMPT_STORE).delete(id);
|
|
676
|
+
req.onsuccess = () => resolve();
|
|
677
|
+
req.onerror = () => reject(req.error);
|
|
678
|
+
});
|
|
679
|
+
notifyFavorites();
|
|
680
|
+
} catch (err) {
|
|
681
|
+
console.warn("[dsh-image-gen] Failed to delete favorite prompt:", err);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
function folderIdOf(kind, name) {
|
|
685
|
+
return `f-${kind}-${name.trim().toLowerCase().replace(/\s+/g, "-")}-${name.length.toString(36)}`;
|
|
686
|
+
}
|
|
687
|
+
/** Create a favorites folder; returns null when the name is empty or already used for the kind. */
|
|
688
|
+
async function addFavoriteFolder(kind, name) {
|
|
689
|
+
const trimmed = name.trim();
|
|
690
|
+
if (trimmed === "") return null;
|
|
691
|
+
try {
|
|
692
|
+
const db = await getDB();
|
|
693
|
+
if ((await readAll(db, FAV_FOLDER_STORE)).some((folder) => folder.kind === kind && folder.name === trimmed)) return null;
|
|
694
|
+
const folder = {
|
|
695
|
+
id: folderIdOf(kind, trimmed),
|
|
696
|
+
kind,
|
|
697
|
+
name: trimmed,
|
|
698
|
+
addedAt: Date.now()
|
|
699
|
+
};
|
|
700
|
+
await new Promise((resolve, reject) => {
|
|
701
|
+
const req = db.transaction(FAV_FOLDER_STORE, "readwrite").objectStore(FAV_FOLDER_STORE).put(folder);
|
|
702
|
+
req.onsuccess = () => resolve();
|
|
703
|
+
req.onerror = () => reject(req.error);
|
|
704
|
+
});
|
|
705
|
+
notifyFavorites();
|
|
706
|
+
return folder;
|
|
707
|
+
} catch (err) {
|
|
708
|
+
console.warn("[dsh-image-gen] Failed to add favorite folder:", err);
|
|
709
|
+
return null;
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
/** List all favorite folders. */
|
|
713
|
+
async function getFavoriteFolders() {
|
|
714
|
+
try {
|
|
715
|
+
return (await readAll(await getDB(), FAV_FOLDER_STORE)).sort((a, b) => a.addedAt - b.addedAt);
|
|
716
|
+
} catch (err) {
|
|
717
|
+
console.warn("[dsh-image-gen] Failed to read favorite folders:", err);
|
|
718
|
+
return [];
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
/** Delete a folder; member favorites survive and become unfiled. */
|
|
722
|
+
async function deleteFavoriteFolder(id) {
|
|
723
|
+
try {
|
|
724
|
+
const db = await getDB();
|
|
725
|
+
await new Promise((resolve, reject) => {
|
|
726
|
+
const tx = db.transaction(FAV_PROMPT_STORE, "readwrite");
|
|
727
|
+
const req = tx.objectStore(FAV_PROMPT_STORE).openCursor();
|
|
728
|
+
req.onsuccess = (event) => {
|
|
729
|
+
const cursor = event.target.result;
|
|
730
|
+
if (cursor) {
|
|
731
|
+
const row = cursor.value;
|
|
732
|
+
if (row.folderId === id) {
|
|
733
|
+
delete row.folderId;
|
|
734
|
+
cursor.update(row);
|
|
735
|
+
}
|
|
736
|
+
cursor.continue();
|
|
737
|
+
}
|
|
738
|
+
};
|
|
739
|
+
tx.oncomplete = () => resolve();
|
|
740
|
+
tx.onerror = () => reject(tx.error);
|
|
741
|
+
});
|
|
742
|
+
await new Promise((resolve, reject) => {
|
|
743
|
+
const req = db.transaction(FAV_FOLDER_STORE, "readwrite").objectStore(FAV_FOLDER_STORE).delete(id);
|
|
744
|
+
req.onsuccess = () => resolve();
|
|
745
|
+
req.onerror = () => reject(req.error);
|
|
746
|
+
});
|
|
747
|
+
notifyFavorites();
|
|
748
|
+
} catch (err) {
|
|
749
|
+
console.warn("[dsh-image-gen] Failed to delete favorite folder:", err);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
async function moveFavorite(storeName, id, folderId) {
|
|
753
|
+
try {
|
|
754
|
+
const db = await getDB();
|
|
755
|
+
const ok = await new Promise((resolve, reject) => {
|
|
756
|
+
const tx = db.transaction(storeName, "readwrite");
|
|
757
|
+
const req = tx.objectStore(storeName).get(id);
|
|
758
|
+
req.onsuccess = () => {
|
|
759
|
+
const row = req.result;
|
|
760
|
+
if (row === void 0) {
|
|
761
|
+
resolve(false);
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
764
|
+
if (folderId === void 0) delete row.folderId;
|
|
765
|
+
else row.folderId = folderId;
|
|
766
|
+
tx.objectStore(storeName).put(row);
|
|
767
|
+
resolve(true);
|
|
768
|
+
};
|
|
769
|
+
tx.onerror = () => reject(tx.error);
|
|
770
|
+
});
|
|
771
|
+
if (ok) notifyFavorites();
|
|
772
|
+
return ok;
|
|
773
|
+
} catch (err) {
|
|
774
|
+
console.warn("[dsh-image-gen] Failed to move favorite:", err);
|
|
775
|
+
return false;
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
/** File a favorite prompt into a folder (undefined unfiles it). */
|
|
779
|
+
function moveFavoritePrompt(id, folderId) {
|
|
780
|
+
return moveFavorite(FAV_PROMPT_STORE, id, folderId);
|
|
781
|
+
}
|
|
782
|
+
/** Rewrite a favorite prompt's text in place, keeping its id stable. */
|
|
783
|
+
async function updateFavoritePrompt(id, text) {
|
|
784
|
+
const trimmed = text.trim();
|
|
785
|
+
if (trimmed === "") return false;
|
|
786
|
+
try {
|
|
787
|
+
const db = await getDB();
|
|
788
|
+
const ok = await new Promise((resolve, reject) => {
|
|
789
|
+
const tx = db.transaction(FAV_PROMPT_STORE, "readwrite");
|
|
790
|
+
const req = tx.objectStore(FAV_PROMPT_STORE).get(id);
|
|
791
|
+
req.onsuccess = () => {
|
|
792
|
+
const row = req.result;
|
|
793
|
+
if (row === void 0) {
|
|
794
|
+
resolve(false);
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
row.text = trimmed;
|
|
798
|
+
tx.objectStore(FAV_PROMPT_STORE).put(row);
|
|
799
|
+
resolve(true);
|
|
800
|
+
};
|
|
801
|
+
tx.onerror = () => reject(tx.error);
|
|
802
|
+
});
|
|
803
|
+
if (ok) notifyFavorites();
|
|
804
|
+
return ok;
|
|
805
|
+
} catch (err) {
|
|
806
|
+
console.warn("[dsh-image-gen] Failed to update favorite prompt:", err);
|
|
807
|
+
return false;
|
|
808
|
+
}
|
|
809
|
+
}
|
|
566
810
|
//#endregion
|
|
567
811
|
//#region node_modules/.pnpm/lucide-react@1.38.0_react@18.3.1/node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.mjs
|
|
568
812
|
/**
|
|
@@ -1209,6 +1453,34 @@ window.__ModuleLoader__.load({
|
|
|
1209
1453
|
* This source code is licensed under the ISC license.
|
|
1210
1454
|
* See the LICENSE file in the root directory of this source tree.
|
|
1211
1455
|
*/
|
|
1456
|
+
const Shuffle = createLucideIcon("shuffle", [
|
|
1457
|
+
["path", {
|
|
1458
|
+
d: "m18 14 4 4-4 4",
|
|
1459
|
+
key: "10pe0f"
|
|
1460
|
+
}],
|
|
1461
|
+
["path", {
|
|
1462
|
+
d: "m18 2 4 4-4 4",
|
|
1463
|
+
key: "pucp1d"
|
|
1464
|
+
}],
|
|
1465
|
+
["path", {
|
|
1466
|
+
d: "M2 18h1.973a4 4 0 0 0 3.3-1.7l5.454-8.6a4 4 0 0 1 3.3-1.7H22",
|
|
1467
|
+
key: "1ailkh"
|
|
1468
|
+
}],
|
|
1469
|
+
["path", {
|
|
1470
|
+
d: "M2 6h1.972a4 4 0 0 1 3.6 2.2",
|
|
1471
|
+
key: "km57vx"
|
|
1472
|
+
}],
|
|
1473
|
+
["path", {
|
|
1474
|
+
d: "M22 18h-6.041a4 4 0 0 1-3.3-1.8l-.359-.45",
|
|
1475
|
+
key: "os18l9"
|
|
1476
|
+
}]
|
|
1477
|
+
]);
|
|
1478
|
+
/**
|
|
1479
|
+
* @license lucide-react v1.38.0 - ISC
|
|
1480
|
+
*
|
|
1481
|
+
* This source code is licensed under the ISC license.
|
|
1482
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
1483
|
+
*/
|
|
1212
1484
|
const SlidersHorizontal = createLucideIcon("sliders-horizontal", [
|
|
1213
1485
|
["path", {
|
|
1214
1486
|
d: "M10 5H3",
|
|
@@ -115760,6 +116032,24 @@ img.ProseMirror-separator {
|
|
|
115760
116032
|
}
|
|
115761
116033
|
});
|
|
115762
116034
|
}
|
|
116035
|
+
/**
|
|
116036
|
+
* Match tldraw's light/dark canvas to the DSH host theme. The host publishes
|
|
116037
|
+
* dark mode as the data-ds-dark-theme attribute on <body>; tldraw keeps its
|
|
116038
|
+
* own persisted user preference, so apply the host value now and observe
|
|
116039
|
+
* later flips. Returns the observer disposer.
|
|
116040
|
+
*/
|
|
116041
|
+
function syncTldrawThemeWithHost(editor) {
|
|
116042
|
+
const apply = () => {
|
|
116043
|
+
editor.user.updateUserPreferences({ colorScheme: document.body.hasAttribute("data-ds-dark-theme") ? "dark" : "light" });
|
|
116044
|
+
};
|
|
116045
|
+
apply();
|
|
116046
|
+
const observer = new MutationObserver(apply);
|
|
116047
|
+
observer.observe(document.body, {
|
|
116048
|
+
attributes: true,
|
|
116049
|
+
attributeFilter: ["data-ds-dark-theme"]
|
|
116050
|
+
});
|
|
116051
|
+
return () => observer.disconnect();
|
|
116052
|
+
}
|
|
115763
116053
|
//#endregion
|
|
115764
116054
|
//#region lib/types/client/tl/canvas-selection.js
|
|
115765
116055
|
/** Bound raster dimensions before exporting; large multi-image PNGs get a
|
|
@@ -116425,6 +116715,7 @@ img.ProseMirror-separator {
|
|
|
116425
116715
|
editor.run(() => editor.selectNone());
|
|
116426
116716
|
mountedEditors.add(editor);
|
|
116427
116717
|
applyBrandTheme(editor);
|
|
116718
|
+
const stopThemeSync = syncTldrawThemeWithHost(editor);
|
|
116428
116719
|
editor.updateInstanceState({ isGridMode: true });
|
|
116429
116720
|
console.info(`[dsh-image-gen] tldraw mounted (instance ${editor.id})`);
|
|
116430
116721
|
const stopLanding = registerTlLandingConsumer((items) => {
|
|
@@ -116460,6 +116751,7 @@ img.ProseMirror-separator {
|
|
|
116460
116751
|
mountedEditors.delete(editor);
|
|
116461
116752
|
mountedCanvases.delete(clear);
|
|
116462
116753
|
stopLanding();
|
|
116754
|
+
stopThemeSync();
|
|
116463
116755
|
stopSync();
|
|
116464
116756
|
retrySync.current = () => {};
|
|
116465
116757
|
};
|
|
@@ -116504,6 +116796,31 @@ img.ProseMirror-separator {
|
|
|
116504
116796
|
unconfigured: "未配置",
|
|
116505
116797
|
recent: "最近生成",
|
|
116506
116798
|
empty: "暂无生成历史",
|
|
116799
|
+
railTabRecent: "最新生成",
|
|
116800
|
+
railTabFavorites: "收藏",
|
|
116801
|
+
favImages: "收藏图片",
|
|
116802
|
+
favPrompts: "收藏提示词",
|
|
116803
|
+
favNewFolder: "新建文件夹",
|
|
116804
|
+
favFolderPlaceholder: "文件夹名称",
|
|
116805
|
+
favCreate: "创建",
|
|
116806
|
+
favCancel: "取消",
|
|
116807
|
+
favMoveTo: "移动到文件夹",
|
|
116808
|
+
favNoFolder: "未分组",
|
|
116809
|
+
favMove: "移动",
|
|
116810
|
+
favDeleteFolder: "删除文件夹",
|
|
116811
|
+
favEditPrompt: "编辑提示词",
|
|
116812
|
+
favUse: "使用",
|
|
116813
|
+
favSave: "保存",
|
|
116814
|
+
favEditPromptPlaceholder: "输入提示词内容…",
|
|
116815
|
+
favFolder: "所属文件夹",
|
|
116816
|
+
favEmptyImages: "在图片操作区点「收藏」后,图片会显示在这里",
|
|
116817
|
+
favEmptyPrompts: "点提示词输入框旁的「☆ 收藏」后,提示词会显示在这里",
|
|
116818
|
+
favoritePrompt: "收藏提示词",
|
|
116819
|
+
favActionShort: "收藏",
|
|
116820
|
+
favPromptSaved: "已收藏提示词",
|
|
116821
|
+
favPromptApplied: "已填入提示词",
|
|
116822
|
+
favRefApplied: "已加入参考图",
|
|
116823
|
+
favSaveFailed: "收藏失败,请重试",
|
|
116507
116824
|
generate: "文生图",
|
|
116508
116825
|
edit: "图生图",
|
|
116509
116826
|
reference: "参考图",
|
|
@@ -116560,6 +116877,8 @@ img.ProseMirror-separator {
|
|
|
116560
116877
|
infiniteCanvas: "无限画布",
|
|
116561
116878
|
loading: "正在读取图片…",
|
|
116562
116879
|
generationFailed: "生成失败",
|
|
116880
|
+
gatewayTimeout: "请求被反向代理中断(超时):请重试;反复出现需调大代理超时或换直连网络",
|
|
116881
|
+
requestFailed: "请求失败(HTTP {status})",
|
|
116563
116882
|
selectHistory: "从左侧选择一张图片,或在右侧开始新的生成。",
|
|
116564
116883
|
created: "生成时间",
|
|
116565
116884
|
elapsed: "耗时",
|
|
@@ -116567,6 +116886,7 @@ img.ProseMirror-separator {
|
|
|
116567
116886
|
output: "输出参数",
|
|
116568
116887
|
closeReference: "移除参考图",
|
|
116569
116888
|
uploadInvalid: "请选择有效的图片文件(最大 10MB)",
|
|
116889
|
+
uploadUnreadable: "部分图片读取失败,请重新选择后再试",
|
|
116570
116890
|
imageLoadFailed: "图片读取失败",
|
|
116571
116891
|
fullscreen: "大图全屏",
|
|
116572
116892
|
close: "关闭",
|
|
@@ -116613,6 +116933,31 @@ img.ProseMirror-separator {
|
|
|
116613
116933
|
unconfigured: "Not configured",
|
|
116614
116934
|
recent: "Recent generations",
|
|
116615
116935
|
empty: "No generated images yet",
|
|
116936
|
+
railTabRecent: "Latest",
|
|
116937
|
+
railTabFavorites: "Favorites",
|
|
116938
|
+
favImages: "Favorite images",
|
|
116939
|
+
favPrompts: "Favorite prompts",
|
|
116940
|
+
favNewFolder: "New folder",
|
|
116941
|
+
favFolderPlaceholder: "Folder name",
|
|
116942
|
+
favCreate: "Create",
|
|
116943
|
+
favCancel: "Cancel",
|
|
116944
|
+
favMoveTo: "Move to folder",
|
|
116945
|
+
favNoFolder: "Unfiled",
|
|
116946
|
+
favMove: "Move",
|
|
116947
|
+
favDeleteFolder: "Delete folder",
|
|
116948
|
+
favEditPrompt: "Edit prompt",
|
|
116949
|
+
favUse: "Use",
|
|
116950
|
+
favSave: "Save",
|
|
116951
|
+
favEditPromptPlaceholder: "Prompt text…",
|
|
116952
|
+
favFolder: "Folder",
|
|
116953
|
+
favEmptyImages: "Click Favorite on an image; favorited images appear here",
|
|
116954
|
+
favEmptyPrompts: "Click ☆ Save beside the prompt box",
|
|
116955
|
+
favoritePrompt: "Save prompt",
|
|
116956
|
+
favActionShort: "Save",
|
|
116957
|
+
favPromptSaved: "Prompt saved",
|
|
116958
|
+
favPromptApplied: "Prompt applied",
|
|
116959
|
+
favRefApplied: "Reference added",
|
|
116960
|
+
favSaveFailed: "Could not save; please retry",
|
|
116616
116961
|
generate: "Text to image",
|
|
116617
116962
|
edit: "Image to image",
|
|
116618
116963
|
reference: "Reference image",
|
|
@@ -116669,6 +117014,8 @@ img.ProseMirror-separator {
|
|
|
116669
117014
|
infiniteCanvas: "Infinite canvas",
|
|
116670
117015
|
loading: "Loading image…",
|
|
116671
117016
|
generationFailed: "Generation failed",
|
|
117017
|
+
gatewayTimeout: "The reverse proxy cut the request (timeout): retry; if it repeats, raise the proxy timeout or use a direct network.",
|
|
117018
|
+
requestFailed: "Request failed (HTTP {status})",
|
|
116672
117019
|
selectHistory: "Select an image on the left, or start a new generation on the right.",
|
|
116673
117020
|
created: "Created",
|
|
116674
117021
|
elapsed: "Elapsed",
|
|
@@ -116676,6 +117023,7 @@ img.ProseMirror-separator {
|
|
|
116676
117023
|
output: "Output",
|
|
116677
117024
|
closeReference: "Remove reference",
|
|
116678
117025
|
uploadInvalid: "Choose a valid image file up to 10MB.",
|
|
117026
|
+
uploadUnreadable: "Some images could not be read; pick them again.",
|
|
116679
117027
|
imageLoadFailed: "Could not load image",
|
|
116680
117028
|
fullscreen: "Fullscreen",
|
|
116681
117029
|
close: "Close",
|
|
@@ -116719,17 +117067,28 @@ img.ProseMirror-separator {
|
|
|
116719
117067
|
};
|
|
116720
117068
|
/** localStorage flag remembering that the one-time infinite-canvas hint was dismissed. */
|
|
116721
117069
|
const INFINITE_CANVAS_HINT_KEY = "dsh-ig-infinite-canvas-hint-dismissed";
|
|
116722
|
-
const StudioView = ({ locale, credentialEvents, workspace, initialPrompt, initialCanvasSurface, showInfiniteCanvasHint, onInitialPromptApplied, onOpenInspiration }) => {
|
|
117070
|
+
const StudioView = ({ locale, credentialEvents, workspace, initialPrompt, initialReference, initialCanvasSurface, showInfiniteCanvasHint, onInitialPromptApplied, onInitialReferenceApplied, onOpenInspiration }) => {
|
|
116723
117071
|
const [lang, setLang] = (0, react.useState)(() => locale?.getSnapshot?.().active?.startsWith("en") ? "en" : "zh");
|
|
116724
117072
|
const [config, setConfig] = (0, react.useState)(null);
|
|
116725
117073
|
const [configLoading, setConfigLoading] = (0, react.useState)(true);
|
|
116726
117074
|
const [configError, setConfigError] = (0, react.useState)(null);
|
|
116727
117075
|
const [items, setItems] = (0, react.useState)([]);
|
|
117076
|
+
/** Which rail tab is showing: generation history or the favorites rail. */
|
|
117077
|
+
const [railTab, setRailTab] = (0, react.useState)("recent");
|
|
117078
|
+
const [favPrompts, setFavPrompts] = (0, react.useState)([]);
|
|
117079
|
+
const [favFolders, setFavFolders] = (0, react.useState)([]);
|
|
117080
|
+
const [activePromptFolder, setActivePromptFolder] = (0, react.useState)("");
|
|
117081
|
+
const [folderDraft, setFolderDraft] = (0, react.useState)(null);
|
|
117082
|
+
const [folderDraftName, setFolderDraftName] = (0, react.useState)("");
|
|
117083
|
+
const [editingPrompt, setEditingPrompt] = (0, react.useState)(null);
|
|
117084
|
+
const [editPromptText, setEditPromptText] = (0, react.useState)("");
|
|
117085
|
+
const [editPromptFolder, setEditPromptFolder] = (0, react.useState)("");
|
|
117086
|
+
const [movingFav, setMovingFav] = (0, react.useState)(null);
|
|
116728
117087
|
const [sidebarCollapsed, setSidebarCollapsed] = (0, react.useState)(false);
|
|
116729
117088
|
/** Manual-only collapse for the right generate form; the form stays put in
|
|
116730
117089
|
* narrow seats because it is the primary generation surface. Starts folded
|
|
116731
117090
|
* when the studio opens straight into the infinite canvas. */
|
|
116732
|
-
const [generateCollapsed, setGenerateCollapsed] = (0, react.useState)(initialCanvasSurface === "infinite");
|
|
117091
|
+
const [generateCollapsed, setGenerateCollapsed] = (0, react.useState)(initialCanvasSurface === "infinite" && initialPrompt === void 0);
|
|
116733
117092
|
/** Workbench root, observed so a narrow column (right sidebar) can fold the recent rail. */
|
|
116734
117093
|
const workbenchRootRef = (0, react.useRef)(null);
|
|
116735
117094
|
/** Set once the user toggles the rail by hand; auto-folding then stands down for this mount. */
|
|
@@ -116833,6 +117192,15 @@ img.ProseMirror-separator {
|
|
|
116833
117192
|
for (const [name, value] of Object.entries(values ?? {})) text = text.replace(`{${name}}`, value);
|
|
116834
117193
|
return text;
|
|
116835
117194
|
};
|
|
117195
|
+
/** Parse a studio response body; a gateway HTML error page (502/504 from a
|
|
117196
|
+
* reverse proxy) must surface as a readable message, not a JSON SyntaxError. */
|
|
117197
|
+
const readStudioBody = async (response) => {
|
|
117198
|
+
try {
|
|
117199
|
+
return await response.json();
|
|
117200
|
+
} catch {
|
|
117201
|
+
return { error: response.status === 502 || response.status === 504 ? t("gatewayTimeout") : t("requestFailed", { status: String(response.status) }) };
|
|
117202
|
+
}
|
|
117203
|
+
};
|
|
116836
117204
|
(0, react.useEffect)(() => locale?.subscribe?.(() => setLang(locale.getSnapshot().active?.startsWith("en") ? "en" : "zh")), [locale]);
|
|
116837
117205
|
const formStateRef = (0, react.useRef)({
|
|
116838
117206
|
provider,
|
|
@@ -116854,7 +117222,7 @@ img.ProseMirror-separator {
|
|
|
116854
117222
|
signal: controller.signal,
|
|
116855
117223
|
credentials: "same-origin"
|
|
116856
117224
|
});
|
|
116857
|
-
const payload = await response
|
|
117225
|
+
const payload = await readStudioBody(response);
|
|
116858
117226
|
if (!response.ok || !("providers" in payload)) throw new Error("error" in payload && payload.error ? payload.error : "Studio unavailable");
|
|
116859
117227
|
setConfig(payload);
|
|
116860
117228
|
if (silent) {
|
|
@@ -116900,6 +117268,20 @@ img.ProseMirror-separator {
|
|
|
116900
117268
|
unsubscribe();
|
|
116901
117269
|
};
|
|
116902
117270
|
}, []);
|
|
117271
|
+
(0, react.useEffect)(() => {
|
|
117272
|
+
let mounted = true;
|
|
117273
|
+
const load = () => void Promise.all([getFavoritePrompts(), getFavoriteFolders()]).then(([prompts, folders]) => {
|
|
117274
|
+
if (!mounted) return;
|
|
117275
|
+
setFavPrompts(prompts);
|
|
117276
|
+
setFavFolders(folders);
|
|
117277
|
+
});
|
|
117278
|
+
load();
|
|
117279
|
+
const unsubscribe = subscribeFavorites(load);
|
|
117280
|
+
return () => {
|
|
117281
|
+
mounted = false;
|
|
117282
|
+
unsubscribe();
|
|
117283
|
+
};
|
|
117284
|
+
}, []);
|
|
116903
117285
|
(0, react.useEffect)(() => {
|
|
116904
117286
|
return () => {
|
|
116905
117287
|
requestRef.current?.abort();
|
|
@@ -117024,7 +117406,65 @@ img.ProseMirror-separator {
|
|
|
117024
117406
|
};
|
|
117025
117407
|
};
|
|
117026
117408
|
const handleImageClick = () => {};
|
|
117027
|
-
|
|
117409
|
+
/** Keep the current prompt text in the favorites rail. */
|
|
117410
|
+
const handleFavoritePrompt = async () => {
|
|
117411
|
+
if (prompt.trim().length === 0) {
|
|
117412
|
+
setError(t("needPrompt"));
|
|
117413
|
+
return;
|
|
117414
|
+
}
|
|
117415
|
+
if (await saveFavoritePrompt(prompt)) {
|
|
117416
|
+
railToggledByUserRef.current = true;
|
|
117417
|
+
setSidebarCollapsed(false);
|
|
117418
|
+
setRailTab("favorites");
|
|
117419
|
+
flash(t("favPromptSaved"));
|
|
117420
|
+
} else setError(t("favSaveFailed"));
|
|
117421
|
+
};
|
|
117422
|
+
/** Turn one favorited gallery image back into a live reference (edit mode). */
|
|
117423
|
+
const applyFavoriteImage = async (item) => {
|
|
117424
|
+
const max = maxReferences;
|
|
117425
|
+
if (referencesRef.current.length >= max) {
|
|
117426
|
+
setError(t("maxReferencesExceeded", { max: String(max) }));
|
|
117427
|
+
return;
|
|
117428
|
+
}
|
|
117429
|
+
try {
|
|
117430
|
+
const blob = await fetchAttachmentBlob(item.attachment);
|
|
117431
|
+
const newItem = {
|
|
117432
|
+
id: `fav-${item.id}-${Date.now()}`,
|
|
117433
|
+
attachment: item.attachment,
|
|
117434
|
+
previewUrl: URL.createObjectURL(blob)
|
|
117435
|
+
};
|
|
117436
|
+
const next = [...referencesRef.current, newItem];
|
|
117437
|
+
setReferences(next);
|
|
117438
|
+
referencesRef.current = next;
|
|
117439
|
+
setMode("edit");
|
|
117440
|
+
setError(null);
|
|
117441
|
+
flash(t("favRefApplied"));
|
|
117442
|
+
} catch {
|
|
117443
|
+
setError(t("imageLoadFailed"));
|
|
117444
|
+
}
|
|
117445
|
+
};
|
|
117446
|
+
const createFavFolder = async () => {
|
|
117447
|
+
if (await addFavoriteFolder("prompt", folderDraftName) === null) {
|
|
117448
|
+
flash(t("favSaveFailed"));
|
|
117449
|
+
return;
|
|
117450
|
+
}
|
|
117451
|
+
setFolderDraft(null);
|
|
117452
|
+
setFolderDraftName("");
|
|
117453
|
+
};
|
|
117454
|
+
const openPromptEditor = (fav) => {
|
|
117455
|
+
setEditingPrompt(fav);
|
|
117456
|
+
setEditPromptText(fav.text);
|
|
117457
|
+
setEditPromptFolder(fav.folderId ?? "");
|
|
117458
|
+
};
|
|
117459
|
+
const doMoveFavorite = (folderId) => {
|
|
117460
|
+
if (movingFav === null) return;
|
|
117461
|
+
moveFavoritePrompt(movingFav.id, folderId);
|
|
117462
|
+
};
|
|
117463
|
+
const applyFavoritePrompt = (fav) => {
|
|
117464
|
+
setPrompt(fav.text);
|
|
117465
|
+
flash(t("favPromptApplied"));
|
|
117466
|
+
};
|
|
117467
|
+
const addReferenceFiles = async (fileList) => {
|
|
117028
117468
|
if (!fileList || fileList.length === 0) return;
|
|
117029
117469
|
const files = Array.from(fileList);
|
|
117030
117470
|
const validFiles = [];
|
|
@@ -117050,13 +117490,31 @@ img.ProseMirror-separator {
|
|
|
117050
117490
|
const toAdd = validFiles.slice(0, available);
|
|
117051
117491
|
if (validFiles.length > available) setError(t("maxReferencesExceeded", { max: String(maxReferences) }));
|
|
117052
117492
|
else setError(null);
|
|
117053
|
-
const
|
|
117493
|
+
const snapshotted = [];
|
|
117494
|
+
for (const file of toAdd) try {
|
|
117495
|
+
const bytes = await file.arrayBuffer();
|
|
117496
|
+
snapshotted.push(new File([bytes], file.name, {
|
|
117497
|
+
type: file.type,
|
|
117498
|
+
lastModified: file.lastModified
|
|
117499
|
+
}));
|
|
117500
|
+
} catch {
|
|
117501
|
+
setError(t("uploadUnreadable"));
|
|
117502
|
+
}
|
|
117503
|
+
const newItems = snapshotted.map((file, idx) => ({
|
|
117054
117504
|
id: `upload-${Date.now()}-${idx}-${Math.random().toString(36).slice(2, 7)}`,
|
|
117055
117505
|
file,
|
|
117056
117506
|
previewUrl: URL.createObjectURL(file)
|
|
117057
117507
|
}));
|
|
117058
117508
|
setReferences((prev) => [...prev, ...newItems]);
|
|
117059
117509
|
};
|
|
117510
|
+
const appliedReferenceRef = (0, react.useRef)(null);
|
|
117511
|
+
(0, react.useEffect)(() => {
|
|
117512
|
+
if (initialReference === void 0 || appliedReferenceRef.current === initialReference) return;
|
|
117513
|
+
appliedReferenceRef.current = initialReference;
|
|
117514
|
+
addReferenceFiles([initialReference]);
|
|
117515
|
+
setMode("edit");
|
|
117516
|
+
onInitialReferenceApplied?.();
|
|
117517
|
+
}, [initialReference, onInitialReferenceApplied]);
|
|
117060
117518
|
const removeReference = (id) => {
|
|
117061
117519
|
const target = referencesRef.current.find((item) => item.id === id);
|
|
117062
117520
|
if (target && target.previewUrl.startsWith("blob:")) URL.revokeObjectURL(target.previewUrl);
|
|
@@ -117188,7 +117646,7 @@ img.ProseMirror-separator {
|
|
|
117188
117646
|
...referencesPayload === void 0 ? {} : { references: referencesPayload }
|
|
117189
117647
|
})
|
|
117190
117648
|
});
|
|
117191
|
-
const payload = await response
|
|
117649
|
+
const payload = await readStudioBody(response);
|
|
117192
117650
|
if (!response.ok || !("attachment" in payload)) throw new Error("error" in payload && payload.error ? payload.error : `${target.profile.label}: ${t("generationFailed")}`);
|
|
117193
117651
|
return {
|
|
117194
117652
|
payload,
|
|
@@ -117251,7 +117709,7 @@ img.ProseMirror-separator {
|
|
|
117251
117709
|
...referencesPayload === void 0 ? {} : { references: referencesPayload }
|
|
117252
117710
|
})
|
|
117253
117711
|
});
|
|
117254
|
-
const payload = await response
|
|
117712
|
+
const payload = await readStudioBody(response);
|
|
117255
117713
|
if (!response.ok || !("attachment" in payload)) throw new Error("error" in payload && payload.error ? payload.error : t("generationFailed"));
|
|
117256
117714
|
const generatedList = Array.isArray(payload.items) && payload.items.length > 0 ? payload.items : [{
|
|
117257
117715
|
attachment: payload.attachment,
|
|
@@ -117323,8 +117781,8 @@ img.ProseMirror-separator {
|
|
|
117323
117781
|
selected,
|
|
117324
117782
|
selectedBatchItems
|
|
117325
117783
|
]);
|
|
117326
|
-
const saveButtonLabel = currentBatch !== null ? pendingGalleryItems.length > 0 ? t("saveSelected", { count: String(pendingGalleryItems.length) }) : selectedBatchItems.length === 0 ? t("saveSelected", { count: "0" }) : t("inGallery") :
|
|
117327
|
-
const saveSelectionComplete = currentBatch === null ?
|
|
117784
|
+
const saveButtonLabel = currentBatch !== null ? pendingGalleryItems.length > 0 ? t("saveSelected", { count: String(pendingGalleryItems.length) }) : selectedBatchItems.length === 0 ? t("saveSelected", { count: "0" }) : t("inGallery") : pendingGalleryItems.length > 0 ? t("saveToGallery") : selected !== null ? t("inGallery") : t("saveToGallery");
|
|
117785
|
+
const saveSelectionComplete = currentBatch === null ? pendingGalleryItems.length === 0 : selectedBatchItems.length > 0 && pendingGalleryItems.length === 0;
|
|
117328
117786
|
const saveGalleryEntry = async (item) => {
|
|
117329
117787
|
let savedTo = item.savedTo;
|
|
117330
117788
|
const targetRoot = workspace?.path || config?.workspaceRoot;
|
|
@@ -117504,44 +117962,272 @@ img.ProseMirror-separator {
|
|
|
117504
117962
|
children: [
|
|
117505
117963
|
!sidebarCollapsed && (0, react_jsx_runtime.jsxs)("aside", {
|
|
117506
117964
|
className: "dsh-ig-recent-panel",
|
|
117507
|
-
children: [
|
|
117508
|
-
|
|
117509
|
-
|
|
117510
|
-
|
|
117511
|
-
|
|
117512
|
-
|
|
117513
|
-
|
|
117514
|
-
|
|
117515
|
-
|
|
117516
|
-
|
|
117517
|
-
|
|
117965
|
+
children: [
|
|
117966
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
117967
|
+
className: "dsh-ig-panel-title",
|
|
117968
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
117969
|
+
style: {
|
|
117970
|
+
display: "flex",
|
|
117971
|
+
alignItems: "center",
|
|
117972
|
+
gap: "8px"
|
|
117973
|
+
},
|
|
117974
|
+
children: [(0, react_jsx_runtime.jsx)("span", { children: railTab === "recent" ? t("recent") : t("railTabFavorites") }), (0, react_jsx_runtime.jsx)("span", {
|
|
117975
|
+
className: "dsh-ig-count-badge",
|
|
117976
|
+
children: railTab === "recent" ? items.length : items.filter((item) => item.isFavorite).length + favPrompts.length
|
|
117977
|
+
})]
|
|
117978
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
117979
|
+
type: "button",
|
|
117980
|
+
className: "dsh-ig-collapse-btn",
|
|
117981
|
+
onClick: () => {
|
|
117982
|
+
railToggledByUserRef.current = true;
|
|
117983
|
+
setSidebarCollapsed(true);
|
|
117984
|
+
},
|
|
117985
|
+
title: t("collapseSidebar"),
|
|
117986
|
+
children: (0, react_jsx_runtime.jsx)(PanelLeftClose, { size: 15 })
|
|
117518
117987
|
})]
|
|
117519
|
-
}),
|
|
117520
|
-
|
|
117521
|
-
className: "dsh-ig-
|
|
117522
|
-
|
|
117523
|
-
|
|
117524
|
-
|
|
117525
|
-
|
|
117526
|
-
|
|
117527
|
-
|
|
117528
|
-
|
|
117529
|
-
|
|
117530
|
-
|
|
117531
|
-
|
|
117532
|
-
|
|
117533
|
-
|
|
117534
|
-
|
|
117535
|
-
|
|
117536
|
-
|
|
117537
|
-
|
|
117538
|
-
}
|
|
117539
|
-
|
|
117540
|
-
className: "dsh-ig-
|
|
117541
|
-
|
|
117542
|
-
|
|
117543
|
-
|
|
117544
|
-
|
|
117988
|
+
}),
|
|
117989
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
117990
|
+
className: "dsh-ig-rail-tabs",
|
|
117991
|
+
role: "tablist",
|
|
117992
|
+
children: [(0, react_jsx_runtime.jsx)("button", {
|
|
117993
|
+
type: "button",
|
|
117994
|
+
role: "tab",
|
|
117995
|
+
"aria-selected": railTab === "recent",
|
|
117996
|
+
className: `dsh-ig-rail-tab ${railTab === "recent" ? "is-active" : ""}`,
|
|
117997
|
+
onClick: () => setRailTab("recent"),
|
|
117998
|
+
children: t("railTabRecent")
|
|
117999
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
118000
|
+
type: "button",
|
|
118001
|
+
role: "tab",
|
|
118002
|
+
"aria-selected": railTab === "favorites",
|
|
118003
|
+
className: `dsh-ig-rail-tab ${railTab === "favorites" ? "is-active" : ""}`,
|
|
118004
|
+
onClick: () => setRailTab("favorites"),
|
|
118005
|
+
children: t("railTabFavorites")
|
|
118006
|
+
})]
|
|
118007
|
+
}),
|
|
118008
|
+
railTab === "recent" ? (0, react_jsx_runtime.jsxs)("div", {
|
|
118009
|
+
className: "dsh-ig-recent-scroll",
|
|
118010
|
+
children: [items.length === 0 ? (0, react_jsx_runtime.jsxs)("div", {
|
|
118011
|
+
className: "dsh-ig-recent-empty",
|
|
118012
|
+
children: [(0, react_jsx_runtime.jsx)(ImagePlus, { size: 22 }), (0, react_jsx_runtime.jsx)("span", { children: t("empty") })]
|
|
118013
|
+
}) : displayItems.map((item) => (0, react_jsx_runtime.jsx)(RecentItem, {
|
|
118014
|
+
item,
|
|
118015
|
+
active: selected?.id === item.id,
|
|
118016
|
+
onClick: () => selectItem(item)
|
|
118017
|
+
}, item.id)), items.length > visibleLimit && (0, react_jsx_runtime.jsx)("button", {
|
|
118018
|
+
type: "button",
|
|
118019
|
+
className: "dsh-ig-load-more",
|
|
118020
|
+
onClick: () => setVisibleLimit((l) => l + 30),
|
|
118021
|
+
children: t("loadMore", { n: String(items.length - visibleLimit) })
|
|
118022
|
+
})]
|
|
118023
|
+
}) : (0, react_jsx_runtime.jsxs)("div", {
|
|
118024
|
+
className: "dsh-ig-fav-scroll",
|
|
118025
|
+
children: [
|
|
118026
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
118027
|
+
className: "dsh-ig-fav-section-label",
|
|
118028
|
+
children: (0, react_jsx_runtime.jsx)("span", { children: t("favImages") })
|
|
118029
|
+
}),
|
|
118030
|
+
(() => {
|
|
118031
|
+
const list = items.filter((item) => item.isFavorite);
|
|
118032
|
+
if (list.length === 0) return (0, react_jsx_runtime.jsxs)("div", {
|
|
118033
|
+
className: "dsh-ig-fav-empty",
|
|
118034
|
+
children: [(0, react_jsx_runtime.jsx)(ImagePlus, { size: 18 }), (0, react_jsx_runtime.jsx)("span", { children: t("favEmptyImages") })]
|
|
118035
|
+
});
|
|
118036
|
+
return (0, react_jsx_runtime.jsx)("div", {
|
|
118037
|
+
className: "dsh-ig-fav-grid",
|
|
118038
|
+
children: list.map((item) => (0, react_jsx_runtime.jsx)(RecentItem, {
|
|
118039
|
+
item,
|
|
118040
|
+
active: false,
|
|
118041
|
+
onClick: () => void applyFavoriteImage(item)
|
|
118042
|
+
}, item.id))
|
|
118043
|
+
});
|
|
118044
|
+
})(),
|
|
118045
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
118046
|
+
className: "dsh-ig-fav-section-label",
|
|
118047
|
+
children: [(0, react_jsx_runtime.jsx)("span", { children: t("favPrompts") }), (0, react_jsx_runtime.jsx)("button", {
|
|
118048
|
+
type: "button",
|
|
118049
|
+
className: "dsh-ig-fav-folder-add",
|
|
118050
|
+
onClick: () => {
|
|
118051
|
+
setFolderDraft({ kind: "prompt" });
|
|
118052
|
+
setFolderDraftName("");
|
|
118053
|
+
},
|
|
118054
|
+
title: t("favNewFolder"),
|
|
118055
|
+
children: "+"
|
|
118056
|
+
})]
|
|
118057
|
+
}),
|
|
118058
|
+
(0, react_jsx_runtime.jsx)(FavoriteFolderBar, {
|
|
118059
|
+
folders: favFolders.filter((folder) => folder.kind === "prompt"),
|
|
118060
|
+
active: activePromptFolder,
|
|
118061
|
+
onSelect: (id) => setActivePromptFolder(id === activePromptFolder ? "" : id),
|
|
118062
|
+
onDelete: (id) => void deleteFavoriteFolder(id),
|
|
118063
|
+
deleteLabel: t("favDeleteFolder")
|
|
118064
|
+
}),
|
|
118065
|
+
folderDraft?.kind === "prompt" && (0, react_jsx_runtime.jsxs)("div", {
|
|
118066
|
+
className: "dsh-ig-fav-folder-draft",
|
|
118067
|
+
children: [
|
|
118068
|
+
(0, react_jsx_runtime.jsx)("input", {
|
|
118069
|
+
value: folderDraftName,
|
|
118070
|
+
placeholder: t("favFolderPlaceholder"),
|
|
118071
|
+
onChange: (e) => setFolderDraftName(e.target.value),
|
|
118072
|
+
onKeyDown: (e) => {
|
|
118073
|
+
if (e.key === "Enter") createFavFolder();
|
|
118074
|
+
}
|
|
118075
|
+
}),
|
|
118076
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
118077
|
+
type: "button",
|
|
118078
|
+
onClick: () => void createFavFolder(),
|
|
118079
|
+
children: t("favCreate")
|
|
118080
|
+
}),
|
|
118081
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
118082
|
+
type: "button",
|
|
118083
|
+
onClick: () => setFolderDraft(null),
|
|
118084
|
+
children: t("favCancel")
|
|
118085
|
+
})
|
|
118086
|
+
]
|
|
118087
|
+
}),
|
|
118088
|
+
(() => {
|
|
118089
|
+
const list = favPrompts.filter((fav) => activePromptFolder === "" || fav.folderId === activePromptFolder);
|
|
118090
|
+
if (list.length === 0) return (0, react_jsx_runtime.jsxs)("div", {
|
|
118091
|
+
className: "dsh-ig-fav-empty",
|
|
118092
|
+
children: [(0, react_jsx_runtime.jsx)(PencilLine, { size: 18 }), (0, react_jsx_runtime.jsx)("span", { children: t("favEmptyPrompts") })]
|
|
118093
|
+
});
|
|
118094
|
+
return (0, react_jsx_runtime.jsx)("div", {
|
|
118095
|
+
className: "dsh-ig-fav-prompts",
|
|
118096
|
+
children: list.map((fav) => (0, react_jsx_runtime.jsxs)("div", {
|
|
118097
|
+
className: "dsh-ig-fav-prompt",
|
|
118098
|
+
children: [(0, react_jsx_runtime.jsx)("button", {
|
|
118099
|
+
type: "button",
|
|
118100
|
+
className: "dsh-ig-fav-prompt-text",
|
|
118101
|
+
title: fav.text,
|
|
118102
|
+
onClick: () => openPromptEditor(fav),
|
|
118103
|
+
children: fav.text
|
|
118104
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
118105
|
+
type: "button",
|
|
118106
|
+
className: "dsh-ig-fav-del",
|
|
118107
|
+
title: t("remove"),
|
|
118108
|
+
onClick: () => void deleteFavoritePrompt(fav.id),
|
|
118109
|
+
children: (0, react_jsx_runtime.jsx)(X, { size: 11 })
|
|
118110
|
+
})]
|
|
118111
|
+
}, fav.id))
|
|
118112
|
+
});
|
|
118113
|
+
})()
|
|
118114
|
+
]
|
|
118115
|
+
})
|
|
118116
|
+
]
|
|
118117
|
+
}),
|
|
118118
|
+
(editingPrompt !== null || movingFav !== null) && (0, react_jsx_runtime.jsx)("div", {
|
|
118119
|
+
className: "dsh-ig-fav-dialog-wrap",
|
|
118120
|
+
onClick: () => {
|
|
118121
|
+
setEditingPrompt(null);
|
|
118122
|
+
setMovingFav(null);
|
|
118123
|
+
},
|
|
118124
|
+
children: (0, react_jsx_runtime.jsxs)("div", {
|
|
118125
|
+
className: "dsh-ig-fav-dialog",
|
|
118126
|
+
onClick: (e) => e.stopPropagation(),
|
|
118127
|
+
children: [editingPrompt !== null && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
118128
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
118129
|
+
className: "dsh-ig-fav-dialog-title",
|
|
118130
|
+
children: t("favEditPrompt")
|
|
118131
|
+
}),
|
|
118132
|
+
(0, react_jsx_runtime.jsx)("textarea", {
|
|
118133
|
+
className: "dsh-ig-fav-dialog-textarea",
|
|
118134
|
+
value: editPromptText,
|
|
118135
|
+
placeholder: t("favEditPromptPlaceholder"),
|
|
118136
|
+
onChange: (e) => setEditPromptText(e.target.value),
|
|
118137
|
+
rows: 5
|
|
118138
|
+
}),
|
|
118139
|
+
(0, react_jsx_runtime.jsxs)("label", {
|
|
118140
|
+
className: "dsh-ig-fav-dialog-folder-label",
|
|
118141
|
+
children: [t("favFolder"), (0, react_jsx_runtime.jsxs)("select", {
|
|
118142
|
+
value: editPromptFolder,
|
|
118143
|
+
onChange: (e) => setEditPromptFolder(e.target.value),
|
|
118144
|
+
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
118145
|
+
value: "",
|
|
118146
|
+
children: t("favNoFolder")
|
|
118147
|
+
}), favFolders.filter((folder) => folder.kind === "prompt").map((folder) => (0, react_jsx_runtime.jsx)("option", {
|
|
118148
|
+
value: folder.id,
|
|
118149
|
+
children: folder.name
|
|
118150
|
+
}, folder.id))]
|
|
118151
|
+
})]
|
|
118152
|
+
}),
|
|
118153
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
118154
|
+
className: "dsh-ig-fav-dialog-actions",
|
|
118155
|
+
children: [
|
|
118156
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
118157
|
+
type: "button",
|
|
118158
|
+
className: "is-primary",
|
|
118159
|
+
onClick: () => {
|
|
118160
|
+
updateFavoritePrompt(editingPrompt.id, editPromptText).then((ok) => {
|
|
118161
|
+
if (ok) moveFavoritePrompt(editingPrompt.id, editPromptFolder === "" ? void 0 : editPromptFolder);
|
|
118162
|
+
});
|
|
118163
|
+
setEditingPrompt(null);
|
|
118164
|
+
},
|
|
118165
|
+
children: t("favSave")
|
|
118166
|
+
}),
|
|
118167
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
118168
|
+
type: "button",
|
|
118169
|
+
onClick: () => {
|
|
118170
|
+
applyFavoritePrompt({
|
|
118171
|
+
...editingPrompt,
|
|
118172
|
+
text: editPromptText
|
|
118173
|
+
});
|
|
118174
|
+
setEditingPrompt(null);
|
|
118175
|
+
},
|
|
118176
|
+
children: t("favUse")
|
|
118177
|
+
}),
|
|
118178
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
118179
|
+
type: "button",
|
|
118180
|
+
onClick: () => {
|
|
118181
|
+
setMovingFav({
|
|
118182
|
+
kind: "prompt",
|
|
118183
|
+
id: editingPrompt.id,
|
|
118184
|
+
folderId: editingPrompt.folderId
|
|
118185
|
+
});
|
|
118186
|
+
setEditingPrompt(null);
|
|
118187
|
+
},
|
|
118188
|
+
children: t("favMove")
|
|
118189
|
+
}),
|
|
118190
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
118191
|
+
type: "button",
|
|
118192
|
+
onClick: () => setEditingPrompt(null),
|
|
118193
|
+
children: t("favCancel")
|
|
118194
|
+
})
|
|
118195
|
+
]
|
|
118196
|
+
})
|
|
118197
|
+
] }), editingPrompt === null && movingFav !== null && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
118198
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
118199
|
+
className: "dsh-ig-fav-dialog-title",
|
|
118200
|
+
children: t("favMoveTo")
|
|
118201
|
+
}),
|
|
118202
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
118203
|
+
className: "dsh-ig-fav-dialog-folders",
|
|
118204
|
+
children: [(0, react_jsx_runtime.jsx)("button", {
|
|
118205
|
+
type: "button",
|
|
118206
|
+
onClick: () => {
|
|
118207
|
+
doMoveFavorite(void 0);
|
|
118208
|
+
setMovingFav(null);
|
|
118209
|
+
},
|
|
118210
|
+
children: t("favNoFolder")
|
|
118211
|
+
}), favFolders.filter((folder) => folder.kind === movingFav.kind).map((folder) => (0, react_jsx_runtime.jsx)("button", {
|
|
118212
|
+
type: "button",
|
|
118213
|
+
className: movingFav.folderId === folder.id ? "is-current" : "",
|
|
118214
|
+
onClick: () => {
|
|
118215
|
+
doMoveFavorite(folder.id);
|
|
118216
|
+
setMovingFav(null);
|
|
118217
|
+
},
|
|
118218
|
+
children: folder.name
|
|
118219
|
+
}, folder.id))]
|
|
118220
|
+
}),
|
|
118221
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
118222
|
+
className: "dsh-ig-fav-dialog-actions",
|
|
118223
|
+
children: (0, react_jsx_runtime.jsx)("button", {
|
|
118224
|
+
type: "button",
|
|
118225
|
+
onClick: () => setMovingFav(null),
|
|
118226
|
+
children: t("favCancel")
|
|
118227
|
+
})
|
|
118228
|
+
})
|
|
118229
|
+
] })]
|
|
118230
|
+
})
|
|
117545
118231
|
}),
|
|
117546
118232
|
(0, react_jsx_runtime.jsxs)("main", {
|
|
117547
118233
|
className: "dsh-ig-canvas-column",
|
|
@@ -117938,21 +118624,30 @@ img.ProseMirror-separator {
|
|
|
117938
118624
|
" ",
|
|
117939
118625
|
(0, react_jsx_runtime.jsx)("b", { children: "*" })
|
|
117940
118626
|
]
|
|
117941
|
-
}), (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
117942
|
-
|
|
117943
|
-
|
|
117944
|
-
|
|
117945
|
-
|
|
117946
|
-
|
|
117947
|
-
|
|
117948
|
-
|
|
117949
|
-
|
|
117950
|
-
|
|
118627
|
+
}), (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
118628
|
+
(0, react_jsx_runtime.jsxs)("button", {
|
|
118629
|
+
type: "button",
|
|
118630
|
+
className: "dsh-ig-find-inspiration",
|
|
118631
|
+
onClick: onOpenInspiration,
|
|
118632
|
+
children: [(0, react_jsx_runtime.jsx)(Sparkles, { size: 11 }), t("findInspiration")]
|
|
118633
|
+
}),
|
|
118634
|
+
(0, react_jsx_runtime.jsxs)("button", {
|
|
118635
|
+
type: "button",
|
|
118636
|
+
className: "dsh-ig-fav-save-btn",
|
|
118637
|
+
onClick: () => void handleFavoritePrompt(),
|
|
118638
|
+
title: t("favoritePrompt"),
|
|
118639
|
+
children: [(0, react_jsx_runtime.jsx)(Star, { size: 12 }), t("favActionShort")]
|
|
118640
|
+
}),
|
|
118641
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
118642
|
+
type: "button",
|
|
118643
|
+
onClick: () => setPrompt(""),
|
|
118644
|
+
children: t("clear")
|
|
118645
|
+
})
|
|
118646
|
+
] })]
|
|
117951
118647
|
}),
|
|
117952
118648
|
(0, react_jsx_runtime.jsx)("textarea", {
|
|
117953
118649
|
id: "dsh-ig-prompt",
|
|
117954
118650
|
value: prompt,
|
|
117955
|
-
maxLength: 2e3,
|
|
117956
118651
|
onChange: (event) => setPrompt(event.target.value),
|
|
117957
118652
|
onKeyDown: (event) => {
|
|
117958
118653
|
if (event.nativeEvent.isComposing) return;
|
|
@@ -117963,7 +118658,7 @@ img.ProseMirror-separator {
|
|
|
117963
118658
|
},
|
|
117964
118659
|
placeholder: t("promptPlaceholder")
|
|
117965
118660
|
}),
|
|
117966
|
-
(0, react_jsx_runtime.
|
|
118661
|
+
(0, react_jsx_runtime.jsx)("small", { children: prompt.length })
|
|
117967
118662
|
]
|
|
117968
118663
|
}),
|
|
117969
118664
|
config === null ? configLoading ? (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -118556,6 +119251,26 @@ img.ProseMirror-separator {
|
|
|
118556
119251
|
})
|
|
118557
119252
|
});
|
|
118558
119253
|
};
|
|
119254
|
+
const FavoriteFolderBar = ({ folders, active, onSelect, onDelete, deleteLabel }) => {
|
|
119255
|
+
if (folders.length === 0) return null;
|
|
119256
|
+
return (0, react_jsx_runtime.jsx)("div", {
|
|
119257
|
+
className: "dsh-ig-fav-folders",
|
|
119258
|
+
children: folders.map((folder) => (0, react_jsx_runtime.jsxs)("span", {
|
|
119259
|
+
className: `dsh-ig-fav-folder-chip ${active === folder.id ? "is-active" : ""}`,
|
|
119260
|
+
children: [(0, react_jsx_runtime.jsx)("button", {
|
|
119261
|
+
type: "button",
|
|
119262
|
+
onClick: () => onSelect(folder.id),
|
|
119263
|
+
children: folder.name
|
|
119264
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
119265
|
+
type: "button",
|
|
119266
|
+
className: "dsh-ig-fav-folder-del",
|
|
119267
|
+
title: deleteLabel,
|
|
119268
|
+
onClick: () => onDelete(folder.id),
|
|
119269
|
+
children: (0, react_jsx_runtime.jsx)(X, { size: 9 })
|
|
119270
|
+
})]
|
|
119271
|
+
}, folder.id))
|
|
119272
|
+
});
|
|
119273
|
+
};
|
|
118559
119274
|
function useInView() {
|
|
118560
119275
|
const [inView, setInView] = (0, react.useState)(false);
|
|
118561
119276
|
const observerRef = (0, react.useRef)(null);
|
|
@@ -118653,8 +119368,17 @@ img.ProseMirror-separator {
|
|
|
118653
119368
|
const MAX_BYTES = 188743680;
|
|
118654
119369
|
const pending = /* @__PURE__ */ new Map();
|
|
118655
119370
|
let cacheEpoch = 0;
|
|
118656
|
-
|
|
118657
|
-
|
|
119371
|
+
/**
|
|
119372
|
+
* Resolve the IndexedDB key for one image. `rev` (the source's imageRevision,
|
|
119373
|
+
* falling back to its version) namespaces the cache by image content: when a
|
|
119374
|
+
* source re-packages its images at stable case IDs, a bumped rev orphans the
|
|
119375
|
+
* old blobs instead of serving them forever.
|
|
119376
|
+
*/
|
|
119377
|
+
function cacheKey(sourceId, caseId, rev) {
|
|
119378
|
+
return rev === void 0 ? `${sourceId}:${caseId}` : `${sourceId}:${caseId}@${rev}`;
|
|
119379
|
+
}
|
|
119380
|
+
function fetchInspirationImage(sourceId, caseId, rev) {
|
|
119381
|
+
const key = cacheKey(sourceId, caseId, rev);
|
|
118658
119382
|
const existing = pending.get(key);
|
|
118659
119383
|
if (existing !== void 0) return existing;
|
|
118660
119384
|
const requestEpoch = cacheEpoch;
|
|
@@ -118677,8 +119401,8 @@ img.ProseMirror-separator {
|
|
|
118677
119401
|
pending.set(key, task);
|
|
118678
119402
|
return task;
|
|
118679
119403
|
}
|
|
118680
|
-
async function evictInspirationImage(sourceId, caseId) {
|
|
118681
|
-
const key =
|
|
119404
|
+
async function evictInspirationImage(sourceId, caseId, rev) {
|
|
119405
|
+
const key = cacheKey(sourceId, caseId, rev);
|
|
118682
119406
|
pending.delete(key);
|
|
118683
119407
|
const db = await openDatabase$1();
|
|
118684
119408
|
if (db === void 0) return;
|
|
@@ -118865,6 +119589,988 @@ img.ProseMirror-separator {
|
|
|
118865
119589
|
return Array.isArray(sources) && sources.length > 0 && sources.every((source) => typeof source === "object" && source !== null && Array.isArray(source.cases));
|
|
118866
119590
|
}
|
|
118867
119591
|
//#endregion
|
|
119592
|
+
//#region lib/types/inspiration/data/baoyu-compose.json
|
|
119593
|
+
var types = [
|
|
119594
|
+
{
|
|
119595
|
+
"id": "hero",
|
|
119596
|
+
"description": "Large visual impact, title overlay",
|
|
119597
|
+
"composition": "Large focal visual (60-70% area), title overlay on visual, dramatic composition"
|
|
119598
|
+
},
|
|
119599
|
+
{
|
|
119600
|
+
"id": "conceptual",
|
|
119601
|
+
"description": "Concept visualization, abstract core ideas",
|
|
119602
|
+
"composition": "Abstract shapes representing core concepts, information hierarchy, clean zones"
|
|
119603
|
+
},
|
|
119604
|
+
{
|
|
119605
|
+
"id": "typography",
|
|
119606
|
+
"description": "Text-focused layout, prominent title",
|
|
119607
|
+
"composition": "Title as primary element (40%+ area), minimal supporting visuals, strong hierarchy"
|
|
119608
|
+
},
|
|
119609
|
+
{
|
|
119610
|
+
"id": "metaphor",
|
|
119611
|
+
"description": "Visual metaphor, concrete expressing abstract",
|
|
119612
|
+
"composition": "Concrete object/scene representing abstract idea, symbolic elements, emotional resonance"
|
|
119613
|
+
},
|
|
119614
|
+
{
|
|
119615
|
+
"id": "scene",
|
|
119616
|
+
"description": "Atmospheric scene, narrative feel",
|
|
119617
|
+
"composition": "Atmospheric environment, narrative elements, mood-setting lighting and colors"
|
|
119618
|
+
},
|
|
119619
|
+
{
|
|
119620
|
+
"id": "minimal",
|
|
119621
|
+
"description": "Minimalist composition, generous whitespace",
|
|
119622
|
+
"composition": "Single focal element, generous whitespace (60%+), essential shapes only"
|
|
119623
|
+
}
|
|
119624
|
+
];
|
|
119625
|
+
var palettes = [
|
|
119626
|
+
{
|
|
119627
|
+
"id": "warm",
|
|
119628
|
+
"tagline": "Friendly, approachable, human-centered",
|
|
119629
|
+
"colors": [
|
|
119630
|
+
{
|
|
119631
|
+
"role": "Primary 1",
|
|
119632
|
+
"name": "Warm Orange",
|
|
119633
|
+
"hex": "#ed8936"
|
|
119634
|
+
},
|
|
119635
|
+
{
|
|
119636
|
+
"role": "Primary 2",
|
|
119637
|
+
"name": "Golden Yellow",
|
|
119638
|
+
"hex": "#f6ad55"
|
|
119639
|
+
},
|
|
119640
|
+
{
|
|
119641
|
+
"role": "Primary 3",
|
|
119642
|
+
"name": "Terracotta",
|
|
119643
|
+
"hex": "#c05621"
|
|
119644
|
+
},
|
|
119645
|
+
{
|
|
119646
|
+
"role": "Background",
|
|
119647
|
+
"name": "Cream",
|
|
119648
|
+
"hex": "#fffaf0"
|
|
119649
|
+
},
|
|
119650
|
+
{
|
|
119651
|
+
"role": "Background Alt",
|
|
119652
|
+
"name": "Soft Peach",
|
|
119653
|
+
"hex": "#fed7aa"
|
|
119654
|
+
},
|
|
119655
|
+
{
|
|
119656
|
+
"role": "Accent 1",
|
|
119657
|
+
"name": "Deep Brown",
|
|
119658
|
+
"hex": "#744210"
|
|
119659
|
+
},
|
|
119660
|
+
{
|
|
119661
|
+
"role": "Accent 2",
|
|
119662
|
+
"name": "Soft Red",
|
|
119663
|
+
"hex": "#e53e3e"
|
|
119664
|
+
}
|
|
119665
|
+
],
|
|
119666
|
+
"decorativeHints": [
|
|
119667
|
+
"Sun rays, warm lighting effects",
|
|
119668
|
+
"Rounded shapes, organic curves",
|
|
119669
|
+
"Hearts, smiling faces, friendly icons",
|
|
119670
|
+
"Warm gradient overlays"
|
|
119671
|
+
],
|
|
119672
|
+
"bestFor": ""
|
|
119673
|
+
},
|
|
119674
|
+
{
|
|
119675
|
+
"id": "cool",
|
|
119676
|
+
"tagline": "Technical, professional, precise",
|
|
119677
|
+
"colors": [
|
|
119678
|
+
{
|
|
119679
|
+
"role": "Primary 1",
|
|
119680
|
+
"name": "Engineering Blue",
|
|
119681
|
+
"hex": "#2563eb"
|
|
119682
|
+
},
|
|
119683
|
+
{
|
|
119684
|
+
"role": "Primary 2",
|
|
119685
|
+
"name": "Navy Blue",
|
|
119686
|
+
"hex": "#1e3a5f"
|
|
119687
|
+
},
|
|
119688
|
+
{
|
|
119689
|
+
"role": "Primary 3",
|
|
119690
|
+
"name": "Cyan",
|
|
119691
|
+
"hex": "#06b6d4"
|
|
119692
|
+
},
|
|
119693
|
+
{
|
|
119694
|
+
"role": "Background",
|
|
119695
|
+
"name": "Light Gray",
|
|
119696
|
+
"hex": "#f8f9fa"
|
|
119697
|
+
},
|
|
119698
|
+
{
|
|
119699
|
+
"role": "Background Alt",
|
|
119700
|
+
"name": "Blueprint Off-White",
|
|
119701
|
+
"hex": "#faf8f5"
|
|
119702
|
+
},
|
|
119703
|
+
{
|
|
119704
|
+
"role": "Accent 1",
|
|
119705
|
+
"name": "Amber",
|
|
119706
|
+
"hex": "#f59e0b"
|
|
119707
|
+
},
|
|
119708
|
+
{
|
|
119709
|
+
"role": "Accent 2",
|
|
119710
|
+
"name": "Light Blue",
|
|
119711
|
+
"hex": "#bfdbfe"
|
|
119712
|
+
}
|
|
119713
|
+
],
|
|
119714
|
+
"decorativeHints": [
|
|
119715
|
+
"Grid lines and alignment guides",
|
|
119716
|
+
"Dimension indicators and measurements",
|
|
119717
|
+
"Technical schematics and diagrams",
|
|
119718
|
+
"Geometric precision elements"
|
|
119719
|
+
],
|
|
119720
|
+
"bestFor": ""
|
|
119721
|
+
},
|
|
119722
|
+
{
|
|
119723
|
+
"id": "dark",
|
|
119724
|
+
"tagline": "Cinematic, premium, atmospheric",
|
|
119725
|
+
"colors": [
|
|
119726
|
+
{
|
|
119727
|
+
"role": "Primary 1",
|
|
119728
|
+
"name": "Electric Purple",
|
|
119729
|
+
"hex": "#8b5cf6"
|
|
119730
|
+
},
|
|
119731
|
+
{
|
|
119732
|
+
"role": "Primary 2",
|
|
119733
|
+
"name": "Cyan Blue",
|
|
119734
|
+
"hex": "#06b6d4"
|
|
119735
|
+
},
|
|
119736
|
+
{
|
|
119737
|
+
"role": "Primary 3",
|
|
119738
|
+
"name": "Magenta Pink",
|
|
119739
|
+
"hex": "#ec4899"
|
|
119740
|
+
},
|
|
119741
|
+
{
|
|
119742
|
+
"role": "Background",
|
|
119743
|
+
"name": "Deep Purple-Black",
|
|
119744
|
+
"hex": "#0a0a0a"
|
|
119745
|
+
},
|
|
119746
|
+
{
|
|
119747
|
+
"role": "Background Alt",
|
|
119748
|
+
"name": "Rich Navy",
|
|
119749
|
+
"hex": "#1a1a2e"
|
|
119750
|
+
},
|
|
119751
|
+
{
|
|
119752
|
+
"role": "Accent 1",
|
|
119753
|
+
"name": "Amber",
|
|
119754
|
+
"hex": "#f59e0b"
|
|
119755
|
+
},
|
|
119756
|
+
{
|
|
119757
|
+
"role": "Accent 2",
|
|
119758
|
+
"name": "Pure White",
|
|
119759
|
+
"hex": "#ffffff"
|
|
119760
|
+
}
|
|
119761
|
+
],
|
|
119762
|
+
"decorativeHints": [
|
|
119763
|
+
"Glowing accent elements and neon highlights",
|
|
119764
|
+
"Atmospheric fog or particle effects",
|
|
119765
|
+
"Silhouettes with backlit edges",
|
|
119766
|
+
"Subtle gradient backgrounds"
|
|
119767
|
+
],
|
|
119768
|
+
"bestFor": ""
|
|
119769
|
+
},
|
|
119770
|
+
{
|
|
119771
|
+
"id": "earth",
|
|
119772
|
+
"tagline": "Natural, organic, grounded",
|
|
119773
|
+
"colors": [
|
|
119774
|
+
{
|
|
119775
|
+
"role": "Primary 1",
|
|
119776
|
+
"name": "Forest Green",
|
|
119777
|
+
"hex": "#276749"
|
|
119778
|
+
},
|
|
119779
|
+
{
|
|
119780
|
+
"role": "Primary 2",
|
|
119781
|
+
"name": "Sage",
|
|
119782
|
+
"hex": "#9ae6b4"
|
|
119783
|
+
},
|
|
119784
|
+
{
|
|
119785
|
+
"role": "Primary 3",
|
|
119786
|
+
"name": "Earth Brown",
|
|
119787
|
+
"hex": "#744210"
|
|
119788
|
+
},
|
|
119789
|
+
{
|
|
119790
|
+
"role": "Background",
|
|
119791
|
+
"name": "Sand Beige",
|
|
119792
|
+
"hex": "#f5e6d3"
|
|
119793
|
+
},
|
|
119794
|
+
{
|
|
119795
|
+
"role": "Background Alt",
|
|
119796
|
+
"name": "Sky Blue",
|
|
119797
|
+
"hex": "#e0f2fe"
|
|
119798
|
+
},
|
|
119799
|
+
{
|
|
119800
|
+
"role": "Accent 1",
|
|
119801
|
+
"name": "Sunset Orange",
|
|
119802
|
+
"hex": "#ed8936"
|
|
119803
|
+
},
|
|
119804
|
+
{
|
|
119805
|
+
"role": "Accent 2",
|
|
119806
|
+
"name": "Water Blue",
|
|
119807
|
+
"hex": "#63b3ed"
|
|
119808
|
+
}
|
|
119809
|
+
],
|
|
119810
|
+
"decorativeHints": [
|
|
119811
|
+
"Leaves, trees, mountains, natural forms",
|
|
119812
|
+
"Sun, clouds, organic flowing lines",
|
|
119813
|
+
"Botanical illustrations",
|
|
119814
|
+
"Earthy textures and natural patterns"
|
|
119815
|
+
],
|
|
119816
|
+
"bestFor": ""
|
|
119817
|
+
},
|
|
119818
|
+
{
|
|
119819
|
+
"id": "elegant",
|
|
119820
|
+
"tagline": "Sophisticated, refined, understated luxury",
|
|
119821
|
+
"colors": [
|
|
119822
|
+
{
|
|
119823
|
+
"role": "Primary 1",
|
|
119824
|
+
"name": "Soft Coral",
|
|
119825
|
+
"hex": "#e8a598"
|
|
119826
|
+
},
|
|
119827
|
+
{
|
|
119828
|
+
"role": "Primary 2",
|
|
119829
|
+
"name": "Muted Teal",
|
|
119830
|
+
"hex": "#5b8a8a"
|
|
119831
|
+
},
|
|
119832
|
+
{
|
|
119833
|
+
"role": "Primary 3",
|
|
119834
|
+
"name": "Dusty Rose",
|
|
119835
|
+
"hex": "#d4a5a5"
|
|
119836
|
+
},
|
|
119837
|
+
{
|
|
119838
|
+
"role": "Background",
|
|
119839
|
+
"name": "Warm Cream",
|
|
119840
|
+
"hex": "#f5f0e6"
|
|
119841
|
+
},
|
|
119842
|
+
{
|
|
119843
|
+
"role": "Background Alt",
|
|
119844
|
+
"name": "Soft Beige",
|
|
119845
|
+
"hex": "#f0ebe0"
|
|
119846
|
+
},
|
|
119847
|
+
{
|
|
119848
|
+
"role": "Accent 1",
|
|
119849
|
+
"name": "Gold",
|
|
119850
|
+
"hex": "#c9a962"
|
|
119851
|
+
},
|
|
119852
|
+
{
|
|
119853
|
+
"role": "Accent 2",
|
|
119854
|
+
"name": "Copper",
|
|
119855
|
+
"hex": "#b87333"
|
|
119856
|
+
}
|
|
119857
|
+
],
|
|
119858
|
+
"decorativeHints": [
|
|
119859
|
+
"Delicate ornamental details",
|
|
119860
|
+
"Subtle gradients and soft transitions",
|
|
119861
|
+
"Refined geometric patterns",
|
|
119862
|
+
"Balanced, symmetrical compositions"
|
|
119863
|
+
],
|
|
119864
|
+
"bestFor": ""
|
|
119865
|
+
},
|
|
119866
|
+
{
|
|
119867
|
+
"id": "macaron",
|
|
119868
|
+
"tagline": "Soft macaron pastel color blocks on warm cream",
|
|
119869
|
+
"colors": [
|
|
119870
|
+
{
|
|
119871
|
+
"role": "Primary 1",
|
|
119872
|
+
"name": "Sky Blue",
|
|
119873
|
+
"hex": "#a8d8ea"
|
|
119874
|
+
},
|
|
119875
|
+
{
|
|
119876
|
+
"role": "Primary 2",
|
|
119877
|
+
"name": "Mint Green",
|
|
119878
|
+
"hex": "#b5e5cf"
|
|
119879
|
+
},
|
|
119880
|
+
{
|
|
119881
|
+
"role": "Primary 3",
|
|
119882
|
+
"name": "Lavender",
|
|
119883
|
+
"hex": "#d5c6e0"
|
|
119884
|
+
},
|
|
119885
|
+
{
|
|
119886
|
+
"role": "Background",
|
|
119887
|
+
"name": "Warm Cream",
|
|
119888
|
+
"hex": "#f5f0e8"
|
|
119889
|
+
},
|
|
119890
|
+
{
|
|
119891
|
+
"role": "Background Alt",
|
|
119892
|
+
"name": "Peach",
|
|
119893
|
+
"hex": "#ffd5c2"
|
|
119894
|
+
},
|
|
119895
|
+
{
|
|
119896
|
+
"role": "Accent 1",
|
|
119897
|
+
"name": "Coral Red",
|
|
119898
|
+
"hex": "#e8655a"
|
|
119899
|
+
},
|
|
119900
|
+
{
|
|
119901
|
+
"role": "Accent 2",
|
|
119902
|
+
"name": "Deep Charcoal",
|
|
119903
|
+
"hex": "#2d2d2d"
|
|
119904
|
+
}
|
|
119905
|
+
],
|
|
119906
|
+
"decorativeHints": [
|
|
119907
|
+
"Rounded pastel color blocks",
|
|
119908
|
+
"Subtle warm paper grain texture",
|
|
119909
|
+
"Soft shadows, no hard edges",
|
|
119910
|
+
"Gentle gradient transitions between zones"
|
|
119911
|
+
],
|
|
119912
|
+
"bestFor": ""
|
|
119913
|
+
},
|
|
119914
|
+
{
|
|
119915
|
+
"id": "mono",
|
|
119916
|
+
"tagline": "Clean, focused, essential",
|
|
119917
|
+
"colors": [
|
|
119918
|
+
{
|
|
119919
|
+
"role": "Primary 1",
|
|
119920
|
+
"name": "Pure Black",
|
|
119921
|
+
"hex": "#000000"
|
|
119922
|
+
},
|
|
119923
|
+
{
|
|
119924
|
+
"role": "Primary 2",
|
|
119925
|
+
"name": "Near Black",
|
|
119926
|
+
"hex": "#1f1f1f"
|
|
119927
|
+
},
|
|
119928
|
+
{
|
|
119929
|
+
"role": "Primary 3",
|
|
119930
|
+
"name": "Dark Gray",
|
|
119931
|
+
"hex": "#374151"
|
|
119932
|
+
},
|
|
119933
|
+
{
|
|
119934
|
+
"role": "Background",
|
|
119935
|
+
"name": "White",
|
|
119936
|
+
"hex": "#ffffff"
|
|
119937
|
+
},
|
|
119938
|
+
{
|
|
119939
|
+
"role": "Background Alt",
|
|
119940
|
+
"name": "Off-White",
|
|
119941
|
+
"hex": "#fafafa"
|
|
119942
|
+
},
|
|
119943
|
+
{
|
|
119944
|
+
"role": "Accent 2",
|
|
119945
|
+
"name": "Medium Gray",
|
|
119946
|
+
"hex": "#9ca3af"
|
|
119947
|
+
}
|
|
119948
|
+
],
|
|
119949
|
+
"decorativeHints": [
|
|
119950
|
+
"Maximum negative space",
|
|
119951
|
+
"Thin lines and minimal strokes",
|
|
119952
|
+
"Single focal point emphasis",
|
|
119953
|
+
"Stark contrast between elements"
|
|
119954
|
+
],
|
|
119955
|
+
"bestFor": ""
|
|
119956
|
+
},
|
|
119957
|
+
{
|
|
119958
|
+
"id": "pastel",
|
|
119959
|
+
"tagline": "Gentle, whimsical, soft",
|
|
119960
|
+
"colors": [
|
|
119961
|
+
{
|
|
119962
|
+
"role": "Primary 1",
|
|
119963
|
+
"name": "Soft Pink",
|
|
119964
|
+
"hex": "#ffb6c1"
|
|
119965
|
+
},
|
|
119966
|
+
{
|
|
119967
|
+
"role": "Primary 2",
|
|
119968
|
+
"name": "Mint",
|
|
119969
|
+
"hex": "#98d8c8"
|
|
119970
|
+
},
|
|
119971
|
+
{
|
|
119972
|
+
"role": "Primary 3",
|
|
119973
|
+
"name": "Lavender",
|
|
119974
|
+
"hex": "#c8a2c8"
|
|
119975
|
+
},
|
|
119976
|
+
{
|
|
119977
|
+
"role": "Background",
|
|
119978
|
+
"name": "White",
|
|
119979
|
+
"hex": "#ffffff"
|
|
119980
|
+
},
|
|
119981
|
+
{
|
|
119982
|
+
"role": "Background Alt",
|
|
119983
|
+
"name": "Light Cream",
|
|
119984
|
+
"hex": "#fff8e7"
|
|
119985
|
+
},
|
|
119986
|
+
{
|
|
119987
|
+
"role": "Accent 1",
|
|
119988
|
+
"name": "Butter Yellow",
|
|
119989
|
+
"hex": "#fffacd"
|
|
119990
|
+
},
|
|
119991
|
+
{
|
|
119992
|
+
"role": "Accent 2",
|
|
119993
|
+
"name": "Sky Blue",
|
|
119994
|
+
"hex": "#bee3f8"
|
|
119995
|
+
}
|
|
119996
|
+
],
|
|
119997
|
+
"decorativeHints": [
|
|
119998
|
+
"Cute rounded proportions",
|
|
119999
|
+
"Stars, sparkles, flowers, decorative flourishes",
|
|
120000
|
+
"Soft shadows and gentle highlights",
|
|
120001
|
+
"Storybook-style elements"
|
|
120002
|
+
],
|
|
120003
|
+
"bestFor": ""
|
|
120004
|
+
},
|
|
120005
|
+
{
|
|
120006
|
+
"id": "retro",
|
|
120007
|
+
"tagline": "Nostalgic, vintage, classic",
|
|
120008
|
+
"colors": [
|
|
120009
|
+
{
|
|
120010
|
+
"role": "Primary 1",
|
|
120011
|
+
"name": "Coral Red",
|
|
120012
|
+
"hex": "#e07a5f"
|
|
120013
|
+
},
|
|
120014
|
+
{
|
|
120015
|
+
"role": "Primary 2",
|
|
120016
|
+
"name": "Mint Green",
|
|
120017
|
+
"hex": "#81b29a"
|
|
120018
|
+
},
|
|
120019
|
+
{
|
|
120020
|
+
"role": "Primary 3",
|
|
120021
|
+
"name": "Mustard Yellow",
|
|
120022
|
+
"hex": "#f2cc8f"
|
|
120023
|
+
},
|
|
120024
|
+
{
|
|
120025
|
+
"role": "Primary 4",
|
|
120026
|
+
"name": "Dark Maroon",
|
|
120027
|
+
"hex": "#5d3a3a"
|
|
120028
|
+
},
|
|
120029
|
+
{
|
|
120030
|
+
"role": "Background",
|
|
120031
|
+
"name": "Cream Off-White",
|
|
120032
|
+
"hex": "#f5f0e6"
|
|
120033
|
+
},
|
|
120034
|
+
{
|
|
120035
|
+
"role": "Background Alt",
|
|
120036
|
+
"name": "Aged Paper",
|
|
120037
|
+
"hex": "#f5e6d3"
|
|
120038
|
+
},
|
|
120039
|
+
{
|
|
120040
|
+
"role": "Accent 1",
|
|
120041
|
+
"name": "Burnt Orange",
|
|
120042
|
+
"hex": "#d4764a"
|
|
120043
|
+
},
|
|
120044
|
+
{
|
|
120045
|
+
"role": "Accent 2",
|
|
120046
|
+
"name": "Rock Blue",
|
|
120047
|
+
"hex": "#577590"
|
|
120048
|
+
},
|
|
120049
|
+
{
|
|
120050
|
+
"role": "Accent 3",
|
|
120051
|
+
"name": "Vintage Gold",
|
|
120052
|
+
"hex": "#c9a227"
|
|
120053
|
+
},
|
|
120054
|
+
{
|
|
120055
|
+
"role": "Accent 4",
|
|
120056
|
+
"name": "Faded Teal",
|
|
120057
|
+
"hex": "#2f7373"
|
|
120058
|
+
}
|
|
120059
|
+
],
|
|
120060
|
+
"decorativeHints": [
|
|
120061
|
+
"Halftone dots and vintage badges",
|
|
120062
|
+
"Aged textures with subtle paper grain",
|
|
120063
|
+
"Sunburst/radiating lines for energy",
|
|
120064
|
+
"Pill-shaped clouds, small dots and stars",
|
|
120065
|
+
"Classic icons and retro motifs"
|
|
120066
|
+
],
|
|
120067
|
+
"bestFor": ""
|
|
120068
|
+
},
|
|
120069
|
+
{
|
|
120070
|
+
"id": "duotone",
|
|
120071
|
+
"tagline": "Dramatic, cinematic, two-color high contrast",
|
|
120072
|
+
"colors": [
|
|
120073
|
+
{
|
|
120074
|
+
"role": "Primary 1",
|
|
120075
|
+
"name": "Burnt Orange",
|
|
120076
|
+
"hex": "#e8751a"
|
|
120077
|
+
},
|
|
120078
|
+
{
|
|
120079
|
+
"role": "Primary 2",
|
|
120080
|
+
"name": "Deep Teal",
|
|
120081
|
+
"hex": "#0a6e6e"
|
|
120082
|
+
},
|
|
120083
|
+
{
|
|
120084
|
+
"role": "Background",
|
|
120085
|
+
"name": "Off-Black",
|
|
120086
|
+
"hex": "#121212"
|
|
120087
|
+
},
|
|
120088
|
+
{
|
|
120089
|
+
"role": "Background Alt",
|
|
120090
|
+
"name": "Dark Charcoal",
|
|
120091
|
+
"hex": "#1e1e1e"
|
|
120092
|
+
},
|
|
120093
|
+
{
|
|
120094
|
+
"role": "Accent 1",
|
|
120095
|
+
"name": "Warm Cream",
|
|
120096
|
+
"hex": "#f5e6d0"
|
|
120097
|
+
},
|
|
120098
|
+
{
|
|
120099
|
+
"role": "Accent 2",
|
|
120100
|
+
"name": "Amber Highlight",
|
|
120101
|
+
"hex": "#f4a623"
|
|
120102
|
+
}
|
|
120103
|
+
],
|
|
120104
|
+
"decorativeHints": [
|
|
120105
|
+
"Stark two-color separation across entire composition",
|
|
120106
|
+
"Halftone transitions between the two colors",
|
|
120107
|
+
"Silhouettes in one color against the other",
|
|
120108
|
+
"Minimal use of third color (only for small highlights)",
|
|
120109
|
+
"High contrast figure-ground relationships"
|
|
120110
|
+
],
|
|
120111
|
+
"bestFor": "",
|
|
120112
|
+
"pairs": [
|
|
120113
|
+
{
|
|
120114
|
+
"name": "Orange + Teal",
|
|
120115
|
+
"a": "#e8751a",
|
|
120116
|
+
"b": "#0a6e6e",
|
|
120117
|
+
"feel": "Cinematic, action"
|
|
120118
|
+
},
|
|
120119
|
+
{
|
|
120120
|
+
"name": "Red + Cream",
|
|
120121
|
+
"a": "#c0392b",
|
|
120122
|
+
"b": "#f5e6d0",
|
|
120123
|
+
"feel": "Bold, classic"
|
|
120124
|
+
},
|
|
120125
|
+
{
|
|
120126
|
+
"name": "Blue + Gold",
|
|
120127
|
+
"a": "#1a3a5c",
|
|
120128
|
+
"b": "#d4a843",
|
|
120129
|
+
"feel": "Prestigious, premium"
|
|
120130
|
+
},
|
|
120131
|
+
{
|
|
120132
|
+
"name": "Purple + Green",
|
|
120133
|
+
"a": "#6b3fa0",
|
|
120134
|
+
"b": "#2ecc71",
|
|
120135
|
+
"feel": "Futuristic, contrast"
|
|
120136
|
+
},
|
|
120137
|
+
{
|
|
120138
|
+
"name": "Magenta + Cyan",
|
|
120139
|
+
"a": "#c2185b",
|
|
120140
|
+
"b": "#00bcd4",
|
|
120141
|
+
"feel": "Vibrant, pop"
|
|
120142
|
+
},
|
|
120143
|
+
{
|
|
120144
|
+
"name": "Crimson + Navy",
|
|
120145
|
+
"a": "#dc143c",
|
|
120146
|
+
"b": "#0d1b2a",
|
|
120147
|
+
"feel": "Dramatic, noir"
|
|
120148
|
+
}
|
|
120149
|
+
]
|
|
120150
|
+
},
|
|
120151
|
+
{
|
|
120152
|
+
"id": "vivid",
|
|
120153
|
+
"tagline": "Energetic, bold, attention-grabbing",
|
|
120154
|
+
"colors": [
|
|
120155
|
+
{
|
|
120156
|
+
"role": "Primary 1",
|
|
120157
|
+
"name": "Bright Red",
|
|
120158
|
+
"hex": "#ef4444"
|
|
120159
|
+
},
|
|
120160
|
+
{
|
|
120161
|
+
"role": "Primary 2",
|
|
120162
|
+
"name": "Neon Green",
|
|
120163
|
+
"hex": "#22c55e"
|
|
120164
|
+
},
|
|
120165
|
+
{
|
|
120166
|
+
"role": "Primary 3",
|
|
120167
|
+
"name": "Electric Blue",
|
|
120168
|
+
"hex": "#3b82f6"
|
|
120169
|
+
},
|
|
120170
|
+
{
|
|
120171
|
+
"role": "Background",
|
|
120172
|
+
"name": "Light Blue",
|
|
120173
|
+
"hex": "#eff6ff"
|
|
120174
|
+
},
|
|
120175
|
+
{
|
|
120176
|
+
"role": "Background Alt",
|
|
120177
|
+
"name": "Soft Lavender",
|
|
120178
|
+
"hex": "#f5f3ff"
|
|
120179
|
+
},
|
|
120180
|
+
{
|
|
120181
|
+
"role": "Accent 1",
|
|
120182
|
+
"name": "Bright Orange",
|
|
120183
|
+
"hex": "#fb923c"
|
|
120184
|
+
},
|
|
120185
|
+
{
|
|
120186
|
+
"role": "Accent 2",
|
|
120187
|
+
"name": "Vivid Yellow",
|
|
120188
|
+
"hex": "#facc15"
|
|
120189
|
+
}
|
|
120190
|
+
],
|
|
120191
|
+
"decorativeHints": [
|
|
120192
|
+
"Dynamic diagonal lines and angles",
|
|
120193
|
+
"Bold geometric shapes and color blocks",
|
|
120194
|
+
"Dramatic lighting effects",
|
|
120195
|
+
"High-energy visual compositions"
|
|
120196
|
+
],
|
|
120197
|
+
"bestFor": ""
|
|
120198
|
+
}
|
|
120199
|
+
];
|
|
120200
|
+
var renderings = [
|
|
120201
|
+
{
|
|
120202
|
+
"id": "flat-vector",
|
|
120203
|
+
"tagline": "Clean, modern, geometric illustration",
|
|
120204
|
+
"lines": [
|
|
120205
|
+
"Clean outlines with uniform stroke weight",
|
|
120206
|
+
"Closed shapes (coloring-book style)",
|
|
120207
|
+
"Rounded line endings, avoid sharp corners",
|
|
120208
|
+
"Consistent stroke width throughout"
|
|
120209
|
+
],
|
|
120210
|
+
"texture": [
|
|
120211
|
+
"None: smooth, flat color fills only",
|
|
120212
|
+
"No gradients, shadows, or noise",
|
|
120213
|
+
"Solid color blocks"
|
|
120214
|
+
],
|
|
120215
|
+
"depth": [
|
|
120216
|
+
"Flat: no shadows, no perspective",
|
|
120217
|
+
"2D layering with overlap for depth illusion",
|
|
120218
|
+
"Optional 2.5D isometric layering (front/back occlusion, no atmospheric perspective)",
|
|
120219
|
+
"No 3D effects or bevels"
|
|
120220
|
+
],
|
|
120221
|
+
"elements": [
|
|
120222
|
+
"Geometric icons and simple shapes",
|
|
120223
|
+
"Bold outlined objects with clean fills",
|
|
120224
|
+
"Geometric simplification: complex objects → basic shapes (trees → lollipop/triangle, buildings → rectangles)",
|
|
120225
|
+
"\"Toy model\" aesthetic: cute, rounded proportions",
|
|
120226
|
+
"Decorative: dots, lines, sunbursts, pill-shaped clouds, small stars",
|
|
120227
|
+
"Isolated elements on clean backgrounds"
|
|
120228
|
+
]
|
|
120229
|
+
},
|
|
120230
|
+
{
|
|
120231
|
+
"id": "pixel",
|
|
120232
|
+
"tagline": "Retro 8-bit, nostalgic, chunky",
|
|
120233
|
+
"lines": [
|
|
120234
|
+
"Pixel grid alignment, no anti-aliasing",
|
|
120235
|
+
"Staircase edges on diagonals",
|
|
120236
|
+
"Single-pixel or double-pixel outlines",
|
|
120237
|
+
"Blocky, angular forms"
|
|
120238
|
+
],
|
|
120239
|
+
"texture": [
|
|
120240
|
+
"Dithering patterns for gradients",
|
|
120241
|
+
"No smooth transitions",
|
|
120242
|
+
"Cross-hatching with pixel precision",
|
|
120243
|
+
"Limited 16-32 color palette per scene"
|
|
120244
|
+
],
|
|
120245
|
+
"depth": [
|
|
120246
|
+
"None: flat pixel planes only",
|
|
120247
|
+
"Parallax layering (foreground/background)",
|
|
120248
|
+
"No perspective or 3D effects"
|
|
120249
|
+
],
|
|
120250
|
+
"elements": [
|
|
120251
|
+
"8-bit sprites and chunky shapes",
|
|
120252
|
+
"Simple iconography: stars, hearts, arrows",
|
|
120253
|
+
"Text bubbles with pixel borders",
|
|
120254
|
+
"Progress bars with chunky segments",
|
|
120255
|
+
"Retro gaming UI elements"
|
|
120256
|
+
]
|
|
120257
|
+
},
|
|
120258
|
+
{
|
|
120259
|
+
"id": "digital",
|
|
120260
|
+
"tagline": "Polished, precise, modern",
|
|
120261
|
+
"lines": [
|
|
120262
|
+
"Clean, precise, computer-perfect edges",
|
|
120263
|
+
"Consistent stroke weights",
|
|
120264
|
+
"Sharp corners where appropriate",
|
|
120265
|
+
"Anti-aliased smooth rendering"
|
|
120266
|
+
],
|
|
120267
|
+
"texture": [
|
|
120268
|
+
"Smooth surfaces with no visible texture",
|
|
120269
|
+
"Subtle gradients permitted (soft, controlled)",
|
|
120270
|
+
"Frosted glass and blur effects",
|
|
120271
|
+
"Clean shadows with consistent direction"
|
|
120272
|
+
],
|
|
120273
|
+
"depth": [
|
|
120274
|
+
"Subtle gradients and soft drop shadows",
|
|
120275
|
+
"Layered card-based layouts",
|
|
120276
|
+
"Light 3D effects (subtle, not realistic)",
|
|
120277
|
+
"Material Design-inspired elevation"
|
|
120278
|
+
],
|
|
120279
|
+
"elements": [
|
|
120280
|
+
"Polished icons and UI components",
|
|
120281
|
+
"Data visualizations: charts, graphs, metrics",
|
|
120282
|
+
"Card layouts and structured grids",
|
|
120283
|
+
"Tag chips, progress bars, status indicators",
|
|
120284
|
+
"Clean geometric shapes"
|
|
120285
|
+
]
|
|
120286
|
+
},
|
|
120287
|
+
{
|
|
120288
|
+
"id": "hand-drawn",
|
|
120289
|
+
"tagline": "Sketchy, organic, personal",
|
|
120290
|
+
"lines": [
|
|
120291
|
+
"Sketchy, organic, slightly imperfect strokes",
|
|
120292
|
+
"Variable line weight (thicker at pressure points)",
|
|
120293
|
+
"Wavy connectors and arrows",
|
|
120294
|
+
"Natural hand tremor visible"
|
|
120295
|
+
],
|
|
120296
|
+
"texture": [
|
|
120297
|
+
"Paper grain and subtle surface texture",
|
|
120298
|
+
"Pencil/pen/marker texture on strokes",
|
|
120299
|
+
"Casual fills with visible brush direction"
|
|
120300
|
+
],
|
|
120301
|
+
"depth": [
|
|
120302
|
+
"Minimal: light hand-drawn shadows or hatching",
|
|
120303
|
+
"No realistic depth or perspective",
|
|
120304
|
+
"Simple layering with overlap"
|
|
120305
|
+
],
|
|
120306
|
+
"elements": [
|
|
120307
|
+
"Doodles, organic shapes, hand-lettered labels",
|
|
120308
|
+
"Conceptual icons with sketchy quality",
|
|
120309
|
+
"Connection lines with hand-drawn wavy feel",
|
|
120310
|
+
"Stars, arrows, underlines, circles, checkmarks",
|
|
120311
|
+
"Stick figures and simple characters"
|
|
120312
|
+
]
|
|
120313
|
+
},
|
|
120314
|
+
{
|
|
120315
|
+
"id": "painterly",
|
|
120316
|
+
"tagline": "Soft, artistic, expressive",
|
|
120317
|
+
"lines": [
|
|
120318
|
+
"Soft brush strokes with variable opacity",
|
|
120319
|
+
"No hard outlines; edges defined by color transitions",
|
|
120320
|
+
"Organic flowing strokes with natural blending"
|
|
120321
|
+
],
|
|
120322
|
+
"texture": [
|
|
120323
|
+
"Visible paint or watercolor wash textures",
|
|
120324
|
+
"Color bleeds and wet-on-wet effects",
|
|
120325
|
+
"Paper texture showing through transparent areas",
|
|
120326
|
+
"Brush stroke patterns visible"
|
|
120327
|
+
],
|
|
120328
|
+
"depth": [
|
|
120329
|
+
"Soft edges with natural color blending",
|
|
120330
|
+
"Atmospheric depth through color fading",
|
|
120331
|
+
"Layered washes creating depth illusion"
|
|
120332
|
+
],
|
|
120333
|
+
"elements": [
|
|
120334
|
+
"Watercolor washes as backgrounds",
|
|
120335
|
+
"Natural elements: leaves, flowers, organic forms",
|
|
120336
|
+
"Soft gradients and color transitions",
|
|
120337
|
+
"Splatter and drip effects as accents",
|
|
120338
|
+
"Botanical and environmental motifs"
|
|
120339
|
+
]
|
|
120340
|
+
},
|
|
120341
|
+
{
|
|
120342
|
+
"id": "chalk",
|
|
120343
|
+
"tagline": "Educational, authentic, classroom",
|
|
120344
|
+
"lines": [
|
|
120345
|
+
"Imperfect chalk strokes with variable pressure",
|
|
120346
|
+
"Visible chalk texture and grain",
|
|
120347
|
+
"Slightly wobbly, hand-drawn quality",
|
|
120348
|
+
"Thick strokes for emphasis, thin for details"
|
|
120349
|
+
],
|
|
120350
|
+
"texture": [
|
|
120351
|
+
"Chalk dust effects around text and elements",
|
|
120352
|
+
"Board surface (dark, slightly worn)",
|
|
120353
|
+
"Eraser smudges and residue",
|
|
120354
|
+
"Grainy chalk quality on all elements"
|
|
120355
|
+
],
|
|
120356
|
+
"depth": [
|
|
120357
|
+
"None: flat chalk drawings on board surface",
|
|
120358
|
+
"Layering through erasure and redrawing",
|
|
120359
|
+
"No shadows or perspective"
|
|
120360
|
+
],
|
|
120361
|
+
"elements": [
|
|
120362
|
+
"Chalk doodles: stars, arrows, underlines",
|
|
120363
|
+
"Mathematical formulas and diagrams",
|
|
120364
|
+
"Stick figures and simple icons",
|
|
120365
|
+
"Connection lines with chalk feel",
|
|
120366
|
+
"Checkmarks, circles, boxes for lists",
|
|
120367
|
+
"Wooden frame border optional"
|
|
120368
|
+
]
|
|
120369
|
+
},
|
|
120370
|
+
{
|
|
120371
|
+
"id": "screen-print",
|
|
120372
|
+
"tagline": "Bold, limited-color poster art with print texture",
|
|
120373
|
+
"lines": [
|
|
120374
|
+
"Clean, sharp edges between color blocks",
|
|
120375
|
+
"No outlines — shapes defined by color boundaries",
|
|
120376
|
+
"Stencil-cut quality, bold silhouettes",
|
|
120377
|
+
"Geometric shapes with precise registration"
|
|
120378
|
+
],
|
|
120379
|
+
"texture": [
|
|
120380
|
+
"Halftone dot patterns within color fills",
|
|
120381
|
+
"Slight color layer misregistration (offset between print layers)",
|
|
120382
|
+
"Paper grain texture beneath colors",
|
|
120383
|
+
"Risograph / screen print imperfections (ink spread, dot gain)"
|
|
120384
|
+
],
|
|
120385
|
+
"depth": [
|
|
120386
|
+
"Flat color planes layered front to back",
|
|
120387
|
+
"Depth through silhouette overlap and color layering",
|
|
120388
|
+
"No gradients — tonal variation via halftone density",
|
|
120389
|
+
"Negative space as active compositional element"
|
|
120390
|
+
],
|
|
120391
|
+
"elements": [
|
|
120392
|
+
"Bold silhouettes and symbolic shapes",
|
|
120393
|
+
"Geometric framing (circles, arches, triangles)",
|
|
120394
|
+
"Figure-ground inversion (negative space forms secondary image)",
|
|
120395
|
+
"Limited icon vocabulary: key props, symbolic objects",
|
|
120396
|
+
"Typography integrated as design element, not overlay",
|
|
120397
|
+
"Vintage poster border treatments"
|
|
120398
|
+
]
|
|
120399
|
+
}
|
|
120400
|
+
];
|
|
120401
|
+
var textLevels = [
|
|
120402
|
+
{
|
|
120403
|
+
"id": "none",
|
|
120404
|
+
"area": "85% visual area"
|
|
120405
|
+
},
|
|
120406
|
+
{
|
|
120407
|
+
"id": "title-only",
|
|
120408
|
+
"area": "85% visual area"
|
|
120409
|
+
},
|
|
120410
|
+
{
|
|
120411
|
+
"id": "title-subtitle",
|
|
120412
|
+
"area": "75% visual area"
|
|
120413
|
+
},
|
|
120414
|
+
{
|
|
120415
|
+
"id": "text-rich",
|
|
120416
|
+
"area": "60% visual area"
|
|
120417
|
+
}
|
|
120418
|
+
];
|
|
120419
|
+
var moods = [
|
|
120420
|
+
{
|
|
120421
|
+
"id": "subtle",
|
|
120422
|
+
"application": "Use low contrast, muted colors, light visual weight, calm aesthetic"
|
|
120423
|
+
},
|
|
120424
|
+
{
|
|
120425
|
+
"id": "balanced",
|
|
120426
|
+
"application": "Use medium contrast, normal saturation, balanced visual weight"
|
|
120427
|
+
},
|
|
120428
|
+
{
|
|
120429
|
+
"id": "bold",
|
|
120430
|
+
"application": "Use high contrast, vivid saturated colors, heavy visual weight, dynamic energy"
|
|
120431
|
+
}
|
|
120432
|
+
];
|
|
120433
|
+
//#endregion
|
|
120434
|
+
//#region lib/types/baoyu-compose.js
|
|
120435
|
+
/**
|
|
120436
|
+
* Dimension-composition prompt assembly for the inspiration composer tab.
|
|
120437
|
+
* Data is generated by scripts/build-baoyu-compose.mjs from JimLiu/baoyu-skills
|
|
120438
|
+
* (baoyu-cover-image skill, MIT license).
|
|
120439
|
+
*/
|
|
120440
|
+
/** Pseudo inspiration source id that switches the view into composer mode. */
|
|
120441
|
+
const BAOYU_COMPOSER_SOURCE_ID = "baoyu-compose";
|
|
120442
|
+
const BAOYU_TYPES = types;
|
|
120443
|
+
const BAOYU_PALETTES = palettes;
|
|
120444
|
+
const BAOYU_RENDERINGS = renderings;
|
|
120445
|
+
const BAOYU_TEXT_LEVELS = textLevels;
|
|
120446
|
+
const BAOYU_MOODS = moods;
|
|
120447
|
+
/** Chinese labels for every dimension option id, shown when the UI language is zh. */
|
|
120448
|
+
const BAOYU_LABELS_ZH = {
|
|
120449
|
+
hero: "主视觉大图",
|
|
120450
|
+
conceptual: "概念抽象",
|
|
120451
|
+
typography: "文字主导",
|
|
120452
|
+
metaphor: "隐喻象征",
|
|
120453
|
+
scene: "氛围场景",
|
|
120454
|
+
minimal: "极简留白",
|
|
120455
|
+
warm: "暖色",
|
|
120456
|
+
cool: "冷色",
|
|
120457
|
+
dark: "暗色",
|
|
120458
|
+
earth: "大地色",
|
|
120459
|
+
elegant: "优雅",
|
|
120460
|
+
macaron: "马卡龙",
|
|
120461
|
+
mono: "单色",
|
|
120462
|
+
pastel: "粉彩",
|
|
120463
|
+
retro: "复古",
|
|
120464
|
+
duotone: "双色调",
|
|
120465
|
+
vivid: "高饱和",
|
|
120466
|
+
"flat-vector": "扁平矢量",
|
|
120467
|
+
pixel: "像素风",
|
|
120468
|
+
digital: "数字插画",
|
|
120469
|
+
"hand-drawn": "手绘",
|
|
120470
|
+
painterly: "绘画感",
|
|
120471
|
+
chalk: "粉笔",
|
|
120472
|
+
"screen-print": "丝网印刷",
|
|
120473
|
+
none: "无文字",
|
|
120474
|
+
"title-only": "仅标题",
|
|
120475
|
+
"title-subtitle": "标题+副标题",
|
|
120476
|
+
"text-rich": "丰富文字",
|
|
120477
|
+
subtle: "含蓄",
|
|
120478
|
+
balanced: "均衡",
|
|
120479
|
+
bold: "强烈"
|
|
120480
|
+
};
|
|
120481
|
+
const BAOYU_DEFAULT_SELECTION = {
|
|
120482
|
+
type: "metaphor",
|
|
120483
|
+
palette: "warm",
|
|
120484
|
+
rendering: "flat-vector",
|
|
120485
|
+
text: "title-only",
|
|
120486
|
+
mood: "balanced",
|
|
120487
|
+
title: ""
|
|
120488
|
+
};
|
|
120489
|
+
function palette(id) {
|
|
120490
|
+
return BAOYU_PALETTES.find((item) => item.id === id);
|
|
120491
|
+
}
|
|
120492
|
+
function rendering(id) {
|
|
120493
|
+
return BAOYU_RENDERINGS.find((item) => item.id === id);
|
|
120494
|
+
}
|
|
120495
|
+
function typeOf(id) {
|
|
120496
|
+
return BAOYU_TYPES.find((item) => item.id === id);
|
|
120497
|
+
}
|
|
120498
|
+
function moodOf(id) {
|
|
120499
|
+
return BAOYU_MOODS.find((item) => item.id === id);
|
|
120500
|
+
}
|
|
120501
|
+
function textLevel(id) {
|
|
120502
|
+
return BAOYU_TEXT_LEVELS.find((item) => item.id === id);
|
|
120503
|
+
}
|
|
120504
|
+
/** Assemble the five-dimension selection into one generate_image-ready prompt. */
|
|
120505
|
+
function composeBaoyuPrompt(selection) {
|
|
120506
|
+
const chosenType = typeOf(selection.type);
|
|
120507
|
+
const chosenPalette = palette(selection.palette);
|
|
120508
|
+
const chosenRendering = rendering(selection.rendering);
|
|
120509
|
+
const chosenText = textLevel(selection.text);
|
|
120510
|
+
const chosenMood = moodOf(selection.mood);
|
|
120511
|
+
if (chosenType === void 0 || chosenPalette === void 0 || chosenRendering === void 0 || chosenText === void 0 || chosenMood === void 0) throw new Error("invalid-baoyu-selection");
|
|
120512
|
+
const title = selection.title.trim();
|
|
120513
|
+
if (selection.text !== "none" && title === "") throw new Error("baoyu-title-required");
|
|
120514
|
+
const primary = chosenPalette.colors.filter((color) => color.role.startsWith("Primary"));
|
|
120515
|
+
const background = chosenPalette.colors.filter((color) => color.role.startsWith("Background"));
|
|
120516
|
+
const accent = chosenPalette.colors.filter((color) => color.role.startsWith("Accent"));
|
|
120517
|
+
const swatch = (colors) => colors.map((color) => `${color.name} ${color.hex}`).join(", ");
|
|
120518
|
+
const textElements = selection.text === "none" ? "No text elements; the full area stays visual." : [
|
|
120519
|
+
`Title: "${title}"`,
|
|
120520
|
+
...selection.text === "title-subtitle" || selection.text === "text-rich" ? ["Subtitle: derive one short supporting line from the title"] : [],
|
|
120521
|
+
...selection.text === "text-rich" ? ["Tags: derive 2-3 keyword badges from the title"] : []
|
|
120522
|
+
].join("\n");
|
|
120523
|
+
const pairNote = chosenPalette.pairs === void 0 ? "" : `\n- Duotone pair: pick ONE dominant two-color pair from ${chosenPalette.pairs.map((pair) => `${pair.name} (${pair.a} + ${pair.b})`).join("; ")}`;
|
|
120524
|
+
return [
|
|
120525
|
+
"Cover image.",
|
|
120526
|
+
"",
|
|
120527
|
+
"# Visual Design",
|
|
120528
|
+
`- Type: ${chosenType.id} — ${chosenType.composition}`,
|
|
120529
|
+
`- Palette: ${chosenPalette.id} (${chosenPalette.tagline})`,
|
|
120530
|
+
`- Rendering: ${chosenRendering.id} — ${chosenRendering.tagline}`,
|
|
120531
|
+
`- Text level: ${chosenText.id} (${chosenText.area})`,
|
|
120532
|
+
`- Mood: ${chosenMood.id} — ${chosenMood.application}`,
|
|
120533
|
+
"",
|
|
120534
|
+
"# Text Elements",
|
|
120535
|
+
textElements,
|
|
120536
|
+
"",
|
|
120537
|
+
"# Composition",
|
|
120538
|
+
`- Type composition: ${chosenType.composition}`,
|
|
120539
|
+
"- Layout: generous whitespace (40-60% breathing room); one dominant focal point with 1-2 supporting elements plus decorative accents; main visual centered or slightly left, reserving the right side for the title when included.",
|
|
120540
|
+
`- Decorative: ${chosenPalette.decorativeHints.join("; ")}`,
|
|
120541
|
+
"",
|
|
120542
|
+
"# Color Scheme",
|
|
120543
|
+
`- Primary: ${swatch(primary)}`,
|
|
120544
|
+
`- Background: ${swatch(background)}`,
|
|
120545
|
+
`- Accent: ${swatch(accent)}${pairNote}`,
|
|
120546
|
+
`- Mood adjustment: ${chosenMood.application}`,
|
|
120547
|
+
"- Color constraint: Color values (#hex) and color names are rendering guidance only — do NOT display color names, hex codes, or palette labels as visible text in the image.",
|
|
120548
|
+
"",
|
|
120549
|
+
`# Rendering Notes (${chosenRendering.id})`,
|
|
120550
|
+
`- Lines: ${chosenRendering.lines.join("; ")}`,
|
|
120551
|
+
`- Texture: ${chosenRendering.texture.join("; ")}`,
|
|
120552
|
+
`- Depth: ${chosenRendering.depth.join("; ")}`,
|
|
120553
|
+
`- Elements: ${chosenRendering.elements.join("; ")}`,
|
|
120554
|
+
"",
|
|
120555
|
+
"# Core Principles",
|
|
120556
|
+
"- Ample whitespace, highlight the core message, avoid cluttered layouts.",
|
|
120557
|
+
"- Simplified silhouettes for any characters — no realistic human faces or bodies.",
|
|
120558
|
+
"- Icon-based vocabulary: represent concepts with simple, recognizable icons."
|
|
120559
|
+
].join("\n");
|
|
120560
|
+
}
|
|
120561
|
+
/** Randomize every visual dimension, keeping the current title text. */
|
|
120562
|
+
function randomBaoyuSelection(current) {
|
|
120563
|
+
const pick = (items) => items[Math.floor(Math.random() * items.length)];
|
|
120564
|
+
return {
|
|
120565
|
+
type: pick(BAOYU_TYPES).id,
|
|
120566
|
+
palette: pick(BAOYU_PALETTES).id,
|
|
120567
|
+
rendering: pick(BAOYU_RENDERINGS).id,
|
|
120568
|
+
text: pick(BAOYU_TEXT_LEVELS).id,
|
|
120569
|
+
mood: pick(BAOYU_MOODS).id,
|
|
120570
|
+
title: current.title
|
|
120571
|
+
};
|
|
120572
|
+
}
|
|
120573
|
+
//#endregion
|
|
118868
120574
|
//#region lib/types/client/inspiration-view.js
|
|
118869
120575
|
const FAVORITES_STORAGE_KEY = "dsh-ig-inspiration-favorites";
|
|
118870
120576
|
function loadInspirationFavorites() {
|
|
@@ -118956,6 +120662,7 @@ img.ProseMirror-separator {
|
|
|
118956
120662
|
allCategories: "全部分类",
|
|
118957
120663
|
allStyles: "全部风格",
|
|
118958
120664
|
allScenes: "全部场景",
|
|
120665
|
+
categoryNav: "分类导航",
|
|
118959
120666
|
search: "搜索案例、Prompt、风格…",
|
|
118960
120667
|
results: "找到 {count} 个案例",
|
|
118961
120668
|
noResults: "没有匹配的素材,换个关键词或筛选条件试试。",
|
|
@@ -118965,6 +120672,9 @@ img.ProseMirror-separator {
|
|
|
118965
120672
|
copied: "已复制",
|
|
118966
120673
|
use: "使用这个 Prompt",
|
|
118967
120674
|
source: "查看原来源",
|
|
120675
|
+
useReference: "提示词 + 参考图",
|
|
120676
|
+
referenceLoading: "获取参考图中…",
|
|
120677
|
+
referenceFailed: "参考图获取失败,请重试",
|
|
118968
120678
|
loading: "正在读取素材库…",
|
|
118969
120679
|
loadFailed: "素材库读取失败,请稍后重试。",
|
|
118970
120680
|
copyFailed: "复制失败",
|
|
@@ -118979,7 +120689,21 @@ img.ProseMirror-separator {
|
|
|
118979
120689
|
favorite: "收藏",
|
|
118980
120690
|
favorited: "已收藏",
|
|
118981
120691
|
zoomHint: "点击放大查看",
|
|
118982
|
-
close: "关闭"
|
|
120692
|
+
close: "关闭",
|
|
120693
|
+
composeTab: "宝玉维度组合",
|
|
120694
|
+
composeHint: "五个维度自由拼接封面 Prompt,数据源自宝玉封图 skill(JimLiu/baoyu-skills,MIT)。",
|
|
120695
|
+
composeType: "类型",
|
|
120696
|
+
composePalette: "色板",
|
|
120697
|
+
composeRendering: "渲染",
|
|
120698
|
+
composeText: "文字",
|
|
120699
|
+
composeMood: "情绪",
|
|
120700
|
+
composeTitleLabel: "标题文字",
|
|
120701
|
+
composeTitlePlaceholder: "输入封面标题(文字层级含标题时必填)",
|
|
120702
|
+
composeTitleRequired: "该文字层级需要先填写标题。",
|
|
120703
|
+
composeRandomize: "随机组合",
|
|
120704
|
+
composeUse: "用此 Prompt 去生成",
|
|
120705
|
+
composeCombos: "共 {count} 种组合",
|
|
120706
|
+
composePreview: "拼接结果预览"
|
|
118983
120707
|
},
|
|
118984
120708
|
en: {
|
|
118985
120709
|
kicker: "Prompt inspiration",
|
|
@@ -118999,6 +120723,7 @@ img.ProseMirror-separator {
|
|
|
118999
120723
|
allCategories: "All categories",
|
|
119000
120724
|
allStyles: "All styles",
|
|
119001
120725
|
allScenes: "All scenes",
|
|
120726
|
+
categoryNav: "Categories",
|
|
119002
120727
|
search: "Search examples, prompts, styles…",
|
|
119003
120728
|
results: "{count} examples",
|
|
119004
120729
|
noResults: "No matching examples. Try another keyword or filter.",
|
|
@@ -119008,6 +120733,9 @@ img.ProseMirror-separator {
|
|
|
119008
120733
|
copied: "Copied",
|
|
119009
120734
|
use: "Use this prompt",
|
|
119010
120735
|
source: "View source",
|
|
120736
|
+
useReference: "Prompt + reference",
|
|
120737
|
+
referenceLoading: "Fetching image…",
|
|
120738
|
+
referenceFailed: "Failed to load the reference image",
|
|
119011
120739
|
loading: "Loading inspiration…",
|
|
119012
120740
|
loadFailed: "Could not load the inspiration library.",
|
|
119013
120741
|
copyFailed: "Failed to copy",
|
|
@@ -119022,12 +120750,28 @@ img.ProseMirror-separator {
|
|
|
119022
120750
|
favorite: "Favorite",
|
|
119023
120751
|
favorited: "Favorited",
|
|
119024
120752
|
zoomHint: "Click to zoom in",
|
|
119025
|
-
close: "Close"
|
|
119026
|
-
|
|
119027
|
-
|
|
119028
|
-
|
|
120753
|
+
close: "Close",
|
|
120754
|
+
composeTab: "Baoyu Composer",
|
|
120755
|
+
composeHint: "Stitch a cover prompt from five dimensions, based on the baoyu cover-image skill (JimLiu/baoyu-skills, MIT).",
|
|
120756
|
+
composeType: "Type",
|
|
120757
|
+
composePalette: "Palette",
|
|
120758
|
+
composeRendering: "Rendering",
|
|
120759
|
+
composeText: "Text",
|
|
120760
|
+
composeMood: "Mood",
|
|
120761
|
+
composeTitleLabel: "Title text",
|
|
120762
|
+
composeTitlePlaceholder: "Cover title (required when the text level includes a title)",
|
|
120763
|
+
composeTitleRequired: "This text level needs a title first.",
|
|
120764
|
+
composeRandomize: "Randomize",
|
|
120765
|
+
composeUse: "Generate with this prompt",
|
|
120766
|
+
composeCombos: "{count} combinations",
|
|
120767
|
+
composePreview: "Composed prompt preview"
|
|
120768
|
+
}
|
|
120769
|
+
};
|
|
120770
|
+
const InspirationView = ({ locale, onUsePrompt, onUseReference }) => {
|
|
119029
120771
|
const [language, setLanguage] = (0, react.useState)(() => locale?.getSnapshot?.().active?.startsWith("en") ? "en" : "zh");
|
|
119030
120772
|
const [catalog, setCatalog] = (0, react.useState)(null);
|
|
120773
|
+
const [activeSourceId, setActiveSourceId] = (0, react.useState)("");
|
|
120774
|
+
const [baoyuSelection, setBaoyuSelection] = (0, react.useState)(BAOYU_DEFAULT_SELECTION);
|
|
119031
120775
|
const [catalogError, setCatalogError] = (0, react.useState)(false);
|
|
119032
120776
|
const [search, setSearch] = (0, react.useState)("");
|
|
119033
120777
|
const [category, setCategory] = (0, react.useState)("");
|
|
@@ -119043,8 +120787,12 @@ img.ProseMirror-separator {
|
|
|
119043
120787
|
const [onlyFavorites, setOnlyFavorites] = (0, react.useState)(false);
|
|
119044
120788
|
const [lightboxCase, setLightboxCase] = (0, react.useState)(null);
|
|
119045
120789
|
const [toast, setToast] = (0, react.useState)(null);
|
|
120790
|
+
const [referenceBusy, setReferenceBusy] = (0, react.useState)(false);
|
|
120791
|
+
const [pendingJump, setPendingJump] = (0, react.useState)("");
|
|
120792
|
+
const [activeCategory, setActiveCategory] = (0, react.useState)("");
|
|
119046
120793
|
const toastTimerRef = (0, react.useRef)(null);
|
|
119047
120794
|
const sentinelRef = (0, react.useRef)(null);
|
|
120795
|
+
const listRef = (0, react.useRef)(null);
|
|
119048
120796
|
(0, react.useEffect)(() => {
|
|
119049
120797
|
if (!locale?.subscribe) return;
|
|
119050
120798
|
return locale.subscribe(() => setLanguage(locale.getSnapshot?.().active?.startsWith("en") ? "en" : "zh"));
|
|
@@ -119114,7 +120862,33 @@ img.ProseMirror-separator {
|
|
|
119114
120862
|
mounted = false;
|
|
119115
120863
|
};
|
|
119116
120864
|
}, []);
|
|
119117
|
-
const source = catalog?.sources[0] ?? null;
|
|
120865
|
+
const source = catalog?.sources.find((candidate) => candidate.id === activeSourceId) ?? catalog?.sources[0] ?? null;
|
|
120866
|
+
const composerActive = activeSourceId === BAOYU_COMPOSER_SOURCE_ID;
|
|
120867
|
+
/** Switch the active library; each source owns its own category/style/scene vocabularies. */
|
|
120868
|
+
const switchSource = (id) => {
|
|
120869
|
+
if (id === activeSourceId) return;
|
|
120870
|
+
setActiveSourceId(id);
|
|
120871
|
+
setCategory("");
|
|
120872
|
+
setStyle("");
|
|
120873
|
+
setScene("");
|
|
120874
|
+
setOnlyFavorites(false);
|
|
120875
|
+
setSelected(null);
|
|
120876
|
+
setPendingJump("");
|
|
120877
|
+
setActiveCategory("");
|
|
120878
|
+
};
|
|
120879
|
+
const useSelectedReference = async () => {
|
|
120880
|
+
if (selected === null || source === null || onUseReference === void 0) return;
|
|
120881
|
+
setReferenceBusy(true);
|
|
120882
|
+
try {
|
|
120883
|
+
const blob = await fetchInspirationImage(source.id, selected.id, source.imageRevision ?? source.version);
|
|
120884
|
+
const ext = blob.type === "image/jpeg" ? "jpg" : blob.type.split("/")[1]?.replace(/[^a-z0-9]/gi, "") || "png";
|
|
120885
|
+
onUseReference(new File([blob], `inspiration-${selected.id}.${ext}`, { type: blob.type.startsWith("image/") ? blob.type : "image/webp" }), selected.prompt);
|
|
120886
|
+
} catch {
|
|
120887
|
+
showToast(t("referenceFailed"), true);
|
|
120888
|
+
} finally {
|
|
120889
|
+
setReferenceBusy(false);
|
|
120890
|
+
}
|
|
120891
|
+
};
|
|
119118
120892
|
const matchingCases = (0, react.useMemo)(() => {
|
|
119119
120893
|
if (source === null) return [];
|
|
119120
120894
|
const query = search.trim().toLowerCase();
|
|
@@ -119156,6 +120930,67 @@ img.ProseMirror-separator {
|
|
|
119156
120930
|
onlyFavorites
|
|
119157
120931
|
]);
|
|
119158
120932
|
const visibleCases = matchingCases.slice(0, visibleLimit);
|
|
120933
|
+
const categoryCounts = (0, react.useMemo)(() => {
|
|
120934
|
+
const counts = /* @__PURE__ */ new Map();
|
|
120935
|
+
for (const item of matchingCases) counts.set(item.category, (counts.get(item.category) ?? 0) + 1);
|
|
120936
|
+
return counts;
|
|
120937
|
+
}, [matchingCases]);
|
|
120938
|
+
const visibleGroups = (0, react.useMemo)(() => {
|
|
120939
|
+
if (source === null) return [];
|
|
120940
|
+
const byCategory = /* @__PURE__ */ new Map();
|
|
120941
|
+
for (const item of visibleCases) {
|
|
120942
|
+
const bucket = byCategory.get(item.category);
|
|
120943
|
+
if (bucket !== void 0) bucket.push(item);
|
|
120944
|
+
else byCategory.set(item.category, [item]);
|
|
120945
|
+
}
|
|
120946
|
+
return source.categories.flatMap((name) => {
|
|
120947
|
+
const items = byCategory.get(name);
|
|
120948
|
+
return items !== void 0 ? [{
|
|
120949
|
+
name,
|
|
120950
|
+
items
|
|
120951
|
+
}] : [];
|
|
120952
|
+
});
|
|
120953
|
+
}, [source, visibleCases]);
|
|
120954
|
+
const visibleGroupSignature = visibleGroups.map((group) => group.name).join("\0");
|
|
120955
|
+
const jumpToCategory = (name) => {
|
|
120956
|
+
if (category !== "") setCategory("");
|
|
120957
|
+
setPendingJump(name);
|
|
120958
|
+
};
|
|
120959
|
+
(0, react.useEffect)(() => {
|
|
120960
|
+
if (pendingJump === "") return;
|
|
120961
|
+
const index = matchingCases.findIndex((item) => item.category === pendingJump);
|
|
120962
|
+
if (index < 0) return;
|
|
120963
|
+
if (index >= visibleLimit) {
|
|
120964
|
+
setVisibleLimit(index + 60);
|
|
120965
|
+
return;
|
|
120966
|
+
}
|
|
120967
|
+
const raf = requestAnimationFrame(() => {
|
|
120968
|
+
document.getElementById(`dsh-ig-cat-${encodeURIComponent(pendingJump)}`)?.scrollIntoView({
|
|
120969
|
+
behavior: "smooth",
|
|
120970
|
+
block: "start"
|
|
120971
|
+
});
|
|
120972
|
+
setPendingJump("");
|
|
120973
|
+
});
|
|
120974
|
+
return () => cancelAnimationFrame(raf);
|
|
120975
|
+
}, [
|
|
120976
|
+
pendingJump,
|
|
120977
|
+
matchingCases,
|
|
120978
|
+
visibleLimit
|
|
120979
|
+
]);
|
|
120980
|
+
(0, react.useEffect)(() => {
|
|
120981
|
+
const root = listRef.current;
|
|
120982
|
+
if (root === null) return;
|
|
120983
|
+
const headers = Array.from(root.querySelectorAll(".dsh-ig-inspiration-group-head"));
|
|
120984
|
+
if (headers.length === 0) return;
|
|
120985
|
+
const categoryByTarget = /* @__PURE__ */ new Map();
|
|
120986
|
+
for (const header of headers) categoryByTarget.set(header, header.dataset.category ?? "");
|
|
120987
|
+
const observer = new IntersectionObserver((entries) => {
|
|
120988
|
+
const visible = entries.find((entry) => entry.isIntersecting);
|
|
120989
|
+
if (visible !== void 0) setActiveCategory(categoryByTarget.get(visible.target) ?? "");
|
|
120990
|
+
}, { rootMargin: "0px 0px -75% 0px" });
|
|
120991
|
+
for (const header of headers) observer.observe(header);
|
|
120992
|
+
return () => observer.disconnect();
|
|
120993
|
+
}, [visibleGroupSignature]);
|
|
119159
120994
|
(0, react.useEffect)(() => {
|
|
119160
120995
|
const el = sentinelRef.current;
|
|
119161
120996
|
if (!el) return;
|
|
@@ -119280,179 +121115,256 @@ img.ProseMirror-separator {
|
|
|
119280
121115
|
className: "dsh-ig-spin",
|
|
119281
121116
|
size: 23
|
|
119282
121117
|
}), (0, react_jsx_runtime.jsx)("span", { children: t("loading") })]
|
|
119283
|
-
}) : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
119284
|
-
className: "dsh-ig-inspiration-
|
|
119285
|
-
|
|
119286
|
-
|
|
119287
|
-
|
|
119288
|
-
|
|
119289
|
-
|
|
119290
|
-
|
|
119291
|
-
|
|
119292
|
-
|
|
119293
|
-
|
|
119294
|
-
|
|
121118
|
+
}) : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [catalog !== null ? (0, react_jsx_runtime.jsxs)("div", {
|
|
121119
|
+
className: "dsh-ig-inspiration-sources",
|
|
121120
|
+
role: "tablist",
|
|
121121
|
+
children: [catalog.sources.map((item) => (0, react_jsx_runtime.jsx)("button", {
|
|
121122
|
+
type: "button",
|
|
121123
|
+
role: "tab",
|
|
121124
|
+
"aria-selected": !composerActive && item.id === source?.id,
|
|
121125
|
+
className: `dsh-ig-inspiration-source-chip ${!composerActive && item.id === source?.id ? "is-active" : ""}`,
|
|
121126
|
+
onClick: () => switchSource(item.id),
|
|
121127
|
+
children: item.label
|
|
121128
|
+
}, item.id)), (0, react_jsx_runtime.jsxs)("button", {
|
|
121129
|
+
type: "button",
|
|
121130
|
+
role: "tab",
|
|
121131
|
+
"aria-selected": composerActive,
|
|
121132
|
+
className: `dsh-ig-inspiration-source-chip ${composerActive ? "is-active" : ""}`,
|
|
121133
|
+
onClick: () => switchSource(BAOYU_COMPOSER_SOURCE_ID),
|
|
121134
|
+
children: [(0, react_jsx_runtime.jsx)(Sparkles, { size: 11 }), t("composeTab")]
|
|
121135
|
+
})]
|
|
121136
|
+
}) : null, composerActive ? (0, react_jsx_runtime.jsx)(BaoyuComposerPanel, {
|
|
121137
|
+
language,
|
|
121138
|
+
selection: baoyuSelection,
|
|
121139
|
+
onChange: setBaoyuSelection,
|
|
121140
|
+
onUsePrompt
|
|
121141
|
+
}) : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
121142
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
121143
|
+
className: "dsh-ig-inspiration-toolbar",
|
|
121144
|
+
children: [
|
|
121145
|
+
(0, react_jsx_runtime.jsxs)("label", {
|
|
121146
|
+
className: "dsh-ig-inspiration-search",
|
|
121147
|
+
children: [(0, react_jsx_runtime.jsx)(Search, { size: 15 }), (0, react_jsx_runtime.jsx)("input", {
|
|
121148
|
+
value: search,
|
|
121149
|
+
onChange: (event) => setSearch(event.target.value),
|
|
121150
|
+
placeholder: t("search")
|
|
121151
|
+
})]
|
|
121152
|
+
}),
|
|
121153
|
+
(0, react_jsx_runtime.jsxs)("button", {
|
|
121154
|
+
type: "button",
|
|
121155
|
+
className: `dsh-ig-inspiration-fav-filter ${onlyFavorites ? "is-active" : ""}`,
|
|
121156
|
+
onClick: () => setOnlyFavorites((prev) => !prev),
|
|
121157
|
+
title: t("onlyFavorites"),
|
|
121158
|
+
children: [(0, react_jsx_runtime.jsx)(Star, {
|
|
121159
|
+
size: 14,
|
|
121160
|
+
className: onlyFavorites ? "fill-star" : ""
|
|
121161
|
+
}), (0, react_jsx_runtime.jsxs)("span", { children: [t("onlyFavorites"), favorites.size > 0 ? ` (${favorites.size})` : ""] })]
|
|
121162
|
+
}),
|
|
121163
|
+
(0, react_jsx_runtime.jsxs)("select", {
|
|
121164
|
+
value: category,
|
|
121165
|
+
onChange: (event) => setCategory(event.target.value),
|
|
121166
|
+
"aria-label": t("allCategories"),
|
|
121167
|
+
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
121168
|
+
value: "",
|
|
121169
|
+
children: t("allCategories")
|
|
121170
|
+
}), source.categories.map((item) => (0, react_jsx_runtime.jsx)("option", {
|
|
121171
|
+
value: item,
|
|
121172
|
+
children: translateTag(item, language)
|
|
121173
|
+
}, item))]
|
|
121174
|
+
}),
|
|
121175
|
+
(0, react_jsx_runtime.jsxs)("select", {
|
|
121176
|
+
value: style,
|
|
121177
|
+
onChange: (event) => setStyle(event.target.value),
|
|
121178
|
+
"aria-label": t("allStyles"),
|
|
121179
|
+
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
121180
|
+
value: "",
|
|
121181
|
+
children: t("allStyles")
|
|
121182
|
+
}), source.styles.map((item) => (0, react_jsx_runtime.jsx)("option", {
|
|
121183
|
+
value: item,
|
|
121184
|
+
children: translateTag(item, language)
|
|
121185
|
+
}, item))]
|
|
121186
|
+
}),
|
|
121187
|
+
(0, react_jsx_runtime.jsxs)("select", {
|
|
121188
|
+
value: scene,
|
|
121189
|
+
onChange: (event) => setScene(event.target.value),
|
|
121190
|
+
"aria-label": t("allScenes"),
|
|
121191
|
+
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
121192
|
+
value: "",
|
|
121193
|
+
children: t("allScenes")
|
|
121194
|
+
}), source.scenes.map((item) => (0, react_jsx_runtime.jsx)("option", {
|
|
121195
|
+
value: item,
|
|
121196
|
+
children: translateTag(item, language)
|
|
121197
|
+
}, item))]
|
|
121198
|
+
})
|
|
121199
|
+
]
|
|
121200
|
+
}),
|
|
121201
|
+
(0, react_jsx_runtime.jsxs)("nav", {
|
|
121202
|
+
className: "dsh-ig-inspiration-catnav",
|
|
121203
|
+
"aria-label": t("categoryNav"),
|
|
121204
|
+
children: [(0, react_jsx_runtime.jsxs)("button", {
|
|
119295
121205
|
type: "button",
|
|
119296
|
-
className: `dsh-ig-inspiration-
|
|
119297
|
-
onClick: () =>
|
|
119298
|
-
|
|
119299
|
-
|
|
119300
|
-
|
|
119301
|
-
|
|
119302
|
-
|
|
119303
|
-
}),
|
|
119304
|
-
(0, react_jsx_runtime.jsxs)("select", {
|
|
119305
|
-
value: category,
|
|
119306
|
-
onChange: (event) => setCategory(event.target.value),
|
|
119307
|
-
"aria-label": t("allCategories"),
|
|
119308
|
-
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
119309
|
-
value: "",
|
|
119310
|
-
children: t("allCategories")
|
|
119311
|
-
}), source.categories.map((item) => (0, react_jsx_runtime.jsx)("option", {
|
|
119312
|
-
value: item,
|
|
119313
|
-
children: translateTag(item, language)
|
|
119314
|
-
}, item))]
|
|
119315
|
-
}),
|
|
119316
|
-
(0, react_jsx_runtime.jsxs)("select", {
|
|
119317
|
-
value: style,
|
|
119318
|
-
onChange: (event) => setStyle(event.target.value),
|
|
119319
|
-
"aria-label": t("allStyles"),
|
|
119320
|
-
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
119321
|
-
value: "",
|
|
119322
|
-
children: t("allStyles")
|
|
119323
|
-
}), source.styles.map((item) => (0, react_jsx_runtime.jsx)("option", {
|
|
119324
|
-
value: item,
|
|
119325
|
-
children: translateTag(item, language)
|
|
119326
|
-
}, item))]
|
|
119327
|
-
}),
|
|
119328
|
-
(0, react_jsx_runtime.jsxs)("select", {
|
|
119329
|
-
value: scene,
|
|
119330
|
-
onChange: (event) => setScene(event.target.value),
|
|
119331
|
-
"aria-label": t("allScenes"),
|
|
119332
|
-
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
119333
|
-
value: "",
|
|
119334
|
-
children: t("allScenes")
|
|
119335
|
-
}), source.scenes.map((item) => (0, react_jsx_runtime.jsx)("option", {
|
|
119336
|
-
value: item,
|
|
119337
|
-
children: translateTag(item, language)
|
|
119338
|
-
}, item))]
|
|
119339
|
-
})
|
|
119340
|
-
]
|
|
119341
|
-
}), (0, react_jsx_runtime.jsxs)("div", {
|
|
119342
|
-
className: "dsh-ig-inspiration-layout",
|
|
119343
|
-
children: [(0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
119344
|
-
className: "dsh-ig-inspiration-summary",
|
|
119345
|
-
children: [(0, react_jsx_runtime.jsx)("strong", { children: t("results", { count: String(matchingCases.length) }) }), (0, react_jsx_runtime.jsx)("span", { children: source.version.slice(0, 8) })]
|
|
119346
|
-
}), matchingCases.length === 0 ? (0, react_jsx_runtime.jsx)("div", {
|
|
119347
|
-
className: "dsh-ig-inspiration-empty",
|
|
119348
|
-
children: onlyFavorites ? t("noFavorites") : t("noResults")
|
|
119349
|
-
}) : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)("div", {
|
|
119350
|
-
className: "dsh-ig-inspiration-grid",
|
|
119351
|
-
children: visibleCases.map((item) => (0, react_jsx_runtime.jsx)(InspirationCard, {
|
|
119352
|
-
item,
|
|
119353
|
-
sourceId: source.id,
|
|
119354
|
-
selected: selected?.id === item.id,
|
|
119355
|
-
isFavorited: favorites.has(item.id),
|
|
119356
|
-
language,
|
|
119357
|
-
featuredLabel: t("featured"),
|
|
119358
|
-
retryLabel: t("retry"),
|
|
119359
|
-
onSelect: () => {
|
|
119360
|
-
setSelected(item);
|
|
119361
|
-
setCopied(false);
|
|
121206
|
+
className: `dsh-ig-inspiration-catnav-chip ${category === "" && activeCategory === "" ? "is-active" : ""}`,
|
|
121207
|
+
onClick: () => {
|
|
121208
|
+
if (category !== "") setCategory("");
|
|
121209
|
+
listRef.current?.scrollIntoView({
|
|
121210
|
+
behavior: "smooth",
|
|
121211
|
+
block: "start"
|
|
121212
|
+
});
|
|
119362
121213
|
},
|
|
119363
|
-
|
|
119364
|
-
},
|
|
119365
|
-
|
|
119366
|
-
|
|
119367
|
-
|
|
119368
|
-
|
|
119369
|
-
|
|
119370
|
-
|
|
119371
|
-
|
|
119372
|
-
|
|
119373
|
-
|
|
119374
|
-
|
|
119375
|
-
|
|
119376
|
-
|
|
119377
|
-
|
|
119378
|
-
|
|
119379
|
-
|
|
119380
|
-
className: "dsh-ig-inspiration-
|
|
119381
|
-
|
|
119382
|
-
|
|
119383
|
-
|
|
119384
|
-
|
|
119385
|
-
|
|
119386
|
-
|
|
119387
|
-
|
|
119388
|
-
children:
|
|
119389
|
-
|
|
119390
|
-
|
|
119391
|
-
|
|
119392
|
-
|
|
119393
|
-
|
|
119394
|
-
|
|
119395
|
-
|
|
119396
|
-
|
|
119397
|
-
|
|
119398
|
-
|
|
119399
|
-
|
|
119400
|
-
|
|
119401
|
-
|
|
119402
|
-
|
|
119403
|
-
|
|
119404
|
-
|
|
119405
|
-
|
|
119406
|
-
|
|
119407
|
-
|
|
119408
|
-
|
|
119409
|
-
|
|
119410
|
-
|
|
119411
|
-
})
|
|
119412
|
-
})
|
|
119413
|
-
|
|
119414
|
-
|
|
119415
|
-
|
|
119416
|
-
|
|
119417
|
-
|
|
119418
|
-
|
|
119419
|
-
|
|
119420
|
-
|
|
119421
|
-
|
|
119422
|
-
|
|
119423
|
-
|
|
119424
|
-
|
|
119425
|
-
|
|
119426
|
-
|
|
119427
|
-
|
|
121214
|
+
children: [(0, react_jsx_runtime.jsx)("span", { children: t("allCategories") }), (0, react_jsx_runtime.jsx)("em", { children: matchingCases.length })]
|
|
121215
|
+
}), source.categories.map((name) => {
|
|
121216
|
+
const count = categoryCounts.get(name) ?? 0;
|
|
121217
|
+
const isActive = category === name || category === "" && activeCategory === name;
|
|
121218
|
+
return (0, react_jsx_runtime.jsxs)("button", {
|
|
121219
|
+
type: "button",
|
|
121220
|
+
disabled: count === 0,
|
|
121221
|
+
"aria-current": isActive || void 0,
|
|
121222
|
+
className: `dsh-ig-inspiration-catnav-chip ${isActive ? "is-active" : ""}`,
|
|
121223
|
+
onClick: () => jumpToCategory(name),
|
|
121224
|
+
children: [(0, react_jsx_runtime.jsx)("span", { children: translateTag(name, language) }), (0, react_jsx_runtime.jsx)("em", { children: count })]
|
|
121225
|
+
}, name);
|
|
121226
|
+
})]
|
|
121227
|
+
}),
|
|
121228
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
121229
|
+
className: "dsh-ig-inspiration-layout",
|
|
121230
|
+
children: [(0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
121231
|
+
className: "dsh-ig-inspiration-summary",
|
|
121232
|
+
children: [(0, react_jsx_runtime.jsx)("strong", { children: t("results", { count: String(matchingCases.length) }) }), (0, react_jsx_runtime.jsx)("span", { children: source.version.slice(0, 8) })]
|
|
121233
|
+
}), matchingCases.length === 0 ? (0, react_jsx_runtime.jsx)("div", {
|
|
121234
|
+
className: "dsh-ig-inspiration-empty",
|
|
121235
|
+
children: onlyFavorites ? t("noFavorites") : t("noResults")
|
|
121236
|
+
}) : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)("div", {
|
|
121237
|
+
ref: listRef,
|
|
121238
|
+
className: "dsh-ig-inspiration-list",
|
|
121239
|
+
children: visibleGroups.map((group) => (0, react_jsx_runtime.jsxs)("section", {
|
|
121240
|
+
className: "dsh-ig-inspiration-group",
|
|
121241
|
+
children: [(0, react_jsx_runtime.jsxs)("h3", {
|
|
121242
|
+
id: `dsh-ig-cat-${encodeURIComponent(group.name)}`,
|
|
121243
|
+
"data-category": group.name,
|
|
121244
|
+
className: "dsh-ig-inspiration-group-head",
|
|
121245
|
+
children: [(0, react_jsx_runtime.jsx)("span", { children: translateTag(group.name, language) }), (0, react_jsx_runtime.jsx)("em", { children: categoryCounts.get(group.name) ?? group.items.length })]
|
|
121246
|
+
}), (0, react_jsx_runtime.jsx)("div", {
|
|
121247
|
+
className: "dsh-ig-inspiration-grid",
|
|
121248
|
+
children: group.items.map((item) => (0, react_jsx_runtime.jsx)(InspirationCard, {
|
|
121249
|
+
item,
|
|
121250
|
+
sourceId: source.id,
|
|
121251
|
+
sourceRevision: source.imageRevision ?? source.version,
|
|
121252
|
+
selected: selected?.id === item.id,
|
|
121253
|
+
isFavorited: favorites.has(item.id),
|
|
121254
|
+
language,
|
|
121255
|
+
featuredLabel: t("featured"),
|
|
121256
|
+
retryLabel: t("retry"),
|
|
121257
|
+
onSelect: () => {
|
|
121258
|
+
setSelected(item);
|
|
121259
|
+
setCopied(false);
|
|
121260
|
+
},
|
|
121261
|
+
onToggleFavorite: () => toggleFavorite(item.id)
|
|
121262
|
+
}, item.id))
|
|
121263
|
+
})]
|
|
121264
|
+
}, group.name))
|
|
121265
|
+
}), visibleCases.length < matchingCases.length ? (0, react_jsx_runtime.jsx)("div", {
|
|
121266
|
+
ref: sentinelRef,
|
|
121267
|
+
style: {
|
|
121268
|
+
height: 32,
|
|
121269
|
+
margin: "16px 0"
|
|
121270
|
+
}
|
|
121271
|
+
}) : (0, react_jsx_runtime.jsx)("div", {
|
|
121272
|
+
className: "dsh-ig-inspiration-end-hint",
|
|
121273
|
+
children: t("allLoaded", { count: String(matchingCases.length) })
|
|
121274
|
+
})] })] }), (0, react_jsx_runtime.jsx)("aside", {
|
|
121275
|
+
className: "dsh-ig-inspiration-inspector",
|
|
121276
|
+
children: selected === null ? (0, react_jsx_runtime.jsxs)("div", {
|
|
121277
|
+
className: "dsh-ig-inspiration-inspector-empty",
|
|
121278
|
+
children: [(0, react_jsx_runtime.jsx)(Image$2, { size: 28 }), (0, react_jsx_runtime.jsx)("span", { children: t("selectHint") })]
|
|
121279
|
+
}) : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
121280
|
+
className: "dsh-ig-inspiration-inspector-image",
|
|
121281
|
+
onClick: () => setLightboxCase({
|
|
121282
|
+
sourceId: source.id,
|
|
121283
|
+
caseId: selected.id,
|
|
121284
|
+
revision: source.imageRevision ?? source.version,
|
|
121285
|
+
title: selected.title,
|
|
121286
|
+
alt: selected.imageAlt
|
|
119428
121287
|
}),
|
|
119429
|
-
|
|
119430
|
-
|
|
119431
|
-
|
|
119432
|
-
|
|
119433
|
-
|
|
119434
|
-
|
|
119435
|
-
|
|
119436
|
-
|
|
119437
|
-
|
|
119438
|
-
|
|
119439
|
-
|
|
119440
|
-
|
|
119441
|
-
|
|
119442
|
-
|
|
119443
|
-
|
|
119444
|
-
|
|
121288
|
+
title: t("zoomHint"),
|
|
121289
|
+
children: [(0, react_jsx_runtime.jsx)(InspirationImage, {
|
|
121290
|
+
sourceId: source.id,
|
|
121291
|
+
caseId: selected.id,
|
|
121292
|
+
revision: source.imageRevision ?? source.version,
|
|
121293
|
+
alt: selected.imageAlt,
|
|
121294
|
+
retryLabel: t("retry")
|
|
121295
|
+
}), (0, react_jsx_runtime.jsxs)("span", {
|
|
121296
|
+
className: "dsh-ig-inspiration-inspector-zoom-hint",
|
|
121297
|
+
children: [(0, react_jsx_runtime.jsx)(Maximize2, { size: 11 }), t("zoomHint")]
|
|
121298
|
+
})]
|
|
121299
|
+
}), (0, react_jsx_runtime.jsxs)("div", {
|
|
121300
|
+
className: "dsh-ig-inspiration-inspector-body",
|
|
121301
|
+
children: [
|
|
121302
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
121303
|
+
className: "dsh-ig-inspiration-inspector-head",
|
|
121304
|
+
children: [(0, react_jsx_runtime.jsx)("h2", { children: selected.title }), (0, react_jsx_runtime.jsx)("button", {
|
|
119445
121305
|
type: "button",
|
|
119446
|
-
className:
|
|
119447
|
-
onClick: () =>
|
|
119448
|
-
|
|
119449
|
-
|
|
119450
|
-
|
|
119451
|
-
|
|
119452
|
-
|
|
119453
|
-
|
|
119454
|
-
|
|
119455
|
-
|
|
121306
|
+
className: `dsh-ig-inspiration-inspector-fav ${favorites.has(selected.id) ? "is-favorited" : ""}`,
|
|
121307
|
+
onClick: () => toggleFavorite(selected.id),
|
|
121308
|
+
title: favorites.has(selected.id) ? t("favorited") : t("favorite"),
|
|
121309
|
+
children: (0, react_jsx_runtime.jsx)(Star, {
|
|
121310
|
+
size: 15,
|
|
121311
|
+
className: favorites.has(selected.id) ? "fill-star" : ""
|
|
121312
|
+
})
|
|
121313
|
+
})]
|
|
121314
|
+
}),
|
|
121315
|
+
selected.sourceLabel && (0, react_jsx_runtime.jsx)("p", {
|
|
121316
|
+
className: "dsh-ig-inspiration-origin",
|
|
121317
|
+
children: selected.sourceLabel
|
|
121318
|
+
}),
|
|
121319
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
121320
|
+
className: "dsh-ig-inspiration-tags",
|
|
121321
|
+
children: [(0, react_jsx_runtime.jsx)("span", { children: translateTag(selected.category, language) }), selected.styles.slice(0, 3).map((item) => (0, react_jsx_runtime.jsx)("span", { children: translateTag(item, language) }, item))]
|
|
121322
|
+
}),
|
|
121323
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
121324
|
+
className: "dsh-ig-inspiration-prompt-label",
|
|
121325
|
+
children: [(0, react_jsx_runtime.jsx)("span", { children: t("prompt") }), (0, react_jsx_runtime.jsx)("span", { children: selected.prompt.length })]
|
|
121326
|
+
}),
|
|
121327
|
+
(0, react_jsx_runtime.jsx)("p", {
|
|
121328
|
+
className: "dsh-ig-inspiration-prompt",
|
|
121329
|
+
children: selected.prompt
|
|
121330
|
+
}),
|
|
121331
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
121332
|
+
className: "dsh-ig-inspiration-actions",
|
|
121333
|
+
children: [
|
|
121334
|
+
(0, react_jsx_runtime.jsxs)("button", {
|
|
121335
|
+
type: "button",
|
|
121336
|
+
onClick: () => void copyPrompt(),
|
|
121337
|
+
children: [copied ? (0, react_jsx_runtime.jsx)(Check, { size: 14 }) : (0, react_jsx_runtime.jsx)(Clipboard, { size: 14 }), copied ? t("copied") : t("copy")]
|
|
121338
|
+
}),
|
|
121339
|
+
selected.sourceUrl ?? selected.githubUrl ? (0, react_jsx_runtime.jsxs)("a", {
|
|
121340
|
+
className: "dsh-ig-inspiration-source-link",
|
|
121341
|
+
href: selected.sourceUrl ?? selected.githubUrl,
|
|
121342
|
+
target: "_blank",
|
|
121343
|
+
rel: "noreferrer",
|
|
121344
|
+
children: [(0, react_jsx_runtime.jsx)(ExternalLink, { size: 14 }), t("source")]
|
|
121345
|
+
}) : (0, react_jsx_runtime.jsx)("span", {}),
|
|
121346
|
+
(0, react_jsx_runtime.jsxs)("button", {
|
|
121347
|
+
type: "button",
|
|
121348
|
+
className: "dsh-ig-inspiration-use",
|
|
121349
|
+
onClick: () => onUsePrompt(selected.prompt),
|
|
121350
|
+
children: [(0, react_jsx_runtime.jsx)(Sparkles, { size: 14 }), t("use")]
|
|
121351
|
+
}),
|
|
121352
|
+
onUseReference !== void 0 ? (0, react_jsx_runtime.jsxs)("button", {
|
|
121353
|
+
type: "button",
|
|
121354
|
+
className: "dsh-ig-inspiration-use is-secondary",
|
|
121355
|
+
disabled: referenceBusy,
|
|
121356
|
+
onClick: () => {
|
|
121357
|
+
useSelectedReference();
|
|
121358
|
+
},
|
|
121359
|
+
children: [(0, react_jsx_runtime.jsx)(ImagePlus, { size: 14 }), referenceBusy ? t("referenceLoading") : t("useReference")]
|
|
121360
|
+
}) : null
|
|
121361
|
+
]
|
|
121362
|
+
})
|
|
121363
|
+
]
|
|
121364
|
+
})] })
|
|
121365
|
+
})]
|
|
121366
|
+
})
|
|
121367
|
+
] })] }),
|
|
119456
121368
|
lightboxCase !== null && (0, react_jsx_runtime.jsx)("div", {
|
|
119457
121369
|
className: "dsh-ig-inspiration-lightbox",
|
|
119458
121370
|
onClick: () => setLightboxCase(null),
|
|
@@ -119472,6 +121384,7 @@ img.ProseMirror-separator {
|
|
|
119472
121384
|
children: (0, react_jsx_runtime.jsx)(InspirationImage, {
|
|
119473
121385
|
sourceId: lightboxCase.sourceId,
|
|
119474
121386
|
caseId: lightboxCase.caseId,
|
|
121387
|
+
revision: lightboxCase.revision,
|
|
119475
121388
|
alt: lightboxCase.alt,
|
|
119476
121389
|
retryLabel: t("retry")
|
|
119477
121390
|
})
|
|
@@ -119524,7 +121437,155 @@ img.ProseMirror-separator {
|
|
|
119524
121437
|
]
|
|
119525
121438
|
});
|
|
119526
121439
|
};
|
|
119527
|
-
const
|
|
121440
|
+
const BaoyuComposerPanel = ({ language, selection, onChange, onUsePrompt }) => {
|
|
121441
|
+
const [copied, setCopied] = (0, react.useState)(false);
|
|
121442
|
+
const [copyFailed, setCopyFailed] = (0, react.useState)(false);
|
|
121443
|
+
const tr = (key, params) => {
|
|
121444
|
+
let text = COPY[language][key] ?? COPY.zh[key];
|
|
121445
|
+
if (params) for (const [k, v] of Object.entries(params)) text = text.replace(`{${k}}`, v);
|
|
121446
|
+
return text;
|
|
121447
|
+
};
|
|
121448
|
+
const label = (id) => language === "zh" ? BAOYU_LABELS_ZH[id] ?? id : id;
|
|
121449
|
+
const needsTitle = selection.text !== "none";
|
|
121450
|
+
const titleReady = !needsTitle || selection.title.trim() !== "";
|
|
121451
|
+
let prompt = "";
|
|
121452
|
+
if (titleReady) try {
|
|
121453
|
+
prompt = composeBaoyuPrompt(selection);
|
|
121454
|
+
} catch {
|
|
121455
|
+
prompt = "";
|
|
121456
|
+
}
|
|
121457
|
+
const combos = BAOYU_TYPES.length * BAOYU_PALETTES.length * BAOYU_RENDERINGS.length * BAOYU_TEXT_LEVELS.length * BAOYU_MOODS.length;
|
|
121458
|
+
const dimension = (name, key, options) => (0, react_jsx_runtime.jsxs)("div", {
|
|
121459
|
+
className: "dsh-ig-baoyu-dim",
|
|
121460
|
+
children: [(0, react_jsx_runtime.jsx)("div", {
|
|
121461
|
+
className: "dsh-ig-baoyu-dim-head",
|
|
121462
|
+
children: name
|
|
121463
|
+
}), (0, react_jsx_runtime.jsx)("div", {
|
|
121464
|
+
className: "dsh-ig-baoyu-chips",
|
|
121465
|
+
children: options.map((option) => {
|
|
121466
|
+
const palette = key === "palette" ? BAOYU_PALETTES.find((item) => item.id === option.id) : void 0;
|
|
121467
|
+
return (0, react_jsx_runtime.jsxs)("button", {
|
|
121468
|
+
type: "button",
|
|
121469
|
+
className: `dsh-ig-baoyu-chip ${selection[key] === option.id ? "is-active" : ""}`,
|
|
121470
|
+
onClick: () => {
|
|
121471
|
+
onChange({
|
|
121472
|
+
...selection,
|
|
121473
|
+
[key]: option.id
|
|
121474
|
+
});
|
|
121475
|
+
setCopied(false);
|
|
121476
|
+
},
|
|
121477
|
+
title: language === "zh" ? palette?.tagline ?? option.id : option.id,
|
|
121478
|
+
children: [(0, react_jsx_runtime.jsx)("span", { children: label(option.id) }), palette !== void 0 ? (0, react_jsx_runtime.jsx)("span", {
|
|
121479
|
+
className: "dsh-ig-baoyu-swatch",
|
|
121480
|
+
children: [
|
|
121481
|
+
palette.colors[0],
|
|
121482
|
+
palette.colors.find((color) => color.role === "Background"),
|
|
121483
|
+
palette.colors.find((color) => color.role === "Accent 1")
|
|
121484
|
+
].map((color, index) => color === void 0 ? null : (0, react_jsx_runtime.jsx)("i", { style: { background: color.hex } }, index))
|
|
121485
|
+
}) : null]
|
|
121486
|
+
}, option.id);
|
|
121487
|
+
})
|
|
121488
|
+
})]
|
|
121489
|
+
}, name);
|
|
121490
|
+
const copyPrompt = async () => {
|
|
121491
|
+
if (prompt === "") return;
|
|
121492
|
+
try {
|
|
121493
|
+
await navigator.clipboard.writeText(prompt);
|
|
121494
|
+
setCopied(true);
|
|
121495
|
+
setCopyFailed(false);
|
|
121496
|
+
} catch {
|
|
121497
|
+
setCopyFailed(true);
|
|
121498
|
+
}
|
|
121499
|
+
};
|
|
121500
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
121501
|
+
className: "dsh-ig-baoyu-panel",
|
|
121502
|
+
children: [
|
|
121503
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
121504
|
+
className: "dsh-ig-baoyu-intro",
|
|
121505
|
+
children: [(0, react_jsx_runtime.jsx)("strong", {
|
|
121506
|
+
className: "dsh-ig-baoyu-combos",
|
|
121507
|
+
children: tr("composeCombos", { count: String(combos) })
|
|
121508
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
121509
|
+
className: "dsh-ig-baoyu-hint",
|
|
121510
|
+
children: tr("composeHint")
|
|
121511
|
+
})]
|
|
121512
|
+
}),
|
|
121513
|
+
dimension(tr("composeType"), "type", BAOYU_TYPES),
|
|
121514
|
+
dimension(tr("composePalette"), "palette", BAOYU_PALETTES),
|
|
121515
|
+
dimension(tr("composeRendering"), "rendering", BAOYU_RENDERINGS),
|
|
121516
|
+
dimension(tr("composeText"), "text", BAOYU_TEXT_LEVELS),
|
|
121517
|
+
dimension(tr("composeMood"), "mood", BAOYU_MOODS),
|
|
121518
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
121519
|
+
className: "dsh-ig-baoyu-dim",
|
|
121520
|
+
children: [
|
|
121521
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
121522
|
+
className: "dsh-ig-baoyu-dim-head",
|
|
121523
|
+
children: tr("composeTitleLabel")
|
|
121524
|
+
}),
|
|
121525
|
+
(0, react_jsx_runtime.jsx)("input", {
|
|
121526
|
+
className: "dsh-ig-baoyu-title-input",
|
|
121527
|
+
value: selection.title,
|
|
121528
|
+
placeholder: tr("composeTitlePlaceholder"),
|
|
121529
|
+
disabled: selection.text === "none",
|
|
121530
|
+
onChange: (event) => {
|
|
121531
|
+
onChange({
|
|
121532
|
+
...selection,
|
|
121533
|
+
title: event.target.value
|
|
121534
|
+
});
|
|
121535
|
+
setCopied(false);
|
|
121536
|
+
}
|
|
121537
|
+
}),
|
|
121538
|
+
needsTitle && !titleReady ? (0, react_jsx_runtime.jsx)("div", {
|
|
121539
|
+
className: "dsh-ig-baoyu-required",
|
|
121540
|
+
children: tr("composeTitleRequired")
|
|
121541
|
+
}) : null
|
|
121542
|
+
]
|
|
121543
|
+
}),
|
|
121544
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
121545
|
+
className: "dsh-ig-baoyu-actions",
|
|
121546
|
+
children: [
|
|
121547
|
+
(0, react_jsx_runtime.jsxs)("button", {
|
|
121548
|
+
type: "button",
|
|
121549
|
+
className: "dsh-ig-baoyu-btn",
|
|
121550
|
+
onClick: () => onChange(randomBaoyuSelection(selection)),
|
|
121551
|
+
children: [(0, react_jsx_runtime.jsx)(Shuffle, { size: 13 }), (0, react_jsx_runtime.jsx)("span", { children: tr("composeRandomize") })]
|
|
121552
|
+
}),
|
|
121553
|
+
(0, react_jsx_runtime.jsxs)("button", {
|
|
121554
|
+
type: "button",
|
|
121555
|
+
className: "dsh-ig-baoyu-btn",
|
|
121556
|
+
disabled: prompt === "",
|
|
121557
|
+
onClick: () => {
|
|
121558
|
+
copyPrompt();
|
|
121559
|
+
},
|
|
121560
|
+
children: [copied ? (0, react_jsx_runtime.jsx)(Check, { size: 13 }) : (0, react_jsx_runtime.jsx)(Clipboard, { size: 13 }), (0, react_jsx_runtime.jsx)("span", { children: copied ? tr("copied") : tr("copy") })]
|
|
121561
|
+
}),
|
|
121562
|
+
(0, react_jsx_runtime.jsxs)("button", {
|
|
121563
|
+
type: "button",
|
|
121564
|
+
className: "dsh-ig-baoyu-btn is-primary",
|
|
121565
|
+
disabled: prompt === "",
|
|
121566
|
+
onClick: () => onUsePrompt(prompt),
|
|
121567
|
+
children: [(0, react_jsx_runtime.jsx)(Sparkles, { size: 13 }), (0, react_jsx_runtime.jsx)("span", { children: tr("composeUse") })]
|
|
121568
|
+
}),
|
|
121569
|
+
copyFailed ? (0, react_jsx_runtime.jsx)("span", {
|
|
121570
|
+
className: "dsh-ig-baoyu-required",
|
|
121571
|
+
children: tr("copyFailed")
|
|
121572
|
+
}) : null
|
|
121573
|
+
]
|
|
121574
|
+
}),
|
|
121575
|
+
prompt !== "" ? (0, react_jsx_runtime.jsxs)("div", {
|
|
121576
|
+
className: "dsh-ig-baoyu-preview-block",
|
|
121577
|
+
children: [(0, react_jsx_runtime.jsx)("div", {
|
|
121578
|
+
className: "dsh-ig-baoyu-preview-head",
|
|
121579
|
+
children: tr("composePreview")
|
|
121580
|
+
}), (0, react_jsx_runtime.jsx)("pre", {
|
|
121581
|
+
className: "dsh-ig-baoyu-preview",
|
|
121582
|
+
children: prompt
|
|
121583
|
+
})]
|
|
121584
|
+
}) : null
|
|
121585
|
+
]
|
|
121586
|
+
});
|
|
121587
|
+
};
|
|
121588
|
+
const InspirationCard = ({ item, sourceId, sourceRevision, selected, isFavorited, language, featuredLabel, retryLabel, onSelect, onToggleFavorite }) => (0, react_jsx_runtime.jsxs)("button", {
|
|
119528
121589
|
type: "button",
|
|
119529
121590
|
className: `dsh-ig-inspiration-card ${selected ? "is-selected" : ""}`,
|
|
119530
121591
|
onClick: onSelect,
|
|
@@ -119551,6 +121612,7 @@ img.ProseMirror-separator {
|
|
|
119551
121612
|
(0, react_jsx_runtime.jsx)(InspirationImage, {
|
|
119552
121613
|
sourceId,
|
|
119553
121614
|
caseId: item.id,
|
|
121615
|
+
revision: sourceRevision,
|
|
119554
121616
|
alt: item.imageAlt,
|
|
119555
121617
|
retryLabel
|
|
119556
121618
|
})
|
|
@@ -119560,7 +121622,7 @@ img.ProseMirror-separator {
|
|
|
119560
121622
|
children: [(0, react_jsx_runtime.jsx)("strong", { children: item.title }), (0, react_jsx_runtime.jsx)("span", { children: translateTag(item.category, language) })]
|
|
119561
121623
|
})]
|
|
119562
121624
|
});
|
|
119563
|
-
const InspirationImage = ({ sourceId, caseId, alt, retryLabel = "Retry" }) => {
|
|
121625
|
+
const InspirationImage = ({ sourceId, caseId, revision, alt, retryLabel = "Retry" }) => {
|
|
119564
121626
|
const [node, setNode] = (0, react.useState)(null);
|
|
119565
121627
|
const [visible, setVisible] = (0, react.useState)(false);
|
|
119566
121628
|
const [url, setUrl] = (0, react.useState)(null);
|
|
@@ -119581,7 +121643,7 @@ img.ProseMirror-separator {
|
|
|
119581
121643
|
urlRef.current = null;
|
|
119582
121644
|
}
|
|
119583
121645
|
setUrl(null);
|
|
119584
|
-
fetchInspirationImage(sourceId, caseId).then((blob) => {
|
|
121646
|
+
fetchInspirationImage(sourceId, caseId, revision).then((blob) => {
|
|
119585
121647
|
if (!active) return;
|
|
119586
121648
|
const next = URL.createObjectURL(blob);
|
|
119587
121649
|
if (urlRef.current !== null) URL.revokeObjectURL(urlRef.current);
|
|
@@ -119596,7 +121658,8 @@ img.ProseMirror-separator {
|
|
|
119596
121658
|
}, [
|
|
119597
121659
|
visible,
|
|
119598
121660
|
sourceId,
|
|
119599
|
-
caseId
|
|
121661
|
+
caseId,
|
|
121662
|
+
revision
|
|
119600
121663
|
]);
|
|
119601
121664
|
(0, react.useEffect)(() => {
|
|
119602
121665
|
return () => {
|
|
@@ -119633,7 +121696,7 @@ img.ProseMirror-separator {
|
|
|
119633
121696
|
urlRef.current = null;
|
|
119634
121697
|
}
|
|
119635
121698
|
setUrl(null);
|
|
119636
|
-
evictInspirationImage(sourceId, caseId).then(() => fetchInspirationImage(sourceId, caseId)).then((blob) => {
|
|
121699
|
+
evictInspirationImage(sourceId, caseId, revision).then(() => fetchInspirationImage(sourceId, caseId, revision)).then((blob) => {
|
|
119637
121700
|
const next = URL.createObjectURL(blob);
|
|
119638
121701
|
if (urlRef.current !== null) URL.revokeObjectURL(urlRef.current);
|
|
119639
121702
|
urlRef.current = next;
|
|
@@ -119751,6 +121814,12 @@ img.ProseMirror-separator {
|
|
|
119751
121814
|
filterXAI: "xAI Grok",
|
|
119752
121815
|
filterZhipu: "智谱 GLM",
|
|
119753
121816
|
filterComfyUI: "本地 ComfyUI",
|
|
121817
|
+
filterImport: "导入",
|
|
121818
|
+
importImages: "导入图片",
|
|
121819
|
+
importAdded: "已导入 {count} 张图片",
|
|
121820
|
+
importPartial: "导入 {count} 张,{fail} 张失败",
|
|
121821
|
+
importFailed: "导入失败",
|
|
121822
|
+
importPickHint: "选择要导入的图片(PNG/JPG/WebP/GIF)",
|
|
119754
121823
|
filterAllModels: "全部模型",
|
|
119755
121824
|
filterAllRatios: "全部比例",
|
|
119756
121825
|
searchPlaceholder: "搜索 Prompt、标签…",
|
|
@@ -119847,6 +121916,12 @@ img.ProseMirror-separator {
|
|
|
119847
121916
|
filterXAI: "xAI Grok",
|
|
119848
121917
|
filterZhipu: "Zhipu GLM",
|
|
119849
121918
|
filterComfyUI: "Local ComfyUI",
|
|
121919
|
+
filterImport: "Imported",
|
|
121920
|
+
importImages: "Import images",
|
|
121921
|
+
importAdded: "Imported {count} images",
|
|
121922
|
+
importPartial: "Imported {count}, {fail} failed",
|
|
121923
|
+
importFailed: "Import failed",
|
|
121924
|
+
importPickHint: "Choose images to import (PNG/JPG/WebP/GIF)",
|
|
119850
121925
|
filterAllModels: "All Models",
|
|
119851
121926
|
filterAllRatios: "All Ratios",
|
|
119852
121927
|
searchPlaceholder: "Search prompt, tags…",
|
|
@@ -119929,6 +122004,19 @@ img.ProseMirror-separator {
|
|
|
119929
122004
|
}
|
|
119930
122005
|
};
|
|
119931
122006
|
/** Format human-readable relative time */
|
|
122007
|
+
/** Read a browser-picked file as base64 payload for the import route. */
|
|
122008
|
+
function readFileBase64(file) {
|
|
122009
|
+
return new Promise((resolve, reject) => {
|
|
122010
|
+
const reader = new FileReader();
|
|
122011
|
+
reader.onload = () => {
|
|
122012
|
+
const result = reader.result;
|
|
122013
|
+
if (typeof result === "string") resolve(result.slice(result.indexOf(",") + 1));
|
|
122014
|
+
else reject(/* @__PURE__ */ new Error("read-failed"));
|
|
122015
|
+
};
|
|
122016
|
+
reader.onerror = () => reject(/* @__PURE__ */ new Error("read-failed"));
|
|
122017
|
+
reader.readAsDataURL(file);
|
|
122018
|
+
});
|
|
122019
|
+
}
|
|
119932
122020
|
function formatRelativeTime(timestamp, t) {
|
|
119933
122021
|
const diff = Date.now() - timestamp;
|
|
119934
122022
|
if (diff < 6e4) return t("justNow");
|
|
@@ -119987,6 +122075,7 @@ img.ProseMirror-separator {
|
|
|
119987
122075
|
const { locale, sessionId, useSessions, useWorkspaces, credentialEvents, inSidebar, defaultTab, initialCanvasSurface, useTabInfo } = props;
|
|
119988
122076
|
const [activeTab, setActiveTab] = (0, react.useState)(defaultTab ?? "gallery");
|
|
119989
122077
|
const [studioDraft, setStudioDraft] = (0, react.useState)(void 0);
|
|
122078
|
+
const [studioReference, setStudioReference] = (0, react.useState)(void 0);
|
|
119990
122079
|
const [items, setItems] = (0, react.useState)([]);
|
|
119991
122080
|
const [search, setSearch] = (0, react.useState)("");
|
|
119992
122081
|
const [selectedProvider, setSelectedProvider] = (0, react.useState)("all");
|
|
@@ -120101,11 +122190,80 @@ img.ProseMirror-separator {
|
|
|
120101
122190
|
setToast(null);
|
|
120102
122191
|
}, 2e3);
|
|
120103
122192
|
};
|
|
122193
|
+
const [importing, setImporting] = (0, react.useState)(false);
|
|
122194
|
+
const importInputRef = (0, react.useRef)(null);
|
|
122195
|
+
const importImages = async (files) => {
|
|
122196
|
+
if (files === null || files.length === 0 || importing) return;
|
|
122197
|
+
const all = Array.from(files);
|
|
122198
|
+
const picked = all.filter((file) => file.type.startsWith("image/")).slice(0, 8);
|
|
122199
|
+
if (picked.length === 0) {
|
|
122200
|
+
showToast(t("importFailed"));
|
|
122201
|
+
return;
|
|
122202
|
+
}
|
|
122203
|
+
setImporting(true);
|
|
122204
|
+
try {
|
|
122205
|
+
const reads = await Promise.allSettled(picked.map((file) => readFileBase64(file)));
|
|
122206
|
+
const images = reads.flatMap((read, index) => {
|
|
122207
|
+
if (read.status !== "fulfilled") return [];
|
|
122208
|
+
const file = picked[index];
|
|
122209
|
+
return [{
|
|
122210
|
+
data: read.value,
|
|
122211
|
+
mediaType: file.type,
|
|
122212
|
+
...file.name.length > 0 ? { name: file.name } : {}
|
|
122213
|
+
}];
|
|
122214
|
+
});
|
|
122215
|
+
const readFailures = reads.length - images.length;
|
|
122216
|
+
if (images.length === 0) {
|
|
122217
|
+
showToast(t("importFailed"));
|
|
122218
|
+
return;
|
|
122219
|
+
}
|
|
122220
|
+
const response = await fetch(IMPORT_ROUTE, {
|
|
122221
|
+
method: "POST",
|
|
122222
|
+
credentials: "same-origin",
|
|
122223
|
+
headers: { "content-type": "application/json" },
|
|
122224
|
+
body: JSON.stringify({ images })
|
|
122225
|
+
});
|
|
122226
|
+
if (!response.ok) throw new Error(`HTTP ${String(response.status)}`);
|
|
122227
|
+
const payload = await response.json();
|
|
122228
|
+
const imported = payload.images ?? [];
|
|
122229
|
+
let added = 0;
|
|
122230
|
+
let writeFailures = 0;
|
|
122231
|
+
for (const entry of imported) if (await saveGalleryItem({
|
|
122232
|
+
id: `import-${entry.attachment.attachmentId}-${crypto.randomUUID()}`,
|
|
122233
|
+
attachment: entry.attachment,
|
|
122234
|
+
prompt: "",
|
|
122235
|
+
provider: "import",
|
|
122236
|
+
model: "",
|
|
122237
|
+
createdAt: Date.now(),
|
|
122238
|
+
...activeWorkspace?.workspaceId ? { workspaceId: activeWorkspace.workspaceId } : {},
|
|
122239
|
+
...activeWorkspace?.path ? { workspacePath: activeWorkspace.path } : {},
|
|
122240
|
+
...currentSessionId ? { sessionId: currentSessionId } : {}
|
|
122241
|
+
})) added += 1;
|
|
122242
|
+
else writeFailures += 1;
|
|
122243
|
+
const failCount = (payload.failures ?? []).length + (all.length - picked.length) + readFailures + writeFailures;
|
|
122244
|
+
if (added === 0) showToast(t("importFailed"));
|
|
122245
|
+
else if (failCount > 0) showToast(t("importPartial", {
|
|
122246
|
+
count: String(added),
|
|
122247
|
+
fail: String(failCount)
|
|
122248
|
+
}));
|
|
122249
|
+
else showToast(t("importAdded", { count: String(added) }));
|
|
122250
|
+
} catch {
|
|
122251
|
+
showToast(t("importFailed"));
|
|
122252
|
+
} finally {
|
|
122253
|
+
setImporting(false);
|
|
122254
|
+
}
|
|
122255
|
+
};
|
|
120104
122256
|
const useInspirationPrompt = (0, react.useCallback)((prompt) => {
|
|
120105
122257
|
setStudioDraft(prompt);
|
|
120106
122258
|
setActiveTab("studio");
|
|
120107
122259
|
}, []);
|
|
122260
|
+
const useInspirationReference = (0, react.useCallback)((file, prompt) => {
|
|
122261
|
+
setStudioDraft(prompt);
|
|
122262
|
+
setStudioReference(file);
|
|
122263
|
+
setActiveTab("studio");
|
|
122264
|
+
}, []);
|
|
120108
122265
|
const clearStudioDraft = (0, react.useCallback)(() => setStudioDraft(void 0), []);
|
|
122266
|
+
const clearStudioReference = (0, react.useCallback)(() => setStudioReference(void 0), []);
|
|
120109
122267
|
(0, react.useEffect)(() => {
|
|
120110
122268
|
if (inSidebar) return void 0;
|
|
120111
122269
|
const seat = document.querySelector("[data-composer-seat]");
|
|
@@ -120655,6 +122813,10 @@ img.ProseMirror-separator {
|
|
|
120655
122813
|
(0, react_jsx_runtime.jsx)("option", {
|
|
120656
122814
|
value: "comfyui",
|
|
120657
122815
|
children: t("filterComfyUI")
|
|
122816
|
+
}),
|
|
122817
|
+
(0, react_jsx_runtime.jsx)("option", {
|
|
122818
|
+
value: "import",
|
|
122819
|
+
children: t("filterImport")
|
|
120658
122820
|
})
|
|
120659
122821
|
]
|
|
120660
122822
|
}),
|
|
@@ -120737,27 +122899,48 @@ img.ProseMirror-separator {
|
|
|
120737
122899
|
]
|
|
120738
122900
|
}), (0, react_jsx_runtime.jsxs)("div", {
|
|
120739
122901
|
className: "dsh-ig-studio-toolbar-right",
|
|
120740
|
-
children: [
|
|
120741
|
-
|
|
120742
|
-
|
|
120743
|
-
|
|
120744
|
-
|
|
120745
|
-
|
|
120746
|
-
|
|
120747
|
-
|
|
120748
|
-
|
|
120749
|
-
|
|
120750
|
-
|
|
120751
|
-
|
|
120752
|
-
|
|
120753
|
-
|
|
120754
|
-
|
|
120755
|
-
|
|
120756
|
-
|
|
120757
|
-
|
|
120758
|
-
},
|
|
120759
|
-
|
|
120760
|
-
|
|
122902
|
+
children: [
|
|
122903
|
+
activeTab === "gallery" && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)("input", {
|
|
122904
|
+
ref: importInputRef,
|
|
122905
|
+
type: "file",
|
|
122906
|
+
accept: "image/png,image/jpeg,image/webp,image/gif",
|
|
122907
|
+
multiple: true,
|
|
122908
|
+
style: { display: "none" },
|
|
122909
|
+
onChange: (event) => {
|
|
122910
|
+
importImages(event.target.files);
|
|
122911
|
+
event.target.value = "";
|
|
122912
|
+
}
|
|
122913
|
+
}), (0, react_jsx_runtime.jsxs)("button", {
|
|
122914
|
+
type: "button",
|
|
122915
|
+
className: "dsh-ig-studio-btn",
|
|
122916
|
+
disabled: importing,
|
|
122917
|
+
title: t("importPickHint"),
|
|
122918
|
+
onClick: () => importInputRef.current?.click(),
|
|
122919
|
+
children: [(0, react_jsx_runtime.jsx)(Upload, { size: 13 }), (0, react_jsx_runtime.jsx)("span", { children: t("importImages") })]
|
|
122920
|
+
})] }),
|
|
122921
|
+
(0, react_jsx_runtime.jsxs)("select", {
|
|
122922
|
+
className: "dsh-ig-studio-select dsh-ig-studio-select-sort",
|
|
122923
|
+
value: sortBy,
|
|
122924
|
+
onChange: (e) => setSortBy(e.target.value),
|
|
122925
|
+
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
122926
|
+
value: "newest",
|
|
122927
|
+
children: t("sortNewest")
|
|
122928
|
+
}), (0, react_jsx_runtime.jsx)("option", {
|
|
122929
|
+
value: "oldest",
|
|
122930
|
+
children: t("sortOldest")
|
|
122931
|
+
})]
|
|
122932
|
+
}),
|
|
122933
|
+
(0, react_jsx_runtime.jsxs)("button", {
|
|
122934
|
+
type: "button",
|
|
122935
|
+
className: `dsh-ig-studio-btn ${isManageMode ? "is-active" : ""}`,
|
|
122936
|
+
title: isManageMode ? t("exitManage") : t("manage"),
|
|
122937
|
+
onClick: () => {
|
|
122938
|
+
if (isManageMode) handleExitManage();
|
|
122939
|
+
else setIsManageMode(true);
|
|
122940
|
+
},
|
|
122941
|
+
children: [(0, react_jsx_runtime.jsx)(SquareCheckBig, { size: 13 }), (0, react_jsx_runtime.jsx)("span", { children: isManageMode ? t("exitManage") : t("manage") })]
|
|
122942
|
+
})
|
|
122943
|
+
]
|
|
120761
122944
|
})]
|
|
120762
122945
|
}),
|
|
120763
122946
|
(0, react_jsx_runtime.jsx)("div", {
|
|
@@ -120827,15 +123010,18 @@ img.ProseMirror-separator {
|
|
|
120827
123010
|
}, item.id))
|
|
120828
123011
|
}) : activeTab === "inspiration" ? (0, react_jsx_runtime.jsx)(InspirationView, {
|
|
120829
123012
|
locale,
|
|
120830
|
-
onUsePrompt: useInspirationPrompt
|
|
123013
|
+
onUsePrompt: useInspirationPrompt,
|
|
123014
|
+
onUseReference: useInspirationReference
|
|
120831
123015
|
}) : (0, react_jsx_runtime.jsx)(StudioView, {
|
|
120832
123016
|
locale,
|
|
120833
123017
|
credentialEvents,
|
|
120834
123018
|
workspace: activeWorkspace,
|
|
120835
123019
|
initialPrompt: studioDraft,
|
|
123020
|
+
initialReference: studioReference,
|
|
120836
123021
|
initialCanvasSurface,
|
|
120837
123022
|
showInfiniteCanvasHint: !inSidebar,
|
|
120838
123023
|
onInitialPromptApplied: clearStudioDraft,
|
|
123024
|
+
onInitialReferenceApplied: clearStudioReference,
|
|
120839
123025
|
onOpenInspiration: () => setActiveTab("inspiration")
|
|
120840
123026
|
})
|
|
120841
123027
|
}),
|
|
@@ -120995,7 +123181,7 @@ img.ProseMirror-separator {
|
|
|
120995
123181
|
children: [
|
|
120996
123182
|
(0, react_jsx_runtime.jsx)("span", {
|
|
120997
123183
|
className: "dsh-ig-tag",
|
|
120998
|
-
children: previewItem.provider
|
|
123184
|
+
children: previewItem.provider === "import" ? t("filterImport") : previewItem.provider
|
|
120999
123185
|
}),
|
|
121000
123186
|
previewItem.model && (0, react_jsx_runtime.jsx)("span", {
|
|
121001
123187
|
className: "dsh-ig-tag dsh-ig-tag-model",
|
|
@@ -121053,7 +123239,7 @@ img.ProseMirror-separator {
|
|
|
121053
123239
|
children: [
|
|
121054
123240
|
(0, react_jsx_runtime.jsx)("span", {
|
|
121055
123241
|
className: "dsh-ig-tag",
|
|
121056
|
-
children: previewItem.provider
|
|
123242
|
+
children: previewItem.provider === "import" ? t("filterImport") : previewItem.provider
|
|
121057
123243
|
}),
|
|
121058
123244
|
previewItem.model ? (0, react_jsx_runtime.jsx)("span", {
|
|
121059
123245
|
className: "dsh-ig-tag dsh-ig-tag-model",
|
|
@@ -121646,105 +123832,139 @@ img.ProseMirror-separator {
|
|
|
121646
123832
|
//#region lib/types/client/studio-style.js
|
|
121647
123833
|
const STUDIO_STYLE = `
|
|
121648
123834
|
.dsh-ig-gallery-page-body.is-workbench{flex:1 1 0;height:100%;min-height:0;padding:0;overflow:hidden;display:flex;flex-direction:column}
|
|
121649
|
-
.dsh-ig-workbench{--ig-blue
|
|
123835
|
+
.dsh-ig-workbench{--ig-blue:var(--dsw-alias-brand-primary-new-colorprimary-new-color,#2f64f5);--ig-blue-line:color-mix(in srgb,var(--ig-blue) 45%,transparent);--ig-line:var(--dsw-alias-border-l2,color-mix(in srgb,currentColor 11%,transparent));--ig-soft:color-mix(in srgb,currentColor 4%,transparent);--ig-fg:var(--dsw-alias-label-primary,var(--foreground,#182033));--ig-fg-2:var(--dsw-alias-label-secondary,#5a6478);--ig-fg-3:var(--dsw-alias-label-tertiary,#717b90);--ig-fg-cap:var(--dsw-alias-label-caption,#929bad);--ig-bg:var(--dsw-alias-bg-layer-1,var(--background,#fff));--ig-bg-panel:var(--dsw-alias-bg-layer-2,color-mix(in srgb,var(--background,#fff) 96%,#f5f7fb));--ig-bg-thumb:var(--dsw-alias-bg-skeleton,#eef1f7);--ig-danger:#b63737;--ig-warn:#8b671c;position:relative;display:flex;flex-direction:column;min-height:0;height:100%;overflow:hidden;padding:10px 12px 12px;color:var(--ig-fg);box-sizing:border-box;background:radial-gradient(circle at 60% -20%,rgba(63,104,246,.07),transparent 30%)}
|
|
123836
|
+
body[data-ds-dark-theme] .dsh-ig-workbench{--ig-danger:#f08c8c;--ig-warn:#e5b76a}
|
|
121650
123837
|
.dsh-ig-workbench *{box-sizing:border-box}.dsh-ig-workbench button,.dsh-ig-workbench select,.dsh-ig-workbench textarea{font:inherit;color:inherit}
|
|
121651
|
-
.dsh-ig-workbench-grid{display:grid;grid-template-columns:minmax(190px,238px) minmax(0,1fr) minmax(286px,340px);grid-template-rows:minmax(0,1fr);min-height:0;height:0;flex:1 1 0;border:1px solid var(--ig-line);border-radius:12px;overflow:hidden;background:var(--
|
|
123838
|
+
.dsh-ig-workbench-grid{display:grid;grid-template-columns:minmax(190px,238px) minmax(0,1fr) minmax(286px,340px);grid-template-rows:minmax(0,1fr);min-height:0;height:0;flex:1 1 0;border:1px solid var(--ig-line);border-radius:12px;overflow:hidden;background:var(--ig-bg);box-shadow:0 12px 32px rgba(30,42,76,.05);transition:grid-template-columns .2s ease}
|
|
121652
123839
|
.dsh-ig-workbench-grid.is-sidebar-collapsed{grid-template-columns:minmax(0,1fr) minmax(286px,340px)}
|
|
121653
123840
|
.dsh-ig-workbench-grid.is-generate-collapsed{grid-template-columns:minmax(190px,238px) minmax(0,1fr)}
|
|
121654
123841
|
.dsh-ig-workbench-grid.is-sidebar-collapsed.is-generate-collapsed{grid-template-columns:minmax(0,1fr)}
|
|
121655
|
-
.dsh-ig-recent-panel,.dsh-ig-generate-panel{min-width:0;min-height:0;overflow:hidden;background:
|
|
123842
|
+
.dsh-ig-recent-panel,.dsh-ig-generate-panel{min-width:0;min-height:0;overflow:hidden;background:var(--ig-bg-panel)}.dsh-ig-recent-panel{display:flex;flex-direction:column;border-right:1px solid var(--ig-line)}
|
|
121656
123843
|
.dsh-ig-panel-title{height:48px;flex:0 0 48px;padding:0 12px 0 14px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--ig-line);font-size:13px;font-weight:650}
|
|
121657
|
-
.dsh-ig-count-badge{font-size:11px;min-width:22px;text-align:center;padding:2px 6px;border-radius:999px;background:var(--ig-soft);color
|
|
121658
|
-
.dsh-ig-collapse-btn{width:28px;height:28px;display:inline-flex;align-items:center;justify-content:center;border:1px solid transparent;border-radius:6px;background:transparent;color
|
|
121659
|
-
.dsh-ig-collapse-btn:hover{border-color:var(--ig-line);background:var(--ig-soft);color:var(--
|
|
121660
|
-
.dsh-ig-recent-scroll{flex:1 1 0;height:0;padding:8px;overflow-x:hidden;overflow-y:auto;min-height:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(78px,1fr));gap:6px;align-content:start}.dsh-ig-recent-empty{min-height:180px;display:flex;flex-direction:column;justify-content:center;align-items:center;gap:10px;color
|
|
121661
|
-
.dsh-ig-
|
|
121662
|
-
.dsh-ig-
|
|
121663
|
-
.dsh-ig-
|
|
121664
|
-
.dsh-ig-
|
|
123844
|
+
.dsh-ig-count-badge{font-size:11px;min-width:22px;text-align:center;padding:2px 6px;border-radius:999px;background:var(--ig-soft);color:var(--ig-fg-3);font-weight:500}
|
|
123845
|
+
.dsh-ig-collapse-btn{width:28px;height:28px;display:inline-flex;align-items:center;justify-content:center;border:1px solid transparent;border-radius:6px;background:transparent;color:var(--ig-fg-3);cursor:pointer;transition:all .15s}
|
|
123846
|
+
.dsh-ig-collapse-btn:hover{border-color:var(--ig-line);background:var(--ig-soft);color:var(--ig-fg)}
|
|
123847
|
+
.dsh-ig-recent-scroll{flex:1 1 0;height:0;padding:8px;overflow-x:hidden;overflow-y:auto;min-height:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(78px,1fr));gap:6px;align-content:start}.dsh-ig-recent-empty{min-height:180px;display:flex;flex-direction:column;justify-content:center;align-items:center;gap:10px;color:var(--ig-fg-cap);text-align:center;font-size:12px;grid-column:1/-1}
|
|
123848
|
+
.dsh-ig-fav-folder-add{margin-left:auto;padding:0 5px;border:0;background:transparent;color:var(--ig-fg-3);font-size:12px;line-height:16px;cursor:pointer;border-radius:4px}.dsh-ig-fav-folder-add:hover{color:var(--ig-blue);background:var(--ig-bg-thumb)}
|
|
123849
|
+
.dsh-ig-fav-folders{display:flex;flex-wrap:wrap;gap:4px;margin:4px 0 6px}
|
|
123850
|
+
.dsh-ig-fav-folder-chip{display:inline-flex;align-items:center;gap:2px;padding:2px 6px;border:1px solid var(--ig-line);border-radius:999px;background:transparent;color:var(--ig-fg-3);font-size:10.5px}
|
|
123851
|
+
.dsh-ig-fav-folder-chip.is-active{border-color:var(--ig-blue-line);color:var(--ig-blue);background:color-mix(in srgb,var(--ig-blue) 10%,transparent)}
|
|
123852
|
+
.dsh-ig-fav-folder-chip>button:first-child{border:0;background:transparent;color:inherit;font-size:inherit;padding:0;cursor:pointer}
|
|
123853
|
+
.dsh-ig-fav-folder-del{border:0;background:transparent;color:var(--ig-fg-3);cursor:pointer;display:inline-flex;padding:0}.dsh-ig-fav-folder-del:hover{color:var(--ig-danger)}
|
|
123854
|
+
.dsh-ig-fav-folder-draft{display:flex;gap:4px;margin:2px 0 6px}
|
|
123855
|
+
.dsh-ig-fav-folder-draft input{flex:1;min-width:0;padding:3px 6px;border:1px solid var(--ig-line);border-radius:5px;background:var(--ig-bg);color:var(--ig-fg);font-size:11px}
|
|
123856
|
+
.dsh-ig-fav-folder-draft button{padding:3px 8px;border:1px solid var(--ig-line);border-radius:5px;background:transparent;color:var(--ig-fg-2);font-size:11px;cursor:pointer}
|
|
123857
|
+
.dsh-ig-fav-folder-draft button:first-of-type{border-color:var(--ig-blue-line);color:var(--ig-blue)}
|
|
123858
|
+
.dsh-ig-fav-dialog-wrap{position:fixed;inset:0;z-index:60;display:flex;align-items:center;justify-content:center;background:rgba(15,20,34,.45)}
|
|
123859
|
+
.dsh-ig-fav-dialog{width:min(420px,92vw);max-height:70vh;overflow:auto;padding:14px;border-radius:10px;background:var(--ig-bg-panel);border:1px solid var(--ig-line);box-shadow:0 12px 32px rgba(10,14,26,.25);display:flex;flex-direction:column;gap:10px}
|
|
123860
|
+
.dsh-ig-fav-dialog-title{font-size:12.5px;font-weight:600;color:var(--ig-fg)}
|
|
123861
|
+
.dsh-ig-fav-dialog-textarea{width:100%;resize:vertical;padding:8px;border:1px solid var(--ig-line);border-radius:6px;background:var(--ig-bg);color:var(--ig-fg);font-size:12px;line-height:1.5}
|
|
123862
|
+
.dsh-ig-fav-dialog-folder-label{display:flex;align-items:center;gap:8px;font-size:11.5px;color:var(--ig-fg-2)}
|
|
123863
|
+
.dsh-ig-fav-dialog-folder-label select{flex:1;padding:4px 6px;border:1px solid var(--ig-line);border-radius:5px;background:var(--ig-bg);color:var(--ig-fg);font-size:11.5px}
|
|
123864
|
+
.dsh-ig-fav-dialog-actions{display:flex;gap:6px;justify-content:flex-end;flex-wrap:wrap}
|
|
123865
|
+
.dsh-ig-fav-dialog-actions button{padding:5px 12px;border:1px solid var(--ig-line);border-radius:6px;background:transparent;color:var(--ig-fg-2);font-size:12px;cursor:pointer}
|
|
123866
|
+
.dsh-ig-fav-dialog-actions button.is-primary{border-color:var(--ig-blue);background:var(--ig-blue);color:#fff}
|
|
123867
|
+
.dsh-ig-fav-dialog-folders{display:flex;flex-direction:column;gap:4px}
|
|
123868
|
+
.dsh-ig-fav-dialog-folders button{text-align:left;padding:6px 10px;border:1px solid var(--ig-line);border-radius:6px;background:transparent;color:var(--ig-fg-2);font-size:12px;cursor:pointer}
|
|
123869
|
+
.dsh-ig-fav-dialog-folders button:hover,.dsh-ig-fav-dialog-folders button.is-current{border-color:var(--ig-blue-line);color:var(--ig-blue);background:color-mix(in srgb,var(--ig-blue) 8%,transparent)}
|
|
123870
|
+
.dsh-ig-fav-del{position:absolute;top:-5px;right:-5px;width:18px;height:18px;display:inline-flex;align-items:center;justify-content:center;padding:0;border:1px solid var(--ig-line);border-radius:50%;background:var(--ig-bg);color:var(--ig-fg-3);cursor:pointer;z-index:2;opacity:0;pointer-events:none;transition:opacity .12s,color .15s,border-color .15s}.dsh-ig-fav-del:hover{color:#d5495c;border-color:#e6a3ad}.dsh-ig-fav-prompt:hover .dsh-ig-fav-del,.dsh-ig-fav-del:focus-visible{opacity:1;pointer-events:auto}.dsh-ig-fav-del:focus-visible{outline:2px solid var(--ig-blue);outline-offset:1px}
|
|
123871
|
+
.dsh-ig-fav-prompt{position:relative;display:flex;align-items:flex-start;gap:2px}
|
|
123872
|
+
.dsh-ig-fav-prompt-text{flex:1;min-width:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;text-align:left;padding:5px 8px;border:1px solid var(--ig-line);border-radius:6px;background:transparent;font-size:11px;line-height:1.45;color:var(--ig-fg);cursor:pointer;transition:all .15s}.dsh-ig-fav-prompt-text:hover{border-color:var(--ig-blue-line);background:var(--ig-soft)}
|
|
123873
|
+
.dsh-ig-fav-save-btn{display:inline-flex;align-items:center;justify-content:center;padding:2px 4px;border:0;background:transparent;color:var(--ig-fg-cap);cursor:pointer;transition:color .15s}.dsh-ig-fav-save-btn:hover{color:#e8a33d}
|
|
123874
|
+
.dsh-ig-rail-tabs{flex:none;display:flex;gap:4px;padding:4px 8px 6px;border-bottom:1px solid var(--ig-line)}
|
|
123875
|
+
.dsh-ig-rail-tab{flex:1;height:26px;display:inline-flex;align-items:center;justify-content:center;border:1px solid transparent;border-radius:6px;background:transparent;font-size:12px;color:var(--ig-fg-3);cursor:pointer;transition:all .15s}.dsh-ig-rail-tab:hover{background:var(--ig-soft);color:var(--ig-fg)}.dsh-ig-rail-tab.is-active{border-color:var(--ig-blue-line);background:var(--ig-soft);color:var(--ig-blue);font-weight:600}
|
|
123876
|
+
.dsh-ig-fav-scroll{flex:1 1 0;height:0;overflow-x:hidden;overflow-y:auto;min-height:0;padding:8px}
|
|
123877
|
+
.dsh-ig-fav-section-label{padding:4px 2px 6px;font-size:11px;font-weight:600;color:var(--ig-fg-3)}
|
|
123878
|
+
.dsh-ig-fav-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(64px,1fr));gap:6px}
|
|
123879
|
+
.dsh-ig-fav-empty{min-height:64px;display:flex;flex-direction:column;justify-content:center;align-items:center;gap:8px;color:var(--ig-fg-cap);text-align:center;font-size:11px;border:1px dashed var(--ig-line);border-radius:8px;margin-bottom:8px;padding:8px}
|
|
123880
|
+
.dsh-ig-fav-prompts{display:flex;flex-direction:column;gap:4px}
|
|
123881
|
+
.dsh-ig-recent-item{position:relative;width:100%;aspect-ratio:1;align-self:start;padding:0;border:1px solid transparent;border-radius:8px;background:transparent;cursor:pointer;transition:border-color .16s,box-shadow .16s}.dsh-ig-recent-item:hover{border-color:var(--ig-blue-line);box-shadow:0 1px 4px rgba(30,42,76,.14)}.dsh-ig-recent-item.is-active{border-color:var(--ig-blue);box-shadow:0 0 0 2px rgba(47,100,245,.18)}.dsh-ig-recent-thumb{width:100%;height:100%;border-radius:7px;display:flex;align-items:center;justify-content:center;overflow:hidden;background:var(--ig-bg-thumb);color:var(--ig-fg-cap)}.dsh-ig-recent-thumb img{width:100%;height:100%;object-fit:cover}
|
|
123882
|
+
.dsh-ig-load-more{grid-column:1/-1;width:100%;height:32px;margin:4px 0 2px;display:flex;align-items:center;justify-content:center;border:1px dashed var(--ig-line);border-radius:7px;background:transparent;font-size:11px;color:var(--ig-fg-2);cursor:pointer;transition:background .15s,color .15s}.dsh-ig-load-more:hover{background:var(--ig-soft);color:var(--ig-blue);border-color:var(--ig-blue-line)}
|
|
123883
|
+
.dsh-ig-mini-btn{height:22px;padding:0 7px;display:inline-flex;align-items:center;gap:3px;border:1px solid var(--ig-line);border-radius:5px;background:var(--ig-bg);font-size:10.5px;font-weight:500;color:var(--ig-fg);cursor:pointer;transition:all .15s}.dsh-ig-mini-btn:hover{border-color:var(--ig-blue-line);color:var(--ig-blue);background:rgba(47,100,245,.06)}
|
|
123884
|
+
.dsh-ig-canvas-column{min-width:0;min-height:0;height:100%;overflow:hidden;display:flex;flex-direction:column;background:var(--dsw-alias-bg-layer-2,var(--ig-bg))}
|
|
121665
123885
|
.dsh-ig-canvas-toolbar{height:46px;flex:0 0 46px;display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:8px;padding:0 14px;border-bottom:1px solid var(--ig-line)}
|
|
121666
123886
|
.dsh-ig-canvas-toolbar-left,.dsh-ig-canvas-toolbar-right{display:flex;align-items:center;gap:6px;min-width:0}
|
|
121667
123887
|
.dsh-ig-canvas-toolbar-left{justify-self:start}
|
|
121668
123888
|
.dsh-ig-canvas-toolbar-right{justify-self:end}
|
|
121669
123889
|
.dsh-ig-canvas-toolbar-center{display:flex;align-items:center;justify-self:center;gap:6px;min-width:0}
|
|
121670
123890
|
.dsh-ig-toolbar-divider{width:1px;height:16px;background:var(--ig-line);flex-shrink:0;margin:0 2px}
|
|
121671
|
-
.dsh-ig-canvas-toolbar button{height:30px;min-width:30px;padding:0 9px;display:inline-flex;align-items:center;justify-content:center;gap:5px;border:1px solid var(--ig-line);border-radius:7px;background:var(--
|
|
121672
|
-
.dsh-ig-canvas-toolbar button:hover{border-color
|
|
121673
|
-
.dsh-ig-canvas-toolbar button.is-active{border-color
|
|
123891
|
+
.dsh-ig-canvas-toolbar button{height:30px;min-width:30px;padding:0 9px;display:inline-flex;align-items:center;justify-content:center;gap:5px;border:1px solid var(--ig-line);border-radius:7px;background:var(--ig-bg);color:var(--ig-fg);font-size:11.5px;font-weight:500;cursor:pointer;transition:border-color .15s,background .15s,color .15s}
|
|
123892
|
+
.dsh-ig-canvas-toolbar button:hover{border-color:var(--ig-blue-line);background:rgba(47,100,245,.05);color:var(--ig-blue)}
|
|
123893
|
+
.dsh-ig-canvas-toolbar button.is-active{border-color:var(--ig-blue-line);background:rgba(47,100,245,.08);color:var(--ig-blue);font-weight:550}
|
|
121674
123894
|
.dsh-ig-canvas-toolbar-center button.is-active{border-color:var(--ig-blue);background:rgba(47,100,245,.09);color:var(--ig-blue);font-weight:600;box-shadow:inset 0 0 0 1px rgba(47,100,245,.28)}
|
|
121675
|
-
.dsh-ig-zoom-display{font-size:11px;min-width:38px;text-align:center;color
|
|
121676
|
-
.dsh-ig-canvas-hint{flex:0 0 auto;display:flex;align-items:flex-start;gap:8px;padding:7px 12px;border-bottom:1px solid rgba(47,100,245,.14);background:rgba(47,100,245,.055);color
|
|
123895
|
+
.dsh-ig-zoom-display{font-size:11px;min-width:38px;text-align:center;color:var(--ig-fg-2);user-select:none;font-variant-numeric:tabular-nums}
|
|
123896
|
+
.dsh-ig-canvas-hint{flex:0 0 auto;display:flex;align-items:flex-start;gap:8px;padding:7px 12px;border-bottom:1px solid rgba(47,100,245,.14);background:rgba(47,100,245,.055);color:var(--ig-fg-2);font-size:11.5px;line-height:17px}.dsh-ig-canvas-hint>svg:first-child{flex-shrink:0;color:var(--ig-blue);margin-top:1px}.dsh-ig-canvas-hint>span{flex:1 1 0;min-width:0}.dsh-ig-canvas-hint>button{flex-shrink:0;width:22px;height:22px;display:inline-flex;align-items:center;justify-content:center;border:0;border-radius:5px;background:transparent;color:var(--ig-fg-cap);cursor:pointer;transition:background .15s,color .15s}.dsh-ig-canvas-hint>button:hover{background:rgba(47,100,245,.1);color:var(--ig-blue)}
|
|
121677
123897
|
.dsh-ig-status-badge-wrap{position:relative;display:inline-flex;align-items:center}
|
|
121678
|
-
.dsh-ig-status-badge{height:30px;display:inline-flex;align-items:center;gap:7px;padding:0 10px;border:1px solid var(--ig-line);border-radius:7px;background:var(--
|
|
121679
|
-
.dsh-ig-status-badge:hover{border-color
|
|
123898
|
+
.dsh-ig-status-badge{height:30px;display:inline-flex;align-items:center;gap:7px;padding:0 10px;border:1px solid var(--ig-line);border-radius:7px;background:var(--ig-bg);cursor:pointer;user-select:none;transition:border-color .15s,background .15s,box-shadow .15s}
|
|
123899
|
+
.dsh-ig-status-badge:hover{border-color:var(--ig-blue-line);background:rgba(47,100,245,.04)}
|
|
121680
123900
|
.dsh-ig-status-dot{width:7px;height:7px;min-width:7px;max-width:7px;border-radius:50%;flex-shrink:0;box-sizing:border-box}
|
|
121681
123901
|
.dsh-ig-status-dot.is-ready{background:#10b981;box-shadow:0 0 0 2px rgba(16,185,129,.2)}
|
|
121682
123902
|
.dsh-ig-status-dot.is-muted{background:#ef4444;box-shadow:0 0 0 2px rgba(239,68,68,.2)}
|
|
121683
|
-
.dsh-ig-status-text{font-size:11.5px;font-weight:500;color:var(--
|
|
121684
|
-
.dsh-ig-status-arrow{color
|
|
123903
|
+
.dsh-ig-status-text{font-size:11.5px;font-weight:500;color:var(--ig-fg);line-height:1}
|
|
123904
|
+
.dsh-ig-status-arrow{color:var(--ig-fg-cap);transition:transform .15s,color .15s}
|
|
121685
123905
|
.dsh-ig-status-badge-wrap:hover .dsh-ig-status-arrow{transform:rotate(180deg);color:var(--ig-blue)}
|
|
121686
|
-
.dsh-ig-status-popover{position:absolute;left:0;top:calc(100% + 6px);width:260px;background:var(--
|
|
123906
|
+
.dsh-ig-status-popover{position:absolute;left:0;top:calc(100% + 6px);width:260px;background:var(--ig-bg);border:1px solid var(--ig-line);border-radius:9px;box-shadow:0 12px 36px rgba(20,28,45,.14);padding:10px 12px;z-index:40;opacity:0;pointer-events:none;transform:translateY(4px);transition:opacity .15s cubic-bezier(.16,1,.3,1),transform .15s cubic-bezier(.16,1,.3,1)}
|
|
121687
123907
|
.dsh-ig-status-badge-wrap:hover .dsh-ig-status-popover{opacity:1;pointer-events:auto;transform:translateY(0)}
|
|
121688
|
-
.dsh-ig-status-popover-title{display:flex;align-items:center;justify-content:space-between;font-size:10px;font-weight:650;color
|
|
123908
|
+
.dsh-ig-status-popover-title{display:flex;align-items:center;justify-content:space-between;font-size:10px;font-weight:650;color:var(--ig-fg-cap);margin-bottom:8px;letter-spacing:.02em;text-transform:uppercase}
|
|
121689
123909
|
.dsh-ig-status-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:5px}
|
|
121690
123910
|
.dsh-ig-status-list li{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:6px 8px;border-radius:6px;transition:background .12s}
|
|
121691
123911
|
.dsh-ig-status-list li.is-configured{background:rgba(16,185,129,.05);border:1px solid rgba(16,185,129,.12)}
|
|
121692
123912
|
.dsh-ig-status-list li.is-missing{background:rgba(239,68,68,.04);border:1px solid rgba(239,68,68,.12);opacity:.75}
|
|
121693
123913
|
.dsh-ig-status-item-name{display:flex;flex-direction:column;min-width:0}
|
|
121694
|
-
.dsh-ig-status-item-name strong{font-size:11.5px;font-weight:600;color:var(--
|
|
121695
|
-
.dsh-ig-status-item-name small{font-size:9.5px;color
|
|
123914
|
+
.dsh-ig-status-item-name strong{font-size:11.5px;font-weight:600;color:var(--ig-fg);line-height:16px}
|
|
123915
|
+
.dsh-ig-status-item-name small{font-size:9.5px;color:var(--ig-fg-cap);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:145px;line-height:14px}
|
|
121696
123916
|
.dsh-ig-status-item-tag{font-size:10px;font-weight:600;padding:2px 6px;border-radius:4px;flex-shrink:0}
|
|
121697
123917
|
.is-configured .dsh-ig-status-item-tag{color:#059669;background:rgba(16,185,129,.14)}
|
|
121698
123918
|
.is-missing .dsh-ig-status-item-tag{color:#dc2626;background:rgba(239,68,68,.14)}
|
|
121699
123919
|
.dsh-ig-canvas{position:relative;flex:1 1 0;height:0;min-height:0;display:flex;align-items:center;justify-content:center;overflow:hidden;padding:24px;touch-action:none;user-select:none;cursor:grab;background-image:linear-gradient(45deg,rgba(114,128,156,.035) 25%,transparent 25%),linear-gradient(-45deg,rgba(114,128,156,.035) 25%,transparent 25%),linear-gradient(45deg,transparent 75%,rgba(114,128,156,.035) 75%),linear-gradient(-45deg,transparent 75%,rgba(114,128,156,.035) 75%);background-size:24px 24px;background-position:0 0,0 12px,12px -12px,-12px 0}
|
|
121700
123920
|
.dsh-ig-canvas.is-dragging,.dsh-ig-canvas.is-dragging *{cursor:grabbing!important}
|
|
121701
123921
|
.dsh-ig-canvas img{display:block;max-width:100%;max-height:100%;width:auto;height:auto;border-radius:10px;box-shadow:0 14px 45px rgba(25,35,63,.18);user-select:none;-webkit-user-drag:none;pointer-events:auto}
|
|
121702
|
-
.dsh-ig-canvas-empty,.dsh-ig-generating-state{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:12px;color
|
|
121703
|
-
.dsh-ig-generating-state strong{font-size:15px;color:var(--
|
|
121704
|
-
.dsh-ig-result-strip{flex:0 0 auto;min-height:52px;padding:8px 14px;display:flex;align-items:center;justify-content:space-between;gap:12px;border-top:1px solid var(--ig-line)}.dsh-ig-result-strip>span{font-size:12px;font-weight:650}.dsh-ig-result-strip>div,.dsh-ig-result-actions>div{display:flex;gap:7px}.dsh-ig-result-strip button,.dsh-ig-result-actions button{height:32px;display:inline-flex;align-items:center;gap:6px;padding:0 10px;border:1px solid var(--ig-line);border-radius:7px;background:var(--
|
|
121705
|
-
.dsh-ig-generate-panel{height:100%;display:flex;flex-direction:column;border-left:1px solid var(--ig-line);overflow:hidden}.dsh-ig-generator-form{flex:1 1 0;height:0;padding:15px;display:flex;flex-direction:column;gap:15px;overflow-x:hidden;overflow-y:auto;min-height:0}.dsh-ig-mode-switch{display:grid;grid-template-columns:1fr 1fr;gap:8px}.dsh-ig-mode-switch button{height:39px;border:1px solid var(--ig-line);border-radius:8px;background:var(--
|
|
121706
|
-
.dsh-ig-field{position:relative;display:flex;flex-direction:column;gap:7px}.dsh-ig-field>label,.dsh-ig-field-label label{font-size:11.5px;font-weight:630}.dsh-ig-field>label span{font-weight:400;color
|
|
121707
|
-
.dsh-ig-generation-kind{display:grid;grid-template-columns:1fr 1fr;gap:4px;padding:3px;border:1px solid var(--ig-line);border-radius:9px;background:var(--ig-soft)}.dsh-ig-generation-kind button{height:31px;border:0;border-radius:6px;background:transparent;color
|
|
121708
|
-
.dsh-ig-compare-box{padding:10px;border:1px solid rgba(47,100,245,.2);border-radius:10px;background:linear-gradient(145deg,rgba(47,100,245,.055),rgba(99,102,241,.018));display:flex;flex-direction:column;gap:9px}.dsh-ig-compare-heading{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}.dsh-ig-compare-heading>div{min-width:0;display:flex;flex-direction:column;gap:2px}.dsh-ig-compare-heading strong{font-size:11.5px}.dsh-ig-compare-heading small{font-size:9.5px;color
|
|
121709
|
-
.dsh-ig-upload{height:92px;border:1px dashed
|
|
123922
|
+
.dsh-ig-canvas-empty,.dsh-ig-generating-state{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:12px;color:var(--ig-fg-cap);font-size:12px;padding:26px;cursor:default}
|
|
123923
|
+
.dsh-ig-generating-state strong{font-size:15px;color:var(--ig-fg)}.dsh-ig-generating-state span{font-size:11px}.dsh-ig-generation-orbit{width:66px;height:66px;border-radius:50%;display:grid;place-items:center;color:var(--ig-blue);background:rgba(47,100,245,.09);box-shadow:0 0 0 10px rgba(47,100,245,.035);animation:dshIgPulse 1.8s ease-in-out infinite}
|
|
123924
|
+
.dsh-ig-result-strip{flex:0 0 auto;min-height:52px;padding:8px 14px;display:flex;align-items:center;justify-content:space-between;gap:12px;border-top:1px solid var(--ig-line)}.dsh-ig-result-strip>span{font-size:12px;font-weight:650}.dsh-ig-result-strip>div,.dsh-ig-result-actions>div{display:flex;gap:7px}.dsh-ig-result-strip button,.dsh-ig-result-actions button{height:32px;display:inline-flex;align-items:center;gap:6px;padding:0 10px;border:1px solid var(--ig-line);border-radius:7px;background:var(--ig-bg);font-size:11px;cursor:pointer}.dsh-ig-result-strip button:hover,.dsh-ig-result-actions button:hover{border-color:var(--ig-blue-line);color:var(--ig-blue)}.dsh-ig-result-actions{flex:0 0 auto;min-height:54px;padding:8px 14px;display:flex;align-items:center;justify-content:space-between;gap:12px;border-top:1px solid var(--ig-line)}.dsh-ig-result-actions p{margin:0;min-width:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;font-size:11.5px;line-height:18px;color:var(--ig-fg-2)}.dsh-ig-result-meta{flex:0 0 auto;min-height:32px;padding:6px 14px;display:flex;gap:13px;align-items:center;flex-wrap:wrap;border-top:1px solid var(--ig-line);font-size:10px;color:var(--ig-fg-cap)}.dsh-ig-result-meta span+span:before{content:'·';margin-right:13px}
|
|
123925
|
+
.dsh-ig-generate-panel{height:100%;display:flex;flex-direction:column;border-left:1px solid var(--ig-line);overflow:hidden}.dsh-ig-generator-form{flex:1 1 0;height:0;padding:15px;display:flex;flex-direction:column;gap:15px;overflow-x:hidden;overflow-y:auto;min-height:0}.dsh-ig-mode-switch{display:grid;grid-template-columns:1fr 1fr;gap:8px}.dsh-ig-mode-switch button{height:39px;border:1px solid var(--ig-line);border-radius:8px;background:var(--ig-bg);display:flex;align-items:center;justify-content:center;gap:7px;font-size:12px;cursor:pointer}.dsh-ig-mode-switch button.is-active{border-color:var(--ig-blue-line);color:var(--ig-blue);background:rgba(47,100,245,.065);box-shadow:inset 0 0 0 1px rgba(47,100,245,.1)}
|
|
123926
|
+
.dsh-ig-field{position:relative;display:flex;flex-direction:column;gap:7px}.dsh-ig-field>label,.dsh-ig-field-label label{font-size:11.5px;font-weight:630}.dsh-ig-field>label span{font-weight:400;color:var(--ig-fg-cap)}.dsh-ig-field-label{display:flex;align-items:center;justify-content:space-between}.dsh-ig-field-label b{color:#e14d4d}.dsh-ig-field-label button{border:0;background:transparent;color:var(--ig-fg-3);font-size:10.5px;cursor:pointer}.dsh-ig-field textarea{width:100%;height:112px;padding:11px 12px 22px;resize:vertical;border:1px solid var(--ig-line);border-radius:9px;background:var(--ig-bg);font-size:12px;line-height:19px;outline:none}.dsh-ig-field textarea:focus{border-color:var(--ig-blue);box-shadow:0 0 0 3px rgba(47,100,245,.09)}.dsh-ig-field>small{position:absolute;right:9px;bottom:7px;color:var(--ig-fg-cap);font-size:9.5px}.dsh-ig-field-grid{display:grid;grid-template-columns:1fr 1fr;gap:9px}.dsh-ig-field-select{display:flex;flex-direction:column;gap:6px;min-width:0}.dsh-ig-field-select>span{font-size:11px;font-weight:620}.dsh-ig-field-select select{width:100%;height:36px;padding:0 26px 0 9px;border:1px solid var(--ig-line);border-radius:8px;background:var(--ig-bg);font-size:11px;outline:none;text-overflow:ellipsis}.dsh-ig-field-select select:focus{border-color:var(--ig-blue)}.dsh-ig-count-row{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}.dsh-ig-count-pill{height:34px;border:1px solid var(--ig-line);border-radius:7px;background:var(--ig-bg);font-size:12px;font-weight:600;color:var(--ig-fg-2);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .15s}.dsh-ig-count-pill:hover{border-color:var(--ig-blue-line);color:var(--ig-blue)}.dsh-ig-count-pill.is-active{border-color:var(--ig-blue);background:rgba(47,100,245,.08);color:var(--ig-blue);box-shadow:inset 0 0 0 1px var(--ig-blue)}
|
|
123927
|
+
.dsh-ig-generation-kind{display:grid;grid-template-columns:1fr 1fr;gap:4px;padding:3px;border:1px solid var(--ig-line);border-radius:9px;background:var(--ig-soft)}.dsh-ig-generation-kind button{height:31px;border:0;border-radius:6px;background:transparent;color:var(--ig-fg-3);font-size:11.5px;display:flex;align-items:center;justify-content:center;gap:6px;cursor:pointer;transition:background .15s,color .15s,box-shadow .15s}.dsh-ig-generation-kind button.is-active{background:var(--ig-bg);color:var(--ig-blue);font-weight:650;box-shadow:0 2px 8px rgba(30,42,76,.09)}
|
|
123928
|
+
.dsh-ig-compare-box{padding:10px;border:1px solid rgba(47,100,245,.2);border-radius:10px;background:linear-gradient(145deg,rgba(47,100,245,.055),rgba(99,102,241,.018));display:flex;flex-direction:column;gap:9px}.dsh-ig-compare-heading{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}.dsh-ig-compare-heading>div{min-width:0;display:flex;flex-direction:column;gap:2px}.dsh-ig-compare-heading strong{font-size:11.5px}.dsh-ig-compare-heading small{font-size:9.5px;color:var(--ig-fg-cap)}.dsh-ig-compare-heading>span{flex:none;padding:2px 6px;border-radius:999px;background:rgba(47,100,245,.11);color:var(--ig-blue);font-size:9.5px;font-weight:650}.dsh-ig-model-checks{display:flex;flex-direction:column;gap:6px}.dsh-ig-model-checks>button{min-height:43px;width:100%;padding:6px 7px;display:grid;grid-template-columns:18px minmax(0,1fr) auto;align-items:center;gap:7px;border:1px solid var(--ig-line);border-radius:8px;background:var(--ig-bg);text-align:left;cursor:pointer;transition:border-color .15s,background .15s,transform .15s}.dsh-ig-model-checks>button:hover{border-color:var(--ig-blue-line);transform:translateY(-1px)}.dsh-ig-model-checks>button.is-selected{border-color:var(--ig-blue-line);background:rgba(47,100,245,.055);box-shadow:inset 3px 0 0 var(--ig-blue)}.dsh-ig-model-checkmark{width:17px;height:17px;border:1px solid var(--ig-line);border-radius:5px;display:grid;place-items:center;color:#fff;background:var(--ig-bg)}.dsh-ig-model-checks>button.is-selected .dsh-ig-model-checkmark{border-color:var(--ig-blue);background:var(--ig-blue)}.dsh-ig-model-copy{display:flex;flex-direction:column;min-width:0}.dsh-ig-model-copy strong{font-size:11px;line-height:15px}.dsh-ig-model-copy small{max-width:130px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ig-fg-cap);font-size:9.5px;line-height:14px}.dsh-ig-model-settings{display:flex;flex-direction:column;align-items:flex-end;gap:2px;color:var(--ig-fg-2);font-size:9.5px;white-space:nowrap}.dsh-ig-model-settings em{font-style:normal;color:var(--ig-warn);font-size:8.5px}.dsh-ig-compare-box>p{margin:0;color:var(--ig-fg-3);font-size:9.5px;line-height:14px}
|
|
123929
|
+
.dsh-ig-upload{height:92px;border:1px dashed var(--ig-line);border-radius:9px;background:color-mix(in srgb,var(--ig-bg) 55%,transparent);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;color:var(--ig-fg-3);cursor:pointer}.dsh-ig-upload strong{font-size:11px;font-weight:570}.dsh-ig-upload small{font-size:9.5px}.dsh-ig-upload:hover,.dsh-ig-upload.is-dragging{border-color:var(--ig-blue);background:rgba(47,100,245,.05);color:var(--ig-blue)}
|
|
121710
123930
|
.dsh-ig-reference-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(64px,1fr));gap:8px}
|
|
121711
|
-
.dsh-ig-reference-card{position:relative;aspect-ratio:1;border-radius:8px;overflow:hidden;background
|
|
123931
|
+
.dsh-ig-reference-card{position:relative;aspect-ratio:1;border-radius:8px;overflow:hidden;background:var(--ig-bg-thumb);border:1px solid var(--ig-line)}
|
|
121712
123932
|
.dsh-ig-reference-card img{width:100%;height:100%;object-fit:cover}
|
|
121713
123933
|
.dsh-ig-reference-card button{position:absolute;right:4px;top:4px;width:18px;height:18px;border:0;border-radius:50%;display:grid;place-items:center;background:rgba(20,28,45,.75);color:#fff;cursor:pointer;padding:0;transition:background .15s}
|
|
121714
123934
|
.dsh-ig-reference-card button:hover{background:#ef4444}
|
|
121715
|
-
.dsh-ig-reference-add{aspect-ratio:1;border:1px dashed
|
|
123935
|
+
.dsh-ig-reference-add{aspect-ratio:1;border:1px dashed var(--ig-line);border-radius:8px;background:color-mix(in srgb,var(--ig-bg) 55%,transparent);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;color:var(--ig-fg-3);cursor:pointer;font-size:10px;transition:border-color .15s,color .15s,background .15s}
|
|
121716
123936
|
.dsh-ig-reference-add:hover{border-color:var(--ig-blue);background:rgba(47,100,245,.05);color:var(--ig-blue)}
|
|
121717
|
-
.dsh-ig-reference-preview{position:relative;height:108px;border-radius:9px;overflow:hidden;background
|
|
121718
|
-
.dsh-ig-inline-note,.dsh-ig-form-error{padding:9px 10px;border-radius:7px;font-size:10.5px;line-height:16px}.dsh-ig-inline-note{background
|
|
121719
|
-
.dsh-ig-config-error{padding:14px;display:flex;flex-direction:column;align-items:center;gap:10px;background
|
|
123937
|
+
.dsh-ig-reference-preview{position:relative;height:108px;border-radius:9px;overflow:hidden;background:var(--ig-bg-thumb)}.dsh-ig-reference-preview img{width:100%;height:100%;object-fit:contain}.dsh-ig-reference-preview button{position:absolute;right:7px;top:7px;width:25px;height:25px;border:0;border-radius:50%;display:grid;place-items:center;background:rgba(20,28,45,.72);color:#fff;cursor:pointer}
|
|
123938
|
+
.dsh-ig-inline-note,.dsh-ig-form-error{padding:9px 10px;border-radius:7px;font-size:10.5px;line-height:16px}.dsh-ig-inline-note{background:rgba(245,158,11,.1);color:var(--ig-warn);border:1px solid rgba(245,158,11,.35)}.dsh-ig-form-error{background:rgba(239,68,68,.08);color:var(--ig-danger);border:1px solid rgba(239,68,68,.3)}.dsh-ig-form-loading{height:70px;display:grid;place-items:center;color:var(--ig-blue)}
|
|
123939
|
+
.dsh-ig-config-error{padding:14px;display:flex;flex-direction:column;align-items:center;gap:10px;background:rgba(239,68,68,.07);border:1px solid rgba(239,68,68,.3);border-radius:8px;color:var(--ig-danger);font-size:11.5px;text-align:center}.dsh-ig-config-error p{margin:0;line-height:17px}.dsh-ig-config-error button{height:30px;display:inline-flex;align-items:center;gap:6px;padding:0 12px;border:1px solid rgba(239,68,68,.35);border-radius:6px;background:var(--ig-bg);color:var(--ig-danger);font-size:11.5px;font-weight:600;cursor:pointer}.dsh-ig-config-error button:hover{background:rgba(239,68,68,.12)}
|
|
121720
123940
|
.dsh-ig-generate-button{height:42px;flex:0 0 auto;border:0;border-radius:8px;background:linear-gradient(135deg,#386cf6,#2758e7);color:#fff!important;display:flex;align-items:center;justify-content:center;gap:8px;font-size:12px;font-weight:650;cursor:pointer;box-shadow:0 8px 18px rgba(47,100,245,.22);transition:transform .16s,box-shadow .16s}.dsh-ig-generate-button:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 10px 24px rgba(47,100,245,.28)}.dsh-ig-generate-button:disabled{opacity:.55;cursor:not-allowed;box-shadow:none}
|
|
121721
123941
|
.dsh-ig-generate-button.is-cancel{background:linear-gradient(135deg,#ef4444,#dc2626);box-shadow:0 8px 18px rgba(239,68,68,.25)}.dsh-ig-generate-button.is-cancel:hover{background:linear-gradient(135deg,#dc2626,#b91c1c);box-shadow:0 10px 24px rgba(239,68,68,.35)}
|
|
121722
|
-
.dsh-ig-details{padding:16px;margin:0;overflow:auto}.dsh-ig-details>div{padding:12px 0;border-bottom:1px solid var(--ig-line)}.dsh-ig-details dt{font-size:10.5px;color
|
|
123942
|
+
.dsh-ig-details{padding:16px;margin:0;overflow:auto}.dsh-ig-details>div{padding:12px 0;border-bottom:1px solid var(--ig-line)}.dsh-ig-details dt{font-size:10.5px;color:var(--ig-fg-cap);margin-bottom:5px}.dsh-ig-details dd{margin:0;font-size:11.5px;line-height:18px;word-break:break-word}.dsh-ig-details-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;height:220px;padding:20px;color:var(--ig-fg-cap);font-size:11px;text-align:center}
|
|
121723
123943
|
.dsh-ig-workbench-modal-backdrop{position:fixed;inset:0;background:rgba(15,23,42,.45);backdrop-filter:blur(3px);z-index:999;display:grid;place-items:center;padding:16px}
|
|
121724
|
-
.dsh-ig-workbench-modal-box{width:100%;max-width:380px;background:var(--
|
|
123944
|
+
.dsh-ig-workbench-modal-box{width:100%;max-width:380px;background:var(--ig-bg);border-radius:12px;padding:20px;box-shadow:0 20px 48px rgba(0,0,0,.22);display:flex;flex-direction:column;gap:14px}
|
|
121725
123945
|
.dsh-ig-workbench-modal-header{display:flex;align-items:center;gap:10px}
|
|
121726
123946
|
.dsh-ig-workbench-modal-header strong{font-size:14px;font-weight:650;color:#b91c1c}
|
|
121727
|
-
.dsh-ig-workbench-modal-desc{font-size:12px;line-height:18px;color
|
|
121728
|
-
.dsh-ig-workbench-modal-option{display:flex;align-items:center;gap:8px;font-size:11.5px;color
|
|
123947
|
+
.dsh-ig-workbench-modal-desc{font-size:12px;line-height:18px;color:var(--ig-fg-2);margin:0}
|
|
123948
|
+
.dsh-ig-workbench-modal-option{display:flex;align-items:center;gap:8px;font-size:11.5px;color:var(--ig-fg-2);cursor:pointer}
|
|
121729
123949
|
.dsh-ig-workbench-modal-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:4px}
|
|
121730
123950
|
.dsh-ig-workbench-modal-actions button{height:32px;padding:0 14px;border-radius:7px;font-size:11.5px;font-weight:600;cursor:pointer}
|
|
121731
|
-
.dsh-ig-workbench-modal-cancel{border:1px solid var(--ig-line);background:var(--
|
|
121732
|
-
.dsh-ig-workbench-modal-cancel:hover{background
|
|
123951
|
+
.dsh-ig-workbench-modal-cancel{border:1px solid var(--ig-line);background:var(--ig-bg);color:var(--ig-fg-2)}
|
|
123952
|
+
.dsh-ig-workbench-modal-cancel:hover{background:var(--ig-soft)}
|
|
121733
123953
|
.dsh-ig-workbench-modal-danger{border:0;background:#dc2626;color:#fff}
|
|
121734
123954
|
.dsh-ig-workbench-modal-danger:hover{background:#b91c1c}
|
|
121735
123955
|
@keyframes dshIgPulse{50%{transform:scale(1.06);box-shadow:0 0 0 16px rgba(47,100,245,.025)}}
|
|
121736
123956
|
.dsh-ig-workbench-toast{position:fixed;bottom:28px;left:50%;transform:translateX(-50%);background:rgba(15,23,42,0.88);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);color:#fff;padding:8px 18px;border-radius:10px;font-size:12.5px;font-weight:500;box-shadow:0 12px 32px rgba(0,0,0,0.3);z-index:99999;animation:dshIgFade .15s ease-out;pointer-events:none}
|
|
121737
123957
|
@keyframes dshIgFade{from{opacity:0;transform:translate(-50%,6px)}to{opacity:1;transform:translate(-50%,0)}}
|
|
121738
123958
|
@media(max-width:1120px){.dsh-ig-workbench-grid{grid-template-columns:190px minmax(360px,1fr) 300px}.dsh-ig-result-actions button,.dsh-ig-result-strip button{padding:0 7px;font-size:10px;gap:4px}.dsh-ig-result-actions>div,.dsh-ig-result-strip>div{gap:5px}}
|
|
121739
|
-
@media(max-width:900px){.dsh-ig-gallery-page-body.is-workbench{height:auto;overflow:auto}.dsh-ig-workbench{height:auto;min-height:100%;overflow:visible;padding:12px}.dsh-ig-workbench-heading{height:auto;padding-bottom:12px;align-items:center}.dsh-ig-provider-quick>span{display:none}.dsh-ig-workbench-grid{height:auto;display:flex;flex:none;flex-direction:column;overflow:visible}.dsh-ig-recent-panel{height:auto;overflow:hidden;border-right:0;border-bottom:1px solid var(--ig-line)}.dsh-ig-recent-scroll{height:auto;display:flex;overflow-x:auto;overflow-y:hidden;padding:8px}.dsh-ig-recent-item{min-width:220px}.dsh-ig-canvas-column{height:auto;min-height:560px}.dsh-ig-generate-panel{height:auto;border-left:0;border-top:1px solid var(--ig-line);min-height:560px}.dsh-ig-generator-form{height:auto;overflow:visible}.dsh-ig-canvas{height:auto;min-height:360px}}
|
|
123959
|
+
@media(max-width:900px){.dsh-ig-gallery-page-body.is-workbench{height:auto;overflow:auto}.dsh-ig-workbench{height:auto;min-height:100%;overflow:visible;padding:12px}.dsh-ig-workbench-heading{height:auto;padding-bottom:12px;align-items:center}.dsh-ig-provider-quick>span{display:none}.dsh-ig-workbench-grid{height:auto;display:flex;flex:none;flex-direction:column;overflow:visible}.dsh-ig-recent-panel{height:auto;overflow:hidden;border-right:0;border-bottom:1px solid var(--ig-line)}.dsh-ig-recent-scroll{height:auto;display:flex;overflow-x:auto;overflow-y:hidden;padding:8px}.dsh-ig-fav-scroll{height:auto;flex:none;overflow:visible}.dsh-ig-recent-item{min-width:220px}.dsh-ig-canvas-column{height:auto;min-height:560px}.dsh-ig-generate-panel{height:auto;border-left:0;border-top:1px solid var(--ig-line);min-height:560px}.dsh-ig-generator-form{height:auto;overflow:visible}.dsh-ig-canvas{height:auto;min-height:360px}}
|
|
121740
123960
|
@media(max-width:560px){.dsh-ig-workbench-heading>div{display:block}.dsh-ig-workbench-heading h1{font-size:15px}.dsh-ig-provider-quick select{min-width:128px;max-width:150px}.dsh-ig-canvas{padding:12px;min-height:300px}.dsh-ig-result-strip,.dsh-ig-result-actions{align-items:flex-start;flex-direction:column}.dsh-ig-result-strip>div,.dsh-ig-result-actions>div{width:100%}.dsh-ig-result-strip button,.dsh-ig-result-actions button{flex:1;justify-content:center}.dsh-ig-result-actions button span{display:inline}.dsh-ig-field-grid{grid-template-columns:1fr}.dsh-ig-result-meta span+span:before{display:none}}
|
|
121741
123961
|
@media(prefers-reduced-motion:reduce){.dsh-ig-workbench *{scroll-behavior:auto!important;animation-duration:.01ms!important;transition-duration:.01ms!important}}
|
|
121742
|
-
.dsh-ig-field-label>span{display:flex;align-items:center;gap:5px}.dsh-ig-field-label .dsh-ig-find-inspiration{display:inline-flex;align-items:center;gap:3px;color:var(--ig-blue);font-weight:600}.dsh-ig-field-label .dsh-ig-find-inspiration:hover{color
|
|
121743
|
-
.dsh-ig-workspace-filter-label{height:30px;display:inline-flex;align-items:center;gap:6px;padding:0 10px;border:1px solid var(--ig-line,rgba(0,0,0,.1));border-radius:7px;background:var(--
|
|
121744
|
-
.dsh-ig-workspace-filter-label:hover{border-color
|
|
123962
|
+
.dsh-ig-field-label>span{display:flex;align-items:center;gap:5px}.dsh-ig-field-label .dsh-ig-find-inspiration{display:inline-flex;align-items:center;gap:3px;color:var(--ig-blue);font-weight:600}.dsh-ig-field-label .dsh-ig-find-inspiration:hover{color:color-mix(in srgb,var(--ig-blue) 78%,#fff)}
|
|
123963
|
+
.dsh-ig-workspace-filter-label{height:30px;display:inline-flex;align-items:center;gap:6px;padding:0 10px;border:1px solid var(--ig-line,rgba(0,0,0,.1));border-radius:7px;background:var(--ig-bg);font-size:11.5px;color:var(--ig-fg);cursor:pointer;user-select:none;transition:border-color .15s,background .15s}
|
|
123964
|
+
.dsh-ig-workspace-filter-label:hover{border-color:var(--ig-blue-line);background:rgba(47,100,245,.04)}
|
|
121745
123965
|
.dsh-ig-workspace-checkbox{cursor:pointer;accent-color:#2f64f5;width:13.5px;height:13.5px;margin:0}
|
|
121746
123966
|
.dsh-ig-workspace-filter-text{font-weight:500;white-space:nowrap}
|
|
121747
|
-
.dsh-ig-workspace-filter-badge{font-size:10px;font-weight:600;padding:1px 6px;border-radius:999px;background:color-mix(in srgb,currentColor 7%,transparent);color
|
|
123967
|
+
.dsh-ig-workspace-filter-badge{font-size:10px;font-weight:600;padding:1px 6px;border-radius:999px;background:color-mix(in srgb,currentColor 7%,transparent);color:var(--ig-fg-2);font-variant-numeric:tabular-nums}
|
|
121748
123968
|
.dsh-ig-canvas-cluster{display:grid;gap:16px;align-items:center;justify-content:center;user-select:none;pointer-events:auto;flex-shrink:0}
|
|
121749
123969
|
.dsh-ig-canvas-cluster[data-count="2"]{grid-template-columns:repeat(2,1fr);max-width:880px}
|
|
121750
123970
|
.dsh-ig-canvas-cluster[data-count="3"],.dsh-ig-canvas-cluster[data-count="4"]{grid-template-columns:repeat(2,1fr);max-width:760px}
|
|
@@ -121757,19 +123977,19 @@ img.ProseMirror-separator {
|
|
|
121757
123977
|
.dsh-ig-canvas-badge.is-model{max-width:calc(100% - 20px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600}
|
|
121758
123978
|
.dsh-ig-canvas-item.is-checked .dsh-ig-canvas-badge{background:var(--ig-blue)}
|
|
121759
123979
|
.dsh-ig-canvas-check{position:absolute;top:10px;right:10px;width:22px;height:22px;border:1.5px solid rgba(255,255,255,.85);border-radius:50%;display:grid;place-items:center;background:rgba(15,23,42,.48);color:#fff;box-shadow:0 2px 8px rgba(15,23,42,.18);backdrop-filter:blur(4px);z-index:2;pointer-events:none}.dsh-ig-canvas-item.is-checked .dsh-ig-canvas-check{border-color:#fff;background:var(--ig-blue)}
|
|
121760
|
-
.dsh-ig-canvas-item-loading{width:260px;height:260px;display:flex;align-items:center;justify-content:center;background:
|
|
123980
|
+
.dsh-ig-canvas-item-loading{width:260px;height:260px;display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--ig-bg) 55%,transparent);border:1px solid var(--ig-line);border-radius:10px;color:var(--ig-fg-cap)}
|
|
121761
123981
|
.dsh-ig-lightbox-nav{position:absolute;top:50%;transform:translateY(-50%);width:42px;height:42px;border-radius:50%;border:0;background:rgba(15,23,42,.65);color:#fff;display:grid;place-items:center;cursor:pointer;transition:background .15s,transform .15s;z-index:10;backdrop-filter:blur(4px)}
|
|
121762
123982
|
.dsh-ig-lightbox-nav:hover{background:rgba(47,100,245,.85);transform:translateY(-50%) scale(1.08)}
|
|
121763
123983
|
.dsh-ig-lightbox-nav.is-prev{left:18px}
|
|
121764
123984
|
.dsh-ig-lightbox-nav.is-next{right:18px}
|
|
121765
123985
|
.dsh-ig-save-gallery-btn{color:var(--ig-blue)!important;border-color:rgba(47,100,245,.35)!important;background:rgba(47,100,245,.06)!important}
|
|
121766
123986
|
.dsh-ig-save-gallery-btn:hover{background:rgba(47,100,245,.12)!important}
|
|
121767
|
-
.dsh-ig-save-gallery-btn.is-saved{color
|
|
123987
|
+
.dsh-ig-save-gallery-btn.is-saved{color:var(--ig-fg-2)!important;border-color:var(--ig-line)!important;background:transparent!important}
|
|
121768
123988
|
|
|
121769
123989
|
/* tldraw infinite canvas surface (P0 spike) */
|
|
121770
123990
|
.dsh-ig-tl-canvas{position:relative;flex:1 1 0;height:0;min-height:0;overflow:hidden;isolation:isolate}
|
|
121771
|
-
.dsh-ig-canvas-sync-status{position:absolute;z-index:500;bottom:48px;left:60px;right:16px;display:flex;align-items:center;justify-content:center;gap:8px;max-width:560px;margin:auto;padding:7px 12px;border:1px solid var(--
|
|
121772
|
-
.dsh-ig-canvas-sync-status[data-phase='error']{color
|
|
123991
|
+
.dsh-ig-canvas-sync-status{position:absolute;z-index:500;bottom:48px;left:60px;right:16px;display:flex;align-items:center;justify-content:center;gap:8px;max-width:560px;margin:auto;padding:7px 12px;border:1px solid var(--ig-line);border-radius:10px;background:var(--ig-bg);color:var(--ig-fg-2);box-shadow:0 2px 8px #0001;font-size:12px;pointer-events:none}
|
|
123992
|
+
.dsh-ig-canvas-sync-status[data-phase='error']{color:var(--ig-danger);border-color:rgba(239,68,68,.4)}
|
|
121773
123993
|
.dsh-ig-canvas-sync-status button{pointer-events:auto;flex-shrink:0;border:1px solid currentColor;border-radius:6px;padding:3px 9px;background:transparent;color:inherit;cursor:pointer}
|
|
121774
123994
|
|
|
121775
123995
|
/* ---- Right-sidebar seat variant (DSH 0.1.5 'sidebar.right.pane.tab') ----
|
|
@@ -121962,6 +124182,10 @@ img.ProseMirror-separator {
|
|
|
121962
124182
|
.dsh-ig-inspiration-head{display:flex;align-items:flex-start;justify-content:space-between;gap:18px;margin-bottom:18px}.dsh-ig-inspiration-head-actions{display:flex;align-items:center;gap:8px}.dsh-ig-inspiration-kicker{margin:0 0 4px;color:var(--inspiration-blue);font-size:11px;letter-spacing:.08em;font-weight:700;text-transform:uppercase}.dsh-ig-inspiration-head h1{margin:0;font-size:18px;letter-spacing:-.025em;line-height:1.25}.dsh-ig-inspiration-subtitle{margin:5px 0 0;color:var(--inspiration-muted);font-size:12px;line-height:1.5}.dsh-ig-inspiration-refresh,.dsh-ig-inspiration-clear-cache{height:32px;padding:0 11px;display:inline-flex;align-items:center;gap:6px;border:1px solid var(--inspiration-line);border-radius:7px;background:var(--dsw-alias-bg-layer-1,#fff);color:var(--inspiration-muted);font:inherit;font-size:12px;white-space:nowrap;cursor:pointer;transition:all .15s ease}.dsh-ig-inspiration-refresh:hover:not(:disabled){border-color:rgba(47,100,245,.42);color:var(--inspiration-blue);background:rgba(47,100,245,.04)}.dsh-ig-inspiration-clear-cache:hover:not(:disabled){border-color:rgba(239,68,68,.4);color:#ef4444;background:rgba(239,68,68,.04)}.dsh-ig-inspiration-refresh:disabled,.dsh-ig-inspiration-clear-cache:disabled{opacity:.55;cursor:wait}
|
|
121963
124183
|
.dsh-ig-inspiration-toolbar{display:grid;grid-template-columns:minmax(180px,1fr) auto repeat(3,minmax(110px,140px));gap:8px;padding:10px;border:1px solid var(--inspiration-line);border-radius:10px;background:color-mix(in srgb,var(--dsw-alias-bg-layer-1,#fff) 90%,#edf2ff);margin-bottom:16px}.dsh-ig-inspiration-search{min-width:0;position:relative}.dsh-ig-inspiration-search svg{position:absolute;left:10px;top:50%;transform:translateY(-50%);color:#8995aa}.dsh-ig-inspiration-toolbar input,.dsh-ig-inspiration-toolbar select{width:100%;height:34px;box-sizing:border-box;border:1px solid transparent;border-radius:6px;background:var(--dsw-alias-bg-layer-1,#fff);color:inherit;padding:0 9px;font:inherit;font-size:12px;outline:none}.dsh-ig-inspiration-toolbar input{padding-left:31px}.dsh-ig-inspiration-toolbar input:focus,.dsh-ig-inspiration-toolbar select:focus{border-color:var(--inspiration-blue);box-shadow:0 0 0 3px rgba(47,100,245,.1)}
|
|
121964
124184
|
.dsh-ig-inspiration-fav-filter{height:34px;padding:0 12px;display:inline-flex;align-items:center;gap:6px;border:1px solid var(--inspiration-line);border-radius:6px;background:var(--dsw-alias-bg-layer-1,#fff);color:var(--inspiration-muted);font:inherit;font-size:12px;cursor:pointer;white-space:nowrap;transition:all .15s ease}.dsh-ig-inspiration-fav-filter:hover{border-color:rgba(47,100,245,.4);color:var(--inspiration-blue)}.dsh-ig-inspiration-fav-filter.is-active{background:#eef3ff;border-color:var(--inspiration-blue);color:var(--inspiration-blue);font-weight:600}.fill-star{fill:currentColor}
|
|
124185
|
+
.dsh-ig-inspiration-catnav{position:sticky;top:0;z-index:6;display:flex;flex-wrap:wrap;gap:6px;margin:0 0 14px;padding:8px;border:1px solid var(--inspiration-line);border-radius:10px;background:color-mix(in srgb,var(--dsw-alias-bg-layer-1,#fff) 92%,#edf2ff);backdrop-filter:blur(8px)}
|
|
124186
|
+
.dsh-ig-inspiration-catnav-chip{height:26px;padding:0 11px;display:inline-flex;align-items:center;gap:6px;border:1px solid var(--inspiration-line);border-radius:999px;background:var(--dsw-alias-bg-layer-1,#fff);color:var(--inspiration-muted);font:inherit;font-size:11px;font-weight:600;cursor:pointer;white-space:nowrap;transition:all .15s ease}.dsh-ig-inspiration-catnav-chip em{font-style:normal;font-size:10px;opacity:.75}.dsh-ig-inspiration-catnav-chip:hover:not(:disabled){border-color:rgba(47,100,245,.46);color:var(--inspiration-blue)}.dsh-ig-inspiration-catnav-chip.is-active{border-color:var(--inspiration-blue);background:#eef3ff;color:var(--inspiration-blue)}.dsh-ig-inspiration-catnav-chip:disabled{opacity:.4;cursor:default}
|
|
124187
|
+
.dsh-ig-inspiration-group{margin:0}
|
|
124188
|
+
.dsh-ig-inspiration-group-head{position:sticky;top:48px;z-index:5;display:flex;align-items:center;gap:8px;margin:6px 0 10px;padding:7px 2px;font-size:12px;font-weight:700;letter-spacing:.02em;color:var(--inspiration-ink);background:color-mix(in srgb,var(--dsw-alias-bg-layer-1,#fff) 86%,transparent);backdrop-filter:blur(6px);scroll-margin-top:48px}.dsh-ig-inspiration-group-head em{font-style:normal;font-weight:600;font-size:10.5px;color:var(--inspiration-muted)}
|
|
121965
124189
|
.dsh-ig-inspiration-layout{display:grid;grid-template-columns:minmax(0,1fr) minmax(260px,310px);gap:18px;align-items:start}.dsh-ig-inspiration-summary{height:24px;display:flex;align-items:center;justify-content:space-between;color:var(--inspiration-muted);font-size:11.5px}.dsh-ig-inspiration-summary strong{color:inherit;font-weight:650}.dsh-ig-inspiration-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(185px,1fr));gap:12px}.dsh-ig-inspiration-card{position:relative;min-width:0;padding:0;border:1px solid var(--inspiration-line);border-radius:10px;overflow:hidden;background:var(--dsw-alias-bg-layer-1,#fff);text-align:left;cursor:pointer;transition:transform .16s ease,border-color .16s ease,box-shadow .16s ease;content-visibility:auto;contain-intrinsic-size:245px}.dsh-ig-inspiration-card:hover,.dsh-ig-inspiration-card.is-selected{border-color:rgba(47,100,245,.58);box-shadow:0 8px 22px rgba(37,62,123,.11)}.dsh-ig-inspiration-card:hover{transform:translateY(-2px)}.dsh-ig-inspiration-card.is-selected:after{content:'';position:absolute;inset:0;border:2px solid var(--inspiration-blue);border-radius:9px;pointer-events:none}.dsh-ig-inspiration-visual{aspect-ratio:1/1;position:relative;background:linear-gradient(135deg,#f0f4fc,#e3eafa);overflow:hidden}.dsh-ig-inspiration-visual img{width:100%;height:100%;object-fit:cover;display:block}.dsh-ig-inspiration-image-placeholder{height:100%;display:grid;place-items:center;color:#8a99b3}.dsh-ig-inspiration-image-placeholder.is-error{font-size:11px;padding:10px;text-align:center}.dsh-ig-inspiration-card-copy{padding:9px 10px 10px}.dsh-ig-inspiration-card-copy strong{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:17px}.dsh-ig-inspiration-card-copy span{display:block;margin-top:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--inspiration-muted);font-size:10.5px}.dsh-ig-inspiration-featured{position:absolute;top:8px;left:8px;display:inline-flex;align-items:center;gap:3px;padding:3px 6px;border-radius:999px;background:rgba(20,31,52,.72);backdrop-filter:blur(5px);color:#fff;font-size:10px;font-weight:600;z-index:1}.dsh-ig-inspiration-card-star{position:absolute;top:8px;right:8px;width:26px;height:26px;border-radius:50%;background:rgba(20,31,52,.6);backdrop-filter:blur(4px);border:none;color:#fff;display:grid;place-items:center;cursor:pointer;z-index:2;opacity:0;transition:opacity .15s,transform .15s}.dsh-ig-inspiration-card:hover .dsh-ig-inspiration-card-star,.dsh-ig-inspiration-card-star.is-favorited{opacity:1}.dsh-ig-inspiration-card-star.is-favorited{color:#f59e0b;background:rgba(20,31,52,.85)}.dsh-ig-inspiration-card-star:hover{transform:scale(1.15)}
|
|
121966
124190
|
.dsh-ig-inspiration-empty{min-height:310px;display:grid;place-items:center;padding:30px;text-align:center;color:var(--inspiration-muted);border:1px dashed var(--inspiration-line);border-radius:10px;font-size:12px}
|
|
121967
124191
|
.dsh-ig-inspiration-empty.is-catalog-error{display:flex;flex-direction:column;gap:12px;color:var(--inspiration-text)}
|
|
@@ -121985,7 +124209,37 @@ img.ProseMirror-separator {
|
|
|
121985
124209
|
.dsh-ig-inspiration-end-hint{display:flex;align-items:center;justify-content:center;padding:24px 0 16px;color:var(--inspiration-muted);font-size:12px}
|
|
121986
124210
|
.dsh-ig-inspiration-inspector{position:sticky;top:0;overflow:hidden;border:1px solid var(--inspiration-line);border-radius:11px;background:var(--dsw-alias-bg-layer-1,#fff);box-shadow:0 9px 28px rgba(27,45,88,.06)}.dsh-ig-inspiration-inspector-empty{min-height:310px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:9px;padding:22px;color:var(--inspiration-muted);font-size:12px;text-align:center}.dsh-ig-inspiration-inspector-image{aspect-ratio:16/10;background:#f1f4fa;position:relative;cursor:zoom-in}.dsh-ig-inspiration-inspector-image img{width:100%;height:100%;object-fit:cover}.dsh-ig-inspiration-inspector-zoom-hint{position:absolute;bottom:8px;right:8px;display:inline-flex;align-items:center;gap:4px;padding:4px 8px;border-radius:6px;background:rgba(15,23,42,.75);backdrop-filter:blur(5px);color:#fff;font-size:10.5px;font-weight:500;opacity:0;transition:opacity .15s ease;pointer-events:none}.dsh-ig-inspiration-inspector-image:hover .dsh-ig-inspiration-inspector-zoom-hint{opacity:1}.dsh-ig-inspiration-inspector-body{padding:14px}.dsh-ig-inspiration-inspector-head{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}.dsh-ig-inspiration-inspector-body h2{margin:0;font-size:14px;line-height:1.4;flex:1}.dsh-ig-inspiration-inspector-fav{width:30px;height:30px;flex-shrink:0;border:1px solid var(--inspiration-line);border-radius:7px;background:var(--dsw-alias-bg-layer-1,#fff);color:var(--inspiration-muted);display:grid;place-items:center;cursor:pointer;transition:all .15s ease}.dsh-ig-inspiration-inspector-fav:hover{border-color:rgba(245,158,11,.4);color:#f59e0b}.dsh-ig-inspiration-inspector-fav.is-favorited{color:#f59e0b;border-color:rgba(245,158,11,.5);background:rgba(245,158,11,.08)}.dsh-ig-inspiration-origin{margin:5px 0 12px;color:var(--inspiration-muted);font-size:11px}.dsh-ig-inspiration-tags{display:flex;flex-wrap:wrap;gap:5px;margin:0 0 12px}.dsh-ig-inspiration-tags span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:3px 6px;border-radius:4px;background:#eef3ff;color:#3e5fb8;font-size:10px}.dsh-ig-inspiration-prompt-label{display:flex;align-items:center;justify-content:space-between;margin:0 0 6px;color:var(--inspiration-muted);font-size:10.5px;font-weight:650}.dsh-ig-inspiration-prompt{max-height:155px;margin:0;padding:9px;overflow:auto;white-space:pre-wrap;border:1px solid var(--inspiration-line);border-radius:7px;background:color-mix(in srgb,var(--dsw-alias-bg-layer-2,#f8fafc) 90%,#e9efff);font-size:11px;line-height:1.55;color:#526078}.dsh-ig-inspiration-actions{display:grid;grid-template-columns:1fr 1fr;gap:7px;margin-top:12px}.dsh-ig-inspiration-actions button,.dsh-ig-inspiration-source-link{height:34px;display:inline-flex;align-items:center;justify-content:center;gap:6px;border:1px solid var(--inspiration-line);border-radius:7px;background:var(--dsw-alias-bg-layer-1,#fff);color:#536075;font:inherit;font-size:11.5px;font-weight:600;cursor:pointer;text-decoration:none}.dsh-ig-inspiration-actions button:hover,.dsh-ig-inspiration-source-link:hover{border-color:rgba(47,100,245,.46);color:var(--inspiration-blue)}.dsh-ig-inspiration-actions .dsh-ig-inspiration-use{grid-column:1/-1;border-color:var(--inspiration-blue);background:linear-gradient(135deg,#386cf6,#2758e7);color:#fff;box-shadow:0 7px 15px rgba(47,100,245,.2)}.dsh-ig-inspiration-actions .dsh-ig-inspiration-use:hover{color:#fff;transform:translateY(-1px)}
|
|
121987
124211
|
.dsh-ig-inspiration-lightbox{position:fixed;inset:0;z-index:10000;background:rgba(8,12,22,.88);backdrop-filter:blur(8px);display:flex;align-items:center;justify-content:center;padding:24px;box-sizing:border-box}.dsh-ig-inspiration-lightbox-content{position:relative;max-width:90vw;max-height:90vh;display:flex;flex-direction:column;align-items:center}.dsh-ig-inspiration-lightbox-img-wrap{max-width:85vw;max-height:82vh;border-radius:10px;overflow:hidden;box-shadow:0 25px 60px rgba(0,0,0,.7);background:#05070d}.dsh-ig-inspiration-lightbox-img-wrap img{width:auto;height:auto;max-width:85vw;max-height:82vh;object-fit:contain;display:block}.dsh-ig-inspiration-lightbox-close{position:absolute;top:-16px;right:-16px;width:34px;height:34px;border-radius:50%;background:#1e293b;color:#fff;border:1px solid rgba(255,255,255,.2);cursor:pointer;display:grid;place-items:center;transition:background .15s,transform .15s;z-index:10}.dsh-ig-inspiration-lightbox-close:hover{background:#334155;transform:scale(1.1)}.dsh-ig-inspiration-lightbox-caption{margin-top:12px;color:rgba(255,255,255,.9);font-size:13px;font-weight:500;text-shadow:0 2px 4px rgba(0,0,0,.6)}
|
|
124212
|
+
.dsh-ig-inspiration-sources{display:flex;flex-wrap:wrap;gap:7px;margin-bottom:10px}.dsh-ig-inspiration-source-chip{height:30px;padding:0 13px;display:inline-flex;align-items:center;border:1px solid var(--inspiration-line);border-radius:999px;background:var(--dsw-alias-bg-layer-1,#fff);color:var(--inspiration-muted);font:inherit;font-size:11.5px;font-weight:600;cursor:pointer;transition:all .15s ease}.dsh-ig-inspiration-source-chip:hover{border-color:rgba(47,100,245,.46);color:var(--inspiration-blue)}.dsh-ig-inspiration-source-chip.is-active{border-color:var(--inspiration-blue);background:linear-gradient(135deg,#386cf6,#2758e7);color:#fff;box-shadow:0 5px 12px rgba(47,100,245,.22)}
|
|
124213
|
+
.dsh-ig-inspiration-actions .dsh-ig-inspiration-use.is-secondary{grid-column:1/-1;border-color:rgba(47,100,245,.5);background:var(--dsw-alias-bg-layer-1,#fff);color:var(--inspiration-blue);box-shadow:none}.dsh-ig-inspiration-actions .dsh-ig-inspiration-use.is-secondary:hover{color:#2758e7;transform:translateY(-1px)}.dsh-ig-inspiration-actions .dsh-ig-inspiration-use.is-secondary:disabled{opacity:.6;cursor:wait;transform:none}
|
|
121988
124214
|
@media(max-width:980px){.dsh-ig-inspiration-layout{grid-template-columns:1fr}.dsh-ig-inspiration-inspector{position:relative;top:auto}.dsh-ig-inspiration-inspector-empty{min-height:150px}.dsh-ig-inspiration-inspector-image{max-height:290px}.dsh-ig-inspiration-inspector-image img{object-fit:contain;background:#f1f4fa}}@media(max-width:700px){.dsh-ig-inspiration{padding:14px}.dsh-ig-inspiration-head{align-items:center}.dsh-ig-inspiration-toolbar{grid-template-columns:1fr 1fr}.dsh-ig-inspiration-search{grid-column:1/-1}.dsh-ig-inspiration-fav-filter{grid-column:1/-1}.dsh-ig-inspiration-grid{grid-template-columns:repeat(auto-fill,minmax(145px,1fr));gap:9px}}@media(max-width:420px){.dsh-ig-inspiration-toolbar{grid-template-columns:1fr}.dsh-ig-inspiration-search{grid-column:auto}}
|
|
124215
|
+
|
|
124216
|
+
.dsh-ig-inspiration-source-chip svg{flex-shrink:0}
|
|
124217
|
+
.dsh-ig-baoyu-panel{border:1px solid var(--inspiration-line);border-radius:11px;background:var(--dsw-alias-bg-layer-1,#fff);padding:18px;display:flex;flex-direction:column;gap:14px}
|
|
124218
|
+
.dsh-ig-baoyu-intro{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
|
|
124219
|
+
.dsh-ig-baoyu-combos{font-size:12px;color:var(--inspiration-blue)}
|
|
124220
|
+
.dsh-ig-baoyu-hint{font-size:11px;color:var(--inspiration-muted)}
|
|
124221
|
+
.dsh-ig-baoyu-dim{display:flex;flex-direction:column;gap:7px}
|
|
124222
|
+
.dsh-ig-baoyu-dim-head{font-size:11px;font-weight:650;color:var(--inspiration-muted);letter-spacing:.02em}
|
|
124223
|
+
.dsh-ig-baoyu-chips{display:flex;flex-wrap:wrap;gap:6px}
|
|
124224
|
+
.dsh-ig-baoyu-chip{height:28px;padding:0 10px;display:inline-flex;align-items:center;gap:6px;border:1px solid var(--inspiration-line);border-radius:999px;background:var(--dsw-alias-bg-layer-1,#fff);color:#536075;font:inherit;font-size:11px;font-weight:600;cursor:pointer;transition:all .15s ease}
|
|
124225
|
+
.dsh-ig-baoyu-chip:hover{border-color:rgba(47,100,245,.46);color:var(--inspiration-blue)}
|
|
124226
|
+
.dsh-ig-baoyu-chip.is-active{border-color:var(--inspiration-blue);background:rgba(47,100,245,.09);color:var(--inspiration-blue)}
|
|
124227
|
+
.dsh-ig-baoyu-swatch{display:inline-flex;gap:2px}
|
|
124228
|
+
.dsh-ig-baoyu-swatch i{width:9px;height:9px;border-radius:50%;border:1px solid rgba(15,23,42,.15);display:block}
|
|
124229
|
+
.dsh-ig-baoyu-title-input{height:34px;flex:1;padding:0 11px;border:1px solid var(--inspiration-line);border-radius:7px;background:var(--dsw-alias-bg-layer-1,#fff);color:inherit;font:inherit;font-size:12px}
|
|
124230
|
+
.dsh-ig-baoyu-title-input:focus{outline:none;border-color:rgba(47,100,245,.55)}
|
|
124231
|
+
.dsh-ig-baoyu-title-input:disabled{opacity:.45}
|
|
124232
|
+
.dsh-ig-baoyu-required{color:#dc2626;font-size:11px}
|
|
124233
|
+
.dsh-ig-baoyu-actions{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
|
|
124234
|
+
.dsh-ig-baoyu-btn{height:34px;padding:0 14px;display:inline-flex;align-items:center;gap:6px;border:1px solid var(--inspiration-line);border-radius:7px;background:var(--dsw-alias-bg-layer-1,#fff);color:#536075;font:inherit;font-size:11.5px;font-weight:600;cursor:pointer;transition:all .15s ease}
|
|
124235
|
+
.dsh-ig-baoyu-btn:hover{border-color:rgba(47,100,245,.46);color:var(--inspiration-blue)}
|
|
124236
|
+
.dsh-ig-baoyu-btn:disabled{opacity:.5;cursor:not-allowed}
|
|
124237
|
+
.dsh-ig-baoyu-btn.is-primary{border-color:var(--inspiration-blue);background:linear-gradient(135deg,#386cf6,#2758e7);color:#fff;box-shadow:0 7px 15px rgba(47,100,245,.2)}
|
|
124238
|
+
.dsh-ig-baoyu-btn.is-primary:hover{color:#fff;transform:translateY(-1px)}
|
|
124239
|
+
.dsh-ig-baoyu-btn.is-primary:disabled{opacity:.5;cursor:not-allowed;transform:none}
|
|
124240
|
+
.dsh-ig-baoyu-preview-block{display:flex;flex-direction:column;gap:6px}
|
|
124241
|
+
.dsh-ig-baoyu-preview-head{font-size:11px;font-weight:650;color:var(--inspiration-muted)}
|
|
124242
|
+
.dsh-ig-baoyu-preview{max-height:260px;margin:0;padding:12px;overflow:auto;white-space:pre-wrap;border:1px solid var(--inspiration-line);border-radius:7px;background:color-mix(in srgb,var(--dsw-alias-bg-layer-2,#f8fafc) 90%,#e9efff);font-size:11px;line-height:1.6;color:#526078}
|
|
121989
124243
|
`;
|
|
121990
124244
|
//#endregion
|
|
121991
124245
|
//#region lib/types/client/conversation-image-revisions.js
|
|
@@ -122500,7 +124754,7 @@ img.ProseMirror-separator {
|
|
|
122500
124754
|
`;
|
|
122501
124755
|
//#endregion
|
|
122502
124756
|
//#region lib/types/client/index.js
|
|
122503
|
-
console.info(`[dsh-image-gen] canvas bundle 2026-09-
|
|
124757
|
+
console.info(`[dsh-image-gen] canvas bundle 2026-09-28T16:41:08.496Z`);
|
|
122504
124758
|
/** Right-sidebar tab-type registration id (DSH 0.1.5 `sidebarRightTabs`). */
|
|
122505
124759
|
const SIDEBAR_STUDIO_TAB_ID = "dsh-image-gen/studio";
|
|
122506
124760
|
/** The tab kind: a page type opened by kind, recognizing no resource address. */
|
|
@@ -122572,7 +124826,8 @@ img.ProseMirror-separator {
|
|
|
122572
124826
|
editFormat: "图生图请求形态",
|
|
122573
124827
|
editFormatMultipart: "标准 multipart(OpenAI 官方)",
|
|
122574
124828
|
editFormatJsonImageUrlArray: "JSON images 数组(商汤等中转)",
|
|
122575
|
-
|
|
124829
|
+
editFormatFormReferenceImages: "multipart + reference_images JSON 数组(base64)",
|
|
124830
|
+
editFormatHint: "文生图不受影响。仅当中转站的图生图接口使用自有契约(如商汤 SenseNova 的 JSON images 数组,或要求 reference_images base64 数组的中转)时才需要切换。",
|
|
122576
124831
|
editExtra: "附加 JSON 字段",
|
|
122577
124832
|
editExtraPlaceholder: "{\"watermark\": false, \"prompt_extend\": true}",
|
|
122578
124833
|
editExtraHint: "仅 JSON 形态生效;会合并到请求体末尾,可覆盖默认字段。留空表示不附加。",
|
|
@@ -122716,7 +124971,8 @@ img.ProseMirror-separator {
|
|
|
122716
124971
|
editFormat: "Edit request format",
|
|
122717
124972
|
editFormatMultipart: "Standard multipart (official OpenAI)",
|
|
122718
124973
|
editFormatJsonImageUrlArray: "JSON images array (SenseNova etc.)",
|
|
122719
|
-
|
|
124974
|
+
editFormatFormReferenceImages: "Multipart with a reference_images JSON array (base64)",
|
|
124975
|
+
editFormatHint: "Text-to-image is unaffected. Only switch when the relay runs image edits on its own contract (e.g. SenseNova's JSON images array, or a relay that takes reference_images as a base64 JSON array); size is pinned to \"auto\" in the JSON images format (the only value SenseNova's edits endpoint accepts) and can be overridden via extra fields.",
|
|
122720
124976
|
editExtra: "Extra JSON fields",
|
|
122721
124977
|
editExtraPlaceholder: "{\"watermark\": false, \"prompt_extend\": true}",
|
|
122722
124978
|
editExtraHint: "Only used with the JSON format; merged into the request body last and may override defaults. Leave empty for none.",
|
|
@@ -123409,6 +125665,10 @@ img.ProseMirror-separator {
|
|
|
123409
125665
|
return "";
|
|
123410
125666
|
}
|
|
123411
125667
|
}
|
|
125668
|
+
/** Persisted or selected edit-format value → row state; unknown values fall back to standard multipart. */
|
|
125669
|
+
function parseEditFormat(value) {
|
|
125670
|
+
return value === "jsonImageUrlArray" || value === "formReferenceImages" ? value : "multipart";
|
|
125671
|
+
}
|
|
123412
125672
|
/** Build one row per provider from persisted settings, including ComfyUI extras. */
|
|
123413
125673
|
function rowsFromSettings(value) {
|
|
123414
125674
|
const rows = {};
|
|
@@ -123422,7 +125682,7 @@ img.ProseMirror-separator {
|
|
|
123422
125682
|
timeoutSeconds: Math.max(1, Math.round((value?.comfyuiTimeoutMs ?? 3e5) / 1e3))
|
|
123423
125683
|
} : {},
|
|
123424
125684
|
...provider === "openai-compat" ? {
|
|
123425
|
-
editFormat: value?.openaiCompatEditFormat
|
|
125685
|
+
editFormat: parseEditFormat(value?.openaiCompatEditFormat),
|
|
123426
125686
|
editExtraText: editExtraTextOf(value?.openaiCompatEditExtra)
|
|
123427
125687
|
} : {},
|
|
123428
125688
|
...provider === "seedream" ? {
|
|
@@ -124239,16 +126499,23 @@ img.ProseMirror-separator {
|
|
|
124239
126499
|
className: "dsh-ig-input",
|
|
124240
126500
|
value: row.editFormat,
|
|
124241
126501
|
onChange: (event) => {
|
|
124242
|
-
updateRow(provider, { editFormat: event.target.value
|
|
126502
|
+
updateRow(provider, { editFormat: parseEditFormat(event.target.value) });
|
|
124243
126503
|
},
|
|
124244
126504
|
disabled: !snapshot.writable,
|
|
124245
|
-
children: [
|
|
124246
|
-
|
|
124247
|
-
|
|
124248
|
-
|
|
124249
|
-
|
|
124250
|
-
|
|
124251
|
-
|
|
126505
|
+
children: [
|
|
126506
|
+
(0, react_jsx_runtime.jsx)("option", {
|
|
126507
|
+
value: "multipart",
|
|
126508
|
+
children: t("editFormatMultipart")
|
|
126509
|
+
}),
|
|
126510
|
+
(0, react_jsx_runtime.jsx)("option", {
|
|
126511
|
+
value: "jsonImageUrlArray",
|
|
126512
|
+
children: t("editFormatJsonImageUrlArray")
|
|
126513
|
+
}),
|
|
126514
|
+
(0, react_jsx_runtime.jsx)("option", {
|
|
126515
|
+
value: "formReferenceImages",
|
|
126516
|
+
children: t("editFormatFormReferenceImages")
|
|
126517
|
+
})
|
|
126518
|
+
]
|
|
124252
126519
|
}),
|
|
124253
126520
|
(0, react_jsx_runtime.jsx)("span", {
|
|
124254
126521
|
className: "dsh-ig-hint",
|
|
@@ -125404,7 +127671,6 @@ img.ProseMirror-separator {
|
|
|
125404
127671
|
(0, react_jsx_runtime.jsxs)("label", { children: [(0, react_jsx_runtime.jsx)("span", { children: t("prompt") }), (0, react_jsx_runtime.jsx)("textarea", {
|
|
125405
127672
|
ref: regenerateTextareaRef,
|
|
125406
127673
|
value: regeneratePrompt,
|
|
125407
|
-
maxLength: 2e3,
|
|
125408
127674
|
disabled: isRegenerating,
|
|
125409
127675
|
onChange: (event) => setRegeneratePrompt(event.target.value),
|
|
125410
127676
|
onKeyDown: (event) => {
|