@budibase/frontend-core 2.29.21 → 2.29.23

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 (51) hide show
  1. package/package.json +5 -5
  2. package/src/components/FilterBuilder.svelte +1 -5
  3. package/src/components/grid/cells/DataCell.svelte +63 -12
  4. package/src/components/grid/cells/GridCell.svelte +36 -16
  5. package/src/components/grid/cells/GutterCell.svelte +15 -8
  6. package/src/components/grid/cells/HeaderCell.svelte +3 -3
  7. package/src/components/grid/cells/RelationshipCell.svelte +16 -8
  8. package/src/components/grid/controls/BulkDeleteHandler.svelte +98 -13
  9. package/src/components/grid/controls/BulkDuplicationHandler.svelte +79 -0
  10. package/src/components/grid/controls/ClipboardHandler.svelte +67 -0
  11. package/src/components/grid/controls/ColumnsSettingButton.svelte +5 -10
  12. package/src/components/grid/controls/SizeButton.svelte +6 -13
  13. package/src/components/grid/controls/SortButton.svelte +8 -22
  14. package/src/components/grid/layout/ButtonColumn.svelte +12 -6
  15. package/src/components/grid/layout/Grid.svelte +11 -7
  16. package/src/components/grid/layout/GridBody.svelte +2 -2
  17. package/src/components/grid/layout/GridRow.svelte +12 -6
  18. package/src/components/grid/layout/GridScrollWrapper.svelte +9 -7
  19. package/src/components/grid/layout/HeaderRow.svelte +2 -2
  20. package/src/components/grid/layout/NewColumnButton.svelte +11 -5
  21. package/src/components/grid/layout/NewRow.svelte +16 -12
  22. package/src/components/grid/layout/StickyColumn.svelte +24 -14
  23. package/src/components/grid/lib/utils.js +4 -4
  24. package/src/components/grid/overlays/KeyboardManager.svelte +144 -95
  25. package/src/components/grid/overlays/MenuOverlay.svelte +114 -63
  26. package/src/components/grid/overlays/ReorderOverlay.svelte +14 -18
  27. package/src/components/grid/overlays/ResizeOverlay.svelte +8 -21
  28. package/src/components/grid/stores/clipboard.js +215 -18
  29. package/src/components/grid/stores/columns.js +78 -97
  30. package/src/components/grid/stores/conditions.js +157 -0
  31. package/src/components/grid/stores/config.js +2 -2
  32. package/src/components/grid/stores/datasource.js +4 -14
  33. package/src/components/grid/stores/datasources/nonPlus.js +2 -4
  34. package/src/components/grid/stores/datasources/table.js +6 -5
  35. package/src/components/grid/stores/datasources/viewV2.js +7 -9
  36. package/src/components/grid/stores/index.js +5 -3
  37. package/src/components/grid/stores/menu.js +40 -6
  38. package/src/components/grid/stores/pagination.js +9 -3
  39. package/src/components/grid/stores/reorder.js +67 -42
  40. package/src/components/grid/stores/resize.js +1 -1
  41. package/src/components/grid/stores/rows.js +220 -85
  42. package/src/components/grid/stores/scroll.js +31 -28
  43. package/src/components/grid/stores/ui.js +295 -70
  44. package/src/components/grid/stores/users.js +2 -2
  45. package/src/components/grid/stores/validation.js +43 -16
  46. package/src/components/grid/stores/viewport.js +30 -24
  47. package/src/components/index.js +1 -0
  48. package/src/constants.js +3 -0
  49. package/src/themes/midnight.css +18 -17
  50. package/src/themes/nord.css +2 -1
  51. package/src/utils/utils.js +2 -0
@@ -1,37 +1,33 @@
1
1
  <script>
2
2
  import { getContext } from "svelte"
3
3
  import GridScrollWrapper from "../layout/GridScrollWrapper.svelte"
