@budibase/bbui 1.0.80-alpha.1 → 1.0.80

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.
@@ -3,9 +3,8 @@
3
3
  import "@spectrum-css/table/dist/index-vars.css"
4
4
  import CellRenderer from "./CellRenderer.svelte"
5
5
  import SelectEditRenderer from "./SelectEditRenderer.svelte"
6
- import { cloneDeep, deepGet } from "../helpers"
7
- import ProgressCircle from "../ProgressCircle/ProgressCircle.svelte"
8
- import Checkbox from "../Form/Checkbox.svelte"
6
+ import { cloneDeep } from "lodash"
7
+ import { deepGet } from "../helpers"
9
8
 
10
9
  /**
11
10
  * The expected schema is our normal couch schemas for our tables.
@@ -16,11 +15,6 @@
16
15
  * sortable: Set to false to disable sorting data by a certain column
17
16
  * editable: Set to false to disable editing a certain column if the
18
17
  * allowEditColumns prop is true
19
- * width: the width of the column
20
- * align: the alignment of the column
21
- * template: a HBS or JS binding to use as the value
22
- * background: the background color
23
- * color: the text color
24
18
  */
25
19
  export let data = []
26
20
  export let schema = {}
@@ -32,16 +26,16 @@
32
26
  export let allowEditRows = true
33
27
  export let allowEditColumns = true
34
28
  export let selectedRows = []
29
+ export let editColumnTitle = "Edit"
35
30
  export let customRenderers = []
36
31
  export let disableSorting = false
37
- export let autoSortColumns = true
38
- export let compact = false
39
32
 
40
33
  const dispatch = createEventDispatcher()
41
34
 
42
35
  // Config
36
+ const rowHeight = 55
43
37
  const headerHeight = 36
44
- $: rowHeight = compact ? 46 : 55
38
+ const rowPreload = 5
45
39
 
46
40
  // Sorting state
47
41
  let sortColumn
@@ -50,33 +44,33 @@
50
44
  // Table state
51
45
  let height = 0
52
46
  let loaded = false
53
- let checkboxStatus = false
54
-
55
47
  $: schema = fixSchema(schema)
56
48
  $: if (!loading) loaded = true
57
- $: fields = getFields(schema, showAutoColumns, autoSortColumns)
58
- $: rows = fields?.length ? data || [] : []
59
- $: visibleRowCount = getVisibleRowCount(
60
- loaded,
61
- height,
62
- rows.length,
63
- rowCount,
64
- rowHeight
65
- )
66
- $: contentStyle = getContentStyle(visibleRowCount, rowCount, rowHeight)
49
+ $: rows = data ?? []
50
+ $: visibleRowCount = getVisibleRowCount(loaded, height, rows.length, rowCount)
51
+ $: contentStyle = getContentStyle(visibleRowCount, rowCount)
67
52
  $: sortedRows = sortRows(rows, sortColumn, sortOrder)
68
- $: gridStyle = getGridStyle(fields, schema, showEditColumn)
53
+ $: fields = getFields(schema, showAutoColumns)
69
54
  $: showEditColumn = allowEditRows || allowSelectRows
70
- $: cellStyles = computeCellStyles(schema)
71
55
 
