@budibase/bbui 2.8.31 → 2.8.32-alpha.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@budibase/bbui",
3
3
  "description": "A UI solution used in the different Budibase projects.",
4
- "version": "2.8.31",
4
+ "version": "2.8.32-alpha.0",
5
5
  "license": "MPL-2.0",
6
6
  "svelte": "src/index.js",
7
7
  "module": "dist/bbui.es.js",
@@ -38,8 +38,8 @@
38
38
  ],
39
39
  "dependencies": {
40
40
  "@adobe/spectrum-css-workflow-icons": "1.2.1",
41
- "@budibase/shared-core": "2.8.31",
42
- "@budibase/string-templates": "2.8.31",
41
+ "@budibase/shared-core": "2.8.32-alpha.0",
42
+ "@budibase/string-templates": "2.8.32-alpha.0",
43
43
  "@spectrum-css/accordion": "3.0.24",
44
44
  "@spectrum-css/actionbutton": "1.0.1",
45
45
  "@spectrum-css/actiongroup": "1.0.1",
@@ -84,6 +84,7 @@
84
84
  "@spectrum-css/vars": "3.0.1",
85
85
  "dayjs": "^1.10.4",
86
86
  "easymde": "^2.16.1",
87
+ "svelte-dnd-action": "^0.9.8",
87
88
  "svelte-flatpickr": "3.2.3",
88
89
  "svelte-portal": "^1.0.0"
89
90
  },
@@ -96,7 +97,9 @@
96
97
  "dependsOn": [
97
98
  {
98
99
  "projects": [
99
- "@budibase/string-templates"
100
+ "@budibase/string-templates",
101
+ "@budibase/shared-core",
102
+ "@budibase/types"
100
103
  ],
101
104
  "target": "build"
102
105
  }
@@ -104,5 +107,5 @@
104
107
  }
105
108
  }
106
109
  },
107
- "gitHead": "4613b17c1e76328bf279998c821a17195fbaab37"
110
+ "gitHead": "d004c83e8892505e19d9a06b85167a9f79f127fe"
108
111
  }
@@ -1,6 +1,7 @@
1
1
  <script>
2
2
  import "@spectrum-css/button/dist/index-vars.css"
3
- import Tooltip from "../Tooltip/Tooltip.svelte"
3
+ import AbsTooltip from "../Tooltip/AbsTooltip.svelte"
4
+ import { createEventDispatcher } from "svelte"
4
5
 
5
6
  export let type
6
7
  export let disabled = false
@@ -17,65 +18,52 @@
17
18
  export let newStyles = true
18
19
  export let id
19
20
 
20
- let showTooltip = false
21
+ const dispatch = createEventDispatcher()
21
22
  </script>
22
23
 
