@budibase/bbui 1.0.80 → 1.0.81-alpha.2

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,8 +3,9 @@
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 } from "lodash"
7
- import { deepGet } from "../helpers"
6
+ import { cloneDeep, deepGet } from "../helpers"
7
+ import ProgressCircle from "../ProgressCircle/ProgressCircle.svelte"
8
+ import Checkbox from "../Form/Checkbox.svelte"
8
9
 
9
10
  /**
10
11
  * The expected schema is our normal couch schemas for our tables.
@@ -15,6 +16,11 @@
15
16
  * sortable: Set to false to disable sorting data by a certain column
16
17
  * editable: Set to false to disable editing a certain column if the
17
18
  * 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
18
24
  */
19
25
  export let data = []
20
26
  export let schema = {}
@@ -26,16 +32,16 @@
26
32
  export let allowEditRows = true
27
33
  export let allowEditColumns = true
28
34
  export let selectedRows = []
29
- export let editColumnTitle = "Edit"
30
35
  export let customRenderers = []
31
36
  export let disableSorting = false
37
+ export let autoSortColumns = true
38
+ export let compact = false
32
39
 
33
40
  const dispatch = createEventDispatcher()
34
41
 
35
42
  // Config
36
- const rowHeight = 55
37
43
  const headerHeight = 36
38
- const rowPreload = 5
44
+ $: rowHeight = compact ? 46 : 55
39
45
 
40
46
  // Sorting state
41
47
  let sortColumn
@@ -44,33 +50,33 @@
44
50
  // Table state
45
51
  let height = 0
46
52
  let loaded = false
53
+ let checkboxStatus = false
54
+
47
55
  $: schema = fixSchema(schema)
48
56
  $: if (!loading) loaded = true
49
- $: rows = data ?? []
50
- $: visibleRowCount = getVisibleRowCount(loaded, height, rows.length, rowCount)
51
- $: contentStyle = getContentStyle(visibleRowCount, rowCount)
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)
52
67
  $: sortedRows = sortRows(rows, sortColumn, sortOrder)
53
- $: fields = getFields(schema, showAutoColumns)
68
+ $: gridStyle = getGridStyle(fields, schema, showEditColumn)
54
69
  $: showEditColumn = allowEditRows || allowSelectRows
70
+ $: cellStyles = computeCellStyles(schema)
55
71
 
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
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
+ }
74
80
  }
75
81
 
76
82
  const fixSchema = schema => {
@@ -91,7 +97,7 @@
91
97
  return fixedSchema
92
98
  }
93
99
 
