LJMolotov commited on
Commit
a269c1b
verified
1 Parent(s): 5dd8374

Add 3 files

Browse files
Files changed (3) hide show
  1. README.md +6 -4
  2. index.html +1529 -19
  3. prompts.txt +3 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: My Multi Notes
3
- emoji: 馃彚
4
- colorFrom: yellow
5
  colorTo: purple
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: my-multi-notes
3
+ emoji: 馃惓
4
+ colorFrom: pink
5
  colorTo: purple
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,1529 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="es">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Excel Clone Avanzado</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
+ .cell.selected {
11
+ box-shadow: inset 0 0 0 2px #3b82f6;
12
+ }
13
+ .cell.editing {
14
+ background-color: #1e293b;
15
+ box-shadow: inset 0 0 0 2px #10b981;
16
+ }
17
+ .column-resize-handle {
18
+ position: absolute;
19
+ right: -2px;
20
+ top: 0;
21
+ width: 4px;
22
+ height: 100%;
23
+ background-color: transparent;
24
+ cursor: col-resize;
25
+ z-index: 10;
26
+ }
27
+ .row-resize-handle {
28
+ position: absolute;
29
+ bottom: -2px;
30
+ left: 0;
31
+ width: 100%;
32
+ height: 4px;
33
+ background-color: transparent;
34
+ cursor: row-resize;
35
+ z-index: 10;
36
+ }
37
+ .scroll-shadow-right {
38
+ box-shadow: inset -10px 0 8px -8px rgba(0, 0, 0, 0.4);
39
+ }
40
+ .scroll-shadow-bottom {
41
+ box-shadow: inset 0 -10px 8px -8px rgba(0, 0, 0, 0.4);
42
+ }
43
+ .tab-active {
44
+ border-bottom: 2px solid #3b82f6;
45
+ color: #3b82f6;
46
+ }
47
+ .format-button.active {
48
+ background-color: #374151;
49
+ }
50
+ .color-preview {
51
+ width: 16px;
52
+ height: 16px;
53
+ display: inline-block;
54
+ border: 1px solid #6b7280;
55
+ vertical-align: middle;
56
+ margin-left: 4px;
57
+ }
58
+ </style>
59
+ </head>
60
+ <body class="bg-gray-800 text-gray-100 h-screen flex flex-col overflow-hidden">
61
+ <!-- Toolbar Superior -->
62
+ <div class="bg-gray-900 p-2 flex items-center border-b border-gray-700">
63
+ <!-- Archivo -->
64
+ <div class="relative group">
65
+ <button id="file-menu" class="px-3 py-1 rounded hover:bg-gray-700 text-blue-400 font-medium">
66
+ <i class="fas fa-file mr-1"></i> Archivo
67
+ </button>
68
+ <div class="absolute hidden group-hover:block bg-gray-800 border border-gray-700 rounded shadow-lg z-20 w-48">
69
+ <button id="new-file" class="block w-full text-left px-4 py-2 hover:bg-gray-700 text-green-400">
70
+ <i class="fas fa-file-circle-plus mr-2"></i> Nuevo
71
+ </button>
72
+ <button id="open-file" class="block w-full text-left px-4 py-2 hover:bg-gray-700 text-yellow-400">
73
+ <i class="fas fa-folder-open mr-2"></i> Abrir
74
+ </button>
75
+ <button id="save-file" class="block w-full text-left px-4 py-2 hover:bg-gray-700 text-purple-400">
76
+ <i class="fas fa-save mr-2"></i> Guardar
77
+ </button>
78
+ <div class="border-t border-gray-700"></div>
79
+ <button id="export-pdf" class="block w-full text-left px-4 py-2 hover:bg-gray-700 text-red-400">
80
+ <i class="fas fa-file-pdf mr-2"></i> Exportar PDF
81
+ </button>
82
+ </div>
83
+ </div>
84
+
85
+ <!-- Edici贸n -->
86
+ <div class="relative group ml-2">
87
+ <button class="px-3 py-1 rounded hover:bg-gray-700 text-green-400 font-medium">
88
+ <i class="fas fa-edit mr-1"></i> Edici贸n
89
+ </button>
90
+ <div class="absolute hidden group-hover:block bg-gray-800 border border-gray-700 rounded shadow-lg z-20 w-48">
91
+ <button id="undo" class="block w-full text-left px-4 py-2 hover:bg-gray-700 text-blue-400">
92
+ <i class="fas fa-undo mr-2"></i> Deshacer
93
+ </button>
94
+ <button id="redo" class="block w-full text-left px-4 py-2 hover:bg-gray-700 text-purple-400">
95
+ <i class="fas fa-redo mr-2"></i> Rehacer
96
+ </button>
97
+ <div class="border-t border-gray-700"></div>
98
+ <button id="cut" class="block w-full text-left px-4 py-2 hover:bg-gray-700 text-yellow-400">
99
+ <i class="fas fa-cut mr-2"></i> Cortar
100
+ </button>
101
+ <button id="copy" class="block w-full text-left px-4 py-2 hover:bg-gray-700 text-pink-400">
102
+ <i class="fas fa-copy mr-2"></i> Copiar
103
+ </button>
104
+ <button id="paste" class="block w-full text-left px-4 py-2 hover:bg-gray-700 text-indigo-400">
105
+ <i class="fas fa-paste mr-2"></i> Pegar
106
+ </button>
107
+ <div class="border-t border-gray-700"></div>
108
+ <button id="clear-contents" class="block w-full text-left px-4 py-2 hover:bg-gray-700 text-red-400">
109
+ <i class="fas fa-eraser mr-2"></i> Limpiar contenido
110
+ </button>
111
+ <button id="clear-formats" class="block w-full text-left px-4 py-2 hover:bg-gray-700 text-orange-400">
112
+ <i class="fas fa-remove-format mr-2"></i> Limpiar formato
113
+ </button>
114
+ </div>
115
+ </div>
116
+
117
+ <!-- Formato -->
118
+ <div class="flex items-center space-x-2 ml-4">
119
+ <select id="font-family" class="bg-gray-800 border border-gray-700 rounded px-2 py-1 text-sm text-white hover:bg-gray-700">
120
+ <option>Calibri</option>
121
+ <option>Arial</option>
122
+ <option>Times New Roman</option>
123
+ <option>Courier New</option>
124
+ <option>Verdana</option>
125
+ </select>
126
+ <select id="font-size" class="bg-gray-800 border border-gray-700 rounded px-2 py-1 text-sm text-white hover:bg-gray-700">
127
+ <option>8</option>
128
+ <option>10</option>
129
+ <option>11</option>
130
+ <option selected>12</option>
131
+ <option>14</option>
132
+ <option>16</option>
133
+ <option>18</option>
134
+ <option>20</option>
135
+ <option>24</option>
136
+ </select>
137
+ <button id="bold" class="p-2 rounded hover:bg-gray-700 text-pink-400 format-button">
138
+ <i class="fas fa-bold"></i>
139
+ </button>
140
+ <button id="italic" class="p-2 rounded hover:bg-gray-700 text-red-400 format-button">
141
+ <i class="fas fa-italic"></i>
142
+ </button>
143
+ <button id="underline" class="p-2 rounded hover:bg-gray-700 text-orange-400 format-button">
144
+ <i class="fas fa-underline"></i>
145
+ </button>
146
+ <div class="border-l border-gray-700 h-6 mx-1"></div>
147
+ <button id="align-left" class="p-2 rounded hover:bg-gray-700 text-cyan-400 format-button">
148
+ <i class="fas fa-align-left"></i>
149
+ </button>
150
+ <button id="align-center" class="p-2 rounded hover:bg-gray-700 text-emerald-400 format-button">
151
+ <i class="fas fa-align-center"></i>
152
+ </button>
153
+ <button id="align-right" class="p-2 rounded hover:bg-gray-700 text-blue-400 format-button">
154
+ <i class="fas fa-align-right"></i>
155
+ </button>
156
+ <div class="border-l border-gray-700 h-6 mx-1"></div>
157
+ <div class="relative">
158
+ <button id="text-color" class="p-2 rounded hover:bg-gray-700 text-yellow-400 flex items-center">
159
+ <i class="fas fa-font"></i>
160
+ <span id="text-color-preview" class="color-preview"></span>
161
+ </button>
162
+ </div>
163
+ <div class="relative">
164
+ <button id="fill-color" class="p-2 rounded hover:bg-gray-700 text-green-400 flex items-center">
165
+ <i class="fas fa-fill-drip"></i>
166
+ <span id="fill-color-preview" class="color-preview"></span>
167
+ </button>
168
+ </div>
169
+ <button id="border-style" class="p-2 rounded hover:bg-gray-700 text-purple-400">
170
+ <i class="fas fa-border-all"></i>
171
+ </button>
172
+ <button id="remove-colors" class="p-2 rounded hover:bg-gray-700 text-red-400">
173
+ <i class="fas fa-palette"></i> <i class="fas fa-slash"></i>
174
+ </button>
175
+ </div>
176
+
177
+ <!-- F贸rmulas y Datos -->
178
+ <div class="ml-auto flex items-center space-x-2">
179
+ <button id="insert-function" class="px-3 py-1 rounded hover:bg-gray-700 text-indigo-400">
180
+ <i class="fas fa-sigma mr-1"></i> Fx
181
+ </button>
182
+ <button id="sort-asc" class="p-2 rounded hover:bg-gray-700 text-blue-400">
183
+ <i class="fas fa-sort-amount-up"></i>
184
+ </button>
185
+ <button id="sort-desc" class="p-2 rounded hover:bg-gray-700 text-red-400">
186
+ <i class="fas fa-sort-amount-down"></i>
187
+ </button>
188
+ <button id="filter" class="p-2 rounded hover:bg-gray-700 text-rose-400">
189
+ <i class="fas fa-filter"></i>
190
+ </button>
191
+ <button id="chart" class="p-2 rounded hover:bg-gray-700 text-green-400">
192
+ <i class="fas fa-chart-line"></i>
193
+ </button>
194
+ </div>
195
+ </div>
196
+
197
+ <!-- Pesta帽as de Hojas -->
198
+ <div class="bg-gray-900 p-1 flex items-center border-b border-gray-700">
199
+ <button id="add-sheet" class="px-2 py-1 rounded hover:bg-gray-700 text-green-400">
200
+ <i class="fas fa-plus"></i>
201
+ </button>
202
+ <div class="flex ml-2 overflow-x-auto">
203
+ <button class="px-3 py-1 rounded-l hover:bg-gray-700 text-sm font-medium tab-active">
204
+ Hoja1
205
+ </button>
206
+ <button class="px-3 py-1 hover:bg-gray-700 text-sm font-medium text-gray-400">
207
+ Hoja2
208
+ </button>
209
+ <button class="px-3 py-1 rounded-r hover:bg-gray-700 text-sm font-medium text-gray-400">
210
+ Hoja3
211
+ </button>
212
+ </div>
213
+ </div>
214
+
215
+ <!-- Formula Bar -->
216
+ <div class="bg-gray-900 p-1 flex items-center border-b border-gray-700">
217
+ <div id="cell-reference" class="w-16 text-center text-sm font-mono text-blue-400">A1</div>
218
+ <div class="flex-1 flex">
219
+ <input type="text" id="formula-input" class="bg-gray-800 border border-gray-700 rounded-l px-2 py-1 text-sm w-full font-mono focus:outline-none focus:ring-1 focus:ring-blue-500" placeholder="Introduce f贸rmula...">
220
+ <button id="apply-formula" class="bg-blue-600 hover:bg-blue-700 px-3 rounded-r">
221
+ <i class="fas fa-check"></i>
222
+ </button>
223
+ </div>
224
+ <div class="ml-2 text-xs text-gray-400">
225
+ <span id="formula-help">F2 para editar celda, Enter para confirmar</span>
226
+ </div>
227
+ </div>
228
+
229
+ <!-- Main Grid -->
230
+ <div class="flex-1 flex overflow-hidden">
231
+ <!-- Row Numbers -->
232
+ <div class="bg-gray-900 border-r border-gray-700 overflow-hidden" id="row-numbers">
233
+ <div class="w-10 h-8 flex items-center justify-center text-xs text-gray-400 border-b border-gray-700"></div>
234
+ <!-- Rows will be added dynamically -->
235
+ </div>
236
+
237
+ <!-- Column Headers + Grid -->
238
+ <div class="flex-1 flex flex-col overflow-hidden">
239
+ <!-- Column Headers -->
240
+ <div class="bg-gray-900 border-b border-gray-700 flex" id="column-headers">
241
+ <!-- Columns will be added dynamically -->
242
+ </div>
243
+
244
+ <!-- Grid Container -->
245
+ <div class="flex-1 overflow-auto relative scroll-shadow-right scroll-shadow-bottom" id="grid-container">
246
+ <div id="grid" class="absolute"></div>
247
+ </div>
248
+ </div>
249
+ </div>
250
+
251
+ <!-- Status Bar -->
252
+ <div class="bg-gray-900 p-1 flex items-center border-t border-gray-700 text-xs">
253
+ <div class="flex space-x-4">
254
+ <span id="status" class="text-green-400">Listo</span>
255
+ <span id="num-lock" class="text-yellow-400 hidden">NUM</span>
256
+ <span id="caps-lock" class="text-blue-400 hidden">MAY脷S</span>
257
+ <span id="selection-info" class="text-purple-400">1 celda seleccionada</span>
258
+ </div>
259
+ <div class="ml-auto flex space-x-2">
260
+ <span class="text-pink-400">Zoom: 100%</span>
261
+ <button id="zoom-out" class="text-pink-400 hover:bg-gray-700 px-1 rounded">-</button>
262
+ <button id="zoom-in" class="text-pink-400 hover:bg-gray-700 px-1 rounded">+</button>
263
+ <button id="zoom-reset" class="text-pink-400 hover:bg-gray-700 px-1 rounded">100%</button>
264
+ </div>
265
+ </div>
266
+
267
+ <!-- Color Picker (hidden by default) -->
268
+ <div id="color-picker" class="hidden absolute bg-gray-800 border border-gray-700 rounded shadow-lg p-2 z-50">
269
+ <div class="grid grid-cols-8 gap-1">
270
+ <div class="w-4 h-4 bg-red-500 hover:border hover:border-white cursor-pointer" data-color="#ef4444"></div>
271
+ <div class="w-4 h-4 bg-orange-500 hover:border hover:border-white cursor-pointer" data-color="#f97316"></div>
272
+ <div class="w-4 h-4 bg-yellow-500 hover:border hover:border-white cursor-pointer" data-color="#eab308"></div>
273
+ <div class="w-4 h-4 bg-green-500 hover:border hover:border-white cursor-pointer" data-color="#22c55e"></div>
274
+ <div class="w-4 h-4 bg-emerald-500 hover:border hover:border-white cursor-pointer" data-color="#10b981"></div>
275
+ <div class="w-4 h-4 bg-cyan-500 hover:border hover:border-white cursor-pointer" data-color="#06b6d4"></div>
276
+ <div class="w-4 h-4 bg-blue-500 hover:border hover:border-white cursor-pointer" data-color="#3b82f6"></div>
277
+ <div class="w-4 h-4 bg-indigo-500 hover:border hover:border-white cursor-pointer" data-color="#6366f1"></div>
278
+ <div class="w-4 h-4 bg-purple-500 hover:border hover:border-white cursor-pointer" data-color="#8b5cf6"></div>
279
+ <div class="w-4 h-4 bg-pink-500 hover:border hover:border-white cursor-pointer" data-color="#ec4899"></div>
280
+ <div class="w-4 h-4 bg-rose-500 hover:border hover:border-white cursor-pointer" data-color="#f43f5e"></div>
281
+ <div class="w-4 h-4 bg-amber-500 hover:border hover:border-white cursor-pointer" data-color="#f59e0b"></div>
282
+ <div class="w-4 h-4 bg-lime-500 hover:border hover:border-white cursor-pointer" data-color="#84cc16"></div>
283
+ <div class="w-4 h-4 bg-teal-500 hover:border hover:border-white cursor-pointer" data-color="#14b8a6"></div>
284
+ <div class="w-4 h-4 bg-sky-500 hover:border hover:border-white cursor-pointer" data-color="#0ea5e9"></div>
285
+ <div class="w-4 h-4 bg-violet-500 hover:border hover:border-white cursor-pointer" data-color="#8b5cf6"></div>
286
+ </div>
287
+ <div class="mt-2 flex justify-between">
288
+ <button id="color-picker-cancel" class="px-2 py-1 text-xs bg-gray-700 rounded hover:bg-gray-600">Cancelar</button>
289
+ <button id="color-picker-apply" class="px-2 py-1 text-xs bg-blue-600 rounded hover:bg-blue-700">Aplicar</button>
290
+ <button id="color-picker-remove" class="px-2 py-1 text-xs bg-red-600 rounded hover:bg-red-700">Quitar</button>
291
+ </div>
292
+ </div>
293
+
294
+ <script>
295
+ document.addEventListener('DOMContentLoaded', function() {
296
+ // Configuration
297
+ const ROWS = 50;
298
+ const COLS = 26;
299
+ const CELL_WIDTH = 100;
300
+ const CELL_HEIGHT = 25;
301
+ const HEADER_HEIGHT = 25;
302
+
303
+ // State
304
+ let selectedCell = null;
305
+ let editingCell = null;
306
+ let data = {};
307
+ let formulas = {};
308
+ let cellWidths = {};
309
+ let cellHeights = {};
310
+ let cellStyles = {};
311
+ let activeSheet = 'Hoja1';
312
+ let sheets = {
313
+ 'Hoja1': { data: {}, formulas: {}, cellStyles: {} },
314
+ 'Hoja2': { data: {}, formulas: {}, cellStyles: {} },
315
+ 'Hoja3': { data: {}, formulas: {}, cellStyles: {} }
316
+ };
317
+ let history = [];
318
+ let historyIndex = -1;
319
+ let isBold = false;
320
+ let isItalic = false;
321
+ let isUnderline = false;
322
+ let textAlign = 'left';
323
+ let currentColorPickerType = null;
324
+ let defaultTextColor = '#ffffff'; // Blanco
325
+ let defaultFillColor = 'transparent'; // Transparente
326
+
327
+ // DOM Elements
328
+ const grid = document.getElementById('grid');
329
+ const gridContainer = document.getElementById('grid-container');
330
+ const columnHeaders = document.getElementById('column-headers');
331
+ const rowNumbers = document.getElementById('row-numbers');
332
+ const formulaInput = document.getElementById('formula-input');
333
+ const cellReference = document.getElementById('cell-reference');
334
+ const statusElement = document.getElementById('status');
335
+ const selectionInfo = document.getElementById('selection-info');
336
+ const colorPicker = document.getElementById('color-picker');
337
+ const numLockElement = document.getElementById('num-lock');
338
+ const capsLockElement = document.getElementById('caps-lock');
339
+ const textColorPreview = document.getElementById('text-color-preview');
340
+ const fillColorPreview = document.getElementById('fill-color-preview');
341
+
342
+ // Initialize grid
343
+ function initGrid() {
344
+ // Set grid dimensions
345
+ grid.style.width = `${COLS * CELL_WIDTH}px`;
346
+ grid.style.height = `${ROWS * CELL_HEIGHT}px`;
347
+
348
+ // Create column headers (A, B, C...)
349
+ for (let col = 0; col < COLS; col++) {
350
+ const colHeader = document.createElement('div');
351
+ const colLetter = String.fromCharCode(65 + col);
352
+ colHeader.className = 'h-8 flex items-center justify-center text-xs text-gray-400 border-b border-gray-700 relative';
353
+ colHeader.style.width = `${CELL_WIDTH}px`;
354
+ colHeader.textContent = colLetter;
355
+
356
+ // Add resize handle
357
+ const resizeHandle = document.createElement('div');
358
+ resizeHandle.className = 'column-resize-handle';
359
+ resizeHandle.dataset.col = col;
360
+ resizeHandle.addEventListener('mousedown', startColumnResize);
361
+ colHeader.appendChild(resizeHandle);
362
+
363
+ columnHeaders.appendChild(colHeader);
364
+ }
365
+
366
+ // Create row numbers (1, 2, 3...)
367
+ for (let row = 1; row <= ROWS; row++) {
368
+ const rowNumber = document.createElement('div');
369
+ rowNumber.className = 'w-10 h-8 flex items-center justify-center text-xs text-gray-400 border-b border-gray-700 relative';
370
+ rowNumber.textContent = row;
371
+
372
+ // Add resize handle
373
+ const resizeHandle = document.createElement('div');
374
+ resizeHandle.className = 'row-resize-handle';
375
+ resizeHandle.dataset.row = row - 1;
376
+ resizeHandle.addEventListener('mousedown', startRowResize);
377
+ rowNumber.appendChild(resizeHandle);
378
+
379
+ rowNumbers.appendChild(rowNumber);
380
+ }
381
+
382
+ // Create cells
383
+ for (let row = 0; row < ROWS; row++) {
384
+ for (let col = 0; col < COLS; col++) {
385
+ const cell = document.createElement('div');
386
+ const cellId = `${String.fromCharCode(65 + col)}${row + 1}`;
387
+
388
+ cell.className = 'cell absolute bg-gray-800 border border-gray-700 p-1 overflow-hidden text-sm';
389
+ cell.style.width = `${CELL_WIDTH}px`;
390
+ cell.style.height = `${CELL_HEIGHT}px`;
391
+ cell.style.left = `${col * CELL_WIDTH}px`;
392
+ cell.style.top = `${row * CELL_HEIGHT}px`;
393
+ cell.dataset.row = row;
394
+ cell.dataset.col = col;
395
+ cell.dataset.id = cellId;
396
+
397
+ cell.addEventListener('click', handleCellClick);
398
+ cell.addEventListener('dblclick', handleCellDoubleClick);
399
+
400
+ grid.appendChild(cell);
401
+ }
402
+ }
403
+
404
+ // Set default color previews
405
+ textColorPreview.style.backgroundColor = defaultTextColor;
406
+ fillColorPreview.style.backgroundColor = defaultFillColor;
407
+
408
+ // Add initial state to history
409
+ saveState();
410
+ }
411
+
412
+ // Handle cell click
413
+ function handleCellClick(e) {
414
+ const cell = e.currentTarget;
415
+ const cellId = cell.dataset.id;
416
+
417
+ // Remove previous selection
418
+ if (selectedCell) {
419
+ selectedCell.classList.remove('selected');
420
+ }
421
+
422
+ // Set new selection
423
+ selectedCell = cell;
424
+ cell.classList.add('selected');
425
+
426
+ // Update formula bar
427
+ formulaInput.value = formulas[cellId] || data[cellId] || '';
428
+ formulaInput.focus();
429
+
430
+ // Update cell reference
431
+ cellReference.textContent = cellId;
432
+
433
+ // Update selection info
434
+ selectionInfo.textContent = "1 celda seleccionada";
435
+
436
+ // Update status
437
+ statusElement.textContent = "Listo";
438
+
439
+ // Update format buttons based on cell style
440
+ updateFormatButtons(cellId);
441
+ }
442
+
443
+ // Update format buttons based on cell style
444
+ function updateFormatButtons(cellId) {
445
+ // Reset all format buttons
446
+ document.querySelectorAll('.format-button').forEach(btn => btn.classList.remove('active'));
447
+
448
+ if (cellStyles[cellId]) {
449
+ const style = cellStyles[cellId];
450
+
451
+ // Bold
452
+ if (style.bold) {
453
+ document.getElementById('bold').classList.add('active');
454
+ }
455
+
456
+ // Italic
457
+ if (style.italic) {
458
+ document.getElementById('italic').classList.add('active');
459
+ }
460
+
461
+ // Underline
462
+ if (style.underline) {
463
+ document.getElementById('underline').classList.add('active');
464
+ }
465
+
466
+ // Text align
467
+ if (style.textAlign) {
468
+ document.getElementById(`align-${style.textAlign}`).classList.add('active');
469
+ }
470
+
471
+ // Update color previews
472
+ if (style.color) {
473
+ textColorPreview.style.backgroundColor = style.color;
474
+ } else {
475
+ textColorPreview.style.backgroundColor = defaultTextColor;
476
+ }
477
+
478
+ if (style.backgroundColor) {
479
+ fillColorPreview.style.backgroundColor = style.backgroundColor;
480
+ } else {
481
+ fillColorPreview.style.backgroundColor = defaultFillColor;
482
+ }
483
+ }
484
+ }
485
+
486
+ // Handle cell double click (edit mode)
487
+ function handleCellDoubleClick(e) {
488
+ const cell = e.currentTarget;
489
+ const cellId = cell.dataset.id;
490
+
491
+ // Exit previous edit mode
492
+ if (editingCell) {
493
+ exitEditMode();
494
+ }
495
+
496
+ // Enter edit mode
497
+ editingCell = cell;
498
+ cell.classList.add('editing');
499
+
500
+ // Create input element
501
+ const input = document.createElement('input');
502
+ input.type = 'text';
503
+ input.className = 'w-full h-full bg-gray-800 text-white px-1 outline-none';
504
+ input.value = data[cellId] || '';
505
+ input.dataset.cellId = cellId;
506
+
507
+ // Apply cell styles to input
508
+ if (cellStyles[cellId]) {
509
+ if (cellStyles[cellId].bold) input.style.fontWeight = 'bold';
510
+ if (cellStyles[cellId].italic) input.style.fontStyle = 'italic';
511
+ if (cellStyles[cellId].underline) input.style.textDecoration = 'underline';
512
+ if (cellStyles[cellId].textAlign) input.style.textAlign = cellStyles[cellId].textAlign;
513
+ if (cellStyles[cellId].color) input.style.color = cellStyles[cellId].color;
514
+ if (cellStyles[cellId].backgroundColor) input.style.backgroundColor = cellStyles[cellId].backgroundColor;
515
+ if (cellStyles[cellId].fontSize) input.style.fontSize = cellStyles[cellId].fontSize + 'px';
516
+ if (cellStyles[cellId].fontFamily) input.style.fontFamily = cellStyles[cellId].fontFamily;
517
+ }
518
+
519
+ // Clear cell content and add input
520
+ cell.innerHTML = '';
521
+ cell.appendChild(input);
522
+ input.focus();
523
+
524
+ // Handle input events
525
+ input.addEventListener('blur', handleInputBlur);
526
+ input.addEventListener('keydown', handleInputKeyDown);
527
+
528
+ // Update status
529
+ statusElement.textContent = "Editando";
530
+ }
531
+
532
+ // Exit edit mode
533
+ function exitEditMode() {
534
+ if (!editingCell) return;
535
+
536
+ const cell = editingCell;
537
+ const cellId = cell.dataset.id;
538
+ const input = cell.querySelector('input');
539
+
540
+ if (input) {
541
+ // Save data
542
+ const value = input.value.trim();
543
+ if (value.startsWith('=')) {
544
+ formulas[cellId] = value;
545
+ try {
546
+ data[cellId] = evaluateFormula(value.substring(1));
547
+ } catch (e) {
548
+ data[cellId] = '#ERROR!';
549
+ }
550
+ } else {
551
+ data[cellId] = value;
552
+ delete formulas[cellId];
553
+ }
554
+
555
+ // Update cell display
556
+ cell.innerHTML = '';
557
+ cell.textContent = data[cellId] || '';
558
+
559
+ // Apply styles
560
+ applyCellStyles(cell, cellId);
561
+ }
562
+
563
+ cell.classList.remove('editing');
564
+ editingCell = null;
565
+
566
+ // Save state to history
567
+ saveState();
568
+
569
+ // Update status
570
+ statusElement.textContent = "Listo";
571
+ }
572
+
573
+ // Apply cell styles
574
+ function applyCellStyles(cell, cellId) {
575
+ // Reset to defaults first
576
+ cell.style = '';
577
+ cell.className = 'cell absolute bg-gray-800 border border-gray-700 p-1 overflow-hidden text-sm';
578
+
579
+ if (cellStyles[cellId]) {
580
+ const style = cellStyles[cellId];
581
+ if (style.bold) cell.style.fontWeight = 'bold';
582
+ if (style.italic) cell.style.fontStyle = 'italic';
583
+ if (style.underline) cell.style.textDecoration = 'underline';
584
+ if (style.textAlign) cell.style.textAlign = style.textAlign;
585
+ if (style.color) cell.style.color = style.color;
586
+ if (style.backgroundColor) cell.style.backgroundColor = style.backgroundColor;
587
+ if (style.fontSize) cell.style.fontSize = style.fontSize + 'px';
588
+ if (style.fontFamily) cell.style.fontFamily = style.fontFamily;
589
+ }
590
+
591
+ // Update color previews
592
+ updateColorPreviews(cellId);
593
+ }
594
+
595
+ // Update color previews
596
+ function updateColorPreviews(cellId) {
597
+ if (cellStyles[cellId]) {
598
+ if (cellStyles[cellId].color) {
599
+ textColorPreview.style.backgroundColor = cellStyles[cellId].color;
600
+ } else {
601
+ textColorPreview.style.backgroundColor = defaultTextColor;
602
+ }
603
+
604
+ if (cellStyles[cellId].backgroundColor) {
605
+ fillColorPreview.style.backgroundColor = cellStyles[cellId].backgroundColor;
606
+ } else {
607
+ fillColorPreview.style.backgroundColor = defaultFillColor;
608
+ }
609
+ } else {
610
+ textColorPreview.style.backgroundColor = defaultTextColor;
611
+ fillColorPreview.style.backgroundColor = defaultFillColor;
612
+ }
613
+ }
614
+
615
+ // Handle input blur (exit edit mode)
616
+ function handleInputBlur(e) {
617
+ exitEditMode();
618
+ }
619
+
620
+ // Handle input key events
621
+ function handleInputKeyDown(e) {
622
+ if (e.key === 'Enter') {
623
+ exitEditMode();
624
+ } else if (e.key === 'Escape') {
625
+ const input = e.currentTarget;
626
+ const cell = input.parentElement;
627
+
628
+ // Restore original content
629
+ cell.innerHTML = '';
630
+ cell.textContent = data[cell.dataset.id] || '';
631
+ applyCellStyles(cell, cell.dataset.id);
632
+
633
+ cell.classList.remove('editing');
634
+ editingCell = null;
635
+
636
+ // Update status
637
+ statusElement.textContent = "Listo";
638
+ }
639
+ }
640
+
641
+ // Simple formula evaluation (very basic implementation)
642
+ function evaluateFormula(formula) {
643
+ // Basic SUM implementation
644
+ if (formula.toUpperCase().startsWith('SUM(')) {
645
+ const range = formula.match(/\((.*?)\)/)[1];
646
+ const [start, end] = range.split(':');
647
+
648
+ let sum = 0;
649
+ const startCol = start.charCodeAt(0) - 65;
650
+ const startRow = parseInt(start.substring(1)) - 1;
651
+ const endCol = end.charCodeAt(0) - 65;
652
+ const endRow = parseInt(end.substring(1)) - 1;
653
+
654
+ for (let row = startRow; row <= endRow; row++) {
655
+ for (let col = startCol; col <= endCol; col++) {
656
+ const cellId = `${String.fromCharCode(65 + col)}${row + 1}`;
657
+ const value = parseFloat(data[cellId]) || 0;
658
+ sum += value;
659
+ }
660
+ }
661
+
662
+ return sum;
663
+ }
664
+
665
+ // Basic arithmetic
666
+ if (formula.includes('+')) {
667
+ const parts = formula.split('+');
668
+ return (parseFloat(parts[0]) || 0) + (parseFloat(parts[1]) || 0);
669
+ }
670
+ if (formula.includes('-')) {
671
+ const parts = formula.split('-');
672
+ return (parseFloat(parts[0]) || 0) - (parseFloat(parts[1]) || 0);
673
+ }
674
+ if (formula.includes('*')) {
675
+ const parts = formula.split('*');
676
+ return (parseFloat(parts[0]) || 0) * (parseFloat(parts[1]) || 0);
677
+ }
678
+ if (formula.includes('/')) {
679
+ const parts = formula.split('/');
680
+ return (parseFloat(parts[0]) || 0) / (parseFloat(parts[1]) || 1);
681
+ }
682
+
683
+ // Cell reference
684
+ if (/^[A-Z]+\d+$/.test(formula)) {
685
+ return data[formula] || 0;
686
+ }
687
+
688
+ return formula; // Return as is if not a recognized formula
689
+ }
690
+
691
+ // Handle column resize
692
+ let isResizingColumn = false;
693
+ let resizingCol = null;
694
+ let startX = 0;
695
+ let startWidth = 0;
696
+
697
+ function startColumnResize(e) {
698
+ e.preventDefault();
699
+ e.stopPropagation();
700
+
701
+ isResizingColumn = true;
702
+ resizingCol = parseInt(e.currentTarget.dataset.col);
703
+ startX = e.clientX;
704
+ startWidth = CELL_WIDTH;
705
+
706
+ document.addEventListener('mousemove', handleColumnResize);
707
+ document.addEventListener('mouseup', stopColumnResize);
708
+
709
+ // Update status
710
+ statusElement.textContent = "Redimensionando columna";
711
+ }
712
+
713
+ function handleColumnResize(e) {
714
+ if (!isResizingColumn) return;
715
+
716
+ const dx = e.clientX - startX;
717
+ const newWidth = Math.max(30, startWidth + dx);
718
+
719
+ // Update column width
720
+ const colLetter = String.fromCharCode(65 + resizingCol);
721
+ cellWidths[colLetter] = newWidth;
722
+
723
+ // Update header
724
+ columnHeaders.children[resizingCol].style.width = `${newWidth}px`;
725
+
726
+ // Update all cells in this column
727
+ const cells = document.querySelectorAll(`.cell[data-col="${resizingCol}"]`);
728
+ cells.forEach(cell => {
729
+ cell.style.width = `${newWidth}px`;
730
+ });
731
+
732
+ // Update grid width
733
+ updateGridDimensions();
734
+ }
735
+
736
+ function stopColumnResize() {
737
+ isResizingColumn = false;
738
+ document.removeEventListener('mousemove', handleColumnResize);
739
+ document.removeEventListener('mouseup', stopColumnResize);
740
+
741
+ // Save state to history
742
+ saveState();
743
+
744
+ // Update status
745
+ statusElement.textContent = "Listo";
746
+ }
747
+
748
+ // Handle row resize
749
+ let isResizingRow = false;
750
+ let resizingRow = null;
751
+ let startY = 0;
752
+ let startHeight = 0;
753
+
754
+ function startRowResize(e) {
755
+ e.preventDefault();
756
+ e.stopPropagation();
757
+
758
+ isResizingRow = true;
759
+ resizingRow = parseInt(e.currentTarget.dataset.row);
760
+ startY = e.clientY;
761
+ startHeight = CELL_HEIGHT;
762
+
763
+ document.addEventListener('mousemove', handleRowResize);
764
+ document.addEventListener('mouseup', stopRowResize);
765
+
766
+ // Update status
767
+ statusElement.textContent = "Redimensionando fila";
768
+ }
769
+
770
+ function handleRowResize(e) {
771
+ if (!isResizingRow) return;
772
+
773
+ const dy = e.clientY - startY;
774
+ const newHeight = Math.max(20, startHeight + dy);
775
+
776
+ // Update row height
777
+ cellHeights[resizingRow + 1] = newHeight;
778
+
779
+ // Update row number display
780
+ rowNumbers.children[resizingRow + 1].style.height = `${newHeight}px`;
781
+
782
+ // Update all cells in this row
783
+ const cells = document.querySelectorAll(`.cell[data-row="${resizingRow}"]`);
784
+ cells.forEach(cell => {
785
+ cell.style.height = `${newHeight}px`;
786
+ });
787
+
788
+ // Update grid height
789
+ updateGridDimensions();
790
+ }
791
+
792
+ function stopRowResize() {
793
+ isResizingRow = false;
794
+ document.removeEventListener('mousemove', handleRowResize);
795
+ document.removeEventListener('mouseup', stopRowResize);
796
+
797
+ // Save state to history
798
+ saveState();
799
+
800
+ // Update status
801
+ statusElement.textContent = "Listo";
802
+ }
803
+
804
+ // Update grid dimensions after resize
805
+ function updateGridDimensions() {
806
+ let totalWidth = 0;
807
+ for (let col = 0; col < COLS; col++) {
808
+ const colLetter = String.fromCharCode(65 + col);
809
+ totalWidth += cellWidths[colLetter] || CELL_WIDTH;
810
+ }
811
+
812
+ let totalHeight = 0;
813
+ for (let row = 0; row < ROWS; row++) {
814
+ totalHeight += cellHeights[row + 1] || CELL_HEIGHT;
815
+ }
816
+
817
+ grid.style.width = `${totalWidth}px`;
818
+ grid.style.height = `${totalHeight}px`;
819
+ }
820
+
821
+ // Handle formula input
822
+ formulaInput.addEventListener('keydown', function(e) {
823
+ if (e.key === 'Enter' && selectedCell) {
824
+ const value = formulaInput.value.trim();
825
+ const cellId = selectedCell.dataset.id;
826
+
827
+ if (value.startsWith('=')) {
828
+ formulas[cellId] = value;
829
+ try {
830
+ data[cellId] = evaluateFormula(value.substring(1));
831
+ } catch (e) {
832
+ data[cellId] = '#ERROR!';
833
+ }
834
+ } else {
835
+ data[cellId] = value;
836
+ delete formulas[cellId];
837
+ }
838
+
839
+ selectedCell.textContent = data[cellId] || '';
840
+ formulaInput.blur();
841
+
842
+ // Save state to history
843
+ saveState();
844
+ }
845
+ });
846
+
847
+ // Apply formula button
848
+ document.getElementById('apply-formula').addEventListener('click', function() {
849
+ if (selectedCell) {
850
+ const value = formulaInput.value.trim();
851
+ const cellId = selectedCell.dataset.id;
852
+
853
+ if (value.startsWith('=')) {
854
+ formulas[cellId] = value;
855
+ try {
856
+ data[cellId] = evaluateFormula(value.substring(1));
857
+ } catch (e) {
858
+ data[cellId] = '#ERROR!';
859
+ }
860
+ } else {
861
+ data[cellId] = value;
862
+ delete formulas[cellId];
863
+ }
864
+
865
+ selectedCell.textContent = data[cellId] || '';
866
+
867
+ // Save state to history
868
+ saveState();
869
+ }
870
+ });
871
+
872
+ // Format buttons
873
+ document.getElementById('bold').addEventListener('click', function() {
874
+ if (selectedCell) {
875
+ const cellId = selectedCell.dataset.id;
876
+
877
+ // Initialize cell style if not exists
878
+ if (!cellStyles[cellId]) {
879
+ cellStyles[cellId] = {};
880
+ }
881
+
882
+ // Toggle bold
883
+ cellStyles[cellId].bold = !cellStyles[cellId].bold;
884
+ selectedCell.style.fontWeight = cellStyles[cellId].bold ? 'bold' : 'normal';
885
+
886
+ // Toggle active class
887
+ this.classList.toggle('active');
888
+
889
+ // Save state to history
890
+ saveState();
891
+ }
892
+ });
893
+
894
+ document.getElementById('italic').addEventListener('click', function() {
895
+ if (selectedCell) {
896
+ const cellId = selectedCell.dataset.id;
897
+
898
+ if (!cellStyles[cellId]) {
899
+ cellStyles[cellId] = {};
900
+ }
901
+
902
+ cellStyles[cellId].italic = !cellStyles[cellId].italic;
903
+ selectedCell.style.fontStyle = cellStyles[cellId].italic ? 'italic' : 'normal';
904
+
905
+ this.classList.toggle('active');
906
+ saveState();
907
+ }
908
+ });
909
+
910
+ document.getElementById('underline').addEventListener('click', function() {
911
+ if (selectedCell) {
912
+ const cellId = selectedCell.dataset.id;
913
+
914
+ if (!cellStyles[cellId]) {
915
+ cellStyles[cellId] = {};
916
+ }
917
+
918
+ cellStyles[cellId].underline = !cellStyles[cellId].underline;
919
+ selectedCell.style.textDecoration = cellStyles[cellId].underline ? 'underline' : 'none';
920
+
921
+ this.classList.toggle('active');
922
+ saveState();
923
+ }
924
+ });
925
+
926
+ // Alignment buttons
927
+ document.getElementById('align-left').addEventListener('click', function() {
928
+ if (selectedCell) {
929
+ const cellId = selectedCell.dataset.id;
930
+
931
+ if (!cellStyles[cellId]) {
932
+ cellStyles[cellId] = {};
933
+ }
934
+
935
+ cellStyles[cellId].textAlign = 'left';
936
+ selectedCell.style.textAlign = 'left';
937
+
938
+ // Update active state
939
+ document.querySelectorAll('.format-button').forEach(btn => btn.classList.remove('active'));
940
+ this.classList.add('active');
941
+
942
+ saveState();
943
+ }
944
+ });
945
+
946
+ document.getElementById('align-center').addEventListener('click', function() {
947
+ if (selectedCell) {
948
+ const cellId = selectedCell.dataset.id;
949
+
950
+ if (!cellStyles[cellId]) {
951
+ cellStyles[cellId] = {};
952
+ }
953
+
954
+ cellStyles[cellId].textAlign = 'center';
955
+ selectedCell.style.textAlign = 'center';
956
+
957
+ document.querySelectorAll('.format-button').forEach(btn => btn.classList.remove('active'));
958
+ this.classList.add('active');
959
+
960
+ saveState();
961
+ }
962
+ });
963
+
964
+ document.getElementById('align-right').addEventListener('click', function() {
965
+ if (selectedCell) {
966
+ const cellId = selectedCell.dataset.id;
967
+
968
+ if (!cellStyles[cellId]) {
969
+ cellStyles[cellId] = {};
970
+ }
971
+
972
+ cellStyles[cellId].textAlign = 'right';
973
+ selectedCell.style.textAlign = 'right';
974
+
975
+ document.querySelectorAll('.format-button').forEach(btn => btn.classList.remove('active'));
976
+ this.classList.add('active');
977
+
978
+ saveState();
979
+ }
980
+ });
981
+
982
+ // Font family change
983
+ document.getElementById('font-family').addEventListener('change', function() {
984
+ if (selectedCell) {
985
+ const cellId = selectedCell.dataset.id;
986
+
987
+ if (!cellStyles[cellId]) {
988
+ cellStyles[cellId] = {};
989
+ }
990
+
991
+ cellStyles[cellId].fontFamily = this.value;
992
+ selectedCell.style.fontFamily = this.value;
993
+
994
+ saveState();
995
+ }
996
+ });
997
+
998
+ // Font size change
999
+ document.getElementById('font-size').addEventListener('change', function() {
1000
+ if (selectedCell) {
1001
+ const cellId = selectedCell.dataset.id;
1002
+
1003
+ if (!cellStyles[cellId]) {
1004
+ cellStyles[cellId] = {};
1005
+ }
1006
+
1007
+ cellStyles[cellId].fontSize = parseInt(this.value);
1008
+ selectedCell.style.fontSize = this.value + 'px';
1009
+
1010
+ saveState();
1011
+ }
1012
+ });
1013
+
1014
+ // Text color button
1015
+ document.getElementById('text-color').addEventListener('click', function(e) {
1016
+ currentColorPickerType = 'text';
1017
+ showColorPicker(e.currentTarget);
1018
+ });
1019
+
1020
+ // Fill color button
1021
+ document.getElementById('fill-color').addEventListener('click', function(e) {
1022
+ currentColorPickerType = 'background';
1023
+ showColorPicker(e.currentTarget);
1024
+ });
1025
+
1026
+ // Remove colors button
1027
+ document.getElementById('remove-colors').addEventListener('click', function() {
1028
+ if (selectedCell) {
1029
+ const cellId = selectedCell.dataset.id;
1030
+
1031
+ if (cellStyles[cellId]) {
1032
+ // Remove color properties
1033
+ delete cellStyles[cellId].color;
1034
+ delete cellStyles[cellId].backgroundColor;
1035
+
1036
+ // Apply changes
1037
+ applyCellStyles(selectedCell, cellId);
1038
+
1039
+ // Save state
1040
+ saveState();
1041
+
1042
+ // Update status
1043
+ statusElement.textContent = "Colores eliminados";
1044
+ setTimeout(() => statusElement.textContent = "Listo", 2000);
1045
+ }
1046
+ }
1047
+ });
1048
+
1049
+ // Show color picker
1050
+ function showColorPicker(target) {
1051
+ const rect = target.getBoundingClientRect();
1052
+ colorPicker.style.top = `${rect.bottom + 5}px`;
1053
+ colorPicker.style.left = `${rect.left}px`;
1054
+ colorPicker.classList.remove('hidden');
1055
+ }
1056
+
1057
+ // Color picker selection
1058
+ colorPicker.querySelectorAll('[data-color]').forEach(color => {
1059
+ color.addEventListener('click', function() {
1060
+ const selectedColor = this.dataset.color;
1061
+
1062
+ if (selectedCell && currentColorPickerType) {
1063
+ const cellId = selectedCell.dataset.id;
1064
+
1065
+ if (!cellStyles[cellId]) {
1066
+ cellStyles[cellId] = {};
1067
+ }
1068
+
1069
+ if (currentColorPickerType === 'text') {
1070
+ cellStyles[cellId].color = selectedColor;
1071
+ selectedCell.style.color = selectedColor;
1072
+ textColorPreview.style.backgroundColor = selectedColor;
1073
+ } else {
1074
+ cellStyles[cellId].backgroundColor = selectedColor;
1075
+ selectedCell.style.backgroundColor = selectedColor;
1076
+ fillColorPreview.style.backgroundColor = selectedColor;
1077
+ }
1078
+
1079
+ saveState();
1080
+ }
1081
+
1082
+ colorPicker.classList.add('hidden');
1083
+ });
1084
+ });
1085
+
1086
+ // Color picker remove
1087
+ document.getElementById('color-picker-remove').addEventListener('click', function() {
1088
+ if (selectedCell && currentColorPickerType) {
1089
+ const cellId = selectedCell.dataset.id;
1090
+
1091
+ if (cellStyles[cellId]) {
1092
+ if (currentColorPickerType === 'text') {
1093
+ delete cellStyles[cellId].color;
1094
+ selectedCell.style.color = '';
1095
+ textColorPreview.style.backgroundColor = defaultTextColor;
1096
+ } else {
1097
+ delete cellStyles[cellId].backgroundColor;
1098
+ selectedCell.style.backgroundColor = '';
1099
+ fillColorPreview.style.backgroundColor = defaultFillColor;
1100
+ }
1101
+
1102
+ saveState();
1103
+ }
1104
+ }
1105
+
1106
+ colorPicker.classList.add('hidden');
1107
+ });
1108
+
1109
+ // Color picker cancel
1110
+ document.getElementById('color-picker-cancel').addEventListener('click', function() {
1111
+ colorPicker.classList.add('hidden');
1112
+ });
1113
+
1114
+ // Clear contents button
1115
+ document.getElementById('clear-contents').addEventListener('click', function() {
1116
+ if (selectedCell) {
1117
+ const cellId = selectedCell.dataset.id;
1118
+
1119
+ // Clear data and formulas but keep formatting
1120
+ delete data[cellId];
1121
+ delete formulas[cellId];
1122
+
1123
+ selectedCell.textContent = '';
1124
+
1125
+ // Save state
1126
+ saveState();
1127
+
1128
+ // Update status
1129
+ statusElement.textContent = "Contenido eliminado";
1130
+ setTimeout(() => statusElement.textContent = "Listo", 2000);
1131
+ }
1132
+ });
1133
+
1134
+ // Clear formats button
1135
+ document.getElementById('clear-formats').addEventListener('click', function() {
1136
+ if (selectedCell) {
1137
+ const cellId = selectedCell.dataset.id;
1138
+
1139
+ // Remove all formatting
1140
+ delete cellStyles[cellId];
1141
+
1142
+ // Reset cell styles
1143
+ selectedCell.style = '';
1144
+ selectedCell.className = 'cell absolute bg-gray-800 border border-gray-700 p-1 overflow-hidden text-sm selected';
1145
+
1146
+ // Reset color previews
1147
+ textColorPreview.style.backgroundColor = defaultTextColor;
1148
+ fillColorPreview.style.backgroundColor = defaultFillColor;
1149
+
1150
+ // Reset format buttons
1151
+ document.querySelectorAll('.format-button').forEach(btn => btn.classList.remove('active'));
1152
+
1153
+ // Save state
1154
+ saveState();
1155
+
1156
+ // Update status
1157
+ statusElement.textContent = "Formato eliminado";
1158
+ setTimeout(() => statusElement.textContent = "Listo", 2000);
1159
+ }
1160
+ });
1161
+
1162
+ // File operations
1163
+ document.getElementById('new-file').addEventListener('click', function() {
1164
+ if (confirm('驴Crear nuevo archivo? Se perder谩n los cambios no guardados.')) {
1165
+ // Reset all data
1166
+ data = {};
1167
+ formulas = {};
1168
+ cellStyles = {};
1169
+ cellWidths = {};
1170
+ cellHeights = {};
1171
+
1172
+ // Clear all cells
1173
+ document.querySelectorAll('.cell').forEach(cell => {
1174
+ cell.textContent = '';
1175
+ cell.style = '';
1176
+ cell.className = 'cell absolute bg-gray-800 border border-gray-700 p-1 overflow-hidden text-sm';
1177
+ });
1178
+
1179
+ // Reset column widths
1180
+ for (let col = 0; col < COLS; col++) {
1181
+ columnHeaders.children[col].style.width = `${CELL_WIDTH}px`;
1182
+ document.querySelectorAll(`.cell[data-col="${col}"]`).forEach(cell => {
1183
+ cell.style.width = `${CELL_WIDTH}px`;
1184
+ });
1185
+ }
1186
+
1187
+ // Reset row heights
1188
+ for (let row = 0; row < ROWS; row++) {
1189
+ rowNumbers.children[row + 1].style.height = `${CELL_HEIGHT}px`;
1190
+ document.querySelectorAll(`.cell[data-row="${row}"]`).forEach(cell => {
1191
+ cell.style.height = `${CELL_HEIGHT}px`;
1192
+ });
1193
+ }
1194
+
1195
+ // Reset grid dimensions
1196
+ grid.style.width = `${COLS * CELL_WIDTH}px`;
1197
+ grid.style.height = `${ROWS * CELL_HEIGHT}px`;
1198
+
1199
+ // Reset formula bar
1200
+ formulaInput.value = '';
1201
+ cellReference.textContent = 'A1';
1202
+
1203
+ // Reset color previews
1204
+ textColorPreview.style.backgroundColor = defaultTextColor;
1205
+ fillColorPreview.style.backgroundColor = defaultFillColor;
1206
+
1207
+ // Reset format buttons
1208
+ document.querySelectorAll('.format-button').forEach(btn => btn.classList.remove('active'));
1209
+
1210
+ // Save state
1211
+ saveState();
1212
+
1213
+ // Update status
1214
+ statusElement.textContent = "Nuevo archivo creado";
1215
+ setTimeout(() => statusElement.textContent = "Listo", 2000);
1216
+ }
1217
+ });
1218
+
1219
+ document.getElementById('save-file').addEventListener('click', function() {
1220
+ // In a real app, this would save to server or download file
1221
+ const excelData = {
1222
+ data: data,
1223
+ formulas: formulas,
1224
+ cellStyles: cellStyles,
1225
+ cellWidths: cellWidths,
1226
+ cellHeights: cellHeights
1227
+ };
1228
+
1229
+ console.log('Datos a guardar:', excelData);
1230
+ statusElement.textContent = "Archivo guardado (consola)";
1231
+ setTimeout(() => statusElement.textContent = "Listo", 2000);
1232
+ });
1233
+
1234
+ document.getElementById('export-pdf').addEventListener('click', function() {
1235
+ // In a real app, this would generate a PDF
1236
+ statusElement.textContent = "Exportando a PDF...";
1237
+ setTimeout(() => {
1238
+ statusElement.textContent = "PDF generado (simulado)";
1239
+ setTimeout(() => statusElement.textContent = "Listo", 2000);
1240
+ }, 1000);
1241
+ });
1242
+
1243
+ // Edit operations
1244
+ document.getElementById('undo').addEventListener('click', undo);
1245
+ document.getElementById('redo').addEventListener('click', redo);
1246
+ document.getElementById('cut').addEventListener('click', cut);
1247
+ document.getElementById('copy').addEventListener('click', copy);
1248
+ document.getElementById('paste').addEventListener('click', paste);
1249
+
1250
+ let clipboard = null;
1251
+
1252
+ function cut() {
1253
+ if (selectedCell) {
1254
+ copy();
1255
+ data[selectedCell.dataset.id] = '';
1256
+ selectedCell.textContent = '';
1257
+ saveState();
1258
+ statusElement.textContent = "Texto cortado";
1259
+ }
1260
+ }
1261
+
1262
+ function copy() {
1263
+ if (selectedCell) {
1264
+ clipboard = {
1265
+ value: data[selectedCell.dataset.id] || '',
1266
+ style: cellStyles[selectedCell.dataset.id] || null
1267
+ };
1268
+ statusElement.textContent = "Texto copiado";
1269
+ }
1270
+ }
1271
+
1272
+ function paste() {
1273
+ if (selectedCell && clipboard) {
1274
+ const cellId = selectedCell.dataset.id;
1275
+ data[cellId] = clipboard.value;
1276
+
1277
+ if (clipboard.style) {
1278
+ cellStyles[cellId] = {...clipboard.style};
1279
+ applyCellStyles(selectedCell, cellId);
1280
+ }
1281
+
1282
+ selectedCell.textContent = data[cellId] || '';
1283
+ saveState();
1284
+ statusElement.textContent = "Texto pegado";
1285
+ }
1286
+ }
1287
+
1288
+ // Save state to history
1289
+ function saveState() {
1290
+ // Truncate history if we're not at the end
1291
+ if (historyIndex < history.length - 1) {
1292
+ history = history.slice(0, historyIndex + 1);
1293
+ }
1294
+
1295
+ // Save current state
1296
+ history.push({
1297
+ data: {...data},
1298
+ formulas: {...formulas},
1299
+ cellStyles: {...cellStyles},
1300
+ cellWidths: {...cellWidths},
1301
+ cellHeights: {...cellHeights}
1302
+ });
1303
+
1304
+ historyIndex = history.length - 1;
1305
+
1306
+ // Limit history size
1307
+ if (history.length > 50) {
1308
+ history.shift();
1309
+ historyIndex--;
1310
+ }
1311
+ }
1312
+
1313
+ // Undo
1314
+ function undo() {
1315
+ if (historyIndex > 0) {
1316
+ historyIndex--;
1317
+ restoreState();
1318
+ statusElement.textContent = "Deshacer";
1319
+ }
1320
+ }
1321
+
1322
+ // Redo
1323
+ function redo() {
1324
+ if (historyIndex < history.length - 1) {
1325
+ historyIndex++;
1326
+ restoreState();
1327
+ statusElement.textContent = "Rehacer";
1328
+ }
1329
+ }
1330
+
1331
+ // Restore state from history
1332
+ function restoreState() {
1333
+ const state = history[historyIndex];
1334
+
1335
+ data = {...state.data};
1336
+ formulas = {...state.formulas};
1337
+ cellStyles = {...state.cellStyles};
1338
+ cellWidths = {...state.cellWidths};
1339
+ cellHeights = {...state.cellHeights};
1340
+
1341
+ // Update all cells
1342
+ document.querySelectorAll('.cell').forEach(cell => {
1343
+ const cellId = cell.dataset.id;
1344
+ cell.textContent = data[cellId] || '';
1345
+ applyCellStyles(cell, cellId);
1346
+ });
1347
+
1348
+ // Update column widths
1349
+ for (let col = 0; col < COLS; col++) {
1350
+ const colLetter = String.fromCharCode(65 + col);
1351
+ const width = cellWidths[colLetter] || CELL_WIDTH;
1352
+ columnHeaders.children[col].style.width = `${width}px`;
1353
+
1354
+ const cells = document.querySelectorAll(`.cell[data-col="${col}"]`);
1355
+ cells.forEach(cell => {
1356
+ cell.style.width = `${width}px`;
1357
+ });
1358
+ }
1359
+
1360
+ // Update row heights
1361
+ for (let row = 0; row < ROWS; row++) {
1362
+ const height = cellHeights[row + 1] || CELL_HEIGHT;
1363
+ rowNumbers.children[row + 1].style.height = `${height}px`;
1364
+
1365
+ const cells = document.querySelectorAll(`.cell[data-row="${row}"]`);
1366
+ cells.forEach(cell => {
1367
+ cell.style.height = `${height}px`;
1368
+ });
1369
+ }
1370
+
1371
+ // Update grid dimensions
1372
+ updateGridDimensions();
1373
+
1374
+ // Update color previews
1375
+ if (selectedCell) {
1376
+ updateColorPreviews(selectedCell.dataset.id);
1377
+ updateFormatButtons(selectedCell.dataset.id);
1378
+ }
1379
+ }
1380
+
1381
+ // Insert function button
1382
+ document.getElementById('insert-function').addEventListener('click', function() {
1383
+ if (selectedCell) {
1384
+ formulaInput.value = '=SUM(';
1385
+ formulaInput.focus();
1386
+ statusElement.textContent = "Insertando funci贸n SUM";
1387
+ }
1388
+ });
1389
+
1390
+ // Sort buttons
1391
+ document.getElementById('sort-asc').addEventListener('click', function() {
1392
+ statusElement.textContent = "Orden ascendente (simulado)";
1393
+ });
1394
+
1395
+ document.getElementById('sort-desc').addEventListener('click', function() {
1396
+ statusElement.textContent = "Orden descendente (simulado)";
1397
+ });
1398
+
1399
+ // Filter button
1400
+ document.getElementById('filter').addEventListener('click', function() {
1401
+ statusElement.textContent = "Filtro aplicado (simulado)";
1402
+ });
1403
+
1404
+ // Chart button
1405
+ document.getElementById('chart').addEventListener('click', function() {
1406
+ statusElement.textContent = "Creando gr谩fico (simulado)";
1407
+ setTimeout(() => {
1408
+ alert('Gr谩fico creado (simulaci贸n)');
1409
+ statusElement.textContent = "Listo";
1410
+ }, 1000);
1411
+ });
1412
+
1413
+ // Zoom buttons
1414
+ document.getElementById('zoom-in').addEventListener('click', function() {
1415
+ const currentZoom = parseInt(gridContainer.style.zoom || '100');
1416
+ const newZoom = Math.min(currentZoom + 10, 200);
1417
+ gridContainer.style.zoom = `${newZoom}%`;
1418
+ document.querySelector('.text-pink-400').textContent = `Zoom: ${newZoom}%`;
1419
+ statusElement.textContent = `Zoom: ${newZoom}%`;
1420
+ });
1421
+
1422
+ document.getElementById('zoom-out').addEventListener('click', function() {
1423
+ const currentZoom = parseInt(gridContainer.style.zoom || '100');
1424
+ const newZoom = Math.max(currentZoom - 10, 50);
1425
+ gridContainer.style.zoom = `${newZoom}%`;
1426
+ document.querySelector('.text-pink-400').textContent = `Zoom: ${newZoom}%`;
1427
+ statusElement.textContent = `Zoom: ${newZoom}%`;
1428
+ });
1429
+
1430
+ document.getElementById('zoom-reset').addEventListener('click', function() {
1431
+ gridContainer.style.zoom = '100%';
1432
+ document.querySelector('.text-pink-400').textContent = 'Zoom: 100%';
1433
+ statusElement.textContent = 'Zoom: 100%';
1434
+ });
1435
+
1436
+ // Add sheet button
1437
+ document.getElementById('add-sheet').addEventListener('click', function() {
1438
+ const sheetButtons = document.querySelectorAll('.tab-active + button, .tab-active');
1439
+ const lastSheet = sheetButtons[sheetButtons.length - 1];
1440
+ const sheetNumber = parseInt(lastSheet.textContent.replace('Hoja', '')) + 1;
1441
+
1442
+ const newSheetButton = document.createElement('button');
1443
+ newSheetButton.className = 'px-3 py-1 hover:bg-gray-700 text-sm font-medium text-gray-400';
1444
+ newSheetButton.textContent = `Hoja${sheetNumber}`;
1445
+
1446
+ lastSheet.parentNode.insertBefore(newSheetButton, lastSheet.nextSibling);
1447
+
1448
+ // Add to sheets data
1449
+ sheets[`Hoja${sheetNumber}`] = { data: {}, formulas: {}, cellStyles: {} };
1450
+
1451
+ statusElement.textContent = `Hoja${sheetNumber} a帽adida`;
1452
+ });
1453
+
1454
+ // Sheet tab click
1455
+ document.querySelectorAll('[class*="tab-"]').forEach(tab => {
1456
+ tab.addEventListener('click', function() {
1457
+ if (!this.classList.contains('tab-active')) {
1458
+ // Switch sheet
1459
+ document.querySelector('.tab-active').classList.remove('tab-active', 'text-blue-400');
1460
+ document.querySelector('.tab-active').classList.add('text-gray-400');
1461
+
1462
+ this.classList.add('tab-active', 'text-blue-400');
1463
+ this.classList.remove('text-gray-400');
1464
+
1465
+ // Update active sheet
1466
+ activeSheet = this.textContent.trim();
1467
+
1468
+ // In a real app, we would load the sheet data
1469
+ statusElement.textContent = `Cambiado a ${activeSheet}`;
1470
+ }
1471
+ });
1472
+ });
1473
+
1474
+ // Detect num lock and caps lock
1475
+ document.addEventListener('keydown', function(e) {
1476
+ if (e.getModifierState('NumLock')) {
1477
+ numLockElement.classList.remove('hidden');
1478
+ } else {
1479
+ numLockElement.classList.add('hidden');
1480
+ }
1481
+
1482
+ if (e.getModifierState('CapsLock')) {
1483
+ capsLockElement.classList.remove('hidden');
1484
+ } else {
1485
+ capsLockElement.classList.add('hidden');
1486
+ }
1487
+ });
1488
+
1489
+ // Initialize
1490
+ initGrid();
1491
+
1492
+ // Add keyboard navigation
1493
+ document.addEventListener('keydown', function(e) {
1494
+ if (!selectedCell) return;
1495
+
1496
+ const row = parseInt(selectedCell.dataset.row);
1497
+ const col = parseInt(selectedCell.dataset.col);
1498
+
1499
+ if (e.key === 'ArrowRight' && col < COLS - 1) {
1500
+ const nextCell = document.querySelector(`.cell[data-row="${row}"][data-col="${col + 1}"]`);
1501
+ nextCell.click();
1502
+ } else if (e.key === 'ArrowLeft' && col > 0) {
1503
+ const nextCell = document.querySelector(`.cell[data-row="${row}"][data-col="${col - 1}"]`);
1504
+ nextCell.click();
1505
+ } else if (e.key === 'ArrowDown' && row < ROWS - 1) {
1506
+ const nextCell = document.querySelector(`.cell[data-row="${row + 1}"][data-col="${col}"]`);
1507
+ nextCell.click();
1508
+ } else if (e.key === 'ArrowUp' && row > 0) {
1509
+ const nextCell = document.querySelector(`.cell[data-row="${row - 1}"][data-col="${col}"]`);
1510
+ nextCell.click();
1511
+ } else if (e.key === 'Enter') {
1512
+ selectedCell.dispatchEvent(new MouseEvent('dblclick'));
1513
+ } else if (e.key === 'F2') {
1514
+ selectedCell.dispatchEvent(new MouseEvent('dblclick'));
1515
+ } else if (e.key === 'Tab') {
1516
+ e.preventDefault();
1517
+ if (e.shiftKey && col > 0) {
1518
+ const prevCell = document.querySelector(`.cell[data-row="${row}"][data-col="${col - 1}"]`);
1519
+ prevCell.click();
1520
+ } else if (col < COLS - 1) {
1521
+ const nextCell = document.querySelector(`.cell[data-row="${row}"][data-col="${col + 1}"]`);
1522
+ nextCell.click();
1523
+ }
1524
+ }
1525
+ });
1526
+ });
1527
+ </script>
1528
+ <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=LJMolotov/my-multi-notes" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
1529
+ </html>
prompts.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ QUIERO UN CLON DE EXCEL COMPLETAMENTE FUUNCIONAL Y COLORES VIVOS FONDO MEDIO OSCURO
2
+ QUE TODO SEA UTIL Y FUNCIONAL CADA BOTOM
3
+ QUE PUEDA PONER Y QUITAR COLORES Y EDITAR