23
- <button
24
- {id}
25
- {type}
26
- class:spectrum-Button--cta={cta}
27
- class:spectrum-Button--primary={primary}
28
- class:spectrum-Button--secondary={secondary}
29
- class:spectrum-Button--warning={warning}
30
- class:spectrum-Button--overBackground={overBackground}
31
- class:spectrum-Button--quiet={quiet}
32
- class:new-styles={newStyles}
33
- class:active
34
- class:disabled
35
- class="spectrum-Button spectrum-Button--size{size.toUpperCase()}"
36
- {disabled}
37
- on:click|preventDefault
38
- on:mouseover={() => (showTooltip = true)}
39
- on:focus={() => (showTooltip = true)}
40
- on:mouseleave={() => (showTooltip = false)}
41
- >
42
- {#if icon}
43
- <svg
44
- class="spectrum-Icon spectrum-Icon--size{size.toUpperCase()}"
45
- focusable="false"
46
- aria-hidden="true"
47
- aria-label={icon}
48
- >
49
- <use xlink:href="#spectrum-icon-18-{icon}" />
50
- </svg>
51
- {/if}
52
- {#if $$slots}
53
- <span class="spectrum-Button-label"><slot /></span>
54
- {/if}
55
- {#if !disabled && tooltip}
56
- <div class="tooltip-icon">
24
+ <AbsTooltip text={tooltip}>
25
+ <button
26
+ {id}
27
+ {type}
28
+ class:spectrum-Button--cta={cta}
29
+ class:spectrum-Button--primary={primary}
30
+ class:spectrum-Button--secondary={secondary}
31
+ class:spectrum-Button--warning={warning}
32
+ class:spectrum-Button--overBackground={overBackground}
33
+ class:spectrum-Button--quiet={quiet}
34
+ class:new-styles={newStyles}
35
+ class:active
36
+ class:is-disabled={disabled}
37
+ class="spectrum-Button spectrum-Button--size{size.toUpperCase()}"
38
+ on:click|preventDefault={() => {
39
+ if (!disabled) {
40
+ dispatch("click")
41
+ }
42
+ }}
43
+ >
44
+ {#if icon}
57
45
  <svg
58
46
  class="spectrum-Icon spectrum-Icon--size{size.toUpperCase()}"
59
47
  focusable="false"
60
48
  aria-hidden="true"
61
- aria-label="Info"
49
+ aria-label={icon}
62
50
  >
63
- <use xlink:href="#spectrum-icon-18-InfoOutline" />
51
+ <use xlink:href="#spectrum-icon-18-{icon}" />
64
52
  </svg>
65
- </div>
66
- {/if}
67
- {#if showTooltip && tooltip}
68
- <div class="tooltip">
69
- <Tooltip textWrapping={true} direction={"bottom"} text={tooltip} />
70
- </div>
71
- {/if}
72
- </button>
53
+ {/if}
54
+ {#if $$slots}
55
+ <span class="spectrum-Button-label"><slot /></span>
56
+ {/if}
57
+ </button>
58
+ </AbsTooltip>
73
59
 
74
60
  <style>
75
61
  button {
76
62
  position: relative;
77
63
  }
78
-
64
+ button.is-disabled {
65
+ cursor: default;
66
+ }
79
67
  .spectrum-Button-label {
80
68
  white-space: nowrap;
81
69
  overflow: hidden;
@@ -84,21 +72,6 @@
84
72
  .active {
85
73
  color: var(--spectrum-global-color-blue-600) !important;
86
74
  }
87
- .tooltip {
88
- position: absolute;
89
- display: flex;
90
- justify-content: center;
91
- z-index: 100;
92
- width: 160px;
93
- text-align: center;
94
- transform: translateX(-50%);
95
- left: 50%;
96
- top: calc(100% - 3px);
97
- }
98
- .tooltip-icon {
99
- padding-left: var(--spacing-m);
100
- line-height: 0;
101
- }
102
75
  .spectrum-Button--primary.new-styles {
103
76
  background: var(--spectrum-global-color-gray-800);
104
77
  border-color: transparent;
@@ -112,10 +85,10 @@
112
85
  border-color: transparent;
113
86
  color: var(--spectrum-global-color-gray-900);
114
87
  }
115
- .spectrum-Button--secondary.new-styles:not(.disabled):hover {
88
+ .spectrum-Button--secondary.new-styles:not(.is-disabled):hover {
116
89
  background: var(--spectrum-global-color-gray-300);
117
90
  }
118
- .spectrum-Button--secondary.new-styles.disabled {
91
+ .spectrum-Button--secondary.new-styles.is-disabled {
119
92
  color: var(--spectrum-global-color-gray-500);
120
93
  }
121
94
  </style>
@@ -15,8 +15,6 @@
15
15
 
16
16
  const dispatch = createEventDispatcher()
17
17
 
18
- $: placeholder = !value
19
-
20
18
  const extractProperty = (value, property) => {
21
19
  if (value && typeof value === "object") {
22
20
  return value[property]
@@ -12,23 +12,24 @@
12
12
  export let getOptionValue = option => option
13
13
 
14
14
  const dispatch = createEventDispatcher()
15
+
15
16
  const onChange = e => {
16
- let tempValue = value
17
- let isChecked = e.target.checked
18
- if (!tempValue.includes(e.target.value) && isChecked) {
19
- tempValue.push(e.target.value)
17
+ const optionValue = e.target.value
18
+ if (e.target.checked && !value.includes(optionValue)) {
19
+ dispatch("change", [...value, optionValue])
20
+ } else {
21
+ dispatch(
22
+ "change",
23
+ value.filter(x => x !== optionValue)
24
+ )
20
25
  }
21
- value = tempValue
22
- dispatch(
23
- "change",
24
- tempValue.filter(val => val !== e.target.value || isChecked)
25
- )
26
26
  }
27
27
  </script>
28
28
 
29
29
  <div class={`spectrum-FieldGroup spectrum-FieldGroup--${direction}`}>
30
30
  {#if options && Array.isArray(options)}
31
31
  {#each options as option}
32
+ {@const optionValue = getOptionValue(option)}
32
33
  <div
33
34
  title={getOptionLabel(option)}
34
35
  class="spectrum-Checkbox spectrum-FieldGroup-item"
@@ -39,11 +40,11 @@
39
40
  >
40
41
  <input
41
42
  on:change={onChange}
42
- value={getOptionValue(option)}
43
43
  type="checkbox"
44
44
  class="spectrum-Checkbox-input"
45
+ value={optionValue}
46
+ checked={value.includes(optionValue)}
45
47
  {disabled}
46
- checked={value.includes(getOptionValue(option))}
47
48
  />
48
49
  <span class="spectrum-Checkbox-box">
49
50
  <svg
@@ -150,7 +150,7 @@
150
150
  </div>
151
151
  {:else if variables.length}
152
152
  <div style="max-height: 100px">
153
- {#each variables as variable, idx}
153
+ {#each variables as variable}
154
154
  <li
155
155
  class="spectrum-Menu-item"
156
156
  role="option"
@@ -1,5 +1,4 @@
1
1
  <script>
2
- //import { createEventDispatcher } from "svelte"
3
2
  import "@spectrum-css/popover/dist/index-vars.css"
4
3
  import clickOutside from "../Actions/click_outside"
5
4
  import { fly } from "svelte/transition"
@@ -1,6 +1,7 @@
1
1
  <script>
2
2
  import "@spectrum-css/link/dist/index-vars.css"
3
3
  import { createEventDispatcher } from "svelte"
4
+ import Tooltip from "../Tooltip/Tooltip.svelte"
4
5
 
5
6
  export let href = "#"
6
7
  export let size = "M"
@@ -10,18 +11,61 @@
10
11
  export let overBackground = false
11
12
  export let target
12
13
  export let download
14
+ export let disabled = false
15
+ export let tooltip = null
13
16
 
14
17
  const dispatch = createEventDispatcher()
18
+
19
+ const onClick = e => {
20
+ if (!disabled) {
21
+ dispatch("click")
22
+ e.stopPropagation()
23
+ }
24
+ }
15
25
  </script>
16
26
 
17
27
  <a
18
- on:click={e => dispatch("click") && e.stopPropagation()}
28
+ on:click={onClick}
19
29
  {href}
20
30
  {target}
21
31
  {download}
32
+ class:disabled
22
33
  class:spectrum-Link--primary={primary}
23
34
  class:spectrum-Link--secondary={secondary}
24
35
  class:spectrum-Link--overBackground={overBackground}
25
36
  class:spectrum-Link--quiet={quiet}
26
- class="spectrum-Link spectrum-Link--size{size}"><slot /></a
37
+ class="spectrum-Link spectrum-Link--size{size}"
27
38
  >
39
+ <slot />
40
+ {#if tooltip}
41
+ <div class="tooltip">
42
+ <Tooltip textWrapping direction="bottom" text={tooltip} />
43
+ </div>
44
+ {/if}
45
+ </a>
46
+
47
+ <style>
48
+ a {
49
+ position: relative;
50
+ }
51
+ a.disabled {
52
+ color: var(--spectrum-global-color-gray-500);
53
+ }
54
+ a.disabled:hover {
55
+ text-decoration: none;
56
+ cursor: default;
57
+ }
58
+ .tooltip {
59
+ position: absolute;
60
+ left: 50%;
61
+ top: 100%;
62
+ transform: translateX(-50%);
63
+ opacity: 0;
64
+ transition: 130ms ease-out;
65
+ pointer-events: none;
66
+ z-index: 100;
67
+ }
68
+ a:hover .tooltip {
69
+ opacity: 1;
70
+ }
71
+ </style>
@@ -1,3 +1,7 @@
1
+ <script context="module">
2
+ export const keepOpen = Symbol("keepOpen")
3
+ </script>
4
+
1
5
  <script>
2
6
  import "@spectrum-css/dialog/dist/index-vars.css"
3
7
  import { getContext } from "svelte"
@@ -30,7 +34,7 @@
30
34
 
31
35
  async function secondary(e) {
32
36
  loading = true
33
- if (!secondaryAction || (await secondaryAction(e)) !== false) {
37
+ if (!secondaryAction || (await secondaryAction(e)) !== keepOpen) {
34
38
  hide()
35
39
  }
36
40
  loading = false
@@ -38,7 +42,7 @@
38
42
 
39
43
  async function confirm() {
40
44
  loading = true
41
- if (!onConfirm || (await onConfirm()) !== false) {
45
+ if (!onConfirm || (await onConfirm()) !== keepOpen) {
42
46
  hide()
43
47
  }
44
48
  loading = false
@@ -46,7 +50,7 @@
46
50
 
47
51
  async function close() {
48
52
  loading = true
49
- if (!onCancel || (await onCancel()) !== false) {
53
+ if (!onCancel || (await onCancel()) !== keepOpen) {
50
54
  cancel()
51
55
  }
52
56
  loading = false
@@ -0,0 +1,252 @@
1
+ <script>
2
+ import { flip } from "svelte/animate"
3
+ import { dndzone } from "svelte-dnd-action"
4
+ import Icon from "../Icon/Icon.svelte"
5
+ import Popover from "../Popover/Popover.svelte"
6
+ import { onMount } from "svelte"
7
+ const flipDurationMs = 150
8
+
9
+ export let constraints
10
+ export let optionColors = {}
11
+ let options = []
12
+
13
+ let colorPopovers = []
14
+ let anchors = []
15
+
16
+ let colorsArray = [
17
+ "hsla(0, 90%, 75%, 0.3)",
18
+ "hsla(50, 80%, 75%, 0.3)",
19
+ "hsla(120, 90%, 75%, 0.3)",
20
+ "hsla(200, 90%, 75%, 0.3)",
21
+ "hsla(240, 90%, 75%, 0.3)",
22
+ "hsla(320, 90%, 75%, 0.3)",
23
+ ]
24
+ $: {
25
+ if (constraints.inclusion.length) {
26
+ options = constraints.inclusion.map(value => ({
27
+ name: value,
28
+ id: Math.random(),
29
+ }))
30
+ }
31
+ }
32
+ const removeInput = idx => {
33
+ delete optionColors[options[idx].name]
34
+ constraints.inclusion = constraints.inclusion.filter((e, i) => i !== idx)
35
+ options = options.filter((e, i) => i !== idx)
36
+ colorPopovers.pop(undefined)
37
+ anchors.pop(undefined)
38
+ }
39
+
40
+ const addNewInput = () => {
41
+ options = [
42
+ ...options,
43
+ { name: `Option ${constraints.inclusion.length + 1}`, id: Math.random() },
44
+ ]
45
+ constraints.inclusion = [
46
+ ...constraints.inclusion,
47
+ `Option ${constraints.inclusion.length + 1}`,
48
+ ]
49
+
50
+ colorPopovers.push(undefined)
51
+ anchors.push(undefined)
52
+ }
53
+
54
+ const handleDndConsider = e => {
55
+ options = e.detail.items
56
+ }
57
+ const handleDndFinalize = e => {
58
+ options = e.detail.items
59
+ constraints.inclusion = options.map(option => option.name)
60
+ }
61
+
62
+ const handleColorChange = (optionName, color, idx) => {
63
+ optionColors[optionName] = color
64
+ colorPopovers[idx].hide()
65
+ }
66
+
67
+ const handleNameChange = (optionName, idx, value) => {
68
+ constraints.inclusion[idx] = value
69
+ options[idx].name = value
70
+ optionColors[value] = optionColors[optionName]
71
+ delete optionColors[optionName]
72
+ }
73
+
74
+ const openColorPickerPopover = (optionIdx, target) => {
75
+ colorPopovers[optionIdx].show()
76
+ anchors[optionIdx] = target
77
+ }
78
+
79
+ onMount(() => {
80
+ // Initialize anchor arrays on mount, assuming 'options' is already populated
81
+ colorPopovers = constraints.inclusion.map(() => undefined)
82
+ anchors = constraints.inclusion.map(() => undefined)
83
+ })
84
+ </script>
85
+
86
+ <div>
87
+ <div
88
+ class="actions"
89
+ use:dndzone={{
90
+ items: options,
91
+ flipDurationMs,
92
+ dropTargetStyle: { outline: "none" },
93
+ }}
94
+ on:consider={handleDndConsider}
95
+ on:finalize={handleDndFinalize}
96
+ >
97
+ {#each options as option, idx (option.id)}
98
+ <div
99
+ class="no-border action-container"
100
+ animate:flip={{ duration: flipDurationMs }}
101
+ >
102
+ <div class="child drag-handle-spacing">
103
+ <Icon name="DragHandle" size="L" />
104
+ </div>
105
+ <div class="child color-picker">
106
+ <div
107
+ id="color-picker"
108
+ bind:this={anchors[idx]}
109
+ style="--color:{optionColors?.[option.name] ||
110
+ 'hsla(0, 1%, 50%, 0.3)'}"
111
+ class="circle"
112
+ on:click={e => openColorPickerPopover(idx, e.target)}
113
+ >
114
+ <Popover
115
+ bind:this={colorPopovers[idx]}
116
+ anchor={anchors[idx]}
117
+ align="left"
118
+ offset={0}
119
+ style=""
120
+ popoverTarget={document.getElementById(`color-picker`)}
121
+ animate={false}
122
+ >
123
+ <div class="colors">
124
+ {#each colorsArray as color}
125
+ <div
126
+ on:click={() => handleColorChange(option.name, color, idx)}
127
+ style="--color:{color};"
128
+ class="circle circle-hover"
129
+ />
130
+ {/each}
131
+ </div>
132
+ </Popover>
133
+ </div>
134
+ </div>
135
+ <div class="child">
136
+ <input
137
+ class="input-field"
138
+ type="text"
139
+ on:change={e => handleNameChange(option.name, idx, e.target.value)}
140
+ value={option.name}
141
+ placeholder="Option name"
142
+ />
143
+ </div>
144
+ <div class="child">
145
+ <Icon name="Close" hoverable size="S" on:click={removeInput(idx)} />
146
+ </div>
147
+ </div>
148
+ {/each}
149
+ </div>
150
+ <div on:click={addNewInput} class="add-option">
151
+ <Icon hoverable name="Add" />
152
+ <div>Add option</div>
153
+ </div>
154
+ </div>
155
+
156
+ <style>
157
+ .action-container {
158
+ background-color: var(--spectrum-alias-background-color-primary);
159
+ border-radius: 0px;
160
+ border: 1px solid var(--spectrum-global-color-gray-300);
161
+ transition: background-color 130ms ease-in-out, color 130ms ease-in-out,
162
+ border-color 130ms ease-in-out;
163
+ display: flex;
164
+ flex-direction: row;
165
+ align-items: center;
166
+ }
167
+ .no-border {
168
+ border-bottom: none;
169
+ }
170
+
171
+ .action-container:last-child {
172
+ border-bottom: 1px solid var(--spectrum-global-color-gray-300) !important;
173
+ }
174
+
175
+ .child {
176
+ height: 30px;
177
+ }
178
+ .child:hover,
179
+ .child:focus {
180
+ background: var(--spectrum-global-color-gray-200);
181
+ }
182
+ .add-option {
183
+ display: flex;
184
+ flex-direction: row;
185
+ align-items: center;
186
+ padding: var(--spacing-m);
187
+ gap: var(--spacing-m);
188
+ cursor: pointer;
189
+ }
190
+
191
+ .input-field {
192
+ border: none;
193
+ outline: none;
194
+ background-color: transparent;
195
+ width: 100%;
196
+ color: var(--text);
197
+ }
198
+
199
+ .child input[type="text"] {
200
+ padding-left: 10px;
201
+ }
202
+
203
+ .input-field:hover,
204
+ .input-field:focus {
205
+ background: var(--spectrum-global-color-gray-200);
206
+ }
207
+
208
+ .action-container > :nth-child(1) {
209
+ flex-grow: 1;
210
+ justify-content: center;
211
+ display: flex;
212
+ }
213
+
214
+ .action-container > :nth-child(2) {
215
+ flex-grow: 1;
216
+ display: flex;
217
+ justify-content: center;
218
+ align-items: center;
219
+ }
220
+
221
+ .action-container > :nth-child(3) {
222
+ flex-grow: 4;
223
+ display: flex;
224
+ }
225
+ .action-container > :nth-child(4) {
226
+ flex-grow: 1;
227
+ justify-content: center;
228
+ display: flex;
229
+ }
230
+
231
+ .circle {
232
+ height: 20px;
233
+ width: 20px;
234
+ background-color: var(--color);
235
+ border-radius: 50%;
236
+ display: inline-block;
237
+ box-sizing: border-box;
238
+ }
239
+
240
+ .circle-hover:hover {
241
+ border: 1px solid var(--spectrum-global-color-blue-400);
242
+ cursor: pointer;
243
+ }
244
+
245
+ .colors {
246
+ display: grid;
247
+ grid-template-columns: 1fr 1fr 1fr;
248
+ gap: var(--spacing-xl);
249
+ justify-items: center;
250
+ margin: var(--spacing-m);
251
+ }
252
+ </style>
@@ -21,6 +21,7 @@
21
21
  export let offset = 5
22
22
  export let customHeight
23
23
  export let animate = true
24
+ export let customZindex
24
25
 
25
26
  $: target = portalTarget || getContext(Context.PopoverRoot) || ".spectrum"
26
27
 
@@ -77,8 +78,9 @@
77
78
  }}
78
79
  on:keydown={handleEscape}
79
80
  class="spectrum-Popover is-open"
81
+ class:customZindex
80
82
  role="presentation"
81
- style="height: {customHeight}"
83
+ style="height: {customHeight}; --customZindex: {customZindex};"
82
84
  transition:fly|local={{ y: -20, duration: animate ? 200 : 0 }}
83
85
  >
84
86
  <slot />
@@ -92,4 +94,8 @@
92
94
  border-color: var(--spectrum-global-color-gray-300);
93
95
  overflow: auto;
94
96
  }
97
+
98
+ .customZindex {
99
+ z-index: var(--customZindex) !important;
100
+ }
95
101
  </style>
@@ -29,7 +29,6 @@
29
29
  $: type = getType(schema)
30
30
  $: customRenderer = customRenderers?.find(x => x.column === schema?.name)
31
31
  $: renderer = customRenderer?.component ?? typeMap[type] ?? StringRenderer
32
- $: width = schema?.width || "150px"
33
32
  $: cellValue = getCellValue(value, schema.template)
34
33
 
35
34
  const getType = schema => {
@@ -379,7 +379,7 @@
379
379
  </div>
380
380
  {/if}
381
381
  {#if sortedRows?.length}
382
- {#each sortedRows as row, idx}
382
+ {#each sortedRows as row}
383
383
  <div class="spectrum-Table-row" class:clickable={allowClickRows}>
384
384
  {#if showEditColumn}
385
385
  <div