@budibase/bbui 1.1.1 → 1.1.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.
Files changed (145) hide show
  1. package/LICENSE +375 -0
  2. package/README.md +19 -17
  3. package/dist/bbui.es.js +210 -0
  4. package/dist/bbui.es.js.map +1 -0
  5. package/package.json +71 -26
  6. package/src/ActionButton/ActionButton.svelte +95 -0
  7. package/src/ActionGroup/ActionGroup.svelte +26 -0
  8. package/src/ActionMenu/ActionMenu.svelte +44 -0
  9. package/src/Actions/ClickOutside.svench.svx +30 -0
  10. package/src/Actions/PositionDropdown.svench.svx +81 -0
  11. package/src/Actions/autoresize_textarea.js +14 -0
  12. package/src/Actions/click_outside.js +18 -0
  13. package/src/Actions/position_dropdown.js +66 -0
  14. package/src/Avatar/Avatar.svelte +49 -0
  15. package/src/Badge/Badge.svelte +29 -0
  16. package/src/Banner/Banner.svelte +72 -0
  17. package/src/Banner/BannerDisplay.svelte +31 -0
  18. package/src/Button/Button.svelte +114 -0
  19. package/src/Button/Button.svench +138 -0
  20. package/src/ButtonGroup/ButtonGroup.svelte +30 -0
  21. package/src/ClearButton/ClearButton.svelte +19 -0
  22. package/src/ColorPicker/ColorPicker.svelte +297 -0
  23. package/src/DetailSummary/DetailSummary.svelte +83 -0
  24. package/src/Divider/Divider.svelte +28 -0
  25. package/src/Drawer/Drawer.svelte +112 -0
  26. package/src/Drawer/Drawer.svench +42 -0
  27. package/src/Drawer/DrawerContent.svelte +46 -0
  28. package/src/Form/Checkbox.svelte +23 -0
  29. package/src/Form/Combobox.svelte +45 -0
  30. package/src/Form/Core/Checkbox.svelte +69 -0
  31. package/src/Form/Core/CheckboxGroup.svelte +68 -0
  32. package/src/Form/Core/Combobox.svelte +142 -0
  33. package/src/Form/Core/DatePicker.svelte +242 -0
  34. package/src/Form/Core/Dropzone.svelte +438 -0
  35. package/src/Form/Core/Multiselect.svelte +88 -0
  36. package/src/Form/Core/Picker.svelte +256 -0
  37. package/src/Form/Core/RadioGroup.svelte +47 -0
  38. package/src/Form/Core/RichTextField.svelte +42 -0
  39. package/src/Form/Core/Search.svelte +105 -0
  40. package/src/Form/Core/Select.svelte +76 -0
  41. package/src/Form/Core/Slider.svelte +86 -0
  42. package/src/Form/Core/Stepper.svelte +172 -0
  43. package/src/Form/Core/Switch.svelte +37 -0
  44. package/src/Form/Core/TextArea.svelte +78 -0
  45. package/src/Form/Core/TextField.svelte +119 -0
  46. package/src/Form/Core/index.js +15 -0
  47. package/src/Form/DatePicker.svelte +37 -0
  48. package/src/Form/Dropzone.svelte +40 -0
  49. package/src/Form/Field.svelte +42 -0
  50. package/src/Form/FieldLabel.svelte +32 -0
  51. package/src/Form/Input.svelte +40 -45
  52. package/src/Form/Multiselect.svelte +39 -0
  53. package/src/Form/RadioGroup.svelte +40 -0
  54. package/src/Form/RichTextField.svelte +36 -0
  55. package/src/Form/Search.svelte +36 -0
  56. package/src/Form/Select.svelte +48 -43
  57. package/src/Form/Slider.svelte +24 -0
  58. package/src/Form/Stepper.svelte +45 -0
  59. package/src/Form/TextArea.svelte +29 -44
  60. package/src/Form/Toggle.svelte +23 -0
  61. package/src/Icon/Icon.svelte +86 -0
  62. package/src/IconSideNav/IconSideNav.svelte +14 -0
  63. package/src/IconSideNav/IconSideNavItem.svelte +56 -0
  64. package/src/InlineAlert/InlineAlert.svelte +56 -0
  65. package/src/Label/Label.svelte +20 -0
  66. package/src/Layout/Layout.svelte +94 -0
  67. package/src/Layout/Page.svelte +32 -0
  68. package/src/Link/Link.svelte +22 -0
  69. package/src/List/Items/DetailSummary.svench +46 -8
  70. package/src/Markdown/MarkdownEditor.svelte +60 -0
  71. package/src/Markdown/MarkdownViewer.svelte +70 -0
  72. package/src/Markdown/SpectrumMDE.svelte +184 -0
  73. package/src/Menu/Item.svelte +45 -0
  74. package/src/Menu/Menu.svelte +7 -0
  75. package/src/Menu/Menu.svench +19 -0
  76. package/src/Menu/Section.svelte +10 -0
  77. package/src/Menu/Separator.svelte +1 -0
  78. package/src/Modal/Content.svelte +6 -0
  79. package/src/Modal/CustomContent.svelte +38 -0
  80. package/src/Modal/Modal.svelte +142 -0
  81. package/src/Modal/Modal.svench +117 -0
  82. package/src/Modal/ModalContent.svelte +190 -0
  83. package/src/Modal/QuizModal.svelte +54 -0
  84. package/src/Notification/Notification.svelte +70 -0
  85. package/src/Notification/NotificationDisplay.svelte +43 -0
  86. package/src/Pagination/Pagination.svelte +57 -0
  87. package/src/Popover/Popover.svelte +77 -0
  88. package/src/Popover/Popover.svench +121 -0
  89. package/src/ProgressBar/ProgressBar.svelte +54 -0
  90. package/src/ProgressCircle/ProgressCircle.svelte +62 -0
  91. package/src/SideNavigation/Item.svelte +47 -0
  92. package/src/SideNavigation/Navigation.svelte +12 -0
  93. package/src/StatusLight/StatusLight.svelte +64 -0
  94. package/src/Stores/Notifications.svench.svx +78 -0
  95. package/src/Stores/banner.js +37 -0
  96. package/src/Stores/notifications.js +84 -0
  97. package/src/Table/ArrayRenderer.svelte +17 -0
  98. package/src/Table/AttachmentRenderer.svelte +60 -0
  99. package/src/Table/BoldRenderer.svelte +15 -0
  100. package/src/Table/BooleanRenderer.svelte +42 -0
  101. package/src/Table/CellRenderer.svelte +69 -0
  102. package/src/Table/CodeRenderer.svelte +14 -0
  103. package/src/Table/DateTimeRenderer.svelte +29 -0
  104. package/src/Table/InternalRenderer.svelte +24 -0
  105. package/src/Table/RelationshipRenderer.svelte +40 -0
  106. package/src/Table/SelectEditRenderer.svelte +28 -0
  107. package/src/Table/StringRenderer.svelte +14 -0
  108. package/src/Table/Table.svelte +631 -0
  109. package/src/Table/index.js +1 -0
  110. package/src/Tabs/Tab.svelte +88 -0
  111. package/src/Tabs/Tabs.svelte +125 -0
  112. package/src/Tags/Tag.svelte +43 -0
  113. package/src/Tags/Tags.svelte +7 -0
  114. package/src/Tooltip/Tooltip.svelte +30 -0
  115. package/src/Tooltip/TooltipWrapper.svelte +60 -0
  116. package/src/TreeView/Item.svelte +41 -0
  117. package/src/TreeView/Tree.svelte +16 -0
  118. package/src/Typography/Body.svelte +21 -0
  119. package/src/Typography/Code.svelte +10 -0
  120. package/src/Typography/Detail.svelte +19 -0
  121. package/src/Typography/Heading.svelte +17 -0
  122. package/src/bbui.css +96 -0
  123. package/src/context.js +3 -0
  124. package/src/helpers.js +134 -0
  125. package/src/index.js +91 -11
  126. package/src/spectrum-icons-rollup.js +31 -0
  127. package/src/spectrum-icons-vite.js +31 -0
  128. package/dist/bundle.css +0 -7
  129. package/dist/bundle.css.map +0 -20
  130. package/dist/index.js +0 -1045
  131. package/dist/index.mjs +0 -1031
  132. package/src/Branding/Budibase-logo.svelte +0 -68
  133. package/src/Branding/Logo.svelte +0 -16
  134. package/src/Branding/Logo.svench +0 -8
  135. package/src/Form/Button.svelte +0 -52
  136. package/src/Form/Button.svench +0 -26
  137. package/src/Form/Input.svench +0 -8
  138. package/src/Form/Select.svench +0 -8
  139. package/src/Form/TextArea.svench +0 -8
  140. package/src/Links/Home.svelte +0 -49
  141. package/src/Links/Home.svench +0 -19
  142. package/src/List/Items/DetailSummary.svelte +0 -66
  143. package/src/actions/autoresize_textarea.js +0 -14
  144. package/src/icons/Contribution.svelte +0 -14
  145. package/src/index.svench.svx +0 -35
