Add 3 files
Browse files- README.md +7 -5
- index.html +669 -19
- prompts.txt +2 -0
README.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
|
|
|
|
|
|
| 8 |
---
|
| 9 |
|
| 10 |
-
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
|
| 1 |
---
|
| 2 |
+
title: board
|
| 3 |
+
emoji: 🐳
|
| 4 |
+
colorFrom: gray
|
| 5 |
+
colorTo: yellow
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
| 8 |
+
tags:
|
| 9 |
+
- deepsite
|
| 10 |
---
|
| 11 |
|
| 12 |
+
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
index.html
CHANGED
|
@@ -1,19 +1,669 @@
|
|
| 1 |
-
<!
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>CollabBoard - Online Whiteboard</title>
|
| 7 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 8 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
| 9 |
+
<style>
|
| 10 |
+
#whiteboard {
|
| 11 |
+
touch-action: none;
|
| 12 |
+
background-image: linear-gradient(#e5e7eb 1px, transparent 1px), linear-gradient(90deg, #e5e7eb 1px, transparent 1px);
|
| 13 |
+
background-size: 20px 20px;
|
| 14 |
+
cursor: crosshair;
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
.tool-btn.active {
|
| 18 |
+
@apply bg-blue-100 border-blue-500;
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
.color-option {
|
| 22 |
+
width: 24px;
|
| 23 |
+
height: 24px;
|
| 24 |
+
border-radius: 50%;
|
| 25 |
+
cursor: pointer;
|
| 26 |
+
transition: transform 0.2s;
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
.color-option:hover {
|
| 30 |
+
transform: scale(1.2);
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
.color-option.selected {
|
| 34 |
+
transform: scale(1.3);
|
| 35 |
+
box-shadow: 0 0 0 2px white, 0 0 0 3px #3b82f6;
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
.sticky-note {
|
| 39 |
+
min-width: 150px;
|
| 40 |
+
min-height: 150px;
|
| 41 |
+
resize: both;
|
| 42 |
+
overflow: hidden;
|
| 43 |
+
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
.sticky-note textarea {
|
| 47 |
+
background: transparent;
|
| 48 |
+
resize: none;
|
| 49 |
+
outline: none;
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
.shape-preview {
|
| 53 |
+
position: absolute;
|
| 54 |
+
pointer-events: none;
|
| 55 |
+
opacity: 0.7;
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
.board-thumbnail {
|
| 59 |
+
transition: transform 0.2s, box-shadow 0.2s;
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
.board-thumbnail:hover {
|
| 63 |
+
transform: translateY(-2px);
|
| 64 |
+
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
/* Custom scrollbar */
|
| 68 |
+
::-webkit-scrollbar {
|
| 69 |
+
width: 8px;
|
| 70 |
+
height: 8px;
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
::-webkit-scrollbar-track {
|
| 74 |
+
background: #f1f1f1;
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
::-webkit-scrollbar-thumb {
|
| 78 |
+
background: #c1c1c1;
|
| 79 |
+
border-radius: 4px;
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
::-webkit-scrollbar-thumb:hover {
|
| 83 |
+
background: #a8a8a8;
|
| 84 |
+
}
|
| 85 |
+
</style>
|
| 86 |
+
</head>
|
| 87 |
+
<body class="bg-gray-50 h-screen flex flex-col">
|
| 88 |
+
<!-- Header -->
|
| 89 |
+
<header class="bg-white shadow-sm py-3 px-4 flex items-center justify-between">
|
| 90 |
+
<div class="flex items-center space-x-2">
|
| 91 |
+
<div class="bg-blue-600 text-white p-2 rounded-lg">
|
| 92 |
+
<i class="fas fa-chalkboard text-xl"></i>
|
| 93 |
+
</div>
|
| 94 |
+
<h1 class="text-xl font-bold text-gray-800">CollabBoard</h1>
|
| 95 |
+
</div>
|
| 96 |
+
|
| 97 |
+
<div class="flex items-center space-x-4">
|
| 98 |
+
<button id="presentation-btn" class="flex items-center space-x-1 bg-blue-50 hover:bg-blue-100 text-blue-700 px-3 py-1.5 rounded-lg text-sm font-medium">
|
| 99 |
+
<i class="fas fa-expand"></i>
|
| 100 |
+
<span>Presentation</span>
|
| 101 |
+
</button>
|
| 102 |
+
|
| 103 |
+
<button id="share-btn" class="flex items-center space-x-1 bg-green-50 hover:bg-green-100 text-green-700 px-3 py-1.5 rounded-lg text-sm font-medium">
|
| 104 |
+
<i class="fas fa-share-alt"></i>
|
| 105 |
+
<span>Share</span>
|
| 106 |
+
</button>
|
| 107 |
+
|
| 108 |
+
<div class="relative">
|
| 109 |
+
<button id="user-menu-btn" class="flex items-center space-x-1 bg-gray-100 hover:bg-gray-200 px-3 py-1.5 rounded-lg text-sm font-medium">
|
| 110 |
+
<i class="fas fa-user-circle text-gray-700"></i>
|
| 111 |
+
<span>User</span>
|
| 112 |
+
</button>
|
| 113 |
+
<div id="user-menu" class="hidden absolute right-0 mt-2 w-48 bg-white rounded-md shadow-lg py-1 z-50">
|
| 114 |
+
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Account Settings</a>
|
| 115 |
+
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Sign Out</a>
|
| 116 |
+
</div>
|
| 117 |
+
</div>
|
| 118 |
+
</div>
|
| 119 |
+
</header>
|
| 120 |
+
|
| 121 |
+
<div class="flex flex-1 overflow-hidden">
|
| 122 |
+
<!-- Sidebar -->
|
| 123 |
+
<div id="sidebar" class="w-64 bg-white border-r border-gray-200 flex flex-col">
|
| 124 |
+
<div class="p-4 border-b border-gray-200">
|
| 125 |
+
<button id="new-board-btn" class="w-full bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded-lg font-medium flex items-center justify-center space-x-2">
|
| 126 |
+
<i class="fas fa-plus"></i>
|
| 127 |
+
<span>New Board</span>
|
| 128 |
+
</button>
|
| 129 |
+
</div>
|
| 130 |
+
|
| 131 |
+
<div class="p-4 border-b border-gray-200">
|
| 132 |
+
<div class="flex items-center justify-between mb-2">
|
| 133 |
+
<h3 class="font-medium text-gray-700">Your Boards</h3>
|
| 134 |
+
</div>
|
| 135 |
+
|
| 136 |
+
<div class="space-y-2" id="boards-list">
|
| 137 |
+
<!-- Boards will be added here dynamically -->
|
| 138 |
+
</div>
|
| 139 |
+
</div>
|
| 140 |
+
|
| 141 |
+
<div class="p-4 border-b border-gray-200">
|
| 142 |
+
<h3 class="font-medium text-gray-700 mb-2">Tags</h3>
|
| 143 |
+
<div class="space-y-1">
|
| 144 |
+
<div class="flex items-center space-x-2 p-1.5 rounded hover:bg-gray-100 cursor-pointer">
|
| 145 |
+
<div class="w-3 h-3 rounded-full bg-red-500"></div>
|
| 146 |
+
<span class="text-sm">Urgent</span>
|
| 147 |
+
</div>
|
| 148 |
+
<div class="flex items-center space-x-2 p-1.5 rounded hover:bg-gray-100 cursor-pointer">
|
| 149 |
+
<div class="w-3 h-3 rounded-full bg-yellow-500"></div>
|
| 150 |
+
<span class="text-sm">Ideas</span>
|
| 151 |
+
</div>
|
| 152 |
+
<div class="flex items-center space-x-2 p-1.5 rounded hover:bg-gray-100 cursor-pointer">
|
| 153 |
+
<div class="w-3 h-3 rounded-full bg-green-500"></div>
|
| 154 |
+
<span class="text-sm">Completed</span>
|
| 155 |
+
</div>
|
| 156 |
+
</div>
|
| 157 |
+
</div>
|
| 158 |
+
|
| 159 |
+
<div class="p-4">
|
| 160 |
+
<h3 class="font-medium text-gray-700 mb-2">Collaborators</h3>
|
| 161 |
+
<div class="space-y-2">
|
| 162 |
+
<div class="flex items-center space-x-2">
|
| 163 |
+
<div class="w-8 h-8 rounded-full bg-blue-100 flex items-center justify-center text-blue-600">
|
| 164 |
+
<i class="fas fa-user"></i>
|
| 165 |
+
</div>
|
| 166 |
+
<span class="text-sm">You</span>
|
| 167 |
+
</div>
|
| 168 |
+
</div>
|
| 169 |
+
</div>
|
| 170 |
+
</div>
|
| 171 |
+
|
| 172 |
+
<!-- Main Content -->
|
| 173 |
+
<div class="flex-1 flex flex-col overflow-hidden">
|
| 174 |
+
<!-- Toolbar -->
|
| 175 |
+
<div class="bg-white border-b border-gray-200 p-2 flex items-center justify-between">
|
| 176 |
+
<div class="flex items-center space-x-2 overflow-x-auto py-1">
|
| 177 |
+
<!-- Undo/Redo -->
|
| 178 |
+
<div class="flex items-center space-x-1 border-r border-gray-200 pr-2">
|
| 179 |
+
<button id="undo-btn" class="p-2 border rounded hover:bg-gray-100" title="Undo (Ctrl+Z)">
|
| 180 |
+
<i class="fas fa-undo"></i>
|
| 181 |
+
</button>
|
| 182 |
+
<button id="redo-btn" class="p-2 border rounded hover:bg-gray-100" title="Redo (Ctrl+Y)">
|
| 183 |
+
<i class="fas fa-redo"></i>
|
| 184 |
+
</button>
|
| 185 |
+
</div>
|
| 186 |
+
|
| 187 |
+
<!-- Drawing Tools -->
|
| 188 |
+
<div class="flex items-center space-x-1 border-r border-gray-200 pr-2">
|
| 189 |
+
<button id="select-tool" class="tool-btn p-2 border rounded hover:bg-gray-100 active" title="Select (V)">
|
| 190 |
+
<i class="fas fa-mouse-pointer"></i>
|
| 191 |
+
</button>
|
| 192 |
+
<button id="pen-tool" class="tool-btn p-2 border rounded hover:bg-gray-100" title="Pen (P)">
|
| 193 |
+
<i class="fas fa-pen"></i>
|
| 194 |
+
</button>
|
| 195 |
+
<button id="highlighter-tool" class="tool-btn p-2 border rounded hover:bg-gray-100" title="Highlighter (H)">
|
| 196 |
+
<i class="fas fa-highlighter"></i>
|
| 197 |
+
</button>
|
| 198 |
+
<button id="eraser-tool" class="tool-btn p-2 border rounded hover:bg-gray-100" title="Eraser (E)">
|
| 199 |
+
<i class="fas fa-eraser"></i>
|
| 200 |
+
</button>
|
| 201 |
+
<button id="text-tool" class="tool-btn p-2 border rounded hover:bg-gray-100" title="Text (T)">
|
| 202 |
+
<i class="fas fa-font"></i>
|
| 203 |
+
</button>
|
| 204 |
+
<button id="shape-tool" class="tool-btn p-2 border rounded hover:bg-gray-100" title="Shapes (S)">
|
| 205 |
+
<i class="fas fa-shapes"></i>
|
| 206 |
+
</button>
|
| 207 |
+
<button id="sticky-tool" class="tool-btn p-2 border rounded hover:bg-gray-100" title="Sticky Note (N)">
|
| 208 |
+
<i class="fas fa-sticky-note"></i>
|
| 209 |
+
</button>
|
| 210 |
+
<button id="laser-tool" class="tool-btn p-2 border rounded hover:bg-gray-100" title="Laser Pointer (L)">
|
| 211 |
+
<i class="fas fa-location-arrow"></i>
|
| 212 |
+
</button>
|
| 213 |
+
</div>
|
| 214 |
+
|
| 215 |
+
<!-- Brush Size -->
|
| 216 |
+
<div class="flex items-center space-x-1 border-r border-gray-200 pr-2">
|
| 217 |
+
<span class="text-sm text-gray-600">Size:</span>
|
| 218 |
+
<input id="brush-size" type="range" min="1" max="30" value="3" class="w-20">
|
| 219 |
+
<span id="brush-size-value" class="text-xs text-gray-600 w-6 text-center">3</span>
|
| 220 |
+
</div>
|
| 221 |
+
|
| 222 |
+
<!-- Colors -->
|
| 223 |
+
<div class="flex items-center space-x-1 border-r border-gray-200 pr-2">
|
| 224 |
+
<div class="color-option bg-black selected" data-color="#000000"></div>
|
| 225 |
+
<div class="color-option bg-red-500" data-color="#ef4444"></div>
|
| 226 |
+
<div class="color-option bg-yellow-500" data-color="#eab308"></div>
|
| 227 |
+
<div class="color-option bg-green-500" data-color="#22c55e"></div>
|
| 228 |
+
<div class="color-option bg-blue-500" data-color="#3b82f6"></div>
|
| 229 |
+
<div class="color-option bg-purple-500" data-color="#a855f7"></div>
|
| 230 |
+
<div class="color-option bg-pink-500" data-color="#ec4899"></div>
|
| 231 |
+
<div class="color-option bg-white border border-gray-300" data-color="#ffffff"></div>
|
| 232 |
+
</div>
|
| 233 |
+
|
| 234 |
+
<!-- Custom Color -->
|
| 235 |
+
<div class="flex items-center space-x-1">
|
| 236 |
+
<input type="color" id="custom-color" value="#000000" class="w-6 h-6 border border-gray-300 rounded cursor-pointer">
|
| 237 |
+
<span class="text-sm text-gray-600">Custom</span>
|
| 238 |
+
</div>
|
| 239 |
+
</div>
|
| 240 |
+
|
| 241 |
+
<div class="flex items-center space-x-2">
|
| 242 |
+
<button id="clear-btn" class="p-2 border rounded hover:bg-gray-100 text-red-500" title="Clear Board">
|
| 243 |
+
<i class="fas fa-trash-alt"></i>
|
| 244 |
+
</button>
|
| 245 |
+
<button id="save-btn" class="p-2 border rounded hover:bg-gray-100 text-green-500" title="Save Board">
|
| 246 |
+
<i class="fas fa-save"></i>
|
| 247 |
+
</button>
|
| 248 |
+
</div>
|
| 249 |
+
</div>
|
| 250 |
+
|
| 251 |
+
<!-- Whiteboard Canvas -->
|
| 252 |
+
<div class="flex-1 overflow-auto relative">
|
| 253 |
+
<canvas id="whiteboard" class="absolute top-0 left-0"></canvas>
|
| 254 |
+
</div>
|
| 255 |
+
|
| 256 |
+
<!-- Zoom Controls -->
|
| 257 |
+
<div class="bg-white border-t border-gray-200 p-2 flex items-center justify-between">
|
| 258 |
+
<div class="flex items-center space-x-2">
|
| 259 |
+
<button id="zoom-out" class="p-1.5 border rounded hover:bg-gray-100">
|
| 260 |
+
<i class="fas fa-search-minus"></i>
|
| 261 |
+
</button>
|
| 262 |
+
<span id="zoom-level" class="text-sm font-medium">100%</span>
|
| 263 |
+
<button id="zoom-in" class="p-1.5 border rounded hover:bg-gray-100">
|
| 264 |
+
<i class="fas fa-search-plus"></i>
|
| 265 |
+
</button>
|
| 266 |
+
<button id="zoom-fit" class="p-1.5 border rounded hover:bg-gray-100 text-sm ml-2">
|
| 267 |
+
Fit to Screen
|
| 268 |
+
</button>
|
| 269 |
+
</div>
|
| 270 |
+
<div class="text-sm text-gray-500">
|
| 271 |
+
<span id="cursor-position">0, 0</span>
|
| 272 |
+
</div>
|
| 273 |
+
</div>
|
| 274 |
+
</div>
|
| 275 |
+
</div>
|
| 276 |
+
|
| 277 |
+
<script>
|
| 278 |
+
document.addEventListener('DOMContentLoaded', function() {
|
| 279 |
+
// Canvas setup
|
| 280 |
+
const canvas = document.getElementById('whiteboard');
|
| 281 |
+
const ctx = canvas.getContext('2d');
|
| 282 |
+
let isDrawing = false;
|
| 283 |
+
let currentTool = 'pen';
|
| 284 |
+
let currentColor = '#000000';
|
| 285 |
+
let brushSize = 3;
|
| 286 |
+
let zoomLevel = 1;
|
| 287 |
+
let offsetX = 0;
|
| 288 |
+
let offsetY = 0;
|
| 289 |
+
let startX, startY;
|
| 290 |
+
let actionHistory = [];
|
| 291 |
+
let historyIndex = -1;
|
| 292 |
+
let boards = [];
|
| 293 |
+
let currentBoardIndex = -1;
|
| 294 |
+
|
| 295 |
+
// Initialize canvas size
|
| 296 |
+
function initCanvas() {
|
| 297 |
+
const container = canvas.parentElement;
|
| 298 |
+
canvas.width = container.clientWidth;
|
| 299 |
+
canvas.height = container.clientHeight;
|
| 300 |
+
redrawCanvas();
|
| 301 |
+
}
|
| 302 |
+
|
| 303 |
+
// Redraw everything on the canvas
|
| 304 |
+
function redrawCanvas() {
|
| 305 |
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
| 306 |
+
|
| 307 |
+
// Draw grid
|
| 308 |
+
ctx.fillStyle = '#e5e7eb';
|
| 309 |
+
const gridSize = 20 * zoomLevel;
|
| 310 |
+
for (let x = 0; x < canvas.width; x += gridSize) {
|
| 311 |
+
ctx.fillRect(x - offsetX % gridSize, 0, 1, canvas.height);
|
| 312 |
+
}
|
| 313 |
+
for (let y = 0; y < canvas.height; y += gridSize) {
|
| 314 |
+
ctx.fillRect(0, y - offsetY % gridSize, canvas.width, 1);
|
| 315 |
+
}
|
| 316 |
+
|
| 317 |
+
// Draw all actions
|
| 318 |
+
if (currentBoardIndex >= 0 && boards[currentBoardIndex]) {
|
| 319 |
+
const board = boards[currentBoardIndex];
|
| 320 |
+
for (let i = 0; i <= historyIndex; i++) {
|
| 321 |
+
drawAction(board.actions[i]);
|
| 322 |
+
}
|
| 323 |
+
}
|
| 324 |
+
}
|
| 325 |
+
|
| 326 |
+
// Draw a single action
|
| 327 |
+
function drawAction(action) {
|
| 328 |
+
if (!action) return;
|
| 329 |
+
|
| 330 |
+
ctx.strokeStyle = action.color || currentColor;
|
| 331 |
+
ctx.fillStyle = action.color || currentColor;
|
| 332 |
+
ctx.lineWidth = action.size || brushSize;
|
| 333 |
+
ctx.lineCap = 'round';
|
| 334 |
+
ctx.lineJoin = 'round';
|
| 335 |
+
|
| 336 |
+
switch (action.type) {
|
| 337 |
+
case 'freehand':
|
| 338 |
+
ctx.beginPath();
|
| 339 |
+
ctx.moveTo(action.points[0].x, action.points[0].y);
|
| 340 |
+
for (let i = 1; i < action.points.length; i++) {
|
| 341 |
+
ctx.lineTo(action.points[i].x, action.points[i].y);
|
| 342 |
+
}
|
| 343 |
+
ctx.stroke();
|
| 344 |
+
break;
|
| 345 |
+
case 'erase':
|
| 346 |
+
ctx.globalCompositeOperation = 'destination-out';
|
| 347 |
+
ctx.beginPath();
|
| 348 |
+
ctx.moveTo(action.points[0].x, action.points[0].y);
|
| 349 |
+
for (let i = 1; i < action.points.length; i++) {
|
| 350 |
+
ctx.lineTo(action.points[i].x, action.points[i].y);
|
| 351 |
+
}
|
| 352 |
+
ctx.stroke();
|
| 353 |
+
ctx.globalCompositeOperation = 'source-over';
|
| 354 |
+
break;
|
| 355 |
+
// Add cases for other action types (text, shapes, etc.)
|
| 356 |
+
}
|
| 357 |
+
}
|
| 358 |
+
|
| 359 |
+
// Save current state to history
|
| 360 |
+
function saveToHistory(action) {
|
| 361 |
+
if (currentBoardIndex >= 0) {
|
| 362 |
+
// If we're not at the end of history, remove future actions
|
| 363 |
+
if (historyIndex < boards[currentBoardIndex].actions.length - 1) {
|
| 364 |
+
boards[currentBoardIndex].actions = boards[currentBoardIndex].actions.slice(0, historyIndex + 1);
|
| 365 |
+
}
|
| 366 |
+
|
| 367 |
+
boards[currentBoardIndex].actions.push(action);
|
| 368 |
+
historyIndex++;
|
| 369 |
+
updateUndoRedoButtons();
|
| 370 |
+
}
|
| 371 |
+
}
|
| 372 |
+
|
| 373 |
+
// Undo last action
|
| 374 |
+
function undo() {
|
| 375 |
+
if (historyIndex >= 0) {
|
| 376 |
+
historyIndex--;
|
| 377 |
+
redrawCanvas();
|
| 378 |
+
updateUndoRedoButtons();
|
| 379 |
+
}
|
| 380 |
+
}
|
| 381 |
+
|
| 382 |
+
// Redo last undone action
|
| 383 |
+
function redo() {
|
| 384 |
+
if (currentBoardIndex >= 0 && historyIndex < boards[currentBoardIndex].actions.length - 1) {
|
| 385 |
+
historyIndex++;
|
| 386 |
+
drawAction(boards[currentBoardIndex].actions[historyIndex]);
|
| 387 |
+
updateUndoRedoButtons();
|
| 388 |
+
}
|
| 389 |
+
}
|
| 390 |
+
|
| 391 |
+
// Update undo/redo button states
|
| 392 |
+
function updateUndoRedoButtons() {
|
| 393 |
+
document.getElementById('undo-btn').disabled = historyIndex < 0;
|
| 394 |
+
document.getElementById('redo-btn').disabled =
|
| 395 |
+
currentBoardIndex < 0 || historyIndex >= boards[currentBoardIndex].actions.length - 1;
|
| 396 |
+
}
|
| 397 |
+
|
| 398 |
+
// Create a new board
|
| 399 |
+
function createNewBoard() {
|
| 400 |
+
const newBoard = {
|
| 401 |
+
id: Date.now(),
|
| 402 |
+
title: `Board ${boards.length + 1}`,
|
| 403 |
+
actions: [],
|
| 404 |
+
createdAt: new Date()
|
| 405 |
+
};
|
| 406 |
+
|
| 407 |
+
boards.push(newBoard);
|
| 408 |
+
currentBoardIndex = boards.length - 1;
|
| 409 |
+
historyIndex = -1;
|
| 410 |
+
|
| 411 |
+
// Add to sidebar
|
| 412 |
+
addBoardToSidebar(newBoard);
|
| 413 |
+
|
| 414 |
+
// Clear canvas
|
| 415 |
+
redrawCanvas();
|
| 416 |
+
updateUndoRedoButtons();
|
| 417 |
+
}
|
| 418 |
+
|
| 419 |
+
// Add board to sidebar
|
| 420 |
+
function addBoardToSidebar(board) {
|
| 421 |
+
const boardElement = document.createElement('div');
|
| 422 |
+
boardElement.className = 'board-thumbnail bg-white p-2 rounded-lg border border-gray-200 cursor-pointer';
|
| 423 |
+
boardElement.innerHTML = `
|
| 424 |
+
<div class="bg-gray-100 h-24 rounded-md mb-2 flex items-center justify-center">
|
| 425 |
+
<i class="fas fa-chalkboard text-gray-400 text-2xl"></i>
|
| 426 |
+
</div>
|
| 427 |
+
<h4 class="font-medium text-sm truncate">${board.title}</h4>
|
| 428 |
+
<p class="text-xs text-gray-500">Just now</p>
|
| 429 |
+
`;
|
| 430 |
+
|
| 431 |
+
boardElement.addEventListener('click', () => {
|
| 432 |
+
// Switch to this board
|
| 433 |
+
const index = boards.findIndex(b => b.id === board.id);
|
| 434 |
+
if (index >= 0) {
|
| 435 |
+
currentBoardIndex = index;
|
| 436 |
+
historyIndex = boards[currentBoardIndex].actions.length - 1;
|
| 437 |
+
redrawCanvas();
|
| 438 |
+
updateUndoRedoButtons();
|
| 439 |
+
}
|
| 440 |
+
});
|
| 441 |
+
|
| 442 |
+
document.getElementById('boards-list').prepend(boardElement);
|
| 443 |
+
}
|
| 444 |
+
|
| 445 |
+
// Event listeners for drawing
|
| 446 |
+
canvas.addEventListener('mousedown', startDrawing);
|
| 447 |
+
canvas.addEventListener('mousemove', draw);
|
| 448 |
+
canvas.addEventListener('mouseup', stopDrawing);
|
| 449 |
+
canvas.addEventListener('mouseout', stopDrawing);
|
| 450 |
+
|
| 451 |
+
// Touch events for mobile
|
| 452 |
+
canvas.addEventListener('touchstart', handleTouchStart);
|
| 453 |
+
canvas.addEventListener('touchmove', handleTouchMove);
|
| 454 |
+
canvas.addEventListener('touchend', handleTouchEnd);
|
| 455 |
+
|
| 456 |
+
function startDrawing(e) {
|
| 457 |
+
isDrawing = true;
|
| 458 |
+
|
| 459 |
+
const rect = canvas.getBoundingClientRect();
|
| 460 |
+
startX = (e.clientX - rect.left - offsetX) / zoomLevel;
|
| 461 |
+
startY = (e.clientY - rect.top - offsetY) / zoomLevel;
|
| 462 |
+
|
| 463 |
+
if (currentTool === 'pen' || currentTool === 'highlighter' || currentTool === 'eraser') {
|
| 464 |
+
const action = {
|
| 465 |
+
type: currentTool === 'eraser' ? 'erase' : 'freehand',
|
| 466 |
+
color: currentTool === 'highlighter' ? currentColor + '80' : currentColor,
|
| 467 |
+
size: brushSize,
|
| 468 |
+
points: [{ x: startX, y: startY }]
|
| 469 |
+
};
|
| 470 |
+
|
| 471 |
+
if (currentBoardIndex >= 0) {
|
| 472 |
+
boards[currentBoardIndex].actions.push(action);
|
| 473 |
+
historyIndex = boards[currentBoardIndex].actions.length - 1;
|
| 474 |
+
}
|
| 475 |
+
}
|
| 476 |
+
|
| 477 |
+
draw(e);
|
| 478 |
+
}
|
| 479 |
+
|
| 480 |
+
function draw(e) {
|
| 481 |
+
if (!isDrawing) return;
|
| 482 |
+
|
| 483 |
+
const rect = canvas.getBoundingClientRect();
|
| 484 |
+
const x = (e.clientX - rect.left - offsetX) / zoomLevel;
|
| 485 |
+
const y = (e.clientY - rect.top - offsetY) / zoomLevel;
|
| 486 |
+
|
| 487 |
+
// Update cursor position display
|
| 488 |
+
document.getElementById('cursor-position').textContent =
|
| 489 |
+
`${Math.round(x)}, ${Math.round(y)}`;
|
| 490 |
+
|
| 491 |
+
if (currentTool === 'pen' || currentTool === 'highlighter' || currentTool === 'eraser') {
|
| 492 |
+
if (currentBoardIndex >= 0 && boards[currentBoardIndex].actions.length > 0) {
|
| 493 |
+
const lastAction = boards[currentBoardIndex].actions[historyIndex];
|
| 494 |
+
if (lastAction && (lastAction.type === 'freehand' || lastAction.type === 'erase')) {
|
| 495 |
+
lastAction.points.push({ x, y });
|
| 496 |
+
redrawCanvas();
|
| 497 |
+
}
|
| 498 |
+
}
|
| 499 |
+
}
|
| 500 |
+
}
|
| 501 |
+
|
| 502 |
+
function stopDrawing() {
|
| 503 |
+
isDrawing = false;
|
| 504 |
+
}
|
| 505 |
+
|
| 506 |
+
// Touch event handlers
|
| 507 |
+
function handleTouchStart(e) {
|
| 508 |
+
e.preventDefault();
|
| 509 |
+
const touch = e.touches[0];
|
| 510 |
+
const mouseEvent = new MouseEvent('mousedown', {
|
| 511 |
+
clientX: touch.clientX,
|
| 512 |
+
clientY: touch.clientY
|
| 513 |
+
});
|
| 514 |
+
startDrawing(mouseEvent);
|
| 515 |
+
}
|
| 516 |
+
|
| 517 |
+
function handleTouchMove(e) {
|
| 518 |
+
e.preventDefault();
|
| 519 |
+
const touch = e.touches[0];
|
| 520 |
+
const mouseEvent = new MouseEvent('mousemove', {
|
| 521 |
+
clientX: touch.clientX,
|
| 522 |
+
clientY: touch.clientY
|
| 523 |
+
});
|
| 524 |
+
draw(mouseEvent);
|
| 525 |
+
}
|
| 526 |
+
|
| 527 |
+
function handleTouchEnd(e) {
|
| 528 |
+
e.preventDefault();
|
| 529 |
+
const mouseEvent = new MouseEvent('mouseup', {});
|
| 530 |
+
stopDrawing(mouseEvent);
|
| 531 |
+
}
|
| 532 |
+
|
| 533 |
+
// Tool selection
|
| 534 |
+
document.querySelectorAll('.tool-btn').forEach(btn => {
|
| 535 |
+
btn.addEventListener('click', function() {
|
| 536 |
+
document.querySelectorAll('.tool-btn').forEach(b => b.classList.remove('active'));
|
| 537 |
+
this.classList.add('active');
|
| 538 |
+
|
| 539 |
+
switch (this.id) {
|
| 540 |
+
case 'select-tool': currentTool = 'select'; break;
|
| 541 |
+
case 'pen-tool': currentTool = 'pen'; break;
|
| 542 |
+
case 'highlighter-tool': currentTool = 'highlighter'; break;
|
| 543 |
+
case 'eraser-tool': currentTool = 'eraser'; break;
|
| 544 |
+
case 'text-tool': currentTool = 'text'; break;
|
| 545 |
+
case 'shape-tool': currentTool = 'shape'; break;
|
| 546 |
+
case 'sticky-tool': currentTool = 'sticky'; break;
|
| 547 |
+
case 'laser-tool': currentTool = 'laser'; break;
|
| 548 |
+
}
|
| 549 |
+
|
| 550 |
+
// Change cursor based on tool
|
| 551 |
+
if (currentTool === 'pen' || currentTool === 'highlighter') {
|
| 552 |
+
canvas.style.cursor = 'crosshair';
|
| 553 |
+
} else if (currentTool === 'eraser') {
|
| 554 |
+
canvas.style.cursor = 'url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\' width=\'16\' height=\'16\' viewBox=\'0 0 16 16\'><circle cx=\'8\' cy=\'8\' r=\'8\' fill=\'black\'/></svg>") 8 8, auto';
|
| 555 |
+
} else {
|
| 556 |
+
canvas.style.cursor = 'default';
|
| 557 |
+
}
|
| 558 |
+
});
|
| 559 |
+
});
|
| 560 |
+
|
| 561 |
+
// Color selection
|
| 562 |
+
document.querySelectorAll('.color-option').forEach(option => {
|
| 563 |
+
option.addEventListener('click', function() {
|
| 564 |
+
document.querySelectorAll('.color-option').forEach(o => o.classList.remove('selected'));
|
| 565 |
+
this.classList.add('selected');
|
| 566 |
+
currentColor = this.dataset.color;
|
| 567 |
+
document.getElementById('custom-color').value = currentColor;
|
| 568 |
+
});
|
| 569 |
+
});
|
| 570 |
+
|
| 571 |
+
// Custom color picker
|
| 572 |
+
document.getElementById('custom-color').addEventListener('input', function() {
|
| 573 |
+
currentColor = this.value;
|
| 574 |
+
// Find and select the matching color option if it exists
|
| 575 |
+
let found = false;
|
| 576 |
+
document.querySelectorAll('.color-option').forEach(option => {
|
| 577 |
+
if (option.dataset.color.toLowerCase() === currentColor.toLowerCase()) {
|
| 578 |
+
option.classList.add('selected');
|
| 579 |
+
found = true;
|
| 580 |
+
} else {
|
| 581 |
+
option.classList.remove('selected');
|
| 582 |
+
}
|
| 583 |
+
});
|
| 584 |
+
|
| 585 |
+
if (!found) {
|
| 586 |
+
document.querySelectorAll('.color-option').forEach(o => o.classList.remove('selected'));
|
| 587 |
+
}
|
| 588 |
+
});
|
| 589 |
+
|
| 590 |
+
// Brush size
|
| 591 |
+
document.getElementById('brush-size').addEventListener('input', function() {
|
| 592 |
+
brushSize = this.value;
|
| 593 |
+
document.getElementById('brush-size-value').textContent = brushSize;
|
| 594 |
+
});
|
| 595 |
+
|
| 596 |
+
// Zoom controls
|
| 597 |
+
document.getElementById('zoom-in').addEventListener('click', function() {
|
| 598 |
+
zoomLevel = Math.min(zoomLevel * 1.2, 5);
|
| 599 |
+
updateZoomDisplay();
|
| 600 |
+
redrawCanvas();
|
| 601 |
+
});
|
| 602 |
+
|
| 603 |
+
document.getElementById('zoom-out').addEventListener('click', function() {
|
| 604 |
+
zoomLevel = Math.max(zoomLevel / 1.2, 0.2);
|
| 605 |
+
updateZoomDisplay();
|
| 606 |
+
redrawCanvas();
|
| 607 |
+
});
|
| 608 |
+
|
| 609 |
+
document.getElementById('zoom-fit').addEventListener('click', function() {
|
| 610 |
+
zoomLevel = 1;
|
| 611 |
+
offsetX = 0;
|
| 612 |
+
offsetY = 0;
|
| 613 |
+
updateZoomDisplay();
|
| 614 |
+
redrawCanvas();
|
| 615 |
+
});
|
| 616 |
+
|
| 617 |
+
function updateZoomDisplay() {
|
| 618 |
+
document.getElementById('zoom-level').textContent = `${Math.round(zoomLevel * 100)}%`;
|
| 619 |
+
}
|
| 620 |
+
|
| 621 |
+
// Undo/redo buttons
|
| 622 |
+
document.getElementById('undo-btn').addEventListener('click', undo);
|
| 623 |
+
document.getElementById('redo-btn').addEventListener('click', redo);
|
| 624 |
+
|
| 625 |
+
// Keyboard shortcuts
|
| 626 |
+
document.addEventListener('keydown', function(e) {
|
| 627 |
+
// Ctrl+Z for undo
|
| 628 |
+
if (e.ctrlKey && e.key === 'z') {
|
| 629 |
+
e.preventDefault();
|
| 630 |
+
undo();
|
| 631 |
+
}
|
| 632 |
+
// Ctrl+Y for redo
|
| 633 |
+
else if (e.ctrlKey && e.key === 'y') {
|
| 634 |
+
e.preventDefault();
|
| 635 |
+
redo();
|
| 636 |
+
}
|
| 637 |
+
});
|
| 638 |
+
|
| 639 |
+
// New board button
|
| 640 |
+
document.getElementById('new-board-btn').addEventListener('click', createNewBoard);
|
| 641 |
+
|
| 642 |
+
// Clear button
|
| 643 |
+
document.getElementById('clear-btn').addEventListener('click', function() {
|
| 644 |
+
if (confirm('Are you sure you want to clear the board?')) {
|
| 645 |
+
if (currentBoardIndex >= 0) {
|
| 646 |
+
boards[currentBoardIndex].actions = [];
|
| 647 |
+
historyIndex = -1;
|
| 648 |
+
redrawCanvas();
|
| 649 |
+
updateUndoRedoButtons();
|
| 650 |
+
}
|
| 651 |
+
}
|
| 652 |
+
});
|
| 653 |
+
|
| 654 |
+
// Save button
|
| 655 |
+
document.getElementById('save-btn').addEventListener('click', function() {
|
| 656 |
+
alert('Board saved!');
|
| 657 |
+
// In a real app, this would save to localStorage or a server
|
| 658 |
+
});
|
| 659 |
+
|
| 660 |
+
// Initialize
|
| 661 |
+
initCanvas();
|
| 662 |
+
window.addEventListener('resize', initCanvas);
|
| 663 |
+
|
| 664 |
+
// Create first board
|
| 665 |
+
createNewBoard();
|
| 666 |
+
});
|
| 667 |
+
</script>
|
| 668 |
+
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=madansa7/board" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
|
| 669 |
+
</html>
|
prompts.txt
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
🧾 Prompt: Online Whiteboard Web App for Teaching & Collaboration 🎯 Objective Build a clean, intuitive online whiteboard that combines the simplicity of Google Keep’s Notes UI with robust drawing, zooming, and content-saving capabilities for teaching, brainstorming, or personal note-taking. Should work seamlessly on desktop, tablet, and mobile. 🧰 Core Features 🖼️ Canvas & Drawing Tools Infinite or scrollable whiteboard space (similar to Miro or Excalidraw). Pen tool with multiple brush sizes. Color palette with custom hex support. Highlighter tool (semi-transparent ink). Eraser (soft and hard modes). Text tool with basic formatting (font size, color, bold, italic). Shape tool (rectangle, circle, arrow, line). Sticky Notes that can be moved or minimized. 🔍 Smart Interaction Features Lasso tool or selection mode to grab and move drawn content or text. Pinch to zoom (mobile/tablet) or scroll to zoom (desktop). Pan/drag mode for navigating large boards. Zoom-to-selection feature to focus on any drawn/selected area. 💾 Save & Export Save to cloud (Google Drive, Firebase, or local storage for MVP). Export board as: PNG or JPEG (cropped to content) PDF (with optional background grid) SVG (for vector drawings) Auto-save every few seconds or after any interaction. 🗃️ Board Management Create multiple boards with titles and tags. Quick thumbnail preview for each saved board. Duplicate, delete, or rename boards. 👩🏫 Teaching & Presentation Mode Laser pointer mode (click-and-hold to show a pointer circle). Fullscreen mode for teaching. Optional voice recorder to sync voice notes with board activity. Real-time sync or sharing via a URL (use Firebase or WebRTC for MVP collaboration).
|
| 2 |
+
not able to draw anythng in the board and new board button does not wokr, does not need math class notes, have undo redo button, select option in tools tray,
|