@budibase/frontend-core 2.5.6-alpha.5 → 2.5.6-alpha.7

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 (63) hide show
  1. package/package.json +6 -4
  2. package/src/components/grid/cells/AttachmentCell.svelte +153 -0
  3. package/src/components/grid/cells/BooleanCell.svelte +44 -0
  4. package/src/components/grid/cells/DataCell.svelte +86 -0
  5. package/src/components/grid/cells/DateCell.svelte +77 -0
  6. package/src/components/grid/cells/FormulaCell.svelte +5 -0
  7. package/src/components/grid/cells/GridCell.svelte +159 -0
  8. package/src/components/grid/cells/HeaderCell.svelte +237 -0
  9. package/src/components/grid/cells/JSONCell.svelte +36 -0
  10. package/src/components/grid/cells/LongFormCell.svelte +117 -0
  11. package/src/components/grid/cells/MultiSelectCell.svelte +7 -0
  12. package/src/components/grid/cells/NumberCell.svelte +7 -0
  13. package/src/components/grid/cells/OptionsCell.svelte +239 -0
  14. package/src/components/grid/cells/RelationshipCell.svelte +503 -0
  15. package/src/components/grid/cells/TextCell.svelte +110 -0
  16. package/src/components/grid/controls/AddColumnButton.svelte +16 -0
  17. package/src/components/grid/controls/AddRowButton.svelte +18 -0
  18. package/src/components/grid/controls/BetaButton.svelte +46 -0
  19. package/src/components/grid/controls/DeleteButton.svelte +72 -0
  20. package/src/components/grid/controls/HideColumnsButton.svelte +91 -0
  21. package/src/components/grid/controls/RowHeightButton.svelte +70 -0
  22. package/src/components/grid/controls/SortButton.svelte +107 -0
  23. package/src/components/grid/index.js +1 -0
  24. package/src/components/grid/layout/Avatar.svelte +24 -0
  25. package/src/components/grid/layout/Grid.svelte +250 -0
  26. package/src/components/grid/layout/GridBody.svelte +38 -0
  27. package/src/components/grid/layout/GridRow.svelte +57 -0
  28. package/src/components/grid/layout/GridScrollWrapper.svelte +84 -0
  29. package/src/components/grid/layout/HeaderRow.svelte +30 -0
  30. package/src/components/grid/layout/NewRowTop.svelte +247 -0
  31. package/src/components/grid/layout/RowCount.svelte +9 -0
  32. package/src/components/grid/layout/StickyColumn.svelte +245 -0
  33. package/src/components/grid/layout/UserAvatars.svelte +20 -0
  34. package/src/components/grid/lib/constants.js +11 -0
  35. package/src/components/grid/lib/events.js +29 -0
  36. package/src/components/grid/lib/renderers.js +29 -0
  37. package/src/components/grid/lib/utils.js +26 -0
  38. package/src/components/grid/lib/websocket.js +63 -0
  39. package/src/components/grid/overlays/KeyboardManager.svelte +180 -0
  40. package/src/components/grid/overlays/MenuOverlay.svelte +95 -0
  41. package/src/components/grid/overlays/ReorderOverlay.svelte +63 -0
  42. package/src/components/grid/overlays/ResizeOverlay.svelte +70 -0
  43. package/src/components/grid/overlays/ScrollOverlay.svelte +121 -0
  44. package/src/components/grid/stores/bounds.js +16 -0
  45. package/src/components/grid/stores/clipboard.js +34 -0
  46. package/src/components/grid/stores/columns.js +206 -0
  47. package/src/components/grid/stores/index.js +48 -0
  48. package/src/components/grid/stores/menu.js +49 -0
  49. package/src/components/grid/stores/pagination.js +24 -0
  50. package/src/components/grid/stores/reorder.js +155 -0
  51. package/src/components/grid/stores/resize.js +124 -0
  52. package/src/components/grid/stores/rows.js +462 -0
  53. package/src/components/grid/stores/scroll.js +201 -0
  54. package/src/components/grid/stores/ui.js +168 -0
  55. package/src/components/grid/stores/users.js +115 -0
  56. package/src/components/grid/stores/validation.js +45 -0
  57. package/src/components/grid/stores/viewport.js +141 -0
  58. package/src/components/index.js +1 -0
  59. package/src/fetch/DataFetch.js +27 -21
  60. package/src/fetch/QueryFetch.js +1 -1
  61. package/src/themes/midnight.css +3 -0
  62. package/src/themes/nord.css +3 -0
  63. package/src/utils/utils.js +20 -0
