@ninebone/datagrid 0.0.18 → 0.0.21

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,1807 @@
1
+
2
+ cell-button {
3
+ --cell-button-border: 1px solid #d1d5db;
4
+ --cell-button-color: #1f2937;
5
+ --cell-button-background: #f3f4f6;
6
+
7
+ --cell-button-hover-border: 1px solid #d1d5db;
8
+ --cell-button-hover-color: #1f2937;
9
+ --cell-button-hover-background: #f3f4f6;
10
+ --cell-button-active-border: 1px solid #d1d5db;
11
+ --cell-button-active-color: #1f2937;
12
+ --cell-button-active-background: #f3f4f6;
13
+
14
+ display: block;
15
+ position: absolute;
16
+ inset: 0; /* top: 0, right: 0, bottom: 0, left: 0 */
17
+ padding: 3px 4px;
18
+
19
+ button {
20
+ width: 100%;
21
+ display: inline-flex;
22
+ align-items: center;
23
+ justify-content: center;
24
+ border-radius: 4px;
25
+ border: var(--cell-button-border);
26
+ color: var(--cell-button-color);
27
+ background: var(--cell-button-background);
28
+ text-overflow: ellipsis;
29
+ white-space: nowrap;
30
+ overflow: hidden;
31
+ }
32
+ button:hover {
33
+ border: var(--cell-button-hover-border);
34
+ color: var(--cell-button-hover-color);
35
+ background: var(--cell-button-hover-background);
36
+ }
37
+ button:active {
38
+ border: var(--cell-button-active-border);
39
+ color: var(--cell-button-active-color);
40
+ background: var(--cell-button-active-background);
41
+ }
42
+ }
43
+
44
+ cell-checkbox {
45
+ display: flex;
46
+ align-items: center;
47
+ width: 100%;
48
+ height: 100%;
49
+
50
+ label {
51
+ display: inline-flex;
52
+ align-items: center;
53
+ user-select: none;
54
+ }
55
+ input[type="checkbox"] {
56
+ margin-left: 4px;
57
+ margin-right: 4px;
58
+ }
59
+ }
60
+
61
+
62
+ .CELL-CHECKBOX {
63
+ cell-checkbox {
64
+ justify-content: center;
65
+ }
66
+ label {
67
+ display: flex;
68
+ }
69
+ input {
70
+ background-color: #ffffff;
71
+ }
72
+ }
73
+ .CELL-CHECKBOX[text-align='left'] {
74
+ cell-checkbox {
75
+ justify-content: flex-start;
76
+ }
77
+ }
78
+ .CELL-CHECKBOX[text-align='center'] {
79
+ cell-checkbox {
80
+ justify-content: center;
81
+ }
82
+ }
83
+ .CELL-CHECKBOX[text-align='right'] {
84
+ cell-checkbox {
85
+ justify-content: flex-end;
86
+ }
87
+ label {
88
+ flex-direction: row-reverse;
89
+ }
90
+ }
91
+
92
+
93
+ cell-combo {
94
+ --cell-combo-button-border-color: #eee;
95
+ --cell-combo-button-bg-color: #f9f9f9;
96
+
97
+ button.btn1 {
98
+ width: calc(100% - 24px);
99
+ border: 1px solid var(--cell-combo-button-border-color);
100
+ border-right: none;
101
+ border-top-left-radius: 3px;
102
+ border-bottom-left-radius: 3px;
103
+ text-align: left;
104
+ background-color: white;
105
+ overflow: hidden;
106
+ text-overflow: ellipsis;
107
+ white-space: nowrap;
108
+ padding: 0 4px;
109
+ color: #000;
110
+ }
111
+ button.btn2 {
112
+ padding: 3px;
113
+ width: 24px;
114
+ border: 1px solid var(--cell-combo-button-border-color);
115
+ border-top-right-radius: 3px;
116
+ border-bottom-right-radius: 3px;
117
+ background-color: var(--cell-combo-button-bg-color);
118
+ display: flex;
119
+ align-items: center;
120
+ justify-content: center;
121
+ color: #333;
122
+ }
123
+ button.btn2:after {
124
+ content: "";
125
+ border-top: 0.3em solid;
126
+ border-right: 0.3em solid transparent;
127
+ border-bottom: 0;
128
+ border-left: 0.3em solid transparent;
129
+ }
130
+ }
131
+
132
+
133
+
134
+ cell-combo-panel {
135
+ z-index: 2;
136
+ position: absolute;
137
+ width: 250px;
138
+ height: 250px;
139
+ border: 1px solid #999;
140
+ background-color: white;
141
+ overflow: hidden;
142
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
143
+ display: none;
144
+ flex-direction: column;
145
+ padding: 0;
146
+ margin: 0;
147
+ resize: both;
148
+
149
+ .head {
150
+ display: none;
151
+ padding: 6px;
152
+ background: #f8f9fa;
153
+ border-bottom: 1px solid #e5e7eb;
154
+
155
+ input[type="text"] {
156
+ width: 100%;
157
+ height: 26px;
158
+ padding: 0 6px;
159
+ border: 1px solid #d1d5db;
160
+ border-radius: 3px;
161
+ }
162
+ }
163
+
164
+ .footer {
165
+ display: none;
166
+ height: 32px;
167
+ background: #f3f4f6;
168
+ border-top: 1px solid #e5e7eb;
169
+ align-items: center;
170
+ padding: 0 8px;
171
+
172
+ label {
173
+ user-select: none;
174
+ }
175
+
176
+ button {
177
+ height: 22px;
178
+ padding: 0 12px;
179
+ background: #2563eb;
180
+ color: white;
181
+ border: none;
182
+ border-radius: 3px;
183
+ }
184
+
185
+ button:hover {
186
+ background: #1d4ed8;
187
+ }
188
+ }
189
+
190
+ nine-table-simple {
191
+ width: 100%;
192
+ flex: 1;
193
+ border: none;
194
+ }
195
+ }
196
+
197
+
198
+
199
+ cell-combo-panel.active {
200
+ display: flex;
201
+ }
202
+
203
+ cell-combo-panel.expand {
204
+ .head {
205
+ display: flex;
206
+ }
207
+ }
208
+
209
+ cell-combo-panel.multi {
210
+ .footer {
211
+ display: flex;
212
+ justify-content: space-between;
213
+ }
214
+ }
215
+
216
+
217
+
218
+ cell-combo-panel.loading {
219
+ nine-table-simple {
220
+ visibility: hidden;
221
+ }
222
+ }
223
+ cell-combo-panel.loading::after {
224
+ content: "";
225
+ position: absolute;
226
+ inset: 0;
227
+ background: rgba(255, 255, 255, 0.3);
228
+ z-index: 10;
229
+ display: flex;
230
+ align-items: center;
231
+ justify-content: center;
232
+ }
233
+ cell-combo-panel.loading::before {
234
+ content: "";
235
+ position: absolute;
236
+ top: 50%;
237
+ left: 50%;
238
+ width: 24px;
239
+ height: 24px;
240
+ margin: -12px 0 0 -12px;
241
+ border: 3px solid #e5e7eb;
242
+ border-top-color: #2563eb;
243
+ border-radius: 50%;
244
+ animation: combo-loading-spin 0.6s linear infinite;
245
+ z-index: 999999911;
246
+ }
247
+ @keyframes combo-loading-spin {
248
+ to {
249
+ transform: rotate(360deg);
250
+ }
251
+ }
252
+
253
+ :host {
254
+ --cell-input-border-color: #eee;
255
+ --cell-input-bg: #fff;
256
+ --cell-input-color: #333;
257
+ --cell-input-readonly-bg: #fdfdfd;
258
+ --cell-input-btn-bg: #f9f9f9;
259
+ }
260
+
261
+ cell-input {
262
+ input {
263
+ position: relative;
264
+ user-select: auto;
265
+ width: 100%;
266
+ border: 1px solid var(--cell-input-border-color);
267
+ padding-left: 4px;
268
+ background: var(--cell-input-bg);
269
+ color: var(--cell-input-color);
270
+ }
271
+
272
+ input:read-only {
273
+ border-color: var(--cell-input-readonly-bg);
274
+ filter: brightness(97%);
275
+ }
276
+ }
277
+
278
+ cell-input-color {
279
+
280
+ input[type=color] {
281
+ width: 100%;
282
+ padding: 0px;
283
+ margin-left: unset;
284
+ border: 1px solid var(--cell-input-border-color);
285
+ border-right: none;
286
+ -webkit-appearance: none;
287
+ -moz-appearance: none;
288
+ appearance: none;
289
+ background-color: transparent;
290
+ }
291
+
292
+ input[type=color]::-webkit-color-swatch {
293
+ border: 0;
294
+ }
295
+
296
+ input[type=color]::-webkit-color-swatch-wrapper {
297
+ padding: 1px;
298
+ }
299
+
300
+ button {
301
+ display: inline-flex;
302
+ width: 24px;
303
+ margin-right: unset;
304
+ border: 1px solid var(--cell-input-border-color);
305
+ background-color: var(--cell-input-btn-bg);
306
+ justify-content: center;
307
+ align-items: center;
308
+ }
309
+
310
+ button:after {
311
+ content: "";
312
+ border-top: 0.3em solid var(--cell-input-color);
313
+ border-right: 0.3em solid transparent;
314
+ border-bottom: 0;
315
+ border-left: 0.3em solid transparent;
316
+ }
317
+
318
+ input[type=color]:hover, button:hover {
319
+ filter: brightness(95%);
320
+ }
321
+ }
322
+
323
+ cell-input-date {
324
+
325
+ input {
326
+ position: relative;
327
+ margin: 0;
328
+ width: 100%;
329
+ padding: 0 4px;
330
+ border: 1px solid var(--cell-input-border-color);
331
+ background: var(--cell-input-bg);
332
+ -webkit-appearance: none;
333
+ -moz-appearance: none;
334
+ appearance: none;
335
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="black" viewBox="0 0 24 24"><path d="M7 10l5 5 5-5z"/></svg>');
336
+ background-repeat: no-repeat;
337
+ background-position: right 4px center;
338
+ background-size: 14px 16px;
339
+ color: var(--cell-input-color);
340
+ }
341
+
342
+ input:hover {
343
+ filter: brightness(95%);
344
+ }
345
+
346
+ input::before {
347
+ content: attr(data-placeholder);
348
+ position: absolute;
349
+ display: flex;
350
+ align-items: center;
351
+ width: calc(100% - 22px);
352
+ height: 100%;
353
+ left: 1px;
354
+ top: 1px;
355
+ pointer-events: none;
356
+ }
357
+
358
+ input.has-value::before, input:focus::before {
359
+ display: none;
360
+ }
361
+
362
+ input:focus {
363
+
364
+ }
365
+ }
366
+
367
+ cell-input-number {
368
+ input.border-left-none {
369
+ border-left: 0;
370
+ border-top-left-radius: 0;
371
+ border-bottom-left-radius: 0;
372
+ }
373
+ input.border-right-none {
374
+ border-right: 0;
375
+ border-top-right-radius: 0;
376
+ border-bottom-right-radius: 0;
377
+ }
378
+
379
+ input {
380
+ position: relative;
381
+ user-select: auto;
382
+ width: 100%;
383
+ border: 1px solid var(--cell-input-border-color);
384
+ background: var(--cell-input-bg);
385
+ color: var(--cell-input-color);
386
+ text-align: right;
387
+ }
388
+
389
+ input:read-only {
390
+ border-color: var(--cell-input-readonly-bg);
391
+ filter: brightness(97%);
392
+ }
393
+ }
394
+ cell-radio {
395
+ height: 100%;
396
+ width: calc(100% - 8px);
397
+ display: flex;
398
+ align-items: center;
399
+ margin-left: 4px;
400
+ margin-right: 4px;
401
+
402
+ div {
403
+ display: flex;
404
+ flex-direction: row;
405
+ }
406
+
407
+ label {
408
+ display: flex;
409
+ align-items: center;
410
+ margin-right: 8px;
411
+ user-select: none;
412
+ }
413
+
414
+ label.disabled {
415
+ pointer-events: none;
416
+ opacity: 0.5;
417
+ }
418
+
419
+ span {
420
+ margin-left: 4px;
421
+ }
422
+ }
423
+
424
+ .CELL-RADIO[text-align='left'] {
425
+ cell-radio {
426
+ justify-content: flex-start;
427
+ }
428
+ }
429
+ .CELL-RADIO[text-align='center'] {
430
+ cell-radio {
431
+ justify-content: center;
432
+ }
433
+ }
434
+ .CELL-RADIO[text-align='right'] {
435
+ cell-radio {
436
+ justify-content: flex-end;
437
+ }
438
+ }
439
+
440
+
441
+
442
+
443
+
444
+ cell-renderer { /* Custom element host layout */
445
+ display: block;
446
+ span.wrapper {
447
+ display: block;
448
+ width: 100%;
449
+ overflow: hidden;
450
+ text-overflow: ellipsis;
451
+ white-space: nowrap; /* 줄바꿈 방지 */
452
+ }
453
+ }
454
+
455
+ .CELL-RENDERER { /* Parent cell hook */
456
+ text-align: left;
457
+ }
458
+ .CELL-RENDERER[text-align="center"] {
459
+ text-align: center;
460
+ }
461
+ .CELL-RENDERER[text-align="right"] {
462
+ text-align: right;
463
+ }
464
+ cell-row-indicator {
465
+ --row-indicator-prefix-size: 0.40rem;
466
+ --row-indicator-suffix-size: 0.55rem;
467
+ --row-indicator-sub-size: 0.40rem;
468
+ --row-indicator-sub-opacity: 0.2;
469
+ --row-indicator-status-size: 0.55rem;
470
+
471
+ display: block;
472
+ position: absolute; /* 💡 셀 전체를 강제로 꽉 채움 */
473
+ top: 0;
474
+ left: 0;
475
+ right: 0;
476
+ bottom: 0;
477
+ user-select: none;
478
+
479
+ .ng-row-main {
480
+ display: flex;
481
+ align-items: center;
482
+ justify-content: center;
483
+ width: 100%;
484
+ height: 100%;
485
+ text-align: center;
486
+ overflow: hidden;
487
+ font-size: 10px;
488
+ }
489
+
490
+ .ng-row-prefix {
491
+ font-weight: normal;
492
+ font-size: var(--row-indicator-prefix-size);
493
+ }
494
+
495
+ .ng-row-suffix {
496
+ font-size: var(--row-indicator-suffix-size);
497
+ }
498
+
499
+ .ng-row-sub {
500
+ position: absolute;
501
+ right: 2px;
502
+ bottom: 1px;
503
+ font-size: var(--row-indicator-sub-size);
504
+ line-height: 1;
505
+ opacity: var(--row-indicator-sub-opacity);
506
+ pointer-events: none;
507
+ }
508
+
509
+ .row-status {
510
+ display: inline-block;
511
+ position: absolute;
512
+ right: 0;
513
+ top: 1px;
514
+ width: 4px;
515
+ height: 4px;
516
+ border-radius: 50%;
517
+ }
518
+ }
519
+
520
+
521
+ cell-row-indicator.is-insert .row-status {
522
+ background-color: #333;
523
+ }
524
+
525
+ cell-row-indicator.is-update .row-status {
526
+ background-color: darkgoldenrod;
527
+ }
528
+
529
+ cell-row-indicator.is-delete .row-status {
530
+ background-color: red;
531
+ }
532
+ :host {
533
+ --cell-selection-bg: rgba(37, 99, 235, 0.08);
534
+ --cell-selection-border-color: #2563eb;
535
+ }
536
+
537
+ tbody {
538
+
539
+ tr.selected {
540
+ cell-row-indicator {
541
+ border-left: 2px solid darkgoldenrod;
542
+ }
543
+
544
+ cell-row-indicator {
545
+ border-left: 2px solid darkgoldenrod;
546
+ }
547
+ }
548
+
549
+ .selected {
550
+ background-color: var(--cell-selection-bg);
551
+ }
552
+
553
+ .selected-start {
554
+ background-color: transparent;
555
+ }
556
+
557
+ .selected-top { border-top: 2px solid var(--cell-selection-border-color); }
558
+ .selected-bottom { border-bottom: 2px solid var(--cell-selection-border-color); }
559
+ .selected-left { border-left: 2px solid var(--cell-selection-border-color); }
560
+ .selected-right { border-right: 2px solid var(--cell-selection-border-color); }
561
+ }
562
+
563
+ nine-table-col-expand {
564
+ position: absolute;
565
+ right: 2px;
566
+ top: 2px;
567
+ width: 12px;
568
+ height: 12px;
569
+ background-repeat: no-repeat;
570
+ background-position: center;
571
+ background-size: contain;
572
+ z-index: 2;
573
+ pointer-events: auto;
574
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="%234b5563" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M6 8a.5.5 0 0 0 .5.5h5.793l-2.147 2.146a.5.5 0 0 0 .708.708l3-3a.5.5 0 0 0 0-.708l-3-3a.5.5 0 0 0-.708.708L12.293 7.5H6.5A.5.5 0 0 0 6 8m-2.5 7a.5.5 0 0 1-.5-.5v-13a.5.5 0 0 1 1 0v13a.5.5 0 0 1-.5.5"/></svg>');
575
+ }
576
+
577
+ nine-table-col-expand.expand {
578
+ right: 2px;
579
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="%234b5563" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M12.5 15a.5.5 0 0 1-.5-.5v-13a.5.5 0 0 1 1 0v13a.5.5 0 0 1-.5.5M10 8a.5.5 0 0 1-.5.5H3.707l2.147 2.146a.5.5 0 0 1-.708.708l-3-3a.5.5 0 0 1 0-.708l3-3a.5.5 0 1 1 .708.708L3.707 7.5H9.5a.5.5 0 0 1 .5.5"/></svg>');
580
+ }
581
+
582
+ nine-table-col-expand.collapsed {
583
+ left: 50%;
584
+ right: auto;
585
+ transform: translate(-50%, 0);
586
+ }
587
+
588
+
589
+ tr.col-indicator-rowgroup {
590
+ th,td {
591
+ padding: 0;
592
+ }
593
+ }
594
+
595
+ .col-indicator-rowgroup.expand {
596
+ height: 20px;
597
+ }
598
+ .col-indicator-rowgroup.collapse {
599
+ height: 2px;
600
+ }
601
+ .col-indicator-rowgroup.expand th {
602
+ background-color: #eee;
603
+ border-right-color: #ccc;
604
+ border-top: 2px solid #666;
605
+ }
606
+ .col-indicator-rowgroup.collapse th {
607
+ background-color: #666;
608
+ border: none;
609
+ }
610
+ .col-indicator-rowgroup.collapse div {
611
+ display: unset;
612
+ }
613
+ .col-indicator-rowgroup.collapse div {
614
+ display: none;
615
+ }
616
+ .ng-col-mover-indi {
617
+ position: absolute;
618
+ width: 2px;
619
+ background-color: #2563eb;
620
+ display: none;
621
+ pointer-events: none;
622
+ z-index: 10020;
623
+ }
624
+
625
+ .ng-col-mover-indi::before {
626
+ content: '';
627
+ position: absolute;
628
+ top: -6px;
629
+ left: -4px;
630
+ width: 0;
631
+ height: 0;
632
+ border-top: 6px solid #2563eb;
633
+ border-left: 5px solid transparent;
634
+ border-right: 5px solid transparent;
635
+ }
636
+
637
+ .ng-col-mover-indi::after {
638
+ content: '';
639
+ position: absolute;
640
+ bottom: -6px;
641
+ left: -4px;
642
+ width: 0;
643
+ height: 0;
644
+ border-bottom: 6px solid #2563eb;
645
+ border-left: 5px solid transparent;
646
+ border-right: 5px solid transparent;
647
+ }
648
+
649
+ .ng-col-mover-grip {
650
+ position: absolute;
651
+ display: none;
652
+ pointer-events: none;
653
+ z-index: 10010;
654
+ background-color: rgba(37, 99, 235, 0.12);
655
+ border: none;
656
+ box-shadow: 0 4px 12px rgba(37, 99, 235, 0.15);
657
+ overflow: hidden;
658
+ backdrop-filter: blur(1px);
659
+ transition: background-color 0.15s ease, border-color 0.15s ease;
660
+
661
+ .grip-header-content {
662
+ position: absolute;
663
+ top: 0;
664
+ left: 0;
665
+ width: 100%;
666
+ z-index: 2;
667
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
668
+ }
669
+
670
+ th, td {
671
+ user-select: none;
672
+ pointer-events: none;
673
+ }
674
+ }
675
+
676
+
677
+ .ng-col-mover-grip.invalid {
678
+ background-color: rgba(239, 68, 68, 0.12);
679
+ box-shadow: 0 4px 12px rgba(239, 68, 68, 0.15);
680
+
681
+ .grip-header-content {
682
+ border-bottom: 2px solid #ef4444;
683
+ }
684
+ }
685
+
686
+
687
+ thead {
688
+ .resizable-edge {
689
+ cursor: col-resize;
690
+ }
691
+ }
692
+
693
+ nine-table-col-resizer-panel {
694
+ --col-resizer-color: #2563eb;
695
+ --col-resizer-bg: rgba(37, 99, 235, 0.12);
696
+ --col-resizer-badge-bg: #1e40af;
697
+ --col-resizer-badge-color: #ffffff;
698
+
699
+ --col-resizer-tooltip-left: 0px;
700
+ --col-resizer-tooltip-width: 0px;
701
+
702
+ display: none;
703
+ position: absolute;
704
+ top: 0;
705
+ left: 0;
706
+ width: 100%;
707
+ height: 100%;
708
+ pointer-events: none;
709
+ z-index: 9999;
710
+
711
+ .resizer-overlay {
712
+ position: absolute;
713
+ top: 0;
714
+ left: var(--col-resizer-tooltip-left, 0px);
715
+ width: var(--col-resizer-tooltip-width, 0px);
716
+ height: 100%;
717
+ background-color: var(--col-resizer-bg);
718
+ border-left: 1px dashed var(--col-resizer-color);
719
+ border-right: 2px solid var(--col-resizer-color);
720
+ display: flex;
721
+ align-items: flex-start;
722
+ justify-content: center;
723
+ padding-top: 8px;
724
+ pointer-events: none;
725
+ opacity: 1;
726
+ transition: opacity 0.15s ease-out;
727
+
728
+ .size-badge {
729
+ padding: 2px 8px;
730
+ font-size: 11px;
731
+ font-weight: 700;
732
+ color: var(--col-resizer-badge-color);
733
+ background-color: var(--col-resizer-badge-bg);
734
+ border-radius: 4px;
735
+ line-height: 14px;
736
+ white-space: nowrap;
737
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
738
+ }
739
+ }
740
+
741
+ .resizer-overlay.fade-out {
742
+ opacity: 0;
743
+ }
744
+ }
745
+
746
+ nine-table-col-resizer-panel.active {
747
+ display: block;
748
+ }
749
+
750
+
751
+ nine-table-filter-button {
752
+ position: absolute;
753
+ bottom: 2px;
754
+ right: 2px;
755
+ width: 12px;
756
+ height: 12px;
757
+ z-index: 2;
758
+ cursor: pointer;
759
+ background-repeat: no-repeat;
760
+ background-position: center;
761
+ background-size: contain;
762
+ display: inline-block;
763
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 16 16"><path fill="%239ca3af" d="M1.5 1.5A.5.5 0 0 1 2 1h12a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.128.334L10 8.692V13.5a.5.5 0 0 1-.342.474l-3 1A.5.5 0 0 1 6 14.5V8.692L1.628 3.834A.5.5 0 0 1 1.5 3.5zm1 .5v1.308l4.372 4.858A.5.5 0 0 1 7 8.5v5.306l2-.666V8.5a.5.5 0 0 1 .128-.334L13.5 3.308V2z"/></svg>');
764
+ }
765
+
766
+ nine-table-filter-button.filtered {
767
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 16 16"><path fill="%232563eb" d="M1.5 1.5A.5.5 0 0 1 2 1h12a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.128.334L10 8.692V13.5a.5.5 0 0 1-.342.474l-3 1A.5.5 0 0 1 6 14.5V8.692L1.628 3.834A.5.5 0 0 1 1.5 3.5z"/></svg>');
768
+ }
769
+
770
+
771
+ nine-table-filter-panel {
772
+ z-index: 2;
773
+ position: absolute;
774
+ width: 250px;
775
+ height: 250px;
776
+ border: 1px solid #999;
777
+ background-color: white;
778
+ overflow: hidden;
779
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
780
+ display: none;
781
+ flex-direction: column;
782
+ padding: 0;
783
+ margin: 0;
784
+ font-size: 12px;
785
+ resize: both;
786
+
787
+ nine-table-simple {
788
+ width: 100%;
789
+ flex: 1;
790
+ border: none;
791
+ }
792
+
793
+ .search-box {
794
+ width: 100%;
795
+ height: 28px;
796
+ box-sizing: border-box;
797
+ padding: 0px 8px;
798
+ border: none;
799
+ border-bottom: 1px solid #e5e7eb;
800
+ border-radius: 0px;
801
+ outline: none;
802
+ font-size: 12px;
803
+ background: #fafafa;
804
+ color: #333;
805
+ }
806
+ .search-box:focus {
807
+ background: #ffffff;
808
+ }
809
+ .footer-section {
810
+ display: flex;
811
+ flex-direction: column;
812
+ padding: 4px 6px;
813
+ gap: 8px;
814
+ border-top: 1px solid #e5e7eb;
815
+ background: #f9fafb;
816
+ flex-shrink: 0;
817
+ }
818
+ .footer-btns {
819
+ display: flex;
820
+ align-items: center;
821
+ justify-content: space-between;
822
+ gap: 6px;
823
+ }
824
+ .footer-btns label {
825
+ display: flex;
826
+ align-items: center;
827
+ gap: 4px;
828
+ cursor: pointer;
829
+ user-select: none;
830
+ }
831
+ .btn-group {
832
+ display: flex;
833
+ gap: 4px;
834
+ }
835
+ button {
836
+ padding: 4px 14px;
837
+ border-radius: 4px;
838
+ border: 1px solid #d1d5db;
839
+ background: #ffffff;
840
+ cursor: pointer;
841
+ font-size: 11px;
842
+ }
843
+ button:hover {
844
+ background: #f3f4f6;
845
+ }
846
+ button#btnOk {
847
+ background: #2563eb;
848
+ color: white;
849
+ border: none;
850
+ }
851
+ }
852
+ nine-table-filter-panel.active {
853
+ display: flex;
854
+ }
855
+
856
+ nine-table-filter-panel.loading {
857
+ nine-table-simple {
858
+ visibility: hidden;
859
+ }
860
+ }
861
+ nine-table-filter-panel.loading::after {
862
+ content: "";
863
+ position: absolute;
864
+ inset: 0;
865
+ background: rgba(255, 255, 255, 0.3);
866
+ z-index: 10;
867
+ display: flex;
868
+ align-items: center;
869
+ justify-content: center;
870
+ }
871
+ nine-table-filter-panel.loading::before {
872
+ content: "";
873
+ position: absolute;
874
+ top: 50%;
875
+ left: 50%;
876
+ width: 24px;
877
+ height: 24px;
878
+ margin: -12px 0 0 -12px;
879
+ border: 3px solid #e5e7eb;
880
+ border-top-color: #2563eb;
881
+ border-radius: 50%;
882
+ animation: filter-loading-spin 0.6s linear infinite;
883
+ z-index: 999999911;
884
+ }
885
+
886
+ @keyframes filter-loading-spin {
887
+ to {
888
+ transform: rotate(360deg);
889
+ }
890
+ }
891
+ :host {
892
+ width: 100%;
893
+ height: 100%;
894
+ }
895
+
896
+
897
+ :host {
898
+ display: flex;
899
+ flex-direction: column;
900
+ position: relative;
901
+ overflow: hidden;
902
+
903
+ background: #fff;
904
+ }
905
+
906
+
907
+ :host([theme="simple"]) {
908
+ /* 1. 불필요한 패널 및 컴포넌트 숨기기 */
909
+ .ng-part-header, .ng-part-footer,
910
+ nine-table-toolbar,
911
+ nine-table-sheets-footer,
912
+ nine-table-vscrollbar,
913
+ nine-table-hscrollbar,
914
+ nine-table-sheet .ng-scroll-edge {
915
+ display: none;
916
+ }
917
+
918
+ .col-indicator-rowgroup {
919
+ display: none;
920
+ }
921
+
922
+ tr {
923
+ height: 32px;
924
+ }
925
+
926
+ nine-table-sheet {
927
+ border: none;
928
+ overflow: hidden;
929
+ grid-template-columns: 1fr;
930
+ grid-template-rows: 1fr;
931
+ }
932
+
933
+ nine-table-sheet tr th,
934
+ nine-table-sheet tr td {
935
+ border: none;
936
+ padding: 0 8px;
937
+ }
938
+ }
939
+
940
+ /* 🎯 Toolbar 숨김 제어 */
941
+ :host([theme="simple"]) nine-table-toolbar,
942
+ :host([show-header="false"]) nine-table-toolbar {
943
+ display: none;
944
+ }
945
+
946
+ /* 🎯 Footer(StatusBar) 숨김 제어 (show-statusbar="false") */
947
+ :host([theme="simple"]) nine-table-sheets-footer,
948
+ :host([show-footer="false"]) nine-table-sheets-footer,
949
+ :host([show-statusbar="false"]) nine-table-sheets-footer {
950
+ display: none;
951
+ }
952
+
953
+ :host([theme="simple"]) {
954
+ col[data-col="0"], th[data-col="0"], td[data-col="0"] {
955
+ display: none;
956
+ }
957
+ .ng-container-right {
958
+ display: none;
959
+ }
960
+ tr {
961
+ height: 26px;
962
+ }
963
+ }
964
+
965
+
966
+ :host([theme="simple"]),
967
+ :host([auto-height="true"]),
968
+ :host([scroll-bar="none"]) {
969
+
970
+ nine-table-vscrollbar
971
+ nine-table-hscrollbar,
972
+ nine-table-sheet .ng-scroll-edge {
973
+ display: none;
974
+ }
975
+ nine-table-sheet {
976
+ --hscrollbar-height: 0px;
977
+ --vscrollbar-width: 0px;
978
+
979
+ .ng-sheet-body {
980
+ overflow-y: auto;
981
+ overflow-x: auto;
982
+ scrollbar-width: thin;
983
+ scrollbar-color: rgba(0, 0, 0, 0.2) transparent;
984
+ }
985
+
986
+ .ng-sheet-body::-webkit-scrollbar {
987
+ display: block;
988
+ width: 6px;
989
+ height: 6px;
990
+ }
991
+
992
+ .ng-sheet-body::-webkit-scrollbar-track {
993
+ background: transparent;
994
+ }
995
+
996
+ .ng-sheet-body::-webkit-scrollbar-thumb {
997
+ background: rgba(0, 0, 0, 0.15);
998
+ border-radius: 3px;
999
+ }
1000
+
1001
+ .ng-sheet-body::-webkit-scrollbar-thumb:hover {
1002
+ background: rgba(0, 0, 0, 0.3);
1003
+ }
1004
+ }
1005
+ }
1006
+
1007
+
1008
+ :host(.loading) {
1009
+ .ng-loading-bar {
1010
+ display: block;
1011
+ }
1012
+ }
1013
+
1014
+
1015
+ .ng-loading-bar {
1016
+ position: absolute;
1017
+ top: 0;
1018
+ left: 0;
1019
+ right: 0;
1020
+ height: 2px;
1021
+ background: rgba(255, 255, 255, 0.08); /* 은은한 화이트 트랙 배경 */
1022
+ z-index: 10000;
1023
+ display: none;
1024
+ overflow: hidden;
1025
+ }
1026
+
1027
+ /* 🎯 아주 좁고 쨍한 빛 조각 형태로 압축 */
1028
+ .ng-loading-bar::after {
1029
+ content: '';
1030
+ position: absolute;
1031
+ top: 0;
1032
+ left: 0;
1033
+ bottom: 0;
1034
+ width: 12%; /* 바의 전체 길이를 12%로 대폭 축소 */
1035
+ background: linear-gradient(
1036
+ 90deg,
1037
+ transparent 0%,
1038
+ rgba(255, 255, 255, 0.4) 20%,
1039
+ #ffffff 50%,
1040
+ rgba(255, 255, 255, 0.4) 80%,
1041
+ transparent 100%
1042
+ );
1043
+ box-shadow: 0 0 10px rgba(255, 255, 255, 0.9);
1044
+ animation: ng-loading-slide 0.9s ease-in-out infinite;
1045
+ }
1046
+
1047
+ @keyframes ng-loading-slide {
1048
+ 0% {
1049
+ transform: translateX(-150%);
1050
+ }
1051
+ 100% {
1052
+ transform: translateX(850%); /* 폭이 좁아진 만큼 이동 거리 확장 */
1053
+ }
1054
+ }
1055
+
1056
+ input[type="checkbox"] {
1057
+ appearance: none;
1058
+ -webkit-appearance: none;
1059
+ width: 14px;
1060
+ height: 14px;
1061
+ background-color: #ffffff; /* 미체크 시 배경 */
1062
+ border: 1px solid #9ca3af;
1063
+ border-radius: 3px;
1064
+ margin: 0;
1065
+ display: inline-flex;
1066
+ align-items: center;
1067
+ justify-content: center;
1068
+ transition: background-color 0.15s ease, border-color 0.15s ease;
1069
+ }
1070
+ input[type="checkbox"]:checked {
1071
+ background-color: #2563eb; /* 체크 시 파란색 배경 */
1072
+ border-color: #2563eb;
1073
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>');
1074
+ background-repeat: no-repeat;
1075
+ background-position: center;
1076
+ }
1077
+
1078
+ input[type="radio"] {
1079
+ appearance: none;
1080
+ -webkit-appearance: none;
1081
+ width: 14px;
1082
+ height: 14px;
1083
+ background-color: #ffffff;
1084
+ border: 1px solid #9ca3af;
1085
+ border-radius: 50%;
1086
+ margin: 0;
1087
+ display: inline-flex;
1088
+ align-items: center;
1089
+ justify-content: center;
1090
+ }
1091
+
1092
+ input[type="radio"]:checked {
1093
+ background-image: url('data:image/svg+xml;utf8,<svg height="14" width="14" xmlns="http://www.w3.org/2000/svg"><circle r="3.5" cx="50%" cy="50%" fill="%232563eb" /></svg>');
1094
+ background-repeat: no-repeat;
1095
+ background-position: center;
1096
+ }
1097
+ * {
1098
+ outline: none;
1099
+ box-sizing: border-box;
1100
+ cursor: default;
1101
+ font-size: 12px;
1102
+ }
1103
+
1104
+ nine-table-body { display: flex; flex-direction: row; flex: 1; overflow: hidden; position: relative; }
1105
+ nine-table-summary { display: none; width: 250px; flex-shrink: 0; border-right: 1px solid #e5e7eb; }
1106
+ nine-table-analysis { display: none; }
1107
+ nine-table-footer { display: none; }
1108
+
1109
+ nine-table-sheets {
1110
+ flex: 1;
1111
+ display: flex;
1112
+ flex-direction: column;
1113
+ overflow: hidden;
1114
+ position: relative;
1115
+ background: #fff;
1116
+
1117
+ nine-table-sheets-body {
1118
+ flex: 1;
1119
+ overflow: hidden;
1120
+ position: relative;
1121
+ display: flex;
1122
+ flex-direction: row;
1123
+ }
1124
+ }
1125
+
1126
+ cell-input, cell-input-number, cell-button, cell-input-color, cell-input-date, cell-combo {
1127
+ position: absolute;
1128
+ inset: 0;
1129
+ padding: 2px 4px;
1130
+ display: flex;
1131
+
1132
+ input, button {
1133
+ height: 100%;
1134
+ }
1135
+ }
1136
+
1137
+
1138
+ .empty-value {
1139
+ color: #999;
1140
+ }
1141
+
1142
+
1143
+ nine-table-menu-panel {
1144
+ .menu-wrapper {
1145
+ background: #ffffff;
1146
+ border: 1px solid #d1d5db;
1147
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
1148
+ border-radius: 4px;
1149
+ padding: 4px 0;
1150
+ min-width: 150px;
1151
+ }
1152
+
1153
+ ul {
1154
+ list-style: none;
1155
+ margin: 0;
1156
+ padding: 0;
1157
+ }
1158
+
1159
+ li {
1160
+ position: relative;
1161
+ padding: 6px 16px;
1162
+ color: #374151;
1163
+ display: flex;
1164
+ align-items: center;
1165
+ justify-content: space-between;
1166
+ }
1167
+
1168
+ li:hover {
1169
+ background-color: #f3f4f6;
1170
+ color: #111827;
1171
+ }
1172
+
1173
+ li.on::before {
1174
+ content: '✓';
1175
+ position: absolute;
1176
+ left: 4px;
1177
+ font-weight: bold;
1178
+ }
1179
+
1180
+ li.disabled {
1181
+ opacity: 0.5;
1182
+ cursor: not-allowed;
1183
+ background: transparent !important;
1184
+ }
1185
+
1186
+ li.ng-menu-separator {
1187
+ height: 1px;
1188
+ background: #e5e7eb;
1189
+ margin: 4px 0;
1190
+ padding: 0;
1191
+ }
1192
+
1193
+ li.submenu::after {
1194
+ content: '▶';
1195
+ font-size: 9px;
1196
+ margin-left: 8px;
1197
+ color: #9ca3af;
1198
+ }
1199
+
1200
+ .ng-menu-sublist {
1201
+ display: none;
1202
+ position: absolute;
1203
+ top: -4px;
1204
+ left: 100%;
1205
+ background: #ffffff;
1206
+ border: 1px solid #d1d5db;
1207
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
1208
+ border-radius: 4px;
1209
+ padding: 4px 0;
1210
+ min-width: 140px;
1211
+ }
1212
+
1213
+ li.submenu:hover > .ng-menu-sublist {
1214
+ display: block;
1215
+ }
1216
+ }
1217
+ :host {
1218
+ --hscrollbar-height: 16px;
1219
+ --vscrollbar-width: 16px;
1220
+ }
1221
+
1222
+ .scroll-edge {
1223
+ display: none; /* 평소에는 기본 숨김 */
1224
+ grid-row: 2;
1225
+ grid-column: 2;
1226
+ width: var(--vscrollbar-width);
1227
+ height: var(--hscrollbar-height);
1228
+ background: #f3f4f6;
1229
+ border-top: 1px solid #e5e7eb;
1230
+ z-index: 10;
1231
+ }
1232
+
1233
+ nine-table-hscrollbar {
1234
+
1235
+ --hscrollbar-background: #f9fafb;
1236
+ --hscrollbar-border-top: 1px solid #e5e7eb;
1237
+ --hscrollbar-button-background: #f3f4f6;
1238
+ --hscrollbar-track-background: #f3f4f6;
1239
+ --hscrollbar-thumb-background: #9ca3af;
1240
+ --hscrollbar-thumb-hover-background: #6b7280;
1241
+
1242
+ display: none;
1243
+ grid-row: 2;
1244
+ grid-column: 1;
1245
+ flex-direction: row;
1246
+ height: var(--hscrollbar-height);
1247
+ min-height: var(--hscrollbar-height);
1248
+ background: var(--hscrollbar-background);
1249
+ border-top: var(--hscrollbar-border-top);
1250
+ z-index: 10;
1251
+ overflow: hidden;
1252
+ width: 100%;
1253
+ user-select: none;
1254
+ position: relative;
1255
+
1256
+ button {
1257
+ width: var(--hscrollbar-height);
1258
+ height: 100%;
1259
+ background: var(--hscrollbar-button-background);
1260
+ border: none;
1261
+ display: flex;
1262
+ align-items: center;
1263
+ justify-content: center;
1264
+ padding: 0;
1265
+ flex-shrink: 0;
1266
+ z-index: 2;
1267
+ }
1268
+ button:disabled {
1269
+ opacity: 0.4;
1270
+ }
1271
+
1272
+ .scroll-icon {
1273
+ width: 100%;
1274
+ height: 100%;
1275
+ background-repeat: no-repeat;
1276
+ background-position: center;
1277
+ }
1278
+
1279
+ .scroll-left .scroll-icon {
1280
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 16 16"><path fill="none" stroke="%236b7280" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M10 12L6 8l4-4"/></svg>');
1281
+ }
1282
+
1283
+ .scroll-right .scroll-icon {
1284
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 16 16"><path fill="none" stroke="%236b7280" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M6 4l4 4-4 4"/></svg>');
1285
+ }
1286
+
1287
+ .scroll-track {
1288
+ flex: 1;
1289
+ height: 100%;
1290
+ position: relative;
1291
+ background: var(--hscrollbar-track-background);
1292
+ overflow: hidden;
1293
+ }
1294
+ .scroll-thumb {
1295
+ position: absolute;
1296
+ top: 2px;
1297
+ bottom: 2px;
1298
+ left: 0px;
1299
+ background: var(--hscrollbar-thumb-background);
1300
+ border-radius: 4px;
1301
+ z-index: 1;
1302
+ }
1303
+ .scroll-thumb:hover {
1304
+ background: var(--hscrollbar-thumb-hover-background);
1305
+ }
1306
+ }
1307
+
1308
+ nine-table-vscrollbar {
1309
+
1310
+ --vscrollbar-background: #f9fafb;
1311
+ --vscrollbar-border-top: 2px solid #333;
1312
+ --vscrollbar-button-background: #f3f4f6;
1313
+ --vscrollbar-track-background: #f3f4f6;
1314
+ --vscrollbar-thumb-background: #9ca3af;
1315
+ --vscrollbar-thumb-hover-background: #6b7280;
1316
+
1317
+ display: none;
1318
+ border-top: var(--vscrollbar-border-top);
1319
+ grid-row: 1;
1320
+ grid-column: 2;
1321
+ width: var(--vscrollbar-width);
1322
+ height: 100%;
1323
+ z-index: 50;
1324
+ flex-direction: column;
1325
+ background: var(--vscrollbar-background);
1326
+ user-select: none;
1327
+ position: relative;
1328
+
1329
+ button {
1330
+ height: var(--vscrollbar-width);
1331
+ width: 100%;
1332
+ background: var(--vscrollbar-button-background);
1333
+ border: none;
1334
+ display: flex;
1335
+ align-items: center;
1336
+ justify-content: center;
1337
+ padding: 0;
1338
+ flex-shrink: 0;
1339
+ z-index: 2;
1340
+ }
1341
+ button:disabled {
1342
+ opacity: 0.4;
1343
+ }
1344
+
1345
+ .scroll-icon {
1346
+ width: 100%;
1347
+ height: 100%;
1348
+ background-repeat: no-repeat;
1349
+ background-position: center;
1350
+ }
1351
+
1352
+ .scroll-top .scroll-icon {
1353
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 16 16"><path fill="none" stroke="%236b7280" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M4 10l4-4 4 4"/></svg>');
1354
+ }
1355
+
1356
+ .scroll-bottom .scroll-icon {
1357
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 16 16"><path fill="none" stroke="%236b7280" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M4 6l4 4 4-4"/></svg>');
1358
+ }
1359
+
1360
+ .scroll-track {
1361
+ flex: 1;
1362
+ width: 100%;
1363
+ position: relative;
1364
+ background: var(--vscrollbar-track-background);
1365
+ overflow: hidden;
1366
+ }
1367
+ .scroll-thumb {
1368
+ position: absolute;
1369
+ left: 2px;
1370
+ right: 2px;
1371
+ top: 0px;
1372
+ height: 30px;
1373
+ background: var(--vscrollbar-thumb-background);
1374
+ border-radius: 4px;
1375
+ z-index: 1;
1376
+ }
1377
+ .scroll-thumb:hover {
1378
+ background: var(--vscrollbar-thumb-hover-background);
1379
+ }
1380
+ }
1381
+
1382
+
1383
+ /* --- 세로 스크롤바가 활성화되었을 때만 CSS로 2열 너비 확장 및 요소 표시 --- */
1384
+ nine-table-sheet.vscroll-visible {
1385
+ grid-template-columns: 1fr var(--vscrollbar-width);
1386
+
1387
+ nine-table-vscrollbar {
1388
+ display: flex;
1389
+ }
1390
+ }
1391
+
1392
+ /* --- 가로 스크롤바가 활성화되었을 때만 CSS로 행 높이 확장 및 요소 표시 --- */
1393
+ nine-table-sheet.hscroll-visible {
1394
+ grid-template-rows: 1fr var(--hscrollbar-height);
1395
+
1396
+ nine-table-hscrollbar, .scroll-edge {
1397
+ display: flex;
1398
+ }
1399
+ }
1400
+
1401
+ @media (hover: none) and (pointer: coarse) {
1402
+
1403
+ nine-table-sheet.vscroll-visible {
1404
+ grid-template-columns: 1fr;
1405
+ nine-table-vscrollbar {
1406
+ display: none;
1407
+ }
1408
+ }
1409
+ nine-table-sheet.hscroll-visible {
1410
+ grid-template-rows: 1fr;
1411
+
1412
+ nine-table-hscrollbar, .scroll-edge {
1413
+ display: none;
1414
+ }
1415
+ }
1416
+
1417
+ /* Hide custom scrollbar elements on touch-based mobile devices */
1418
+ nine-table-vscrollbar,
1419
+ nine-table-hscrollbar,
1420
+ .scroll-edge {
1421
+ display: none;
1422
+ }
1423
+
1424
+ /* Optional: Hide native scrollbars visually while maintaining smooth touch/momentum scrolling */
1425
+ .ng-sheet-body {
1426
+ scrollbar-width: none; /* Firefox */
1427
+ -ms-overflow-style: none; /* IE/Edge */
1428
+ }
1429
+ .ng-sheet-body::-webkit-scrollbar {
1430
+ display: none; /* Chrome/Safari/Opera */
1431
+ }
1432
+ }
1433
+
1434
+
1435
+ nine-table-sheet {
1436
+ --sheet-bg: #ffffff;
1437
+ --sheet-nodata-color: #9ca3af;
1438
+ --sheet-fixed-brightness: 99%;
1439
+
1440
+ display: none;
1441
+ grid-template-columns: 1fr 0;
1442
+ grid-template-rows: 1fr 0;
1443
+ width: 100%;
1444
+ height: 100%;
1445
+ position: relative;
1446
+ background: var(--sheet-bg);
1447
+ overflow: hidden;
1448
+
1449
+ .ng-sheet-body {
1450
+ display: block;
1451
+ flex: 1 1 auto;
1452
+ width: 100%;
1453
+ height: 100%;
1454
+ overflow-y: auto;
1455
+ overflow-x: hidden;
1456
+ position: relative;
1457
+ scrollbar-width: none;
1458
+ &::-webkit-scrollbar { display: none; height: 0px; width: 0px; }
1459
+ }
1460
+
1461
+ .ng-sheet-body-content {
1462
+ display: flex;
1463
+ flex-direction: row;
1464
+ width: 100%;
1465
+ height: 100%;
1466
+ left: 0;
1467
+ top: 0;
1468
+ position: sticky;
1469
+ }
1470
+
1471
+ .ng-container-left, .ng-container-body, .ng-container-right {
1472
+ flex-direction: column;
1473
+ position: relative;
1474
+ background: var(--sheet-bg);
1475
+ }
1476
+ .ng-container-body {
1477
+ display: flex;
1478
+ }
1479
+ .ng-container-left, .ng-container-right {
1480
+ border: none;
1481
+ flex-shrink: 0;
1482
+ overflow: hidden;
1483
+ filter: brightness(var(--sheet-fixed-brightness));
1484
+ }
1485
+ .ng-container-body {
1486
+ flex: 1;
1487
+ overflow-x: auto;
1488
+ overflow-y: hidden;
1489
+ scrollbar-width: none;
1490
+ &::-webkit-scrollbar { display: none; height: 0px; width: 0px; }
1491
+ }
1492
+
1493
+ .nodata-overlay {
1494
+ display: none;
1495
+ position: absolute;
1496
+ top: 0;
1497
+ left: 0;
1498
+ right: 0;
1499
+ bottom: 0;
1500
+ background: var(--sheet-bg);
1501
+ z-index: 20;
1502
+ align-items: center;
1503
+ justify-content: center;
1504
+ color: var(--sheet-nodata-color);
1505
+ }
1506
+ }
1507
+
1508
+ nine-table-sheet.active {
1509
+ display: grid;
1510
+ }
1511
+
1512
+
1513
+
1514
+
1515
+ nine-table-sheets-footer {
1516
+ display: flex;
1517
+ height: 26px;
1518
+ --background: #f3f4f6;
1519
+ border-top: 1px solid #e5e7eb;
1520
+ align-items: center;
1521
+ justify-content: space-between;
1522
+ padding: 0 8px;
1523
+ flex-shrink: 0;
1524
+
1525
+ .sheets-counter {
1526
+ color: #6b7280;
1527
+ padding-left: 12px;
1528
+ flex-shrink: 0;
1529
+
1530
+ span#row-count {
1531
+ font-weight: 700;
1532
+ }
1533
+ }
1534
+
1535
+
1536
+
1537
+ .nine-tab-bar {
1538
+ display: flex;
1539
+ align-items: flex-start;
1540
+ gap: 2px;
1541
+ overflow-x: auto;
1542
+ flex: 1;
1543
+ height: 100%;
1544
+
1545
+
1546
+
1547
+ nt-sheets-tab-item {
1548
+ padding: 4px 12px;
1549
+ color: #4b5563;
1550
+ background: #f9fafb;
1551
+ border: 1px solid #e5e7eb;
1552
+ border-top: none;
1553
+ border-radius: 0 0 3px 3px;
1554
+ user-select: none;
1555
+ height: 100%;
1556
+ display: flex;
1557
+ align-items: center;
1558
+ }
1559
+
1560
+ nt-sheets-tab-item.active {
1561
+ background: white;
1562
+ color: #111827;
1563
+ font-weight: 600;
1564
+ border-bottom: 2px solid green;
1565
+ }
1566
+ }
1567
+ }
1568
+
1569
+
1570
+
1571
+ .asc::after,
1572
+ .desc::after {
1573
+ z-index: 1;
1574
+ content: "";
1575
+ display: inline-block;
1576
+ width: 10px;
1577
+ height: 10px;
1578
+ position: absolute;
1579
+ left: 50%;
1580
+ top: -2px;
1581
+ transform: translateX(-50%);
1582
+ background-repeat: no-repeat;
1583
+ background-position: center;
1584
+ background-size: contain;
1585
+ }
1586
+
1587
+ .asc::after {
1588
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 16 16"><path fill="%232563eb" d="M8 3L3 11h10L8 3z"/></svg>');
1589
+ }
1590
+
1591
+ .desc::after {
1592
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 16 16"><path fill="%23dc2626" d="M8 13L3 5h10l-5 8z"/></svg>');
1593
+ }
1594
+
1595
+
1596
+ tbody.body td *:first-child, tbody.body th *:first-child {
1597
+ transform: translate(0, 0);
1598
+ transition: transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1.35), opacity 0.4s ease-out;
1599
+ }
1600
+
1601
+ tbody.body .sorting-anim-asc *:first-child {
1602
+ transform: translate(0px, 20px);
1603
+ opacity: 0.2;
1604
+ transition: none;
1605
+ }
1606
+
1607
+ tbody.body .sorting-anim-desc *:first-child {
1608
+ transform: translate(0px, -30px);
1609
+ opacity: 0.2;
1610
+ transition: none;
1611
+ }
1612
+
1613
+ tbody.body .sorting-anim-none *:first-child {
1614
+ transform: translate(0px, 0px);
1615
+ opacity: 0.2;
1616
+ transition: none;
1617
+ }
1618
+ table {
1619
+ --table-th-bg: #f9fafb;
1620
+ --table-th-color: #111827;
1621
+ --table-td-bg: #fff;
1622
+ --table-td-color: #111827;
1623
+ --table-disabled-bg: #f0f0f0;
1624
+ --th-border-left: none;
1625
+ --th-border-top: none;
1626
+ --th-border-right: 1px solid #e5e7eb;
1627
+ --th-border-bottom: 1px solid #e5e7eb;
1628
+ --td-border-left: none;
1629
+ --tD-border-top: none;
1630
+ --td-border-right: 1px solid #e5e7eb;
1631
+ --td-border-bottom: 1px solid #e5e7eb;
1632
+
1633
+
1634
+ border-collapse: separate;
1635
+ border-spacing: 0;
1636
+ width: auto;
1637
+ min-width: 100%;
1638
+ table-layout: fixed;
1639
+ }
1640
+
1641
+ nine-table-sheet[auto-fit-col="true"] table {
1642
+ width: 100%;
1643
+ min-width: 100%;
1644
+ }
1645
+
1646
+ col {
1647
+ width: attr(width px);
1648
+ }
1649
+
1650
+ thead {
1651
+ display: table-header-group;
1652
+ position: sticky;
1653
+ top: 0;
1654
+ z-index: 10;
1655
+ }
1656
+
1657
+ tfoot {
1658
+ display: table-footer-group;
1659
+ position: sticky;
1660
+ bottom: 0;
1661
+ z-index: 10;
1662
+ }
1663
+
1664
+ tbody {
1665
+ position: relative;
1666
+ }
1667
+
1668
+ tbody.foot {
1669
+ height: 100vh;
1670
+ }
1671
+
1672
+ thead tr {
1673
+ height: 48px;
1674
+ }
1675
+ tbody tr {
1676
+ height: 32px;
1677
+ }
1678
+ tfoot tr {
1679
+ height: 32px;
1680
+ }
1681
+
1682
+ tr.hover th, tr.hover td {
1683
+ background-color: rgba(37, 99, 235, 0.06);
1684
+ }
1685
+
1686
+ th, td {
1687
+ overflow: hidden;
1688
+ white-space: nowrap;
1689
+ text-overflow: ellipsis;
1690
+ padding: 0px 4px;
1691
+ border-top: 1px solid transparent;
1692
+ border-left: 1px solid transparent;
1693
+ color: var(--table-td-color);
1694
+ position: relative;
1695
+ }
1696
+
1697
+ th {
1698
+ border-left: var(--th-border-left);
1699
+ border-top: var(--th-border-top);
1700
+ border-right: var(--th-border-right);
1701
+ border-bottom: var(--th-border-bottom);
1702
+ background: var(--table-th-bg);
1703
+ color: var(--table-th-color);
1704
+ font-weight: 600;
1705
+ user-select: none;
1706
+ }
1707
+
1708
+ td {
1709
+ border-left: var(--td-border-left);
1710
+ border-top: var(--td-border-top);
1711
+ border-right: var(--td-border-right);
1712
+ border-bottom: var(--td-border-bottom);
1713
+ background: var(--table-td-bg);
1714
+ color: var(--table-td-color);
1715
+ }
1716
+
1717
+ td.invalid::after {
1718
+ content: "";
1719
+ position: absolute;
1720
+ top: 0;
1721
+ right: 0;
1722
+ width: 0;
1723
+ height: 0;
1724
+ border-top: 2px solid red;
1725
+ border-right: 2px solid red;
1726
+ border-bottom: 2px solid transparent;
1727
+ border-left: 2px solid transparent;
1728
+ z-index: 1;
1729
+ pointer-events: none;
1730
+ }
1731
+
1732
+ td[disabled="true"] {
1733
+ input, button {
1734
+ background: var(--table-disabled-bg);
1735
+ opacity: 0.5;
1736
+ pointer-events: none;
1737
+ }
1738
+ }
1739
+
1740
+ td[text-align="left"] {
1741
+ input {
1742
+ text-align: left;
1743
+ }
1744
+ }
1745
+ td[text-align="right"] {
1746
+ input {
1747
+ text-align: right;
1748
+ }
1749
+ }
1750
+ td[text-align="center"] {
1751
+ input {
1752
+ text-align: center;
1753
+ }
1754
+ }
1755
+
1756
+ nine-table-toolbar {
1757
+ --display: flex;
1758
+ display: none;
1759
+ align-items: center;
1760
+ justify-content: space-between;
1761
+ height: 40px;
1762
+ padding: 0 12px;
1763
+ --border-bottom: 1px solid #e5e7eb;
1764
+ background: #ffffff;
1765
+ user-select: none;
1766
+ flex-shrink: 0;
1767
+
1768
+
1769
+ .ng-toolbar-left {
1770
+ display: flex;
1771
+ align-items: center;
1772
+ gap: 8px;
1773
+ }
1774
+ .ng-toolbar-title {
1775
+ font-size: 13px;
1776
+ font-weight: 600;
1777
+ color: #111827;
1778
+ }
1779
+ .ng-toolbar-menu-btn {
1780
+ display: inline-flex;
1781
+ align-items: center;
1782
+ justify-content: center;
1783
+ background: none;
1784
+ border: none;
1785
+ padding: 4px;
1786
+ border-radius: 4px;
1787
+ }
1788
+ .ng-toolbar-menu-btn:hover {
1789
+ background-color: #f3f4f6;
1790
+ }
1791
+ .ng-toolbar-custom {
1792
+ display: flex;
1793
+ align-items: center;
1794
+ gap: 6px;
1795
+ }
1796
+ }
1797
+
1798
+ :host([theme="simple"]) nine-table-toolbar,
1799
+ :host([show-header="false"]) nine-table-toolbar {
1800
+ display: none;
1801
+
1802
+ .ng-toolbar-menu-btn {
1803
+ display: none;
1804
+ }
1805
+ }
1806
+
1807
+