72
- // Deselect the "select all" checkbox when the user navigates to a new page
73
- $: {
74
- let checkRowCount = rows.filter(o1 =>
75
- selectedRows.some(o2 => o1._id === o2._id)
76
- )
77
- if (checkRowCount.length === 0) {
78
- checkboxStatus = false
79
- }
56
+ // Scrolling state
57
+ let timeout
58
+ let nextScrollTop = 0
59
+ let scrollTop = 0
60
+ $: firstVisibleRow = calculateFirstVisibleRow(scrollTop)
61
+ $: lastVisibleRow = calculateLastVisibleRow(
62
+ firstVisibleRow,
63
+ visibleRowCount,
64
+ rows.length
65
+ )
66
+
67
+ // Reset state when data changes
68
+ $: rows.length, reset()
69
+ const reset = () => {
70
+ nextScrollTop = 0
71
+ scrollTop = 0
72
+ clearTimeout(timeout)
73
+ timeout = null
80
74
  }
81
75
 
82
76
  const fixSchema = schema => {
@@ -97,7 +91,7 @@
97
91
  return fixedSchema
98
92
  }
99
93
 
100
- const getVisibleRowCount = (loaded, height, allRows, rowCount, rowHeight) => {
94
+ const getVisibleRowCount = (loaded, height, allRows, rowCount) => {
101
95
  if (!loaded) {
102
96
  return rowCount || 0
103
97
  }
@@ -107,28 +101,11 @@
107
101
  return Math.min(allRows, Math.ceil(height / rowHeight))
108
102
  }
109
103
 
110
- const getContentStyle = (visibleRows, rowCount, rowHeight) => {
104
+ const getContentStyle = (visibleRows, rowCount) => {
111
105
  if (!rowCount || !visibleRows) {
112
106
  return ""
113
107
  }
114
- return `height: ${headerHeight + visibleRows * rowHeight}px;`
115
- }
116
-
117
- const getGridStyle = (fields, schema, showEditColumn) => {
118
- let style = "grid-template-columns:"
119
- if (showEditColumn) {
120
- style += " auto"
121
- }
122
- fields?.forEach(field => {
123
- const fieldSchema = schema[field]
124
- if (fieldSchema.width) {
125
- style += ` ${fieldSchema.width}`
126
- } else {
127
- style += " minmax(auto, 1fr)"
128
- }
129
- })
130
- style += ";"
131
- return style
108
+ return `height: ${headerHeight + visibleRows * (rowHeight + 1)}px;`
132
109
  }
133
110
 
134
111
  const sortRows = (rows, sortColumn, sortOrder) => {
@@ -167,14 +144,14 @@
167
144
  return name || ""
168
145
  }
169
146
 
170
- const getFields = (schema, showAutoColumns, autoSortColumns) => {
147
+ const getFields = (schema, showAutoColumns) => {
171
148
  let columns = []
172
149
  let autoColumns = []
173
150
  Object.entries(schema || {}).forEach(([field, fieldSchema]) => {
174
151
  if (!field || !fieldSchema) {
175
152
  return
176
153
  }
177
- if (!autoSortColumns || !fieldSchema?.autocolumn) {
154
+ if (!fieldSchema?.autocolumn) {
178
155
  columns.push(fieldSchema)
179
156
  } else if (showAutoColumns) {
180
157
  autoColumns.push(fieldSchema)
@@ -195,6 +172,28 @@
195
172
  .map(column => column.name)
196
173
  }
197
174
 
175
+ const onScroll = event => {
176
+ nextScrollTop = event.target.scrollTop
177
+ if (timeout) {
178
+ return
179
+ }
180
+ timeout = setTimeout(() => {
181
+ scrollTop = nextScrollTop
182
+ timeout = null
183
+ }, 50)
184
+ }
185
+
186
+ const calculateFirstVisibleRow = scrollTop => {
187
+ return Math.max(Math.floor(scrollTop / (rowHeight + 1)) - rowPreload, 0)
188
+ }
189
+
190
+ const calculateLastVisibleRow = (firstRow, visibleRowCount, allRowCount) => {
191
+ if (visibleRowCount === 0) {
192
+ return -1
193
+ }
194
+ return Math.min(firstRow + visibleRowCount + 2 * rowPreload, allRowCount)
195
+ }
196
+
198
197
  const editColumn = (e, field) => {
199
198
  e.stopPropagation()
200
199
  dispatch("editcolumn", field)
@@ -209,270 +208,176 @@
209
208
  if (!allowSelectRows) {
210
209
  return
211
210
  }
212
- if (selectedRows.some(selectedRow => selectedRow._id === row._id)) {
213
- selectedRows = selectedRows.filter(
214
- selectedRow => selectedRow._id !== row._id
215
- )
211
+ if (selectedRows.includes(row)) {
212
+ selectedRows = selectedRows.filter(selectedRow => selectedRow !== row)
216
213
  } else {
217
214
  selectedRows = [...selectedRows, row]
218
215
  }
219
216
  }
220
-
221
- const toggleSelectAll = e => {
222
- const select = !!e.detail
223
- if (select) {
224
- // Add any rows which are not already in selected rows
225
- rows.forEach(row => {
226
- if (selectedRows.findIndex(x => x._id === row._id) === -1) {
227
- selectedRows.push(row)
228
- }
229
- })
230
- } else {
231
- // Remove any rows from selected rows that are in the current data set
232
- selectedRows = selectedRows.filter(el =>
233
- rows.every(f => f._id !== el._id)
234
- )
235
- }
236
- }
237
-
238
- const computeCellStyles = schema => {
239
- let styles = {}
240
- Object.keys(schema || {}).forEach(field => {
241
- styles[field] = ""
242
- if (schema[field].color) {
243
- styles[field] += `color: ${schema[field].color};`
244
- }
245
- if (schema[field].background) {
246
- styles[field] += `background-color: ${schema[field].background};`
247
- }
248
- if (schema[field].align === "Center") {
249
- styles[field] += "justify-content: center; text-align: center;"
250
- }
251
- if (schema[field].align === "Right") {
252
- styles[field] += "justify-content: flex-end; text-align: right;"
253
- }
254
- })
255
- return styles
256
- }
257
217
  </script>
258
218
 
259
- <div
260
- class="wrapper"
261
- class:wrapper--quiet={quiet}
262
- class:wrapper--compact={compact}
263
- bind:offsetHeight={height}
264
- style={`--row-height: ${rowHeight}px; --header-height: ${headerHeight}px;`}
265
- >
219
+ <div class="wrapper" bind:offsetHeight={height}>
266
220
  {#if !loaded}
267
- <div class="loading" style={contentStyle}>
268
- <ProgressCircle />
269
- </div>
221
+ <div class="loading" style={contentStyle} />
270
222
  {:else}
271
- <div class="spectrum-Table" style={`${contentStyle}${gridStyle}`}>
272
- {#if fields.length}
273
- <div class="spectrum-Table-head">
274
- {#if showEditColumn}
275
- <div
276
- class="spectrum-Table-headCell spectrum-Table-headCell--divider spectrum-Table-headCell--edit"
277
- >
278
- {#if allowSelectRows}
279
- <Checkbox
280
- bind:value={checkboxStatus}
281
- on:change={toggleSelectAll}
282
- />
283
- {:else}
284
- Edit
285
- {/if}
286
- </div>
223
+ <div
224
+ on:scroll={onScroll}
225
+ class:quiet
226
+ style={`--row-height: ${rowHeight}px; --header-height: ${headerHeight}px;`}
227
+ class="container"
228
+ >
229
+ <div style={contentStyle}>
230
+ <table class="spectrum-Table" class:spectrum-Table--quiet={quiet}>
231
+ {#if fields.length}
232
+ <thead class="spectrum-Table-head">
233
+ <tr>
234
+ {#if showEditColumn}
235
+ <th class="spectrum-Table-headCell">
236
+ <div class="spectrum-Table-headCell-content">
237
+ {editColumnTitle || ""}
238
+ </div>
239
+ </th>
240
+ {/if}
241
+ {#each fields as field}
242
+ <th
243
+ class="spectrum-Table-headCell"
244
+ class:is-sortable={schema[field].sortable !== false}
245
+ class:is-sorted-desc={sortColumn === field &&
246
+ sortOrder === "Descending"}
247
+ class:is-sorted-asc={sortColumn === field &&
248
+ sortOrder === "Ascending"}
249
+ on:click={() => sortBy(schema[field])}
250
+ >
251
+ <div class="spectrum-Table-headCell-content">
252
+ <div class="title">{getDisplayName(schema[field])}</div>
253
+ {#if schema[field]?.autocolumn}
254
+ <svg
255
+ class="spectrum-Icon spectrum-Table-autoIcon"
256
+ focusable="false"
257
+ >
258
+ <use xlink:href="#spectrum-icon-18-MagicWand" />
259
+ </svg>
260
+ {/if}
261
+ {#if sortColumn === field}
262
+ <svg
263
+ class="spectrum-Icon spectrum-UIIcon-ArrowDown100 spectrum-Table-sortedIcon"
264
+ focusable="false"
265
+ aria-hidden="true"
266
+ >
267
+ <use xlink:href="#spectrum-css-icon-Arrow100" />
268
+ </svg>
269
+ {/if}
270
+ {#if allowEditColumns && schema[field]?.editable !== false}
271
+ <svg
272
+ class="spectrum-Icon spectrum-Table-editIcon"
273
+ focusable="false"
274
+ on:click={e => editColumn(e, field)}
275
+ >
276
+ <use xlink:href="#spectrum-icon-18-Edit" />
277
+ </svg>
278
+ {/if}
279
+ </div>
280
+ </th>
281
+ {/each}
282
+ </tr>
283
+ </thead>
287
284
  {/if}
288
- {#each fields as field}
289
- <div
290
- class="spectrum-Table-headCell"
291
- class:spectrum-Table-headCell--alignCenter={schema[field]
292
- .align === "Center"}
293
- class:spectrum-Table-headCell--alignRight={schema[field].align ===
294
- "Right"}
295
- class:is-sortable={schema[field].sortable !== false}
296
- class:is-sorted-desc={sortColumn === field &&
297
- sortOrder === "Descending"}
298
- class:is-sorted-asc={sortColumn === field &&
299
- sortOrder === "Ascending"}
300
- on:click={() => sortBy(schema[field])}
301
- >
302
- <div class="title">{getDisplayName(schema[field])}</div>
303
- {#if schema[field]?.autocolumn}
304
- <svg
305
- class="spectrum-Icon spectrum-Table-autoIcon"
306
- focusable="false"
307
- >
308
- <use xlink:href="#spectrum-icon-18-MagicWand" />
309
- </svg>
310
- {/if}
311
- {#if sortColumn === field}
312
- <svg
313
- class="spectrum-Icon spectrum-UIIcon-ArrowDown100 spectrum-Table-sortedIcon"
314
- focusable="false"
315
- aria-hidden="true"
316
- >
317
- <use xlink:href="#spectrum-css-icon-Arrow100" />
318
- </svg>
319
- {/if}
320
- {#if allowEditColumns && schema[field]?.editable !== false}
321
- <svg
322
- class="spectrum-Icon spectrum-Table-editIcon"
323
- focusable="false"
324
- on:click={e => editColumn(e, field)}
285
+ <tbody class="spectrum-Table-body">
286
+ {#if sortedRows?.length && fields.length}
287
+ {#each sortedRows as row, idx}
288
+ <tr
289
+ on:click={() => dispatch("click", row)}
290
+ on:click={() => toggleSelectRow(row)}
291
+ class="spectrum-Table-row"
292
+ class:hidden={idx < firstVisibleRow || idx > lastVisibleRow}
325
293
  >
326
- <use xlink:href="#spectrum-icon-18-Edit" />
327
- </svg>
328
- {/if}
329
- </div>
330
- {/each}
331
- </div>
332
- {/if}
333
- {#if sortedRows?.length}
334
- {#each sortedRows as row, idx}
335
- <div
336
- class="spectrum-Table-row"
337
- on:click={() => dispatch("click", row)}
338
- on:click={() => toggleSelectRow(row)}
339
- >
340
- {#if showEditColumn}
341
- <div
342
- class="spectrum-Table-cell spectrum-Table-cell--divider spectrum-Table-cell--edit"
343
- on:click={e => {
344
- toggleSelectRow(row)
345
- e.stopPropagation()
346
- }}
347
- >
348
- <SelectEditRenderer
349
- data={row}
350
- selected={selectedRows.findIndex(
351
- selectedRow => selectedRow._id === row._id
352
- ) !== -1}
353
- onEdit={e => editRow(e, row)}
354
- {allowSelectRows}
355
- {allowEditRows}
356
- />
357
- </div>
294
+ {#if idx >= firstVisibleRow && idx <= lastVisibleRow}
295
+ {#if showEditColumn}
296
+ <td
297
+ class="spectrum-Table-cell spectrum-Table-cell--divider"
298
+ >
299
+ <div class="spectrum-Table-cell-content">
300
+ <SelectEditRenderer
301
+ data={row}
302
+ selected={selectedRows.includes(row)}
303
+ onToggleSelection={() => toggleSelectRow(row)}
304
+ onEdit={e => editRow(e, row)}
305
+ {allowSelectRows}
306
+ {allowEditRows}
307
+ />
308
+ </div>
309
+ </td>
310
+ {/if}
311
+ {#each fields as field}
312
+ <td
313
+ class="spectrum-Table-cell"
314
+ class:spectrum-Table-cell--divider={!!schema[field]
315
+ .divider}
316
+ >
317
+ <div class="spectrum-Table-cell-content">
318
+ <CellRenderer
319
+ {customRenderers}
320
+ {row}
321
+ schema={schema[field]}
322
+ value={deepGet(row, field)}
323
+ on:clickrelationship
324
+ >
325
+ <slot />
326
+ </CellRenderer>
327
+ </div>
328
+ </td>
329
+ {/each}
330
+ {/if}
331
+ </tr>
332
+ {/each}
333
+ {:else}
334
+ <tr class="placeholder-row">
335
+ {#if showEditColumn}
336
+ <td class="placeholder-offset" />
337
+ {/if}
338
+ {#each fields as field}
339
+ <td />
340
+ {/each}
341
+ <div class="placeholder" class:has-fields={fields.length > 0}>
342
+ <div class="placeholder-content">
343
+ <svg
344
+ class="spectrum-Icon spectrum-Icon--sizeXXL"
345
+ focusable="false"
346
+ >
347
+ <use xlink:href="#spectrum-icon-18-Table" />
348
+ </svg>
349
+ <div>No rows found</div>
350
+ </div>
351
+ </div>
352
+ </tr>
358
353
  {/if}
359
- {#each fields as field}
360
- <div
361
- class="spectrum-Table-cell"
362
- class:spectrum-Table-cell--divider={!!schema[field].divider}
363
- style={cellStyles[field]}
364
- >
365
- <CellRenderer
366
- {customRenderers}
367
- {row}
368
- schema={schema[field]}
369
- value={deepGet(row, field)}
370
- on:clickrelationship
371
- >
372
- <slot />
373
- </CellRenderer>
374
- </div>
375
- {/each}
376
- </div>
377
- {/each}
378
- {:else}
379
- <div class="placeholder" class:placeholder--no-fields={!fields?.length}>
380
- <div class="placeholder-content">
381
- <svg class="spectrum-Icon spectrum-Icon--sizeXXL" focusable="false">
382
- <use xlink:href="#spectrum-icon-18-Table" />
383
- </svg>
384
- <div>No rows found</div>
385
- </div>
386
- </div>
387
- {/if}
354
+ </tbody>
355
+ </table>
356
+ </div>
388
357
  </div>
389
358
  {/if}
390
359
  </div>
391
360
 
392
361
  <style>
393
- /* Wrapper */
394
362
  .wrapper {
363
+ background-color: var(--spectrum-alias-background-color-secondary);
364
+ overflow: hidden;
395
365
  position: relative;
396
366
  z-index: 0;
397
- --table-bg: var(--spectrum-global-color-gray-50);
398
- --table-border: 1px solid var(--spectrum-alias-border-color-mid);
399
- --cell-padding: var(--spectrum-global-dimension-size-250);
400
- }
401
- .wrapper--quiet {
402
- --table-bg: var(--spectrum-alias-background-color-transparent);
403
- }
404
- .wrapper--compact {
405
- --cell-padding: var(--spectrum-global-dimension-size-150);
406
367
  }
407
368
 
408
- /* Loading */
409
- .loading {
410
- display: grid;
411
- place-items: center;
412
- min-height: 100px;
413
- }
414
-
415
- /* Table */
416
- .spectrum-Table {
417
- width: 100%;
418
- border-radius: 0;
419
- display: grid;
369
+ .container {
370
+ height: 100%;
371
+ position: relative;
420
372
  overflow: auto;
421
373
  }
422
-
423
- /* Header */
424
- .spectrum-Table-head {
425
- display: contents;
426
- }
427
- .spectrum-Table-head > :first-child {
428
- border-left: 1px solid transparent;
429
- padding-left: var(--cell-padding);
430
- }
431
- .spectrum-Table-head > :last-child {
432
- border-right: 1px solid transparent;
433
- padding-right: var(--cell-padding);
434
- }
435
- .spectrum-Table-headCell {
436
- height: var(--header-height);
437
- position: sticky;
438
- top: 0;
439
- text-overflow: ellipsis;
440
- white-space: nowrap;
441
- background-color: var(--spectrum-alias-background-color-secondary);
442
- z-index: 2;
443
- border-bottom: var(--table-border);
444
- padding: 0 calc(var(--cell-padding) / 1.33);
445
- display: flex;
446
- flex-direction: row;
447
- justify-content: flex-start;
448
- align-items: center;
449
- user-select: none;
450
- }
451
- .spectrum-Table-headCell--alignCenter {
452
- justify-content: center;
453
- }
454
- .spectrum-Table-headCell--alignRight {
455
- justify-content: flex-end;
456
- }
457
- .spectrum-Table-headCell--divider {
458
- padding-right: var(--cell-padding);
459
- }
460
- .spectrum-Table-headCell--divider + .spectrum-Table-headCell {
461
- padding-left: var(--cell-padding);
462
- }
463
- .spectrum-Table-headCell--edit {
464
- position: sticky;
465
- left: 0;
466
- z-index: 3;
467
- }
468
- .spectrum-Table-headCell .title {
469
- overflow: hidden;
470
- text-overflow: ellipsis;
374
+ .container.quiet {
375
+ border: none;
471
376
  }
472
- .spectrum-Table-headCell:hover .spectrum-Table-editIcon {
473
- opacity: 1;
474
- transition: opacity 0.2s ease;
377
+ table {
378
+ width: 100%;
475
379
  }
380
+
476
381
  .spectrum-Table-headCell .spectrum-Icon {
477
382
  pointer-events: all;
478
383
  margin-left: var(
@@ -488,93 +393,63 @@
488
393
  .spectrum-Table-editIcon {
489
394
  opacity: 0;
490
395
  }
491
-
492
- /* Table rows */
493
- .spectrum-Table-row {
494
- display: contents;
495
- }
496
- .spectrum-Table-row:hover .spectrum-Table-cell {
497
- /*background-color: var(--hover-bg) !important;*/
498
- }
499
- .spectrum-Table-row:hover .spectrum-Table-cell:after {
500
- background-color: var(--spectrum-alias-highlight-hover);
501
- }
502
- .wrapper--quiet .spectrum-Table-row {
503
- border-left: none;
504
- border-right: none;
505
- }
506
- .spectrum-Table-row > :first-child {
507
- border-left: var(--table-border);
508
- padding-left: var(--cell-padding);
509
- }
510
- .spectrum-Table-row > :last-child {
511
- border-right: var(--table-border);
512
- padding-right: var(--cell-padding);
396
+ .spectrum-Table-headCell:hover .spectrum-Table-editIcon {
397
+ opacity: 1;
398
+ transition: opacity 0.2s ease;
513
399
  }
514
400
 
515
- /* Table cells */
516
- .spectrum-Table-cell {
517
- flex: 1 1 auto;
518
- padding: 0 calc(var(--cell-padding) / 1.33);
519
- border-top: none;
520
- border-bottom: none;
521
- border-radius: 0;
522
- text-overflow: ellipsis;
401
+ th {
402
+ vertical-align: middle;
403
+ height: var(--header-height);
404
+ position: sticky;
405
+ top: 0;
406
+ z-index: 2;
407
+ background-color: var(--spectrum-alias-background-color-secondary);
408
+ border-bottom: 1px solid
409
+ var(--spectrum-table-border-color, var(--spectrum-alias-border-color-mid));
410
+ }
411
+ .spectrum-Table-headCell-content {
523
412
  white-space: nowrap;
524
- height: var(--row-height);
525
413
  display: flex;
526
414
  flex-direction: row;
527
415
  justify-content: flex-start;
528
416
  align-items: center;
529
- gap: 4px;
530
- border-bottom: 1px solid var(--spectrum-alias-border-color-mid);
531
- background-color: var(--table-bg);
532
- z-index: 1;
417
+ user-select: none;
533
418
  }
534
- .spectrum-Table-cell--divider {
535
- padding-right: var(--cell-padding);
419
+ .spectrum-Table-headCell-content .title {
420
+ overflow: hidden;
421
+ text-overflow: ellipsis;
536
422
  }
537
- .spectrum-Table-cell--divider + .spectrum-Table-cell {
538
- padding-left: var(--cell-padding);
423
+
424
+ .placeholder-row {
425
+ position: relative;
426
+ height: 150px;
539
427
  }
540
- .spectrum-Table-cell--edit {
541
- position: sticky;
542
- left: 0;
543
- z-index: 2;
428
+ .placeholder-row td {
429
+ border-top: none !important;
430
+ border-bottom: none !important;
544
431
  }
545
- .spectrum-Table-cell:after {
546
- content: "";
547
- position: absolute;
548
- width: 100%;
549
- height: 100%;
550
- background-color: transparent;
551
- top: 0;
552
- left: 0;
553
- pointer-events: none;
554
- transition: background-color
555
- var(--spectrum-global-animation-duration-100, 0.13s) ease-in-out;
432
+ .placeholder-offset {
433
+ width: 1px;
556
434
  }
557
-
558
- /* Placeholder */
559
435
  .placeholder {
436
+ top: 0;
437
+ height: 100%;
438
+ left: 0;
439
+ width: 100%;
440
+ position: absolute;
560
441
  display: flex;
561
442
  flex-direction: row;
562
443
  justify-content: center;
563
444
  align-items: center;
564
- border: var(--table-border);
565
- border-top: none;
566
- grid-column: 1 / -1;
567
- background-color: var(--table-bg);
568
- }
569
- .placeholder--no-fields {
570
- border-top: var(--table-border);
571
445
  }
572
- .wrapper--quiet .placeholder {
573
- border-left: none;
574
- border-right: none;
446
+ .placeholder.has-fields {
447
+ top: var(--header-height);
448
+ height: calc(100% - var(--header-height));
575
449
  }
450
+
576
451
  .placeholder-content {
577
- padding: 40px;
452
+ padding: 20px;
578
453
  display: flex;
579
454
  flex-direction: column;
580
455
  justify-content: center;
@@ -592,4 +467,41 @@
592
467
  );
593
468
  text-align: center;
594
469
  }
470
+
471
+ tbody {
472
+ z-index: 1;
473
+ }
474
+ tbody tr {
475
+ height: var(--row-height);
476
+ }
477
+ tbody tr.hidden {
478
+ height: calc(var(--row-height) + 1px);
479
+ }
480
+ td {
481
+ padding-top: 0;
482
+ padding-bottom: 0;
483
+ border-bottom: none;
484
+ border-top: 1px solid
485
+ var(--spectrum-table-border-color, var(--spectrum-alias-border-color-mid));
486
+ border-radius: 0;
487
+ }
488
+ tr:first-child td {
489
+ border-top: none;
490
+ }
491
+ tr:last-child td {
492
+ border-bottom: 1px solid
493
+ var(--spectrum-table-border-color, var(--spectrum-alias-border-color-mid));
494
+ }
495
+ td.spectrum-Table-cell--divider {
496
+ width: 1px;
497
+ }
498
+ .spectrum-Table-cell-content {
499
+ height: var(--row-height);
500
+ white-space: nowrap;
501
+ display: flex;
502
+ flex-direction: row;
503
+ justify-content: flex-start;
504
+ align-items: center;
505
+ gap: 4px;
506
+ }
595
507
  </style>