wagtail-enap-designsystem 1.2.1.143__py3-none-any.whl → 1.2.1.145__py3-none-any.whl

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.

Potentially problematic release.


This version of wagtail-enap-designsystem might be problematic. Click here for more details.

Files changed (26) hide show
  1. enap_designsystem/blocks/content_blocks.py +2 -1
  2. enap_designsystem/blocks/form.py +1 -6
  3. enap_designsystem/blocks/html_blocks.py +82 -77
  4. enap_designsystem/blocks/layout_blocks.py +26 -0
  5. enap_designsystem/blocks/semana_blocks.py +30 -19
  6. enap_designsystem/migrations/0415_showcasecomponentesdireto_debug_mode_and_more.py +77346 -0
  7. enap_designsystem/migrations/0416_alter_showcasecomponentesdireto_debug_mode_and_more.py +33 -0
  8. enap_designsystem/migrations/0417_alter_showcasecomponentesdireto_options_and_more.py +53 -0
  9. enap_designsystem/models.py +729 -146
  10. enap_designsystem/static/enap_designsystem/blocks/accordions.css +1 -0
  11. enap_designsystem/static/enap_designsystem/blocks/semana.css +6 -5
  12. enap_designsystem/templates/enap_designsystem/blocks/apresentacao_block.html +8 -16
  13. enap_designsystem/templates/enap_designsystem/blocks/apresentacao_simple_block.html +11 -12
  14. enap_designsystem/templates/enap_designsystem/blocks/cards_titles.html +23 -31
  15. enap_designsystem/templates/enap_designsystem/blocks/formulario_dinamico.html +4 -4
  16. enap_designsystem/templates/enap_designsystem/blocks/logos_simple_block.html +1 -22
  17. enap_designsystem/templates/enap_designsystem/blocks/numeros_block.html +1 -1
  18. enap_designsystem/templates/enap_designsystem/blocks/section_block.html +2 -2
  19. enap_designsystem/templates/enap_designsystem/blocks/video_hero_banner.html +3 -8
  20. enap_designsystem/templates/enap_designsystem/pages/showcase_components.html +867 -464
  21. enap_designsystem/templates/enap_designsystem/semana_inovacao/blocks_menu_navigation.html +10 -0
  22. {wagtail_enap_designsystem-1.2.1.143.dist-info → wagtail_enap_designsystem-1.2.1.145.dist-info}/METADATA +1 -1
  23. {wagtail_enap_designsystem-1.2.1.143.dist-info → wagtail_enap_designsystem-1.2.1.145.dist-info}/RECORD +26 -23
  24. {wagtail_enap_designsystem-1.2.1.143.dist-info → wagtail_enap_designsystem-1.2.1.145.dist-info}/WHEEL +0 -0
  25. {wagtail_enap_designsystem-1.2.1.143.dist-info → wagtail_enap_designsystem-1.2.1.145.dist-info}/licenses/LICENSE +0 -0
  26. {wagtail_enap_designsystem-1.2.1.143.dist-info → wagtail_enap_designsystem-1.2.1.145.dist-info}/top_level.txt +0 -0
@@ -1,592 +1,995 @@
1
- <!-- enap_designsystem/pages/showcase_direct.html -->
2
- {% load wagtailcore_tags %}
3
-
1
+ <!-- enap_designsystem/pages/showcase_components.html -->
4
2
  <!DOCTYPE html>
5
3
  <html lang="pt-BR">
6
4
  <head>
7
5
  <meta charset="UTF-8">
8
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
9
- <title>{{ page_title }} - ENAP</title>
10
- <script src="https://cdn.tailwindcss.com"></script>
11
- <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
7
+ <title>{{ page_title }}</title>
8
+ <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
12
9
  <style>
13
- body { font-family: 'Inter', sans-serif; }
10
+ * {
11
+ margin: 0;
12
+ padding: 0;
13
+ box-sizing: border-box;
14
+ }
14
15
 
