@coreui/data-grid 0.2.0-rc.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/README.md +4 -2
  2. package/dist/css/data-grid.css +11 -11
  3. package/dist/css/data-grid.css.map +1 -1
  4. package/dist/css/data-grid.min.css +2 -2
  5. package/dist/css/data-grid.min.css.map +1 -1
  6. package/dist/css/data-grid.standalone.css +1066 -0
  7. package/dist/css/data-grid.standalone.css.map +1 -0
  8. package/dist/css/data-grid.standalone.min.css +5 -0
  9. package/dist/css/data-grid.standalone.min.css.map +1 -0
  10. package/dist/js/clipboard.cjs +2 -3
  11. package/dist/js/clipboard.mjs +2 -3
  12. package/dist/js/csv.cjs +5 -6
  13. package/dist/js/csv.cjs.map +1 -1
  14. package/dist/js/csv.mjs +5 -6
  15. package/dist/js/csv.mjs.map +1 -1
  16. package/dist/js/data-grid.esm.js +5685 -5422
  17. package/dist/js/data-grid.esm.js.map +1 -1
  18. package/dist/js/data-grid.esm.min.js +2 -2
  19. package/dist/js/data-grid.esm.min.js.map +1 -1
  20. package/dist/js/data-grid.js +5685 -5423
  21. package/dist/js/data-grid.js.map +1 -1
  22. package/dist/js/data-grid.lite.esm.js +2707 -2629
  23. package/dist/js/data-grid.lite.esm.js.map +1 -1
  24. package/dist/js/data-grid.lite.esm.min.js +2 -2
  25. package/dist/js/data-grid.lite.esm.min.js.map +1 -1
  26. package/dist/js/data-grid.lite.js +2707 -2630
  27. package/dist/js/data-grid.lite.js.map +1 -1
  28. package/dist/js/data-grid.lite.min.js +2 -2
  29. package/dist/js/data-grid.lite.min.js.map +1 -1
  30. package/dist/js/data-grid.lite.mjs +2707 -2629
  31. package/dist/js/data-grid.lite.mjs.map +1 -1
  32. package/dist/js/data-grid.min.js +2 -2
  33. package/dist/js/data-grid.min.js.map +1 -1
  34. package/dist/js/data-grid.mjs +5685 -5422
  35. package/dist/js/data-grid.mjs.map +1 -1
  36. package/dist/js/direction.cjs +25 -0
  37. package/dist/js/direction.cjs.map +1 -0
  38. package/dist/js/direction.mjs +23 -0
  39. package/dist/js/direction.mjs.map +1 -0
  40. package/dist/js/drag.cjs +20 -12
  41. package/dist/js/drag.cjs.map +1 -1
  42. package/dist/js/drag.mjs +20 -12
  43. package/dist/js/drag.mjs.map +1 -1
  44. package/dist/js/{export-table-CNAKStzj.mjs → export-table-BggGRmzQ.mjs} +3 -4
  45. package/dist/js/{export-table-CNAKStzj.mjs.map → export-table-BggGRmzQ.mjs.map} +1 -1
  46. package/dist/js/{export-table-doIwvE5U.cjs → export-table-BiB3_lVo.cjs} +3 -4
  47. package/dist/js/{export-table-doIwvE5U.cjs.map → export-table-BiB3_lVo.cjs.map} +1 -1
  48. package/dist/js/filters.cjs +2 -3
  49. package/dist/js/filters.mjs +2 -3
  50. package/dist/js/labels.cjs +2 -3
  51. package/dist/js/labels.mjs +2 -3
  52. package/dist/js/print.cjs +2 -3
  53. package/dist/js/print.mjs +2 -3
  54. package/dist/js/selector.cjs +22 -0
  55. package/dist/js/selector.cjs.map +1 -0
  56. package/dist/js/selector.mjs +21 -0
  57. package/dist/js/selector.mjs.map +1 -0
  58. package/dist/js/validate.cjs +2 -3
  59. package/dist/js/validate.mjs +2 -3
  60. package/dist/js/xlsx.cjs +5 -7
  61. package/dist/js/xlsx.cjs.map +1 -1
  62. package/dist/js/xlsx.mjs +5 -7
  63. package/dist/js/xlsx.mjs.map +1 -1
  64. package/dist/types/base-component.d.mts +29 -0
  65. package/dist/types/data-grid.d.mts +141 -0
  66. package/dist/types/dom/data.d.mts +15 -0
  67. package/dist/types/dom/event-handler.d.mts +22 -0
  68. package/dist/types/dom/manipulator.d.mts +16 -0
  69. package/dist/types/engine/active-cell.d.mts +33 -0
  70. package/dist/types/engine/active-cell.d.ts +1 -0
  71. package/dist/types/engine/data-source.d.mts +19 -0
  72. package/dist/types/engine/features-lite.d.mts +25 -0
  73. package/dist/types/engine/features.d.mts +35 -0
  74. package/dist/types/engine/scheduler.d.mts +11 -0
  75. package/dist/types/engine/table.d.mts +9 -0
  76. package/dist/types/engine/table.d.ts +1 -1
  77. package/dist/types/engine/validate.d.mts +20 -1
  78. package/dist/types/engine/virtualizer.d.mts +23 -0
  79. package/dist/types/filters.d.mts +13 -1
  80. package/dist/types/icons.d.mts +23 -0
  81. package/dist/types/index-lite.d.mts +19 -1
  82. package/dist/types/index.d.mts +21 -1
  83. package/dist/types/labels.d.mts +9 -1
  84. package/dist/types/types.d.mts +284 -0
  85. package/dist/types/ui/body.d.mts +37 -0
  86. package/dist/types/ui/column-chooser.d.mts +27 -0
  87. package/dist/types/ui/editor.d.mts +8 -0
  88. package/dist/types/ui/filter-menu.d.mts +21 -0
  89. package/dist/types/ui/header.d.mts +51 -0
  90. package/dist/types/ui/loading.d.mts +12 -0
  91. package/dist/types/ui/menu.d.mts +17 -0
  92. package/dist/types/ui/pagination.d.mts +17 -0
  93. package/dist/types/ui/pinning.d.mts +17 -0
  94. package/dist/types/ui/toolbar.d.mts +42 -0
  95. package/dist/types/ui/tooltip.d.mts +10 -0
  96. package/dist/types/util/clipboard.d.mts +29 -1
  97. package/dist/types/util/config.d.mts +28 -0
  98. package/dist/types/util/csv.d.mts +19 -1
  99. package/dist/types/util/debounce.d.mts +7 -0
  100. package/dist/types/util/direction.d.mts +17 -0
  101. package/dist/types/util/direction.d.ts +17 -0
  102. package/dist/types/util/drag.d.mts +48 -1
  103. package/dist/types/util/export-table.d.mts +47 -0
  104. package/dist/types/util/index.d.mts +66 -0
  105. package/dist/types/util/print.d.mts +32 -1
  106. package/dist/types/util/sanitizer.d.mts +15 -0
  107. package/dist/types/util/selector.d.mts +12 -0
  108. package/dist/types/util/selector.d.ts +12 -0
  109. package/dist/types/util/xlsx.d.mts +17 -1
  110. package/dist/types/util/zip.d.mts +11 -0
  111. package/package.json +42 -16
  112. package/scss/_base.scss +13 -0
  113. package/scss/_config.scss +14 -0
  114. package/scss/_functions.scss +1 -0
  115. package/scss/_mixins.scss +1 -0
  116. package/scss/base/_buttons.scss +113 -0
  117. package/scss/base/_forms.scss +157 -0
  118. package/scss/base/_helpers.scss +24 -0
  119. package/scss/base/_pagination.scss +100 -0
  120. package/scss/base/_reboot.scss +93 -0
  121. package/scss/base/_root.scss +85 -0
  122. package/scss/base/_spinner.scss +45 -0
  123. package/scss/base/_table.scss +78 -0
  124. package/scss/components/_data-grid.scss +807 -0
  125. package/scss/data-grid.scss +7 -743
  126. package/scss/data-grid.standalone.scss +16 -0
  127. package/scss/functions/_defaults.scss +25 -0
  128. package/scss/mixins/_tokens.scss +12 -0
  129. package/src/data-grid.ts +22 -6
  130. package/src/engine/active-cell.ts +6 -3
  131. package/src/engine/table.ts +9 -1
  132. package/src/index-lite.ts +1 -1
  133. package/src/index.ts +1 -1
  134. package/src/ui/column-chooser.ts +4 -4
  135. package/src/ui/filter-menu.ts +5 -5
  136. package/src/ui/menu.ts +4 -4
  137. package/src/ui/pagination.ts +1 -1
  138. package/src/ui/tooltip.ts +2 -2
  139. package/src/util/csv.ts +2 -2
  140. package/src/util/direction.ts +38 -0
  141. package/src/util/drag.ts +45 -9
  142. package/src/util/selector.ts +16 -0
  143. package/src/util/xlsx.ts +1 -1
