@budibase/frontend-core 2.6.19-alpha.12 → 2.6.19-alpha.14
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.
- package/package.json +4 -4
- package/src/api/datasources.js +11 -0
- package/src/components/grid/cells/BooleanCell.svelte +3 -0
- package/src/components/grid/cells/DataCell.svelte +2 -0
- package/src/components/grid/cells/GridCell.svelte +9 -4
- package/src/components/grid/cells/GutterCell.svelte +2 -10
- package/src/components/grid/cells/HeaderCell.svelte +5 -1
- package/src/components/grid/layout/Grid.svelte +8 -0
- package/src/components/grid/layout/GridBody.svelte +5 -1
- package/src/components/grid/layout/GridRow.svelte +3 -2
- package/src/components/grid/layout/HeaderRow.svelte +1 -1
- package/src/components/grid/layout/KeyboardShortcut.svelte +1 -1
- package/src/components/grid/layout/NewRow.svelte +3 -3
- package/src/components/grid/layout/StickyColumn.svelte +2 -1
- package/src/components/grid/overlays/KeyboardManager.svelte +1 -4
- package/src/components/grid/stores/reorder.js +77 -9
- package/src/components/grid/stores/ui.js +20 -1
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/frontend-core",
|
|
3
|
-
"version": "2.6.19-alpha.
|
|
3
|
+
"version": "2.6.19-alpha.14",
|
|
4
4
|
"description": "Budibase frontend core libraries used in builder and client",
|
|
5
5
|
"author": "Budibase",
|
|
6
6
|
"license": "MPL-2.0",
|
|
7
7
|
"svelte": "src/index.js",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@budibase/bbui": "2.6.19-alpha.
|
|
10
|
-
"@budibase/shared-core": "2.6.19-alpha.
|
|
9
|
+
"@budibase/bbui": "2.6.19-alpha.14",
|
|
10
|
+
"@budibase/shared-core": "2.6.19-alpha.14",
|
|
11
11
|
"dayjs": "^1.11.7",
|
|
12
12
|
"lodash": "^4.17.21",
|
|
13
13
|
"socket.io-client": "^4.6.1",
|
|
14
14
|
"svelte": "^3.46.2"
|
|
15
15
|
},
|
|
16
|
-
"gitHead": "
|
|
16
|
+
"gitHead": "9e6f7b9f573647eb08850781396dc0d4b874a4b5"
|
|
17
17
|
}
|
package/src/api/datasources.js
CHANGED
|
@@ -58,4 +58,15 @@ export const buildDatasourceEndpoints = API => ({
|
|
|
58
58
|
url: `/api/datasources/${datasourceId}/${datasourceRev}`,
|
|
59
59
|
})
|
|
60
60
|
},
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Validate a datasource configuration
|
|
64
|
+
* @param datasource the datasource configuration to validate
|
|
65
|
+
*/
|
|
66
|
+
validateDatasource: async datasource => {
|
|
67
|
+
return await API.post({
|
|
68
|
+
url: `/api/datasources/verify`,
|
|
69
|
+
body: { datasource },
|
|
70
|
+
})
|
|
71
|
+
},
|
|
61
72
|
})
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
export let selected
|
|
12
12
|
export let rowFocused
|
|
13
13
|
export let rowIdx
|
|
14
|
+
export let topRow = false
|
|
14
15
|
export let focused
|
|
15
16
|
export let selectedUser
|
|
16
17
|
export let column
|
|
@@ -68,6 +69,7 @@
|
|
|
68
69
|
{highlighted}
|
|
69
70
|
{selected}
|
|
70
71
|
{rowIdx}
|
|
72
|
+
{topRow}
|
|
71
73
|
{focused}
|
|
72
74
|
{selectedUser}
|
|
73
75
|
{readonly}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
export let selectedUser = null
|
|
7
7
|
export let error = null
|
|
8
8
|
export let rowIdx
|
|
9
|
+
export let topRow = false
|
|
9
10
|
export let defaultHeight = false
|
|
10
11
|
export let center = false
|
|
11
12
|
export let readonly = false
|
|
@@ -31,13 +32,14 @@
|
|
|
31
32
|
class:readonly
|
|
32
33
|
class:default-height={defaultHeight}
|
|
33
34
|
class:selected-other={selectedUser != null}
|
|
35
|
+
class:alt={rowIdx % 2 === 1}
|
|
36
|
+
class:top={topRow}
|
|
34
37
|
on:focus
|
|
35
38
|
on:mousedown
|
|
36
39
|
on:mouseup
|
|
37
40
|
on:click
|
|
38
41
|
on:contextmenu
|
|
39
42
|
{style}
|
|
40
|
-
data-row={rowIdx}
|
|
41
43
|
>
|
|
42
44
|
{#if error}
|
|
43
45
|
<div class="label">
|
|
@@ -70,6 +72,9 @@
|
|
|
70
72
|
width: 0;
|
|
71
73
|
--cell-color: transparent;
|
|
72
74
|
}
|
|
75
|
+
.cell.alt {
|
|
76
|
+
--cell-background: var(--cell-background-alt);
|
|
77
|
+
}
|
|
73
78
|
.cell.default-height {
|
|
74
79
|
height: var(--default-row-height);
|
|
75
80
|
}
|
|
@@ -98,8 +103,8 @@
|
|
|
98
103
|
.cell.selected-other:not(.focused):after {
|
|
99
104
|
border-radius: 0 2px 2px 2px;
|
|
100
105
|
}
|
|
101
|
-
.cell
|
|
102
|
-
.cell
|
|
106
|
+
.cell.top.error:after,
|
|
107
|
+
.cell.top.selected-other:not(.focused):after {
|
|
103
108
|
border-radius: 2px 2px 2px 0;
|
|
104
109
|
}
|
|
105
110
|
|
|
@@ -152,7 +157,7 @@
|
|
|
152
157
|
overflow: hidden;
|
|
153
158
|
user-select: none;
|
|
154
159
|
}
|
|
155
|
-
.cell
|
|
160
|
+
.cell.top .label {
|
|
156
161
|
bottom: auto;
|
|
157
162
|
top: 100%;
|
|
158
163
|
border-radius: 0 2px 2px 2px;
|
|
@@ -21,16 +21,7 @@
|
|
|
21
21
|
svelteDispatch("select")
|
|
22
22
|
const id = row?._id
|
|
23
23
|
if (id) {
|
|
24
|
-
selectedRows.
|
|
25
|
-
let newState = {
|
|
26
|
-
...state,
|
|
27
|
-
[id]: !state[id],
|
|
28
|
-
}
|
|
29
|
-
if (!newState[id]) {
|
|
30
|
-
delete newState[id]
|
|
31
|
-
}
|
|
32
|
-
return newState
|
|
33
|
-
})
|
|
24
|
+
selectedRows.actions.toggleRow(id)
|
|
34
25
|
}
|
|
35
26
|
}
|
|
36
27
|
|
|
@@ -47,6 +38,7 @@
|
|
|
47
38
|
highlighted={rowFocused || rowHovered}
|
|
48
39
|
selected={rowSelected}
|
|
49
40
|
{defaultHeight}
|
|
41
|
+
rowIdx={row?.__idx}
|
|
50
42
|
>
|
|
51
43
|
<div class="gutter">
|
|
52
44
|
{#if $$slots.default}
|
|
@@ -196,7 +196,11 @@
|
|
|
196
196
|
<MenuItem disabled={!canMoveRight} icon="ChevronRight" on:click={moveRight}>
|
|
197
197
|
Move right
|
|
198
198
|
</MenuItem>
|
|
199
|
-
<MenuItem
|
|
199
|
+
<MenuItem
|
|
200
|
+
disabled={idx === "sticky"}
|
|
201
|
+
icon="VisibilityOff"
|
|
202
|
+
on:click={hideColumn}>Hide column</MenuItem
|
|
203
|
+
>
|
|
200
204
|
</Menu>
|
|
201
205
|
</Popover>
|
|
202
206
|
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
export let allowExpandRows = true
|
|
42
42
|
export let allowEditRows = true
|
|
43
43
|
export let allowDeleteRows = true
|
|
44
|
+
export let stripeRows = false
|
|
44
45
|
|
|
45
46
|
// Unique identifier for DOM nodes inside this instance
|
|
46
47
|
const rand = Math.random()
|
|
@@ -55,6 +56,7 @@
|
|
|
55
56
|
allowExpandRows,
|
|
56
57
|
allowEditRows,
|
|
57
58
|
allowDeleteRows,
|
|
59
|
+
stripeRows,
|
|
58
60
|
})
|
|
59
61
|
|
|
60
62
|
// Build up context
|
|
@@ -90,6 +92,7 @@
|
|
|
90
92
|
allowExpandRows,
|
|
91
93
|
allowEditRows,
|
|
92
94
|
allowDeleteRows,
|
|
95
|
+
stripeRows,
|
|
93
96
|
})
|
|
94
97
|
|
|
95
98
|
// Set context for children to consume
|
|
@@ -107,6 +110,7 @@
|
|
|
107
110
|
id="grid-{rand}"
|
|
108
111
|
class:is-resizing={$isResizing}
|
|
109
112
|
class:is-reordering={$isReordering}
|
|
113
|
+
class:stripe={$config.stripeRows}
|
|
110
114
|
style="--row-height:{$rowHeight}px; --default-row-height:{DefaultRowHeight}px; --gutter-width:{GutterWidth}px; --max-cell-render-height:{MaxCellRenderHeight}px; --max-cell-render-width-overflow:{MaxCellRenderWidthOverflow}px; --content-lines:{$contentLines};"
|
|
111
115
|
>
|
|
112
116
|
<div class="controls">
|
|
@@ -169,6 +173,7 @@
|
|
|
169
173
|
/* Variables */
|
|
170
174
|
--cell-background: var(--spectrum-global-color-gray-50);
|
|
171
175
|
--cell-background-hover: var(--spectrum-global-color-gray-100);
|
|
176
|
+
--cell-background-alt: var(--cell-background);
|
|
172
177
|
--cell-padding: 8px;
|
|
173
178
|
--cell-spacing: 4px;
|
|
174
179
|
--cell-border: 1px solid var(--spectrum-global-color-gray-200);
|
|
@@ -185,6 +190,9 @@
|
|
|
185
190
|
.grid.is-reordering :global(*) {
|
|
186
191
|
cursor: grabbing !important;
|
|
187
192
|
}
|
|
193
|
+
.grid.stripe {
|
|
194
|
+
--cell-background-alt: var(--spectrum-global-color-gray-75);
|
|
195
|
+
}
|
|
188
196
|
|
|
189
197
|
.grid-data-outer,
|
|
190
198
|
.grid-data-inner {
|
|
@@ -36,7 +36,11 @@
|
|
|
36
36
|
<div bind:this={body} class="grid-body">
|
|
37
37
|
<GridScrollWrapper scrollHorizontally scrollVertically wheelInteractive>
|
|
38
38
|
{#each $renderedRows as row, idx}
|
|
39
|
-
<GridRow
|
|
39
|
+
<GridRow
|
|
40
|
+
{row}
|
|
41
|
+
top={idx === 0}
|
|
42
|
+
invertY={idx >= $rowVerticalInversionIndex}
|
|
43
|
+
/>
|
|
40
44
|
{/each}
|
|
41
45
|
{#if $config.allowAddRows && $renderedColumns.length}
|
|
42
46
|
<div
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import DataCell from "../cells/DataCell.svelte"
|
|
4
4
|
|
|
5
5
|
export let row
|
|
6
|
-
export let
|
|
6
|
+
export let top = false
|
|
7
7
|
export let invertY = false
|
|
8
8
|
|
|
9
9
|
const {
|
|
@@ -41,7 +41,8 @@
|
|
|
41
41
|
invertX={columnIdx >= $columnHorizontalInversionIndex}
|
|
42
42
|
highlighted={rowHovered || rowFocused || reorderSource === column.name}
|
|
43
43
|
selected={rowSelected}
|
|
44
|
-
rowIdx={
|
|
44
|
+
rowIdx={row.__idx}
|
|
45
|
+
topRow={top}
|
|
45
46
|
focused={$focusedCellId === cellId}
|
|
46
47
|
selectedUser={$selectedCellMap[cellId]}
|
|
47
48
|
width={column.width}
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
padding: 2px 6px;
|
|
39
39
|
font-size: 12px;
|
|
40
40
|
font-weight: 600;
|
|
41
|
-
background-color: var(--spectrum-global-color-gray-
|
|
41
|
+
background-color: var(--spectrum-global-color-gray-300);
|
|
42
42
|
color: var(--spectrum-global-color-gray-700);
|
|
43
43
|
border-radius: 4px;
|
|
44
44
|
text-align: center;
|
|
@@ -167,7 +167,7 @@
|
|
|
167
167
|
focused={$focusedCellId === cellId}
|
|
168
168
|
width={$stickyColumn.width}
|
|
169
169
|
{updateValue}
|
|
170
|
-
|
|
170
|
+
topRow={offset === 0}
|
|
171
171
|
{invertY}
|
|
172
172
|
>
|
|
173
173
|
{#if $stickyColumn?.schema?.autocolumn}
|
|
@@ -193,7 +193,7 @@
|
|
|
193
193
|
row={newRow}
|
|
194
194
|
focused={$focusedCellId === cellId}
|
|
195
195
|
width={column.width}
|
|
196
|
-
|
|
196
|
+
topRow={offset === 0}
|
|
197
197
|
invertX={columnIdx >= $columnHorizontalInversionIndex}
|
|
198
198
|
{invertY}
|
|
199
199
|
>
|
|
@@ -219,7 +219,7 @@
|
|
|
219
219
|
<Button size="M" secondary newStyles on:click={clear}>
|
|
220
220
|
<div class="button-with-keys">
|
|
221
221
|
Cancel
|
|
222
|
-
<KeyboardShortcut
|
|
222
|
+
<KeyboardShortcut keybind="Esc" />
|
|
223
223
|
</div>
|
|
224
224
|
</Button>
|
|
225
225
|
</div>
|
|
@@ -4,9 +4,10 @@ const reorderInitialState = {
|
|
|
4
4
|
sourceColumn: null,
|
|
5
5
|
targetColumn: null,
|
|
6
6
|
breakpoints: [],
|
|
7
|
-
initialMouseX: null,
|
|
8
|
-
scrollLeft: 0,
|
|
9
7
|
gridLeft: 0,
|
|
8
|
+
width: 0,
|
|
9
|
+
latestX: 0,
|
|
10
|
+
increment: 0,
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
export const createStores = () => {
|
|
@@ -23,14 +24,24 @@ export const createStores = () => {
|
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
export const deriveStores = context => {
|
|
26
|
-
const {
|
|
27
|
-
|
|
27
|
+
const {
|
|
28
|
+
reorder,
|
|
29
|
+
columns,
|
|
30
|
+
visibleColumns,
|
|
31
|
+
scroll,
|
|
32
|
+
bounds,
|
|
33
|
+
stickyColumn,
|
|
34
|
+
ui,
|
|
35
|
+
maxScrollLeft,
|
|
36
|
+
} = context
|
|
37
|
+
|
|
38
|
+
let autoScrollInterval
|
|
39
|
+
let isAutoScrolling
|
|
28
40
|
|
|
29
41
|
// Callback when dragging on a colum header and starting reordering
|
|
30
42
|
const startReordering = (column, e) => {
|
|
31
43
|
const $visibleColumns = get(visibleColumns)
|
|
32
44
|
const $bounds = get(bounds)
|
|
33
|
-
const $scroll = get(scroll)
|
|
34
45
|
const $stickyColumn = get(stickyColumn)
|
|
35
46
|
ui.actions.blur()
|
|
36
47
|
|
|
@@ -51,9 +62,8 @@ export const deriveStores = context => {
|
|
|
51
62
|
sourceColumn: column,
|
|
52
63
|
targetColumn: null,
|
|
53
64
|
breakpoints,
|
|
54
|
-
initialMouseX: e.clientX,
|
|
55
|
-
scrollLeft: $scroll.left,
|
|
56
65
|
gridLeft: $bounds.left,
|
|
66
|
+
width: $bounds.width,
|
|
57
67
|
})
|
|
58
68
|
|
|
59
69
|
// Add listeners to handle mouse movement
|
|
@@ -66,12 +76,44 @@ export const deriveStores = context => {
|
|
|
66
76
|
|
|
67
77
|
// Callback when moving the mouse when reordering columns
|
|
68
78
|
const onReorderMouseMove = e => {
|
|
79
|
+
// Immediately handle the current position
|
|
80
|
+
const x = e.clientX
|
|
81
|
+
reorder.update(state => ({
|
|
82
|
+
...state,
|
|
83
|
+
latestX: x,
|
|
84
|
+
}))
|
|
85
|
+
considerReorderPosition()
|
|
86
|
+
|
|
87
|
+
// Check if we need to start auto-scrolling
|
|
88
|
+
const $reorder = get(reorder)
|
|
89
|
+
const proximityCutoff = 140
|
|
90
|
+
const speedFactor = 8
|
|
91
|
+
const rightProximity = Math.max(0, $reorder.gridLeft + $reorder.width - x)
|
|
92
|
+
const leftProximity = Math.max(0, x - $reorder.gridLeft)
|
|
93
|
+
if (rightProximity < proximityCutoff) {
|
|
94
|
+
const weight = proximityCutoff - rightProximity
|
|
95
|
+
const increment = (weight / proximityCutoff) * speedFactor
|
|
96
|
+
reorder.update(state => ({ ...state, increment }))
|
|
97
|
+
startAutoScroll()
|
|
98
|
+
} else if (leftProximity < proximityCutoff) {
|
|
99
|
+
const weight = -1 * (proximityCutoff - leftProximity)
|
|
100
|
+
const increment = (weight / proximityCutoff) * speedFactor
|
|
101
|
+
reorder.update(state => ({ ...state, increment }))
|
|
102
|
+
startAutoScroll()
|
|
103
|
+
} else {
|
|
104
|
+
stopAutoScroll()
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Actual logic to consider the current position and determine the new order
|
|
109
|
+
const considerReorderPosition = () => {
|
|
69
110
|
const $reorder = get(reorder)
|
|
111
|
+
const $scroll = get(scroll)
|
|
70
112
|
|
|
71
113
|
// Compute the closest breakpoint to the current position
|
|
72
114
|
let targetColumn
|
|
73
115
|
let minDistance = Number.MAX_SAFE_INTEGER
|
|
74
|
-
const mouseX =
|
|
116
|
+
const mouseX = $reorder.latestX - $reorder.gridLeft + $scroll.left
|
|
75
117
|
$reorder.breakpoints.forEach(point => {
|
|
76
118
|
const distance = Math.abs(point.x - mouseX)
|
|
77
119
|
if (distance < minDistance) {
|
|
@@ -79,7 +121,6 @@ export const deriveStores = context => {
|
|
|
79
121
|
targetColumn = point.column
|
|
80
122
|
}
|
|
81
123
|
})
|
|
82
|
-
|
|
83
124
|
if (targetColumn !== $reorder.targetColumn) {
|
|
84
125
|
reorder.update(state => ({
|
|
85
126
|
...state,
|
|
@@ -88,8 +129,35 @@ export const deriveStores = context => {
|
|
|
88
129
|
}
|
|
89
130
|
}
|
|
90
131
|
|
|
132
|
+
// Commences auto-scrolling in a certain direction, triggered when the mouse
|
|
133
|
+
// approaches the edges of the grid
|
|
134
|
+
const startAutoScroll = () => {
|
|
135
|
+
if (isAutoScrolling) {
|
|
136
|
+
return
|
|
137
|
+
}
|
|
138
|
+
isAutoScrolling = true
|
|
139
|
+
autoScrollInterval = setInterval(() => {
|
|
140
|
+
const $maxLeft = get(maxScrollLeft)
|
|
141
|
+
const { increment } = get(reorder)
|
|
142
|
+
scroll.update(state => ({
|
|
143
|
+
...state,
|
|
144
|
+
left: Math.max(0, Math.min($maxLeft, state.left + increment)),
|
|
145
|
+
}))
|
|
146
|
+
considerReorderPosition()
|
|
147
|
+
}, 10)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Stops auto scrolling
|
|
151
|
+
const stopAutoScroll = () => {
|
|
152
|
+
isAutoScrolling = false
|
|
153
|
+
clearInterval(autoScrollInterval)
|
|
154
|
+
}
|
|
155
|
+
|
|
91
156
|
// Callback when stopping reordering columns
|
|
92
157
|
const stopReordering = async () => {
|
|
158
|
+
// Ensure auto-scrolling is stopped
|
|
159
|
+
stopAutoScroll()
|
|
160
|
+
|
|
93
161
|
// Swap position of columns
|
|
94
162
|
let { sourceColumn, targetColumn } = get(reorder)
|
|
95
163
|
moveColumn(sourceColumn, targetColumn)
|
|
@@ -25,14 +25,33 @@ export const createStores = () => {
|
|
|
25
25
|
null
|
|
26
26
|
)
|
|
27
27
|
|
|
28
|
+
// Toggles whether a certain row ID is selected or not
|
|
29
|
+
const toggleSelectedRow = id => {
|
|
30
|
+
selectedRows.update(state => {
|
|
31
|
+
let newState = {
|
|
32
|
+
...state,
|
|
33
|
+
[id]: !state[id],
|
|
34
|
+
}
|
|
35
|
+
if (!newState[id]) {
|
|
36
|
+
delete newState[id]
|
|
37
|
+
}
|
|
38
|
+
return newState
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
|
|
28
42
|
return {
|
|
29
43
|
focusedCellId,
|
|
30
44
|
focusedCellAPI,
|
|
31
45
|
focusedRowId,
|
|
32
46
|
previousFocusedRowId,
|
|
33
|
-
selectedRows,
|
|
34
47
|
hoveredRowId,
|
|
35
48
|
rowHeight,
|
|
49
|
+
selectedRows: {
|
|
50
|
+
...selectedRows,
|
|
51
|
+
actions: {
|
|
52
|
+
toggleRow: toggleSelectedRow,
|
|
53
|
+
},
|
|
54
|
+
},
|
|
36
55
|
}
|
|
37
56
|
}
|
|
38
57
|
|