@coreui/data-grid 0.1.0-rc.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.
- package/LICENSE +3 -0
- package/README.md +37 -0
- package/dist/css/data-grid.css +444 -0
- package/dist/css/data-grid.css.map +1 -0
- package/dist/css/data-grid.min.css +5 -0
- package/dist/css/data-grid.min.css.map +1 -0
- package/dist/js/csv.cjs +68 -0
- package/dist/js/csv.cjs.map +1 -0
- package/dist/js/csv.mjs +63 -0
- package/dist/js/csv.mjs.map +1 -0
- package/dist/js/data-grid.esm.js +9618 -0
- package/dist/js/data-grid.esm.js.map +1 -0
- package/dist/js/data-grid.esm.min.js +8 -0
- package/dist/js/data-grid.esm.min.js.map +1 -0
- package/dist/js/data-grid.js +9635 -0
- package/dist/js/data-grid.js.map +1 -0
- package/dist/js/data-grid.min.js +8 -0
- package/dist/js/data-grid.min.js.map +1 -0
- package/dist/js/data-grid.mjs +9618 -0
- package/dist/js/data-grid.mjs.map +1 -0
- package/dist/js/filters.cjs +143 -0
- package/dist/js/filters.cjs.map +1 -0
- package/dist/js/filters.mjs +137 -0
- package/dist/js/filters.mjs.map +1 -0
- package/dist/js/labels.cjs +76 -0
- package/dist/js/labels.cjs.map +1 -0
- package/dist/js/labels.mjs +71 -0
- package/dist/js/labels.mjs.map +1 -0
- package/dist/types/base-component.d.ts +19 -0
- package/dist/types/data-grid.d.ts +128 -0
- package/dist/types/dom/event-handler.d.ts +11 -0
- package/dist/types/dom/manipulator.d.ts +9 -0
- package/dist/types/engine/active-cell.d.ts +32 -0
- package/dist/types/engine/data-source.d.ts +19 -0
- package/dist/types/engine/scheduler.d.ts +11 -0
- package/dist/types/engine/table.d.ts +9 -0
- package/dist/types/engine/virtualizer.d.ts +21 -0
- package/dist/types/filters.d.mts +1 -0
- package/dist/types/filters.d.ts +13 -0
- package/dist/types/icons.d.ts +21 -0
- package/dist/types/index.d.mts +1 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/labels.d.mts +1 -0
- package/dist/types/labels.d.ts +9 -0
- package/dist/types/types.d.ts +262 -0
- package/dist/types/ui/body.d.ts +34 -0
- package/dist/types/ui/column-chooser.d.ts +27 -0
- package/dist/types/ui/editor.d.ts +8 -0
- package/dist/types/ui/filter-menu.d.ts +21 -0
- package/dist/types/ui/header.d.ts +50 -0
- package/dist/types/ui/loading.d.ts +12 -0
- package/dist/types/ui/menu.d.ts +17 -0
- package/dist/types/ui/pagination.d.ts +17 -0
- package/dist/types/ui/pinning.d.ts +17 -0
- package/dist/types/ui/toolbar.d.ts +34 -0
- package/dist/types/ui/tooltip.d.ts +10 -0
- package/dist/types/util/config.d.ts +11 -0
- package/dist/types/util/csv.d.mts +1 -0
- package/dist/types/util/csv.d.ts +19 -0
- package/dist/types/util/debounce.d.ts +7 -0
- package/dist/types/util/index.d.ts +10 -0
- package/dist/types/util/sanitizer.d.ts +11 -0
- package/package.json +147 -0
- package/scss/data-grid.scss +559 -0
- package/src/base-component.d.ts +19 -0
- package/src/base-component.js +90 -0
- package/src/data-grid.ts +2208 -0
- package/src/dom/data.js +59 -0
- package/src/dom/event-handler.d.ts +11 -0
- package/src/dom/event-handler.js +331 -0
- package/src/dom/manipulator.d.ts +9 -0
- package/src/dom/manipulator.js +75 -0
- package/src/engine/active-cell.ts +195 -0
- package/src/engine/data-source.ts +63 -0
- package/src/engine/scheduler.ts +42 -0
- package/src/engine/table.ts +122 -0
- package/src/engine/virtualizer.ts +57 -0
- package/src/filters.ts +176 -0
- package/src/icons.ts +60 -0
- package/src/index.ts +56 -0
- package/src/labels.ts +70 -0
- package/src/types.ts +334 -0
- package/src/ui/body.ts +348 -0
- package/src/ui/column-chooser.ts +183 -0
- package/src/ui/editor.ts +98 -0
- package/src/ui/filter-menu.ts +398 -0
- package/src/ui/header.ts +441 -0
- package/src/ui/loading.ts +39 -0
- package/src/ui/menu.ts +218 -0
- package/src/ui/pagination.ts +150 -0
- package/src/ui/pinning.ts +53 -0
- package/src/ui/toolbar.ts +144 -0
- package/src/ui/tooltip.ts +113 -0
- package/src/util/config.d.ts +11 -0
- package/src/util/config.js +69 -0
- package/src/util/csv.ts +85 -0
- package/src/util/debounce.ts +18 -0
- package/src/util/index.d.ts +10 -0
- package/src/util/index.js +310 -0
- package/src/util/sanitizer.d.ts +11 -0
- package/src/util/sanitizer.js +162 -0
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* CoreUI PRO data-grid.scss v0.1.0
|
|
3
|
+
* License (https://coreui.io/pro/license/)
|
|
4
|
+
*/
|
|
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
|
+
|
|
11
|
+
// Component tokens. Everything resolves through CoreUI semantic variables,
|
|
12
|
+
// so light/dark theming via [data-coreui-theme] works with no extra rules.
|
|
13
|
+
--cui-data-grid-viewport-max-height: 30rem;
|
|
14
|
+
--cui-data-grid-header-bg: var(--cui-body-bg, #fff);
|
|
15
|
+
--cui-data-grid-header-shadow: inset 0 calc(-1 * var(--cui-border-width, 1px)) 0 var(--cui-border-color, #dee2e6);
|
|
16
|
+
--cui-data-grid-select-cell-width: 2.5rem;
|
|
17
|
+
--cui-data-grid-sorter-margin: .25rem;
|
|
18
|
+
--cui-data-grid-sorter-opacity: .3;
|
|
19
|
+
--cui-data-grid-spacing: .5rem;
|
|
20
|
+
--cui-data-grid-resizer-width: .625rem;
|
|
21
|
+
--cui-data-grid-resizer-grip-height: 60%;
|
|
22
|
+
--cui-data-grid-resizer-grip-color: var(--cui-border-color, #dee2e6);
|
|
23
|
+
--cui-data-grid-resizer-grip-color-hover: var(--cui-secondary-color, #6c757d);
|
|
24
|
+
--cui-data-grid-pinned-border-width: var(--cui-border-width);
|
|
25
|
+
--cui-data-grid-pinned-border-color: var(--cui-border-color, #dee2e6);
|
|
26
|
+
--cui-data-grid-drop-indicator: var(--cui-primary, #321fdb);
|
|
27
|
+
--cui-data-grid-menu-bg: var(--cui-body-bg, #fff);
|
|
28
|
+
--cui-data-grid-menu-border-color: var(--cui-border-color, #dee2e6);
|
|
29
|
+
--cui-data-grid-menu-shadow: var(--cui-box-shadow, 0 .5rem 1rem rgba(0, 0, 0, .15));
|
|
30
|
+
--cui-data-grid-menu-min-width: 10rem;
|
|
31
|
+
--cui-data-grid-menu-item-hover-bg: var(--cui-tertiary-bg, #f8f9fa);
|
|
32
|
+
--cui-data-grid-loading-bg: rgba(var(--cui-body-bg-rgb, 255, 255, 255), .6);
|
|
33
|
+
--cui-data-grid-pinned-bg: var(--cui-body-bg, #fff);
|
|
34
|
+
--cui-data-grid-focus-ring-width: 2px;
|
|
35
|
+
--cui-data-grid-focus-ring-color: var(--cui-primary, #321fdb);
|
|
36
|
+
|
|
37
|
+
.data-grid-toolbar {
|
|
38
|
+
display: flex;
|
|
39
|
+
flex-wrap: wrap;
|
|
40
|
+
gap: var(--cui-data-grid-spacing);
|
|
41
|
+
align-items: center;
|
|
42
|
+
min-height: 48px;
|
|
43
|
+
padding: var(--cui-data-grid-spacing);
|
|
44
|
+
border-bottom: var(--cui-border-width, 1px) solid var(--cui-border-color, #dee2e6);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.data-grid-toolbar-actions {
|
|
48
|
+
display: flex;
|
|
49
|
+
gap: .25rem;
|
|
50
|
+
align-items: center;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.data-grid-toolbar-search {
|
|
54
|
+
margin-inline-start: auto;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.data-grid-viewport {
|
|
58
|
+
position: relative;
|
|
59
|
+
max-height: var(--cui-data-grid-viewport-max-height);
|
|
60
|
+
overflow-y: auto;
|
|
61
|
+
// Windowed rendering resizes the spacer rows and recycles row elements on
|
|
62
|
+
// every frame; browser scroll anchoring chases those mutations and keeps
|
|
63
|
+
// adjusting scrollTop, which turns wheel scrolling into a feedback loop.
|
|
64
|
+
overflow-anchor: none;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Inline editing: the in-cell editor fills the cell; the popup layer hosts
|
|
68
|
+
// rich editors (date pickers, selects) anchored over the cell.
|
|
69
|
+
.data-grid-cell-editor {
|
|
70
|
+
width: 100%;
|
|
71
|
+
min-width: 4rem;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.data-grid-editor-popup {
|
|
75
|
+
position: absolute;
|
|
76
|
+
z-index: 4;
|
|
77
|
+
padding: .25rem;
|
|
78
|
+
background-color: var(--cui-data-grid-menu-bg);
|
|
79
|
+
border: var(--cui-border-width, 1px) solid var(--cui-data-grid-menu-border-color);
|
|
80
|
+
border-radius: var(--cui-border-radius, .375rem);
|
|
81
|
+
box-shadow: var(--cui-data-grid-menu-shadow);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// cellNavigation: the roving-tabindex active cell. The ring is inset so the
|
|
85
|
+
// sticky header and pinned columns don't clip it.
|
|
86
|
+
[role="grid"] :is(td, th):focus-visible {
|
|
87
|
+
outline: var(--cui-data-grid-focus-ring-width) solid var(--cui-data-grid-focus-ring-color);
|
|
88
|
+
outline-offset: calc(-1 * var(--cui-data-grid-focus-ring-width));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.data-grid-viewport:focus-visible {
|
|
92
|
+
outline: 0;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.data-grid-header {
|
|
96
|
+
position: sticky;
|
|
97
|
+
top: 0;
|
|
98
|
+
z-index: 2;
|
|
99
|
+
background-color: var(--cui-data-grid-header-bg);
|
|
100
|
+
box-shadow: var(--cui-data-grid-header-shadow);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Header label row: fixed 48px with vertically centered content (height on a
|
|
104
|
+
// table cell acts as a min; min-height is ignored on table-cell).
|
|
105
|
+
.data-grid-header tr:not(.data-grid-filter-row) > th {
|
|
106
|
+
height: 48px;
|
|
107
|
+
vertical-align: middle;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.data-grid-filter-row > th {
|
|
111
|
+
padding-top: 0;
|
|
112
|
+
font-weight: normal;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.data-grid-header th[data-coreui-draggable] {
|
|
116
|
+
cursor: grab;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.data-grid-header-cell {
|
|
120
|
+
display: flex;
|
|
121
|
+
align-items: center;
|
|
122
|
+
gap: .25rem;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.data-grid-header-label {
|
|
126
|
+
overflow: hidden;
|
|
127
|
+
text-overflow: ellipsis;
|
|
128
|
+
white-space: nowrap;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Icon-only ghost buttons: square them by matching horizontal padding to
|
|
132
|
+
// vertical (follows .btn / .btn-sm automatically) and collapsing the text
|
|
133
|
+
// line-height so height follows the icon, not a 1.5em text line.
|
|
134
|
+
.btn-ghost {
|
|
135
|
+
--cui-btn-padding-x: var(--cui-btn-padding-y);
|
|
136
|
+
--cui-btn-line-height: 1;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.data-grid-menu-button {
|
|
140
|
+
margin-inline-start: auto;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.data-grid-menu {
|
|
144
|
+
position: absolute;
|
|
145
|
+
z-index: 4;
|
|
146
|
+
min-width: var(--cui-data-grid-menu-min-width);
|
|
147
|
+
padding: .25rem 0;
|
|
148
|
+
background-color: var(--cui-data-grid-menu-bg);
|
|
149
|
+
border: var(--cui-border-width, 1px) solid var(--cui-data-grid-menu-border-color);
|
|
150
|
+
border-radius: var(--cui-border-radius, .375rem);
|
|
151
|
+
box-shadow: var(--cui-data-grid-menu-shadow);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.data-grid-menu-item {
|
|
155
|
+
display: flex;
|
|
156
|
+
align-items: center;
|
|
157
|
+
gap: .5rem;
|
|
158
|
+
width: 100%;
|
|
159
|
+
padding: .25rem .75rem;
|
|
160
|
+
font: inherit;
|
|
161
|
+
color: inherit;
|
|
162
|
+
text-align: start;
|
|
163
|
+
cursor: pointer;
|
|
164
|
+
background: none;
|
|
165
|
+
border: 0;
|
|
166
|
+
|
|
167
|
+
&:hover,
|
|
168
|
+
&:focus-visible {
|
|
169
|
+
background-color: var(--cui-data-grid-menu-item-hover-bg);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Disabled items stay focusable (aria-disabled, APG menu pattern) so the
|
|
173
|
+
// roving arrow cycle can reach them.
|
|
174
|
+
&[aria-disabled="true"] {
|
|
175
|
+
color: var(--cui-secondary-color, #6c757d);
|
|
176
|
+
cursor: default;
|
|
177
|
+
background: none;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.data-grid-filter-menu {
|
|
182
|
+
position: absolute;
|
|
183
|
+
z-index: 4;
|
|
184
|
+
display: flex;
|
|
185
|
+
flex-direction: column;
|
|
186
|
+
gap: .5rem;
|
|
187
|
+
min-width: var(--cui-data-grid-menu-min-width);
|
|
188
|
+
max-width: 18rem;
|
|
189
|
+
padding: .75rem;
|
|
190
|
+
background-color: var(--cui-data-grid-menu-bg);
|
|
191
|
+
border: var(--cui-border-width, 1px) solid var(--cui-data-grid-menu-border-color);
|
|
192
|
+
border-radius: var(--cui-border-radius, .375rem);
|
|
193
|
+
box-shadow: var(--cui-data-grid-menu-shadow);
|
|
194
|
+
|
|
195
|
+
> div {
|
|
196
|
+
display: flex;
|
|
197
|
+
flex-direction: column;
|
|
198
|
+
gap: .5rem;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.data-grid-filter-menu-condition {
|
|
203
|
+
display: flex;
|
|
204
|
+
flex-direction: column;
|
|
205
|
+
gap: .25rem;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.data-grid-filter-menu-join {
|
|
209
|
+
display: flex;
|
|
210
|
+
gap: 1rem;
|
|
211
|
+
|
|
212
|
+
label {
|
|
213
|
+
display: flex;
|
|
214
|
+
gap: .375rem;
|
|
215
|
+
align-items: center;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.data-grid-filter-menu-values {
|
|
220
|
+
display: flex;
|
|
221
|
+
flex-direction: column;
|
|
222
|
+
gap: .25rem;
|
|
223
|
+
max-height: 14rem;
|
|
224
|
+
overflow-y: auto;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.data-grid-filter-menu-footer {
|
|
228
|
+
display: flex;
|
|
229
|
+
gap: .5rem;
|
|
230
|
+
justify-content: flex-end;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.data-grid-column-chooser {
|
|
234
|
+
position: absolute;
|
|
235
|
+
z-index: 4;
|
|
236
|
+
display: flex;
|
|
237
|
+
flex-direction: column;
|
|
238
|
+
gap: .5rem;
|
|
239
|
+
min-width: var(--cui-data-grid-menu-min-width);
|
|
240
|
+
max-width: 18rem;
|
|
241
|
+
max-height: 20rem;
|
|
242
|
+
padding: .75rem;
|
|
243
|
+
overflow-y: auto;
|
|
244
|
+
background-color: var(--cui-data-grid-menu-bg);
|
|
245
|
+
border: var(--cui-border-width, 1px) solid var(--cui-data-grid-menu-border-color);
|
|
246
|
+
border-radius: var(--cui-border-radius, .375rem);
|
|
247
|
+
box-shadow: var(--cui-data-grid-menu-shadow);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.data-grid-column-chooser-option {
|
|
251
|
+
display: flex;
|
|
252
|
+
gap: .375rem;
|
|
253
|
+
align-items: center;
|
|
254
|
+
margin-bottom: 0;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.data-grid-column-chooser-footer {
|
|
258
|
+
display: flex;
|
|
259
|
+
gap: .5rem;
|
|
260
|
+
justify-content: flex-end;
|
|
261
|
+
padding-top: .25rem;
|
|
262
|
+
margin-top: .25rem;
|
|
263
|
+
border-top: var(--cui-border-width, 1px) solid var(--cui-data-grid-menu-border-color);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.data-grid-filter-button {
|
|
267
|
+
position: relative;
|
|
268
|
+
// Right-align the trailing controls as a group: the filter button takes the
|
|
269
|
+
// auto margin (menu drops its own below) so filter and menu sit together at
|
|
270
|
+
// the end, matching a menu-only header.
|
|
271
|
+
margin-inline-start: auto;
|
|
272
|
+
|
|
273
|
+
~ .data-grid-menu-button {
|
|
274
|
+
margin-inline-start: 0;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Active-filter indicator dot on the filter button.
|
|
279
|
+
.data-grid-filter-button-filtered::after {
|
|
280
|
+
position: absolute;
|
|
281
|
+
inset-block-start: .125rem;
|
|
282
|
+
inset-inline-end: .125rem;
|
|
283
|
+
width: .375rem;
|
|
284
|
+
height: .375rem;
|
|
285
|
+
content: "";
|
|
286
|
+
background-color: var(--cui-primary, #321fdb);
|
|
287
|
+
border-radius: 50%;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.data-grid-menu-item-icon {
|
|
291
|
+
display: inline-flex;
|
|
292
|
+
opacity: .75;
|
|
293
|
+
|
|
294
|
+
svg {
|
|
295
|
+
width: 1em;
|
|
296
|
+
height: 1em;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.data-grid-menu-divider {
|
|
301
|
+
height: var(--cui-border-width, 1px);
|
|
302
|
+
margin: .25rem 0;
|
|
303
|
+
background-color: var(--cui-data-grid-menu-border-color);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.data-grid-header .data-grid-dragging {
|
|
307
|
+
opacity: .5;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.data-grid-header .data-grid-drop-target {
|
|
311
|
+
box-shadow: inset .125rem 0 0 var(--cui-data-grid-drop-indicator);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
.data-grid-select-cell {
|
|
315
|
+
width: var(--cui-data-grid-select-cell-width);
|
|
316
|
+
text-align: center;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
.data-grid-sort-button {
|
|
320
|
+
display: inline-flex;
|
|
321
|
+
align-items: center;
|
|
322
|
+
gap: var(--cui-data-grid-sorter-margin);
|
|
323
|
+
padding: 0;
|
|
324
|
+
font: inherit;
|
|
325
|
+
color: inherit;
|
|
326
|
+
cursor: pointer;
|
|
327
|
+
user-select: none;
|
|
328
|
+
background: none;
|
|
329
|
+
border: 0;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.data-grid-sort-icon {
|
|
333
|
+
display: inline-flex;
|
|
334
|
+
font-size: .875em;
|
|
335
|
+
opacity: 0;
|
|
336
|
+
|
|
337
|
+
svg {
|
|
338
|
+
width: 1em;
|
|
339
|
+
height: 1em;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// The active sort direction is always visible; the neutral (unsorted) icon is
|
|
344
|
+
// hidden unless `sorterVisibility` opts it in (steadily via "always", or on
|
|
345
|
+
// header hover/focus via "hover").
|
|
346
|
+
.data-grid-sortable[aria-sort] .data-grid-sort-icon {
|
|
347
|
+
opacity: 1;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
&[data-coreui-sorter-visibility="always"] .data-grid-sortable:not([aria-sort]) .data-grid-sort-icon {
|
|
351
|
+
opacity: var(--cui-data-grid-sorter-opacity);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
&[data-coreui-sorter-visibility="hover"] .data-grid-sortable:not([aria-sort]):hover .data-grid-sort-icon,
|
|
355
|
+
&[data-coreui-sorter-visibility="hover"] .data-grid-sortable:not([aria-sort]):focus-within .data-grid-sort-icon {
|
|
356
|
+
opacity: var(--cui-data-grid-sorter-opacity);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
.data-grid-viewport > .table {
|
|
360
|
+
margin-bottom: 0;
|
|
361
|
+
table-layout: fixed;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// Body cells render on a single line and truncate with an ellipsis instead of
|
|
365
|
+
// spilling their content across the fixed-layout column boundary onto the next
|
|
366
|
+
// column. Matches the default of AG Grid / MUI X Data Grid and TanStack's
|
|
367
|
+
// virtualized-table guidance, and keeps every row a uniform height for the
|
|
368
|
+
// fixed-height virtualizer (wrapping would desync `estimateSize`). Pinned cells
|
|
369
|
+
// are excluded so their shadow pseudo-element (painted outside the box via a
|
|
370
|
+
// translate) isn't clipped; the select cell holds only a checkbox.
|
|
371
|
+
.data-grid-viewport > .table > tbody > tr:not(.data-grid-empty) > td:not(.data-grid-select-cell):not(.data-grid-cell-pinned-left):not(.data-grid-cell-pinned-right) {
|
|
372
|
+
overflow: hidden;
|
|
373
|
+
text-overflow: ellipsis;
|
|
374
|
+
white-space: nowrap;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Widths applied to each header cell drive the column layout; letting the
|
|
378
|
+
// table grow to its content (min-width keeps it filling a wide viewport)
|
|
379
|
+
// turns a resize or a pin into horizontal scroll rather than squeezing
|
|
380
|
+
// neighbours. Both features share this layout mode.
|
|
381
|
+
&.data-grid-resizable,
|
|
382
|
+
&.data-grid-pinned {
|
|
383
|
+
.data-grid-viewport {
|
|
384
|
+
overflow-x: auto;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.table {
|
|
388
|
+
width: max-content;
|
|
389
|
+
min-width: 100%;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// A pinned th is already sticky (a positioned containing block for the
|
|
394
|
+
// resizer), so only non-pinned header cells need explicit relative here.
|
|
395
|
+
&.data-grid-resizable .data-grid-header th:not(.data-grid-cell-pinned-left):not(.data-grid-cell-pinned-right) {
|
|
396
|
+
position: relative;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
&.data-grid-pinned .table {
|
|
400
|
+
// position: sticky is unreliable on collapsed-border tables; the grid opts
|
|
401
|
+
// into separate borders so pinned cells stay put on horizontal scroll.
|
|
402
|
+
border-collapse: separate;
|
|
403
|
+
border-spacing: 0;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
.data-grid-cell-pinned-left,
|
|
407
|
+
.data-grid-cell-pinned-right {
|
|
408
|
+
position: sticky;
|
|
409
|
+
z-index: 1;
|
|
410
|
+
background-color: var(--cui-data-grid-pinned-bg);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
.data-grid-header .data-grid-cell-pinned-left,
|
|
414
|
+
.data-grid-header .data-grid-cell-pinned-right {
|
|
415
|
+
z-index: 3;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Edge cells cast a shadow over the scrolling content. A pseudo-element is
|
|
419
|
+
// used because the cell's own box-shadow carries the table striping accent.
|
|
420
|
+
.data-grid-cell-pinned-left-last,
|
|
421
|
+
.data-grid-cell-pinned-right-first {
|
|
422
|
+
position: sticky;
|
|
423
|
+
|
|
424
|
+
&::after {
|
|
425
|
+
position: absolute;
|
|
426
|
+
top: 0;
|
|
427
|
+
bottom: 0;
|
|
428
|
+
width: var(--cui-data-grid-pinned-border-width);
|
|
429
|
+
pointer-events: none;
|
|
430
|
+
content: "";
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
.data-grid-cell-pinned-left-last::after {
|
|
435
|
+
right: 0;
|
|
436
|
+
background: var(--cui-data-grid-pinned-border-color);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
.data-grid-cell-pinned-right-first::after {
|
|
440
|
+
left: 0;
|
|
441
|
+
background: var(--cui-data-grid-pinned-border-color);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
.data-grid-resizer {
|
|
445
|
+
position: absolute;
|
|
446
|
+
top: 0;
|
|
447
|
+
right: calc(-.5 * var(--cui-data-grid-resizer-width));
|
|
448
|
+
z-index: 1;
|
|
449
|
+
display: flex;
|
|
450
|
+
align-items: center;
|
|
451
|
+
justify-content: center;
|
|
452
|
+
width: var(--cui-data-grid-resizer-width);
|
|
453
|
+
height: 100%;
|
|
454
|
+
cursor: col-resize;
|
|
455
|
+
touch-action: none;
|
|
456
|
+
user-select: none;
|
|
457
|
+
|
|
458
|
+
// Always-visible grip so the resizable edge is discoverable, not just a
|
|
459
|
+
// bare hover target.
|
|
460
|
+
&::after {
|
|
461
|
+
width: 2px;
|
|
462
|
+
height: var(--cui-data-grid-resizer-grip-height);
|
|
463
|
+
content: "";
|
|
464
|
+
background-color: var(--cui-data-grid-resizer-grip-color);
|
|
465
|
+
transition: background-color .15s ease;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
&:hover::after,
|
|
469
|
+
&.data-grid-resizer-active::after {
|
|
470
|
+
background-color: var(--cui-data-grid-resizer-grip-color-hover);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
.data-grid-spacer > td {
|
|
475
|
+
padding: 0;
|
|
476
|
+
border: 0;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// Spacer rows break `nth-of-type` striping, so striping inside the grid is
|
|
480
|
+
// driven by the absolute row index (.data-grid-row-odd) instead.
|
|
481
|
+
.data-grid-viewport > .table-striped > tbody > tr:nth-of-type(odd) > * {
|
|
482
|
+
--cui-table-color-type: initial;
|
|
483
|
+
--cui-table-bg-type: initial;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
.data-grid-viewport > .table-striped > tbody > tr.data-grid-row-odd > * {
|
|
487
|
+
--cui-table-color-type: var(--cui-table-striped-color);
|
|
488
|
+
--cui-table-bg-type: var(--cui-table-striped-bg);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// The last row closes on the viewport edge (or the pagination border), so it
|
|
492
|
+
// doesn't need its own separator line.
|
|
493
|
+
.data-grid-viewport > .table > tbody > tr:last-child > * {
|
|
494
|
+
border-bottom-width: 0;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
.data-grid-loading {
|
|
498
|
+
position: absolute;
|
|
499
|
+
inset: 0;
|
|
500
|
+
z-index: 3;
|
|
501
|
+
display: flex;
|
|
502
|
+
align-items: center;
|
|
503
|
+
justify-content: center;
|
|
504
|
+
background-color: var(--cui-data-grid-loading-bg);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// Shared icon-button tooltip. position: fixed (set in JS) so it escapes the
|
|
508
|
+
// viewport overflow; theme-inverted like CoreUI's own tooltip.
|
|
509
|
+
.data-grid-tooltip {
|
|
510
|
+
position: fixed;
|
|
511
|
+
z-index: 1080;
|
|
512
|
+
max-width: 12rem;
|
|
513
|
+
padding: .25rem .5rem;
|
|
514
|
+
font-size: .875rem;
|
|
515
|
+
line-height: 1.4;
|
|
516
|
+
color: var(--cui-body-bg, #fff);
|
|
517
|
+
text-align: center;
|
|
518
|
+
pointer-events: none;
|
|
519
|
+
background-color: var(--cui-emphasis-color, #000);
|
|
520
|
+
border-radius: var(--cui-border-radius, .375rem);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
.data-grid-empty > td {
|
|
524
|
+
padding: 2rem 1rem;
|
|
525
|
+
color: var(--cui-secondary-color, #6c757d);
|
|
526
|
+
text-align: center;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
.data-grid-pagination {
|
|
530
|
+
display: flex;
|
|
531
|
+
// Wrap the page controls, count and page-size select onto multiple rows on
|
|
532
|
+
// narrow viewports; without this the fixed row overflows and scrolls the page
|
|
533
|
+
// instead of staying inside the grid.
|
|
534
|
+
flex-wrap: wrap;
|
|
535
|
+
gap: var(--cui-data-grid-spacing);
|
|
536
|
+
align-items: center;
|
|
537
|
+
min-height: 48px;
|
|
538
|
+
padding: var(--cui-data-grid-spacing);
|
|
539
|
+
border-top: var(--cui-border-width, 1px) solid var(--cui-border-color, #dee2e6);
|
|
540
|
+
|
|
541
|
+
&.data-grid-pagination-top {
|
|
542
|
+
border-top: 0;
|
|
543
|
+
border-bottom: var(--cui-border-width, 1px) solid var(--cui-border-color, #dee2e6);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
.pagination {
|
|
547
|
+
margin-bottom: 0;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
.data-grid-pagination-info {
|
|
551
|
+
margin-inline-start: auto;
|
|
552
|
+
color: var(--cui-secondary-color, #6c757d);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
.form-select {
|
|
556
|
+
width: auto;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Hand-written types for the vendored base-component.js (see the provenance header there)
|
|
2
|
+
import Config from './util/config.js'
|
|
3
|
+
|
|
4
|
+
export default class BaseComponent extends Config {
|
|
5
|
+
constructor(element: Element | string, config?: unknown)
|
|
6
|
+
|
|
7
|
+
_element: HTMLElement
|
|
8
|
+
_config: any
|
|
9
|
+
|
|
10
|
+
dispose(): void
|
|
11
|
+
_queueCallback(callback: () => void, element: Element, isAnimated?: boolean): void
|
|
12
|
+
|
|
13
|
+
static getInstance(element: Element | string | null): any
|
|
14
|
+
static getOrCreateInstance(element: Element | string, config?: unknown): any
|
|
15
|
+
static get VERSION(): string
|
|
16
|
+
static get DATA_KEY(): string
|
|
17
|
+
static get EVENT_KEY(): string
|
|
18
|
+
static eventName(name: string): string
|
|
19
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// Vendored from https://github.com/coreui/coreui-pro/blob/bc4daf1cd79d527bf665d615c0a31f53ab0c3d4e/js/src/base-component.js — sync manually
|
|
2
|
+
/**
|
|
3
|
+
* --------------------------------------------------------------------------
|
|
4
|
+
* CoreUI base-component.js
|
|
5
|
+
* Licensed under MIT (https://github.com/coreui/coreui/blob/main/LICENSE)
|
|
6
|
+
*
|
|
7
|
+
* This component is a modified version of the Bootstrap's base-component.js
|
|
8
|
+
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
|
9
|
+
* --------------------------------------------------------------------------
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import Data from './dom/data.js'
|
|
13
|
+
import EventHandler from './dom/event-handler.js'
|
|
14
|
+
import Config from './util/config.js'
|
|
15
|
+
import { executeAfterTransition, getElement } from './util/index.js'
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Constants
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const VERSION = '0.1.0'
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Class definition
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
class BaseComponent extends Config {
|
|
28
|
+
constructor(element, config) {
|
|
29
|
+
super()
|
|
30
|
+
|
|
31
|
+
element = getElement(element)
|
|
32
|
+
if (!element) {
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
this._element = element
|
|
37
|
+
this._config = this._getConfig(config)
|
|
38
|
+
|
|
39
|
+
Data.set(this._element, this.constructor.DATA_KEY, this)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Public
|
|
43
|
+
dispose() {
|
|
44
|
+
Data.remove(this._element, this.constructor.DATA_KEY)
|
|
45
|
+
EventHandler.off(this._element, this.constructor.EVENT_KEY)
|
|
46
|
+
|
|
47
|
+
for (const propertyName of Object.getOwnPropertyNames(this)) {
|
|
48
|
+
this[propertyName] = null
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Private
|
|
53
|
+
_queueCallback(callback, element, isAnimated = true) {
|
|
54
|
+
executeAfterTransition(callback, element, isAnimated)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
_getConfig(config) {
|
|
58
|
+
config = this._mergeConfigObj(config, this._element)
|
|
59
|
+
config = this._configAfterMerge(config)
|
|
60
|
+
this._typeCheckConfig(config)
|
|
61
|
+
return config
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Static
|
|
65
|
+
static getInstance(element) {
|
|
66
|
+
return Data.get(getElement(element), this.DATA_KEY)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static getOrCreateInstance(element, config = {}) {
|
|
70
|
+
return this.getInstance(element) || new this(element, typeof config === 'object' ? config : null)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static get VERSION() {
|
|
74
|
+
return VERSION
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
static get DATA_KEY() {
|
|
78
|
+
return `coreui.${this.NAME}`
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
static get EVENT_KEY() {
|
|
82
|
+
return `.${this.DATA_KEY}`
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
static eventName(name) {
|
|
86
|
+
return `${name}${this.EVENT_KEY}`
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export default BaseComponent
|