@@ -1,747 +1,11 @@
1
1
  /*!
2
- * CoreUI PRO data-grid.scss v0.2.0
2
+ * CoreUI PRO data-grid.scss v0.4.0
3
3
  * License (https://coreui.io/pro/license/)
4
4
  */
5
5
 
6
- .data-grid {
7
- // The column menu is positioned against the grid root (it must escape the
8
- // viewport's overflow while staying inside the token scope).
9
- position: relative;
10
- // A column so that a root given an explicit height actually constrains the
11
- // scroller: the viewport takes what the toolbar and pagination leave, and
12
- // min-height: 0 lets it shrink below its content instead of overflowing the
13
- // root. With no height set, this changes nothing — the viewport is sized by
14
- // its content up to the max-height token.
15
- display: flex;
16
- flex-direction: column;
17
-
18
- // Component tokens. Everything resolves through CoreUI semantic variables,
19
- // so light/dark theming via [data-coreui-theme] works with no extra rules.
20
- --cui-data-grid-viewport-max-height: 30rem;
21
- --cui-data-grid-header-bg: var(--cui-body-bg, #fff);
22
- --cui-data-grid-header-shadow: inset 0 calc(-1 * var(--cui-border-width, 1px)) 0 var(--cui-border-color, #dee2e6);
23
- --cui-data-grid-cell-selected-bg: rgba(var(--cui-primary-rgb, 50, 31, 219), .12);
24
- --cui-data-grid-cell-selected-border-color: var(--cui-primary, #321fdb);
25
- --cui-data-grid-cell-selected-border-width: 1px;
26
- --cui-data-grid-row-handle-width: 2rem;
27
- --cui-data-grid-select-cell-width: 2.5rem;
28
- --cui-data-grid-sorter-margin: .25rem;
29
- --cui-data-grid-sorter-opacity: .3;
30
- --cui-data-grid-spacing: .5rem;
31
- --cui-data-grid-resizer-width: .625rem;
32
- --cui-data-grid-resizer-grip-height: 60%;
33
- --cui-data-grid-resizer-grip-color: var(--cui-border-color, #dee2e6);
34
- --cui-data-grid-resizer-grip-color-hover: var(--cui-secondary-color, #6c757d);
35
- --cui-data-grid-pinned-border-width: var(--cui-border-width);
36
- --cui-data-grid-pinned-border-color: var(--cui-border-color, #dee2e6);
37
- --cui-data-grid-drop-indicator: var(--cui-primary, #321fdb);
38
- --cui-data-grid-drag-transition: .15s ease;
39
- --cui-data-grid-menu-bg: var(--cui-body-bg, #fff);
40
- --cui-data-grid-menu-border-color: var(--cui-border-color, #dee2e6);
41
- --cui-data-grid-menu-shadow: var(--cui-box-shadow, 0 .5rem 1rem rgba(0, 0, 0, .15));
42
- --cui-data-grid-menu-min-width: 10rem;
43
- --cui-data-grid-menu-item-hover-bg: var(--cui-tertiary-bg, #f8f9fa);
44
- --cui-data-grid-loading-bg: rgba(var(--cui-body-bg-rgb, 255, 255, 255), .6);
45
- --cui-data-grid-pinned-bg: var(--cui-body-bg, #fff);
46
- --cui-data-grid-focus-ring-width: 2px;
47
- --cui-data-grid-focus-ring-color: var(--cui-primary, #321fdb);
48
-
49
- .data-grid-toolbar {
50
- display: flex;
51
- flex-wrap: wrap;
52
- gap: var(--cui-data-grid-spacing);
53
- align-items: center;
54
- min-height: 48px;
55
- padding: var(--cui-data-grid-spacing);
56
- border-bottom: var(--cui-border-width, 1px) solid var(--cui-border-color, #dee2e6);
57
- }
58
-
59
- .data-grid-toolbar-actions {
60
- display: flex;
61
- gap: .25rem;
62
- align-items: center;
63
- }
64
-
65
- .data-grid-toolbar-search {
66
- margin-inline-start: auto;
67
- }
68
-
69
- .data-grid-viewport {
70
- position: relative;
71
- flex: 1 1 auto;
72
- min-height: 0;
73
- max-height: var(--cui-data-grid-viewport-max-height);
74
- overflow-y: auto;
75
- // Windowed rendering resizes the spacer rows and recycles row elements on
76
- // every frame; browser scroll anchoring chases those mutations and keeps
77
- // adjusting scrollTop, which turns wheel scrolling into a feedback loop.
78
- overflow-anchor: none;
79
- }
80
-
81
- // Inline editing: the in-cell editor fills the cell; the popup layer hosts
82
- // rich editors (date pickers, selects) anchored over the cell.
83
- .data-grid-cell-editor {
84
- width: 100%;
85
- min-width: 4rem;
86
- }
87
-
88
- .data-grid-editor-popup {
89
- position: absolute;
90
- z-index: 4;
91
- padding: .25rem;
92
- background-color: var(--cui-data-grid-menu-bg);
93
- border: var(--cui-border-width, 1px) solid var(--cui-data-grid-menu-border-color);
94
- border-radius: var(--cui-border-radius, .375rem);
95
- box-shadow: var(--cui-data-grid-menu-shadow);
96
- }
97
-
98
- // cellNavigation: the roving-tabindex active cell. The ring is inset so the
99
- // sticky header and pinned columns don't clip it.
100
- [role="grid"] :is(td, th):focus-visible {
101
- outline: var(--cui-data-grid-focus-ring-width) solid var(--cui-data-grid-focus-ring-color);
102
- outline-offset: calc(-1 * var(--cui-data-grid-focus-ring-width));
103
- }
104
-
105
- .data-grid-viewport:focus-visible {
106
- outline: 0;
107
- }
108
-
109
- .data-grid-header {
110
- position: sticky;
111
- top: 0;
112
- z-index: 2;
113
- background-color: var(--cui-data-grid-header-bg);
114
- box-shadow: var(--cui-data-grid-header-shadow);
115
- }
116
-
117
- // Header label row: fixed 48px with vertically centered content (height on a
118
- // table cell acts as a min; min-height is ignored on table-cell).
119
- .data-grid-header tr:not(.data-grid-filter-row) > th {
120
- height: 48px;
121
- vertical-align: middle;
122
- }
123
-
124
- .data-grid-filter-row > th {
125
- padding-top: 0;
126
- font-weight: normal;
127
- }
128
-
129
- .data-grid-header th[data-coreui-draggable] {
130
- cursor: grab;
131
- }
132
-
133
- .data-grid-header-cell {
134
- display: flex;
135
- align-items: center;
136
- gap: .25rem;
137
- }
138
-
139
- .data-grid-header-label {
140
- overflow: hidden;
141
- text-overflow: ellipsis;
142
- white-space: nowrap;
143
- }
144
-
145
- // Icon-only ghost buttons: square them by matching horizontal padding to
146
- // vertical (follows .btn / .btn-sm automatically) and collapsing the text
147
- // line-height so height follows the icon, not a 1.5em text line.
148
- .btn-ghost {
149
- --cui-btn-padding-x: var(--cui-btn-padding-y);
150
- --cui-btn-line-height: 1;
151
- }
152
-
153
- .data-grid-menu-button {
154
- margin-inline-start: auto;
155
- }
156
-
157
- .data-grid-menu {
158
- position: absolute;
159
- z-index: 4;
160
- min-width: var(--cui-data-grid-menu-min-width);
161
- padding: .25rem 0;
162
- background-color: var(--cui-data-grid-menu-bg);
163
- border: var(--cui-border-width, 1px) solid var(--cui-data-grid-menu-border-color);
164
- border-radius: var(--cui-border-radius, .375rem);
165
- box-shadow: var(--cui-data-grid-menu-shadow);
166
- }
167
-
168
- .data-grid-menu-item {
169
- display: flex;
170
- align-items: center;
171
- gap: .5rem;
172
- width: 100%;
173
- padding: .25rem .75rem;
174
- font: inherit;
175
- color: inherit;
176
- text-align: start;
177
- cursor: pointer;
178
- background: none;
179
- border: 0;
180
-
181
- &:hover,
182
- &:focus-visible {
183
- background-color: var(--cui-data-grid-menu-item-hover-bg);
184
- }
185
-
186
- // Disabled items stay focusable (aria-disabled, APG menu pattern) so the
187
- // roving arrow cycle can reach them.
188
- &[aria-disabled="true"] {
189
- color: var(--cui-secondary-color, #6c757d);
190
- cursor: default;
191
- background: none;
192
- }
193
- }
194
-
195
- .data-grid-filter-menu {
196
- position: absolute;
197
- z-index: 4;
198
- display: flex;
199
- flex-direction: column;
200
- gap: .5rem;
201
- min-width: var(--cui-data-grid-menu-min-width);
202
- max-width: 18rem;
203
- padding: .75rem;
204
- background-color: var(--cui-data-grid-menu-bg);
205
- border: var(--cui-border-width, 1px) solid var(--cui-data-grid-menu-border-color);
206
- border-radius: var(--cui-border-radius, .375rem);
207
- box-shadow: var(--cui-data-grid-menu-shadow);
208
-
209
- > div {
210
- display: flex;
211
- flex-direction: column;
212
- gap: .5rem;
213
- }
214
- }
215
-
216
- .data-grid-filter-menu-condition {
217
- display: flex;
218
- flex-direction: column;
219
- gap: .25rem;
220
- }
221
-
222
- .data-grid-filter-menu-join {
223
- display: flex;
224
- gap: 1rem;
225
-
226
- label {
227
- display: flex;
228
- gap: .375rem;
229
- align-items: center;
230
- }
231
- }
232
-
233
- .data-grid-filter-menu-values {
234
- display: flex;
235
- flex-direction: column;
236
- gap: .25rem;
237
- max-height: 14rem;
238
- overflow-y: auto;
239
- }
240
-
241
- .data-grid-filter-menu-footer {
242
- display: flex;
243
- gap: .5rem;
244
- justify-content: flex-end;
245
- }
246
-
247
- .data-grid-column-chooser {
248
- position: absolute;
249
- z-index: 4;
250
- display: flex;
251
- flex-direction: column;
252
- gap: .5rem;
253
- min-width: var(--cui-data-grid-menu-min-width);
254
- max-width: 18rem;
255
- max-height: 20rem;
256
- padding: .75rem;
257
- overflow-y: auto;
258
- background-color: var(--cui-data-grid-menu-bg);
259
- border: var(--cui-border-width, 1px) solid var(--cui-data-grid-menu-border-color);
260
- border-radius: var(--cui-border-radius, .375rem);
261
- box-shadow: var(--cui-data-grid-menu-shadow);
262
- }
263
-
264
- .data-grid-column-chooser-option {
265
- display: flex;
266
- gap: .375rem;
267
- align-items: center;
268
- margin-bottom: 0;
269
- }
270
-
271
- .data-grid-column-chooser-footer {
272
- display: flex;
273
- gap: .5rem;
274
- justify-content: flex-end;
275
- padding-top: .25rem;
276
- margin-top: .25rem;
277
- border-top: var(--cui-border-width, 1px) solid var(--cui-data-grid-menu-border-color);
278
- }
279
-
280
- .data-grid-filter-button {
281
- position: relative;
282
- // Right-align the trailing controls as a group: the filter button takes the
283
- // auto margin (menu drops its own below) so filter and menu sit together at
284
- // the end, matching a menu-only header.
285
- margin-inline-start: auto;
286
-
287
- ~ .data-grid-menu-button {
288
- margin-inline-start: 0;
289
- }
290
- }
291
-
292
- // Active-filter indicator dot on the filter button.
293
- .data-grid-filter-button-filtered::after {
294
- position: absolute;
295
- inset-block-start: .125rem;
296
- inset-inline-end: .125rem;
297
- width: .375rem;
298
- height: .375rem;
299
- content: "";
300
- background-color: var(--cui-primary, #321fdb);
301
- border-radius: 50%;
302
- }
303
-
304
- .data-grid-menu-item-icon {
305
- display: inline-flex;
306
- opacity: .75;
307
-
308
- svg {
309
- width: 1em;
310
- height: 1em;
311
- }
312
- }
313
-
314
- .data-grid-menu-divider {
315
- height: var(--cui-border-width, 1px);
316
- margin: .25rem 0;
317
- background-color: var(--cui-data-grid-menu-border-color);
318
- }
319
-
320
- .data-grid-dragging {
321
- opacity: .5;
322
- }
323
-
324
- // While a drag is live the whole grid keeps the grabbing cursor and stops
325
- // painting a text selection under the pointer.
326
- &.data-grid-drag-active {
327
- cursor: grabbing;
328
- user-select: none;
329
- }
330
-
331
- // Both overlays are position: fixed (placed from viewport coordinates in JS)
332
- // so they escape the viewport's overflow, like the tooltip.
333
- .data-grid-drag-ghost {
334
- position: fixed;
335
- top: 0;
336
- left: 0;
337
- z-index: 1080;
338
- display: flex;
339
- align-items: center;
340
- max-width: 16rem;
341
- padding: 0 var(--cui-data-grid-cell-padding-x, .5rem);
342
- overflow: hidden;
343
- font-weight: 600;
344
- text-overflow: ellipsis;
345
- white-space: nowrap;
346
- pointer-events: none;
347
- background-color: var(--cui-data-grid-pinned-bg);
348
- border: var(--cui-border-width, 1px) solid var(--cui-data-grid-drop-indicator);
349
- border-radius: var(--cui-border-radius, .375rem);
350
- box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .15);
351
- transform: translate(-9999px, -9999px);
352
- opacity: .9;
353
- }
354
-
355
- // The settling ghost: on release it flies from the pointer to the slot the
356
- // item landed in (or back home on cancel) and fades out there.
357
- .data-grid-drag-ghost-settle {
358
- transition: transform var(--cui-data-grid-drag-transition), opacity var(--cui-data-grid-drag-transition);
359
- }
360
-
361
- .data-grid-drop-indicator {
362
- position: fixed;
363
- z-index: 1080;
364
- pointer-events: none;
365
- background-color: var(--cui-data-grid-drop-indicator);
366
- transition: top var(--cui-data-grid-drag-transition), left var(--cui-data-grid-drag-transition);
367
- }
368
-
369
- // The live reorder preview: cells slide to the layout the drop will produce.
370
- // Transform only, so nothing reflows and the real order still changes once.
371
- .data-grid-drag-preview {
372
- transition: transform var(--cui-data-grid-drag-transition);
373
- }
374
-
375
- // Someone who asked the OS to stop moving things still gets the preview —
376
- // it snaps to the final layout instead of gliding there.
377
- @media (prefers-reduced-motion: reduce) {
378
- :is(.data-grid-drop-indicator, .data-grid-drag-preview, .data-grid-drag-ghost-settle) {
379
- transition: none;
380
- }
381
- }
382
-
383
- // The line is 2px across its short axis and spans the grid along the other;
384
- // JS sets the spanning size, the axis class sets the thickness.
385
- .data-grid-drop-indicator-x {
386
- width: .125rem;
387
- }
388
-
389
- .data-grid-drop-indicator-y {
390
- height: .125rem;
391
- }
392
-
393
- // Cell selection: a tinted fill on every selected cell, plus an outline
394
- // drawn only on the sides that sit on the selection's boundary — so a
395
- // rectangle reads as one region instead of a grid of boxes. The outline is
396
- // an overlay rather than a border: a border on a table cell would shift the
397
- // whole row's layout the moment a range is selected.
398
- .data-grid-cell-selected {
399
- position: relative;
400
- background-color: var(--cui-data-grid-cell-selected-bg);
401
- }
402
-
403
- .data-grid-cell-selected::after {
404
- position: absolute;
405
- inset: 0;
406
- pointer-events: none;
407
- content: "";
408
- border: 0 solid var(--cui-data-grid-cell-selected-border-color);
409
- }
410
-
411
- .data-grid-cell-selected-top::after {
412
- border-top-width: var(--cui-data-grid-cell-selected-border-width);
413
- }
414
-
415
- .data-grid-cell-selected-right::after {
416
- border-right-width: var(--cui-data-grid-cell-selected-border-width);
417
- }
418
-
419
- .data-grid-cell-selected-bottom::after {
420
- border-bottom-width: var(--cui-data-grid-cell-selected-border-width);
421
- }
422
-
423
- .data-grid-cell-selected-left::after {
424
- border-left-width: var(--cui-data-grid-cell-selected-border-width);
425
- }
426
-
427
- // The reorder column: as narrow as the grip, and the grip itself is the only
428
- // thing that starts a row drag (a row is full of interactive content that a
429
- // whole-row handle would swallow).
430
- .data-grid-row-handle-cell {
431
- width: var(--cui-data-grid-row-handle-width);
432
- padding-inline: 0;
433
- text-align: center;
434
- }
435
-
436
- .data-grid-row-handle {
437
- display: inline-flex;
438
- color: var(--cui-data-grid-resizer-grip-color-hover);
439
- cursor: grab;
440
- touch-action: none;
441
- }
442
-
443
- .data-grid-select-cell {
444
- width: var(--cui-data-grid-select-cell-width);
445
- text-align: center;
446
- }
447
-
448
- .data-grid-sort-button {
449
- display: inline-flex;
450
- align-items: center;
451
- gap: var(--cui-data-grid-sorter-margin);
452
- padding: 0;
453
- font: inherit;
454
- color: inherit;
455
- cursor: pointer;
456
- user-select: none;
457
- background: none;
458
- border: 0;
459
- }
460
-
461
- .data-grid-sort-icon {
462
- display: inline-flex;
463
- font-size: .875em;
464
- opacity: 0;
465
-
466
- svg {
467
- width: 1em;
468
- height: 1em;
469
- }
470
- }
471
-
472
- // The active sort direction is always visible; the neutral (unsorted) icon is
473
- // hidden unless `sorterVisibility` opts it in (steadily via "always", or on
474
- // header hover/focus via "hover").
475
- .data-grid-sortable[aria-sort] .data-grid-sort-icon {
476
- opacity: 1;
477
- }
478
-
479
- &[data-coreui-sorter-visibility="always"] .data-grid-sortable:not([aria-sort]) .data-grid-sort-icon {
480
- opacity: var(--cui-data-grid-sorter-opacity);
481
- }
482
-
483
- &[data-coreui-sorter-visibility="hover"] .data-grid-sortable:not([aria-sort]):hover .data-grid-sort-icon,
484
- &[data-coreui-sorter-visibility="hover"] .data-grid-sortable:not([aria-sort]):focus-within .data-grid-sort-icon {
485
- opacity: var(--cui-data-grid-sorter-opacity);
486
- }
487
-
488
- .data-grid-viewport > .table {
489
- margin-bottom: 0;
490
- table-layout: fixed;
491
- }
492
-
493
- // Body cells render on a single line and truncate with an ellipsis instead of
494
- // spilling their content across the fixed-layout column boundary onto the next
495
- // column. Matches the default of AG Grid / MUI X Data Grid and TanStack's
496
- // virtualized-table guidance, and keeps every row a uniform height for the
497
- // fixed-height virtualizer (wrapping would desync `estimateSize`). Pinned cells
498
- // are excluded so their shadow pseudo-element (painted outside the box via a
499
- // translate) isn't clipped; the select cell holds only a checkbox.
500
- //
501
- // Auto row height is the deliberate exception: there the virtualizer measures
502
- // each row, so cells are free to wrap. Scoping the rule out is what keeps the
503
- // two modes from fighting over specificity.
504
- &:not(.data-grid-auto-row-height) .data-grid-viewport > .table > tbody > tr:not(.data-grid-empty) > td:not(.data-grid-select-cell):not(.data-grid-cell-pinned-start):not(.data-grid-cell-pinned-end) {
505
- overflow: hidden;
506
- text-overflow: ellipsis;
507
- white-space: nowrap;
508
- }
509
-
510
- // Widths applied to each header cell drive the column layout; letting the
511
- // table grow to its content (min-width keeps it filling a wide viewport)
512
- // turns a resize or a pin into horizontal scroll rather than squeezing
513
- // neighbours. Both features share this layout mode.
514
- &.data-grid-resizable,
515
- &.data-grid-pinned {
516
- .data-grid-viewport {
517
- overflow-x: auto;
518
- }
519
-
520
- .table {
521
- width: max-content;
522
- min-width: 100%;
523
- }
524
- }
525
-
526
- // A pinned th is already sticky (a positioned containing block for the
527
- // resizer), so only non-pinned header cells need explicit relative here.
528
- &.data-grid-resizable .data-grid-header th:not(.data-grid-cell-pinned-start):not(.data-grid-cell-pinned-end) {
529
- position: relative;
530
- }
531
-
532
- &.data-grid-pinned .table {
533
- // position: sticky is unreliable on collapsed-border tables; the grid opts
534
- // into separate borders so pinned cells stay put on horizontal scroll.
535
- border-collapse: separate;
536
- border-spacing: 0;
537
- }
538
-
539
- .data-grid-cell-pinned-start,
540
- .data-grid-cell-pinned-end {
541
- position: sticky;
542
- z-index: 1;
543
- background-color: var(--cui-data-grid-pinned-bg);
544
- }
545
-
546
- .data-grid-header .data-grid-cell-pinned-start,
547
- .data-grid-header .data-grid-cell-pinned-end {
548
- z-index: 3;
549
- }
550
-
551
- // Edge cells cast a shadow over the scrolling content. A pseudo-element is
552
- // used because the cell's own box-shadow carries the table striping accent.
553
- .data-grid-cell-pinned-start-last,
554
- .data-grid-cell-pinned-end-first {
555
- position: sticky;
556
-
557
- &::after {
558
- position: absolute;
559
- top: 0;
560
- bottom: 0;
561
- width: var(--cui-data-grid-pinned-border-width);
562
- pointer-events: none;
563
- content: "";
564
- }
565
- }
566
-
567
- .data-grid-cell-pinned-start-last::after {
568
- inset-inline-end: 0;
569
- background: var(--cui-data-grid-pinned-border-color);
570
- }
571
-
572
- .data-grid-cell-pinned-end-first::after {
573
- inset-inline-start: 0;
574
- background: var(--cui-data-grid-pinned-border-color);
575
- }
576
-
577
- .data-grid-resizer {
578
- position: absolute;
579
- top: 0;
580
- right: calc(-.5 * var(--cui-data-grid-resizer-width));
581
- z-index: 1;
582
- display: flex;
583
- align-items: center;
584
- justify-content: center;
585
- width: var(--cui-data-grid-resizer-width);
586
- height: 100%;
587
- cursor: col-resize;
588
- touch-action: none;
589
- user-select: none;
590
-
591
- // Always-visible grip so the resizable edge is discoverable, not just a
592
- // bare hover target.
593
- &::after {
594
- width: 2px;
595
- height: var(--cui-data-grid-resizer-grip-height);
596
- content: "";
597
- background-color: var(--cui-data-grid-resizer-grip-color);
598
- transition: background-color .15s ease;
599
- }
600
-
601
- &:hover::after,
602
- &.data-grid-resizer-active::after {
603
- background-color: var(--cui-data-grid-resizer-grip-color-hover);
604
- }
605
- }
606
-
607
- .data-grid-spacer > td {
608
- padding: 0;
609
- border: 0;
610
- }
611
-
612
- // Spacer rows break `nth-of-type` striping, so striping inside the grid is
613
- // driven by the absolute row index (.data-grid-row-odd) instead.
614
- .data-grid-viewport > .table-striped > tbody > tr:nth-of-type(odd) > * {
615
- --cui-table-color-type: initial;
616
- --cui-table-bg-type: initial;
617
- }
618
-
619
- .data-grid-viewport > .table-striped > tbody > tr.data-grid-row-odd > * {
620
- --cui-table-color-type: var(--cui-table-striped-color);
621
- --cui-table-bg-type: var(--cui-table-striped-bg);
622
- }
623
-
624
- // The last row closes on the viewport edge (or the pagination border), so it
625
- // doesn't need its own separator line.
626
- .data-grid-viewport > .table > tbody > tr:last-child > * {
627
- border-bottom-width: 0;
628
- }
629
-
630
- .data-grid-loading {
631
- position: absolute;
632
- inset: 0;
633
- z-index: 3;
634
- display: flex;
635
- align-items: center;
636
- justify-content: center;
637
- background-color: var(--cui-data-grid-loading-bg);
638
- }
639
-
640
- // Infinite scroll's "next page arriving" strip. Sticky, not an overlay: the
641
- // rows already loaded stay readable while the grid appends to them.
642
- .data-grid-loading-more {
643
- position: sticky;
644
- inset-inline: 0;
645
- bottom: 0;
646
- z-index: 3;
647
- display: flex;
648
- justify-content: center;
649
- padding: var(--cui-data-grid-spacing);
650
- background-color: var(--cui-data-grid-loading-bg);
651
- }
652
-
653
- // Shared icon-button tooltip. position: fixed (set in JS) so it escapes the
654
- // viewport overflow; theme-inverted like CoreUI's own tooltip.
655
- .data-grid-tooltip {
656
- position: fixed;
657
- z-index: 1080;
658
- max-width: 12rem;
659
- padding: .25rem .5rem;
660
- font-size: .875rem;
661
- line-height: 1.4;
662
- color: var(--cui-body-bg, #fff);
663
- text-align: center;
664
- pointer-events: none;
665
- background-color: var(--cui-emphasis-color, #000);
666
- border-radius: var(--cui-border-radius, .375rem);
667
- }
668
-
669
- .data-grid-empty > td {
670
- padding: 2rem 1rem;
671
- color: var(--cui-secondary-color, #6c757d);
672
- text-align: center;
673
- }
674
-
675
- .data-grid-pagination {
676
- display: flex;
677
- // Wrap the page controls, count and page-size select onto multiple rows on
678
- // narrow viewports; without this the fixed row overflows and scrolls the page
679
- // instead of staying inside the grid.
680
- flex-wrap: wrap;
681
- gap: var(--cui-data-grid-spacing);
682
- align-items: center;
683
- min-height: 48px;
684
- padding: var(--cui-data-grid-spacing);
685
- border-top: var(--cui-border-width, 1px) solid var(--cui-border-color, #dee2e6);
686
-
687
- &.data-grid-pagination-top {
688
- border-top: 0;
689
- border-bottom: var(--cui-border-width, 1px) solid var(--cui-border-color, #dee2e6);
690
- }
691
-
692
- .pagination {
693
- margin-bottom: 0;
694
- }
695
-
696
- .data-grid-pagination-info {
697
- margin-inline-start: auto;
698
- color: var(--cui-secondary-color, #6c757d);
699
- }
700
-
701
- .form-select {
702
- width: auto;
703
- }
704
- }
705
- }
706
-
707
- // Print: the grid renders a plain, complete table into the document (see
708
- // util/print.ts) and hides everything else, so a virtualized grid prints all
709
- // its rows instead of the twenty in the window.
710
- @media print {
711
- .data-grid-print-root {
712
- position: absolute;
713
- inset: 0 0 auto;
714
- z-index: 2000;
715
- background-color: #fff;
716
-
717
- h1 {
718
- margin-bottom: 1rem;
719
- font-size: 1.25rem;
720
- }
721
-
722
- table {
723
- width: 100%;
724
- border-collapse: collapse;
725
- }
726
-
727
- :is(th, td) {
728
- padding: .25rem .5rem;
729
- text-align: start;
730
- border: 1px solid #000;
731
- }
732
-
733
- thead {
734
- display: table-header-group;
735
- }
736
-
737
- tr {
738
- break-inside: avoid;
739
- }
740
- }
741
-
742
- // :has() is inside the browser floor (.browserslistrc), and scoping to the
743
- // body's own children keeps the clone's ancestors from being hidden.
744
- body:has(.data-grid-print-root) > :not(.data-grid-print-root) {
745
- display: none !important;
746
- }
747
- }
6
+ // scss-docs-start import-stack
7
+ @forward "config";
8
+ @forward "functions";
9
+ @forward "mixins";
10
+ @forward "components/data-grid";
11
+ // scss-docs-end import-stack