mirror of
https://github.com/wavetermdev/backup.git
synced 2026-08-05 13:57:07 -07:00
Make IconButton its own element, move CopyButton to use it (#357)
This commit is contained in:
@@ -133,21 +133,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.iconbutton {
|
||||
cursor: pointer;
|
||||
opacity: 0.7;
|
||||
align-items: center;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
cursor: default;
|
||||
opacity: 0.45 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.connection-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
ConnectionButton,
|
||||
ControllerStatusIcon,
|
||||
getBlockHeaderIcon,
|
||||
IconButton,
|
||||
Input,
|
||||
} from "@/app/block/blockutil";
|
||||
import { Button } from "@/app/element/button";
|
||||
@@ -29,6 +28,7 @@ import {
|
||||
} from "@/app/store/global";
|
||||
import * as services from "@/app/store/services";
|
||||
import { WshServer } from "@/app/store/wshserver";
|
||||
import { IconButton } from "@/element/iconbutton";
|
||||
import { MagnifyIcon } from "@/element/magnify";
|
||||
import { NodeModel } from "@/layout/index";
|
||||
import * as keyutil from "@/util/keyutil";
|
||||
@@ -88,7 +88,7 @@ function handleHeaderContextMenu(
|
||||
ContextMenuModel.showContextMenu(menu, e);
|
||||
}
|
||||
|
||||
function getViewIconElem(viewIconUnion: string | HeaderIconButton, blockData: Block): JSX.Element {
|
||||
function getViewIconElem(viewIconUnion: string | IconButtonDecl, blockData: Block): JSX.Element {
|
||||
if (viewIconUnion == null || typeof viewIconUnion === "string") {
|
||||
const viewIcon = viewIconUnion as string;
|
||||
return <div className="block-frame-view-icon">{getBlockHeaderIcon(viewIcon, blockData)}</div>;
|
||||
@@ -99,7 +99,7 @@ function getViewIconElem(viewIconUnion: string | HeaderIconButton, blockData: Bl
|
||||
|
||||
const OptMagnifyButton = React.memo(
|
||||
({ magnified, toggleMagnify, disabled }: { magnified: boolean; toggleMagnify: () => void; disabled: boolean }) => {
|
||||
const magnifyDecl: HeaderIconButton = {
|
||||
const magnifyDecl: IconButtonDecl = {
|
||||
elemtype: "iconbutton",
|
||||
icon: <MagnifyIcon enabled={magnified} />,
|
||||
title: magnified ? "Minimize" : "Magnify",
|
||||
@@ -124,7 +124,7 @@ function computeEndIcons(
|
||||
if (endIconButtons && endIconButtons.length > 0) {
|
||||
endIconsElem.push(...endIconButtons.map((button, idx) => <IconButton key={idx} decl={button} />));
|
||||
}
|
||||
const settingsDecl: HeaderIconButton = {
|
||||
const settingsDecl: IconButtonDecl = {
|
||||
elemtype: "iconbutton",
|
||||
icon: "cog",
|
||||
title: "Settings",
|
||||
@@ -139,7 +139,7 @@ function computeEndIcons(
|
||||
disabled={magnifyDisabled}
|
||||
/>
|
||||
);
|
||||
const closeDecl: HeaderIconButton = {
|
||||
const closeDecl: IconButtonDecl = {
|
||||
elemtype: "iconbutton",
|
||||
icon: "xmark-large",
|
||||
title: "Close",
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { NumActiveConnColors } from "@/app/block/blockframe";
|
||||
import { useLongClick } from "@/app/hook/useLongClick";
|
||||
import { getConnStatusAtom, waveEventSubscribe, WOS } from "@/app/store/global";
|
||||
import * as services from "@/app/store/services";
|
||||
import { makeORef } from "@/app/store/wos";
|
||||
@@ -139,20 +138,6 @@ export function getBlockHeaderIcon(blockIcon: string, blockData: Block): React.R
|
||||
return blockIconElem;
|
||||
}
|
||||
|
||||
export const IconButton = React.memo(({ decl, className }: { decl: HeaderIconButton; className?: string }) => {
|
||||
const buttonRef = React.useRef<HTMLDivElement>(null);
|
||||
useLongClick(buttonRef, decl.click, decl.longClick, decl.disabled);
|
||||
return (
|
||||
<div
|
||||
ref={buttonRef}
|
||||
className={clsx("iconbutton", className, decl.className, { disabled: decl.disabled })}
|
||||
title={decl.title}
|
||||
>
|
||||
{typeof decl.icon === "string" ? <i className={util.makeIconClass(decl.icon, true)} /> : decl.icon}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
interface ConnectionButtonProps {
|
||||
connection: string;
|
||||
changeConnModalAtom: jotai.PrimitiveAtom<boolean>;
|
||||
|
||||
@@ -2,15 +2,10 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
.copy-button {
|
||||
padding: 5px 5px !important;
|
||||
opacity: 0.5;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.copied {
|
||||
opacity: 1;
|
||||
color: var(--success-color);
|
||||
i {
|
||||
color: var(--success-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
|
||||
import { clsx } from "clsx";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { Button } from "./button";
|
||||
import "./copybutton.less";
|
||||
import { IconButton } from "./iconbutton";
|
||||
|
||||
type CopyButtonProps = {
|
||||
title: string;
|
||||
@@ -43,13 +43,16 @@ const CopyButton = ({ title, className, onClick }: CopyButtonProps) => {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Button
|
||||
onClick={handleOnClick}
|
||||
className={clsx("copy-button secondary ghost", className, { copied: isCopied })}
|
||||
title={title}
|
||||
>
|
||||
{isCopied ? <i className="fa-sharp fa-solid fa-check"></i> : <i className="fa-sharp fa-solid fa-copy"></i>}
|
||||
</Button>
|
||||
<IconButton
|
||||
decl={{
|
||||
elemtype: "iconbutton",
|
||||
icon: isCopied ? "check" : "copy",
|
||||
title,
|
||||
className: clsx("copy-button", { copied: isCopied }),
|
||||
click: handleOnClick,
|
||||
}}
|
||||
className={className}
|
||||
></IconButton>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
.iconbutton {
|
||||
cursor: pointer;
|
||||
opacity: 0.7;
|
||||
align-items: center;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
cursor: default;
|
||||
opacity: 0.45 !important;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { useLongClick } from "@/app/hook/useLongClick";
|
||||
import { makeIconClass } from "@/util/util";
|
||||
import clsx from "clsx";
|
||||
import { memo, useRef } from "react";
|
||||
import "./iconbutton.less";
|
||||
|
||||
export const IconButton = memo(({ decl, className }: { decl: IconButtonDecl; className?: string }) => {
|
||||
const buttonRef = useRef<HTMLDivElement>(null);
|
||||
useLongClick(buttonRef, decl.click, decl.longClick, decl.disabled);
|
||||
return (
|
||||
<div
|
||||
ref={buttonRef}
|
||||
className={clsx("iconbutton", className, decl.className, { disabled: decl.disabled })}
|
||||
title={decl.title}
|
||||
>
|
||||
{typeof decl.icon === "string" ? <i className={makeIconClass(decl.icon, true)} /> : decl.icon}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
@@ -85,29 +85,12 @@
|
||||
top: 0;
|
||||
right: 0;
|
||||
border-radius: 4px;
|
||||
backdrop-filter: blur(8px);
|
||||
margin: 2px 2px;
|
||||
padding: 4px 4px;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
|
||||
i {
|
||||
color: var(--line-actions-inactive-color);
|
||||
margin-left: 4px;
|
||||
|
||||
&:first-child {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--line-actions-active-color);
|
||||
}
|
||||
|
||||
&.fa-check {
|
||||
color: var(--success-color);
|
||||
}
|
||||
|
||||
&.fa-square-terminal {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
&:hover .codeblock-actions {
|
||||
|
||||
@@ -17,6 +17,7 @@ import rehypeSlug from "rehype-slug";
|
||||
import RemarkFlexibleToc, { TocItem } from "remark-flexible-toc";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import { openLink } from "../store/global";
|
||||
import { IconButton } from "./iconbutton";
|
||||
import "./markdown.less";
|
||||
|
||||
const Link = ({
|
||||
@@ -90,7 +91,16 @@ const CodeBlock = ({ children, onClickExecute }: CodeBlockProps) => {
|
||||
{children}
|
||||
<div className="codeblock-actions">
|
||||
<CopyButton onClick={handleCopy} title="Copy" />
|
||||
{onClickExecute && <i className="fa-regular fa-square-terminal" onClick={handleExecute}></i>}
|
||||
{onClickExecute && (
|
||||
<IconButton
|
||||
decl={{
|
||||
elemtype: "iconbutton",
|
||||
icon: "square-terminal",
|
||||
click: handleExecute,
|
||||
className: "fa-regular",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</pre>
|
||||
);
|
||||
|
||||
@@ -183,7 +183,7 @@ Other useful metadata values to override block titles, icons, colors, themes, et
|
||||
class HelpViewModel implements ViewModel {
|
||||
viewType: string;
|
||||
showTocAtom: PrimitiveAtom<boolean>;
|
||||
endIconButtons: Atom<HeaderIconButton[]>;
|
||||
endIconButtons: Atom<IconButtonDecl[]>;
|
||||
|
||||
constructor() {
|
||||
this.viewType = "help";
|
||||
@@ -195,7 +195,7 @@ class HelpViewModel implements ViewModel {
|
||||
title: "Table of Contents",
|
||||
click: () => this.showTocToggle(),
|
||||
},
|
||||
] as HeaderIconButton[]);
|
||||
] as IconButtonDecl[]);
|
||||
}
|
||||
|
||||
showTocToggle() {
|
||||
|
||||
@@ -80,11 +80,11 @@ export class PreviewModel implements ViewModel {
|
||||
blockId: string;
|
||||
nodeModel: NodeModel;
|
||||
blockAtom: jotai.Atom<Block>;
|
||||
viewIcon: jotai.Atom<string | HeaderIconButton>;
|
||||
viewIcon: jotai.Atom<string | IconButtonDecl>;
|
||||
viewName: jotai.Atom<string>;
|
||||
viewText: jotai.Atom<HeaderElem[]>;
|
||||
preIconButton: jotai.Atom<HeaderIconButton>;
|
||||
endIconButtons: jotai.Atom<HeaderIconButton[]>;
|
||||
preIconButton: jotai.Atom<IconButtonDecl>;
|
||||
endIconButtons: jotai.Atom<IconButtonDecl[]>;
|
||||
previewTextRef: React.RefObject<HTMLDivElement>;
|
||||
editMode: jotai.Atom<boolean>;
|
||||
canPreview: jotai.PrimitiveAtom<boolean>;
|
||||
@@ -294,7 +294,7 @@ export class PreviewModel implements ViewModel {
|
||||
icon: "arrows-rotate",
|
||||
click: () => this.refreshCallback?.(),
|
||||
},
|
||||
] as HeaderIconButton[];
|
||||
] as IconButtonDecl[];
|
||||
} else if (!isCeView && mimeType.startsWith("text/markdown")) {
|
||||
return [
|
||||
{
|
||||
@@ -303,7 +303,7 @@ export class PreviewModel implements ViewModel {
|
||||
title: "Table of Contents",
|
||||
click: () => this.markdownShowTocToggle(),
|
||||
},
|
||||
] as HeaderIconButton[];
|
||||
] as IconButtonDecl[];
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -44,11 +44,11 @@ export class WaveAiModel implements ViewModel {
|
||||
viewType: string;
|
||||
blockId: string;
|
||||
blockAtom: Atom<Block>;
|
||||
viewIcon?: Atom<string | HeaderIconButton>;
|
||||
viewIcon?: Atom<string | IconButtonDecl>;
|
||||
viewName?: Atom<string>;
|
||||
viewText?: Atom<string | HeaderElem[]>;
|
||||
preIconButton?: Atom<HeaderIconButton>;
|
||||
endIconButtons?: Atom<HeaderIconButton[]>;
|
||||
preIconButton?: Atom<IconButtonDecl>;
|
||||
endIconButtons?: Atom<IconButtonDecl[]>;
|
||||
messagesAtom: PrimitiveAtom<Array<ChatMessageType>>;
|
||||
addMessageAtom: WritableAtom<unknown, [message: ChatMessageType], void>;
|
||||
updateLastMessageAtom: WritableAtom<unknown, [text: string, isUpdating: boolean], void>;
|
||||
|
||||
@@ -18,7 +18,7 @@ export class WebViewModel implements ViewModel {
|
||||
viewType: string;
|
||||
blockId: string;
|
||||
blockAtom: jotai.Atom<Block>;
|
||||
viewIcon: jotai.Atom<string | HeaderIconButton>;
|
||||
viewIcon: jotai.Atom<string | IconButtonDecl>;
|
||||
viewName: jotai.Atom<string>;
|
||||
viewText: jotai.Atom<HeaderElem[]>;
|
||||
url: jotai.PrimitiveAtom<string>;
|
||||
|
||||
Vendored
+5
-5
@@ -148,9 +148,9 @@ declare global {
|
||||
|
||||
type SubjectWithRef<T> = rxjs.Subject<T> & { refCount: number; release: () => void };
|
||||
|
||||
type HeaderElem = HeaderIconButton | HeaderText | HeaderInput | HeaderDiv | HeaderTextButton | ConnectionButton;
|
||||
type HeaderElem = IconButtonDecl | HeaderText | HeaderInput | HeaderDiv | HeaderTextButton | ConnectionButton;
|
||||
|
||||
type HeaderIconButton = {
|
||||
type IconButtonDecl = {
|
||||
elemtype: "iconbutton";
|
||||
icon: string | React.ReactNode;
|
||||
className?: string;
|
||||
@@ -207,11 +207,11 @@ declare global {
|
||||
|
||||
interface ViewModel {
|
||||
viewType: string;
|
||||
viewIcon?: jotai.Atom<string | HeaderIconButton>;
|
||||
viewIcon?: jotai.Atom<string | IconButtonDecl>;
|
||||
viewName?: jotai.Atom<string>;
|
||||
viewText?: jotai.Atom<string | HeaderElem[]>;
|
||||
preIconButton?: jotai.Atom<HeaderIconButton>;
|
||||
endIconButtons?: jotai.Atom<HeaderIconButton[]>;
|
||||
preIconButton?: jotai.Atom<IconButtonDecl>;
|
||||
endIconButtons?: jotai.Atom<IconButtonDecl[]>;
|
||||
blockBg?: jotai.Atom<MetaType>;
|
||||
manageConnection?: jotai.Atom<boolean>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user