aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcodetorso <[email protected]>2024-06-22 23:10:28 +0530
committercodetorso <[email protected]>2024-06-22 23:10:28 +0530
commitbecb3064c2c9cc137dbbcfdfa464c8bb71668832 (patch)
tree85e6e9875dd904f811e3fada454039ac6f47a3a9
parentimprove canvas drag and drop make sidepanel work (diff)
downloadsupermemory-becb3064c2c9cc137dbbcfdfa464c8bb71668832.tar.xz
supermemory-becb3064c2c9cc137dbbcfdfa464c8bb71668832.zip
Unreadable Canvas code, jk 😂
-rw-r--r--apps/web/app/(canvas)/canvas.css3
-rw-r--r--apps/web/app/(canvas)/canvas.tsx4
-rw-r--r--apps/web/app/(canvas)/canvas/page.tsx76
-rw-r--r--apps/web/app/(canvas)/dropComponent.tsx134
-rw-r--r--apps/web/app/(canvas)/lib/createEmbeds.ts45
-rw-r--r--apps/web/app/(canvas)/lib/loadSnap.ts7
-rw-r--r--apps/web/app/(canvas)/textCard.tsx66
-rw-r--r--package.json1
-rw-r--r--packages/ui/components/canvas/draggableComponent.tsx2
-rw-r--r--packages/ui/shadcn/switch.tsx29
10 files changed, 319 insertions, 48 deletions
diff --git a/apps/web/app/(canvas)/canvas.css b/apps/web/app/(canvas)/canvas.css
new file mode 100644
index 00000000..f674e48f
--- /dev/null
+++ b/apps/web/app/(canvas)/canvas.css
@@ -0,0 +1,3 @@
+.tlui-dialog__overlay {
+ position: fixed;
+}
diff --git a/apps/web/app/(canvas)/canvas.tsx b/apps/web/app/(canvas)/canvas.tsx
index a8dc312b..72a23c92 100644
--- a/apps/web/app/(canvas)/canvas.tsx
+++ b/apps/web/app/(canvas)/canvas.tsx
@@ -4,6 +4,7 @@ import { createAssetFromUrl } from "./lib/createAssetUrl";
import "tldraw/tldraw.css";
import { components } from "./enabledComp";
import { twitterCardUtil } from "./twitterCard";
+import { textCardUtil } from "./textCard";
import createEmbedsFromUrl from "./lib/createEmbeds";
import { loadRemoteSnapshot } from "./lib/loadSnap";
import { SaveStatus } from "./savesnap";
@@ -11,6 +12,7 @@ import { getAssetUrls } from "@tldraw/assets/selfHosted";
import { memo } from "react";
import DragContext from "./lib/context";
import DropZone from "./dropComponent";
+import './canvas.css'
export const Canvas = memo(() => {
const [isDraggingOver, setIsDraggingOver] = useState<boolean>(false);
@@ -82,7 +84,7 @@ const TldrawComponent =memo(() => {
assetUrls={assetUrls}
components={components}
store={storeWithStatus}
- shapeUtils={[twitterCardUtil]}
+ shapeUtils={[twitterCardUtil, textCardUtil]}
onMount={handleMount}
>
<div className="absolute left-1/2 top-0 z-[1000000] flex -translate-x-1/2 gap-2 bg-[#2C3439] text-[#B3BCC5]">
diff --git a/apps/web/app/(canvas)/canvas/page.tsx b/apps/web/app/(canvas)/canvas/page.tsx
index ea3cee1b..533ed33c 100644
--- a/apps/web/app/(canvas)/canvas/page.tsx
+++ b/apps/web/app/(canvas)/canvas/page.tsx
@@ -7,9 +7,10 @@ import { SettingsIcon, DragIcon } from "@repo/ui/icons";
import DraggableComponentsContainer from "@repo/ui/components/canvas/draggableComponent";
import { AutocompleteIcon, blockIcon } from "@repo/ui/icons";
import Image from "next/image";
+import { Switch } from "@repo/ui/shadcn/switch";
+import { Label } from "@repo/ui/shadcn/label";
function page() {
- const [value, setValue] = useState("");
const [fullScreen, setFullScreen] = useState(false);
const [visible, setVisible] = useState(true);
@@ -42,34 +43,23 @@ function page() {
Change Filters
<Image src={SettingsIcon} alt="setting-icon" />
</div>
- <div className="px-3 py-5">
- <input
- placeholder="search..."
- onChange={(e) => {
- setValue(e.target.value);
- }}
- value={value}
- // rows={1}
- className="w-full resize-none rounded-xl bg-[#151515] px-3 py-4 text-xl text-[#989EA4] outline-none focus:outline-none sm:max-h-52"
- />
- </div>
{visible ? (
<SidePanel />
) : (
- <h1 className="text-center py-10 text-xl">Need more space to show!</h1>
+ <h1 className="text-center py-10 text-xl">
+ Need more space to show!
+ </h1>
)}
</div>
</Panel>
<PanelResizeHandle
className={`relative flex items-center transition-all justify-center ${!fullScreen && "px-1"}`}
>
- {/* <div className="absolute z-[1000000] top-1/2 -translate-y-1/2"> */}
<div
className={`rounded-lg bg-[#2F363B] ${!fullScreen && "px-1"} transition-all py-2`}
>
<Image src={DragIcon} alt="drag-icon" />
</div>
- {/* </div> */}
</PanelResizeHandle>
<Panel className="relative" defaultSize={70} minSize={60}>
<div
@@ -84,26 +74,52 @@ function page() {
);
}
-const content= [
+function SidePanel() {
+ const [value, setValue] = useState("");
+ const [dragAsText, setDragAsText] = useState(false);
+ return (
+ <>
+ <div className="px-3 py-5">
+ <input
+ placeholder="search..."
+ onChange={(e) => {
+ setValue(e.target.value);
+ }}
+ value={value}
+ // rows={1}
+ className="w-full resize-none rounded-xl bg-[#151515] px-3 py-4 text-xl text-[#989EA4] outline-none focus:outline-none sm:max-h-52"
+ />
+ </div>
+ <div className="flex items-center justify-end px-3 py-4">
+ <Switch
+ className="bg-[#151515] data-[state=unchecked]:bg-red-400 data-[state=checked]:bg-blue-400"
+ onCheckedChange={(e) => setDragAsText(e)}
+ id="drag-text-mode"
+ />
+ <Label htmlFor="drag-text-mode">Drag as Text</Label>
+ </div>
+ <DraggableComponentsContainer content={content} />
+ </>
+ );
+}
+
+export default page;
+
+const content = [
{
- content: "Nvidia currently dominates the GPU hardware market, with a market share over 97%. This has led some to argue...",
+ content:
+ "Regional growth patterns diverge, with strong performance in the United States and several emerging markets, contrasted by weaker prospects in many advanced economies, particularly in Europe (World Economic Forum) (OECD). The rapid adoption of artificial intelligence (AI) is expected to drive productivity growth, especially in advanced economies, potentially mitigating labor shortages and boosting income levels in emerging markets (World Economic Forum) (OECD). However, ongoing geopolitical tensions and economic fragmentation are likely to maintain a level of uncertainty and volatility in the global economy (World Economic Forum.",
icon: AutocompleteIcon,
iconAlt: "Autocomplete",
- extraInfo: "Page Url: https://www.cnbc.com/2024/05/23/nvidia-keeps-hitting-records-can-investors-still-buy-the-stock.html?&qsearchterm=nvidia",
+ extraInfo:
+ "Page Url: https://chatgpt.com/c/762cd44e-1752-495b-967a-aa3c23c6024a",
},
{
- content: "Nvidia currently dominates the GPU hardware market, with a market share over 97%. This has led some to argue...",
+ content:
+ "As of mid-2024, the global economy is experiencing modest growth with significant regional disparities. Global GDP growth is projected to be around 3.1% in 2024, rising slightly to 3.2% in 2025. This performance, although below the pre-pandemic average, reflects resilience despite various economic pressures, including tight monetary conditions and geopolitical tensions (IMF)(OECD) Inflation is moderating faster than expected, with global headline inflation projected to fall to 5.8% in 2024 and 4.4% in 2025, contributing to improving real incomes and positive trade growth (IMF) (OECD)",
icon: blockIcon,
iconAlt: "Autocomplete",
- extraInfo: "Page Url: https://www.cnbc.com/2024/05/23/nvidia-keeps-hitting-records-can-investors-still-buy-the-stock.html?&qsearchterm=nvidia",
+ extraInfo:
+ "Page Url: https://www.cnbc.com/2024/05/23/nvidia-keeps-hitting-records-can-investors-still-buy-the-stock.html?&qsearchterm=nvidia",
},
-
-]
-
-function SidePanel(){
- return (
- <DraggableComponentsContainer content={content} />
- )
-}
-
-export default page;
+];
diff --git a/apps/web/app/(canvas)/dropComponent.tsx b/apps/web/app/(canvas)/dropComponent.tsx
index ee50f8d3..a7898b5a 100644
--- a/apps/web/app/(canvas)/dropComponent.tsx
+++ b/apps/web/app/(canvas)/dropComponent.tsx
@@ -9,6 +9,30 @@ const stripHtmlTags = (html: string): string => {
return div.textContent || div.innerText || "";
};
+function formatTextToRatio(text: string) {
+ const totalWidth = text.length;
+ const maxLineWidth = Math.floor(totalWidth / 4);
+
+ const words = text.split(" ");
+ let lines = [];
+ let currentLine = "";
+
+ words.forEach((word) => {
+ // Check if adding the next word exceeds the maximum line width
+ if ((currentLine + word).length <= maxLineWidth) {
+ currentLine += (currentLine ? " " : "") + word;
+ } else {
+ // If the current line is full, push it to new line
+ lines.push(currentLine);
+ currentLine = word;
+ }
+ });
+ if (currentLine) {
+ lines.push(currentLine);
+ }
+ return lines.join("\n");
+}
+
const useDrag = (): DragContextType => {
const context = useContext(DragContext);
if (!context) {
@@ -28,11 +52,22 @@ function DropZone() {
console.log("leaver");
};
+ useEffect(()=> {
+ setInterval(()=> {
+ editor.selectAll();
+ const shapes = editor.getSelectedShapes();
+ const text = shapes.filter((s) => s.type === "text")
+ console.log("hrhh", text)
+ },5000)
+ }, [])
+
const handleDrop = useCallback((event: DragEvent) => {
event.preventDefault();
setIsDraggingOver(false);
const dt = event.dataTransfer;
- if (!dt) {return}
+ if (!dt) {
+ return;
+ }
const items = dt.items;
for (let i = 0; i < items.length; i++) {
@@ -50,7 +85,8 @@ function DropZone() {
} else if (items[i]!.kind === "string") {
items[i]!.getAsString((data) => {
const cleanText = stripHtmlTags(data);
- handleExternalDroppedContent({ editor, text: cleanText });
+ const onethree = formatTextToRatio(cleanText);
+ handleExternalDroppedContent({ editor, text: onethree });
});
}
}
@@ -72,9 +108,99 @@ function DropZone() {
return (
<div
- className={`h-full w-full absolute top-0 left-0 z-[100000] pointer-events-none ${isDraggingOver && "bg-[#2C3439] pointer-events-auto"}`}
+ className={`h-full flex justify-center items-center w-full absolute top-0 left-0 z-[100000] pointer-events-none ${isDraggingOver && "bg-[#2c3439ad] pointer-events-auto"}`}
ref={dropRef}
- ></div>
+ >
+ {
+ isDraggingOver&& (
+ <>
+ <div className="absolute top-4 left-8"><TopRight /></div>
+ <div className="absolute top-4 right-8"><TopLeft /></div>
+ <div className="absolute bottom-4 left-8"><BottomLeft /></div>
+ <div className="absolute bottom-4 right-8"><BottomRight /></div>
+ <h2 className="text-2xl">Drop here to add Content on Canvas</h2>
+ </>
+ )
+
+ }
+
+ </div>
+ );
+}
+
+function TopRight() {
+ return (
+ <svg
+ width="48"
+ height="48"
+ viewBox="0 0 48 48"
+ fill="none"
+ xmlns="http://www.w3.org/2000/svg"
+ >
+ <path
+ d="M44 4H12C7.58172 4 4 7.58172 4 12V44"
+ stroke="white"
+ stroke-width="8"
+ stroke-linecap="round"
+ />
+ </svg>
+ );
+}
+
+function TopLeft() {
+ return (
+ <svg
+ width="48"
+ height="48"
+ viewBox="0 0 48 48"
+ fill="none"
+ xmlns="http://www.w3.org/2000/svg"
+ >
+ <path
+ d="M4 4H36C40.4183 4 44 7.58172 44 12V44"
+ stroke="white"
+ stroke-width="8"
+ stroke-linecap="round"
+ />
+ </svg>
+ );
+}
+
+function BottomLeft() {
+ return (
+ <svg
+ width="48"
+ height="48"
+ viewBox="0 0 48 48"
+ fill="none"
+ xmlns="http://www.w3.org/2000/svg"
+ >
+ <path
+ d="M44 44H12C7.58172 44 4 40.4183 4 36V4"
+ stroke="white"
+ stroke-width="8"
+ stroke-linecap="round"
+ />
+ </svg>
+ );
+}
+
+function BottomRight() {
+ return (
+ <svg
+ width="48"
+ height="48"
+ viewBox="0 0 48 48"
+ fill="none"
+ xmlns="http://www.w3.org/2000/svg"
+ >
+ <path
+ d="M4 44H36C40.4183 44 44 40.4183 44 36V4"
+ stroke="white"
+ stroke-width="8"
+ stroke-linecap="round"
+ />
+ </svg>
);
}
diff --git a/apps/web/app/(canvas)/lib/createEmbeds.ts b/apps/web/app/(canvas)/lib/createEmbeds.ts
index 0db3c71b..0ac3c7a5 100644
--- a/apps/web/app/(canvas)/lib/createEmbeds.ts
+++ b/apps/web/app/(canvas)/lib/createEmbeds.ts
@@ -96,6 +96,27 @@ function isURL(str: string) {
}
}
+function formatTextToRatio(text: string) {
+ const totalWidth = text.length;
+ const maxLineWidth = Math.floor(totalWidth / 10);
+
+ const words = text.split(" ");
+ let lines = [];
+ let currentLine = "";
+
+ words.forEach((word) => {
+ if ((currentLine + word).length <= maxLineWidth) {
+ currentLine += (currentLine ? " " : "") + word;
+ } else {
+ lines.push(currentLine);
+ currentLine = word;
+ }
+ });
+ if (currentLine) {
+ lines.push(currentLine);
+ }
+ return {height: (lines.length+1)*18, width: maxLineWidth*10};
+}
export function handleExternalDroppedContent({text, editor}: {text:string, editor: Editor}){
const position = editor.inputs.shiftKey
@@ -105,17 +126,23 @@ export function handleExternalDroppedContent({text, editor}: {text:string, edito
if (isURL(text)){
createEmbedsFromUrl({editor, url: text})
} else{
+ // editor.createShape({
+ // type: "text",
+ // x: position.x - 75,
+ // y: position.y - 75,
+ // props: {
+ // text: text,
+ // size: "s",
+ // textAlign: "start",
+ // },
+ // });
+ const {height, width} =formatTextToRatio(text)
editor.createShape({
- type: "text",
- x: position.x - 75,
- y: position.y - 75,
- props: {
- text: text,
- size: "s",
- textAlign: "start",
- },
+ type: "Textcard",
+ x: position.x - (width/2),
+ y: position.y - (height/2),
+ props: { content:text, extrainfo: "https://chatgpt.com/c/762cd44e-1752-495b-967a-aa3c23c6024a", w: width, h:height },
});
-
}
}
diff --git a/apps/web/app/(canvas)/lib/loadSnap.ts b/apps/web/app/(canvas)/lib/loadSnap.ts
index 15aad998..a3d58b72 100644
--- a/apps/web/app/(canvas)/lib/loadSnap.ts
+++ b/apps/web/app/(canvas)/lib/loadSnap.ts
@@ -1,13 +1,14 @@
-import { createTLStore, defaultShapeUtils } from "tldraw";
+import { createTLStore, defaultShapeUtils, loadSnapshot } from "tldraw";
import { twitterCardUtil } from "../twitterCard";
+import {textCardUtil} from "../textCard"
export async function loadRemoteSnapshot() {
const res = await fetch(
"https://learning-cf.pruthvirajthinks.workers.dev/get/page3",
);
const snapshot = JSON.parse(await res.json());
const newStore = createTLStore({
- shapeUtils: [...defaultShapeUtils, twitterCardUtil],
+ shapeUtils: [...defaultShapeUtils, twitterCardUtil, textCardUtil],
});
- newStore.loadSnapshot(snapshot);
+ loadSnapshot(newStore, snapshot)
return newStore;
} \ No newline at end of file
diff --git a/apps/web/app/(canvas)/textCard.tsx b/apps/web/app/(canvas)/textCard.tsx
new file mode 100644
index 00000000..4517c521
--- /dev/null
+++ b/apps/web/app/(canvas)/textCard.tsx
@@ -0,0 +1,66 @@
+import { BaseBoxShapeUtil, HTMLContainer, TLBaseBoxShape, TLBaseShape, useIsEditing, useValue } from "tldraw";
+
+type ITextCardShape = TLBaseShape<
+ "Textcard",
+ { w: number; h: number; content: string; extrainfo: string }
+>;
+
+export class textCardUtil extends BaseBoxShapeUtil<ITextCardShape> {
+ static override type = "Textcard" as const;
+
+ getDefaultProps(): ITextCardShape["props"] {
+ return {
+ w: 100,
+ h: 50,
+ content: "",
+ extrainfo: "",
+ };
+ }
+
+ component(s: ITextCardShape) {
+
+ const isEditing = useIsEditing(s.id)
+ const isHoveringWhileEditingSameShape = useValue(
+ 'is hovering',
+ () => {
+ const { editingShapeId, hoveredShapeId } = this.editor.getCurrentPageState()
+
+ if (editingShapeId && hoveredShapeId !== editingShapeId) {
+ const editingShape = this.editor.getShape(editingShapeId)
+ if (editingShape && this.editor.isShapeOfType<TLBaseBoxShape>(editingShape, 'embed')) {
+ return true
+ }
+ }
+
+ return false
+ },
+ []
+ )
+
+ const isInteractive = isEditing || isHoveringWhileEditingSameShape
+ return (
+ <HTMLContainer className="flex h-full w-full items-center justify-center">
+ <div
+ style={{
+ height: s.props.h,
+ width: s.props.w,
+ pointerEvents: isInteractive ? "all" : "none",
+ zIndex: isInteractive ? "" : "-1",
+ background: "#2C3439",
+ borderRadius: "16px",
+ padding: "8px 14px"
+ }}
+ >
+ <h1 style={{ fontSize: "15px" }}>{s.props.content}</h1>
+ <p style={{ fontSize: "14px", color: "#369DFD" }}>
+ {s.props.extrainfo}
+ </p>
+ </div>
+ </HTMLContainer>
+ );
+ }
+
+ indicator(shape: ITextCardShape) {
+ return <rect width={shape.props.w} height={shape.props.h} />;
+ }
+}
diff --git a/package.json b/package.json
index b6597fd7..bd5696be 100644
--- a/package.json
+++ b/package.json
@@ -61,6 +61,7 @@
"@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-separator": "^1.0.3",
"@radix-ui/react-slot": "^1.0.2",
+ "@radix-ui/react-switch": "^1.1.0",
"@radix-ui/react-tabs": "^1.0.4",
"@radix-ui/react-toast": "^1.1.5",
"@tldraw/assets": "^2.2.0",
diff --git a/packages/ui/components/canvas/draggableComponent.tsx b/packages/ui/components/canvas/draggableComponent.tsx
index da3c42c7..f9531f96 100644
--- a/packages/ui/components/canvas/draggableComponent.tsx
+++ b/packages/ui/components/canvas/draggableComponent.tsx
@@ -58,7 +58,7 @@ function DraggableComponents({
onDragEnd={handleDragEnd}
onDragStart={handleDragStart}
draggable
- className={`flex gap-4 px-3 text-[#989EA4] border-2 transition ${isDragging ? "border-blue-600": "border-[#1F2428]"}`}
+ className={`flex gap-4 px-1 rounded-md text-[#989EA4] border-2 transition ${isDragging ? "border-blue-600": "border-[#1F2428]"}`}
>
<Image className="select-none" src={icon} alt={iconAlt} />
<div className="flex flex-col gap-2">
diff --git a/packages/ui/shadcn/switch.tsx b/packages/ui/shadcn/switch.tsx
new file mode 100644
index 00000000..78a67682
--- /dev/null
+++ b/packages/ui/shadcn/switch.tsx
@@ -0,0 +1,29 @@
+"use client"
+
+import * as React from "react"
+import * as SwitchPrimitives from "@radix-ui/react-switch"
+
+import { cn } from "@repo/ui/lib/utils";
+
+const Switch = React.forwardRef<
+ React.ElementRef<typeof SwitchPrimitives.Root>,
+ React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>
+>(({ className, ...props }, ref) => (
+ <SwitchPrimitives.Root
+ className={cn(
+ "peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
+ className
+ )}
+ {...props}
+ ref={ref}
+ >
+ <SwitchPrimitives.Thumb
+ className={cn(
+ "pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0"
+ )}
+ />
+ </SwitchPrimitives.Root>
+))
+Switch.displayName = SwitchPrimitives.Root.displayName
+
+export { Switch }