Unreadable Canvas code, jk 😂

This commit is contained in:
codetorso 2024-06-22 23:10:28 +05:30
parent 2ac315c039
commit becb3064c2
10 changed files with 323 additions and 52 deletions

View file

@ -0,0 +1,3 @@
.tlui-dialog__overlay {
position: fixed;
}

View file

@ -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]">

View file

@ -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= [
{
content: "Nvidia currently dominates the GPU hardware market, with a market share over 97%. This has led some to argue...",
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",
},
{
content: "Nvidia currently dominates the GPU hardware market, with a market share over 97%. This has led some to argue...",
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",
},
]
function SidePanel(){
function SidePanel() {
const [value, setValue] = useState("");
const [dragAsText, setDragAsText] = useState(false);
return (
<DraggableComponentsContainer content={content} />
)
<>
<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:
"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://chatgpt.com/c/762cd44e-1752-495b-967a-aa3c23c6024a",
},
{
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",
},
];

View file

@ -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>
);
}

View file

@ -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 },
});
}
}

View file

@ -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;
}

View file

@ -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} />;
}
}

View file

@ -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",

View file

@ -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">

View file

@ -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 }