pivotgrid-js 0.1.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.
@@ -0,0 +1,672 @@
1
+ /* ── Demo page styles ────────────────────────────────────────────────────── */
2
+
3
+ *, *::before, *::after {
4
+ box-sizing: border-box;
5
+ margin: 0;
6
+ padding: 0;
7
+ }
8
+
9
+ body {
10
+ font-family: -apple-system, 'Segoe UI', sans-serif;
11
+ background: #f4f5f7;
12
+ color: #1a1a1a;
13
+ padding: 12px;
14
+ min-height: 100vh;
15
+
16
+ display: flex;
17
+ flex-direction: column;
18
+ height: 100dvh;
19
+ overflow: hidden;
20
+ gap: 8px;
21
+ }
22
+
23
+ /* ── Toolbar ─────────────────────────────────────────────────────────────── */
24
+
25
+ .toolbar {
26
+ display: flex;
27
+ align-items: center;
28
+ gap: 10px;
29
+ flex-wrap: wrap;
30
+ background: #fff;
31
+ border: 1px solid #e0e0e0;
32
+ border-radius: 8px;
33
+ padding: 8px 12px;
34
+ }
35
+
36
+ .toolbar-label {
37
+ font-size: 11px;
38
+ color: #999;
39
+ text-transform: uppercase;
40
+ letter-spacing: 0.04em;
41
+ white-space: nowrap;
42
+ }
43
+
44
+ .toolbar select {
45
+ padding: 4px 8px;
46
+ font-size: 12px;
47
+ border: 1px solid #d0d0d0;
48
+ border-radius: 6px;
49
+ background: #fff;
50
+ cursor: pointer;
51
+ outline: none;
52
+ color: #333;
53
+ }
54
+
55
+ .toolbar select:focus {
56
+ border-color: #1a73e8;
57
+ }
58
+
59
+ .toolbar-sep {
60
+ width: 1px;
61
+ height: 18px;
62
+ background: #e0e0e0;
63
+ flex-shrink: 0;
64
+ }
65
+
66
+ .toolbar-btn {
67
+ padding: 4px 12px;
68
+ font-size: 12px;
69
+ border: 1px solid #d0d0d0;
70
+ border-radius: 6px;
71
+ background: #fff;
72
+ cursor: pointer;
73
+ color: #333;
74
+ transition: background 0.1s, border-color 0.1s;
75
+ white-space: nowrap;
76
+ }
77
+
78
+ .toolbar-btn:hover:not(:disabled) {
79
+ background: #f0f0f0;
80
+ border-color: #bbb;
81
+ }
82
+
83
+ .toolbar-btn:disabled {
84
+ opacity: 0.45;
85
+ cursor: default;
86
+ }
87
+
88
+ .toolbar-stat {
89
+ margin-left: auto;
90
+ font-size: 11px;
91
+ color: #aaa;
92
+ white-space: nowrap;
93
+ }
94
+
95
+ /* ── Cache zone ──────────────────────────────────────────────────────────── */
96
+
97
+ .cache-zone {
98
+ background: #fff;
99
+ border: 1px solid #e0e0e0;
100
+ border-radius: 8px;
101
+ padding: 8px 12px;
102
+ margin-bottom: 8px;
103
+ flex-shrink: 0;
104
+ }
105
+
106
+ .cache-zone-header {
107
+ display: flex;
108
+ align-items: center;
109
+ gap: 10px;
110
+ margin-bottom: 6px;
111
+ }
112
+
113
+ .cache-zone-label {
114
+ font-size: 11px;
115
+ font-weight: 600;
116
+ color: #999;
117
+ text-transform: uppercase;
118
+ letter-spacing: 0.04em;
119
+ white-space: nowrap;
120
+ }
121
+
122
+ /* Метр заполненности кэша */
123
+ .cache-meter-wrap {
124
+ display: flex;
125
+ align-items: center;
126
+ gap: 8px;
127
+ flex: 1;
128
+ min-width: 0;
129
+ }
130
+
131
+ .cache-meter-bar {
132
+ flex: 1;
133
+ height: 4px;
134
+ background: #f0f0f0;
135
+ border-radius: 2px;
136
+ overflow: hidden;
137
+ min-width: 60px;
138
+ }
139
+
140
+ .cache-meter-fill {
141
+ height: 100%;
142
+ border-radius: 2px;
143
+ transition: width 0.35s ease, background 0.35s;
144
+ }
145
+
146
+ .cache-meter-fill.ok { background: #1a9e5c; }
147
+ .cache-meter-fill.warn { background: #e67e22; }
148
+ .cache-meter-fill.danger { background: #e53935; }
149
+
150
+ .cache-meter-label {
151
+ font-size: 11px;
152
+ white-space: nowrap;
153
+ color: #bbb;
154
+ min-width: 120px;
155
+ }
156
+
157
+ .cache-meter-label.ok { color: #1a9e5c; }
158
+ .cache-meter-label.warn { color: #e67e22; }
159
+ .cache-meter-label.danger { color: #e53935; }
160
+
161
+ /* Статус кэша */
162
+ .cache-status {
163
+ font-size: 11px;
164
+ white-space: nowrap;
165
+ }
166
+
167
+ .cache-status.fresh { color: #1a9e5c; }
168
+ .cache-status.stale { color: #e67e22; font-weight: 500; }
169
+ .cache-status.empty { color: #ccc; }
170
+
171
+ /* Кнопка «Обновить кэш» — подсвечивается когда кэш stale */
172
+ .cache-refresh-btn--stale {
173
+ border-color: #1a73e8 !important;
174
+ color: #1a73e8 !important;
175
+ }
176
+
177
+ /* Fullscreen overlay при обновлении кэша */
178
+ #cache-fullscreen-loader {
179
+ position: fixed;
180
+ inset: 0;
181
+ background: rgba(255, 255, 255, 0.55);
182
+ display: flex;
183
+ align-items: center;
184
+ justify-content: center;
185
+ font-size: 15px;
186
+ color: #999;
187
+ z-index: 500;
188
+ }
189
+
190
+ /* Состояние загрузки кэша — блокируем все чипы */
191
+ .cache-zone--loading .cache-chip {
192
+ pointer-events: none;
193
+ opacity: 0.4;
194
+ }
195
+
196
+ .cache-zone--loading .cache-zone-label,
197
+ .cache-zone--loading .cache-meter-wrap,
198
+ .cache-zone--loading .cache-status {
199
+ opacity: 0.4;
200
+ }
201
+
202
+ /* Кнопка в loading не меняет внешний вид при hover */
203
+ .cache-zone--loading #btn-refresh-cache {
204
+ cursor: wait;
205
+ }
206
+
207
+ /* Чипы измерений */
208
+ .cache-zone-body {
209
+ display: flex;
210
+ flex-wrap: wrap;
211
+ gap: 4px;
212
+ min-height: 28px;
213
+ }
214
+
215
+ .cache-chip {
216
+ display: inline-flex;
217
+ align-items: center;
218
+ padding: 3px 8px;
219
+ background: #fff;
220
+ border: 1px solid #d0d0d0;
221
+ border-radius: 4px;
222
+ font-size: 12px;
223
+ color: #666;
224
+ cursor: pointer;
225
+ user-select: none;
226
+ white-space: nowrap;
227
+ transition: border-color 0.1s, background 0.1s, color 0.1s;
228
+ }
229
+
230
+ .cache-chip:hover {
231
+ border-color: #1a73e8;
232
+ color: #1a73e8;
233
+ }
234
+
235
+ /* В кэше — синий (совпадает с зоной «Строки») */
236
+ .cache-chip.is-cached {
237
+ background: #f0f4ff;
238
+ border-color: #c5d3f7;
239
+ color: #2c4bad;
240
+ }
241
+
242
+ .cache-chip.is-cached:hover {
243
+ border-color: #e53935;
244
+ background: #fff5f5;
245
+ color: #c62828;
246
+ }
247
+
248
+ /* Идёт COUNT-запрос */
249
+ .cache-chip.is-checking {
250
+ background: #fff8e6;
251
+ border-color: #f0a500;
252
+ color: #7a4f00;
253
+ cursor: wait;
254
+ animation: cache-pulse 0.9s ease-in-out infinite;
255
+ }
256
+
257
+ /* Отклонено — превышение лимита */
258
+ .cache-chip.is-rejected {
259
+ background: #fff0f0;
260
+ border-color: #e53935;
261
+ color: #c62828;
262
+ cursor: default;
263
+ animation: cache-shake 0.3s ease-in-out;
264
+ }
265
+
266
+ @keyframes cache-pulse {
267
+ 0%, 100% { opacity: 1; }
268
+ 50% { opacity: 0.45; }
269
+ }
270
+
271
+ @keyframes cache-shake {
272
+ 0%, 100% { transform: translateX(0); }
273
+ 25% { transform: translateX(-5px); }
274
+ 75% { transform: translateX(5px); }
275
+ }
276
+
277
+ /* ── Toast ───────────────────────────────────────────────────────────────── */
278
+
279
+ .cache-toast {
280
+ position: fixed;
281
+ bottom: 24px;
282
+ left: 50%;
283
+ transform: translateX(-50%);
284
+ background: #323232;
285
+ color: #fff;
286
+ font-size: 12px;
287
+ padding: 8px 18px;
288
+ border-radius: 6px;
289
+ box-shadow: 0 4px 16px rgba(0,0,0,0.18);
290
+ opacity: 0;
291
+ pointer-events: none;
292
+ transition: opacity 0.2s;
293
+ z-index: 300;
294
+ white-space: nowrap;
295
+ max-width: calc(100vw - 48px);
296
+ overflow: hidden;
297
+ text-overflow: ellipsis;
298
+ }
299
+
300
+ .cache-toast.visible {
301
+ opacity: 1;
302
+ }
303
+
304
+ /* ── Filter popup ────────────────────────────────────────────────────────── */
305
+
306
+ .fm-popup {
307
+ position: fixed;
308
+ background: #fff;
309
+ border: 1px solid #d0d0d0;
310
+ border-radius: 8px;
311
+ box-shadow: 0 4px 20px rgba(0,0,0,0.12);
312
+ width: 280px;
313
+ max-height: 420px;
314
+ display: flex;
315
+ flex-direction: column;
316
+ z-index: 1000;
317
+ font-size: 13px;
318
+ }
319
+
320
+ .fm-popup-header {
321
+ display: flex;
322
+ align-items: center;
323
+ justify-content: space-between;
324
+ padding: 10px 12px;
325
+ border-bottom: 1px solid #efefef;
326
+ font-weight: 500;
327
+ font-size: 13px;
328
+ flex-shrink: 0;
329
+ }
330
+
331
+ .fm-popup-close {
332
+ background: none;
333
+ border: none;
334
+ cursor: pointer;
335
+ font-size: 18px;
336
+ color: #aaa;
337
+ line-height: 1;
338
+ padding: 0;
339
+ }
340
+
341
+ .fm-popup-close:hover { color: #333; }
342
+
343
+ .fm-search-section {
344
+ padding: 8px 12px;
345
+ border-bottom: 1px solid #efefef;
346
+ flex-shrink: 0;
347
+ }
348
+
349
+ .fm-search-type {
350
+ display: flex;
351
+ gap: 12px;
352
+ margin-bottom: 6px;
353
+ font-size: 12px;
354
+ color: #555;
355
+ }
356
+
357
+ .fm-search-type label {
358
+ display: flex;
359
+ align-items: center;
360
+ gap: 4px;
361
+ cursor: pointer;
362
+ }
363
+
364
+ .fm-search-input {
365
+ width: 100%;
366
+ padding: 5px 8px;
367
+ border: 1px solid #d0d0d0;
368
+ border-radius: 5px;
369
+ font-size: 12px;
370
+ outline: none;
371
+ box-sizing: border-box;
372
+ }
373
+
374
+ .fm-search-input:focus { border-color: #1a73e8; }
375
+
376
+ .fm-checkbox-list {
377
+ flex: 1;
378
+ overflow: hidden;
379
+ display: flex;
380
+ flex-direction: column;
381
+ min-height: 0;
382
+ }
383
+
384
+ .fm-select-all-wrap {
385
+ padding: 5px 12px !important;
386
+ border-bottom: 1px solid #efefef;
387
+ color: #888;
388
+ font-style: italic;
389
+ }
390
+
391
+ .fm-checkbox-scroll {
392
+ flex: 1;
393
+ overflow-y: auto;
394
+ max-height: 200px;
395
+ }
396
+
397
+ .fm-checkbox {
398
+ display: flex;
399
+ align-items: center;
400
+ gap: 6px;
401
+ padding: 4px 12px;
402
+ cursor: pointer;
403
+ font-size: 12px;
404
+ color: #333;
405
+ }
406
+
407
+ .fm-checkbox:hover { background: #f5f9ff; }
408
+ .fm-checkbox input { cursor: pointer; }
409
+
410
+ .fm-no-checkboxes {
411
+ padding: 12px;
412
+ color: #aaa;
413
+ font-size: 12px;
414
+ font-style: italic;
415
+ }
416
+
417
+ .fm-popup-footer {
418
+ display: flex;
419
+ justify-content: space-between;
420
+ padding: 8px 12px;
421
+ border-top: 1px solid #efefef;
422
+ gap: 8px;
423
+ flex-shrink: 0;
424
+ }
425
+
426
+ .fm-btn {
427
+ padding: 5px 14px;
428
+ border-radius: 5px;
429
+ font-size: 12px;
430
+ cursor: pointer;
431
+ border: 1px solid #d0d0d0;
432
+ background: #fff;
433
+ color: #333;
434
+ }
435
+
436
+ .fm-btn:hover { background: #f0f0f0; }
437
+
438
+ .fm-btn-primary {
439
+ background: #1a73e8;
440
+ border-color: #1a73e8;
441
+ color: #fff;
442
+ }
443
+
444
+ .fm-btn-primary:hover { background: #1558b0; }
445
+
446
+ /* ── Pivot container ─────────────────────────────────────────────────────── */
447
+
448
+ #pivot-container {
449
+ /* transition: margin-bottom 0.2s; */
450
+
451
+ flex: 1;
452
+ min-height: 200px;
453
+ overflow: hidden;
454
+ }
455
+
456
+ /* ── Drillthrough panel ──────────────────────────────────────────────────── */
457
+
458
+ .dt-panel {
459
+ display: none;
460
+ position: fixed;
461
+ bottom: 0;
462
+ left: 0;
463
+ right: 0;
464
+ height: 300px;
465
+ background: #fff;
466
+ border-top: 1px solid #d0d0d0;
467
+ box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.08);
468
+ z-index: 100;
469
+ flex-direction: column;
470
+ }
471
+
472
+ .dt-panel.visible {
473
+ display: flex;
474
+ }
475
+
476
+ .dt-header {
477
+ display: flex;
478
+ align-items: center;
479
+ gap: 8px;
480
+ padding: 8px 16px;
481
+ background: #fafafa;
482
+ border-bottom: 1px solid #e8e8e8;
483
+ flex-shrink: 0;
484
+ }
485
+
486
+ .dt-header-label {
487
+ font-size: 11px;
488
+ color: #aaa;
489
+ text-transform: uppercase;
490
+ letter-spacing: 0.05em;
491
+ }
492
+
493
+ .dt-header-context {
494
+ font-size: 13px;
495
+ font-weight: 500;
496
+ color: #1a1a1a;
497
+ }
498
+
499
+ .dt-header-value {
500
+ font-size: 13px;
501
+ color: #1a73e8;
502
+ font-family: 'SF Mono', 'Fira Code', monospace;
503
+ }
504
+
505
+ .dt-header-close {
506
+ margin-left: auto;
507
+ background: none;
508
+ border: none;
509
+ cursor: pointer;
510
+ font-size: 20px;
511
+ line-height: 1;
512
+ color: #aaa;
513
+ padding: 0 2px;
514
+ transition: color 0.1s;
515
+ }
516
+
517
+ .dt-header-close:hover {
518
+ color: #333;
519
+ }
520
+
521
+ .dt-filters {
522
+ display: flex;
523
+ align-items: center;
524
+ gap: 6px;
525
+ flex-wrap: wrap;
526
+ padding: 6px 16px;
527
+ background: #fafafa;
528
+ border-bottom: 1px solid #efefef;
529
+ flex-shrink: 0;
530
+ }
531
+
532
+ .dt-filter-tag {
533
+ display: inline-flex;
534
+ align-items: center;
535
+ gap: 4px;
536
+ padding: 2px 10px;
537
+ background: #e8f0fe;
538
+ color: #1a73e8;
539
+ font-size: 12px;
540
+ border-radius: 10px;
541
+ }
542
+
543
+ .dt-filter-tag .tag-key {
544
+ color: #5f8dd3;
545
+ }
546
+
547
+ .dt-body {
548
+ flex: 1;
549
+ overflow: auto;
550
+ }
551
+
552
+ .dt-table {
553
+ width: 100%;
554
+ border-collapse: collapse;
555
+ font-size: 12px;
556
+ }
557
+
558
+ .dt-table thead th {
559
+ position: sticky;
560
+ top: 0;
561
+ background: #fafafa;
562
+ padding: 6px 12px;
563
+ text-align: left;
564
+ font-size: 11px;
565
+ font-weight: 500;
566
+ color: #888;
567
+ text-transform: uppercase;
568
+ letter-spacing: 0.04em;
569
+ border-bottom: 1px solid #e0e0e0;
570
+ white-space: nowrap;
571
+ }
572
+
573
+ .dt-table thead th.num {
574
+ text-align: right;
575
+ }
576
+
577
+ .dt-table tbody tr:nth-child(even) {
578
+ background: #fafafa;
579
+ }
580
+
581
+ .dt-table tbody tr:hover {
582
+ background: #f0f6ff;
583
+ }
584
+
585
+ .dt-table tbody td {
586
+ padding: 5px 12px;
587
+ color: #333;
588
+ border-bottom: 1px solid #f4f4f4;
589
+ white-space: nowrap;
590
+ }
591
+
592
+ .dt-table tbody td.num {
593
+ text-align: right;
594
+ font-family: 'SF Mono', 'Fira Code', monospace;
595
+ color: #1a1a1a;
596
+ }
597
+
598
+ .dt-footer {
599
+ display: flex;
600
+ align-items: center;
601
+ gap: 20px;
602
+ padding: 6px 16px;
603
+ background: #fafafa;
604
+ border-top: 1px solid #efefef;
605
+ font-size: 12px;
606
+ color: #888;
607
+ flex-shrink: 0;
608
+ }
609
+
610
+ .dt-footer strong {
611
+ color: #1a1a1a;
612
+ font-weight: 500;
613
+ }
614
+
615
+ .dt-footer .dt-warning {
616
+ color: #e67e22;
617
+ }
618
+
619
+ .fz-chip-placeholder {
620
+ display: inline-flex;
621
+ width: 3px;
622
+ height: 24px;
623
+ background: #1a73e8;
624
+ border-radius: 2px;
625
+ margin: 0 2px;
626
+ pointer-events: none;
627
+ }
628
+
629
+ .fz-chip[data-zone="rows"].fz-chip--last {
630
+ background: #1a73e8 !important;
631
+ border-color: #1a73e8 !important;
632
+ color: #fff !important;
633
+ }
634
+
635
+ .fz-chip[data-zone="columns"].fz-chip--last {
636
+ background: #1a6638 !important;
637
+ border-color: #1a6638 !important;
638
+ color: #fff !important;
639
+ }
640
+
641
+ .fz-chip[data-zone="free"].fz-chip--last {
642
+ background: #666 !important;
643
+ border-color: #666 !important;
644
+ color: #fff !important;
645
+ }
646
+
647
+ .toolbar-btn--toggle.is-active {
648
+ background: #e8f0fe;
649
+ border-color: #1a73e8;
650
+ color: #1a73e8;
651
+ }
652
+
653
+ .demo-toggles {
654
+ display: flex;
655
+ gap: 16px;
656
+ font-size: 12px;
657
+ color: #666;
658
+ margin-bottom: 8px;
659
+ }
660
+
661
+ .demo-toggles label {
662
+ display: flex;
663
+ align-items: center;
664
+ gap: 6px;
665
+ cursor: pointer;
666
+ }
667
+
668
+ #pivot-grid {
669
+ flex: 1;
670
+ min-height: 200px;
671
+ overflow: hidden;
672
+ }