@budibase/frontend-core 2.13.10 → 2.13.12
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/GridCell.svelte +1 -1
- package/src/components/grid/layout/ButtonColumn.svelte +144 -0
- package/src/components/grid/layout/Grid.svelte +2 -0
- package/src/components/grid/layout/GridBody.svelte +5 -0
- package/src/components/grid/stores/rows.js +6 -2
- package/src/components/grid/stores/scroll.js +13 -5
- package/src/components/grid/stores/ui.js +2 -0
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/frontend-core",
|
|
3
|
-
"version": "2.13.
|
|
3
|
+
"version": "2.13.12",
|
|
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.13.
|
|
10
|
-
"@budibase/shared-core": "2.13.
|
|
9
|
+
"@budibase/bbui": "2.13.12",
|
|
10
|
+
"@budibase/shared-core": "2.13.12",
|
|
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": "40067f3089c49a710c2b4ead52d03e70d94be272"
|
|
17
17
|
}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
$: style = getStyle(width, selectedUser)
|
|
16
16
|
|
|
17
17
|
const getStyle = (width, selectedUser) => {
|
|
18
|
-
let style = `flex: 0 0 ${width}px;`
|
|
18
|
+
let style = width === "auto" ? "width: auto;" : `flex: 0 0 ${width}px;`
|
|
19
19
|
if (selectedUser) {
|
|
20
20
|
style += `--user-color:${selectedUser.color};`
|
|
21
21
|
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { getContext, onMount } from "svelte"
|
|
3
|
+
import { Button } from "@budibase/bbui"
|
|
4
|
+
import GridCell from "../cells/GridCell.svelte"
|
|
5
|
+
import GridScrollWrapper from "./GridScrollWrapper.svelte"
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
renderedRows,
|
|
9
|
+
hoveredRowId,
|
|
10
|
+
props,
|
|
11
|
+
width,
|
|
12
|
+
rows,
|
|
13
|
+
focusedRow,
|
|
14
|
+
selectedRows,
|
|
15
|
+
visibleColumns,
|
|
16
|
+
scroll,
|
|
17
|
+
isDragging,
|
|
18
|
+
buttonColumnWidth,
|
|
19
|
+
} = getContext("grid")
|
|
20
|
+
|
|
21
|
+
let measureContainer
|
|
22
|
+
|
|
23
|
+
$: buttons = $props.buttons?.slice(0, 3) || []
|
|
24
|
+
$: columnsWidth = $visibleColumns.reduce(
|
|
25
|
+
(total, col) => (total += col.width),
|
|
26
|
+
0
|
|
27
|
+
)
|
|
28
|
+
$: end = columnsWidth - 1 - $scroll.left
|
|
29
|
+
$: left = Math.min($width - $buttonColumnWidth, end)
|
|
30
|
+
|
|
31
|
+
const handleClick = async (button, row) => {
|
|
32
|
+
await button.onClick?.(rows.actions.cleanRow(row))
|
|
33
|
+
// Refresh the row in case it changed
|
|
34
|
+
await rows.actions.refreshRow(row._id)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
onMount(() => {
|
|
38
|
+
const observer = new ResizeObserver(entries => {
|
|
39
|
+
const width = entries?.[0]?.contentRect?.width ?? 0
|
|
40
|
+
buttonColumnWidth.set(width)
|
|
41
|
+
})
|
|
42
|
+
observer.observe(measureContainer)
|
|
43
|
+
})
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<!-- Hidden copy of buttons to measure -->
|
|
47
|
+
<div class="measure" bind:this={measureContainer}>
|
|
48
|
+
<GridCell width="auto">
|
|
49
|
+
<div class="buttons">
|
|
50
|
+
{#each buttons as button}
|
|
51
|
+
<Button size="S">
|
|
52
|
+
{button.text || "Button"}
|
|
53
|
+
</Button>
|
|
54
|
+
{/each}
|
|
55
|
+
</div>
|
|
56
|
+
</GridCell>
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<div
|
|
60
|
+
class="button-column"
|
|
61
|
+
style="left:{left}px"
|
|
62
|
+
class:hidden={$buttonColumnWidth === 0}
|
|
63
|
+
>
|
|
64
|
+
<div class="content" on:mouseleave={() => ($hoveredRowId = null)}>
|
|
65
|
+
<GridScrollWrapper scrollVertically attachHandlers>
|
|
66
|
+
{#each $renderedRows as row}
|
|
67
|
+
{@const rowSelected = !!$selectedRows[row._id]}
|
|
68
|
+
{@const rowHovered = $hoveredRowId === row._id}
|
|
69
|
+
{@const rowFocused = $focusedRow?._id === row._id}
|
|
70
|
+
<div
|
|
71
|
+
class="row"
|
|
72
|
+
on:mouseenter={$isDragging ? null : () => ($hoveredRowId = row._id)}
|
|
73
|
+
on:mouseleave={$isDragging ? null : () => ($hoveredRowId = null)}
|
|
74
|
+
>
|
|
75
|
+
<GridCell
|
|
76
|
+
width="auto"
|
|
77
|
+
rowIdx={row.__idx}
|
|
78
|
+
selected={rowSelected}
|
|
79
|
+
highlighted={rowHovered || rowFocused}
|
|
80
|
+
>
|
|
81
|
+
<div class="buttons">
|
|
82
|
+
{#each buttons as button}
|
|
83
|
+
<Button
|
|
84
|
+
newStyles
|
|
85
|
+
size="S"
|
|
86
|
+
cta={button.type === "cta"}
|
|
87
|
+
primary={button.type === "primary"}
|
|
88
|
+
secondary={button.type === "secondary"}
|
|
89
|
+
warning={button.type === "warning"}
|
|
90
|
+
overBackground={button.type === "overBackground"}
|
|
91
|
+
on:click={() => handleClick(button, row)}
|
|
92
|
+
>
|
|
93
|
+
{button.text || "Button"}
|
|
94
|
+
</Button>
|
|
95
|
+
{/each}
|
|
96
|
+
</div>
|
|
97
|
+
</GridCell>
|
|
98
|
+
</div>
|
|
99
|
+
{/each}
|
|
100
|
+
</GridScrollWrapper>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
|
|
104
|
+
<style>
|
|
105
|
+
.button-column {
|
|
106
|
+
display: flex;
|
|
107
|
+
flex-direction: column;
|
|
108
|
+
background: var(--cell-background);
|
|
109
|
+
position: absolute;
|
|
110
|
+
top: 0;
|
|
111
|
+
}
|
|
112
|
+
.button-column.hidden {
|
|
113
|
+
opacity: 0;
|
|
114
|
+
}
|
|
115
|
+
.content {
|
|
116
|
+
position: relative;
|
|
117
|
+
flex: 1 1 auto;
|
|
118
|
+
}
|
|
119
|
+
.row {
|
|
120
|
+
display: flex;
|
|
121
|
+
flex-direction: row;
|
|
122
|
+
justify-content: flex-start;
|
|
123
|
+
align-items: stretch;
|
|
124
|
+
}
|
|
125
|
+
.buttons {
|
|
126
|
+
display: flex;
|
|
127
|
+
align-items: center;
|
|
128
|
+
padding: 0 var(--cell-padding);
|
|
129
|
+
gap: var(--cell-padding);
|
|
130
|
+
height: inherit;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/* Add left cell border */
|
|
134
|
+
.button-column :global(.cell) {
|
|
135
|
+
border-left: var(--cell-border);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* Hidden copy of buttons to measure width against */
|
|
139
|
+
.measure {
|
|
140
|
+
position: absolute;
|
|
141
|
+
opacity: 0;
|
|
142
|
+
pointer-events: none;
|
|
143
|
+
}
|
|
144
|
+
</style>
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
export let fixedRowHeight = null
|
|
49
49
|
export let notifySuccess = null
|
|
50
50
|
export let notifyError = null
|
|
51
|
+
export let buttons = null
|
|
51
52
|
|
|
52
53
|
// Unique identifier for DOM nodes inside this instance
|
|
53
54
|
const rand = Math.random()
|
|
@@ -99,6 +100,7 @@
|
|
|
99
100
|
fixedRowHeight,
|
|
100
101
|
notifySuccess,
|
|
101
102
|
notifyError,
|
|
103
|
+
buttons,
|
|
102
104
|
})
|
|
103
105
|
|
|
104
106
|
// Set context for children to consume
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import GridScrollWrapper from "./GridScrollWrapper.svelte"
|
|
4
4
|
import GridRow from "./GridRow.svelte"
|
|
5
5
|
import { BlankRowID } from "../lib/constants"
|
|
6
|
+
import ButtonColumn from "./ButtonColumn.svelte"
|
|
6
7
|
|
|
7
8
|
const {
|
|
8
9
|
bounds,
|
|
@@ -13,6 +14,7 @@
|
|
|
13
14
|
dispatch,
|
|
14
15
|
isDragging,
|
|
15
16
|
config,
|
|
17
|
+
props,
|
|
16
18
|
} = getContext("grid")
|
|
17
19
|
|
|
18
20
|
let body
|
|
@@ -54,6 +56,9 @@
|
|
|
54
56
|
/>
|
|
55
57
|
{/if}
|
|
56
58
|
</GridScrollWrapper>
|
|
59
|
+
{#if $props.buttons?.length}
|
|
60
|
+
<ButtonColumn />
|
|
61
|
+
{/if}
|
|
57
62
|
</div>
|
|
58
63
|
|
|
59
64
|
<style>
|
|
@@ -314,8 +314,12 @@ export const createActions = context => {
|
|
|
314
314
|
|
|
315
315
|
// Refreshes a specific row
|
|
316
316
|
const refreshRow = async id => {
|
|
317
|
-
|
|
318
|
-
|
|
317
|
+
try {
|
|
318
|
+
const row = await datasource.actions.getRow(id)
|
|
319
|
+
replaceRow(id, row)
|
|
320
|
+
} catch {
|
|
321
|
+
// Do nothing - we probably just don't support refreshing individual rows
|
|
322
|
+
}
|
|
319
323
|
}
|
|
320
324
|
|
|
321
325
|
// Refreshes all data
|
|
@@ -20,8 +20,15 @@ export const createStores = () => {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export const deriveStores = context => {
|
|
23
|
-
const {
|
|
24
|
-
|
|
23
|
+
const {
|
|
24
|
+
rows,
|
|
25
|
+
visibleColumns,
|
|
26
|
+
stickyColumn,
|
|
27
|
+
rowHeight,
|
|
28
|
+
width,
|
|
29
|
+
height,
|
|
30
|
+
buttonColumnWidth,
|
|
31
|
+
} = context
|
|
25
32
|
|
|
26
33
|
// Memoize store primitives
|
|
27
34
|
const stickyColumnWidth = derived(stickyColumn, $col => $col?.width || 0, 0)
|
|
@@ -40,9 +47,10 @@ export const deriveStores = context => {
|
|
|
40
47
|
|
|
41
48
|
// Derive horizontal limits
|
|
42
49
|
const contentWidth = derived(
|
|
43
|
-
[visibleColumns, stickyColumnWidth],
|
|
44
|
-
([$visibleColumns, $stickyColumnWidth]) => {
|
|
45
|
-
|
|
50
|
+
[visibleColumns, stickyColumnWidth, buttonColumnWidth],
|
|
51
|
+
([$visibleColumns, $stickyColumnWidth, $buttonColumnWidth]) => {
|
|
52
|
+
const space = Math.max(Padding, $buttonColumnWidth - 1)
|
|
53
|
+
let width = GutterWidth + space + $stickyColumnWidth
|
|
46
54
|
$visibleColumns.forEach(col => {
|
|
47
55
|
width += col.width
|
|
48
56
|
})
|
|
@@ -18,6 +18,7 @@ export const createStores = context => {
|
|
|
18
18
|
const previousFocusedRowId = writable(null)
|
|
19
19
|
const gridFocused = writable(false)
|
|
20
20
|
const isDragging = writable(false)
|
|
21
|
+
const buttonColumnWidth = writable(0)
|
|
21
22
|
|
|
22
23
|
// Derive the current focused row ID
|
|
23
24
|
const focusedRowId = derived(
|
|
@@ -51,6 +52,7 @@ export const createStores = context => {
|
|
|
51
52
|
rowHeight,
|
|
52
53
|
gridFocused,
|
|
53
54
|
isDragging,
|
|
55
|
+
buttonColumnWidth,
|
|
54
56
|
selectedRows: {
|
|
55
57
|
...selectedRows,
|
|
56
58
|
actions: {
|