esp32tool 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/README.md +31 -0
  2. package/css/dark.css +156 -0
  3. package/css/light.css +156 -0
  4. package/css/style.css +870 -0
  5. package/dist/const.d.ts +277 -0
  6. package/dist/const.js +511 -0
  7. package/dist/esp_loader.d.ts +222 -0
  8. package/dist/esp_loader.js +1466 -0
  9. package/dist/index.d.ts +10 -0
  10. package/dist/index.js +15 -0
  11. package/dist/lib/spiffs/index.d.ts +15 -0
  12. package/dist/lib/spiffs/index.js +16 -0
  13. package/dist/lib/spiffs/spiffs.d.ts +26 -0
  14. package/dist/lib/spiffs/spiffs.js +132 -0
  15. package/dist/lib/spiffs/spiffsBlock.d.ts +36 -0
  16. package/dist/lib/spiffs/spiffsBlock.js +140 -0
  17. package/dist/lib/spiffs/spiffsConfig.d.ts +63 -0
  18. package/dist/lib/spiffs/spiffsConfig.js +79 -0
  19. package/dist/lib/spiffs/spiffsPage.d.ts +45 -0
  20. package/dist/lib/spiffs/spiffsPage.js +260 -0
  21. package/dist/lib/spiffs/spiffsReader.d.ts +19 -0
  22. package/dist/lib/spiffs/spiffsReader.js +192 -0
  23. package/dist/partition.d.ts +26 -0
  24. package/dist/partition.js +129 -0
  25. package/dist/struct.d.ts +2 -0
  26. package/dist/struct.js +91 -0
  27. package/dist/stubs/esp32.json +8 -0
  28. package/dist/stubs/esp32c2.json +8 -0
  29. package/dist/stubs/esp32c3.json +8 -0
  30. package/dist/stubs/esp32c5.json +8 -0
  31. package/dist/stubs/esp32c6.json +8 -0
  32. package/dist/stubs/esp32c61.json +8 -0
  33. package/dist/stubs/esp32h2.json +8 -0
  34. package/dist/stubs/esp32p4.json +8 -0
  35. package/dist/stubs/esp32p4r3.json +8 -0
  36. package/dist/stubs/esp32s2.json +8 -0
  37. package/dist/stubs/esp32s3.json +8 -0
  38. package/dist/stubs/esp8266.json +8 -0
  39. package/dist/stubs/index.d.ts +10 -0
  40. package/dist/stubs/index.js +56 -0
  41. package/dist/util.d.ts +14 -0
  42. package/dist/util.js +46 -0
  43. package/dist/wasm/filesystems.d.ts +33 -0
  44. package/dist/wasm/filesystems.js +114 -0
  45. package/dist/web/esp32-D955RjN9.js +16 -0
  46. package/dist/web/esp32c2-CJkxHDQi.js +16 -0
  47. package/dist/web/esp32c3-BhUHzH0o.js +16 -0
  48. package/dist/web/esp32c5-Chs0HtmA.js +16 -0
  49. package/dist/web/esp32c6-D6mPN6ut.js +16 -0
  50. package/dist/web/esp32c61-CQiYCWAs.js +16 -0
  51. package/dist/web/esp32h2-LsKJE9AS.js +16 -0
  52. package/dist/web/esp32p4-7nWC-HiD.js +16 -0
  53. package/dist/web/esp32p4r3-CwiPecZW.js +16 -0
  54. package/dist/web/esp32s2-CtqVheSJ.js +16 -0
  55. package/dist/web/esp32s3-CRbtB0QR.js +16 -0
  56. package/dist/web/esp8266-nEkNAo8K.js +16 -0
  57. package/dist/web/index.js +7265 -0
  58. package/electron/main.js +333 -0
  59. package/electron/preload.js +37 -0
  60. package/eslint.config.js +22 -0
  61. package/index.html +408 -0
  62. package/js/modules/esp32-D955RjN9.js +16 -0
  63. package/js/modules/esp32c2-CJkxHDQi.js +16 -0
  64. package/js/modules/esp32c3-BhUHzH0o.js +16 -0
  65. package/js/modules/esp32c5-Chs0HtmA.js +16 -0
  66. package/js/modules/esp32c6-D6mPN6ut.js +16 -0
  67. package/js/modules/esp32c61-CQiYCWAs.js +16 -0
  68. package/js/modules/esp32h2-LsKJE9AS.js +16 -0
  69. package/js/modules/esp32p4-7nWC-HiD.js +16 -0
  70. package/js/modules/esp32p4r3-CwiPecZW.js +16 -0
  71. package/js/modules/esp32s2-CtqVheSJ.js +16 -0
  72. package/js/modules/esp32s3-CRbtB0QR.js +16 -0
  73. package/js/modules/esp8266-nEkNAo8K.js +16 -0
  74. package/js/modules/esptool.js +7265 -0
  75. package/js/script.js +2237 -0
  76. package/js/utilities.js +182 -0
  77. package/license.md +11 -0
  78. package/package.json +61 -0
  79. package/script/build +12 -0
  80. package/script/develop +17 -0
  81. package/src/const.ts +599 -0
  82. package/src/esp_loader.ts +1907 -0
  83. package/src/index.ts +63 -0
  84. package/src/lib/spiffs/index.ts +22 -0
  85. package/src/lib/spiffs/spiffs.ts +175 -0
  86. package/src/lib/spiffs/spiffsBlock.ts +204 -0
  87. package/src/lib/spiffs/spiffsConfig.ts +140 -0
  88. package/src/lib/spiffs/spiffsPage.ts +357 -0
  89. package/src/lib/spiffs/spiffsReader.ts +280 -0
  90. package/src/partition.ts +155 -0
  91. package/src/struct.ts +108 -0
  92. package/src/stubs/README.md +3 -0
  93. package/src/stubs/esp32.json +8 -0
  94. package/src/stubs/esp32c2.json +8 -0
  95. package/src/stubs/esp32c3.json +8 -0
  96. package/src/stubs/esp32c5.json +8 -0
  97. package/src/stubs/esp32c6.json +8 -0
  98. package/src/stubs/esp32c61.json +8 -0
  99. package/src/stubs/esp32h2.json +8 -0
  100. package/src/stubs/esp32p4.json +8 -0
  101. package/src/stubs/esp32p4r3.json +8 -0
  102. package/src/stubs/esp32s2.json +8 -0
  103. package/src/stubs/esp32s3.json +8 -0
  104. package/src/stubs/esp8266.json +8 -0
  105. package/src/stubs/index.ts +86 -0
  106. package/src/util.ts +49 -0
  107. package/src/wasm/fatfs/fatfs.wasm +0 -0
  108. package/src/wasm/fatfs/index.d.ts +26 -0
  109. package/src/wasm/fatfs/index.js +343 -0
  110. package/src/wasm/filesystems.ts +156 -0
  111. package/src/wasm/littlefs/index.d.ts +83 -0
  112. package/src/wasm/littlefs/index.js +529 -0
  113. package/src/wasm/littlefs/littlefs.js +2 -0
  114. package/src/wasm/littlefs/littlefs.wasm +0 -0
  115. package/src/wasm/shared/types.ts +13 -0