@@ -0,0 +1,631 @@
1
+ <script>
2
+ import { createEventDispatcher } from "svelte"
3
+ import "@spectrum-css/table/dist/index-vars.css"
4
+ import CellRenderer from "./CellRenderer.svelte"
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"
9
+
10
+ /**
11
+ * The expected schema is our normal couch schemas for our tables.
12
+ * Each field schema can be enriched with a few extra properties to customise
13
+ * the behaviour.
14
+ * All of these are optional and do not need to be added.
15
+ * displayName: Overrides the field name displayed as the column title
16
+ * sortable: Set to false to disable sorting data by a certain column
17
+ * editable: Set to false to disable editing a certain column if the
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
24
+ */
25
+ export let data = []
26
+ export let schema = {}
27
+ export let showAutoColumns = false
28
+ export let rowCount = 0
29
+ export let quiet = false
30
+ export let loading = false
31
+ export let allowSelectRows
32
+ export let allowEditRows = true
33
+ export let allowEditColumns = true
34
+ export let selectedRows = []
35
+ export let customRenderers = []
36
+ export let disableSorting = false
37
+ export let autoSortColumns = true
38
+ export let compact = false
39
+ export let customPlaceholder = false
40
+ export let placeholderText = "No rows found"
41
+
42
+ const dispatch = createEventDispatcher()
43
+
44
+ // Config
45
+ const headerHeight = 36
46
+ $: rowHeight = compact ? 46 : 55
47
+
48
+ // Sorting state
49
+ let sortColumn
50
+ let sortOrder
51
+
52
+ // Table state
53
+ let height = 0
54
+ let loaded = false
55
+ let checkboxStatus = false
56
+
57
+ $: schema = fixSchema(schema)
58
+ $: if (!loading) loaded = true
59
+ $: fields = getFields(schema, showAutoColumns, autoSortColumns)
60
+ $: rows = fields?.length ? data || [] : []
61
+ $: totalRowCount = rows?.length || 0
62
+ $: visibleRowCount = getVisibleRowCount(
63
+ loaded,
64
+ height,
65
+ rows.length,
66
+ rowCount,
67
+ rowHeight
68
+ )
69
+ $: heightStyle = getHeightStyle(
70
+ visibleRowCount,
71
+ rowCount,
72
+ totalRowCount,
73
+ rowHeight
74
+ )
75
+ $: sortedRows = sortRows(rows, sortColumn, sortOrder)
76
+ $: gridStyle = getGridStyle(fields, schema, showEditColumn)
77
+ $: showEditColumn = allowEditRows || allowSelectRows
78
+ $: cellStyles = computeCellStyles(schema)
79
+
80
+ // Deselect the "select all" checkbox when the user navigates to a new page
81
+ $: {
82
+ let checkRowCount = rows.filter(o1 =>
83
+ selectedRows.some(o2 => o1._id === o2._id)
84
+ )
85
+ if (checkRowCount.length === 0) {
86
+ checkboxStatus = false
87
+ }
88
+ }
89
+
90
+ const fixSchema = schema => {
91
+ let fixedSchema = {}
92
+ Object.entries(schema || {}).forEach(([fieldName, fieldSchema]) => {
93
+ if (typeof fieldSchema === "string") {
94
+ fixedSchema[fieldName] = {
95
+ type: fieldSchema,
96
+ name: fieldName,
97
+ }
98
+ } else {
99
+ fixedSchema[fieldName] = {
100
+ ...fieldSchema,
101
+ name: fieldName,
102
+ }
103
+ }
104
+ })
105
+ return fixedSchema
106
+ }
107
+
108
+ const getVisibleRowCount = (loaded, height, allRows, rowCount, rowHeight) => {
109
+ if (!loaded) {
110
+ return rowCount || 0
111
+ }
112
+ if (rowCount) {
113
+ return Math.min(allRows, rowCount)
114
+ }
115
+ return Math.min(allRows, Math.ceil(height / rowHeight))
116
+ }
117
+
118
+ const getHeightStyle = (
119
+ visibleRowCount,
120
+ rowCount,
121
+ totalRowCount,
122
+ rowHeight
123
+ ) => {
124
+ if (!rowCount || !visibleRowCount || totalRowCount <= rowCount) {
125
+ return ""
126
+ }
127
+ return `height: ${headerHeight + visibleRowCount * rowHeight}px;`
128
+ }
129
+
130
+ const getGridStyle = (fields, schema, showEditColumn) => {
131
+ let style = "grid-template-columns:"
132
+ if (showEditColumn) {
133
+ style += " auto"
134
+ }
135
+ fields?.forEach(field => {
136
+ const fieldSchema = schema[field]
137
+ if (fieldSchema.width) {
138
+ style += ` ${fieldSchema.width}`
139
+ } else {
140
+ style += " minmax(auto, 1fr)"
141
+ }
142
+ })
143
+ style += ";"
144
+ return style
145
+ }
146
+
147
+ const sortRows = (rows, sortColumn, sortOrder) => {
148
+ if (!sortColumn || !sortOrder || disableSorting) {
149
+ return rows
150
+ }
151
+ return rows.slice().sort((a, b) => {
152
+ const colA = a[sortColumn]
153
+ const colB = b[sortColumn]
154
+ if (sortOrder === "Descending") {
155
+ return colA > colB ? -1 : 1
156
+ } else {
157
+ return colA > colB ? 1 : -1
158
+ }
159
+ })
160
+ }
161
+
162
+ const sortBy = fieldSchema => {
163
+ if (fieldSchema.sortable === false) {
164
+ return
165
+ }
166
+ if (fieldSchema.name === sortColumn) {
167
+ sortOrder = sortOrder === "Descending" ? "Ascending" : "Descending"
168
+ } else {
169
+ sortColumn = fieldSchema.name
170
+ sortOrder = "Descending"
171
+ }
172
+ dispatch("sort", { column: sortColumn, order: sortOrder })
173
+ }
174
+
175
+ const getDisplayName = schema => {
176
+ let name = schema?.displayName
177
+ if (schema && name === undefined) {
178
+ name = schema.name
179
+ }
180
+ return name || ""
181
+ }
182
+
183
+ const getFields = (schema, showAutoColumns, autoSortColumns) => {
184
+ let columns = []
185
+ let autoColumns = []
186
+ Object.entries(schema || {}).forEach(([field, fieldSchema]) => {
187
+ if (!field || !fieldSchema) {
188
+ return
189
+ }
190
+ if (!autoSortColumns || !fieldSchema?.autocolumn) {
191
+ columns.push(fieldSchema)
192
+ } else if (showAutoColumns) {
193
+ autoColumns.push(fieldSchema)
194
+ }
195
+ })
196
+ return columns
197
+ .sort((a, b) => {
198
+ const orderA = a.order || Number.MAX_SAFE_INTEGER
199
+ const orderB = b.order || Number.MAX_SAFE_INTEGER
200
+ const nameA = getDisplayName(a)
201
+ const nameB = getDisplayName(b)
202
+ if (orderA !== orderB) {
203
+ return orderA < orderB ? orderA : orderB
204
+ }
205
+ return nameA < nameB ? a : b
206
+ })
207
+ .concat(autoColumns)
208
+ .map(column => column.name)
209
+ }
210
+
211
+ const editColumn = (e, field) => {
212
+ e.stopPropagation()
213
+ dispatch("editcolumn", field)
214
+ }
215
+
216
+ const editRow = (e, row) => {
217
+ e.stopPropagation()
218
+ dispatch("editrow", cloneDeep(row))
219
+ }
220
+
221
+ const toggleSelectRow = row => {
222
+ if (!allowSelectRows) {
223
+ return
224
+ }
225
+ if (selectedRows.some(selectedRow => selectedRow._id === row._id)) {
226
+ selectedRows = selectedRows.filter(
227
+ selectedRow => selectedRow._id !== row._id
228
+ )
229
+ } else {
230
+ selectedRows = [...selectedRows, row]
231
+ }
232
+ }
233
+
234
+ const toggleSelectAll = e => {
235
+ const select = !!e.detail
236
+ if (select) {
237
+ // Add any rows which are not already in selected rows
238
+ rows.forEach(row => {
239
+ if (selectedRows.findIndex(x => x._id === row._id) === -1) {
240
+ selectedRows.push(row)
241
+ }
242
+ })
243
+ } else {
244
+ // Remove any rows from selected rows that are in the current data set
245
+ selectedRows = selectedRows.filter(el =>
246
+ rows.every(f => f._id !== el._id)
247
+ )
248
+ }
249
+ }
250
+
251
+ const computeCellStyles = schema => {
252
+ let styles = {}
253
+ Object.keys(schema || {}).forEach(field => {
254
+ styles[field] = ""
255
+ if (schema[field].color) {
256
+ styles[field] += `color: ${schema[field].color};`
257
+ }
258
+ if (schema[field].background) {
259
+ styles[field] += `background-color: ${schema[field].background};`
260
+ }
261
+ if (schema[field].align === "Center") {
262
+ styles[field] += "justify-content: center; text-align: center;"
263
+ }
264
+ if (schema[field].align === "Right") {
265
+ styles[field] += "justify-content: flex-end; text-align: right;"
266
+ }
267
+ })
268
+ return styles
269
+ }
270
+ </script>
271
+
272
+ <div
273
+ class="wrapper"
274
+ class:wrapper--quiet={quiet}
275
+ class:wrapper--compact={compact}
276
+ bind:offsetHeight={height}
277
+ style={`--row-height: ${rowHeight}px; --header-height: ${headerHeight}px;`}
278
+ >
279
+ {#if !loaded}
280
+ <div class="loading" style={heightStyle}>
281
+ <ProgressCircle />
282
+ </div>
283
+ {:else}
284
+ <div class="spectrum-Table" style={`${heightStyle}${gridStyle}`}>
285
+ {#if fields.length}
286
+ <div class="spectrum-Table-head">
287
+ {#if showEditColumn}
288
+ <div
289
+ class="spectrum-Table-headCell spectrum-Table-headCell--divider spectrum-Table-headCell--edit"
290
+ >
291
+ {#if allowSelectRows}
292
+ <Checkbox
293
+ bind:value={checkboxStatus}
294
+ on:change={toggleSelectAll}
295
+ />
296
+ {:else}
297
+ Edit
298
+ {/if}
299
+ </div>
300
+ {/if}
301
+ {#each fields as field}
302
+ <div
303
+ class="spectrum-Table-headCell"
304
+ class:spectrum-Table-headCell--alignCenter={schema[field]
305
+ .align === "Center"}
306
+ class:spectrum-Table-headCell--alignRight={schema[field].align ===
307
+ "Right"}
308
+ class:is-sortable={schema[field].sortable !== false}
309
+ class:is-sorted-desc={sortColumn === field &&
310
+ sortOrder === "Descending"}
311
+ class:is-sorted-asc={sortColumn === field &&
312
+ sortOrder === "Ascending"}
313
+ on:click={() => sortBy(schema[field])}
314
+ >
315
+ <div class="title">{getDisplayName(schema[field])}</div>
316
+ {#if schema[field]?.autocolumn}
317
+ <svg
318
+ class="spectrum-Icon spectrum-Table-autoIcon"
319
+ focusable="false"
320
+ >
321
+ <use xlink:href="#spectrum-icon-18-MagicWand" />
322
+ </svg>
323
+ {/if}
324
+ {#if sortColumn === field}
325
+ <svg
326
+ class="spectrum-Icon spectrum-UIIcon-ArrowDown100 spectrum-Table-sortedIcon"
327
+ focusable="false"
328
+ aria-hidden="true"
329
+ >
330
+ <use xlink:href="#spectrum-css-icon-Arrow100" />
331
+ </svg>
332
+ {/if}
333
+ {#if allowEditColumns && schema[field]?.editable !== false}
334
+ <svg
335
+ class="spectrum-Icon spectrum-Table-editIcon"
336
+ focusable="false"
337
+ on:click={e => editColumn(e, field)}
338
+ >
339
+ <use xlink:href="#spectrum-icon-18-Edit" />
340
+ </svg>
341
+ {/if}
342
+ </div>
343
+ {/each}
344
+ </div>
345
+ {/if}
346
+ {#if sortedRows?.length}
347
+ {#each sortedRows as row, idx}
348
+ <div class="spectrum-Table-row">
349
+ {#if showEditColumn}
350
+ <div
351
+ class="spectrum-Table-cell spectrum-Table-cell--divider spectrum-Table-cell--edit"
352
+ on:click={e => {
353
+ toggleSelectRow(row)
354
+ e.stopPropagation()
355
+ }}
356
+ >
357
+ <SelectEditRenderer
358
+ data={row}
359
+ selected={selectedRows.findIndex(
360
+ selectedRow => selectedRow._id === row._id
361
+ ) !== -1}
362
+ onEdit={e => editRow(e, row)}
363
+ {allowSelectRows}
364
+ {allowEditRows}
365
+ />
366
+ </div>
367
+ {/if}
368
+ {#each fields as field}
369
+ <div
370
+ class="spectrum-Table-cell"
371
+ class:spectrum-Table-cell--divider={!!schema[field].divider}
372
+ style={cellStyles[field]}
373
+ on:click={() => {
374
+ if (!schema[field]?.preventSelectRow) {
375
+ dispatch("click", row)
376
+ toggleSelectRow(row)
377
+ }
378
+ }}
379
+ >
380
+ <CellRenderer
381
+ {customRenderers}
382
+ {row}
383
+ schema={schema[field]}
384
+ value={deepGet(row, field)}
385
+ on:clickrelationship
386
+ >
387
+ <slot />
388
+ </CellRenderer>
389
+ </div>
390
+ {/each}
391
+ </div>
392
+ {/each}
393
+ {:else}
394
+ <div
395
+ class="placeholder"
396
+ class:placeholder--custom={customPlaceholder}
397
+ class:placeholder--no-fields={!fields?.length}
398
+ >
399
+ {#if customPlaceholder}
400
+ <slot name="placeholder" />
401
+ {:else}
402
+ <div class="placeholder-content">
403
+ <svg
404
+ class="spectrum-Icon spectrum-Icon--sizeXXL"
405
+ focusable="false"
406
+ >
407
+ <use xlink:href="#spectrum-icon-18-Table" />
408
+ </svg>
409
+ <div>{placeholderText}</div>
410
+ </div>
411
+ {/if}
412
+ </div>
413
+ {/if}
414
+ </div>
415
+ {/if}
416
+ </div>
417
+
418
+ <style>
419
+ /* Wrapper */
420
+ .wrapper {
421
+ position: relative;
422
+ z-index: 0;
423
+ --table-bg: var(--spectrum-global-color-gray-50);
424
+ --table-border: 1px solid var(--spectrum-alias-border-color-mid);
425
+ --cell-padding: var(--spectrum-global-dimension-size-250);
426
+ }
427
+ .wrapper--quiet {
428
+ --table-bg: var(--spectrum-alias-background-color-transparent);
429
+ }
430
+ .wrapper--compact {
431
+ --cell-padding: var(--spectrum-global-dimension-size-150);
432
+ }
433
+
434
+ /* Loading */
435
+ .loading {
436
+ display: grid;
437
+ place-items: center;
438
+ min-height: 100px;
439
+ }
440
+
441
+ /* Table */
442
+ .spectrum-Table {
443
+ width: 100%;
444
+ border-radius: 0;
445
+ display: grid;
446
+ overflow: auto;
447
+ }
448
+
449
+ /* Header */
450
+ .spectrum-Table-head {
451
+ display: contents;
452
+ }
453
+ .spectrum-Table-head > :first-child {
454
+ border-left: 1px solid transparent;
455
+ padding-left: var(--cell-padding);
456
+ }
457
+ .spectrum-Table-head > :last-child {
458
+ border-right: 1px solid transparent;
459
+ padding-right: var(--cell-padding);
460
+ }
461
+ .spectrum-Table-headCell {
462
+ height: var(--header-height);
463
+ position: sticky;
464
+ top: 0;
465
+ text-overflow: ellipsis;
466
+ white-space: nowrap;
467
+ background-color: var(--spectrum-alias-background-color-secondary);
468
+ z-index: 2;
469
+ border-bottom: var(--table-border);
470
+ padding: 0 calc(var(--cell-padding) / 1.33);
471
+ display: flex;
472
+ flex-direction: row;
473
+ justify-content: flex-start;
474
+ align-items: center;
475
+ user-select: none;
476
+ border-top: var(--table-border);
477
+ }
478
+ .spectrum-Table-headCell:first-of-type {
479
+ border-left: var(--table-border);
480
+ }
481
+ .spectrum-Table-headCell:last-of-type {
482
+ border-right: var(--table-border);
483
+ }
484
+ .spectrum-Table-headCell--alignCenter {
485
+ justify-content: center;
486
+ }
487
+ .spectrum-Table-headCell--alignRight {
488
+ justify-content: flex-end;
489
+ }
490
+ .spectrum-Table-headCell--divider {
491
+ padding-right: var(--cell-padding);
492
+ }
493
+ .spectrum-Table-headCell--divider + .spectrum-Table-headCell {
494
+ padding-left: var(--cell-padding);
495
+ }
496
+ .spectrum-Table-headCell--edit {
497
+ position: sticky;
498
+ left: 0;
499
+ z-index: 3;
500
+ }
501
+ .spectrum-Table-headCell .title {
502
+ overflow: hidden;
503
+ text-overflow: ellipsis;
504
+ }
505
+ .spectrum-Table-headCell:hover .spectrum-Table-editIcon {
506
+ opacity: 1;
507
+ transition: opacity 0.2s ease;
508
+ }
509
+ .spectrum-Table-headCell .spectrum-Icon {
510
+ pointer-events: all;
511
+ margin-left: var(
512
+ --spectrum-table-header-sort-icon-gap,
513
+ var(--spectrum-global-dimension-size-125)
514
+ );
515
+ }
516
+ .spectrum-Table-editIcon,
517
+ .spectrum-Table-autoIcon {
518
+ width: var(--spectrum-global-dimension-size-150);
519
+ height: var(--spectrum-global-dimension-size-150);
520
+ }
521
+ .spectrum-Table-editIcon {
522
+ opacity: 0;
523
+ }
524
+
525
+ /* Table rows */
526
+ .spectrum-Table-row {
527
+ display: contents;
528
+ }
529
+ .spectrum-Table-row:hover .spectrum-Table-cell {
530
+ /*background-color: var(--hover-bg) !important;*/
531
+ }
532
+ .spectrum-Table-row:hover .spectrum-Table-cell:after {
533
+ background-color: var(--spectrum-alias-highlight-hover);
534
+ }
535
+ .wrapper--quiet .spectrum-Table-row {
536
+ border-left: none;
537
+ border-right: none;
538
+ }
539
+ .spectrum-Table-row > :first-child {
540
+ border-left: var(--table-border);
541
+ padding-left: var(--cell-padding);
542
+ }
543
+ .spectrum-Table-row > :last-child {
544
+ border-right: var(--table-border);
545
+ padding-right: var(--cell-padding);
546
+ }
547
+
548
+ /* Table cells */
549
+ .spectrum-Table-cell {
550
+ flex: 1 1 auto;
551
+ padding: 0 calc(var(--cell-padding) / 1.33);
552
+ border-top: none;
553
+ border-bottom: none;
554
+ border-radius: 0;
555
+ text-overflow: ellipsis;
556
+ white-space: nowrap;
557
+ height: var(--row-height);
558
+ display: flex;
559
+ flex-direction: row;
560
+ justify-content: flex-start;
561
+ align-items: center;
562
+ gap: 4px;
563
+ border-bottom: 1px solid var(--spectrum-alias-border-color-mid);
564
+ background-color: var(--table-bg);
565
+ z-index: 1;
566
+ }
567
+ .spectrum-Table-cell--divider {
568
+ padding-right: var(--cell-padding);
569
+ }
570
+ .spectrum-Table-cell--divider + .spectrum-Table-cell {
571
+ padding-left: var(--cell-padding);
572
+ }
573
+ .spectrum-Table-cell--edit {
574
+ position: sticky;
575
+ left: 0;
576
+ z-index: 2;
577
+ }
578
+ .spectrum-Table-cell:after {
579
+ content: "";
580
+ position: absolute;
581
+ width: 100%;
582
+ height: 100%;
583
+ background-color: transparent;
584
+ top: 0;
585
+ left: 0;
586
+ pointer-events: none;
587
+ transition: background-color
588
+ var(--spectrum-global-animation-duration-100, 0.13s) ease-in-out;
589
+ }
590
+
591
+ /* Placeholder */
592
+ .placeholder {
593
+ display: flex;
594
+ flex-direction: row;
595
+ justify-content: center;
596
+ align-items: center;
597
+ border: var(--table-border);
598
+ border-top: none;
599
+ grid-column: 1 / -1;
600
+ background-color: var(--table-bg);
601
+ padding: 40px;
602
+ }
603
+ .placeholder--no-fields {
604
+ border-top: var(--table-border);
605
+ }
606
+ .placeholder--custom {
607
+ justify-content: flex-start;
608
+ }
609
+ .wrapper--quiet .placeholder {
610
+ border-left: none;
611
+ border-right: none;
612
+ }
613
+ .placeholder-content {
614
+ display: flex;
615
+ flex-direction: column;
616
+ justify-content: center;
617
+ align-items: center;
618
+ color: var(
619
+ --spectrum-table-cell-text-color,
620
+ var(--spectrum-alias-text-color)
621
+ );
622
+ }
623
+ .placeholder-content div {
624
+ margin-top: 10px;
625
+ font-size: var(
626
+ --spectrum-table-cell-text-size,
627
+ var(--spectrum-alias-font-size-default)
628
+ );
629
+ text-align: center;
630
+ }
631
+ </style>
@@ -0,0 +1 @@
1
+ export { default as Table } from "./Table.svelte"
@@ -0,0 +1,88 @@
1
+ <script>
2
+ import { getContext, onMount, createEventDispatcher } from "svelte"
3
+ import Portal from "svelte-portal"
4
+ export let title
5
+ export let icon = ""
6
+
7
+ const dispatch = createEventDispatcher()
8
+ let selected = getContext("tab")
9
+ let tab_internal
10
+ let tabInfo
11
+
12
+ const setTabInfo = () => {
13
+ // If the tabs are being rendered inside a component which uses
14
+ // a svelte transition to enter, then this initial getBoundingClientRect
15
+ // will return an incorrect position.
16
+ // We just need to get this off the main thread to fix this, by using
17
+ // a 0ms timeout.
18
+ setTimeout(() => {
19
+ tabInfo = tab_internal?.getBoundingClientRect()
20
+ if (tabInfo && $selected.title === title) {
21
+ $selected.info = tabInfo
22
+ }
23
+ }, 0)
24
+ }
25
+
26
+ onMount(() => {
27
+ setTabInfo()
28
+ })
29
+
30
+ //Ensure that the underline is in the correct location
31
+ $: {
32
+ if ($selected.title === title && tab_internal) {
33
+ if ($selected.info?.left !== tab_internal.getBoundingClientRect().left) {
34
+ $selected = {
35
+ ...$selected,
36
+ info: tab_internal.getBoundingClientRect(),
37
+ }
38
+ }
39
+ }
40
+ }
41
+
42
+ const onClick = () => {
43
+ $selected = {
44
+ ...$selected,
45
+ title,
46
+ info: tab_internal.getBoundingClientRect(),
47
+ }
48
+ dispatch("click")
49
+ }
50
+ </script>
51
+
52
+ <div
53
+ bind:this={tab_internal}
54
+ on:click={onClick}
55
+ class:is-selected={$selected.title === title}
56
+ class="spectrum-Tabs-item"
57
+ class:emphasized={$selected.title === title && $selected.emphasized}
58
+ tabindex="0"
59
+ >
60
+ {#if icon}
61
+ <svg
62
+ class="spectrum-Icon spectrum-Icon--sizeM"
63
+ focusable="false"
64
+ aria-hidden="true"
65
+ aria-label="Folder"
66
+ >
67
+ <use xlink:href="#spectrum-icon-18-{icon}" />
68
+ </svg>
69
+ {/if}
70
+ <span class="spectrum-Tabs-itemLabel">{title}</span>
71
+ </div>
72
+ {#if $selected.title === title}
73
+ <Portal target=".spectrum-Tabs-content-{$selected.id}">
74
+ <slot />
75
+ </Portal>
76
+ {/if}
77
+
78
+ <style>
79
+ .emphasized {
80
+ color: var(--spectrum-global-color-blue-600);
81
+ }
82
+ .spectrum-Tabs-item {
83
+ color: var(--spectrum-global-color-gray-600);
84
+ }
85
+ .spectrum-Tabs-item.is-selected {
86
+ color: var(--spectrum-global-color-gray-900);
87
+ }
88
+ </style>