94
- const getVisibleRowCount = (loaded, height, allRows, rowCount) => {
100
+ const getVisibleRowCount = (loaded, height, allRows, rowCount, rowHeight) => {
95
101
  if (!loaded) {
96
102
  return rowCount || 0
97
103
  }
@@ -101,11 +107,28 @@
101
107
  return Math.min(allRows, Math.ceil(height / rowHeight))
102
108
  }
103
109
 
104
- const getContentStyle = (visibleRows, rowCount) => {
110
+ const getContentStyle = (visibleRows, rowCount, rowHeight) => {
105
111
  if (!rowCount || !visibleRows) {
106
112
  return ""
107
113
  }
108
- return `height: ${headerHeight + visibleRows * (rowHeight + 1)}px;`
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
109
132
  }
110
133
 
111
134
  const sortRows = (rows, sortColumn, sortOrder) => {
@@ -144,14 +167,14 @@
144
167
  return name || ""
145
168
  }
146
169
 
147
- const getFields = (schema, showAutoColumns) => {
170
+ const getFields = (schema, showAutoColumns, autoSortColumns) => {
148
171
  let columns = []
149
172
  let autoColumns = []
150
173
  Object.entries(schema || {}).forEach(([field, fieldSchema]) => {
151
174
  if (!field || !fieldSchema) {
152
175
  return
153
176
  }
154
- if (!fieldSchema?.autocolumn) {
177
+ if (!autoSortColumns || !fieldSchema?.autocolumn) {
155
178
  columns.push(fieldSchema)
156
179
  } else if (showAutoColumns) {
157
180
  autoColumns.push(fieldSchema)
@@ -172,28 +195,6 @@
172
195
  .map(column => column.name)
173
196
  }
174
197
 
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
-
197
198
  const editColumn = (e, field) => {
198
199
  e.stopPropagation()
199
200
  dispatch("editcolumn", field)
@@ -208,176 +209,270 @@
208
209
  if (!allowSelectRows) {
209
210
  return
210
211
  }
211
- if (selectedRows.includes(row)) {
212
- selectedRows = selectedRows.filter(selectedRow => selectedRow !== row)
212
+ if (selectedRows.some(selectedRow => selectedRow._id === row._id)) {
213
+ selectedRows = selectedRows.filter(
214
+ selectedRow => selectedRow._id !== row._id
215
+ )
213
216
  } else {
214
217
  selectedRows = [...selectedRows, row]
215
218
  }
216
219
  }
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
+ }
217
257
  </script>
218
258
 
219
- <div class="wrapper" bind:offsetHeight={height}>
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
+ >
220
266
  {#if !loaded}
221
- <div class="loading" style={contentStyle} />
267
+ <div class="loading" style={contentStyle}>
268
+ <ProgressCircle />
269
+ </div>
222
270
  {:else}
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>
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>
284
287
  {/if}
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}
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)}
293
325
  >
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>
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>
353
358
  {/if}
354
- </tbody>
355
- </table>
356
- </div>
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}
357
388
  </div>
358
389
  {/if}
359
390
  </div>
360
391
 
361
392
  <style>
393
+ /* Wrapper */
362
394
  .wrapper {
363
- background-color: var(--spectrum-alias-background-color-secondary);
364
- overflow: hidden;
365
395
  position: relative;
366
396
  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);
367
400
  }
368
-
369
- .container {
370
- height: 100%;
371
- position: relative;
372
- overflow: auto;
401
+ .wrapper--quiet {
402
+ --table-bg: var(--spectrum-alias-background-color-transparent);
373
403
  }
374
- .container.quiet {
375
- border: none;
404
+ .wrapper--compact {
405
+ --cell-padding: var(--spectrum-global-dimension-size-150);
406
+ }
407
+
408
+ /* Loading */
409
+ .loading {
410
+ display: grid;
411
+ place-items: center;
412
+ min-height: 100px;
376
413
  }
377
- table {
414
+
415
+ /* Table */
416
+ .spectrum-Table {
378
417
  width: 100%;
418
+ border-radius: 0;
419
+ display: grid;
420
+ overflow: auto;
379
421
  }
380
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;
471
+ }
472
+ .spectrum-Table-headCell:hover .spectrum-Table-editIcon {
473
+ opacity: 1;
474
+ transition: opacity 0.2s ease;
475
+ }
381
476
  .spectrum-Table-headCell .spectrum-Icon {
382
477
  pointer-events: all;
383
478
  margin-left: var(
@@ -393,63 +488,93 @@
393
488
  .spectrum-Table-editIcon {
394
489
  opacity: 0;
395
490
  }
396
- .spectrum-Table-headCell:hover .spectrum-Table-editIcon {
397
- opacity: 1;
398
- transition: opacity 0.2s ease;
399
- }
400
491
 
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));
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);
410
501
  }
411
- .spectrum-Table-headCell-content {
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);
513
+ }
514
+
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;
412
523
  white-space: nowrap;
524
+ height: var(--row-height);
413
525
  display: flex;
414
526
  flex-direction: row;
415
527
  justify-content: flex-start;
416
528
  align-items: center;
417
- user-select: none;
418
- }
419
- .spectrum-Table-headCell-content .title {
420
- overflow: hidden;
421
- text-overflow: ellipsis;
529
+ gap: 4px;
530
+ border-bottom: 1px solid var(--spectrum-alias-border-color-mid);
531
+ background-color: var(--table-bg);
532
+ z-index: 1;
422
533
  }
423
-
424
- .placeholder-row {
425
- position: relative;
426
- height: 150px;
534
+ .spectrum-Table-cell--divider {
535
+ padding-right: var(--cell-padding);
427
536
  }
428
- .placeholder-row td {
429
- border-top: none !important;
430
- border-bottom: none !important;
537
+ .spectrum-Table-cell--divider + .spectrum-Table-cell {
538
+ padding-left: var(--cell-padding);
431
539
  }
432
- .placeholder-offset {
433
- width: 1px;
540
+ .spectrum-Table-cell--edit {
541
+ position: sticky;
542
+ left: 0;
543
+ z-index: 2;
434
544
  }
435
- .placeholder {
436
- top: 0;
545
+ .spectrum-Table-cell:after {
546
+ content: "";
547
+ position: absolute;
548
+ width: 100%;
437
549
  height: 100%;
550
+ background-color: transparent;
551
+ top: 0;
438
552
  left: 0;
439
- width: 100%;
440
- position: absolute;
553
+ pointer-events: none;
554
+ transition: background-color
555
+ var(--spectrum-global-animation-duration-100, 0.13s) ease-in-out;
556
+ }
557
+
558
+ /* Placeholder */
559
+ .placeholder {
441
560
  display: flex;
442
561
  flex-direction: row;
443
562
  justify-content: center;
444
563
  align-items: center;
564
+ border: var(--table-border);
565
+ border-top: none;
566
+ grid-column: 1 / -1;
567
+ background-color: var(--table-bg);
445
568
  }
446
- .placeholder.has-fields {
447
- top: var(--header-height);
448
- height: calc(100% - var(--header-height));
569
+ .placeholder--no-fields {
570
+ border-top: var(--table-border);
571
+ }
572
+ .wrapper--quiet .placeholder {
573
+ border-left: none;
574
+ border-right: none;
449
575
  }
450
-
451
576
  .placeholder-content {
452
- padding: 20px;
577
+ padding: 40px;
453
578
  display: flex;
454
579
  flex-direction: column;
455
580
  justify-content: center;
@@ -467,41 +592,4 @@
467
592
  );
468
593
  text-align: center;
469
594
  }
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
- }
507
595
  </style>