package/css/style.css ADDED
@@ -0,0 +1,870 @@
1
+ /**
2
+ * Header
3
+ */
4
+
5
+ .header {
6
+ box-sizing: border-box;
7
+ font-size: 16px;
8
+ height: 85px;
9
+ padding: 15px 70px;
10
+ position: fixed;
11
+ width: 100%;
12
+ z-index: 1000;
13
+ margin: 0;
14
+ border-bottom: 5px solid #00a7e9;
15
+ display: flex;
16
+ justify-content: space-between;
17
+ align-items: center;
18
+ top: 0;
19
+ transition: transform 0.3s ease-in-out;
20
+ }
21
+
22
+ .header-hidden {
23
+ transform: translateY(-100%);
24
+ }
25
+
26
+ .header .left {
27
+ display: flex;
28
+ align-items: center;
29
+ }
30
+
31
+ .header .title {
32
+ font-size: 24px;
33
+ font-weight: 500;
34
+ margin-right: 30px;
35
+ }
36
+
37
+ .header .right {
38
+ display: flex;
39
+ align-items: center;
40
+ gap: 15px;
41
+ }
42
+
43
+ .header .controls-row {
44
+ display: flex;
45
+ align-items: center;
46
+ gap: 8px;
47
+ margin-right: 20px;
48
+ padding-right: 20px;
49
+ border-right: 2px solid #ccc;
50
+ }
51
+
52
+ .header .controls-row label {
53
+ font-size: 13px;
54
+ margin-left: 12px;
55
+ }
56
+
57
+ .header .controls-row label:first-child {
58
+ margin-left: 0;
59
+ }
60
+
61
+ .header button {
62
+ border: solid 2px #fff;
63
+ background-color: #000;
64
+ color: #fff;
65
+ height: 30px;
66
+ }
67
+
68
+ .header button:hover {
69
+ background-color: #fff;
70
+ color: #000;
71
+ }
72
+
73
+ .header button.highlight {
74
+ background-color: #ff6b00;
75
+ border-color: #ff6b00;
76
+ color: #fff;
77
+ animation: pulse 1.5s infinite;
78
+ }
79
+
80
+ @keyframes pulse {
81
+ 0%, 100% {
82
+ transform: scale(1);
83
+ box-shadow: 0 0 0 0 rgba(255, 107, 0, 0.7);
84
+ }
85
+ 50% {
86
+ transform: scale(1.05);
87
+ box-shadow: 0 0 0 10px rgba(255, 107, 0, 0);
88
+ }
89
+ }
90
+
91
+ .header select {
92
+ height: 30px;
93
+ }
94
+
95
+ button,
96
+ .firmware {
97
+ height: 25px;
98
+ font-size: 16px;
99
+ border-radius: 15px;
100
+ padding-left: 20px;
101
+ padding-right: 20px;
102
+ border-width: 2px;
103
+ }
104
+
105
+ body {
106
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", Arial, sans-serif;
107
+ font-style: normal;
108
+ font-weight: 400;
109
+ margin: 0;
110
+ }
111
+
112
+ p {
113
+ margin: 0;
114
+ }
115
+
116
+ input,
117
+ select,
118
+ button,
119
+ label {
120
+ font-weight: 600;
121
+ outline: none;
122
+ }
123
+
124
+ div.left {
125
+ float: left;
126
+ display: flex;
127
+ align-items: center;
128
+ }
129
+
130
+ div.right {
131
+ float: right;
132
+ display: flex;
133
+ align-items: center;
134
+ }
135
+
136
+ div.clear {
137
+ clear: both;
138
+ }
139
+
140
+ .main {
141
+ overflow-x: hidden;
142
+ overflow-y: auto;
143
+ padding-top: 90px;
144
+ transition: padding-top 0.3s ease-in-out;
145
+ }
146
+
147
+ .main.no-header-padding {
148
+ padding-top: 0;
149
+ }
150
+
151
+ .hidden {
152
+ display: none;
153
+ }
154
+
155
+ .notSupported {
156
+ padding: 1em;
157
+ margin-top: 1em;
158
+ margin-bottom: 1em;
159
+ }
160
+
161
+ .log-controls {
162
+ display: flex;
163
+ align-items: center;
164
+ gap: 8px;
165
+ padding-left: 12px;
166
+ border-left: 1px solid #ccc;
167
+ }
168
+
169
+ .log-controls.hidden {
170
+ display: none;
171
+ }
172
+
173
+ .small-btn {
174
+ padding: 4px 12px;
175
+ font-size: 13px;
176
+ border-radius: 12px;
177
+ border-width: 2px;
178
+ border-style: solid;
179
+ cursor: pointer;
180
+ height: 26px;
181
+ line-height: 14px;
182
+ }
183
+
184
+ #app.connected #commands {
185
+ height: auto;
186
+ max-height: 70vh;
187
+ overflow-y: auto;
188
+ }
189
+
190
+ #app.connected #log {
191
+ height: calc(100vh - 320px);
192
+ min-height: 200px;
193
+ }
194
+
195
+ #app.connected #log.hidden {
196
+ height: 0;
197
+ min-height: 0;
198
+ padding: 0;
199
+ border: 0;
200
+ }
201
+
202
+ #app #commands {
203
+ height: 0;
204
+ overflow: hidden;
205
+ }
206
+
207
+ #app #log {
208
+ height: calc(100vh - 220px);
209
+ min-height: 200px;
210
+ }
211
+
212
+ #app #log.hidden {
213
+ height: 0;
214
+ min-height: 0;
215
+ padding: 0;
216
+ border: 0;
217
+ overflow: hidden;
218
+ }
219
+
220
+ #commands,
221
+ #log {
222
+ transition: height 0.5s;
223
+ }
224
+
225
+ #commands {
226
+ position: relative;
227
+ margin: 0 auto;
228
+ overflow-y: auto;
229
+ padding: 0 60px;
230
+ }
231
+
232
+ #log {
233
+ max-width: 100%;
234
+ font-family: "SF Mono", "Menlo", "Monaco", "Consolas", "Liberation Mono", "Courier New", monospace;
235
+ font-style: normal;
236
+ font-weight: 400;
237
+ font-size: 16px;
238
+ overflow-x: hidden;
239
+ overflow-x: auto;
240
+ transition: color 0.1s linear;
241
+ padding: 0 50px;
242
+ border: 20px solid #000;
243
+ -ms-overflow-style: none;
244
+ scrollbar-width: none;
245
+ background-color: #000;
246
+ color: #cecece;
247
+ }
248
+
249
+ #log::-webkit-scrollbar {
250
+ display: none;
251
+ }
252
+
253
+ .footer {
254
+ padding: 10px 70px;
255
+ height: 20px;
256
+ }
257
+
258
+ .remix {
259
+ display: flex;
260
+ justify-content: center;
261
+ height: 60px;
262
+ position: relative;
263
+ }
264
+
265
+ .remix button {
266
+ position: absolute;
267
+ bottom: 11px;
268
+ }
269
+
270
+ #templates {
271
+ display: none;
272
+ }
273
+
274
+ /* On/Off Switch Widget */
275
+ .onoffswitch {
276
+ display: inline-block;
277
+ position: relative;
278
+ width: 50px;
279
+ margin-right: 5px;
280
+ -webkit-user-select: none;
281
+ -moz-user-select: none;
282
+ -ms-user-select: none;
283
+ margin-left: 5px;
284
+ }
285
+
286
+ .onoffswitch-checkbox {
287
+ display: none;
288
+ }
289
+
290
+ .onoffswitch-label {
291
+ display: block;
292
+ overflow: hidden;
293
+ cursor: pointer;
294
+ border: 1px solid #900;
295
+ border-radius: 15px;
296
+ transition: border 0.3s ease-in 0s;
297
+ }
298
+
299
+ .onoffswitch-inner {
300
+ display: block;
301
+ width: 200%;
302
+ margin-left: -100%;
303
+ transition: margin 0.3s ease-in 0s;
304
+ }
305
+
306
+ .onoffswitch-inner:before,
307
+ .onoffswitch-inner:after {
308
+ display: block;
309
+ float: left;
310
+ width: 50%;
311
+ height: 25px;
312
+ padding: 0;
313
+ line-height: 25px;
314
+ font-size: 14px;
315
+ color: white;
316
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", Arial, sans-serif;
317
+ font-style: normal;
318
+ font-weight: 600;
319
+ box-sizing: border-box;
320
+ }
321
+
322
+ .onoffswitch-inner:before {
323
+ content: "on";
324
+ padding-left: 6px;
325
+ background-color: #8ec641;
326
+ color: #fff;
327
+ }
328
+
329
+ .onoffswitch-inner:after {
330
+ content: "off";
331
+ padding-right: 6px;
332
+ background-color: #c64141;
333
+ color: #fff;
334
+ text-align: right;
335
+ }
336
+
337
+ .onoffswitch-switch {
338
+ display: block;
339
+ width: 19px;
340
+ margin: 3px;
341
+ background: #fff;
342
+ position: absolute;
343
+ top: 0;
344
+ bottom: 0;
345
+ right: 23px;
346
+ border: 1px solid #900;
347
+ border-radius: 15px;
348
+ transition: all 0.3s ease-in 0s;
349
+ }
350
+
351
+ .onoffswitch-checkbox:checked + .onoffswitch-label {
352
+ border-color: #71ae1e;
353
+ }
354
+
355
+ .onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-inner {
356
+ margin-left: 0;
357
+ }
358
+
359
+ .onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-switch {
360
+ right: 0px;
361
+ border-color: #67ac38;
362
+ }
363
+
364
+
365
+
366
+ #commands {
367
+ min-width: 600px;
368
+ justify-content: center;
369
+ position: relative;
370
+ align-items: center;
371
+ }
372
+
373
+ #commands .upload {
374
+ max-width: 600px;
375
+ display: flex;
376
+ align-items: center;
377
+ margin: 5px auto;
378
+ justify-content: flex-start;
379
+ padding-left: calc(50% - 300px);
380
+ }
381
+
382
+ /* Hide upload rows 2-8 by default, show dynamically via JavaScript */
383
+ #commands .upload:nth-child(n+2):nth-child(-n+8) {
384
+ display: none;
385
+ }
386
+
387
+ #commands .upload .offset {
388
+ width: 50px;
389
+ }
390
+
391
+ #commands .upload label {
392
+ white-space: nowrap;
393
+ }
394
+
395
+ .firmware > input {
396
+ width: 0.1px;
397
+ height: 0.1px;
398
+ opacity: 0;
399
+ overflow: hidden;
400
+ position: absolute;
401
+ z-index: -1;
402
+ }
403
+
404
+ .firmware {
405
+ border-style: solid;
406
+ margin-left: 20px;
407
+ margin-right: 20px;
408
+ display: flex;
409
+ align-items: center;
410
+ cursor: pointer;
411
+ }
412
+
413
+ .firmware > svg {
414
+ margin-right: 10px;
415
+ }
416
+
417
+ .debug-function {
418
+ color: #8ec641;
419
+ }
420
+
421
+ .error-message {
422
+ color: #c64141;
423
+ }
424
+
425
+ .timestamp {
426
+ color: #8ec641;
427
+ }
428
+
429
+ .progress-bar {
430
+ width: 100%;
431
+ height: 24px;
432
+ border-style: solid;
433
+ border-width: 2px;
434
+ border-radius: 10px;
435
+ padding: 0;
436
+ overflow: hidden;
437
+ }
438
+
439
+ .progress-bar > div {
440
+ height: 24px;
441
+ background-color: #71ae1e;
442
+ width: 0;
443
+ }
444
+
445
+ #commands .buttons {
446
+ display: flex;
447
+ justify-content: center;
448
+ width: 600px;
449
+ margin: 10px auto;
450
+ }
451
+
452
+ #commands .buttons button {
453
+ margin-left: 10px;
454
+ margin-right: 10px;
455
+ border-width: 2px;
456
+ border-style: solid;
457
+ cursor: pointer;
458
+ }
459
+
460
+ #commands button {
461
+ cursor: pointer;
462
+ }
463
+
464
+ #commands .read-flash {
465
+ width: 800px;
466
+ margin: 20px auto 10px auto;
467
+ padding-top: 20px;
468
+ border-top: 2px solid #ccc;
469
+ display: flex;
470
+ flex-direction: column;
471
+ align-items: center;
472
+ }
473
+
474
+ #commands .read-flash .progress-bar {
475
+ width: 400px;
476
+ margin-bottom: 10px;
477
+ }
478
+
479
+ #commands .read-flash-inputs {
480
+ display: flex;
481
+ align-items: center;
482
+ gap: 15px;
483
+ }
484
+
485
+ #commands .read-flash label {
486
+ display: flex;
487
+ align-items: center;
488
+ gap: 5px;
489
+ white-space: nowrap;
490
+ }
491
+
492
+ #commands .read-flash input {
493
+ width: 100px;
494
+ padding: 5px;
495
+ border-radius: 5px;
496
+ border: 2px solid #ccc;
497
+ }
498
+
499
+ #commands .read-flash button {
500
+ border-width: 2px;
501
+ border-style: solid;
502
+ padding: 2px 30px;
503
+ cursor: pointer;
504
+ }
505
+
506
+ #commands .partition-table {
507
+ width: 800px;
508
+ margin: 20px auto 10px auto;
509
+ padding-top: 20px;
510
+ border-top: 2px solid #ccc;
511
+ display: flex;
512
+ flex-direction: column;
513
+ align-items: center;
514
+ }
515
+
516
+ #commands .partition-table button {
517
+ margin: 0 0 10px 0;
518
+ border-width: 2px;
519
+ border-style: solid;
520
+ padding: 2px 30px;
521
+ cursor: pointer;
522
+ }
523
+
524
+ #commands .partition-table .progress-bar {
525
+ width: 400px;
526
+ margin-bottom: 10px;
527
+ }
528
+
529
+ .partition-table-display {
530
+ width: 100%;
531
+ margin-top: 20px;
532
+ border-collapse: collapse;
533
+ }
534
+
535
+ .partition-table-display th,
536
+ .partition-table-display td {
537
+ padding: 8px 12px;
538
+ text-align: left;
539
+ border: 1px solid #ccc;
540
+ }
541
+
542
+ .partition-table-display th {
543
+ font-weight: 600;
544
+ background-color: #f0f0f0;
545
+ }
546
+
547
+ .partition-download-btn {
548
+ padding: 5px 15px;
549
+ font-size: 14px;
550
+ border-radius: 10px;
551
+ border-width: 2px;
552
+ border-style: solid;
553
+ cursor: pointer;
554
+ background-color: transparent;
555
+ transition: background-color 0.2s, color 0.2s;
556
+ }
557
+
558
+ .partition-download-btn:hover {
559
+ background-color: #00a7e9;
560
+ color: #fff;
561
+ border-color: #00a7e9;
562
+ }
563
+
564
+ .justify {
565
+ display: flex;
566
+ justify-content: space-between;
567
+ }
568
+ .center {
569
+ text-align: center;
570
+ }
571
+
572
+ /* LittleFS Manager Styles */
573
+ .littlefs-manager {
574
+ width: 900px;
575
+ margin: 30px auto;
576
+ padding: 25px;
577
+ border: 2px solid #71ae1e;
578
+ border-radius: 10px;
579
+ background-color: rgba(113, 174, 30, 0.05);
580
+ }
581
+
582
+ .littlefs-manager h3 {
583
+ margin: 0 0 20px 0;
584
+ color: #71ae1e;
585
+ font-size: 20px;
586
+ font-weight: 600;
587
+ }
588
+
589
+ .littlefs-info {
590
+ margin-bottom: 20px;
591
+ padding: 15px;
592
+ background-color: rgba(255, 255, 255, 0.5);
593
+ border-radius: 8px;
594
+ }
595
+
596
+ .littlefs-partition-info {
597
+ margin-bottom: 12px;
598
+ font-size: 14px;
599
+ }
600
+
601
+ .littlefs-size {
602
+ color: #666;
603
+ margin-left: 8px;
604
+ }
605
+
606
+ .littlefs-usage {
607
+ margin-top: 10px;
608
+ }
609
+
610
+ .usage-bar {
611
+ width: 100%;
612
+ height: 20px;
613
+ background-color: #e0e0e0;
614
+ border-radius: 10px;
615
+ overflow: hidden;
616
+ margin-bottom: 8px;
617
+ }
618
+
619
+ .usage-fill {
620
+ height: 100%;
621
+ background: linear-gradient(90deg, #71ae1e 0%, #8ec641 100%);
622
+ transition: width 0.3s ease;
623
+ }
624
+
625
+ .usage-text {
626
+ display: flex;
627
+ justify-content: space-between;
628
+ align-items: center;
629
+ font-size: 13px;
630
+ color: #555;
631
+ }
632
+
633
+ .disk-version {
634
+ font-size: 12px;
635
+ padding: 2px 8px;
636
+ background-color: #71ae1e;
637
+ color: white;
638
+ border-radius: 4px;
639
+ }
640
+
641
+ .littlefs-controls {
642
+ display: flex;
643
+ gap: 10px;
644
+ margin-bottom: 20px;
645
+ flex-wrap: wrap;
646
+ }
647
+
648
+ .littlefs-controls button {
649
+ /* Use default button styles from main stylesheet */
650
+ border-style: solid;
651
+ cursor: pointer;
652
+ }
653
+
654
+ .littlefs-controls button:disabled {
655
+ opacity: 0.5;
656
+ cursor: not-allowed;
657
+ }
658
+
659
+ .littlefs-breadcrumb {
660
+ display: flex;
661
+ align-items: center;
662
+ gap: 10px;
663
+ margin-bottom: 15px;
664
+ padding: 10px;
665
+ background-color: rgba(255, 255, 255, 0.5);
666
+ border-radius: 8px;
667
+ }
668
+
669
+ .littlefs-breadcrumb button {
670
+ /* Use default button styles */
671
+ border-style: solid;
672
+ cursor: pointer;
673
+ }
674
+
675
+ .littlefs-breadcrumb button:disabled {
676
+ opacity: 0.4;
677
+ cursor: not-allowed;
678
+ }
679
+
680
+ .littlefs-breadcrumb span {
681
+ font-family: monospace;
682
+ font-size: 14px;
683
+ color: #333;
684
+ }
685
+
686
+ .littlefs-file-upload {
687
+ display: flex;
688
+ gap: 10px;
689
+ margin-bottom: 15px;
690
+ align-items: center;
691
+ }
692
+
693
+ .littlefs-file-upload input[type="file"] {
694
+ flex: 1;
695
+ padding: 5px;
696
+ border: 2px solid #ccc;
697
+ border-radius: 8px;
698
+ }
699
+
700
+ .littlefs-file-upload button {
701
+ /* Use default button styles */
702
+ border-style: solid;
703
+ cursor: pointer;
704
+ }
705
+
706
+ .littlefs-file-upload button:disabled {
707
+ opacity: 0.5;
708
+ cursor: not-allowed;
709
+ }
710
+
711
+ .littlefs-files {
712
+ max-height: 400px;
713
+ overflow-y: auto;
714
+ border: 1px solid #ccc;
715
+ border-radius: 8px;
716
+ }
717
+
718
+ .file-table {
719
+ width: 100%;
720
+ border-collapse: collapse;
721
+ }
722
+
723
+ .file-table thead {
724
+ position: sticky;
725
+ top: 0;
726
+ background-color: #f5f5f5;
727
+ z-index: 10;
728
+ }
729
+
730
+ .file-table th {
731
+ padding: 10px;
732
+ text-align: left;
733
+ font-weight: 600;
734
+ border-bottom: 2px solid #ccc;
735
+ }
736
+
737
+ .file-table td {
738
+ padding: 8px 10px;
739
+ border-bottom: 1px solid #e0e0e0;
740
+ }
741
+
742
+ .file-table tbody tr:hover {
743
+ background-color: rgba(113, 174, 30, 0.1);
744
+ }
745
+
746
+ .file-table .empty-state {
747
+ text-align: center;
748
+ color: #999;
749
+ padding: 30px;
750
+ font-style: italic;
751
+ }
752
+
753
+ .file-name {
754
+ display: flex;
755
+ align-items: center;
756
+ gap: 8px;
757
+ cursor: pointer;
758
+ }
759
+
760
+ .file-name.clickable:hover {
761
+ color: #71ae1e;
762
+ text-decoration: underline;
763
+ }
764
+
765
+ .file-icon {
766
+ font-size: 16px;
767
+ }
768
+
769
+ .file-actions {
770
+ display: flex;
771
+ gap: 5px;
772
+ }
773
+
774
+ .file-actions button {
775
+ padding: 4px 12px;
776
+ font-size: 12px;
777
+ height: auto;
778
+ border-style: solid;
779
+ cursor: pointer;
780
+ transition: all 0.2s;
781
+ }
782
+
783
+ .littlefs-fs-button {
784
+ display: inline-block;
785
+ margin-left: 8px;
786
+ padding: 2px 8px;
787
+ font-size: 11px;
788
+ height: auto;
789
+ border: none;
790
+ border-radius: 4px;
791
+ cursor: pointer;
792
+ font-weight: 600;
793
+ }
794
+
795
+ /* ESP32-S2 Reconnect Modal */
796
+ .modal {
797
+ display: flex;
798
+ position: fixed;
799
+ z-index: 9999;
800
+ left: 0;
801
+ top: 0;
802
+ width: 100%;
803
+ height: 100%;
804
+ background-color: rgba(0, 0, 0, 0.7);
805
+ align-items: center;
806
+ justify-content: center;
807
+ }
808
+
809
+ .modal.hidden {
810
+ display: none;
811
+ }
812
+
813
+ .modal-content {
814
+ background-color: #fff;
815
+ padding: 40px;
816
+ border-radius: 15px;
817
+ box-shadow: 0 5px 30px rgba(0, 0, 0, 0.3);
818
+ text-align: center;
819
+ max-width: 500px;
820
+ animation: modalSlideIn 0.3s ease-out;
821
+ }
822
+
823
+ @keyframes modalSlideIn {
824
+ from {
825
+ transform: translateY(-50px);
826
+ opacity: 0;
827
+ }
828
+ to {
829
+ transform: translateY(0);
830
+ opacity: 1;
831
+ }
832
+ }
833
+
834
+ .modal-content h2 {
835
+ color: #4a4a4a;
836
+ margin-top: 0;
837
+ font-size: 24px;
838
+ margin-bottom: 20px;
839
+ }
840
+
841
+ .modal-content p {
842
+ font-size: 16px;
843
+ line-height: 1.6;
844
+ margin: 15px 0;
845
+ color: #333;
846
+ }
847
+
848
+ .modal-button {
849
+ background-color: #fff;
850
+ color: #6b6b6b;
851
+ border: 2px solid #6b6b6b;
852
+ padding: 12px 40px;
853
+ font-size: 18px;
854
+ font-weight: 600;
855
+ border-radius: 25px;
856
+ cursor: pointer;
857
+ margin-top: 20px;
858
+ transition: background-color 0.2s, color 0.2s, border-color 0.2s;
859
+ display: inline-flex;
860
+ align-items: center;
861
+ justify-content: center;
862
+ line-height: normal;
863
+ text-align: center;
864
+ }
865
+
866
+ .modal-button:hover {
867
+ background-color: #71ae1e;
868
+ color: #fff;
869
+ border-color: #71ae1e;
870
+ }