fix: respect canvas toolbar toggles
This commit is contained in:
parent
1912bcd25b
commit
b78a2701bb
@ -3257,7 +3257,7 @@ export function AdminSettingsClient() {
|
|||||||
|
|
||||||
const updateCanvasToolbarItem = (
|
const updateCanvasToolbarItem = (
|
||||||
key: CanvasToolbarItemKey,
|
key: CanvasToolbarItemKey,
|
||||||
updates: Partial<{ label: string; iconUrl: string }>
|
updates: Partial<{ label: string; iconUrl: string; enabled: boolean }>
|
||||||
) => {
|
) => {
|
||||||
setSiteSettings((prev) => {
|
setSiteSettings((prev) => {
|
||||||
const normalized = normalizeCanvasToolbarConfig(prev.canvasToolbarConfig);
|
const normalized = normalizeCanvasToolbarConfig(prev.canvasToolbarConfig);
|
||||||
@ -11824,12 +11824,29 @@ export function AdminSettingsClient() {
|
|||||||
updateCanvasToolbarItem(item.key, {
|
updateCanvasToolbarItem(item.key, {
|
||||||
label: defaultItem.label,
|
label: defaultItem.label,
|
||||||
iconUrl: "",
|
iconUrl: "",
|
||||||
|
enabled: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
默认
|
默认
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex items-center justify-between rounded-lg border bg-background/70 px-3 py-2">
|
||||||
|
<div className="space-y-0.5">
|
||||||
|
<div className="text-xs font-medium">启用此功能</div>
|
||||||
|
<div className="text-[11px] text-muted-foreground">
|
||||||
|
关闭后前端不再显示这个工具按钮
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Switch
|
||||||
|
checked={itemConfig.enabled !== false}
|
||||||
|
onCheckedChange={(checked) =>
|
||||||
|
updateCanvasToolbarItem(item.key, {
|
||||||
|
enabled: checked,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div className="space-y-1.5">
|
<div className="space-y-1.5">
|
||||||
<Label
|
<Label
|
||||||
className="text-xs text-muted-foreground"
|
className="text-xs text-muted-foreground"
|
||||||
|
|||||||
@ -108,6 +108,7 @@ import {
|
|||||||
} from "@/lib/canvas/node-content-scale";
|
} from "@/lib/canvas/node-content-scale";
|
||||||
import {
|
import {
|
||||||
getCanvasToolbarItem,
|
getCanvasToolbarItem,
|
||||||
|
isCanvasToolbarItemEnabled,
|
||||||
type CanvasToolbarConfig,
|
type CanvasToolbarConfig,
|
||||||
} from "@/lib/canvas-toolbar-config";
|
} from "@/lib/canvas-toolbar-config";
|
||||||
import { cn, fetcher } from "@/lib/utils";
|
import { cn, fetcher } from "@/lib/utils";
|
||||||
@ -225,6 +226,7 @@ interface BoxCutoutPoint {
|
|||||||
const BOX_CUTOUT_DEFAULT_PADDING_RATIO = 0.08;
|
const BOX_CUTOUT_DEFAULT_PADDING_RATIO = 0.08;
|
||||||
const BOX_CUTOUT_MIN_EDGE_PX = 24;
|
const BOX_CUTOUT_MIN_EDGE_PX = 24;
|
||||||
const FLOATING_TOOLBAR_SCALE = 0.8;
|
const FLOATING_TOOLBAR_SCALE = 0.8;
|
||||||
|
const IMAGE_EDIT_PANEL_SCALE = 0.5;
|
||||||
const DEFAULT_CROP_PRESET_ID = "1:1";
|
const DEFAULT_CROP_PRESET_ID = "1:1";
|
||||||
const IMAGE_ADJUST_NOISE_DATA_URI = `data:image/svg+xml;utf8,${encodeURIComponent(
|
const IMAGE_ADJUST_NOISE_DATA_URI = `data:image/svg+xml;utf8,${encodeURIComponent(
|
||||||
"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 160 160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='1.18' numOctaves='2' stitchTiles='stitch'/></filter><rect width='160' height='160' filter='url(#n)' opacity='1'/></svg>"
|
"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 160 160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='1.18' numOctaves='2' stitchTiles='stitch'/></filter><rect width='160' height='160' filter='url(#n)' opacity='1'/></svg>"
|
||||||
@ -1310,6 +1312,98 @@ export function ImageNode({
|
|||||||
canvasToolbarConfig,
|
canvasToolbarConfig,
|
||||||
"imageCancelCutout"
|
"imageCancelCutout"
|
||||||
);
|
);
|
||||||
|
const imageNodeMoreEnabled = isCanvasToolbarItemEnabled(
|
||||||
|
canvasToolbarConfig,
|
||||||
|
"imageNodeMore"
|
||||||
|
);
|
||||||
|
const imageRemoveBackgroundEnabled = isCanvasToolbarItemEnabled(
|
||||||
|
canvasToolbarConfig,
|
||||||
|
"imageRemoveBackground"
|
||||||
|
);
|
||||||
|
const imageRemoveWatermarkEnabled = isCanvasToolbarItemEnabled(
|
||||||
|
canvasToolbarConfig,
|
||||||
|
"imageRemoveWatermark"
|
||||||
|
);
|
||||||
|
const imageEnhanceEnabled = isCanvasToolbarItemEnabled(
|
||||||
|
canvasToolbarConfig,
|
||||||
|
"imageEnhance"
|
||||||
|
);
|
||||||
|
const imageNoteEnabled = isCanvasToolbarItemEnabled(canvasToolbarConfig, "imageNote");
|
||||||
|
const imageLayerSplitEnabledByToolbar = isCanvasToolbarItemEnabled(
|
||||||
|
canvasToolbarConfig,
|
||||||
|
"imageLayerSplit"
|
||||||
|
);
|
||||||
|
const imageResizeEnabled = isCanvasToolbarItemEnabled(
|
||||||
|
canvasToolbarConfig,
|
||||||
|
"imageResize"
|
||||||
|
);
|
||||||
|
const imageMultiAngleEnabled = isCanvasToolbarItemEnabled(
|
||||||
|
canvasToolbarConfig,
|
||||||
|
"imageMultiAngle"
|
||||||
|
);
|
||||||
|
const imagePromptRegenerateEnabled = isCanvasToolbarItemEnabled(
|
||||||
|
canvasToolbarConfig,
|
||||||
|
"imagePromptRegenerate"
|
||||||
|
);
|
||||||
|
const imageTextEditEnabled = isCanvasToolbarItemEnabled(
|
||||||
|
canvasToolbarConfig,
|
||||||
|
"imageTextEdit"
|
||||||
|
);
|
||||||
|
const imageExtendEnabled = isCanvasToolbarItemEnabled(
|
||||||
|
canvasToolbarConfig,
|
||||||
|
"imageExtend"
|
||||||
|
);
|
||||||
|
const imageCropEnabled = isCanvasToolbarItemEnabled(canvasToolbarConfig, "imageCrop");
|
||||||
|
const imageAdjustEnabled = isCanvasToolbarItemEnabled(
|
||||||
|
canvasToolbarConfig,
|
||||||
|
"imageAdjust"
|
||||||
|
);
|
||||||
|
const imageFlipRotateEnabled = isCanvasToolbarItemEnabled(
|
||||||
|
canvasToolbarConfig,
|
||||||
|
"imageFlipRotate"
|
||||||
|
);
|
||||||
|
const imageRenameEnabled = isCanvasToolbarItemEnabled(
|
||||||
|
canvasToolbarConfig,
|
||||||
|
"imageRename"
|
||||||
|
);
|
||||||
|
const imageDownloadEnabled = isCanvasToolbarItemEnabled(
|
||||||
|
canvasToolbarConfig,
|
||||||
|
"imageDownload"
|
||||||
|
);
|
||||||
|
const imageDeleteEnabled = isCanvasToolbarItemEnabled(
|
||||||
|
canvasToolbarConfig,
|
||||||
|
"imageDelete"
|
||||||
|
);
|
||||||
|
const hasHoverImageMorePrimaryActions =
|
||||||
|
imageRemoveBackgroundEnabled ||
|
||||||
|
imageRemoveWatermarkEnabled ||
|
||||||
|
imageEnhanceEnabled ||
|
||||||
|
imageNoteEnabled ||
|
||||||
|
(isLayerSplitEnabled && imageLayerSplitEnabledByToolbar) ||
|
||||||
|
imageResizeEnabled ||
|
||||||
|
imageMultiAngleEnabled ||
|
||||||
|
imagePromptRegenerateEnabled ||
|
||||||
|
imageTextEditEnabled ||
|
||||||
|
imageExtendEnabled ||
|
||||||
|
imageCropEnabled ||
|
||||||
|
imageAdjustEnabled ||
|
||||||
|
imageFlipRotateEnabled ||
|
||||||
|
imageRenameEnabled;
|
||||||
|
const hasHoverImageMoreSecondaryActions =
|
||||||
|
imageDownloadEnabled || imageDeleteEnabled;
|
||||||
|
const hasHoverImageMoreMenu =
|
||||||
|
imageNodeMoreEnabled &&
|
||||||
|
(hasHoverImageMorePrimaryActions || hasHoverImageMoreSecondaryActions);
|
||||||
|
const hasSelectedImageMorePrimaryActions =
|
||||||
|
imageExtendEnabled ||
|
||||||
|
imageCropEnabled ||
|
||||||
|
imageAdjustEnabled ||
|
||||||
|
imageFlipRotateEnabled ||
|
||||||
|
imagePromptRegenerateEnabled ||
|
||||||
|
imageNoteEnabled;
|
||||||
|
const hasSelectedImageMoreMenu =
|
||||||
|
imageNodeMoreEnabled &&
|
||||||
|
(hasSelectedImageMorePrimaryActions || imageDeleteEnabled);
|
||||||
const contentScale = useMemo(
|
const contentScale = useMemo(
|
||||||
() =>
|
() =>
|
||||||
getNodeContentScale(node.size, {
|
getNodeContentScale(node.size, {
|
||||||
@ -3181,8 +3275,8 @@ export function ImageNode({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const rect = containerRef.current.getBoundingClientRect();
|
const rect = containerRef.current.getBoundingClientRect();
|
||||||
const panelWidth = 520;
|
const panelWidth = 520 * IMAGE_EDIT_PANEL_SCALE;
|
||||||
const panelHeight = 760;
|
const panelHeight = 760 * IMAGE_EDIT_PANEL_SCALE;
|
||||||
const spacing = 18;
|
const spacing = 18;
|
||||||
const maxTop = Math.max(12, window.innerHeight - panelHeight);
|
const maxTop = Math.max(12, window.innerHeight - panelHeight);
|
||||||
|
|
||||||
@ -3201,8 +3295,8 @@ export function ImageNode({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const rect = containerRef.current.getBoundingClientRect();
|
const rect = containerRef.current.getBoundingClientRect();
|
||||||
const panelWidth = 500;
|
const panelWidth = 474 * IMAGE_EDIT_PANEL_SCALE;
|
||||||
const panelHeight = 980;
|
const panelHeight = 980 * IMAGE_EDIT_PANEL_SCALE;
|
||||||
const spacing = 16;
|
const spacing = 16;
|
||||||
const maxTop = Math.max(12, window.innerHeight - panelHeight);
|
const maxTop = Math.max(12, window.innerHeight - panelHeight);
|
||||||
|
|
||||||
@ -3217,12 +3311,12 @@ export function ImageNode({
|
|||||||
|
|
||||||
const getFlipRotatePanelPosition = () => {
|
const getFlipRotatePanelPosition = () => {
|
||||||
if (!containerRef.current || typeof window === "undefined") {
|
if (!containerRef.current || typeof window === "undefined") {
|
||||||
return { top: 0, left: 0, maxWidth: 660 };
|
return { top: 0, left: 0, maxWidth: 660 * IMAGE_EDIT_PANEL_SCALE };
|
||||||
}
|
}
|
||||||
|
|
||||||
const rect = containerRef.current.getBoundingClientRect();
|
const rect = containerRef.current.getBoundingClientRect();
|
||||||
const panelWidth = 640;
|
const panelWidth = 640 * IMAGE_EDIT_PANEL_SCALE;
|
||||||
const panelHeight = 84;
|
const panelHeight = 84 * IMAGE_EDIT_PANEL_SCALE;
|
||||||
const gap = 18;
|
const gap = 18;
|
||||||
const titleSafeHeight = 34;
|
const titleSafeHeight = 34;
|
||||||
const { viewportPadding, safeLeft, safeRight, maxTop } =
|
const { viewportPadding, safeLeft, safeRight, maxTop } =
|
||||||
@ -3275,8 +3369,8 @@ export function ImageNode({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const rect = containerRef.current.getBoundingClientRect();
|
const rect = containerRef.current.getBoundingClientRect();
|
||||||
const panelWidth = 380;
|
const panelWidth = 372 * IMAGE_EDIT_PANEL_SCALE;
|
||||||
const panelHeight = 760;
|
const panelHeight = 760 * IMAGE_EDIT_PANEL_SCALE;
|
||||||
const spacing = 16;
|
const spacing = 16;
|
||||||
const maxTop = Math.max(12, window.innerHeight - panelHeight);
|
const maxTop = Math.max(12, window.innerHeight - panelHeight);
|
||||||
|
|
||||||
@ -6533,7 +6627,11 @@ export function ImageNode({
|
|||||||
{/* 工具栏使用 Portal 渲染到 body,避免被裁剪 */}
|
{/* 工具栏使用 Portal 渲染到 body,避免被裁剪 */}
|
||||||
|
|
||||||
{/* 悬浮时的更多操作按钮 (右上角) */}
|
{/* 悬浮时的更多操作按钮 (右上角) */}
|
||||||
{isHovered && data.src && !isProcessing && !isSelected && (
|
{isHovered &&
|
||||||
|
data.src &&
|
||||||
|
!isProcessing &&
|
||||||
|
!isSelected &&
|
||||||
|
hasHoverImageMoreMenu ? (
|
||||||
<div className="absolute top-2 right-2 flex items-center gap-1">
|
<div className="absolute top-2 right-2 flex items-center gap-1">
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
@ -6551,6 +6649,7 @@ export function ImageNode({
|
|||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="end">
|
<DropdownMenuContent align="end">
|
||||||
|
{imageRemoveBackgroundEnabled ? (
|
||||||
<DropdownMenuItem onClick={() => handleAction("rmbg")}>
|
<DropdownMenuItem onClick={() => handleAction("rmbg")}>
|
||||||
<CanvasToolbarIcon
|
<CanvasToolbarIcon
|
||||||
className="mr-2 h-4 w-4"
|
className="mr-2 h-4 w-4"
|
||||||
@ -6559,6 +6658,8 @@ export function ImageNode({
|
|||||||
/>
|
/>
|
||||||
{imageRemoveBackgroundItem.label}
|
{imageRemoveBackgroundItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
) : null}
|
||||||
|
{imageRemoveWatermarkEnabled ? (
|
||||||
<DropdownMenuItem onClick={() => handleAction("watermark")}>
|
<DropdownMenuItem onClick={() => handleAction("watermark")}>
|
||||||
<CanvasToolbarIcon
|
<CanvasToolbarIcon
|
||||||
className="mr-2 h-4 w-4"
|
className="mr-2 h-4 w-4"
|
||||||
@ -6567,6 +6668,8 @@ export function ImageNode({
|
|||||||
/>
|
/>
|
||||||
{imageRemoveWatermarkItem.label}
|
{imageRemoveWatermarkItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
) : null}
|
||||||
|
{imageEnhanceEnabled ? (
|
||||||
<DropdownMenuItem onClick={() => handleAction("enhance")}>
|
<DropdownMenuItem onClick={() => handleAction("enhance")}>
|
||||||
<CanvasToolbarIcon
|
<CanvasToolbarIcon
|
||||||
className="mr-2 h-4 w-4"
|
className="mr-2 h-4 w-4"
|
||||||
@ -6575,6 +6678,8 @@ export function ImageNode({
|
|||||||
/>
|
/>
|
||||||
{imageEnhanceItem.label}
|
{imageEnhanceItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
) : null}
|
||||||
|
{imageNoteEnabled ? (
|
||||||
<DropdownMenuItem onClick={() => handleAction("note")}>
|
<DropdownMenuItem onClick={() => handleAction("note")}>
|
||||||
<CanvasToolbarIcon
|
<CanvasToolbarIcon
|
||||||
className="mr-2 h-4 w-4"
|
className="mr-2 h-4 w-4"
|
||||||
@ -6583,7 +6688,8 @@ export function ImageNode({
|
|||||||
/>
|
/>
|
||||||
{imageNoteItem.label}
|
{imageNoteItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
{isLayerSplitEnabled ? (
|
) : null}
|
||||||
|
{isLayerSplitEnabled && imageLayerSplitEnabledByToolbar ? (
|
||||||
<DropdownMenuItem onClick={() => handleAction("layer-split")}>
|
<DropdownMenuItem onClick={() => handleAction("layer-split")}>
|
||||||
<CanvasToolbarIcon
|
<CanvasToolbarIcon
|
||||||
className="mr-2 h-4 w-4"
|
className="mr-2 h-4 w-4"
|
||||||
@ -6593,6 +6699,7 @@ export function ImageNode({
|
|||||||
{imageLayerSplitItem.label}
|
{imageLayerSplitItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
) : null}
|
) : null}
|
||||||
|
{imageResizeEnabled ? (
|
||||||
<DropdownMenuItem onClick={() => handleAction("resize")}>
|
<DropdownMenuItem onClick={() => handleAction("resize")}>
|
||||||
<CanvasToolbarIcon
|
<CanvasToolbarIcon
|
||||||
className="mr-2 h-4 w-4"
|
className="mr-2 h-4 w-4"
|
||||||
@ -6601,6 +6708,8 @@ export function ImageNode({
|
|||||||
/>
|
/>
|
||||||
{imageResizeItem.label}
|
{imageResizeItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
) : null}
|
||||||
|
{imageMultiAngleEnabled ? (
|
||||||
<DropdownMenuItem onClick={() => handleAction("angle")}>
|
<DropdownMenuItem onClick={() => handleAction("angle")}>
|
||||||
<CanvasToolbarIcon
|
<CanvasToolbarIcon
|
||||||
className="mr-2 h-4 w-4"
|
className="mr-2 h-4 w-4"
|
||||||
@ -6609,6 +6718,8 @@ export function ImageNode({
|
|||||||
/>
|
/>
|
||||||
{imageMultiAngleItem.label}
|
{imageMultiAngleItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
) : null}
|
||||||
|
{imagePromptRegenerateEnabled ? (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
onClick={() => handleAction("prompt-regenerate")}
|
onClick={() => handleAction("prompt-regenerate")}
|
||||||
>
|
>
|
||||||
@ -6619,6 +6730,8 @@ export function ImageNode({
|
|||||||
/>
|
/>
|
||||||
{imagePromptRegenerateItem.label}
|
{imagePromptRegenerateItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
) : null}
|
||||||
|
{imageTextEditEnabled ? (
|
||||||
<DropdownMenuItem onClick={() => handleAction("text-edit")}>
|
<DropdownMenuItem onClick={() => handleAction("text-edit")}>
|
||||||
<CanvasToolbarIcon
|
<CanvasToolbarIcon
|
||||||
className="mr-2 h-4 w-4"
|
className="mr-2 h-4 w-4"
|
||||||
@ -6627,6 +6740,8 @@ export function ImageNode({
|
|||||||
/>
|
/>
|
||||||
{imageTextEditItem.label}
|
{imageTextEditItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
) : null}
|
||||||
|
{imageExtendEnabled ? (
|
||||||
<DropdownMenuItem onClick={() => handleAction("extend")}>
|
<DropdownMenuItem onClick={() => handleAction("extend")}>
|
||||||
<CanvasToolbarIcon
|
<CanvasToolbarIcon
|
||||||
className="mr-2 h-4 w-4"
|
className="mr-2 h-4 w-4"
|
||||||
@ -6635,6 +6750,8 @@ export function ImageNode({
|
|||||||
/>
|
/>
|
||||||
{imageExtendItem.label}
|
{imageExtendItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
) : null}
|
||||||
|
{imageCropEnabled ? (
|
||||||
<DropdownMenuItem onClick={() => handleAction("crop")}>
|
<DropdownMenuItem onClick={() => handleAction("crop")}>
|
||||||
<CanvasToolbarIcon
|
<CanvasToolbarIcon
|
||||||
className="mr-2 h-4 w-4"
|
className="mr-2 h-4 w-4"
|
||||||
@ -6643,6 +6760,8 @@ export function ImageNode({
|
|||||||
/>
|
/>
|
||||||
{imageCropItem.label}
|
{imageCropItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
) : null}
|
||||||
|
{imageAdjustEnabled ? (
|
||||||
<DropdownMenuItem onClick={() => handleAction("adjust")}>
|
<DropdownMenuItem onClick={() => handleAction("adjust")}>
|
||||||
<CanvasToolbarIcon
|
<CanvasToolbarIcon
|
||||||
className="mr-2 h-4 w-4"
|
className="mr-2 h-4 w-4"
|
||||||
@ -6651,6 +6770,8 @@ export function ImageNode({
|
|||||||
/>
|
/>
|
||||||
{imageAdjustItem.label}
|
{imageAdjustItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
) : null}
|
||||||
|
{imageFlipRotateEnabled ? (
|
||||||
<DropdownMenuItem onClick={() => handleAction("flip-rotate")}>
|
<DropdownMenuItem onClick={() => handleAction("flip-rotate")}>
|
||||||
<CanvasToolbarIcon
|
<CanvasToolbarIcon
|
||||||
className="mr-2 h-4 w-4"
|
className="mr-2 h-4 w-4"
|
||||||
@ -6659,6 +6780,8 @@ export function ImageNode({
|
|||||||
/>
|
/>
|
||||||
{imageFlipRotateItem.label}
|
{imageFlipRotateItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
) : null}
|
||||||
|
{imageRenameEnabled ? (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setDraftTitle(displayTitle);
|
setDraftTitle(displayTitle);
|
||||||
@ -6672,7 +6795,12 @@ export function ImageNode({
|
|||||||
/>
|
/>
|
||||||
{imageRenameItem.label}
|
{imageRenameItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
) : null}
|
||||||
|
{hasHoverImageMorePrimaryActions &&
|
||||||
|
hasHoverImageMoreSecondaryActions ? (
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
|
) : null}
|
||||||
|
{imageDownloadEnabled ? (
|
||||||
<DropdownMenuItem onClick={handleDownload}>
|
<DropdownMenuItem onClick={handleDownload}>
|
||||||
<CanvasToolbarIcon
|
<CanvasToolbarIcon
|
||||||
className="mr-2 h-4 w-4"
|
className="mr-2 h-4 w-4"
|
||||||
@ -6681,6 +6809,8 @@ export function ImageNode({
|
|||||||
/>
|
/>
|
||||||
{imageDownloadItem.label}
|
{imageDownloadItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
) : null}
|
||||||
|
{imageDeleteEnabled ? (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
className="text-destructive"
|
className="text-destructive"
|
||||||
onClick={() => deleteNode(node.id)}
|
onClick={() => deleteNode(node.id)}
|
||||||
@ -6692,10 +6822,11 @@ export function ImageNode({
|
|||||||
/>
|
/>
|
||||||
{imageDeleteItem.label}
|
{imageDeleteItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
) : null}
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</div>
|
</div>
|
||||||
)}
|
) : null}
|
||||||
|
|
||||||
{/* 提示词显示 */}
|
{/* 提示词显示 */}
|
||||||
{data.prompt && isHovered && !isProcessing && (
|
{data.prompt && isHovered && !isProcessing && (
|
||||||
@ -7131,6 +7262,7 @@ export function ImageNode({
|
|||||||
|
|
||||||
<div className="mx-1 h-6 w-px bg-slate-200 dark:bg-slate-700" />
|
<div className="mx-1 h-6 w-px bg-slate-200 dark:bg-slate-700" />
|
||||||
|
|
||||||
|
{hasSelectedImageMoreMenu ? (
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
@ -7152,6 +7284,7 @@ export function ImageNode({
|
|||||||
className="bg-white opacity-100 backdrop-blur-none dark:bg-slate-900 dark:text-slate-100"
|
className="bg-white opacity-100 backdrop-blur-none dark:bg-slate-900 dark:text-slate-100"
|
||||||
side="bottom"
|
side="bottom"
|
||||||
>
|
>
|
||||||
|
{imageExtendEnabled ? (
|
||||||
<DropdownMenuItem onClick={() => handleAction("extend")}>
|
<DropdownMenuItem onClick={() => handleAction("extend")}>
|
||||||
<CanvasToolbarIcon
|
<CanvasToolbarIcon
|
||||||
className="mr-2 h-4 w-4"
|
className="mr-2 h-4 w-4"
|
||||||
@ -7160,6 +7293,8 @@ export function ImageNode({
|
|||||||
/>
|
/>
|
||||||
{imageExtendItem.label}
|
{imageExtendItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
) : null}
|
||||||
|
{imageCropEnabled ? (
|
||||||
<DropdownMenuItem onClick={() => handleAction("crop")}>
|
<DropdownMenuItem onClick={() => handleAction("crop")}>
|
||||||
<CanvasToolbarIcon
|
<CanvasToolbarIcon
|
||||||
className="mr-2 h-4 w-4"
|
className="mr-2 h-4 w-4"
|
||||||
@ -7168,6 +7303,8 @@ export function ImageNode({
|
|||||||
/>
|
/>
|
||||||
{imageCropItem.label}
|
{imageCropItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
) : null}
|
||||||
|
{imageAdjustEnabled ? (
|
||||||
<DropdownMenuItem onClick={() => handleAction("adjust")}>
|
<DropdownMenuItem onClick={() => handleAction("adjust")}>
|
||||||
<CanvasToolbarIcon
|
<CanvasToolbarIcon
|
||||||
className="mr-2 h-4 w-4"
|
className="mr-2 h-4 w-4"
|
||||||
@ -7176,6 +7313,8 @@ export function ImageNode({
|
|||||||
/>
|
/>
|
||||||
{imageAdjustItem.label}
|
{imageAdjustItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
) : null}
|
||||||
|
{imageFlipRotateEnabled ? (
|
||||||
<DropdownMenuItem onClick={() => handleAction("flip-rotate")}>
|
<DropdownMenuItem onClick={() => handleAction("flip-rotate")}>
|
||||||
<CanvasToolbarIcon
|
<CanvasToolbarIcon
|
||||||
className="mr-2 h-4 w-4"
|
className="mr-2 h-4 w-4"
|
||||||
@ -7184,6 +7323,8 @@ export function ImageNode({
|
|||||||
/>
|
/>
|
||||||
{imageFlipRotateItem.label}
|
{imageFlipRotateItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
) : null}
|
||||||
|
{imagePromptRegenerateEnabled ? (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
onClick={() => handleAction("prompt-regenerate")}
|
onClick={() => handleAction("prompt-regenerate")}
|
||||||
>
|
>
|
||||||
@ -7194,6 +7335,8 @@ export function ImageNode({
|
|||||||
/>
|
/>
|
||||||
{imagePromptRegenerateItem.label}
|
{imagePromptRegenerateItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
) : null}
|
||||||
|
{imageNoteEnabled ? (
|
||||||
<DropdownMenuItem onClick={() => handleAction("note")}>
|
<DropdownMenuItem onClick={() => handleAction("note")}>
|
||||||
<CanvasToolbarIcon
|
<CanvasToolbarIcon
|
||||||
className="mr-2 h-4 w-4"
|
className="mr-2 h-4 w-4"
|
||||||
@ -7202,7 +7345,11 @@ export function ImageNode({
|
|||||||
/>
|
/>
|
||||||
{imageNoteItem.label}
|
{imageNoteItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
) : null}
|
||||||
|
{hasSelectedImageMorePrimaryActions && imageDeleteEnabled ? (
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
|
) : null}
|
||||||
|
{imageDeleteEnabled ? (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
className="text-red-600 focus:text-red-700"
|
className="text-red-600 focus:text-red-700"
|
||||||
onClick={() => deleteNode(node.id)}
|
onClick={() => deleteNode(node.id)}
|
||||||
@ -7214,8 +7361,10 @@ export function ImageNode({
|
|||||||
/>
|
/>
|
||||||
{imageDeleteItem.label}
|
{imageDeleteItem.label}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
) : null}
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
|
) : null}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
className="h-10 w-10 rounded-xl text-slate-700 hover:bg-slate-100 hover:text-slate-900 dark:text-slate-100 dark:hover:bg-zinc-800"
|
className="h-10 w-10 rounded-xl text-slate-700 hover:bg-slate-100 hover:text-slate-900 dark:text-slate-100 dark:hover:bg-zinc-800"
|
||||||
@ -7358,6 +7507,8 @@ export function ImageNode({
|
|||||||
style={{
|
style={{
|
||||||
top: cropPanelPosition.top,
|
top: cropPanelPosition.top,
|
||||||
left: cropPanelPosition.left,
|
left: cropPanelPosition.left,
|
||||||
|
transform: `scale(${IMAGE_EDIT_PANEL_SCALE})`,
|
||||||
|
transformOrigin: "top left",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="px-8 pt-8 pb-6">
|
<div className="px-8 pt-8 pb-6">
|
||||||
@ -7513,6 +7664,8 @@ export function ImageNode({
|
|||||||
style={{
|
style={{
|
||||||
top: imageAdjustPanelPosition.top,
|
top: imageAdjustPanelPosition.top,
|
||||||
left: imageAdjustPanelPosition.left,
|
left: imageAdjustPanelPosition.left,
|
||||||
|
transform: `scale(${IMAGE_EDIT_PANEL_SCALE})`,
|
||||||
|
transformOrigin: "top left",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between px-8 pt-8 pb-5">
|
<div className="flex items-center justify-between px-8 pt-8 pb-5">
|
||||||
@ -7604,7 +7757,11 @@ export function ImageNode({
|
|||||||
style={{
|
style={{
|
||||||
top: flipRotatePanelPosition.top,
|
top: flipRotatePanelPosition.top,
|
||||||
left: flipRotatePanelPosition.left,
|
left: flipRotatePanelPosition.left,
|
||||||
maxWidth: `${flipRotatePanelPosition.maxWidth}px`,
|
maxWidth: `${Math.floor(
|
||||||
|
flipRotatePanelPosition.maxWidth / IMAGE_EDIT_PANEL_SCALE
|
||||||
|
)}px`,
|
||||||
|
transform: `scale(${IMAGE_EDIT_PANEL_SCALE})`,
|
||||||
|
transformOrigin: "top left",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex h-[82px] shrink-0 items-center gap-3 px-7">
|
<div className="flex h-[82px] shrink-0 items-center gap-3 px-7">
|
||||||
@ -7712,6 +7869,8 @@ export function ImageNode({
|
|||||||
style={{
|
style={{
|
||||||
top: anglePanelPosition.top,
|
top: anglePanelPosition.top,
|
||||||
left: anglePanelPosition.left,
|
left: anglePanelPosition.left,
|
||||||
|
transform: `scale(${IMAGE_EDIT_PANEL_SCALE})`,
|
||||||
|
transformOrigin: "top left",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
|
|||||||
@ -102,18 +102,24 @@ type FloatingSidebarRailProps = {
|
|||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
className?: string;
|
className?: string;
|
||||||
orientation?: "vertical" | "horizontal";
|
orientation?: "vertical" | "horizontal";
|
||||||
|
tone?: "dark" | "light";
|
||||||
};
|
};
|
||||||
|
|
||||||
export function FloatingSidebarRail({
|
export function FloatingSidebarRail({
|
||||||
children,
|
children,
|
||||||
className,
|
className,
|
||||||
orientation = "vertical",
|
orientation = "vertical",
|
||||||
|
tone = "dark",
|
||||||
}: FloatingSidebarRailProps) {
|
}: FloatingSidebarRailProps) {
|
||||||
const isHorizontal = orientation === "horizontal";
|
const isHorizontal = orientation === "horizontal";
|
||||||
|
const isLight = tone === "light";
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"pointer-events-auto flex items-center gap-1 border border-white/8 bg-[#17181d]/94 text-white shadow-[0_22px_60px_rgba(6,8,14,0.34),inset_0_1px_0_rgba(255,255,255,0.05)] backdrop-blur-2xl",
|
"pointer-events-auto flex items-center gap-1 backdrop-blur-2xl",
|
||||||
|
isLight
|
||||||
|
? "border border-black/8 bg-white/96 text-[#111827] shadow-[0_20px_46px_rgba(15,23,42,0.12)]"
|
||||||
|
: "border border-white/8 bg-[#17181d]/94 text-white shadow-[0_22px_60px_rgba(6,8,14,0.34),inset_0_1px_0_rgba(255,255,255,0.05)]",
|
||||||
isHorizontal
|
isHorizontal
|
||||||
? "h-[56px] w-auto flex-row overflow-hidden rounded-[22px] px-3 py-2"
|
? "h-[56px] w-auto flex-row overflow-hidden rounded-[22px] px-3 py-2"
|
||||||
: "w-[60px] flex-col overflow-y-auto rounded-[28px] px-2 py-2.5",
|
: "w-[60px] flex-col overflow-y-auto rounded-[28px] px-2 py-2.5",
|
||||||
|
|||||||
@ -443,12 +443,12 @@ export function LovartHome({
|
|||||||
!siteLogoDark?.trim() &&
|
!siteLogoDark?.trim() &&
|
||||||
Boolean(siteLogo?.trim());
|
Boolean(siteLogo?.trim());
|
||||||
const sidebarPopupBaseClass =
|
const sidebarPopupBaseClass =
|
||||||
"rounded-[24px] border border-white/10 bg-[#17181d]/96 p-2.5 text-white shadow-[0_24px_64px_rgba(6,8,14,0.4),inset_0_1px_0_rgba(255,255,255,0.04)] backdrop-blur-2xl";
|
"rounded-[24px] border border-black/8 bg-white/96 p-2.5 text-[#111827] shadow-[0_24px_64px_rgba(15,23,42,0.12)] backdrop-blur-xl";
|
||||||
const lovartSidebarButtonClass = (active = false) =>
|
const lovartSidebarButtonClass = (active = false) =>
|
||||||
cn(
|
cn(
|
||||||
"group flex h-11 w-11 items-center justify-center rounded-[16px] text-white/52 transition-all duration-200 hover:bg-white/[0.07] hover:text-white/88",
|
"group flex h-11 w-11 items-center justify-center rounded-[16px] text-[#6b7280] transition-all duration-200 hover:bg-black/[0.04] hover:text-[#111827]",
|
||||||
active &&
|
active &&
|
||||||
"bg-white/[0.1] text-white shadow-[inset_0_1px_0_rgba(255,255,255,0.08),0_10px_22px_rgba(0,0,0,0.22)]"
|
"bg-[#111827] text-white shadow-[0_10px_22px_rgba(15,23,42,0.18)]"
|
||||||
);
|
);
|
||||||
const [prompt, setPrompt] = useState("");
|
const [prompt, setPrompt] = useState("");
|
||||||
const [files, setFiles] = useState<UploadFileItem[]>([]);
|
const [files, setFiles] = useState<UploadFileItem[]>([]);
|
||||||
@ -1381,8 +1381,8 @@ export function LovartHome({
|
|||||||
<SidebarSvgIcon
|
<SidebarSvgIcon
|
||||||
iconUrl={item.iconUrl}
|
iconUrl={item.iconUrl}
|
||||||
fallback={FallbackIcon}
|
fallback={FallbackIcon}
|
||||||
imgClassName={cn(sizeClassName, "object-contain", "brightness-0")}
|
imgClassName={cn(sizeClassName, "object-contain", "brightness-0 invert")}
|
||||||
fallbackClassName={cn(sizeClassName, "text-black")}
|
fallbackClassName={cn(sizeClassName, "text-white")}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1394,12 +1394,11 @@ export function LovartHome({
|
|||||||
imgClassName={cn(
|
imgClassName={cn(
|
||||||
sizeClassName,
|
sizeClassName,
|
||||||
"object-contain",
|
"object-contain",
|
||||||
"brightness-0 invert",
|
options?.active ? "brightness-0 invert opacity-100" : "brightness-0 opacity-60"
|
||||||
options?.active ? "opacity-100" : "opacity-56"
|
|
||||||
)}
|
)}
|
||||||
fallbackClassName={cn(
|
fallbackClassName={cn(
|
||||||
sizeClassName,
|
sizeClassName,
|
||||||
options?.active ? "text-white" : "text-white/60"
|
options?.active ? "text-white" : "text-[#6b7280]"
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -1718,10 +1717,10 @@ export function LovartHome({
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={openNewCanvas}
|
onClick={openNewCanvas}
|
||||||
className="flex h-[60px] w-[60px] shrink-0 items-center justify-center rounded-[22px] border border-white/8 bg-[#17181d]/96 shadow-[0_22px_60px_rgba(6,8,14,0.34),inset_0_1px_0_rgba(255,255,255,0.05)] backdrop-blur-2xl transition-transform duration-200 hover:-translate-y-0.5 hover:bg-[#1b1d23]"
|
className="flex h-[60px] w-[60px] shrink-0 items-center justify-center rounded-[22px] border border-black/8 bg-white/96 shadow-[0_20px_46px_rgba(15,23,42,0.12)] backdrop-blur-xl transition-transform duration-200 hover:-translate-y-0.5 hover:bg-white"
|
||||||
title={getLovartSidebarItem("newProject").label}
|
title={getLovartSidebarItem("newProject").label}
|
||||||
>
|
>
|
||||||
<div className="flex h-10 w-10 items-center justify-center rounded-[14px] bg-white text-black shadow-[0_10px_18px_rgba(255,255,255,0.15)]">
|
<div className="flex h-10 w-10 items-center justify-center rounded-[14px] bg-[#111827] text-white shadow-[0_10px_20px_rgba(15,23,42,0.18)]">
|
||||||
{renderLovartSidebarIcon("newProject", {
|
{renderLovartSidebarIcon("newProject", {
|
||||||
filled: true,
|
filled: true,
|
||||||
sizeClassName: "h-[18px] w-[18px]",
|
sizeClassName: "h-[18px] w-[18px]",
|
||||||
@ -1734,7 +1733,7 @@ export function LovartHome({
|
|||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
) : null}
|
) : null}
|
||||||
<FloatingSidebarRail className="max-h-[calc(100vh-172px)]">
|
<FloatingSidebarRail className="max-h-[calc(100vh-172px)]" tone="light">
|
||||||
{isLovartSidebarItemEnabled("home") ? (
|
{isLovartSidebarItemEnabled("home") ? (
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
@ -1827,7 +1826,7 @@ export function LovartHome({
|
|||||||
align="start"
|
align="start"
|
||||||
className={`w-[300px] ${sidebarPopupBaseClass}`}
|
className={`w-[300px] ${sidebarPopupBaseClass}`}
|
||||||
>
|
>
|
||||||
<div className="px-2 pb-1 pt-1 text-xs font-medium text-white/42">
|
<div className="px-2 pb-1 pt-1 text-xs font-medium text-black/40">
|
||||||
{getLovartSidebarItem("tutorial").label}
|
{getLovartSidebarItem("tutorial").label}
|
||||||
</div>
|
</div>
|
||||||
<div className="max-h-[380px] space-y-1 overflow-y-auto">
|
<div className="max-h-[380px] space-y-1 overflow-y-auto">
|
||||||
@ -1836,10 +1835,10 @@ export function LovartHome({
|
|||||||
<button
|
<button
|
||||||
key={video.id}
|
key={video.id}
|
||||||
type="button"
|
type="button"
|
||||||
className="flex w-full items-center gap-2.5 rounded-2xl p-2.5 text-left transition hover:bg-white/[0.06]"
|
className="flex w-full items-center gap-2.5 rounded-2xl p-2.5 text-left transition hover:bg-black/[0.04]"
|
||||||
onClick={() => handleOpenTutorial(video)}
|
onClick={() => handleOpenTutorial(video)}
|
||||||
>
|
>
|
||||||
<div className="h-10 w-16 flex-shrink-0 overflow-hidden rounded-xl bg-white/[0.06]">
|
<div className="h-10 w-16 flex-shrink-0 overflow-hidden rounded-xl bg-black/[0.04]">
|
||||||
{video.coverUrl ? (
|
{video.coverUrl ? (
|
||||||
<img
|
<img
|
||||||
src={video.coverUrl}
|
src={video.coverUrl}
|
||||||
@ -1848,16 +1847,16 @@ export function LovartHome({
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex h-full w-full items-center justify-center">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
<PlayCircle className="h-4 w-4 text-white/40" />
|
<PlayCircle className="h-4 w-4 text-black/35" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="min-w-0 flex-1">
|
<div className="min-w-0 flex-1">
|
||||||
<div className="truncate text-[13px] font-medium text-white/88">
|
<div className="truncate text-[13px] font-medium text-black/85">
|
||||||
{video.title}
|
{video.title}
|
||||||
</div>
|
</div>
|
||||||
{video.description ? (
|
{video.description ? (
|
||||||
<div className="truncate text-[11px] text-white/42">
|
<div className="truncate text-[11px] text-black/42">
|
||||||
{video.description}
|
{video.description}
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
@ -1865,7 +1864,7 @@ export function LovartHome({
|
|||||||
</button>
|
</button>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<div className="px-2 py-3 text-[12px] text-white/42">暂无教程视频</div>
|
<div className="px-2 py-3 text-[12px] text-black/42">暂无教程视频</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</HoverCardContent>
|
</HoverCardContent>
|
||||||
@ -1994,7 +1993,7 @@ export function LovartHome({
|
|||||||
align="start"
|
align="start"
|
||||||
className={`w-[248px] ${sidebarPopupBaseClass}`}
|
className={`w-[248px] ${sidebarPopupBaseClass}`}
|
||||||
>
|
>
|
||||||
<div className="px-2 pb-1 pt-1 text-xs font-medium text-white/42">
|
<div className="px-2 pb-1 pt-1 text-xs font-medium text-black/40">
|
||||||
{getLovartSidebarItem("toolbox1").label}
|
{getLovartSidebarItem("toolbox1").label}
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
@ -2002,11 +2001,11 @@ export function LovartHome({
|
|||||||
<button
|
<button
|
||||||
key={link.id}
|
key={link.id}
|
||||||
type="button"
|
type="button"
|
||||||
className="flex w-full items-center justify-between rounded-2xl px-3 py-2.5 text-left text-[13px] text-white/82 transition hover:bg-white/[0.06]"
|
className="flex w-full items-center justify-between rounded-2xl px-3 py-2.5 text-left text-[13px] text-black/80 transition hover:bg-black/[0.04]"
|
||||||
onClick={() => openNavLink(link.url)}
|
onClick={() => openNavLink(link.url)}
|
||||||
>
|
>
|
||||||
<span className="line-clamp-1">{link.name}</span>
|
<span className="line-clamp-1">{link.name}</span>
|
||||||
<ArrowRight className="h-3.5 w-3.5 text-white/30" />
|
<ArrowRight className="h-3.5 w-3.5 text-black/30" />
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@ -2031,7 +2030,7 @@ export function LovartHome({
|
|||||||
align="start"
|
align="start"
|
||||||
className={`w-[248px] ${sidebarPopupBaseClass}`}
|
className={`w-[248px] ${sidebarPopupBaseClass}`}
|
||||||
>
|
>
|
||||||
<div className="px-2 pb-1 pt-1 text-xs font-medium text-white/42">
|
<div className="px-2 pb-1 pt-1 text-xs font-medium text-black/40">
|
||||||
{getLovartSidebarItem("toolbox2").label}
|
{getLovartSidebarItem("toolbox2").label}
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
@ -2039,11 +2038,11 @@ export function LovartHome({
|
|||||||
<button
|
<button
|
||||||
key={link.id}
|
key={link.id}
|
||||||
type="button"
|
type="button"
|
||||||
className="flex w-full items-center justify-between rounded-2xl px-3 py-2.5 text-left text-[13px] text-white/82 transition hover:bg-white/[0.06]"
|
className="flex w-full items-center justify-between rounded-2xl px-3 py-2.5 text-left text-[13px] text-black/80 transition hover:bg-black/[0.04]"
|
||||||
onClick={() => openNavLink(link.url)}
|
onClick={() => openNavLink(link.url)}
|
||||||
>
|
>
|
||||||
<span className="line-clamp-1">{link.name}</span>
|
<span className="line-clamp-1">{link.name}</span>
|
||||||
<ArrowRight className="h-3.5 w-3.5 text-white/30" />
|
<ArrowRight className="h-3.5 w-3.5 text-black/30" />
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -699,6 +699,7 @@ export type CanvasToolbarItemKey =
|
|||||||
export type CanvasToolbarItemConfig = {
|
export type CanvasToolbarItemConfig = {
|
||||||
label: string;
|
label: string;
|
||||||
iconUrl: string;
|
iconUrl: string;
|
||||||
|
enabled: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CanvasToolbarConfig = {
|
export type CanvasToolbarConfig = {
|
||||||
@ -710,6 +711,7 @@ const DEFAULT_ITEM_BY_KEY = DEFAULT_CANVAS_TOOLBAR_ITEMS.reduce(
|
|||||||
acc[item.key] = {
|
acc[item.key] = {
|
||||||
label: item.label,
|
label: item.label,
|
||||||
iconUrl: "",
|
iconUrl: "",
|
||||||
|
enabled: true,
|
||||||
};
|
};
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
@ -750,6 +752,8 @@ export function normalizeCanvasToolbarConfig(
|
|||||||
items[defaultItem.key] = {
|
items[defaultItem.key] = {
|
||||||
label,
|
label,
|
||||||
iconUrl,
|
iconUrl,
|
||||||
|
enabled:
|
||||||
|
typeof rawItem.enabled === "boolean" ? rawItem.enabled : true,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -768,3 +772,10 @@ export function getCanvasToolbarItem(
|
|||||||
): CanvasToolbarItemConfig {
|
): CanvasToolbarItemConfig {
|
||||||
return config?.items?.[key] || DEFAULT_ITEM_BY_KEY[key];
|
return config?.items?.[key] || DEFAULT_ITEM_BY_KEY[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isCanvasToolbarItemEnabled(
|
||||||
|
config: CanvasToolbarConfig | null | undefined,
|
||||||
|
key: CanvasToolbarItemKey
|
||||||
|
): boolean {
|
||||||
|
return getCanvasToolbarItem(config, key).enabled !== false;
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user