15
- .component-showcase {
16
- border: 2px solid #e5e7eb;
17
- border-radius: 12px;
16
+ body {
17
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
18
+ background: #f8fafc;
19
+ line-height: 1.6;
20
+ color: #334155;
21
+ }
22
+
23
+ .showcase-container {
24
+ max-width: 1400px;
25
+ margin: 0 auto;
26
+ padding: 2rem;
27
+ }
28
+
29
+ .showcase-header {
30
+ text-align: center;
31
+ margin-bottom: 3rem;
32
+ padding: 3rem 2rem;
33
+ background: linear-gradient(135deg, #1e3a8a 0%, #3b82f6 50%, #06b6d4 100%);
34
+ border-radius: 20px;
35
+ color: white;
36
+ position: relative;
37
+ overflow: hidden;
38
+ box-shadow: 0 20px 40px rgba(30, 58, 138, 0.3);
39
+ }
40
+
41
+ .showcase-header::before {
42
+ content: '';
43
+ position: absolute;
44
+ top: -50%;
45
+ left: -50%;
46
+ width: 200%;
47
+ height: 200%;
48
+ background: radial-gradient(circle, rgba(255,255,255,0.1) 2px, transparent 2px);
49
+ background-size: 30px 30px;
50
+ animation: float 30s infinite linear;
51
+ }
52
+
53
+ @keyframes float {
54
+ 0% { transform: translate(-50px, -50px) rotate(0deg); }
55
+ 100% { transform: translate(50px, 50px) rotate(360deg); }
56
+ }
57
+
58
+ .showcase-header h1 {
59
+ font-size: 3rem;
60
+ font-weight: 700;
61
+ margin-bottom: 1rem;
62
+ text-shadow: 0 2px 4px rgba(0,0,0,0.3);
63
+ position: relative;
64
+ z-index: 2;
65
+ }
66
+
67
+ .showcase-header p {
68
+ font-size: 1.25rem;
69
+ opacity: 0.9;
70
+ position: relative;
71
+ z-index: 2;
72
+ }
73
+
74
+ .controls-bar {
18
75
  background: white;
76
+ padding: 1.5rem;
77
+ border-radius: 15px;
78
+ box-shadow: 0 8px 25px rgba(0,0,0,0.1);
19
79
  margin-bottom: 2rem;
20
- overflow: hidden;
80
+ display: flex;
81
+ flex-wrap: wrap;
82
+ gap: 1rem;
83
+ align-items: center;
84
+ justify-content: space-between;
85
+ }
86
+
87
+ .filter-group {
88
+ display: flex;
89
+ align-items: center;
90
+ gap: 0.75rem;
91
+ }
92
+
93
+ .filter-select {
94
+ padding: 0.75rem 1rem;
95
+ border: 2px solid #e2e8f0;
96
+ border-radius: 10px;
97
+ background: white;
98
+ font-size: 0.9rem;
99
+ color: #334155;
21
100
  transition: all 0.3s ease;
22
101
  }
23
102
 
24
- .component-showcase:hover {
103
+ .filter-select:focus {
104
+ outline: none;
25
105
  border-color: #3b82f6;
26
- box-shadow: 0 4px 12px rgba(59, 130, 246, 0.15);
106
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
27
107
  }
28
108
 
29
- .component-header {
30
- background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);
109
+ .toggle-btn {
110
+ padding: 0.75rem 1.5rem;
111
+ border: 2px solid #e2e8f0;
112
+ border-radius: 10px;
113
+ background: white;
114
+ color: #64748b;
115
+ cursor: pointer;
116
+ font-size: 0.9rem;
117
+ font-weight: 500;
118
+ transition: all 0.3s ease;
119
+ }
120
+
121
+ .toggle-btn:hover {
122
+ border-color: #3b82f6;
123
+ color: #3b82f6;
124
+ transform: translateY(-2px);
125
+ }
126
+
127
+ .toggle-btn.active {
128
+ background: #3b82f6;
31
129
  color: white;
32
- padding: 1rem;
33
- font-size: 0.875rem;
130
+ border-color: #3b82f6;
131
+ box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
34
132
  }
35
133
 
36
- .component-content {
37
- padding: 1.5rem;
134
+ .search-box {
135
+ position: relative;
136
+ flex: 1;
137
+ min-width: 300px;
38
138
  }
39
139
 
40
- .component-meta {
140
+ .search-input {
141
+ width: 100%;
142
+ padding: 0.75rem 1rem 0.75rem 3rem;
143
+ border: 2px solid #e2e8f0;
144
+ border-radius: 10px;
145
+ font-size: 1rem;
146
+ transition: all 0.3s ease;
41
147
  background: #f8fafc;
42
- padding: 0.75rem 1rem;
43
- border-top: 1px solid #e2e8f0;
44
- font-size: 0.75rem;
148
+ }
149
+
150
+ .search-input:focus {
151
+ outline: none;
152
+ border-color: #3b82f6;
153
+ background: white;
154
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
155
+ }
156
+
157
+ .search-icon {
158
+ position: absolute;
159
+ left: 1rem;
160
+ top: 50%;
161
+ transform: translateY(-50%);
162
+ color: #94a3b8;
163
+ font-size: 1.1rem;
164
+ }
165
+
166
+ .stats-grid {
167
+ display: grid;
168
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
169
+ gap: 1.5rem;
170
+ margin-bottom: 3rem;
171
+ }
172
+
173
+ .stat-card {
174
+ background: white;
175
+ padding: 2rem;
176
+ border-radius: 15px;
177
+ text-align: center;
178
+ box-shadow: 0 8px 25px rgba(0,0,0,0.08);
179
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
180
+ border-left: 4px solid #3b82f6;
181
+ }
182
+
183
+ .stat-card:hover {
184
+ transform: translateY(-5px);
185
+ box-shadow: 0 15px 35px rgba(0,0,0,0.12);
186
+ }
187
+
188
+ .stat-number {
189
+ font-size: 3rem;
190
+ font-weight: 800;
191
+ color: #3b82f6;
192
+ margin-bottom: 0.5rem;
193
+ background: linear-gradient(135deg, #3b82f6, #06b6d4);
194
+ -webkit-background-clip: text;
195
+ -webkit-text-fill-color: transparent;
196
+ background-clip: text;
197
+ }
198
+
199
+ .stat-label {
45
200
  color: #64748b;
201
+ font-size: 0.9rem;
202
+ font-weight: 600;
203
+ text-transform: uppercase;
204
+ letter-spacing: 0.05em;
46
205
  }
47
206
 
48
- .error-component {
49
- border-color: #ef4444;
50
- background: #fef2f2;
207
+ .categories-grid {
208
+ display: grid;
209
+ grid-template-columns: 1fr;
210
+ gap: 2rem;
211
+ }
212
+
213
+ .category-card {
214
+ background: white;
215
+ border-radius: 20px;
216
+ box-shadow: 0 10px 30px rgba(0,0,0,0.08);
217
+ overflow: hidden;
218
+ transition: all 0.4s ease;
219
+ border: 1px solid #f1f5f9;
51
220
  }
52
221
 
53
- .error-component .component-header {
54
- background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
222
+ .category-card:hover {
223
+ transform: translateY(-10px);
224
+ box-shadow: 0 25px 50px rgba(0,0,0,0.15);
55
225
  }
56
226
 
57
227
  .category-header {
228
+ padding: 2rem;
58
229
  background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
230
+ border-bottom: 1px solid #e2e8f0;
231
+ position: relative;
232
+ }
233
+
234
+ .category-header::after {
235
+ content: '';
236
+ position: absolute;
237
+ bottom: 0;
238
+ left: 0;
239
+ right: 0;
240
+ height: 4px;
241
+ background: linear-gradient(90deg, #3b82f6, #06b6d4);
242
+ }
243
+
244
+ .category-title {
245
+ font-size: 1.5rem;
246
+ font-weight: 700;
247
+ color: #1e293b;
248
+ margin-bottom: 0.75rem;
249
+ display: flex;
250
+ align-items: center;
251
+ gap: 1rem;
252
+ }
253
+
254
+ .category-icon {
255
+ font-size: 1.75rem;
256
+ color: #3b82f6;
257
+ background: rgba(59, 130, 246, 0.1);
258
+ padding: 0.75rem;
59
259
  border-radius: 12px;
60
- padding: 1.5rem;
61
- margin-bottom: 2rem;
62
- border: 1px solid #cbd5e1;
63
260
  }
64
261
 
65
- .stats-grid {
66
- background: linear-gradient(135deg, #1e40af 0%, #3730a3 100%);
67
- border-radius: 16px;
68
- color: white;
262
+ .category-description {
263
+ color: #64748b;
264
+ font-size: 1rem;
265
+ line-height: 1.6;
266
+ margin-bottom: 1rem;
69
267
  }
70
268
 
71
- /* Sidebar Styles */
72
- .sidebar {
73
- position: fixed;
74
- top: 0;
75
- left: 0;
76
- height: 100vh;
77
- width: 320px;
78
- background: white;
79
- border-right: 2px solid #e5e7eb;
269
+ .category-badges {
270
+ display: flex;
271
+ gap: 0.75rem;
272
+ flex-wrap: wrap;
273
+ }
274
+
275
+ .badge {
276
+ padding: 0.5rem 1rem;
277
+ border-radius: 8px;
278
+ font-size: 0.8rem;
279
+ font-weight: 600;
280
+ text-transform: uppercase;
281
+ letter-spacing: 0.025em;
282
+ }
283
+
284
+ .badge-primary {
285
+ background: #dbeafe;
286
+ color: #1e40af;
287
+ border: 1px solid #93c5fd;
288
+ }
289
+
290
+ .badge-success {
291
+ background: #dcfce7;
292
+ color: #166534;
293
+ border: 1px solid #bbf7d0;
294
+ }
295
+
296
+ .badge-error {
297
+ background: #fee2e2;
298
+ color: #dc2626;
299
+ border: 1px solid #fca5a5;
300
+ }
301
+
302
+ .components-showcase {
303
+ padding: 1.5rem;
304
+ max-height: 1000px;
80
305
  overflow-y: auto;
81
- z-index: 1000;
82
- transition: transform 0.3s ease;
83
306
  }
84
307
 
85
- .sidebar.collapsed {
86
- transform: translateX(-280px);
308
+ .components-showcase::-webkit-scrollbar {
309
+ width: 8px;
87
310
  }
88
311
 
89
- .sidebar-toggle {
90
- position: absolute;
91
- top: 50%;
92
- right: -40px;
93
- transform: translateY(-50%);
94
- background: #3b82f6;
95
- color: white;
96
- border: none;
97
- width: 40px;
98
- height: 80px;
99
- border-radius: 0 8px 8px 0;
100
- cursor: pointer;
312
+ .components-showcase::-webkit-scrollbar-track {
313
+ background: #f1f5f9;
314
+ border-radius: 4px;
315
+ }
316
+
317
+ .components-showcase::-webkit-scrollbar-thumb {
318
+ background: #cbd5e1;
319
+ border-radius: 4px;
320
+ }
321
+
322
+ .components-showcase::-webkit-scrollbar-thumb:hover {
323
+ background: #94a3b8;
324
+ }
325
+
326
+ .component-showcase-item {
327
+ margin-bottom: 3rem;
328
+ border: 1px solid #e2e8f0;
329
+ border-radius: 15px;
330
+ overflow: hidden;
331
+ background: #fafafa;
101
332
  transition: all 0.3s ease;
102
- display: flex;
103
- align-items: center;
104
- justify-content: center;
105
- font-size: 16px;
106
333
  }
107
334
 
108
- .sidebar-toggle:hover {
109
- background: #2563eb;
335
+ .component-showcase-item:hover {
336
+ border-color: #3b82f6;
337
+ transform: translateX(8px);
338
+ box-shadow: 0 8px 25px rgba(59, 130, 246, 0.1);
110
339
  }
111
340
 
112
- .main-content {
113
- margin-left: 320px;
114
- transition: margin-left 0.3s ease;
341
+ .component-header {
342
+ padding: 1.25rem 1.5rem;
343
+ background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
344
+ border-bottom: 1px solid #e2e8f0;
345
+ display: flex;
346
+ justify-content: space-between;
347
+ align-items: center;
348
+ flex-wrap: wrap;
349
+ gap: 1rem;
115
350
  }
116
351
 
117
- .main-content.expanded {
118
- margin-left: 40px;
352
+ .component-name {
353
+ font-size: 1.1rem;
354
+ font-weight: 600;
355
+ color: #1e293b;
119
356
  }
120
357
 
121
- .nav-item {
358
+ .component-meta {
122
359
  display: flex;
360
+ gap: 0.75rem;
123
361
  align-items: center;
124
- padding: 0.75rem 1rem;
125
- text-decoration: none;
126
- color: #374151;
127
- border-bottom: 1px solid #f3f4f6;
128
- transition: all 0.3s ease;
362
+ flex-wrap: wrap;
363
+ }
364
+
365
+ .component-preview {
366
+ padding: 2rem;
367
+ background: white;
368
+ min-height: 150px;
369
+ position: relative;
129
370
  }
130
371
 
131
- .nav-item:hover {
372
+ .component-preview::before {
373
+ content: 'Prévia Visual';
374
+ position: absolute;
375
+ top: 0.75rem;
376
+ right: 1rem;
377
+ font-size: 0.7rem;
378
+ color: #94a3b8;
379
+ text-transform: uppercase;
380
+ letter-spacing: 0.05em;
132
381
  background: #f8fafc;
133
- color: #1d4ed8;
382
+ padding: 0.25rem 0.75rem;
383
+ border-radius: 6px;
384
+ border: 1px solid #e2e8f0;
134
385
  }
135
386
 
136
- .nav-item.active {
137
- background: #eff6ff;
138
- color: #1d4ed8;
139
- border-right: 3px solid #3b82f6;
387
+ .component-preview.has-error {
388
+ background: #fef2f2;
389
+ border-top: 3px solid #dc2626;
140
390
  }
141
391
 
142
- .nav-item-icon {
143
- width: 40px;
144
- height: 40px;
145
- background: #f1f5f9;
146
- border-radius: 8px;
147
- display: flex;
148
- align-items: center;
149
- justify-content: center;
150
- margin-right: 0.75rem;
392
+ .component-preview.has-error::before {
393
+ content: 'Erro na Renderização';
394
+ background: #fee2e2;
395
+ color: #dc2626;
396
+ border-color: #fca5a5;
151
397
  }
152
398
 
153
- .nav-item.active .nav-item-icon {
154
- background: #dbeafe;
155
- color: #1d4ed8;
399
+ .error-message {
400
+ background: #fee2e2;
401
+ color: #dc2626;
402
+ padding: 2rem;
403
+ border-radius: 15px;
404
+ margin: 2rem 0;
405
+ border: 1px solid #fca5a5;
406
+ text-align: center;
407
+ }
408
+
409
+ .no-components {
410
+ text-align: center;
411
+ padding: 4rem;
412
+ color: #64748b;
413
+ background: white;
414
+ border-radius: 20px;
415
+ border: 2px dashed #cbd5e1;
416
+ box-shadow: 0 8px 25px rgba(0,0,0,0.08);
417
+ }
418
+
419
+ .no-components h3 {
420
+ font-size: 1.5rem;
421
+ color: #475569;
422
+ margin-bottom: 1rem;
423
+ }
424
+
425
+ .debug-panel {
426
+ background: #0f172a;
427
+ color: #e2e8f0;
428
+ padding: 2rem;
429
+ border-radius: 15px;
430
+ margin: 2rem 0;
431
+ font-family: 'Monaco', 'Consolas', 'Courier New', monospace;
432
+ font-size: 0.9rem;
433
+ box-shadow: 0 10px 30px rgba(0,0,0,0.2);
156
434
  }
157
435
 
158
- /* Mobile Responsiveness */
159
- @media (max-width: 1024px) {
160
- .sidebar {
161
- transform: translateX(-320px);
436
+ .debug-toggle {
437
+ background: #1e293b;
438
+ color: #e2e8f0;
439
+ border: 2px solid #334155;
440
+ padding: 0.75rem 1.5rem;
441
+ border-radius: 10px;
442
+ cursor: pointer;
443
+ font-weight: 600;
444
+ transition: all 0.3s ease;
445
+ margin-bottom: 1.5rem;
446
+ }
447
+
448
+ .debug-toggle:hover {
449
+ background: #334155;
450
+ border-color: #475569;
451
+ transform: translateY(-2px);
452
+ }
453
+
454
+ .debug-content {
455
+ background: #1e293b;
456
+ padding: 1.5rem;
457
+ border-radius: 10px;
458
+ max-height: 600px;
459
+ overflow-y: auto;
460
+ white-space: pre-line;
461
+ line-height: 1.5;
462
+ }
463
+
464
+ .info-section {
465
+ background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);
466
+ padding: 2rem;
467
+ border-radius: 15px;
468
+ margin-top: 3rem;
469
+ border-left: 4px solid #3b82f6;
470
+ }
471
+
472
+ .info-section h4 {
473
+ color: #1e40af;
474
+ margin-bottom: 1rem;
475
+ font-size: 1.25rem;
476
+ }
477
+
478
+ .info-section p {
479
+ color: #1e40af;
480
+ line-height: 1.6;
481
+ margin-bottom: 0.75rem;
482
+ }
483
+
484
+ /* Responsividade */
485
+ @media (max-width: 768px) {
486
+ .showcase-container {
487
+ padding: 1rem;
162
488
  }
163
489
 
164
- .sidebar.mobile-open {
165
- transform: translateX(0);
490
+ .showcase-header h1 {
491
+ font-size: 2rem;
166
492
  }
167
493
 
168
- .main-content {
169
- margin-left: 0;
494
+ .showcase-header p {
495
+ font-size: 1rem;
170
496
  }
171
497
 
172
- .sidebar-toggle {
173
- right: 16px;
174
- top: 16px;
175
- position: fixed;
176
- transform: none;
177
- width: 48px;
178
- height: 48px;
179
- border-radius: 12px;
180
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
498
+ .categories-grid {
499
+ grid-template-columns: 1fr;
181
500
  }
182
501
 
183
- .mobile-overlay {
184
- position: fixed;
185
- top: 0;
186
- left: 0;
187
- right: 0;
188
- bottom: 0;
189
- background: rgba(0, 0, 0, 0.5);
190
- z-index: 999;
191
- opacity: 0;
192
- visibility: hidden;
193
- transition: all 0.3s ease;
502
+ .stats-grid {
503
+ grid-template-columns: repeat(2, 1fr);
504
+ }
505
+
506
+ .controls-bar {
507
+ flex-direction: column;
508
+ align-items: stretch;
509
+ }
510
+
511
+ .filter-group {
512
+ justify-content: space-between;
194
513
  }
195
514
 
196
- .mobile-overlay.active {
515
+ .component-header {
516
+ flex-direction: column;
517
+ align-items: flex-start;
518
+ }
519
+ }
520
+
521
+ /* Animações */
522
+ .fade-in {
523
+ animation: fadeIn 0.6s ease-out;
524
+ }
525
+
526
+ @keyframes fadeIn {
527
+ from {
528
+ opacity: 0;
529
+ transform: translateY(30px);
530
+ }
531
+ to {
197
532
  opacity: 1;
198
- visibility: visible;
533
+ transform: translateY(0);
199
534
  }
200
535
  }
201
536
 
202
- /* Progress indicator */
203
- .progress-bar {
204
- position: fixed;
205
- top: 0;
206
- left: 0;
207
- height: 3px;
208
- background: #3b82f6;
209
- z-index: 1001;
210
- transition: width 0.3s ease;
537
+ .hidden {
538
+ display: none !important;
539
+ }
540
+
541
+ /* Estilos para placeholders de imagem */
542
+ .image-placeholder {
543
+ background: linear-gradient(135deg, #f1f5f9 0%, #e2e8f0 100%);
544
+ border: 2px dashed #cbd5e1;
545
+ border-radius: 8px;
546
+ display: flex;
547
+ align-items: center;
548
+ justify-content: center;
549
+ min-height: 200px;
550
+ color: #64748b;
551
+ font-size: 0.9rem;
552
+ text-align: center;
553
+ padding: 1rem;
554
+ position: relative;
555
+ overflow: hidden;
556
+ }
557
+
558
+ .image-placeholder::before {
559
+ content: '';
560
+ position: absolute;
561
+ top: -50%;
562
+ left: -50%;
563
+ width: 200%;
564
+ height: 200%;
565
+ background: radial-gradient(circle, rgba(203, 213, 225, 0.3) 1px, transparent 1px);
566
+ background-size: 20px 20px;
567
+ animation: float-placeholder 15s infinite linear;
568
+ }
569
+
570
+ @keyframes float-placeholder {
571
+ 0% { transform: translateX(-20px); }
572
+ 100% { transform: translateX(20px); }
573
+ }
574
+
575
+ .image-placeholder-content {
576
+ position: relative;
577
+ z-index: 2;
578
+ }
579
+
580
+ .image-placeholder i {
581
+ font-size: 3rem;
582
+ margin-bottom: 0.5rem;
583
+ color: #94a3b8;
584
+ }
585
+
586
+ /* Melhorias para componentes renderizados */
587
+ .component-preview > * {
588
+ margin: 0;
589
+ }
590
+
591
+ .component-preview .alert {
592
+ margin-bottom: 0;
593
+ }
594
+
595
+ /* Estilos para garantir que componentes sejam visíveis */
596
+ .component-preview img {
597
+ max-width: 100%;
598
+ height: auto;
599
+ border-radius: 8px;
600
+ box-shadow: 0 4px 8px rgba(0,0,0,0.1);
601
+ }
602
+
603
+ .component-preview .missing-image,
604
+ .component-preview .image-missing {
605
+ background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
606
+ border: 2px dashed #f59e0b;
607
+ border-radius: 8px;
608
+ padding: 2rem;
609
+ text-align: center;
610
+ color: #92400e;
611
+ font-weight: 500;
612
+ }
613
+
614
+ .component-preview .missing-image::before,
615
+ .component-preview .image-missing::before {
616
+ content: '🖼️';
617
+ font-size: 2rem;
618
+ display: block;
619
+ margin-bottom: 0.5rem;
620
+ }
621
+
622
+ .component-preview table {
623
+ width: 100%;
624
+ border-collapse: collapse;
625
+ margin: 0;
626
+ }
627
+
628
+ .component-preview .btn,
629
+ .component-preview button {
630
+ margin: 0.25rem;
631
+ }
632
+
633
+ /* Estilos para melhorar a visualização de formulários */
634
+ .component-preview form {
635
+ background: #f8fafc;
636
+ padding: 1.5rem;
637
+ border-radius: 8px;
638
+ border: 1px solid #e2e8f0;
639
+ }
640
+
641
+ .component-preview input,
642
+ .component-preview textarea,
643
+ .component-preview select {
644
+ width: 100%;
645
+ padding: 0.5rem;
646
+ border: 1px solid #d1d5db;
647
+ border-radius: 4px;
648
+ margin-bottom: 0.5rem;
649
+ }
650
+
651
+ /* Estilos para cards e containers */
652
+ .component-preview .card {
653
+ box-shadow: 0 2px 8px rgba(0,0,0,0.1);
654
+ border-radius: 8px;
655
+ overflow: hidden;
656
+ }
657
+
658
+ .component-preview .container {
659
+ max-width: 100%;
211
660
  }
212
661
  </style>
213
662
  </head>
214
- <body class="bg-gray-50 min-h-screen">
215
-
216
- <!-- Progress Bar -->
217
- <div class="progress-bar" id="progressBar"></div>
218
-
219
- <!-- Mobile Overlay -->
220
- <div class="mobile-overlay" id="mobileOverlay"></div>
221
-
222
- <!-- Sidebar -->
223
- <nav class="sidebar" id="sidebar">
224
- <!-- Sidebar Toggle Button -->
225
- <button class="sidebar-toggle" id="sidebarToggle">
226
- <i class="fas fa-chevron-left" id="toggleIcon"></i>
227
- </button>
228
-
229
- <!-- Sidebar Header -->
230
- <div class="p-6 border-b border-gray-200">
231
- <div class="flex items-center space-x-3">
232
- <div class="w-10 h-10 bg-gradient-to-br from-blue-500 to-indigo-600 rounded-xl flex items-center justify-center">
233
- <i class="fas fa-cubes text-white"></i>
234
- </div>
235
- <div>
236
- <h2 class="font-bold text-gray-900">Componentes</h2>
237
- <p class="text-sm text-gray-500">{{ total_components }} itens</p>
238
- </div>
239
- </div>
663
+ <body>
664
+ <div class="showcase-container">
665
+ <!-- Header -->
666
+ <div class="showcase-header">
667
+ <h1>{{ page_title }}</h1>
668
+ <p>{{ page_description }}</p>
240
669
  </div>
241
670
 
242
- <!-- Stats Summary -->
243
- <div class="p-4 bg-gradient-to-r from-blue-50 to-indigo-50 m-4 rounded-lg">
244
- <div class="grid grid-cols-2 gap-4 text-center">
245
- <div>
246
- <div class="text-2xl font-bold text-blue-600">{{ total_components }}</div>
247
- <div class="text-xs text-gray-600">Componentes</div>
248
- </div>
249
- <div>
250
- <div class="text-2xl font-bold text-indigo-600">{{ total_categories }}</div>
251
- <div class="text-xs text-gray-600">Categorias</div>
252
- </div>
671
+ <!-- Mensagem de Erro -->
672
+ {% if error_message %}
673
+ <div class="error-message">
674
+ <i class="fas fa-exclamation-triangle" style="font-size: 2rem; margin-bottom: 1rem;"></i>
675
+ <h3>Erro ao Carregar Componentes</h3>
676
+ <p>{{ error_message }}</p>
677
+ </div>
678
+ {% endif %}
679
+
680
+ <!-- Controles -->
681
+ <div class="controls-bar">
682
+ <div class="filter-group">
683
+ <label for="categoryFilter"><strong>Categoria:</strong></label>
684
+ <select id="categoryFilter" class="filter-select">
685
+ <option value="">Todas as categorias</option>
686
+ {% for category_name in available_categories %}
687
+ <option value="{{ category_name }}">{{ category_name|title }}</option>
688
+ {% endfor %}
689
+ </select>
690
+ </div>
691
+
692
+ <div class="search-box">
693
+ <i class="fas fa-search search-icon"></i>
694
+ <input type="text" id="searchInput" class="search-input" placeholder="Buscar componentes...">
695
+ </div>
696
+
697
+ <div class="filter-group">
698
+ <button class="toggle-btn" id="errorToggle">
699
+ <i class="fas fa-exclamation-triangle"></i> Apenas Erros
700
+ </button>
701
+ <button class="toggle-btn" id="successToggle">
702
+ <i class="fas fa-check-circle"></i> Apenas Sucessos
703
+ </button>
704
+ <button class="toggle-btn" id="resetFilter">
705
+ <i class="fas fa-sync-alt"></i> Limpar
706
+ </button>
253
707
  </div>
254
708
  </div>
255
709
 
256
- <!-- Navigation Menu -->
257
- <div class="flex-1 overflow-y-auto">
258
- {% for category_name, category in categories_with_components.items %}
259
- <a href="#{{ category_name }}" class="nav-item" data-category="{{ category_name }}">
260
- <div class="nav-item-icon">
261
- <i class="fas fa-{{ category.icon }}"></i>
262
- </div>
263
- <div class="flex-1">
264
- <div class="font-medium">{{ category.display_name }}</div>
265
- <div class="text-xs text-gray-500">{{ category.rendered_components|length }} componentes</div>
266
- </div>
267
- </a>
268
- {% endfor %}
710
+ <!-- Estatísticas -->
711
+ <div class="stats-grid">
712
+ <div class="stat-card">
713
+ <div class="stat-number">{{ total_categories }}</div>
714
+ <div class="stat-label">Categorias</div>
715
+ </div>
716
+ <div class="stat-card">
717
+ <div class="stat-number">{{ total_components }}</div>
718
+ <div class="stat-label">Componentes</div>
719
+ </div>
720
+ <div class="stat-card">
721
+ <div class="stat-number">{{ components_ok }}</div>
722
+ <div class="stat-label">Renderizados</div>
723
+ </div>
724
+ <div class="stat-card">
725
+ <div class="stat-number">{{ components_error }}</div>
726
+ <div class="stat-label">Com Erros</div>
727
+ </div>
269
728
  </div>
270
729
 
271
- <!-- Sidebar Footer -->
272
- <div class="p-4 border-t border-gray-200 bg-gray-50">
273
- <div class="text-center">
274
- <div class="text-xs text-gray-500 mb-1">ENAP Design System</div>
275
- <button onclick="scrollToTop()" class="text-blue-600 text-sm font-medium hover:text-blue-700 transition-colors">
276
- <i class="fas fa-arrow-up mr-1"></i>
277
- Voltar ao topo
278
- </button>
730
+ <!-- Debug Panel -->
731
+ {% if debug_mode and debug_log %}
732
+ <div class="debug-panel">
733
+ <button class="debug-toggle" onclick="toggleDebug()">
734
+ <i class="fas fa-bug"></i> Debug Log
735
+ </button>
736
+ <div id="debug-content" class="debug-content" style="display: none;">
737
+ {% for log_line in debug_log %}{{ log_line }}
738
+ {% endfor %}
279
739
  </div>
280
740
  </div>
281
- </nav>
282
-
283
- <!-- Main Content -->
284
- <div class="main-content" id="mainContent">
741
+ {% endif %}
285
742
 
286
- <!-- Header -->
287
- <header class="bg-white shadow-sm border-b">
288
- <div class="max-w-6xl mx-auto px-4 py-6">
289
- <div class="flex items-center space-x-4 mb-4">
290
- <div class="w-12 h-12 bg-gradient-to-br from-blue-500 to-indigo-600 rounded-xl flex items-center justify-center shadow-lg">
291
- <i class="fas fa-cubes text-white text-lg"></i>
292
- </div>
293
- <div>
294
- <h1 class="text-3xl font-bold text-gray-900">{{ page.title }}</h1>
295
- <p class="text-gray-600">{{ page_description }}</p>
296
- </div>
297
- </div>
298
-
299
- <!-- Description -->
300
- {% if page.description %}
301
- <div class="prose text-gray-600">
302
- {{ page.description|richtext }}
303
- </div>
304
- {% endif %}
305
-
306
- <!-- Error Message -->
307
- {% if error_message %}
308
- <div class="mt-4 p-4 bg-red-100 border border-red-400 text-red-700 rounded-lg">
309
- <i class="fas fa-exclamation-triangle mr-2"></i>
310
- {{ error_message }}
311
- </div>
312
- {% endif %}
313
- </div>
314
- </header>
315
-
316
- <div class="max-w-6xl mx-auto px-4 py-8">
317
-
318
- <!-- Stats -->
319
- <div class="stats-grid p-8 mb-8">
320
- <div class="grid grid-cols-1 md:grid-cols-3 gap-8 text-center">
321
- <div>
322
- <div class="text-4xl font-bold mb-2">{{ total_components }}</div>
323
- <div class="text-blue-100 text-lg">Componentes Renderizados</div>
324
- </div>
325
- <div>
326
- <div class="text-4xl font-bold mb-2">{{ total_categories }}</div>
327
- <div class="text-blue-100 text-lg">Categorias Disponíveis</div>
328
- </div>
329
- <div>
330
- <div class="text-4xl font-bold mb-2">100%</div>
331
- <div class="text-blue-100 text-lg">Renderização Direta</div>
332
- </div>
333
- </div>
334
- </div>
335
-
336
- <!-- Components by Category -->
743
+ <!-- Grid de Categorias -->
744
+ {% if categories_with_components %}
745
+ <div class="categories-grid" id="categoriesGrid">
337
746
  {% for category_name, category in categories_with_components.items %}
338
- <section class="mb-16" id="{{ category_name }}">
339
-
340
- <!-- Category Header -->
747
+ <div class="category-card fade-in" data-category="{{ category_name }}">
341
748
  <div class="category-header">
342
- <div class="flex items-center justify-between">
343
- <div class="flex items-center space-x-4">
344
- <div class="w-16 h-16 bg-white rounded-xl flex items-center justify-center shadow-md">
345
- <i class="fas fa-{{ category.icon }} text-2xl text-blue-600"></i>
346
- </div>
347
- <div>
348
- <h2 class="text-3xl font-bold text-gray-900 mb-2">
349
- {{ category.display_name }}
350
- </h2>
351
- <p class="text-gray-600 text-lg">{{ category.description }}</p>
352
- </div>
353
- </div>
354
- <div class="text-right">
355
- <div class="bg-blue-100 text-blue-800 px-4 py-2 rounded-full font-semibold">
356
- {{ category.rendered_components|length }} componentes
357
- </div>
358
- </div>
749
+ <h2 class="category-title">
750
+ <i class="fas fa-{{ category.icon }} category-icon"></i>
751
+ {{ category.display_name }}
752
+ </h2>
753
+ <p class="category-description">{{ category.description }}</p>
754
+
755
+ <div class="category-badges">
756
+ <span class="badge badge-primary">
757
+ <i class="fas fa-cubes"></i>
758
+ {{ category.rendered_components|length }} componente{{ category.rendered_components|length|pluralize }}
759
+ </span>
760
+ {% with error_count=0 %}
761
+ {% for component in category.rendered_components %}
762
+ {% if component.has_error %}
763
+ {% if forloop.first %}
764
+ <span class="badge badge-error">
765
+ <i class="fas fa-exclamation-triangle"></i>
766
+ Com problemas
767
+ </span>
768
+ {% endif %}
769
+ {% endif %}
770
+ {% endfor %}
771
+ {% endwith %}
359
772
  </div>
360
773
  </div>
361
774
 
362
- <!-- Components Grid -->
363
- <div class="space-y-6">
775
+ <div class="components-showcase">
364
776
  {% for component in category.rendered_components %}
365
- <div class="component-showcase {% if component.has_error %}error-component{% endif %}">
366
-
367
- <!-- Component Header -->
777
+ <div class="component-showcase-item" data-component="{{ component.name }}" data-has-error="{{ component.has_error|yesno:'true,false' }}">
368
778
  <div class="component-header">
369
- <div class="flex items-center justify-between">
370
- <div>
371
- <h3 class="font-semibold text-lg">{{ component.display_name }}</h3>
372
- <div class="text-sm opacity-90 mt-1">
373
- Classe: {{ component.class_name }}
374
- </div>
375
- </div>
376
- <div class="flex items-center space-x-3 text-sm">
377
- {% if component.field_count > 0 %}
378
- <span class="bg-white/20 px-2 py-1 rounded">
379
- {{ component.field_count }} campos
779
+ <div class="component-name">{{ component.display_name }}</div>
780
+ <div class="component-meta">
781
+ {% if component.has_error %}
782
+ <span class="badge badge-error">
783
+ <i class="fas fa-times-circle"></i> Erro
380
784
  </span>
381
- {% endif %}
382
- <span class="bg-white/20 px-2 py-1 rounded">
383
- {{ category_name }}
785
+ {% else %}
786
+ <span class="badge badge-success">
787
+ <i class="fas fa-check-circle"></i> OK
384
788
  </span>
385
- </div>
789
+ {% endif %}
790
+ <span class="badge badge-primary">{{ component.class_name }}</span>
386
791
  </div>
387
792
  </div>
388
793
 
389
- <!-- Component Rendered Content -->
390
- <div class="component-content">
794
+ <div class="component-preview {% if component.has_error %}has-error{% endif %}">
391
795
  {{ component.rendered_html|safe }}
392
796
  </div>
393
797
 
394
- <!-- Component Meta -->
395
- <div class="component-meta">
396
- <div class="flex items-center justify-between">
397
- <span>
398
- Componente: <code>{{ component.name }}</code>
399
- </span>
400
- <span>
401
- {% if component.has_error %}
402
- <i class="fas fa-exclamation-triangle text-red-500 mr-1"></i>
403
- Erro na renderização
404
- {% else %}
405
- <i class="fas fa-check-circle text-green-500 mr-1"></i>
406
- Renderizado com sucesso
407
- {% endif %}
408
- </span>
798
+ {% if debug_mode and component.data_used %}
799
+ <details style="margin: 1rem 1.5rem; font-size: 0.9rem;">
800
+ <summary style="cursor: pointer; padding: 0.75rem; background: #f8fafc; border-radius: 8px; color: #64748b;">
801
+ <i class="fas fa-code"></i> Ver dados utilizados ({{ component.data_used|length }} campos)
802
+ </summary>
803
+ <div style="margin-top: 0.75rem; padding: 1rem; background: #f1f5f9; border-radius: 8px; border-left: 3px solid #3b82f6;">
804
+ {% for key, value in component.data_used.items %}
805
+ <div style="margin-bottom: 0.75rem; padding-bottom: 0.75rem; border-bottom: 1px solid #e2e8f0;">
806
+ <strong style="color: #1e40af; font-family: monospace;">{{ key }}:</strong>
807
+ <div style="color: #374151; margin-top: 0.25rem; word-break: break-word;">{{ value|truncatechars:200 }}</div>
808
+ </div>
809
+ {% endfor %}
409
810
  </div>
410
- </div>
811
+ </details>
812
+ {% endif %}
813
+
814
+ {% if component.error_message %}
815
+ <details style="margin: 1rem 1.5rem; font-size: 0.9rem;">
816
+ <summary style="cursor: pointer; padding: 0.75rem; background: #fee2e2; border-radius: 8px; color: #dc2626;">
817
+ <i class="fas fa-exclamation-triangle"></i> Ver detalhes do erro
818
+ </summary>
819
+ <div style="margin-top: 0.75rem; padding: 1rem; background: #fef2f2; border-radius: 8px; border-left: 3px solid #dc2626; color: #dc2626; font-family: monospace; font-size: 0.8rem;">
820
+ {{ component.error_message }}
821
+ </div>
822
+ </details>
823
+ {% endif %}
824
+ </div>
825
+ {% empty %}
826
+ <div class="no-components">
827
+ <i class="fas fa-search" style="font-size: 3rem; margin-bottom: 1rem; color: #cbd5e1;"></i>
828
+ <h4>Nenhum componente renderizado</h4>
829
+ <p>Esta categoria não possui componentes que puderam ser renderizados.</p>
411
830
  </div>
412
831
  {% endfor %}
413
832
  </div>
414
-
415
- </section>
416
- {% empty %}
417
-
418
- <!-- Empty State -->
419
- <div class="text-center py-16">
420
- <div class="w-24 h-24 bg-gray-200 rounded-full flex items-center justify-center mx-auto mb-6">
421
- <i class="fas fa-cube text-4xl text-gray-400"></i>
422
- </div>
423
- <h3 class="text-2xl font-semibold text-gray-900 mb-4">Nenhuma categoria encontrada</h3>
424
- <div class="max-w-md mx-auto text-gray-600 space-y-2">
425
- <p>Possíveis motivos:</p>
426
- <ul class="text-left space-y-1">
427
- <li>• LAYOUT_STREAMBLOCKS não está configurado</li>
428
- <li>• Erro nos imports dos blocos</li>
429
- <li>• Componentes não têm valores padrão válidos</li>
430
- </ul>
431
- </div>
432
- <div class="mt-6">
433
- <button onclick="location.reload()" class="bg-blue-600 text-white px-6 py-3 rounded-lg hover:bg-blue-700 transition-colors">
434
- <i class="fas fa-refresh mr-2"></i>
435
- Tentar Novamente
436
- </button>
437
- </div>
438
833
  </div>
439
-
440
834
  {% endfor %}
441
835
  </div>
442
-
443
- <!-- Footer -->
444
- <footer class="bg-white border-t mt-16">
445
- <div class="max-w-6xl mx-auto px-4 py-8">
446
- <div class="flex items-center justify-between">
447
- <div class="text-gray-600">
448
- <p>Showcase de Componentes ENAP - Design System</p>
449
- <p class="text-sm">Renderização direta usando valores padrão dos componentes</p>
450
- </div>
451
- <div class="text-gray-500 text-sm">
452
- {{ total_components }} componentes {{ total_categories }} categorias
453
- </div>
454
- </div>
455
- </div>
456
- </footer>
457
-
836
+ {% else %}
837
+ <div class="no-components">
838
+ <i class="fas fa-search" style="font-size: 4rem; margin-bottom: 1.5rem; color: #cbd5e1;"></i>
839
+ <h3>Nenhum componente encontrado</h3>
840
+ <p>Verifique se os <code>LAYOUT_STREAMBLOCKS</code> estão configurados corretamente.</p>
841
+ </div>
842
+ {% endif %}
843
+
844
+ <!-- Informações -->
845
+ <div class="info-section">
846
+ <h4><i class="fas fa-info-circle"></i> Sobre este Showcase</h4>
847
+ <p>
848
+ Este showcase apresenta visualmente todos os componentes do Design System ENAP.
849
+ Cada componente é renderizado com dados realistas para demonstrar sua aparência e funcionalidade.
850
+ </p>
851
+ <p>
852
+ Use os filtros acima para navegar pelas categorias ou buscar componentes específicos.
853
+ Componentes que não puderam ser renderizados são marcados com placeholders informativos.
854
+ </p>
855
+ </div>
458
856
  </div>
459
-
460
- <!-- JavaScript -->
857
+
461
858
  <script>
462
- // Elements
463
- const sidebar = document.getElementById('sidebar');
464
- const mainContent = document.getElementById('mainContent');
465
- const sidebarToggle = document.getElementById('sidebarToggle');
466
- const toggleIcon = document.getElementById('toggleIcon');
467
- const mobileOverlay = document.getElementById('mobileOverlay');
468
- const progressBar = document.getElementById('progressBar');
469
- const navItems = document.querySelectorAll('.nav-item');
470
-
471
- // State
472
- let sidebarCollapsed = false;
473
- let isMobile = window.innerWidth <= 1024;
474
-
475
- // Sidebar Toggle
476
- sidebarToggle.addEventListener('click', function() {
477
- if (isMobile) {
478
- sidebar.classList.toggle('mobile-open');
479
- mobileOverlay.classList.toggle('active');
480
- } else {
481
- sidebarCollapsed = !sidebarCollapsed;
482
- sidebar.classList.toggle('collapsed');
483
- mainContent.classList.toggle('expanded');
484
- toggleIcon.className = sidebarCollapsed ? 'fas fa-chevron-right' : 'fas fa-chevron-left';
485
- }
486
- });
487
-
488
- // Mobile overlay click
489
- mobileOverlay.addEventListener('click', function() {
490
- sidebar.classList.remove('mobile-open');
491
- mobileOverlay.classList.remove('active');
492
- });
493
-
494
- // Window resize handler
495
- window.addEventListener('resize', function() {
496
- const wasMobile = isMobile;
497
- isMobile = window.innerWidth <= 1024;
859
+ // Sistema de filtros e busca
860
+ document.addEventListener('DOMContentLoaded', function() {
861
+ const categoryFilter = document.getElementById('categoryFilter');
862
+ const errorToggle = document.getElementById('errorToggle');
863
+ const successToggle = document.getElementById('successToggle');
864
+ const resetFilter = document.getElementById('resetFilter');
865
+ const searchInput = document.getElementById('searchInput');
866
+ const categoriesGrid = document.getElementById('categoriesGrid');
498
867
 
499
- if (wasMobile !== isMobile) {
500
- // Reset sidebar state when switching between mobile/desktop
501
- sidebar.classList.remove('collapsed', 'mobile-open');
502
- mainContent.classList.remove('expanded');
503
- mobileOverlay.classList.remove('active');
504
- sidebarCollapsed = false;
505
- toggleIcon.className = 'fas fa-chevron-left';
506
- }
507
- });
508
-
509
- // Smooth scrolling and active state management
510
- navItems.forEach(item => {
511
- item.addEventListener('click', function(e) {
512
- e.preventDefault();
513
- const targetId = this.getAttribute('href').substring(1);
514
- const targetElement = document.getElementById(targetId);
868
+ let currentFilters = {
869
+ category: '',
870
+ showOnlyErrors: false,
871
+ showOnlySuccess: false,
872
+ searchTerm: ''
873
+ };
874
+
875
+ function applyFilters() {
876
+ const categories = categoriesGrid.querySelectorAll('.category-card');
877
+ let visibleCategories = 0;
515
878
 
516
- if (targetElement) {
517
- // Remove active class from all items
518
- navItems.forEach(nav => nav.classList.remove('active'));
519
- // Add active class to clicked item
520
- this.classList.add('active');
879
+ categories.forEach(categoryCard => {
880
+ const categoryName = categoryCard.dataset.category;
881
+ let categoryVisible = true;
882
+ let hasVisibleComponents = false;
521
883
 
522
- // Smooth scroll to target
523
- targetElement.scrollIntoView({
524
- behavior: 'smooth',
525
- block: 'start'
526
- });
884
+ // Filtro de categoria
885
+ if (currentFilters.category && categoryName !== currentFilters.category) {
886
+ categoryVisible = false;
887
+ }
527
888
 
528
- // Close mobile sidebar
529
- if (isMobile) {
530
- sidebar.classList.remove('mobile-open');
531
- mobileOverlay.classList.remove('active');
889
+ if (categoryVisible) {
890
+ // Filtros de componentes
891
+ const components = categoryCard.querySelectorAll('.component-showcase-item');
892
+
893
+ components.forEach(component => {
894
+ const componentName = component.dataset.component.toLowerCase();
895
+ const hasError = component.dataset.hasError === 'true';
896
+ let componentVisible = true;
897
+
898
+ // Filtro de erro/sucesso
899
+ if (currentFilters.showOnlyErrors && !hasError) {
900
+ componentVisible = false;
901
+ }
902
+ if (currentFilters.showOnlySuccess && hasError) {
903
+ componentVisible = false;
904
+ }
905
+
906
+ // Filtro de busca
907
+ if (currentFilters.searchTerm && !componentName.includes(currentFilters.searchTerm.toLowerCase())) {
908
+ componentVisible = false;
909
+ }
910
+
911
+ component.style.display = componentVisible ? 'block' : 'none';
912
+
913
+ if (componentVisible) {
914
+ hasVisibleComponents = true;
915
+ }
916
+ });
917
+
918
+ // Mostrar categoria apenas se tiver componentes visíveis
919
+ if (!hasVisibleComponents) {
920
+ categoryVisible = false;
921
+ }
922
+ }
923
+
924
+ categoryCard.style.display = categoryVisible ? 'block' : 'none';
925
+
926
+ if (categoryVisible) {
927
+ visibleCategories++;
532
928
  }
533
- }
929
+ });
930
+ }
931
+
932
+ // Event listeners
933
+ categoryFilter.addEventListener('change', function() {
934
+ currentFilters.category = this.value;
935
+ applyFilters();
534
936
  });
535
- });
536
-
537
- // Scroll spy - update active nav item based on scroll position
538
- function updateActiveNavItem() {
539
- const sections = document.querySelectorAll('section[id]');
540
- const scrollPosition = window.scrollY + 100;
541
937
 
542
- sections.forEach(section => {
543
- const sectionTop = section.offsetTop;
544
- const sectionHeight = section.offsetHeight;
545
- const sectionId = section.getAttribute('id');
938
+ errorToggle.addEventListener('click', function() {
939
+ currentFilters.showOnlyErrors = !currentFilters.showOnlyErrors;
940
+ currentFilters.showOnlySuccess = false;
546
941
 
547
- if (scrollPosition >= sectionTop && scrollPosition < sectionTop + sectionHeight) {
548
- navItems.forEach(nav => nav.classList.remove('active'));
549
- const activeNav = document.querySelector(`a[data-category="${sectionId}"]`);
550
- if (activeNav) {
551
- activeNav.classList.add('active');
552
- }
553
- }
942
+ this.classList.toggle('active', currentFilters.showOnlyErrors);
943
+ successToggle.classList.remove('active');
944
+
945
+ applyFilters();
946
+ });
947
+
948
+ successToggle.addEventListener('click', function() {
949
+ currentFilters.showOnlySuccess = !currentFilters.showOnlySuccess;
950
+ currentFilters.showOnlyErrors = false;
951
+
952
+ this.classList.toggle('active', currentFilters.showOnlySuccess);
953
+ errorToggle.classList.remove('active');
954
+
955
+ applyFilters();
956
+ });
957
+
958
+ resetFilter.addEventListener('click', function() {
959
+ currentFilters = {
960
+ category: '',
961
+ showOnlyErrors: false,
962
+ showOnlySuccess: false,
963
+ searchTerm: ''
964
+ };
965
+
966
+ categoryFilter.value = '';
967
+ searchInput.value = '';
968
+ errorToggle.classList.remove('active');
969
+ successToggle.classList.remove('active');
970
+
971
+ applyFilters();
972
+ });
973
+
974
+ searchInput.addEventListener('input', function() {
975
+ currentFilters.searchTerm = this.value;
976
+ applyFilters();
554
977
  });
555
- }
556
-
557
- // Progress bar
558
- function updateProgressBar() {
559
- const scrollTop = window.pageYOffset;
560
- const docHeight = document.body.offsetHeight - window.innerHeight;
561
- const scrollPercent = (scrollTop / docHeight) * 100;
562
- progressBar.style.width = scrollPercent + '%';
563
- }
564
-
565
- // Scroll event listeners
566
- window.addEventListener('scroll', function() {
567
- updateActiveNavItem();
568
- updateProgressBar();
569
978
  });
570
979
 
571
- // Scroll to top function
572
- function scrollToTop() {
573
- window.scrollTo({
574
- top: 0,
575
- behavior: 'smooth'
576
- });
980
+ // Toggle debug
981
+ function toggleDebug() {
982
+ const debugContent = document.getElementById('debug-content');
983
+ const toggleButton = document.querySelector('.debug-toggle');
984
+
985
+ if (debugContent.style.display === 'none') {
986
+ debugContent.style.display = 'block';
987
+ toggleButton.innerHTML = '<i class="fas fa-bug"></i> Ocultar Debug Log';
988
+ } else {
989
+ debugContent.style.display = 'none';
990
+ toggleButton.innerHTML = '<i class="fas fa-bug"></i> Debug Log';
991
+ }
577
992
  }
578
-
579
- // Initial setup
580
- updateActiveNavItem();
581
- updateProgressBar();
582
-
583
- // Log de estatísticas no console
584
- console.log('Showcase com Sidebar carregado:');
585
- console.log('- Total de componentes:', {{ total_components }});
586
- console.log('- Total de categorias:', {{ total_categories }});
587
- console.log('- Renderização: Direta (sem AJAX)');
588
- console.log('- Navegação: Sidebar fixa com scroll spy');
589
993
  </script>
590
-
591
994
  </body>
592
995
  </html>