@budibase/frontend-core 2.5.6-alpha.3 → 2.5.6-alpha.31

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 (66) hide show
  1. package/package.json +6 -4
  2. package/src/api/other.js +0 -9
  3. package/src/components/grid/cells/AttachmentCell.svelte +154 -0
  4. package/src/components/grid/cells/BooleanCell.svelte +44 -0
  5. package/src/components/grid/cells/DataCell.svelte +88 -0
  6. package/src/components/grid/cells/DateCell.svelte +77 -0
  7. package/src/components/grid/cells/FormulaCell.svelte +5 -0
  8. package/src/components/grid/cells/GridCell.svelte +162 -0
  9. package/src/components/grid/cells/GutterCell.svelte +127 -0
  10. package/src/components/grid/cells/HeaderCell.svelte +246 -0
  11. package/src/components/grid/cells/JSONCell.svelte +36 -0
  12. package/src/components/grid/cells/LongFormCell.svelte +120 -0
  13. package/src/components/grid/cells/MultiSelectCell.svelte +7 -0
  14. package/src/components/grid/cells/NumberCell.svelte +7 -0
  15. package/src/components/grid/cells/OptionsCell.svelte +240 -0
  16. package/src/components/grid/cells/RelationshipCell.svelte +504 -0
  17. package/src/components/grid/cells/TextCell.svelte +111 -0
  18. package/src/components/grid/controls/AddColumnButton.svelte +16 -0
  19. package/src/components/grid/controls/AddRowButton.svelte +18 -0
  20. package/src/components/grid/controls/BetaButton.svelte +46 -0
  21. package/src/components/grid/controls/ColumnWidthButton.svelte +91 -0
  22. package/src/components/grid/controls/DeleteButton.svelte +66 -0
  23. package/src/components/grid/controls/HideColumnsButton.svelte +95 -0
  24. package/src/components/grid/controls/RowHeightButton.svelte +70 -0
  25. package/src/components/grid/controls/SortButton.svelte +116 -0
  26. package/src/components/grid/index.js +1 -0
  27. package/src/components/grid/layout/Avatar.svelte +24 -0
  28. package/src/components/grid/layout/Grid.svelte +254 -0
  29. package/src/components/grid/layout/GridBody.svelte +73 -0
  30. package/src/components/grid/layout/GridRow.svelte +57 -0
  31. package/src/components/grid/layout/GridScrollWrapper.svelte +81 -0
  32. package/src/components/grid/layout/HeaderRow.svelte +62 -0
  33. package/src/components/grid/layout/NewRow.svelte +265 -0
  34. package/src/components/grid/layout/RowCount.svelte +9 -0
  35. package/src/components/grid/layout/StickyColumn.svelte +171 -0
  36. package/src/components/grid/layout/UserAvatars.svelte +20 -0
  37. package/src/components/grid/lib/constants.js +14 -0
  38. package/src/components/grid/lib/events.js +29 -0
  39. package/src/components/grid/lib/renderers.js +29 -0
  40. package/src/components/grid/lib/utils.js +26 -0
  41. package/src/components/grid/lib/websocket.js +63 -0
  42. package/src/components/grid/overlays/KeyboardManager.svelte +223 -0
  43. package/src/components/grid/overlays/MenuOverlay.svelte +96 -0
  44. package/src/components/grid/overlays/ReorderOverlay.svelte +63 -0
  45. package/src/components/grid/overlays/ResizeOverlay.svelte +70 -0
  46. package/src/components/grid/overlays/ScrollOverlay.svelte +121 -0
  47. package/src/components/grid/stores/bounds.js +16 -0
  48. package/src/components/grid/stores/clipboard.js +34 -0
  49. package/src/components/grid/stores/columns.js +206 -0
  50. package/src/components/grid/stores/index.js +48 -0
  51. package/src/components/grid/stores/menu.js +49 -0
  52. package/src/components/grid/stores/pagination.js +24 -0
  53. package/src/components/grid/stores/reorder.js +155 -0
  54. package/src/components/grid/stores/resize.js +124 -0
  55. package/src/components/grid/stores/rows.js +467 -0
  56. package/src/components/grid/stores/scroll.js +201 -0
  57. package/src/components/grid/stores/ui.js +159 -0
  58. package/src/components/grid/stores/users.js +115 -0
  59. package/src/components/grid/stores/validation.js +45 -0
  60. package/src/components/grid/stores/viewport.js +145 -0
  61. package/src/components/index.js +1 -0
  62. package/src/fetch/DataFetch.js +27 -21
  63. package/src/fetch/QueryFetch.js +1 -1
  64. package/src/themes/midnight.css +3 -0
  65. package/src/themes/nord.css +3 -0
  66. package/src/utils/utils.js +20 -0