@@ -0,0 +1,84 @@
1
+ <script>
2
+ import { getContext } from "svelte"
3
+ import { domDebounce } from "../../../utils/utils"
4
+
5
+ const {
6
+ rowHeight,
7
+ scroll,
8
+ focusedCellId,
9
+ renderedRows,
10
+ maxScrollTop,
11
+ maxScrollLeft,
12
+ bounds,
13
+ hoveredRowId,
14
+ hiddenColumnsWidth,
15
+ } = getContext("grid")
16
+
17
+ export let scrollVertically = false
18
+ export let scrollHorizontally = false
19
+ export let wheelInteractive = false
20
+
21
+ $: style = generateStyle($scroll, $rowHeight, $hiddenColumnsWidth)
22
+
23
+ const generateStyle = (scroll, rowHeight, hiddenWidths) => {
24
+ const offsetX = scrollHorizontally ? -1 * scroll.left + hiddenWidths : 0
25
+ const offsetY = scrollVertically ? -1 * (scroll.top % rowHeight) : 0
26
+ return `transform: translate3d(${offsetX}px, ${offsetY}px, 0);`
27
+ }
28
+
29
+ // Handles a wheel even and updates the scroll offsets
30
+ const handleWheel = e => {
31
+ e.preventDefault()
32
+ const modifier = e.ctrlKey || e.metaKey
33
+ let x = modifier ? e.deltaY : e.deltaX
34
+ let y = modifier ? e.deltaX : e.deltaY
35
+ debouncedHandleWheel(x, y, e.clientY)
36
+ }
37
+ const debouncedHandleWheel = domDebounce((deltaX, deltaY, clientY) => {
38
+ const { top, left } = $scroll
39
+
40
+ // Calculate new scroll top
41
+ let newScrollTop = top + deltaY
42
+ newScrollTop = Math.max(0, Math.min(newScrollTop, $maxScrollTop))
43
+
44
+ // Calculate new scroll left
45
+ let newScrollLeft = left + deltaX
46
+ newScrollLeft = Math.max(0, Math.min(newScrollLeft, $maxScrollLeft))
47
+
48
+ // Update state
49
+ scroll.set({
50
+ left: scrollHorizontally ? newScrollLeft : left,
51
+ top: scrollVertically ? newScrollTop : top,
52
+ })
53
+
54
+ // Hover row under cursor
55
+ const y = clientY - $bounds.top + (newScrollTop % $rowHeight)
56
+ const hoveredRow = $renderedRows[Math.floor(y / $rowHeight)]
57
+ hoveredRowId.set(hoveredRow?._id)
58
+ })
59
+ </script>
60
+
61
+ <div
62
+ class="outer"
63
+ on:wheel={wheelInteractive ? handleWheel : null}
64
+ on:click|self={() => ($focusedCellId = null)}
65
+ >
66
+ <div {style} class="inner">
67
+ <slot />
68
+ </div>
69
+ </div>
70
+
71
+ <style>
72
+ .outer {
73
+ min-width: 100%;
74
+ min-height: 100%;
75
+ height: 100%;
76
+ width: 100%;
77
+ max-height: 100%;
78
+ max-width: 100%;
79
+ overflow: hidden;
80
+ }
81
+ .inner {
82
+ position: absolute;
83
+ }
84
+ </style>
@@ -0,0 +1,30 @@
1
+ <script>
2
+ import { getContext } from "svelte"
3
+ import GridScrollWrapper from "./GridScrollWrapper.svelte"
4
+ import HeaderCell from "../cells/HeaderCell.svelte"
5
+
6
+ const { renderedColumns } = getContext("grid")
7
+ </script>
8
+
9
+ <div class="header">
10
+ <GridScrollWrapper scrollHorizontally>
11
+ <div class="row">
12
+ {#each $renderedColumns as column, idx}
13
+ <HeaderCell {column} {idx} />
14
+ {/each}
15
+ </div>
16
+ </GridScrollWrapper>
17
+ </div>
18
+
19
+ <style>
20
+ .header {
21
+ background: var(--background);
22
+ border-bottom: var(--cell-border);
23
+ position: relative;
24
+ height: var(--default-row-height);
25
+ z-index: 1;
26
+ }
27
+ .row {
28
+ display: flex;
29
+ }
30
+ </style>
@@ -0,0 +1,247 @@
1
+ <script>
2
+ import GridCell from "../cells/GridCell.svelte"
3
+ import { getContext, onMount } from "svelte"
4
+ import { Icon, Button } from "@budibase/bbui"
5
+ import GridScrollWrapper from "./GridScrollWrapper.svelte"
6
+ import DataCell from "../cells/DataCell.svelte"
7
+ import { fly } from "svelte/transition"
8
+ import { GutterWidth } from "../lib/constants"
9
+
10
+ const {
11
+ hoveredRowId,
12
+ focusedCellId,
13
+ stickyColumn,
14
+ scroll,
15
+ config,
16
+ dispatch,
17
+ visibleColumns,
18
+ rows,
19
+ showHScrollbar,
20
+ tableId,
21
+ subscribe,
22
+ scrollLeft,
23
+ } = getContext("grid")
24
+
25
+ let isAdding = false
26
+ let newRow = {}
27
+ let touched = false
28
+
29
+ $: firstColumn = $stickyColumn || $visibleColumns[0]
30
+ $: rowHovered = $hoveredRowId === "new"
31
+ $: rowFocused = $focusedCellId?.startsWith("new-")
32
+ $: width = GutterWidth + ($stickyColumn?.width || 0)
33
+ $: $tableId, (isAdding = false)
34
+
35
+ const addRow = async () => {
36
+ // Create row
37
+ const savedRow = await rows.actions.addRow(newRow, 0)
38
+ if (savedRow) {
39
+ // Select the first cell if possible
40
+ if (firstColumn) {
41
+ $focusedCellId = `${savedRow._id}-${firstColumn.name}`
42
+ }
43
+
44
+ // Reset state
45
+ isAdding = false
46
+ scroll.set({
47
+ left: 0,
48
+ top: 0,
49
+ })
50
+ }
51
+ }
52
+
53
+ const cancel = () => {
54
+ isAdding = false
55
+ }
56
+
57
+ const startAdding = () => {
58
+ newRow = {}
59
+ isAdding = true
60
+ if (firstColumn) {
61
+ $focusedCellId = `new-${firstColumn.name}`
62
+ }
63
+ }
64
+
65
+ const updateValue = (rowId, columnName, val) => {
66
+ touched = true
67
+ newRow[columnName] = val
68
+ }
69
+
70
+ const addViaModal = () => {
71
+ isAdding = false
72
+ dispatch("add-row")
73
+ }
74
+
75
+ onMount(() => subscribe("add-row-inline", startAdding))
76
+ </script>
77
+
78
+ <!-- Only show new row functionality if we have any columns -->
79
+ {#if isAdding}
80
+ <div class="container" transition:fly={{ y: 20, duration: 130 }}>
81
+ <div class="content" class:above-scrollbar={$showHScrollbar}>
82
+ <div
83
+ class="new-row"
84
+ on:mouseenter={() => ($hoveredRowId = "new")}
85
+ on:mouseleave={() => ($hoveredRowId = null)}
86
+ >
87
+ <div
88
+ class="sticky-column"
89
+ style="flex: 0 0 {width}px"
90
+ class:scrolled={$scrollLeft > 0}
91
+ >
92
+ <GridCell width={GutterWidth} {rowHovered} {rowFocused}>
93
+ <div class="gutter">
94
+ <div class="number">1</div>
95
+ {#if $config.allowExpandRows}
96
+ <Icon
97
+ name="Maximize"
98
+ size="S"
99
+ hoverable
100
+ on:click={addViaModal}
101
+ />
102
+ {/if}
103
+ </div>
104
+ </GridCell>
105
+ {#if $stickyColumn}
106
+ {@const cellId = `new-${$stickyColumn.name}`}
107
+ <DataCell
108
+ {cellId}
109
+ column={$stickyColumn}
110
+ row={newRow}
111
+ {rowHovered}
112
+ focused={$focusedCellId === cellId}
113
+ {rowFocused}
114
+ width={$stickyColumn.width}
115
+ {updateValue}
116
+ rowIdx={0}
117
+ />
118
+ {/if}
119
+ </div>
120
+
121
+ <GridScrollWrapper scrollHorizontally wheelInteractive>
122
+ <div class="row">
123
+ {#each $visibleColumns as column}
124
+ {@const cellId = `new-${column.name}`}
125
+ {#key cellId}
126
+ <DataCell
127
+ {cellId}
128
+ {column}
129
+ row={newRow}
130
+ {rowHovered}
131
+ focused={$focusedCellId === cellId}
132
+ {rowFocused}
133
+ width={column.width}
134
+ {updateValue}
135
+ rowIdx={0}
136
+ />
137
+ {/key}
138
+ {/each}
139
+ </div>
140
+ </GridScrollWrapper>
141
+ </div>
142
+ </div>
143
+ <div class="buttons">
144
+ <Button size="M" cta on:click={addRow}>Save</Button>
145
+ <Button size="M" secondary newStyles on:click={cancel}>Cancel</Button>
146
+ </div>
147
+ </div>
148
+ {/if}
149
+
150
+ <style>
151
+ .container {
152
+ pointer-events: none;
153
+ position: absolute;
154
+ top: var(--row-height);
155
+ left: 0;
156
+ width: 100%;
157
+ padding-bottom: 800px;
158
+ display: flex;
159
+ flex-direction: column;
160
+ align-items: stretch;
161
+ }
162
+ .container:before {
163
+ position: absolute;
164
+ content: "";
165
+ left: 0;
166
+ top: 0;
167
+ height: 100%;
168
+ width: 100%;
169
+ background: var(--cell-background);
170
+ opacity: 0.8;
171
+ z-index: -1;
172
+ }
173
+ .content {
174
+ pointer-events: all;
175
+ background: var(--background);
176
+ border-bottom: var(--cell-border);
177
+ }
178
+
179
+ .new-row {
180
+ display: flex;
181
+ bottom: 0;
182
+ left: 0;
183
+ width: 100%;
184
+ transition: margin-bottom 130ms ease-out;
185
+ }
186
+ .new-row :global(.cell) {
187
+ --cell-background: var(--background) !important;
188
+ border-bottom: none;
189
+ }
190
+
191
+ .sticky-column {
192
+ display: flex;
193
+ z-index: 1;
194
+ position: relative;
195
+ }
196
+ /* Don't show borders between cells in the sticky column */
197
+ .sticky-column :global(.cell:not(:last-child)) {
198
+ border-right: none;
199
+ }
200
+
201
+ .row {
202
+ width: 0;
203
+ display: flex;
204
+ }
205
+
206
+ /* Add shadow when scrolled */
207
+ .sticky-column.scrolled {
208
+ /*box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.1);*/
209
+ }
210
+ .sticky-column.scrolled:after {
211
+ content: "";
212
+ width: 10px;
213
+ height: 100%;
214
+ background: linear-gradient(to right, rgba(0, 0, 0, 0.05), transparent);
215
+ left: 100%;
216
+ top: 0;
217
+ position: absolute;
218
+ }
219
+
220
+ /* Styles for gutter */
221
+ .gutter {
222
+ flex: 1 1 auto;
223
+ display: grid;
224
+ align-items: center;
225
+ padding: var(--cell-padding);
226
+ grid-template-columns: 1fr auto;
227
+ gap: var(--cell-spacing);
228
+ }
229
+
230
+ /* Floating buttons */
231
+ .buttons {
232
+ display: flex;
233
+ flex-direction: row;
234
+ gap: 8px;
235
+ margin: 24px 0 0 var(--gutter-width);
236
+ pointer-events: all;
237
+ align-self: flex-start;
238
+ }
239
+
240
+ .number {
241
+ display: flex;
242
+ flex-direction: row;
243
+ justify-content: center;
244
+ align-items: center;
245
+ color: var(--spectrum-global-color-gray-500);
246
+ }
247
+ </style>
@@ -0,0 +1,9 @@
1
+ <script>
2
+ import { getContext } from "svelte"
3
+
4
+ const { rows } = getContext("grid")
5
+ </script>
6
+
7
+ <div>
8
+ {$rows.length} row{$rows.length === 1 ? "" : "s"}
9
+ </div>
@@ -0,0 +1,245 @@
1
+ <script>
2
+ import { getContext } from "svelte"
3
+ import { Checkbox, Icon } from "@budibase/bbui"
4
+ import GridCell from "../cells/GridCell.svelte"
5
+ import DataCell from "../cells/DataCell.svelte"
6
+ import GridScrollWrapper from "./GridScrollWrapper.svelte"
7
+ import HeaderCell from "../cells/HeaderCell.svelte"
8
+ import { GutterWidth } from "../lib/constants"
9
+
10
+ const {
11
+ rows,
12
+ selectedRows,
13
+ stickyColumn,
14
+ renderedRows,
15
+ focusedCellId,
16
+ hoveredRowId,
17
+ config,
18
+ selectedCellMap,
19
+ focusedRow,
20
+ dispatch,
21
+ scrollLeft,
22
+ } = getContext("grid")
23
+
24
+ $: rowCount = $rows.length
25
+ $: selectedRowCount = Object.values($selectedRows).filter(x => !!x).length
26
+ $: width = GutterWidth + ($stickyColumn?.width || 0)
27
+
28
+ const selectAll = () => {
29
+ const allSelected = selectedRowCount === rowCount
30
+ if (allSelected) {
31
+ $selectedRows = {}
32
+ } else {
33
+ let allRows = {}
34
+ $rows.forEach(row => {
35
+ allRows[row._id] = true
36
+ })
37
+ $selectedRows = allRows
38
+ }
39
+ }
40
+
41
+ const selectRow = id => {
42
+ selectedRows.update(state => {
43
+ let newState = {
44
+ ...state,
45
+ [id]: !state[id],
46
+ }
47
+ if (!newState[id]) {
48
+ delete newState[id]
49
+ }
50
+ return newState
51
+ })
52
+ }
53
+ </script>
54
+
55
+ <div
56
+ class="sticky-column"
57
+ style="flex: 0 0 {width}px"
58
+ class:scrolled={$scrollLeft > 0}
59
+ >
60
+ <div class="header row">
61
+ <GridCell width={GutterWidth} defaultHeight center>
62
+ <div class="gutter">
63
+ <div class="checkbox visible">
64
+ {#if $config.allowDeleteRows}
65
+ <div on:click={selectAll}>
66
+ <Checkbox
67
+ value={rowCount && selectedRowCount === rowCount}
68
+ disabled={!$renderedRows.length}
69
+ />
70
+ </div>
71
+ {/if}
72
+ </div>
73
+ {#if $config.allowExpandRows}
74
+ <div class="expand">
75
+ <Icon name="Maximize" size="S" />
76
+ </div>
77
+ {/if}
78
+ </div>
79
+ </GridCell>
80
+
81
+ {#if $stickyColumn}
82
+ <HeaderCell column={$stickyColumn} orderable={false} idx="sticky" />
83
+ {/if}
84
+ </div>
85
+
86
+ <div class="content" on:mouseleave={() => ($hoveredRowId = null)}>
87
+ <GridScrollWrapper scrollVertically wheelInteractive>
88
+ {#each $renderedRows as row, idx}
89
+ {@const rowSelected = !!$selectedRows[row._id]}
90
+ {@const rowHovered = $hoveredRowId === row._id}
91
+ {@const rowFocused = $focusedRow?._id === row._id}
92
+ {@const cellId = `${row._id}-${$stickyColumn?.name}`}
93
+ <div
94
+ class="row"
95
+ on:mouseenter={() => ($hoveredRowId = row._id)}
96
+ on:mouseleave={() => ($hoveredRowId = null)}
97
+ >
98
+ <GridCell
99
+ width={GutterWidth}
100
+ highlighted={rowFocused || rowHovered}
101
+ selected={rowSelected}
102
+ >
103
+ <div class="gutter">
104
+ <div
105
+ on:click={() => selectRow(row._id)}
106
+ class="checkbox"
107
+ class:visible={$config.allowDeleteRows &&
108
+ (rowSelected || rowHovered || rowFocused)}
109
+ >
110
+ <Checkbox value={rowSelected} />
111
+ </div>
112
+ <div
113
+ class="number"
114
+ class:visible={!$config.allowDeleteRows ||
115
+ !(rowSelected || rowHovered || rowFocused)}
116
+ >
117
+ {row.__idx + 1}
118
+ </div>
119
+ {#if $config.allowExpandRows}
120
+ <div class="expand" class:visible={rowFocused || rowHovered}>
121
+ <Icon
122
+ name="Maximize"
123
+ hoverable
124
+ size="S"
125
+ on:click={() => {
126
+ dispatch("edit-row", row)
127
+ }}
128
+ />
129
+ </div>
130
+ {/if}
131
+ </div>
132
+ </GridCell>
133
+ {#if $stickyColumn}
134
+ <DataCell
135
+ {row}
136
+ {cellId}
137
+ {rowFocused}
138
+ selected={rowSelected}
139
+ highlighted={rowHovered || rowFocused}
140
+ rowIdx={idx}
141
+ focused={$focusedCellId === cellId}
142
+ selectedUser={$selectedCellMap[cellId]}
143
+ width={$stickyColumn.width}
144
+ column={$stickyColumn}
145
+ />
146
+ {/if}
147
+ </div>
148
+ {/each}
149
+ </GridScrollWrapper>
150
+ </div>
151
+ </div>
152
+
153
+ <style>
154
+ .sticky-column {
155
+ display: flex;
156
+ flex-direction: column;
157
+ position: relative;
158
+ z-index: 2;
159
+ }
160
+
161
+ /* Add right border */
162
+ .sticky-column:before {
163
+ position: absolute;
164
+ content: "";
165
+ width: 0;
166
+ height: 100%;
167
+ left: calc(100% - 1px);
168
+ top: 0;
169
+ border-left: var(--cell-border);
170
+ }
171
+
172
+ /* Add shadow when scrolled */
173
+ .sticky-column.scrolled:after {
174
+ position: absolute;
175
+ content: "";
176
+ width: 8px;
177
+ height: 100%;
178
+ left: 100%;
179
+ top: 0;
180
+ opacity: 1;
181
+ background: linear-gradient(to right, var(--drop-shadow), transparent);
182
+ z-index: -1;
183
+ }
184
+
185
+ /* Don't show borders between cells in the sticky column */
186
+ .sticky-column :global(.cell:not(:last-child)) {
187
+ border-right: none;
188
+ }
189
+
190
+ .header {
191
+ z-index: 1;
192
+ }
193
+ .header :global(.cell) {
194
+ background: var(--spectrum-global-color-gray-100);
195
+ }
196
+ .row {
197
+ display: flex;
198
+ flex-direction: row;
199
+ justify-content: flex-start;
200
+ align-items: stretch;
201
+ }
202
+ .content {
203
+ position: relative;
204
+ flex: 1 1 auto;
205
+ }
206
+
207
+ /* Styles for gutter */
208
+ .gutter {
209
+ flex: 1 1 auto;
210
+ display: grid;
211
+ align-items: center;
212
+ padding: var(--cell-padding);
213
+ grid-template-columns: 1fr auto;
214
+ gap: var(--cell-spacing);
215
+ }
216
+ .checkbox,
217
+ .number {
218
+ display: none;
219
+ flex-direction: row;
220
+ justify-content: center;
221
+ align-items: center;
222
+ }
223
+ .checkbox :global(.spectrum-Checkbox) {
224
+ min-height: 0;
225
+ height: 20px;
226
+ }
227
+ .checkbox :global(.spectrum-Checkbox-box) {
228
+ margin: 3px 0 0 0;
229
+ }
230
+ .number {
231
+ color: var(--spectrum-global-color-gray-500);
232
+ }
233
+ .checkbox.visible,
234
+ .number.visible {
235
+ display: flex;
236
+ }
237
+ .expand {
238
+ opacity: 0;
239
+ pointer-events: none;
240
+ }
241
+ .expand.visible {
242
+ opacity: 1;
243
+ pointer-events: all;
244
+ }
245
+ </style>
@@ -0,0 +1,20 @@
1
+ <script>
2
+ import { getContext } from "svelte"
3
+ import Avatar from "./Avatar.svelte"
4
+
5
+ const { users } = getContext("grid")
6
+ </script>
7
+
8
+ <div class="users">
9
+ {#each $users as user}
10
+ <Avatar {user} />
11
+ {/each}
12
+ </div>
13
+
14
+ <style>
15
+ .users {
16
+ display: flex;
17
+ flex-direction: row;
18
+ gap: 8px;
19
+ }
20
+ </style>
@@ -0,0 +1,11 @@
1
+ export const Padding = 276
2
+ export const MaxCellRenderHeight = 252
3
+ export const MaxCellRenderWidthOverflow = 200
4
+ export const ScrollBarSize = 8
5
+ export const GutterWidth = 72
6
+ export const DefaultColumnWidth = 200
7
+ export const MinColumnWidth = 100
8
+ export const SmallRowHeight = 36
9
+ export const MediumRowHeight = 64
10
+ export const LargeRowHeight = 92
11
+ export const DefaultRowHeight = SmallRowHeight
@@ -0,0 +1,29 @@
1
+ import { createEventDispatcher } from "svelte"
2
+
3
+ export const createEventManagers = () => {
4
+ const svelteDispatch = createEventDispatcher()
5
+ let subscribers = {}
6
+
7
+ // Dispatches an event, notifying subscribers and also emitting a normal
8
+ // svelte event
9
+ const dispatch = (event, payload) => {
10
+ svelteDispatch(event, payload)
11
+ const subs = subscribers[event] || []
12
+ for (let i = 0; i < subs.length; i++) {
13
+ subs[i](payload)
14
+ }
15
+ }
16
+
17
+ // Subscribes to events
18
+ const subscribe = (event, callback) => {
19
+ const subs = subscribers[event] || []
20
+ subscribers[event] = [...subs, callback]
21
+
22
+ // Return unsubscribe function
23
+ return () => {
24
+ subscribers[event] = subscribers[event].filter(cb => cb !== callback)
25
+ }
26
+ }
27
+
28
+ return { dispatch, subscribe }
29
+ }
@@ -0,0 +1,29 @@
1
+ import OptionsCell from "../cells/OptionsCell.svelte"
2
+ import DateCell from "../cells/DateCell.svelte"
3
+ import MultiSelectCell from "../cells/MultiSelectCell.svelte"
4
+ import NumberCell from "../cells/NumberCell.svelte"
5
+ import RelationshipCell from "../cells/RelationshipCell.svelte"
6
+ import TextCell from "../cells/TextCell.svelte"
7
+ import LongFormCell from "../cells/LongFormCell.svelte"
8
+ import BooleanCell from "../cells/BooleanCell.svelte"
9
+ import FormulaCell from "../cells/FormulaCell.svelte"
10
+ import JSONCell from "../cells/JSONCell.svelte"
11
+ import AttachmentCell from "../cells/AttachmentCell.svelte"
12
+
13
+ const TypeComponentMap = {
14
+ text: TextCell,
15
+ options: OptionsCell,
16
+ datetime: DateCell,
17
+ barcodeqr: TextCell,
18
+ longform: LongFormCell,
19
+ array: MultiSelectCell,
20
+ number: NumberCell,
21
+ boolean: BooleanCell,
22
+ attachment: AttachmentCell,
23
+ link: RelationshipCell,
24
+ formula: FormulaCell,
25
+ json: JSONCell,
26
+ }
27
+ export const getCellRenderer = column => {
28
+ return TypeComponentMap[column?.schema?.type] || TextCell
29
+ }