Compare commits

..
Author SHA1 Message Date
bflatastic 6526cac55e dialog, model buttons, ratio button 2025-02-26 17:13:57 +07:00
8 changed files with 24 additions and 85 deletions
@@ -4,8 +4,6 @@ import { SelectionManager } from "../NodesManagers";
import { highlightStrokeWidth, primaryOrange } from "./constants";
import { NodeData, Position } from "../types";
import { RealTimeDrawEngine } from "../RenderingPrimitives/RealTimeDrawEngine";
import { MouseEventHandler } from "react";
import { KonvaEventObject } from "konva/lib/Node";
export abstract class BaseNode {
protected selectionManagerRef: SelectionManager;
@@ -153,18 +151,15 @@ export abstract class BaseNode {
}
};
const handleRightClick = (e: KonvaEventObject<MouseEvent>) => {
const handleRightClick = () => {
this.selectionManagerRef.clearSelection();
this.selectionManagerRef.selectNode(this, undefined, {
show: true,
at: { x: e.evt.x, y: e.evt.y }
});
this.selectionManagerRef.selectNode(this, undefined, true);
}
this.kNode.on("contextmenu", (e) => {
console.log("CONTEXT MENU", e);
e.evt.preventDefault();
handleRightClick(e);
handleRightClick();
});
this.kNode.on("mousedown", (e) => {
@@ -80,12 +80,7 @@ export class SelectionManager {
public isDisabled() {
return this.disable;
}
public selectNode(node: MediaNode, doNotDraw?: boolean, contextMenu: {
show?: boolean,
at?: { x: number, y: number }
} = {
show: false,
}): boolean {
public selectNode(node: MediaNode, doNotDraw?: boolean, showContextMenu = false): boolean {
if (
this.disabled || // no-op when disabled
this.selectedNodes.has(node) || // if the node is already selected
@@ -106,9 +101,9 @@ export class SelectionManager {
this.updateNodeTransformer();
this.updateContextComponents();
console.log("SelectionManager > selectNode > showContextMenu", contextMenu.show);
if (contextMenu.show) {
this.showContextComponents(contextMenu.at);
console.log("SelectionManager > selectNode > showContextMenu", showContextMenu);
if (showContextMenu) {
this.showContextComponents();
}
if (!doNotDraw) {
@@ -271,15 +266,10 @@ export class SelectionManager {
uiAccess.loadingBar.hide();
}
public showContextComponents(at?: { x: number, y: number }) {
public showContextComponents() {
const showOrUpdate = uiAccess.toolbarNode.isShowing()
? uiAccess.toolbarNode.update
: uiAccess.toolbarNode.show;
// If a position is received, set it
// Otherwise use the previous position
const position = at ? at : uiAccess.toolbarNode.signal.value.position;
const node = this.selectedNodes.values().next().value;
if (node === undefined) {
this.hideContextComponents();
@@ -291,7 +281,6 @@ export class SelectionManager {
knodeIds: [node.kNode.id()],
locked: node.isLocked(),
buttonStates: getImageNodeButtonStates({ locked: node.isLocked() }),
position: position
});
}
else if (node instanceof ShapeNode) {
@@ -300,8 +289,7 @@ export class SelectionManager {
knodeIds: [node.kNode.id()],
locked: node.isLocked(),
buttonStates: getShapeNodeButtonStates({ locked: node.isLocked() }),
color: node.color,
position: position
color: node.color
});
}
else if (node instanceof TextNode) {
@@ -310,14 +298,12 @@ export class SelectionManager {
locked: node.isLocked(),
buttonStates: getTextNodeButtonStates({ locked: node.isLocked() }),
color: node.getNodeData({ x: 0, y: 0 })?.textNodeData?.color ?? "#000000",
position: position
});
}
else if (node instanceof VideoNode) {
showOrUpdate({
locked: node.isLocked(),
buttonStates: getVideoNodeButtonStates({ locked: node.isLocked() }),
position: position
});
}
@@ -333,7 +319,6 @@ export class SelectionManager {
showOrUpdate({
locked: node.isLocked(),
buttonStates: getMultiSelectButtonStates({ locked: node.isLocked() }),
position: position
});
}
}
@@ -363,7 +348,6 @@ export class SelectionManager {
// console.log("setting lock");
uiAccess.toolbarNode.setLocked(node.isLocked());
}
console.debug("Setting context position to:", coord)
uiAccess.toolbarNode.setPosition({
x: coord.x,
y: coord.y,
@@ -75,7 +75,7 @@ export const KonvaRootComponent = ({
resetAll={appUiContext.resetAll}
/>
{/* <ContextualLoadingBar /> */}
<ContextualLoadingBar />
<ContextualToolbarNode />
{/* <ContextualButtonRetry /> */}
</>
@@ -33,7 +33,6 @@ export const SignaledPromptText = ({}) => {
onChange={onTextChanged}
value={textContent}
spellCheck={false}
forceBlurOnOutsideClick={true}
/>
</div>
);
@@ -26,7 +26,7 @@ export const Sandbox = () => {
</div>
<ContextualToolbarNode />
{/* <ContextualLoadingBar /> */}
<ContextualLoadingBar />
<ContextualButtonRetry />
</div>
);
+10 -10
View File
@@ -15,8 +15,8 @@ interface SliderProps {
tooltipContent?: ReactNode;
suffix?: string;
innerLabel?: string;
showDecrement?: boolean;
showIncrement?: boolean;
showDecrement?: boolean,
showIncrement?: boolean,
}
export const Slider = ({
@@ -31,7 +31,7 @@ export const Slider = ({
suffix,
innerLabel,
showDecrement,
showIncrement,
showIncrement
}: SliderProps) => {
const [localValue, setLocalValue] = useState(value);
const sliderRef = useRef<HTMLDivElement>(null);
@@ -47,7 +47,7 @@ export const Slider = ({
const clampedValue = Math.min(Math.max(roundedValue, min), max);
setLocalValue(clampedValue);
onChange(clampedValue);
};
}
const updatePosition = (x: number) => {
if (!sliderRef.current) return;
@@ -93,11 +93,11 @@ export const Slider = ({
const handleDecrement = () => {
setClampedValue(localValue - step);
};
}
const handleIncrement = () => {
setClampedValue(localValue + step);
};
}
const percentage = ((localValue - min) / (max - min)) * 100;
const displayValue =
@@ -109,7 +109,7 @@ export const Slider = ({
{showDecrement && (
<Button
icon={faMinus}
className="my-auto mr-1 size-6 rounded-full bg-transparent text-white/80 hover:bg-white/10 focus-visible:outline-primary active:bg-primary/30"
className="size-6 text-white/80 bg-transparent rounded-full hover:bg-white/10 focus-visible:outline-primary active:bg-primary/30 my-auto mr-1"
onClick={handleDecrement}
/>
)}
@@ -125,7 +125,7 @@ export const Slider = ({
>
<div
className={twMerge(
"absolute h-full bg-primary/30 transition-colors duration-300 group-hover:bg-primary/50",
"absolute h-7 bg-primary/30 transition-colors duration-300 group-hover:bg-primary/50",
isDragging && "!bg-primary/50",
)}
style={{ width: `${percentage}%` }}
@@ -142,7 +142,7 @@ export const Slider = ({
)}
<div
className={twMerge(
"absolute right-0 top-1/2 mr-1 h-4 w-0.5 -translate-y-1/2 rounded-full",
"absolute right-0 top-1/2 mr-1.5 h-3.5 w-0.5 -translate-y-1/2",
isDragging ? "bg-white" : "bg-white/50",
)}
onMouseDown={handleMouseDown}
@@ -155,7 +155,7 @@ export const Slider = ({
{showIncrement && (
<Button
icon={faPlus}
className="my-auto ml-1 size-6 rounded-full bg-transparent text-white/80 hover:bg-white/10 focus-visible:outline-primary active:bg-primary/30"
className="size-6 text-white/80 bg-transparent rounded-full hover:bg-white/10 focus-visible:outline-primary active:bg-primary/30 my-auto ml-1"
onClick={handleIncrement}
/>
)}
@@ -1,4 +1,4 @@
import { TextareaHTMLAttributes, forwardRef, useEffect, useRef } from "react";
import { TextareaHTMLAttributes, forwardRef } from "react";
import { twMerge } from "tailwind-merge";
import { kebabCase } from "~/utilities";
@@ -21,58 +21,20 @@ export interface TextareaInterface
extends TextareaHTMLAttributes<HTMLTextAreaElement> {
label?: string;
resize?: ResizeType;
forceBlurOnOutsideClick?: boolean;
}
export const Textarea = forwardRef<HTMLTextAreaElement, TextareaInterface>(
(
{
className,
label,
resize = "vertical",
id,
forceBlurOnOutsideClick,
...rest
}: TextareaInterface,
{ className, label, resize = "vertical", id, ...rest }: TextareaInterface,
ref,
) => {
const resizeStyle = resizeStyles[resize];
const textareaRef = useRef<HTMLTextAreaElement>(null);
// Function to blur the textarea when clicking outside of it
useEffect(() => {
if (!forceBlurOnOutsideClick) return;
const handleClickOutside = (event: MouseEvent) => {
if (
textareaRef.current &&
!textareaRef.current.contains(event.target as Node)
) {
textareaRef.current.blur();
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [forceBlurOnOutsideClick]);
return (
<div className="flex flex-col">
{label && <label htmlFor={id ? id : kebabCase(label)}>{label}</label>}
<textarea
ref={(node) => {
if (typeof ref === "function") {
ref(node);
} else if (ref) {
(ref as any).current = node;
}
if (textareaRef) {
(textareaRef as any).current = node;
}
}}
ref={ref}
id={id ? id : label ? kebabCase(label) : undefined}
className={twMerge(
"rounded-lg border border-ui-border px-4 py-2.5 text-white outline-none focus:outline-none",
@@ -18,7 +18,6 @@ export interface ContextualToolbarProps extends ContextualUi {
lockDisabled: boolean;
buttonStates: ButtonStates;
color: string;
position: { x: number, y: number };
}
interface PartialContextualToolbarProps
extends Partial<Omit<ContextualToolbarProps, "buttonStates">> {