package/package.json CHANGED
@@ -1,15 +1,17 @@
1
1
  {
2
2
  "name": "@budibase/frontend-core",
3
- "version": "2.5.6-alpha.3",
3
+ "version": "2.5.6-alpha.31",
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.5.6-alpha.3",
10
- "@budibase/shared-core": "2.5.6-alpha.3",
9
+ "@budibase/bbui": "2.5.6-alpha.31",
10
+ "@budibase/shared-core": "2.5.6-alpha.31",
11
+ "dayjs": "^1.11.7",
11
12
  "lodash": "^4.17.21",
13
+ "socket.io-client": "^4.6.1",
12
14
  "svelte": "^3.46.2"
13
15
  },
14
- "gitHead": "38b2a2407eeb58c3f143c1d91d517e38b27cdd89"
16
+ "gitHead": "aa0b9fe116c5fbf2dc7ecaae529541aa6c1f2235"
15
17
  }
package/src/api/other.js CHANGED
@@ -1,13 +1,4 @@
1
1
  export const buildOtherEndpoints = API => ({
2
- /**
3
- * TODO: find out what this is
4
- */
5
- checkImportComplete: async () => {
6
- return await API.get({
7
- url: "/api/cloud/import/complete",
8
- })
9
- },
10
-
11
2
  /**
12
3
  * Gets the current environment details.
13
4
  */
@@ -0,0 +1,154 @@
1
+ <script>
2
+ import { onMount } from "svelte"
3
+ import { getContext } from "svelte"
4
+ import { Dropzone, notifications } from "@budibase/bbui"
5
+
6
+ export let value
7
+ export let focused = false
8
+ export let onChange
9
+ export let readonly = false
10
+ export let api
11
+ export let invertX = false
12
+ export let invertY = false
13
+
14
+ const { API } = getContext("grid")
15
+ const imageExtensions = ["png", "tiff", "gif", "raw", "jpg", "jpeg"]
16
+
17
+ let isOpen = false
18
+
19
+ $: editable = focused && !readonly
20
+ $: {
21
+ if (!focused) {
22
+ close()
23
+ }
24
+ }
25
+
26
+ const onKeyDown = () => {
27
+ return isOpen
28
+ }
29
+
30
+ const open = () => {
31
+ isOpen = true
32
+ }
33
+
34
+ const close = () => {
35
+ isOpen = false
36
+ }
37
+
38
+ const isImage = extension => {
39
+ return imageExtensions.includes(extension?.toLowerCase())
40
+ }
41
+
42
+ const handleFileTooLarge = fileSizeLimit => {
43
+ notifications.error(
44
+ `Files cannot exceed ${
45
+ fileSizeLimit / 1000000
46
+ }MB. Please try again with smaller files.`
47
+ )
48
+ }
49
+
50
+ const processFiles = async fileList => {
51
+ let data = new FormData()
52
+ for (let i = 0; i < fileList.length; i++) {
53
+ data.append("file", fileList[i])
54
+ }
55
+ try {
56
+ return await API.uploadBuilderAttachment(data)
57
+ } catch (error) {
58
+ notifications.error("Failed to upload attachment")
59
+ return []
60
+ }
61
+ }
62
+
63
+ const deleteAttachments = async fileList => {
64
+ try {
65
+ return await API.deleteBuilderAttachments(fileList)
66
+ } catch (error) {
67
+ return []
68
+ }
69
+ }
70
+
71
+ onMount(() => {
72
+ api = {
73
+ focus: () => open(),
74
+ blur: () => close(),
75
+ isActive: () => isOpen,
76
+ onKeyDown,
77
+ }
78
+ })
79
+ </script>
80
+
81
+ <div class="attachment-cell" class:editable on:click={editable ? open : null}>
82
+ {#each value || [] as attachment}
83
+ {#if isImage(attachment.extension)}
84
+ <img src={attachment.url} alt={attachment.extension} />
85
+ {:else}
86
+ <div class="file" title={attachment.name}>
87
+ {attachment.extension}
88
+ </div>
89
+ {/if}
90
+ {/each}
91
+ </div>
92
+
93
+ {#if isOpen}
94
+ <div class="dropzone" class:invertX class:invertY>
95
+ <Dropzone
96
+ {value}
97
+ compact
98
+ on:change={e => onChange(e.detail)}
99
+ {processFiles}
100
+ {deleteAttachments}
101
+ {handleFileTooLarge}
102
+ />
103
+ </div>
104
+ {/if}
105
+
106
+ <style>
107
+ .attachment-cell {
108
+ flex: 1 1 auto;
109
+ display: flex;
110
+ flex-direction: row;
111
+ align-items: stretch;
112
+ padding: var(--cell-padding);
113
+ flex-wrap: nowrap;
114
+ gap: var(--cell-spacing);
115
+ align-self: stretch;
116
+ overflow: hidden;
117
+ user-select: none;
118
+ }
119
+ .attachment-cell.editable:hover {
120
+ cursor: pointer;
121
+ }
122
+ .file {
123
+ display: flex;
124
+ flex-direction: row;
125
+ justify-content: flex-start;
126
+ align-items: center;
127
+ padding: 0 10px;
128
+ color: var(--spectrum-global-color-gray-700);
129
+ border: 1px solid var(--spectrum-global-color-gray-300);
130
+ border-radius: 4px;
131
+ text-transform: uppercase;
132
+ font-weight: 600;
133
+ font-size: 12px;
134
+ user-select: none;
135
+ }
136
+ .dropzone {
137
+ position: absolute;
138
+ top: 100%;
139
+ left: 0;
140
+ width: 320px;
141
+ background: var(--background);
142
+ border: var(--cell-border);
143
+ padding: var(--cell-padding);
144
+ box-shadow: 0 0 20px -4px rgba(0, 0, 0, 0.15);
145
+ }
146
+ .dropzone.invertX {
147
+ left: auto;
148
+ right: 0;
149
+ }
150
+ .dropzone.invertY {
151
+ transform: translateY(-100%);
152
+ top: 0;
153
+ }
154
+ </style>
@@ -0,0 +1,44 @@
1
+ <script>
2
+ import { onMount } from "svelte"
3
+ import { Checkbox } from "@budibase/bbui"
4
+
5
+ export let value
6
+ export let focused = false
7
+ export let onChange
8
+ export let readonly = false
9
+ export let api
10
+
11
+ $: editable = focused && !readonly
12
+
13
+ const handleChange = e => {
14
+ onChange(e.detail)
15
+ }
16
+
17
+ const onKeyDown = e => {
18
+ if (e.key === "Enter") {
19
+ onChange(!value)
20
+ return true
21
+ }
22
+ return false
23
+ }
24
+
25
+ onMount(() => {
26
+ api = {
27
+ onKeyDown,
28
+ }
29
+ })
30
+ </script>
31
+
32
+ <div class="boolean-cell" class:editable>
33
+ <Checkbox {value} on:change={handleChange} />
34
+ </div>
35
+
36
+ <style>
37
+ .boolean-cell {
38
+ padding: 2px var(--cell-padding);
39
+ pointer-events: none;
40
+ }
41
+ .boolean-cell.editable {
42
+ pointer-events: all;
43
+ }
44
+ </style>
@@ -0,0 +1,88 @@
1
+ <script>
2
+ import { getContext } from "svelte"
3
+ import GridCell from "./GridCell.svelte"
4
+ import { getCellRenderer } from "../lib/renderers"
5
+ import { derived, writable } from "svelte/store"
6
+
7
+ const { rows, focusedCellId, focusedCellAPI, menu, config, validation } =
8
+ getContext("grid")
9
+
10
+ export let highlighted
11
+ export let selected
12
+ export let rowFocused
13
+ export let rowIdx
14
+ export let focused
15
+ export let selectedUser
16
+ export let column
17
+ export let row
18
+ export let cellId
19
+ export let updateValue = rows.actions.updateValue
20
+ export let invertX = false
21
+ export let invertY = false
22
+
23
+ const emptyError = writable(null)
24
+
25
+ let api
26
+
27
+ // Get the error for this cell if the row is focused
28
+ $: error = getErrorStore(rowFocused, cellId)
29
+
30
+ // Determine if the cell is editable
31
+ $: readonly =
32
+ column.schema.autocolumn ||
33
+ column.schema.disabled ||
34
+ (!$config.allowEditRows && row._id)
35
+
36
+ // Register this cell API if the row is focused
37
+ $: {
38
+ if (focused) {
39
+ focusedCellAPI.set(cellAPI)
40
+ }
41
+ }
42
+
43
+ const getErrorStore = (selected, cellId) => {
44
+ if (!selected) {
45
+ return emptyError
46
+ }
47
+ return derived(validation, $validation => $validation[cellId])
48
+ }
49
+
50
+ const cellAPI = {
51
+ focus: () => api?.focus?.(),
52
+ blur: () => api?.blur?.(),
53
+ isActive: () => api?.isActive?.() ?? false,
54
+ onKeyDown: (...params) => api?.onKeyDown(...params),
55
+ isReadonly: () => readonly,
56
+ getType: () => column.schema.type,
57
+ getValue: () => row[column.name],
58
+ setValue: value => {
59
+ validation.actions.setError(cellId, null)
60
+ updateValue(row._id, column.name, value)
61
+ },
62
+ }
63
+ </script>
64
+
65
+ <GridCell
66
+ {highlighted}
67
+ {selected}
68
+ {rowIdx}
69
+ {focused}
70
+ {selectedUser}
71
+ {readonly}
72
+ error={$error}
73
+ on:click={() => focusedCellId.set(cellId)}
74
+ on:contextmenu={e => menu.actions.open(cellId, e)}
75
+ width={column.width}
76
+ >
77
+ <svelte:component
78
+ this={getCellRenderer(column)}
79
+ bind:api
80
+ value={row[column.name]}
81
+ schema={column.schema}
82
+ onChange={cellAPI.setValue}
83
+ {focused}
84
+ {readonly}
85
+ {invertY}
86
+ {invertX}
87
+ />
88
+ </GridCell>
@@ -0,0 +1,77 @@
1
+ <script>
2
+ import dayjs from "dayjs"
3
+ import { CoreDatePicker, Icon } from "@budibase/bbui"
4
+
5
+ export let value
6
+ export let schema
7
+ export let onChange
8
+ export let focused = false
9
+ export let readonly = false
10
+
11
+ // adding the 0- will turn a string like 00:00:00 into a valid ISO
12
+ // date, but will make actual ISO dates invalid
13
+ $: time = new Date(`0-${value}`)
14
+ $: timeOnly = !isNaN(time) || schema?.timeOnly
15
+ $: dateOnly = schema?.dateOnly
16
+ $: format = timeOnly
17
+ ? "HH:mm:ss"
18
+ : dateOnly
19
+ ? "MMM D YYYY"
20
+ : "MMM D YYYY, HH:mm"
21
+ $: editable = focused && !readonly
22
+ </script>
23
+
24
+ <div class="container">
25
+ <div class="value">
26
+ {#if value}
27
+ {dayjs(timeOnly ? time : value).format(format)}
28
+ {/if}
29
+ </div>
30
+ {#if editable}
31
+ <Icon name="Calendar" />
32
+ {/if}
33
+ </div>
34
+
35
+ {#if editable}
36
+ <div class="picker">
37
+ <CoreDatePicker
38
+ {value}
39
+ on:change={e => onChange(e.detail)}
40
+ appendTo={document.documentElement}
41
+ enableTime={!dateOnly}
42
+ {timeOnly}
43
+ time24hr
44
+ ignoreTimezones={schema.ignoreTimezones}
45
+ />
46
+ </div>
47
+ {/if}
48
+
49
+ <style>
50
+ .container {
51
+ padding: var(--cell-padding);
52
+ display: flex;
53
+ flex-direction: row;
54
+ justify-content: space-between;
55
+ align-items: center;
56
+ flex: 1 1 auto;
57
+ gap: var(--cell-spacing);
58
+ }
59
+ .value {
60
+ flex: 1 1 auto;
61
+ width: 0;
62
+ overflow: hidden;
63
+ text-overflow: ellipsis;
64
+ white-space: nowrap;
65
+ line-height: 20px;
66
+ }
67
+ .picker {
68
+ position: absolute;
69
+ opacity: 0;
70
+ }
71
+ .picker :global(.flatpickr) {
72
+ min-width: 0;
73
+ }
74
+ .picker :global(.spectrum-Textfield-input) {
75
+ width: 100%;
76
+ }
77
+ </style>
@@ -0,0 +1,5 @@
1
+ <script>
2
+ import TextCell from "./TextCell.svelte"
3
+ </script>
4
+
5
+ <TextCell {...$$props} readonly />
@@ -0,0 +1,162 @@
1
+ <script>
2
+ export let focused = false
3
+ export let selected = false
4
+ export let highlighted = false
5
+ export let width = ""
6
+ export let selectedUser = null
7
+ export let error = null
8
+ export let rowIdx
9
+ export let defaultHeight = false
10
+ export let center = false
11
+ export let readonly = false
12
+
13
+ $: style = getStyle(width, selectedUser)
14
+
15
+ const getStyle = (width, selectedUser) => {
16
+ let style = `flex: 0 0 ${width}px;`
17
+ if (selectedUser) {
18
+ style += `--cell-color:${selectedUser.color};`
19
+ }
20
+ return style
21
+ }
22
+ </script>
23
+
24
+ <div
25
+ class="cell"
26
+ class:selected
27
+ class:highlighted
28
+ class:focused
29
+ class:error
30
+ class:center
31
+ class:readonly
32
+ class:default-height={defaultHeight}
33
+ class:selected-other={selectedUser != null}
34
+ on:focus
35
+ on:mousedown
36
+ on:mouseup
37
+ on:click
38
+ on:contextmenu
39
+ {style}
40
+ data-row={rowIdx}
41
+ >
42
+ {#if error}
43
+ <div class="label">
44
+ {error}
45
+ </div>
46
+ {/if}
47
+ <slot />
48
+ {#if selectedUser && !focused}
49
+ <div class="label">
50
+ {selectedUser.label}
51
+ </div>
52
+ {/if}
53
+ </div>
54
+
55
+ <style>
56
+ /* Cells */
57
+ .cell {
58
+ height: var(--row-height);
59
+ border-bottom: var(--cell-border);
60
+ border-right: var(--cell-border);
61
+ display: flex;
62
+ flex-direction: row;
63
+ justify-content: flex-start;
64
+ align-items: flex-start;
65
+ color: var(--spectrum-global-color-gray-800);
66
+ font-size: var(--cell-font-size);
67
+ gap: var(--cell-spacing);
68
+ background: var(--cell-background);
69
+ position: relative;
70
+ width: 0;
71
+ --cell-color: transparent;
72
+ }
73
+ .cell.default-height {
74
+ height: var(--default-row-height);
75
+ }
76
+ .cell.center {
77
+ align-items: center;
78
+ }
79
+
80
+ /* Cell border */
81
+ .cell.focused:after,
82
+ .cell.error:after,
83
+ .cell.selected-other:not(.focused):after {
84
+ content: " ";
85
+ position: absolute;
86
+ top: 0;
87
+ left: 0;
88
+ height: 100%;
89
+ width: 100%;
90
+ border: 2px solid var(--cell-color);
91
+ pointer-events: none;
92
+ border-radius: 2px;
93
+ box-sizing: border-box;
94
+ }
95
+
96
+ /* Cell border for cells with labels */
97
+ .cell.error:after,
98
+ .cell.selected-other:not(.focused):after {
99
+ border-radius: 0 2px 2px 2px;
100
+ }
101
+ .cell[data-row="0"].error:after,
102
+ .cell[data-row="0"].selected-other:not(.focused):after {
103
+ border-radius: 2px 2px 2px 0;
104
+ }
105
+
106
+ /* Cell z-index */
107
+ .cell.error,
108
+ .cell.selected-other:not(.focused) {
109
+ z-index: 1;
110
+ }
111
+ .cell.focused {
112
+ z-index: 2;
113
+ }
114
+ .cell.focused {
115
+ --cell-color: var(--spectrum-global-color-blue-400);
116
+ }
117
+ .cell.error {
118
+ --cell-color: var(--spectrum-global-color-red-500);
119
+ }
120
+ .cell:not(.focused) {
121
+ user-select: none;
122
+ }
123
+ .cell:hover {
124
+ cursor: default;
125
+ }
126
+ .cell.highlighted:not(.focused),
127
+ .cell.focused.readonly {
128
+ --cell-background: var(--cell-background-hover);
129
+ }
130
+ .cell.selected:not(.focused) {
131
+ --cell-background: var(--spectrum-global-color-blue-100);
132
+ }
133
+
134
+ /* Label for additional text */
135
+ .label {
136
+ position: absolute;
137
+ bottom: 100%;
138
+ left: 0;
139
+ padding: 1px 4px 3px 4px;
140
+ margin: 0 0 -2px 0;
141
+ background: var(--user-color);
142
+ border-radius: 2px;
143
+ display: block;
144
+ color: white;
145
+ font-size: 12px;
146
+ font-weight: 600;
147
+ white-space: nowrap;
148
+ text-overflow: ellipsis;
149
+ overflow: hidden;
150
+ user-select: none;
151
+ }
152
+ .cell[data-row="0"] .label {
153
+ bottom: auto;
154
+ top: 100%;
155
+ border-radius: 0 2px 2px 2px;
156
+ padding: 2px 4px 2px 4px;
157
+ margin: -2px 0 0 0;
158
+ }
159
+ .error .label {
160
+ background: var(--spectrum-global-color-red-500);
161
+ }
162
+ </style>
@@ -0,0 +1,127 @@
1
+ <script>
2
+ import { GutterWidth } from "../lib/constants"
3
+ import { getContext } from "svelte"
4
+ import { Checkbox, Icon } from "@budibase/bbui"
5
+ import GridCell from "./GridCell.svelte"
6
+ import { createEventDispatcher } from "svelte"
7
+
8
+ export let row
9
+ export let rowFocused = false
10
+ export let rowHovered = false
11
+ export let rowSelected = false
12
+ export let disableExpand = false
13
+ export let disableNumber = false
14
+ export let defaultHeight = false
15
+ export let disabled = false
16
+
17
+ const { config, dispatch, selectedRows } = getContext("grid")
18
+ const svelteDispatch = createEventDispatcher()
19
+
20
+ const select = () => {
21
+ svelteDispatch("select")
22
+ const id = row?._id
23
+ if (id) {
24
+ selectedRows.update(state => {
25
+ let newState = {
26
+ ...state,
27
+ [id]: !state[id],
28
+ }
29
+ if (!newState[id]) {
30
+ delete newState[id]
31
+ }
32
+ return newState
33
+ })
34
+ }
35
+ }
36
+
37
+ const expand = () => {
38
+ svelteDispatch("expand")
39
+ if (row) {
40
+ dispatch("edit-row", row)
41
+ }
42
+ }
43
+ </script>
44
+
45
+ <GridCell
46
+ width={GutterWidth}
47
+ highlighted={rowFocused || rowHovered}
48
+ selected={rowSelected}
49
+ {defaultHeight}
50
+ >
51
+ <div class="gutter">
52
+ {#if $$slots.default}
53
+ <slot />
54
+ {:else}
55
+ <div
56
+ on:click={select}
57
+ class="checkbox"
58
+ class:visible={$config.allowDeleteRows &&
59
+ (disableNumber || rowSelected || rowHovered || rowFocused)}
60
+ >
61
+ <Checkbox value={rowSelected} {disabled} />
62
+ </div>
63
+ {#if !disableNumber}
64
+ <div
65
+ class="number"
66
+ class:visible={!$config.allowDeleteRows ||
67
+ !(rowSelected || rowHovered || rowFocused)}
68
+ >
69
+ {row.__idx + 1}
70
+ </div>
71
+ {/if}
72
+ {/if}
73
+ {#if $config.allowExpandRows}
74
+ <div
75
+ class="expand"
76
+ class:visible={!disableExpand && (rowFocused || rowHovered)}
77
+ >
78
+ <Icon name="Maximize" hoverable size="S" on:click={expand} />
79
+ </div>
80
+ {/if}
81
+ </div>
82
+ </GridCell>
83
+
84
+ <style>
85
+ .gutter {
86
+ flex: 1 1 auto;
87
+ display: grid;
88
+ align-items: center;
89
+ padding: var(--cell-padding);
90
+ grid-template-columns: 1fr auto;
91
+ gap: var(--cell-spacing);
92
+ }
93
+ .checkbox,
94
+ .number {
95
+ display: none;
96
+ flex-direction: row;
97
+ justify-content: center;
98
+ align-items: center;
99
+ }
100
+ .checkbox :global(.spectrum-Checkbox) {
101
+ min-height: 0;
102
+ height: 20px;
103
+ }
104
+ .checkbox :global(.spectrum-Checkbox-box) {
105
+ margin: 3px 0 0 0;
106
+ }
107
+ .number {
108
+ color: var(--spectrum-global-color-gray-500);
109
+ }
110
+ .checkbox.visible,
111
+ .number.visible {
112
+ display: flex;
113
+ }
114
+ .expand {
115
+ opacity: 0;
116
+ margin-right: 4px;
117
+ }
118
+ .expand :global(.spectrum-Icon) {
119
+ pointer-events: none;
120
+ }
121
+ .expand.visible {
122
+ opacity: 1;
123
+ }
124
+ .expand.visible :global(.spectrum-Icon) {
125
+ pointer-events: all;
126
+ }
127
+ </style>