4
- import { DefaultRowHeight, GutterWidth } from "../lib/constants"
4
+ import { DefaultRowHeight } from "../lib/constants"
5
5
 
6
6
  const {
7
7
  isReordering,
8
8
  reorder,
9
- visibleColumns,
10
- stickyColumn,
9
+ columnLookupMap,
11
10
  rowHeight,
12
11
  renderedRows,
13
12
  scrollLeft,
13
+ stickyWidth,
14
14
  } = getContext("grid")
15
15
 
16
- $: targetColumn = $reorder.targetColumn
17
- $: minLeft = GutterWidth + ($stickyColumn?.width || 0)
18
- $: left = getLeft(targetColumn, $stickyColumn, $visibleColumns, $scrollLeft)
16
+ $: targetColumn = $columnLookupMap[$reorder.targetColumn]
17
+ $: insertAfter = $reorder.insertAfter
18
+ $: left = getLeft(targetColumn, insertAfter, $scrollLeft)
19
19
  $: height = $rowHeight * $renderedRows.length + DefaultRowHeight
20
20
  $: style = `left:${left}px; height:${height}px;`
21
- $: visible = $isReordering && left >= minLeft
21
+ $: visible = $isReordering && left >= $stickyWidth
22
22
 
23
- const getLeft = (targetColumn, stickyColumn, visibleColumns, scrollLeft) => {
24
- let left = GutterWidth + (stickyColumn?.width || 0) - scrollLeft
25
-
26
- // If this is not the sticky column, add additional left space
27
- if (targetColumn !== stickyColumn?.name) {
28
- const column = visibleColumns.find(x => x.name === targetColumn)
29
- if (!column) {
30
- return left
31
- }
32
- left += column.left + column.width
23
+ const getLeft = (targetColumn, insertAfter, scrollLeft) => {
24
+ if (!targetColumn) {
25
+ return 0
26
+ }
27
+ let left = targetColumn.__left - scrollLeft
28
+ if (insertAfter) {
29
+ left += targetColumn.width
33
30
  }
34
-
35
31
  return left
36
32
  }
37
33
  </script>
@@ -1,41 +1,28 @@
1
1
  <script>
2
2
  import { getContext } from "svelte"
3
- import { GutterWidth } from "../lib/constants"
4
3
 
5
- const { resize, visibleColumns, stickyColumn, isReordering, scrollLeft } =
4
+ const { resize, visibleColumns, isReordering, scrollLeft } =
6
5
  getContext("grid")
7
6
 
8
- $: offset = GutterWidth + ($stickyColumn?.width || 0)
9
- $: activeColumn = $resize.column
10
-
11
- const getStyle = (column, offset, scrollLeft) => {
12
- const left = offset + column.left + column.width - scrollLeft
7
+ const getStyle = (column, scrollLeft) => {
8
+ let left = column.__left + column.width
9
+ if (!column.primaryDisplay) {
10
+ left -= scrollLeft
11
+ }
13
12
  return `left:${left}px;`
14
13
  }
15
14
  </script>
16
15
 
17
16
  <!-- svelte-ignore a11y-no-static-element-interactions -->
18
17
  {#if !$isReordering}
19
- {#if $stickyColumn}
20
- <div
21
- class="resize-slider"
22
- class:visible={activeColumn === $stickyColumn.name}
23
- on:mousedown={e => resize.actions.startResizing($stickyColumn, e)}
24
- on:touchstart={e => resize.actions.startResizing($stickyColumn, e)}
25
- on:dblclick={() => resize.actions.resetSize($stickyColumn)}
26
- style="left:{GutterWidth + $stickyColumn.width}px;"
27
- >
28
- <div class="resize-indicator" />
29
- </div>
30
- {/if}
31
18
  {#each $visibleColumns as column}
32
19
  <div
33
20
  class="resize-slider"
34
- class:visible={activeColumn === column.name}
21
+ class:visible={$resize.column === column.name}
35
22
  on:mousedown={e => resize.actions.startResizing(column, e)}
36
23
  on:touchstart={e => resize.actions.startResizing(column, e)}
37
24
  on:dblclick={() => resize.actions.resetSize(column)}
38
- style={getStyle(column, offset, $scrollLeft)}
25
+ style={getStyle(column, $scrollLeft)}
39
26
  >
40
27
  <div class="resize-indicator" />
41
28
  </div>
@@ -1,40 +1,237 @@
1
- import { writable, get } from "svelte/store"
1
+ import { derived, writable, get } from "svelte/store"
2
2
  import { Helpers } from "@budibase/bbui"
3
+ import { parseCellID, getCellID } from "../lib/utils"
4
+ import { NewRowID } from "../lib/constants"
3
5
 
4
6
  export const createStores = () => {
5
- const copiedCell = writable(null)
7
+ const clipboard = writable({
8
+ value: null,
9
+ multiCellCopy: false,
10
+ })
11
+ return {
12
+ clipboard,
13
+ }
14
+ }
15
+
16
+ export const deriveStores = context => {
17
+ const { clipboard, focusedCellAPI, selectedCellCount, config, focusedRowId } =
18
+ context
19
+
20
+ // Derive whether or not we're able to copy
21
+ const copyAllowed = derived(focusedCellAPI, $focusedCellAPI => {
22
+ return $focusedCellAPI != null
23
+ })
24
+
25
+ // Derive whether or not we're able to paste
26
+ const pasteAllowed = derived(
27
+ [clipboard, focusedCellAPI, selectedCellCount, config, focusedRowId],
28
+ ([
29
+ $clipboard,
30
+ $focusedCellAPI,
31
+ $selectedCellCount,
32
+ $config,
33
+ $focusedRowId,
34
+ ]) => {
35
+ if (
36
+ $clipboard.value == null ||
37
+ !$config.canEditRows ||
38
+ !$focusedCellAPI ||
39
+ $focusedRowId === NewRowID
40
+ ) {
41
+ return false
42
+ }
43
+
44
+ // Prevent single-single pasting if the cell is readonly
45
+ const multiCellPaste = $selectedCellCount > 1
46
+ if (
47
+ !$clipboard.multiCellCopy &&
48
+ !multiCellPaste &&
49
+ $focusedCellAPI.isReadonly()
50
+ ) {
51
+ return false
52
+ }
53
+ return true
54
+ }
55
+ )
6
56
 
7
57
  return {
8
- copiedCell,
58
+ copyAllowed,
59
+ pasteAllowed,
9
60
  }
10
61
  }
11
62
 
12
63
  export const createActions = context => {
13
- const { copiedCell, focusedCellAPI } = context
64
+ const {
65
+ clipboard,
66
+ focusedCellAPI,
67
+ copyAllowed,
68
+ pasteAllowed,
69
+ selectedCells,
70
+ selectedCellCount,
71
+ rowLookupMap,
72
+ rowChangeCache,
73
+ rows,
74
+ focusedCellId,
75
+ columnLookupMap,
76
+ visibleColumns,
77
+ } = context
14
78
 
79
+ // Copies the currently selected value (or values)
15
80
  const copy = () => {
16
- const value = get(focusedCellAPI)?.getValue()
17
- copiedCell.set(value)
18
-
19
- // Also copy a stringified version to the clipboard
20
- let stringified = ""
21
- if (value != null && value !== "") {
22
- // Only conditionally stringify to avoid redundant quotes around text
23
- stringified = typeof value === "object" ? JSON.stringify(value) : value
81
+ if (!get(copyAllowed)) {
82
+ return
83
+ }
84
+ const $selectedCells = get(selectedCells)
85
+ const $focusedCellAPI = get(focusedCellAPI)
86
+ const $selectedCellCount = get(selectedCellCount)
87
+ const multiCellCopy = $selectedCellCount > 1
88
+
89
+ // Multiple values to copy
90
+ if (multiCellCopy) {
91
+ const $rowLookupMap = get(rowLookupMap)
92
+ const $rowChangeCache = get(rowChangeCache)
93
+
94
+ // Extract value of each selected cell, accounting for the change cache
95
+ let value = []
96
+ for (let row of $selectedCells) {
97
+ const rowValues = []
98
+ for (let cellId of row) {
99
+ const { rowId, field } = parseCellID(cellId)
100
+ const row = {
101
+ ...$rowLookupMap[rowId],
102
+ ...$rowChangeCache[rowId],
103
+ }
104
+ rowValues.push(row[field])
105
+ }
106
+ value.push(rowValues)
107
+ }
108
+
109
+ // Update state
110
+ clipboard.set({
111
+ value,
112
+ multiCellCopy: true,
113
+ })
114
+ } else {
115
+ // Single value to copy
116
+ const value = $focusedCellAPI.getValue()
117
+ clipboard.set({
118
+ value,
119
+ multiCellCopy,
120
+ })
121
+
122
+ // Also copy a stringified version to the clipboard
123
+ let stringified = ""
124
+ if (value != null && value !== "") {
125
+ // Only conditionally stringify to avoid redundant quotes around text
126
+ stringified = typeof value === "object" ? JSON.stringify(value) : value
127
+ }
128
+ Helpers.copyToClipboard(stringified)
24
129
  }
25
- Helpers.copyToClipboard(stringified)
26
130
  }
27
131
 
28
- const paste = () => {
29
- const $copiedCell = get(copiedCell)
30
- const $focusedCellAPI = get(focusedCellAPI)
31
- if ($copiedCell != null && $focusedCellAPI) {
32
- $focusedCellAPI.setValue($copiedCell)
132
+ // Pastes the previously copied value(s) into the selected cell(s)
133
+ const paste = async progressCallback => {
134
+ if (!get(pasteAllowed)) {
135
+ return
136
+ }
137
+ const { value, multiCellCopy } = get(clipboard)
138
+ const multiCellPaste = get(selectedCellCount) > 1
139
+
140
+ // Choose paste strategy
141
+ if (multiCellCopy) {
142
+ if (multiCellPaste) {
143
+ // Multi to multi - try pasting into all selected cells
144
+ let newValue = value
145
+
146
+ // If we are pasting into more rows than we copied, but the number of
147
+ // columns match, then repeat the copied values as required
148
+ const $selectedCells = get(selectedCells)
149
+ const selectedRows = $selectedCells.length
150
+ const selectedColumns = $selectedCells[0].length
151
+ const copiedRows = value.length
152
+ const copiedColumns = value[0].length
153
+ if (selectedRows > copiedRows && selectedColumns === copiedColumns) {
154
+ newValue = []
155
+ for (let i = 0; i < selectedRows; i++) {
156
+ newValue.push(value[i % copiedRows])
157
+ }
158
+ }
159
+
160
+ // Paste the new value
161
+ await pasteIntoSelectedCells(newValue, progressCallback)
162
+ } else {
163
+ // Multi to single - expand to paste all values
164
+ // Get indices of focused cell
165
+ const $focusedCellId = get(focusedCellId)
166
+ const { rowId, field } = parseCellID($focusedCellId)
167
+ const $rowLookupMap = get(rowLookupMap)
168
+ const $columnLookupMap = get(columnLookupMap)
169
+ const rowIdx = $rowLookupMap[rowId].__idx
170
+ const colIdx = $columnLookupMap[field].__idx
171
+
172
+ // Get limits of how many rows and columns we're able to paste into
173
+ const $rows = get(rows)
174
+ const $visibleColumns = get(visibleColumns)
175
+ const colCount = $visibleColumns.length
176
+ const rowCount = $rows.length
177
+ const selectedRows = value.length
178
+ const selectedColumns = value[0].length
179
+ const rowExtent = Math.min(selectedRows, rowCount - rowIdx) - 1
180
+ const colExtent = Math.min(selectedColumns, colCount - colIdx) - 1
181
+
182
+ // Get the target cell ID (bottom right of our pastable extent)
183
+ const targetRowId = $rows[rowIdx + rowExtent]._id
184
+ const targetColName = $visibleColumns[colIdx + colExtent].name
185
+ const targetCellId = getCellID(targetRowId, targetColName)
186
+
187
+ // Paste into target cell range
188
+ if (targetCellId === $focusedCellId) {
189
+ // Single cell edge case
190
+ get(focusedCellAPI).setValue(value[0][0])
191
+ } else {
192
+ // Select the new cells to paste into, then paste
193
+ selectedCells.actions.selectRange($focusedCellId, targetCellId)
194
+ await pasteIntoSelectedCells(value, progressCallback)
195
+ }
196
+ }
197
+ } else {
198
+ if (multiCellPaste) {
199
+ // Single to multi - duplicate value to all selected cells
200
+ const newValue = get(selectedCells).map(row => row.map(() => value))
201
+ await pasteIntoSelectedCells(newValue, progressCallback)
202
+ } else {
203
+ // Single to single - just update the cell's value
204
+ get(focusedCellAPI).setValue(value)
205
+ }
206
+ }
207
+ }
208
+
209
+ // Paste the specified value into the currently selected cells
210
+ const pasteIntoSelectedCells = async (value, progressCallback) => {
211
+ const $selectedCells = get(selectedCells)
212
+
213
+ // Find the extent at which we can paste
214
+ const rowExtent = Math.min(value.length, $selectedCells.length)
215
+ const colExtent = Math.min(value[0].length, $selectedCells[0].length)
216
+
217
+ // Build change map
218
+ let changeMap = {}
219
+ for (let rowIdx = 0; rowIdx < rowExtent; rowIdx++) {
220
+ for (let colIdx = 0; colIdx < colExtent; colIdx++) {
221
+ const cellId = $selectedCells[rowIdx][colIdx]
222
+ const { rowId, field } = parseCellID(cellId)
223
+ if (!changeMap[rowId]) {
224
+ changeMap[rowId] = {}
225
+ }
226
+ changeMap[rowId][field] = value[rowIdx][colIdx]
227
+ }
33
228
  }
229
+ await rows.actions.bulkUpdate(changeMap, progressCallback)
34
230
  }
35
231
 
36
232
  return {
37
233
  clipboard: {
234
+ ...clipboard,
38
235
  actions: {
39
236
  copy,
40
237
  paste,
@@ -1,74 +1,73 @@
1
1
  import { derived, get, writable } from "svelte/store"
2
- import { GutterWidth, DefaultColumnWidth } from "../lib/constants"
2
+ import { DefaultColumnWidth, GutterWidth } from "../lib/constants"
3
3
 
4
4
  export const createStores = () => {
5
5
  const columns = writable([])
6
- const stickyColumn = writable(null)
7
-
8
- // Derive an enriched version of columns with left offsets and indexes
9
- // automatically calculated
10
- const enrichedColumns = derived(
11
- columns,
12
- $columns => {
13
- let offset = 0
14
- return $columns.map(column => {
15
- const enriched = {
16
- ...column,
17
- left: offset,
18
- }
19
- if (column.visible) {
20
- offset += column.width
21
- }
22
- return enriched
23
- })
24
- },
25
- []
26
- )
27
6
 
28
- // Derived list of columns which have not been explicitly hidden
29
- const visibleColumns = derived(
30
- enrichedColumns,
31
- $columns => {
32
- return $columns.filter(col => col.visible)
33
- },
34
- []
35
- )
7
+ // Enrich columns with metadata about their display position
8
+ const enrichedColumns = derived(columns, $columns => {
9
+ let offset = GutterWidth
10
+ let idx = 0
11
+ return $columns.map(col => {
12
+ const enriched = {
13
+ ...col,
14
+ __idx: idx,
15
+ __left: offset,
16
+ }
17
+ if (col.visible) {
18
+ idx++
19
+ offset += col.width
20
+ }
21
+ return enriched
22
+ })
23
+ })
36
24
 
37
25
  return {
38
26
  columns: {
39
27
  ...columns,
40
28
  subscribe: enrichedColumns.subscribe,
41
29
  },
42
- stickyColumn,
43
- visibleColumns,
44
30
  }
45
31
  }
46
32
 
47
33
  export const deriveStores = context => {
48
- const { columns, stickyColumn } = context
49
-
50
- // Quick access to all columns
51
- const allColumns = derived(
52
- [columns, stickyColumn],
53
- ([$columns, $stickyColumn]) => {
54
- let allCols = $columns || []
55
- if ($stickyColumn) {
56
- allCols = [...allCols, $stickyColumn]
57
- }
58
- return allCols
59
- }
60
- )
34
+ const { columns } = context
35
+
36
+ // Derive a lookup map for all columns by name
37
+ const columnLookupMap = derived(columns, $columns => {
38
+ let map = {}
39
+ $columns.forEach(column => {
40
+ map[column.name] = column
41
+ })
42
+ return map
43
+ })
44
+
45
+ // Derived list of columns which have not been explicitly hidden
46
+ const visibleColumns = derived(columns, $columns => {
47
+ return $columns.filter(col => col.visible)
48
+ })
49
+
50
+ // Split visible columns into their discrete types
51
+ const displayColumn = derived(visibleColumns, $visibleColumns => {
52
+ return $visibleColumns.find(col => col.primaryDisplay)
53
+ })
54
+ const scrollableColumns = derived(visibleColumns, $visibleColumns => {
55
+ return $visibleColumns.filter(col => !col.primaryDisplay)
56
+ })
61
57
 
62
58
  // Derive if we have any normal columns
63
- const hasNonAutoColumn = derived(allColumns, $allColumns => {
64
- const normalCols = $allColumns.filter(column => {
59
+ const hasNonAutoColumn = derived(columns, $columns => {
60
+ const normalCols = $columns.filter(column => {
65
61
  return !column.schema?.autocolumn
66
62
  })
67
63
  return normalCols.length > 0
68
64
  })
69
65
 
70
66
  return {
71
- allColumns,
67
+ displayColumn,
68
+ columnLookupMap,
69
+ visibleColumns,
70
+ scrollableColumns,
72
71
  hasNonAutoColumn,
73
72
  }
74
73
  }
@@ -87,60 +86,57 @@ export const createActions = context => {
87
86
  await datasource.actions.saveSchemaMutations()
88
87
  }
89
88
 
89
+ // Checks if a column is readonly
90
+ const isReadonly = column => {
91
+ if (!column?.schema) {
92
+ return false
93
+ }
94
+ return (
95
+ column.schema.autocolumn ||
96
+ column.schema.disabled ||
97
+ column.schema.type === "formula" ||
98
+ column.schema.readonly
99
+ )
100
+ }
101
+
90
102
  return {
91
103
  columns: {
92
104
  ...columns,
93
105
  actions: {
94
106
  changeAllColumnWidths,
107
+ isReadonly,
95
108
  },
96
109
  },
97
110
  }
98
111
  }
99
112
 
100
113
  export const initialise = context => {
101
- const {
102
- definition,
103
- columns,
104
- stickyColumn,
105
- allColumns,
106
- enrichedSchema,
107
- compact,
108
- } = context
114
+ const { definition, columns, displayColumn, enrichedSchema } = context
109
115
 
110
116
  // Merge new schema fields with existing schema in order to preserve widths
111
117
  const processColumns = $enrichedSchema => {
112
118
  if (!$enrichedSchema) {
113
119
  columns.set([])
114
- stickyColumn.set(null)
115
120
  return
116
121
  }
117
122
  const $definition = get(definition)
118
- const $allColumns = get(allColumns)
119
- const $stickyColumn = get(stickyColumn)
120
- const $compact = get(compact)
123
+ const $columns = get(columns)
124
+ const $displayColumn = get(displayColumn)
121
125
 
122
126
  // Find primary display
123
127
  let primaryDisplay
124
- const candidatePD = $definition.primaryDisplay || $stickyColumn?.name
128
+ const candidatePD = $definition.primaryDisplay || $displayColumn?.name
125
129
  if (candidatePD && $enrichedSchema[candidatePD]) {
126
130
  primaryDisplay = candidatePD
127
131
  }
128
132
 
129
- // Get field list
130
- let fields = []
131
- Object.keys($enrichedSchema).forEach(field => {
132
- if ($compact || field !== primaryDisplay) {
133
- fields.push(field)
134
- }
135
- })
136
-
137
133
  // Update columns, removing extraneous columns and adding missing ones
138
134
  columns.set(
139
- fields
135
+ Object.keys($enrichedSchema)
140
136
  .map(field => {
141
137
  const fieldSchema = $enrichedSchema[field]
142
- const oldColumn = $allColumns?.find(x => x.name === field)
143
- return {
138
+ const oldColumn = $columns?.find(col => col.name === field)
139
+ let column = {
144
140
  name: field,
145
141
  label: fieldSchema.displayName || field,
146
142
  schema: fieldSchema,
@@ -148,19 +144,25 @@ export const initialise = context => {
148
144
  visible: fieldSchema.visible ?? true,
149
145
  readonly: fieldSchema.readonly,
150
146
  order: fieldSchema.order ?? oldColumn?.order,
151
- primaryDisplay: field === primaryDisplay,
147
+ conditions: fieldSchema.conditions,
152
148
  }
149
+ // Override a few properties for primary display
150
+ if (field === primaryDisplay) {
151
+ column.visible = true
152
+ column.order = 0
153
+ column.primaryDisplay = true
154
+ }
155
+ return column
153
156
  })
154
157
  .sort((a, b) => {
155
- // If we don't have a pinned column then primary display will be in
156
- // the normal columns list, and should be first
158
+ // Display column should always come first
157
159
  if (a.name === primaryDisplay) {
158
160
  return -1
159
161
  } else if (b.name === primaryDisplay) {
160
162
  return 1
161
163
  }
162
164
 
163
- // Sort by order first
165
+ // Then sort by order
164
166
  const orderA = a.order
165
167
  const orderB = b.order
166
168
  if (orderA != null && orderB != null) {
@@ -180,29 +182,8 @@ export const initialise = context => {
180
182
  return autoColA ? 1 : -1
181
183
  })
182
184
  )
183
-
184
- // Update sticky column
185
- if ($compact || !primaryDisplay) {
186
- stickyColumn.set(null)
187
- return
188
- }
189
- const stickySchema = $enrichedSchema[primaryDisplay]
190
- const oldStickyColumn = $allColumns?.find(x => x.name === primaryDisplay)
191
- stickyColumn.set({
192
- name: primaryDisplay,
193
- label: stickySchema.displayName || primaryDisplay,
194
- schema: stickySchema,
195
- width: stickySchema.width || oldStickyColumn?.width || DefaultColumnWidth,
196
- visible: true,
197
- order: 0,
198
- left: GutterWidth,
199
- primaryDisplay: true,
200
- })
201
185
  }
202
186
 
203
187
  // Process columns when schema changes
204
188
  enrichedSchema.subscribe(processColumns)
205
-
206
- // Process columns when compact flag changes
207
- compact.subscribe(() => processColumns(get(enrichedSchema)))
208
189
  }