@budibase/frontend-core 2.11.34 → 2.11.35
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/components/grid/cells/GutterCell.svelte +14 -8
- package/src/components/grid/layout/GridBody.svelte +1 -1
- package/src/components/grid/layout/GridRow.svelte +2 -0
- package/src/components/grid/layout/GridScrollWrapper.svelte +46 -8
- package/src/components/grid/layout/NewRow.svelte +1 -1
- package/src/components/grid/layout/StickyColumn.svelte +2 -1
- package/src/components/grid/overlays/ScrollOverlay.svelte +21 -4
- package/src/components/grid/stores/clipboard.js +11 -1
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/frontend-core",
|
|
3
|
-
"version": "2.11.
|
|
3
|
+
"version": "2.11.35",
|
|
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.11.
|
|
10
|
-
"@budibase/shared-core": "2.11.
|
|
9
|
+
"@budibase/bbui": "2.11.35",
|
|
10
|
+
"@budibase/shared-core": "2.11.35",
|
|
11
11
|
"dayjs": "^1.10.8",
|
|
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": "04a1a5e9c5a0c2c079fb44d4117d84d98b227e66"
|
|
17
17
|
}
|
|
@@ -17,13 +17,24 @@
|
|
|
17
17
|
const { config, dispatch, selectedRows } = getContext("grid")
|
|
18
18
|
const svelteDispatch = createEventDispatcher()
|
|
19
19
|
|
|
20
|
-
const select =
|
|
20
|
+
const select = e => {
|
|
21
|
+
e.stopPropagation()
|
|
21
22
|
svelteDispatch("select")
|
|
22
23
|
const id = row?._id
|
|
23
24
|
if (id) {
|
|
24
25
|
selectedRows.actions.toggleRow(id)
|
|
25
26
|
}
|
|
26
27
|
}
|
|
28
|
+
|
|
29
|
+
const bulkDelete = e => {
|
|
30
|
+
e.stopPropagation()
|
|
31
|
+
dispatch("request-bulk-delete")
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const expand = e => {
|
|
35
|
+
e.stopPropagation()
|
|
36
|
+
svelteDispatch("expand")
|
|
37
|
+
}
|
|
27
38
|
</script>
|
|
28
39
|
|
|
29
40
|
<GridCell
|
|
@@ -56,7 +67,7 @@
|
|
|
56
67
|
{/if}
|
|
57
68
|
{/if}
|
|
58
69
|
{#if rowSelected && $config.canDeleteRows}
|
|
59
|
-
<div class="delete" on:click={
|
|
70
|
+
<div class="delete" on:click={bulkDelete}>
|
|
60
71
|
<Icon
|
|
61
72
|
name="Delete"
|
|
62
73
|
size="S"
|
|
@@ -65,12 +76,7 @@
|
|
|
65
76
|
</div>
|
|
66
77
|
{:else}
|
|
67
78
|
<div class="expand" class:visible={$config.canExpandRows && expandable}>
|
|
68
|
-
<Icon
|
|
69
|
-
size="S"
|
|
70
|
-
name="Maximize"
|
|
71
|
-
hoverable
|
|
72
|
-
on:click={() => svelteDispatch("expand")}
|
|
73
|
-
/>
|
|
79
|
+
<Icon size="S" name="Maximize" hoverable on:click={expand} />
|
|
74
80
|
</div>
|
|
75
81
|
{/if}
|
|
76
82
|
</div>
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
</script>
|
|
36
36
|
|
|
37
37
|
<div bind:this={body} class="grid-body">
|
|
38
|
-
<GridScrollWrapper scrollHorizontally scrollVertically
|
|
38
|
+
<GridScrollWrapper scrollHorizontally scrollVertically attachHandlers>
|
|
39
39
|
{#each $renderedRows as row, idx}
|
|
40
40
|
<GridRow
|
|
41
41
|
{row}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
columnHorizontalInversionIndex,
|
|
18
18
|
contentLines,
|
|
19
19
|
isDragging,
|
|
20
|
+
dispatch,
|
|
20
21
|
} = getContext("grid")
|
|
21
22
|
|
|
22
23
|
$: rowSelected = !!$selectedRows[row._id]
|
|
@@ -30,6 +31,7 @@
|
|
|
30
31
|
on:focus
|
|
31
32
|
on:mouseenter={$isDragging ? null : () => ($hoveredRowId = row._id)}
|
|
32
33
|
on:mouseleave={$isDragging ? null : () => ($hoveredRowId = null)}
|
|
34
|
+
on:click={() => dispatch("rowclick", row)}
|
|
33
35
|
>
|
|
34
36
|
{#each $renderedColumns as column, columnIdx (column.name)}
|
|
35
37
|
{@const cellId = `${row._id}-${column.name}`}
|
|
@@ -17,7 +17,11 @@
|
|
|
17
17
|
|
|
18
18
|
export let scrollVertically = false
|
|
19
19
|
export let scrollHorizontally = false
|
|
20
|
-
export let
|
|
20
|
+
export let attachHandlers = false
|
|
21
|
+
|
|
22
|
+
// Used for tracking touch events
|
|
23
|
+
let initialTouchX
|
|
24
|
+
let initialTouchY
|
|
21
25
|
|
|
22
26
|
$: style = generateStyle($scroll, $rowHeight, $hiddenColumnsWidth)
|
|
23
27
|
|
|
@@ -27,17 +31,47 @@
|
|
|
27
31
|
return `transform: translate3d(${offsetX}px, ${offsetY}px, 0);`
|
|
28
32
|
}
|
|
29
33
|
|
|
30
|
-
// Handles a wheel
|
|
34
|
+
// Handles a mouse wheel event and updates scroll state
|
|
31
35
|
const handleWheel = e => {
|
|
32
36
|
e.preventDefault()
|
|
33
|
-
|
|
37
|
+
updateScroll(e.deltaX, e.deltaY, e.clientY)
|
|
34
38
|
|
|
35
39
|
// If a context menu was visible, hide it
|
|
36
40
|
if ($menu.visible) {
|
|
37
41
|
menu.actions.close()
|
|
38
42
|
}
|
|
39
43
|
}
|
|
40
|
-
|
|
44
|
+
|
|
45
|
+
// Handles touch start events
|
|
46
|
+
const handleTouchStart = e => {
|
|
47
|
+
if (!e.touches?.[0]) return
|
|
48
|
+
initialTouchX = e.touches[0].clientX
|
|
49
|
+
initialTouchY = e.touches[0].clientY
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Handles touch move events and updates scroll state
|
|
53
|
+
const handleTouchMove = e => {
|
|
54
|
+
if (!e.touches?.[0]) return
|
|
55
|
+
e.preventDefault()
|
|
56
|
+
|
|
57
|
+
// Compute delta from previous event, and update scroll
|
|
58
|
+
const deltaX = initialTouchX - e.touches[0].clientX
|
|
59
|
+
const deltaY = initialTouchY - e.touches[0].clientY
|
|
60
|
+
updateScroll(deltaX, deltaY)
|
|
61
|
+
|
|
62
|
+
// Store position to reference in next event
|
|
63
|
+
initialTouchX = e.touches[0].clientX
|
|
64
|
+
initialTouchY = e.touches[0].clientY
|
|
65
|
+
|
|
66
|
+
// If a context menu was visible, hide it
|
|
67
|
+
if ($menu.visible) {
|
|
68
|
+
menu.actions.close()
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Updates the scroll offset by a certain delta, and ensure scrolling
|
|
73
|
+
// stays within sensible bounds. Debounced for performance.
|
|
74
|
+
const updateScroll = domDebounce((deltaX, deltaY, clientY) => {
|
|
41
75
|
const { top, left } = $scroll
|
|
42
76
|
|
|
43
77
|
// Calculate new scroll top
|
|
@@ -55,15 +89,19 @@
|
|
|
55
89
|
})
|
|
56
90
|
|
|
57
91
|
// Hover row under cursor
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
92
|
+
if (clientY != null) {
|
|
93
|
+
const y = clientY - $bounds.top + (newScrollTop % $rowHeight)
|
|
94
|
+
const hoveredRow = $renderedRows[Math.floor(y / $rowHeight)]
|
|
95
|
+
hoveredRowId.set(hoveredRow?._id)
|
|
96
|
+
}
|
|
61
97
|
})
|
|
62
98
|
</script>
|
|
63
99
|
|
|
64
100
|
<div
|
|
65
101
|
class="outer"
|
|
66
|
-
on:wheel={
|
|
102
|
+
on:wheel={attachHandlers ? handleWheel : null}
|
|
103
|
+
on:touchstart={attachHandlers ? handleTouchStart : null}
|
|
104
|
+
on:touchmove={attachHandlers ? handleTouchMove : null}
|
|
67
105
|
on:click|self={() => ($focusedCellId = null)}
|
|
68
106
|
>
|
|
69
107
|
<div {style} class="inner">
|
|
@@ -205,7 +205,7 @@
|
|
|
205
205
|
{/if}
|
|
206
206
|
</div>
|
|
207
207
|
<div class="normal-columns" transition:fade|local={{ duration: 130 }}>
|
|
208
|
-
<GridScrollWrapper scrollHorizontally
|
|
208
|
+
<GridScrollWrapper scrollHorizontally attachHandlers>
|
|
209
209
|
<div class="row">
|
|
210
210
|
{#each $renderedColumns as column, columnIdx}
|
|
211
211
|
{@const cellId = `new-${column.name}`}
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
</div>
|
|
65
65
|
|
|
66
66
|
<div class="content" on:mouseleave={() => ($hoveredRowId = null)}>
|
|
67
|
-
<GridScrollWrapper scrollVertically
|
|
67
|
+
<GridScrollWrapper scrollVertically attachHandlers>
|
|
68
68
|
{#each $renderedRows as row, idx}
|
|
69
69
|
{@const rowSelected = !!$selectedRows[row._id]}
|
|
70
70
|
{@const rowHovered = $hoveredRowId === row._id}
|
|
@@ -74,6 +74,7 @@
|
|
|
74
74
|
class="row"
|
|
75
75
|
on:mouseenter={$isDragging ? null : () => ($hoveredRowId = row._id)}
|
|
76
76
|
on:mouseleave={$isDragging ? null : () => ($hoveredRowId = null)}
|
|
77
|
+
on:click={() => dispatch("rowclick", row)}
|
|
77
78
|
>
|
|
78
79
|
<GutterCell {row} {rowFocused} {rowHovered} {rowSelected} />
|
|
79
80
|
{#if $stickyColumn}
|
|
@@ -53,18 +53,27 @@
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
const getLocation = e => {
|
|
57
|
+
return {
|
|
58
|
+
y: e.touches?.[0]?.clientY ?? e.clientY,
|
|
59
|
+
x: e.touches?.[0]?.clientX ?? e.clientX,
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
56
63
|
// V scrollbar drag handlers
|
|
57
64
|
const startVDragging = e => {
|
|
58
65
|
e.preventDefault()
|
|
59
|
-
initialMouse = e.
|
|
66
|
+
initialMouse = getLocation(e).y
|
|
60
67
|
initialScroll = $scrollTop
|
|
61
68
|
document.addEventListener("mousemove", moveVDragging)
|
|
69
|
+
document.addEventListener("touchmove", moveVDragging)
|
|
62
70
|
document.addEventListener("mouseup", stopVDragging)
|
|
71
|
+
document.addEventListener("touchend", stopVDragging)
|
|
63
72
|
isDraggingV = true
|
|
64
73
|
closeMenu()
|
|
65
74
|
}
|
|
66
75
|
const moveVDragging = domDebounce(e => {
|
|
67
|
-
const delta = e.
|
|
76
|
+
const delta = getLocation(e).y - initialMouse
|
|
68
77
|
const weight = delta / availHeight
|
|
69
78
|
const newScrollTop = initialScroll + weight * $maxScrollTop
|
|
70
79
|
scroll.update(state => ({
|
|
@@ -74,22 +83,26 @@
|
|
|
74
83
|
})
|
|
75
84
|
const stopVDragging = () => {
|
|
76
85
|
document.removeEventListener("mousemove", moveVDragging)
|
|
86
|
+
document.removeEventListener("touchmove", moveVDragging)
|
|
77
87
|
document.removeEventListener("mouseup", stopVDragging)
|
|
88
|
+
document.removeEventListener("touchend", stopVDragging)
|
|
78
89
|
isDraggingV = false
|
|
79
90
|
}
|
|
80
91
|
|
|
81
92
|
// H scrollbar drag handlers
|
|
82
93
|
const startHDragging = e => {
|
|
83
94
|
e.preventDefault()
|
|
84
|
-
initialMouse = e.
|
|
95
|
+
initialMouse = getLocation(e).x
|
|
85
96
|
initialScroll = $scrollLeft
|
|
86
97
|
document.addEventListener("mousemove", moveHDragging)
|
|
98
|
+
document.addEventListener("touchmove", moveHDragging)
|
|
87
99
|
document.addEventListener("mouseup", stopHDragging)
|
|
100
|
+
document.addEventListener("touchend", stopHDragging)
|
|
88
101
|
isDraggingH = true
|
|
89
102
|
closeMenu()
|
|
90
103
|
}
|
|
91
104
|
const moveHDragging = domDebounce(e => {
|
|
92
|
-
const delta = e.
|
|
105
|
+
const delta = getLocation(e).x - initialMouse
|
|
93
106
|
const weight = delta / availWidth
|
|
94
107
|
const newScrollLeft = initialScroll + weight * $maxScrollLeft
|
|
95
108
|
scroll.update(state => ({
|
|
@@ -99,7 +112,9 @@
|
|
|
99
112
|
})
|
|
100
113
|
const stopHDragging = () => {
|
|
101
114
|
document.removeEventListener("mousemove", moveHDragging)
|
|
115
|
+
document.removeEventListener("touchmove", moveHDragging)
|
|
102
116
|
document.removeEventListener("mouseup", stopHDragging)
|
|
117
|
+
document.removeEventListener("touchend", stopHDragging)
|
|
103
118
|
isDraggingH = false
|
|
104
119
|
}
|
|
105
120
|
</script>
|
|
@@ -109,6 +124,7 @@
|
|
|
109
124
|
class="v-scrollbar"
|
|
110
125
|
style="--size:{ScrollBarSize}px; top:{barTop}px; height:{barHeight}px;"
|
|
111
126
|
on:mousedown={startVDragging}
|
|
127
|
+
on:touchstart={startVDragging}
|
|
112
128
|
class:dragging={isDraggingV}
|
|
113
129
|
/>
|
|
114
130
|
{/if}
|
|
@@ -117,6 +133,7 @@
|
|
|
117
133
|
class="h-scrollbar"
|
|
118
134
|
style="--size:{ScrollBarSize}px; left:{barLeft}px; width:{barWidth}px;"
|
|
119
135
|
on:mousedown={startHDragging}
|
|
136
|
+
on:touchstart={startHDragging}
|
|
120
137
|
class:dragging={isDraggingH}
|
|
121
138
|
/>
|
|
122
139
|
{/if}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { writable, get } from "svelte/store"
|
|
2
|
+
import { Helpers } from "@budibase/bbui"
|
|
2
3
|
|
|
3
4
|
export const createStores = () => {
|
|
4
5
|
const copiedCell = writable(null)
|
|
@@ -12,7 +13,16 @@ export const createActions = context => {
|
|
|
12
13
|
const { copiedCell, focusedCellAPI } = context
|
|
13
14
|
|
|
14
15
|
const copy = () => {
|
|
15
|
-
|
|
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
|
|
24
|
+
}
|
|
25
|
+
Helpers.copyToClipboard(stringified)
|
|
16
26
|
}
|
|
17
27
|
|
|
18
28
|
const paste = () => {
|