doeqoth commited on
Commit
3a61c2b
·
verified ·
1 Parent(s): 1e3c516

Manual changes saved

Browse files
Files changed (1) hide show
  1. style.css +290 -173
style.css CHANGED
@@ -1,179 +1,296 @@
1
- :root {
2
- --primary: #2563eb;
3
- --secondary: #1e40af;
4
- --accent: #3b82f6;
5
- --bg: #f8fafc;
6
- --surface: #ffffff;
7
- --text: #1e293b;
8
- --text-light: #64748b;
9
- --border: #e2e8f0;
10
- --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
11
- --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
12
- --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
13
- --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1);
14
- }
15
-
16
- * {
17
- font-family: 'Sarabun', sans-serif;
18
- }
19
-
20
- body {
21
- background-color: var(--bg);
22
- color: var(--text);
23
- line-height: 1.6;
24
- }
25
-
26
- /* Custom Scrollbar */
27
- ::-webkit-scrollbar {
28
- width: 8px;
29
- height: 8px;
30
- }
31
-
32
- ::-webkit-scrollbar-track {
33
- background: #f1f5f9;
34
- border-radius: 4px;
35
- }
36
-
37
- ::-webkit-scrollbar-thumb {
38
- background: #cbd5e1;
39
- border-radius: 4px;
40
- }
41
-
42
- ::-webkit-scrollbar-thumb:hover {
43
- background: #94a3b8;
44
- }
45
-
46
- /* Animations */
47
- @keyframes fade-in {
48
- from { opacity: 0; transform: translateY(-10px); }
49
- to { opacity: 1; transform: translateY(0); }
50
- }
51
-
52
- @keyframes slide-up {
53
- from { opacity: 0; transform: translateY(20px); }
54
- to { opacity: 1; transform: translateY(0); }
55
- }
56
-
57
- @keyframes pulse-soft {
58
- 0%, 100% { opacity: 1; }
59
- 50% { opacity: 0.7; }
60
- }
61
-
62
- .animate-fade-in {
63
- animation: fade-in 0.6s ease-out;
64
- }
65
-
66
- .animate-slide-up {
67
- animation: slide-up 0.5s ease-out;
68
- }
69
-
70
- .animate-pulse-soft {
71
- animation: pulse-soft 2s ease-in-out infinite;
72
- }
73
-
74
- /* Upload Zone Styles */
75
- .upload-zone-dragover {
76
- border-color: var(--primary) !important;
77
- background-color: #eff6ff !important;
78
- transform: scale(1.02);
79
- }
80
-
81
- /* Glass Effect */
82
- .glass {
83
- background: rgba(255, 255, 255, 0.85);
84
- backdrop-filter: blur(12px);
85
- -webkit-backdrop-filter: blur(12px);
86
- }
87
-
88
- /* Data Card Hover Effects */
89
- .data-card {
90
- transition: all 0.2s ease;
91
- border: 1px solid var(--border);
92
- }
93
-
94
- .data-card:hover {
95
- transform: translateY(-2px);
96
- box-shadow: var(--shadow-lg);
97
- border-color: #bfdbfe;
98
- }
99
-
100
- /* Floating Controls Container */
101
- #floating-controls-container {
102
- scrollbar-width: none;
103
- -ms-overflow-style: none;
104
- }
105
-
106
- #floating-controls-container::-webkit-scrollbar {
107
- display: none;
108
- }
109
-
110
- /* PDF Canvas Render */
111
- #pdf-canvas, #preview-image {
112
- max-width: 100%;
113
- height: auto;
114
- box-shadow: var(--shadow-xl);
115
- border-radius: 8px;
116
- }
117
-
118
- /* Button Interactions */
119
- .btn-interactive {
120
- transition: all 0.2s ease;
121
- position: relative;
122
- overflow: hidden;
123
- }
124
-
125
- .btn-interactive:active {
126
- transform: scale(0.95);
127
- }
128
-
129
- .btn-interactive::after {
130
- content: '';
131
- position: absolute;
132
- top: 50%;
133
- left: 50%;
134
- width: 0;
135
- height: 0;
136
- border-radius: 50%;
137
- background: rgba(255, 255, 255, 0.3);
138
- transform: translate(-50%, -50%);
139
- transition: width 0.3s, height 0.3s;
140
- }
141
-
142
- .btn-interactive:hover::after {
143
- width: 200px;
144
- height: 200px;
145
- }
146
-
147
- /* JSON Syntax Highlighting */
148
- .json-key { color: #93c5fd; }
149
- .json-string { color: #86efac; }
150
- .json-number { color: #fca5a5; }
151
- .json-boolean { color: #f9a8d4; }
152
-
153
- /* Responsive Adjustments */
154
- @media (max-width: 640px) {
155
- .container {
156
- padding-left: 1rem;
157
- padding-right: 1rem;
158
  }
159
 
160
- #preview-container {
161
- padding: 1rem;
162
- min-height: 300px;
163
- }
164
- }
165
-
166
- /* Print Styles */
167
- @media print {
168
- .no-print {
169
- display: none !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  }
171
 
172
- body {
173
- background: white;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
  }
175
-
176
- #results-section {
177
- display: block !important;
 
 
178
  }
179
- }
 
 
 
1
+ class FloatingControls extends HTMLElement {
2
+ constructor() {
3
+ super();
4
+ this.hasFile = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  }
6
 
7
+ connectedCallback() {
8
+ this.attachShadow({ mode: 'open' });
9
+ this.shadowRoot.innerHTML = `
10
+ <style>
11
+ :host {
12
+ display: block;
13
+ position: fixed;
14
+ bottom: 24px;
15
+ left: 50%;
16
+ transform: translateX(-50%);
17
+ z-index: 100;
18
+ width: auto;
19
+ max-width: 90vw;
20
+ }
21
+
22
+ .controls-container {
23
+ background: rgba(255, 255, 255, 0.95);
24
+ backdrop-filter: blur(20px);
25
+ -webkit-backdrop-filter: blur(20px);
26
+ border: 1px solid rgba(226, 232, 240, 0.8);
27
+ border-radius: 16px;
28
+ padding: 12px 16px;
29
+ box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04), 0 0 0 1px rgba(0, 0, 0, 0.05);
30
+ display: flex;
31
+ align-items: center;
32
+ gap: 8px;
33
+ flex-wrap: wrap;
34
+ justify-content: center;
35
+ transition: all 0.3s ease;
36
+ }
37
+
38
+ .controls-container.disabled {
39
+ opacity: 0.5;
40
+ pointer-events: none;
41
+ }
42
+
43
+ .btn-group {
44
+ display: flex;
45
+ gap: 4px;
46
+ padding: 0 8px;
47
+ border-right: 1px solid #e2e8f0;
48
+ }
49
+
50
+ .btn-group:last-child {
51
+ border-right: none;
52
+ }
53
+
54
+ button {
55
+ display: flex;
56
+ align-items: center;
57
+ gap: 6px;
58
+ padding: 8px 14px;
59
+ border: none;
60
+ border-radius: 10px;
61
+ font-size: 0.875rem;
62
+ font-weight: 500;
63
+ cursor: pointer;
64
+ transition: all 0.2s ease;
65
+ font-family: 'Sarabun', sans-serif;
66
+ white-space: nowrap;
67
+ }
68
+
69
+ button:hover {
70
+ transform: translateY(-1px);
71
+ }
72
+
73
+ button:active {
74
+ transform: translateY(0);
75
+ }
76
+
77
+ .btn-primary {
78
+ background: linear-gradient(135deg, #2563eb, #3b82f6);
79
+ color: white;
80
+ box-shadow: 0 4px 6px -1px rgba(37, 99, 235, 0.2);
81
+ }
82
+
83
+ .btn-primary:hover {
84
+ box-shadow: 0 8px 12px -2px rgba(37, 99, 235, 0.3);
85
+ }
86
+
87
+ .btn-secondary {
88
+ background: #f1f5f9;
89
+ color: #475569;
90
+ border: 1px solid #e2e8f0;
91
+ }
92
+
93
+ .btn-secondary:hover {
94
+ background: #e2e8f0;
95
+ color: #1e293b;
96
+ }
97
+
98
+ .btn-success {
99
+ background: linear-gradient(135deg, #059669, #10b981);
100
+ color: white;
101
+ box-shadow: 0 4px 6px -1px rgba(5, 150, 105, 0.2);
102
+ }
103
+
104
+ .btn-success:hover {
105
+ box-shadow: 0 8px 12px -2px rgba(5, 150, 105, 0.3);
106
+ }
107
+
108
+ .btn-export {
109
+ background: #fffbeb;
110
+ color: #d97706;
111
+ border: 1px solid #fcd34d;
112
+ }
113
+
114
+ .btn-export:hover {
115
+ background: #fef3c7;
116
+ }
117
+
118
+ .separator {
119
+ width: 1px;
120
+ height: 24px;
121
+ background: #e2e8f0;
122
+ margin: 0 4px;
123
+ }
124
+
125
+ .icon {
126
+ width: 16px;
127
+ height: 16px;
128
+ }
129
+
130
+ @media (max-width: 640px) {
131
+ .controls-container {
132
+ padding: 8px 12px;
133
+ gap: 4px;
134
+ }
135
+
136
+ button {
137
+ padding: 6px 10px;
138
+ font-size: 0.75rem;
139
+ }
140
+
141
+ button span {
142
+ display: none;
143
+ }
144
+
145
+ .icon {
146
+ width: 18px;
147
+ height: 18px;
148
+ }
149
+ }
150
+
151
+ @keyframes slide-up {
152
+ from {
153
+ opacity: 0;
154
+ transform: translateY(20px) translateX(-50%);
155
+ }
156
+ to {
157
+ opacity: 1;
158
+ transform: translateY(0) translateX(-50%);
159
+ }
160
+ }
161
+
162
+ :host {
163
+ animation: slide-up 0.4s ease-out;
164
+ }
165
+ </style>
166
+ <div class="controls-container" id="controls-container">
167
+ <div class="btn-group">
168
+ <button class="btn-primary" id="analyze-btn" title="วิเคราะห์โครงสร้าง PDF">
169
+ <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
170
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
171
+ <polyline points="14 2 14 8 20 8"></polyline>
172
+ <line x1="16" y1="13" x2="8" y2="13"></line>
173
+ <line x1="16" y1="17" x2="8" y2="17"></line>
174
+ <polyline points="10 9 9 9 8 9"></polyline>
175
+ </svg>
176
+ <span>วิเคราะห์ PDF</span>
177
+ </button>
178
+ <button class="btn-success" id="ocr-btn" title="OCR ภาษาไทย">
179
+ <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
180
+ <path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"></path>
181
+ <path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"></path>
182
+ </svg>
183
+ <span>OCR ไทย</span>
184
+ </button>
185
+ </div>
186
+
187
+ <div class="btn-group">
188
+ <button class="btn-secondary" id="copy-btn" title="คัดลอกทั้งหมด">
189
+ <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
190
+ <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
191
+ <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
192
+ </svg>
193
+ <span>คัดลอก</span>
194
+ </button>
195
+ </div>
196
+
197
+ <div class="btn-group">
198
+ <button class="btn-export" id="export-json-btn" title="Export JSON">
199
+ <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
200
+ <polyline points="4 17 10 11 4 5"></polyline>
201
+ <line x1="12" y1="19" x2="20" y2="19"></line>
202
+ </svg>
203
+ <span>JSON</span>
204
+ </button>
205
+ <button class="btn-export" id="export-csv-btn" title="Export CSV">
206
+ <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
207
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
208
+ <polyline points="14 2 14 8 20 8"></polyline>
209
+ <line x1="16" y1="13" x2="8" y2="13"></line>
210
+ <line x1="16" y1="17" x2="8" y2="17"></line>
211
+ <polyline points="10 9 9 9 8 9"></polyline>
212
+ </svg>
213
+ <span>CSV</span>
214
+ </button>
215
+ <button class="btn-export" id="export-excel-btn" title="Export Excel">
216
+ <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
217
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
218
+ <polyline points="14 2 14 8 20 8"></polyline>
219
+ <path d="M8 13h8"></path>
220
+ <path d="M8 17h8"></path>
221
+ <path d="M9 9h6"></path>
222
+ </svg>
223
+ <span>Excel</span>
224
+ </button>
225
+ <button class="btn-export" id="export-html-btn" title="Export HTML+CSS+JS">
226
+ <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
227
+ <path d="m13 2-2 2.5h3zm-2 2.5L9 7h3zm-2 2.5L6 9.5h3zm-2 2.5L3 12h3zm8-5L11 7h3zm-2 2.5L9 9.5h3zm-2 2.5L7 12h3z"></path>
228
+ <path d="M14 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2z"></path>
229
+ </svg>
230
+ <span>HTML</span>
231
+ </button>
232
+ </div>
233
+ </div>
234
+ `;
235
+
236
+ this.setupEventListeners();
237
+ this.updateState();
238
  }
239
 
240
+ setupEventListeners() {
241
+ // Listen for events from script.js to know when file is loaded
242
+ document.addEventListener('file-selected', () => {
243
+ this.hasFile = true;
244
+ this.updateState();
245
+ });
246
+
247
+ document.addEventListener('reset-app', () => {
248
+ this.hasFile = false;
249
+ this.updateState();
250
+ });
251
+
252
+ // Button click handlers
253
+ this.shadowRoot.getElementById('analyze-btn').addEventListener('click', () => {
254
+ this.dispatchEvent(new CustomEvent('analyze-pdf', { bubbles: true, composed: true }));
255
+ });
256
+
257
+ this.shadowRoot.getElementById('ocr-btn').addEventListener('click', () => {
258
+ this.dispatchEvent(new CustomEvent('ocr-thai', { bubbles: true, composed: true }));
259
+ });
260
+
261
+ this.shadowRoot.getElementById('copy-btn').addEventListener('click', () => {
262
+ this.dispatchEvent(new CustomEvent('copy-all', { bubbles: true, composed: true }));
263
+ });
264
+
265
+ this.shadowRoot.getElementById('export-json-btn').addEventListener('click', () => {
266
+ this.dispatchEvent(new CustomEvent('export-json', { bubbles: true, composed: true }));
267
+ });
268
+
269
+ this.shadowRoot.getElementById('export-csv-btn').addEventListener('click', () => {
270
+ this.dispatchEvent(new CustomEvent('export-csv', { bubbles: true, composed: true }));
271
+ });
272
+ this.shadowRoot.getElementById('export-excel-btn').addEventListener('click', () => {
273
+ this.dispatchEvent(new CustomEvent('export-excel', { bubbles: true, composed: true }));
274
+ });
275
+
276
+ this.shadowRoot.getElementById('export-html-btn').addEventListener('click', () => {
277
+ this.dispatchEvent(new CustomEvent('export-html', { bubbles: true, composed: true }));
278
+ });
279
+ }
280
+ updateState() {
281
+ const container = this.shadowRoot.getElementById('controls-container');
282
+ if (this.hasFile) {
283
+ container.classList.remove('disabled');
284
+ } else {
285
+ container.classList.add('disabled');
286
+ }
287
  }
288
+
289
+ // Make the controls always visible by removing the disabled class
290
+ showControls() {
291
+ const container = this.shadowRoot.getElementById('controls-container');
292
+ container.classList.remove('disabled');
293
  }
294
+ }
295
+
296
+ customElements.define('floating-controls', FloatingControls);