@budibase/bbui 1.0.191 → 1.0.192

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": "1.0.191",
4
+ "version": "1.0.192",
5
5
  "license": "MPL-2.0",
6
6
  "svelte": "src/index.js",
7
7
  "module": "dist/bbui.es.js",
@@ -38,7 +38,7 @@
38
38
  ],
39
39
  "dependencies": {
40
40
  "@adobe/spectrum-css-workflow-icons": "^1.2.1",
41
- "@budibase/string-templates": "^1.0.191",
41
+ "@budibase/string-templates": "^1.0.192",
42
42
  "@spectrum-css/actionbutton": "^1.0.1",
43
43
  "@spectrum-css/actiongroup": "^1.0.1",
44
44
  "@spectrum-css/avatar": "^3.0.2",
@@ -84,5 +84,5 @@
84
84
  "svelte-flatpickr": "^3.2.3",
85
85
  "svelte-portal": "^1.0.0"
86
86
  },
87
- "gitHead": "5f9a79722351f52ddddc54fba5b5f9ef0804ea97"
87
+ "gitHead": "95d1af6c856ca6b7b105185789214dd1b243f5c7"
88
88
  }
@@ -0,0 +1,68 @@
1
+ <script>
2
+ import "@spectrum-css/fieldgroup/dist/index-vars.css"
3
+ import "@spectrum-css/radio/dist/index-vars.css"
4
+ import { createEventDispatcher } from "svelte"
5
+
6
+ export let direction = "vertical"
7
+ export let value = []
8
+ export let options = []
9
+ export let error = null
10
+ export let disabled = false
11
+ export let getOptionLabel = option => option
12
+ export let getOptionValue = option => option
13
+
14
+ const dispatch = createEventDispatcher()
15
+ 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)
20
+ }
21
+ value = tempValue
22
+ dispatch(
23
+ "change",
24
+ tempValue.filter(val => val !== e.target.value || isChecked)
25
+ )
26
+ }
27
+ </script>
28
+
29
+ <div class={`spectrum-FieldGroup spectrum-FieldGroup--${direction}`}>
30
+ {#if options && Array.isArray(options)}
31
+ {#each options as option}
32
+ <div
33
+ title={getOptionLabel(option)}
34
+ class="spectrum-Checkbox spectrum-FieldGroup-item"
35
+ class:is-invalid={!!error}
36
+ >
37
+ <label
38
+ class="spectrum-Checkbox spectrum-Checkbox--sizeM spectrum-FieldGroup-item"
39
+ >
40
+ <input
41
+ on:change={onChange}
42
+ value={getOptionValue(option)}
43
+ type="checkbox"
44
+ class="spectrum-Checkbox-input"
45
+ {disabled}
46
+ checked={value.includes(getOptionValue(option))}
47
+ />
48
+ <span class="spectrum-Checkbox-box">
49
+ <svg
50
+ class="spectrum-Icon spectrum-UIIcon-Checkmark100 spectrum-Checkbox-checkmark"
51
+ focusable="false"
52
+ aria-hidden="true"
53
+ >
54
+ <use xlink:href="#spectrum-css-icon-Checkmark100" />
55
+ </svg>
56
+ </span>
57
+ <span class="spectrum-Checkbox-label">{getOptionLabel(option)}</span>
58
+ </label>
59
+ </div>
60
+ {/each}
61
+ {/if}
62
+ </div>
63
+
64
+ <style>
65
+ .spectrum-Checkbox-input {
66
+ opacity: 0;
67
+ }
68
+ </style>
@@ -161,8 +161,8 @@
161
161
  <input
162
162
  data-input
163
163
  type="text"
164
- {disabled}
165
164
  class="spectrum-Textfield-input spectrum-InputGroup-input"
165
+ class:is-disabled={disabled}
166
166
  {placeholder}
167
167
  {id}
168
168
  {value}
@@ -172,7 +172,7 @@
172
172
  type="button"
173
173
  class="spectrum-Picker spectrum-Picker--sizeM spectrum-InputGroup-button"
174
174
  tabindex="-1"
175
- {disabled}
175
+ class:is-disabled={disabled}
176
176
  class:is-invalid={!!error}
177
177
  on:click={flatpickr?.open}
178
178
  >
@@ -217,4 +217,7 @@
217
217
  :global(.flatpickr-calendar) {
218
218
  font-family: "Source Sans Pro", sans-serif;
219
219
  }
220
+ .is-disabled {
221
+ pointer-events: none !important;
222
+ }
220
223
  </style>
@@ -18,6 +18,7 @@
18
18
  export let fileSizeLimit = BYTES_IN_MB * 20
19
19
  export let processFiles = null
20
20
  export let handleFileTooLarge = null
21
+ export let handleTooManyFiles = null
21
22
  export let gallery = true
22
23
  export let error = null
23
24
  export let fileTags = []
@@ -71,6 +72,13 @@
71
72
  handleFileTooLarge(fileSizeLimit, value)
72
73
  return
73
74
  }
75
+
76
+ const fileCount = fileList.length + value.length
77
+ if (handleTooManyFiles && maximum && fileCount > maximum) {
78
+ handleTooManyFiles(maximum)
79
+ return
80
+ }
81
+
74
82
  if (processFiles) {
75
83
  const processedFiles = await processFiles(fileList)
76
84
  const newValue = [...value, ...processedFiles]
@@ -43,7 +43,7 @@
43
43
  return
44
44
  }
45
45
  searchTerm = null
46
- open = true
46
+ open = !open
47
47
  }
48
48
 
49
49
  const getSortedOptions = (options, getLabel, sort) => {
@@ -71,105 +71,73 @@
71
71
  }
72
72
  </script>
73
73
 
74
- <button
75
- {id}
76
- class="spectrum-Picker spectrum-Picker--sizeM"
77
- class:spectrum-Picker--quiet={quiet}
78
- {disabled}
79
- class:is-invalid={!!error}
80
- class:is-open={open}
81
- aria-haspopup="listbox"
82
- on:mousedown={onClick}
83
- >
84
- {#if fieldIcon}
85
- <span class="icon-Placeholder-Padding">
86
- <img src={fieldIcon} alt="icon" width="20" height="15" />
87
- </span>
88
- {/if}
89
-
90
- <span
91
- class="spectrum-Picker-label"
92
- class:is-placeholder={isPlaceholder}
93
- class:auto-width={autoWidth}
74
+ <div use:clickOutside={() => (open = false)}>
75
+ <button
76
+ {id}
77
+ class="spectrum-Picker spectrum-Picker--sizeM"
78
+ class:spectrum-Picker--quiet={quiet}
79
+ {disabled}
80
+ class:is-invalid={!!error}
81
+ class:is-open={open}
82
+ aria-haspopup="listbox"
83
+ on:mousedown={onClick}
94
84
  >
95
- {fieldText}
96
- </span>
97
- {#if error}
85
+ {#if fieldIcon}
86
+ <span class="icon-Placeholder-Padding">
87
+ <img src={fieldIcon} alt="icon" width="20" height="15" />
88
+ </span>
89
+ {/if}
90
+
91
+ <span
92
+ class="spectrum-Picker-label"
93
+ class:is-placeholder={isPlaceholder}
94
+ class:auto-width={autoWidth}
95
+ >
96
+ {fieldText}
97
+ </span>
98
+ {#if error}
99
+ <svg
100
+ class="spectrum-Icon spectrum-Icon--sizeM spectrum-Picker-validationIcon"
101
+ focusable="false"
102
+ aria-hidden="true"
103
+ aria-label="Folder"
104
+ >
105
+ <use xlink:href="#spectrum-icon-18-Alert" />
106
+ </svg>
107
+ {/if}
98
108
  <svg
99
- class="spectrum-Icon spectrum-Icon--sizeM spectrum-Picker-validationIcon"
109
+ class="spectrum-Icon spectrum-UIIcon-ChevronDown100 spectrum-Picker-menuIcon"
100
110
  focusable="false"
101
111
  aria-hidden="true"
102
- aria-label="Folder"
103
112
  >
104
- <use xlink:href="#spectrum-icon-18-Alert" />
113
+ <use xlink:href="#spectrum-css-icon-Chevron100" />
105
114
  </svg>
106
- {/if}
107
- <svg
108
- class="spectrum-Icon spectrum-UIIcon-ChevronDown100 spectrum-Picker-menuIcon"
109
- focusable="false"
110
- aria-hidden="true"
111
- >
112
- <use xlink:href="#spectrum-css-icon-Chevron100" />
113
- </svg>
114
- </button>
115
- {#if open}
116
- <div
117
- use:clickOutside={() => (open = false)}
118
- transition:fly|local={{ y: -20, duration: 200 }}
119
- class="spectrum-Popover spectrum-Popover--bottom spectrum-Picker-popover is-open"
120
- class:auto-width={autoWidth}
121
- >
122
- {#if autocomplete}
123
- <Search
124
- value={searchTerm}
125
- on:change={event => (searchTerm = event.detail)}
126
- {disabled}
127
- placeholder="Search"
128
- />
129
- {/if}
130
- <ul class="spectrum-Menu" role="listbox">
131
- {#if placeholderOption}
132
- <li
133
- class="spectrum-Menu-item placeholder"
134
- class:is-selected={isPlaceholder}
135
- role="option"
136
- aria-selected="true"
137
- tabindex="0"
138
- on:click={() => onSelectOption(null)}
139
- >
140
- <span class="spectrum-Menu-itemLabel">{placeholderOption}</span>
141
- <svg
142
- class="spectrum-Icon spectrum-UIIcon-Checkmark100 spectrum-Menu-checkmark spectrum-Menu-itemIcon"
143
- focusable="false"
144
- aria-hidden="true"
145
- >
146
- <use xlink:href="#spectrum-css-icon-Checkmark100" />
147
- </svg>
148
- </li>
115
+ </button>
116
+ {#if open}
117
+ <div
118
+ transition:fly|local={{ y: -20, duration: 200 }}
119
+ class="spectrum-Popover spectrum-Popover--bottom spectrum-Picker-popover is-open"
120
+ class:auto-width={autoWidth}
121
+ >
122
+ {#if autocomplete}
123
+ <Search
124
+ value={searchTerm}
125
+ on:change={event => (searchTerm = event.detail)}
126
+ {disabled}
127
+ placeholder="Search"
128
+ />
149
129
  {/if}
150
- {#if filteredOptions.length}
151
- {#each filteredOptions as option, idx}
130
+ <ul class="spectrum-Menu" role="listbox">
131
+ {#if placeholderOption}
152
132
  <li
153
- class="spectrum-Menu-item"
154
- class:is-selected={isOptionSelected(getOptionValue(option, idx))}
133
+ class="spectrum-Menu-item placeholder"
134
+ class:is-selected={isPlaceholder}
155
135
  role="option"
156
136
  aria-selected="true"
157
137
  tabindex="0"
158
- on:click={() => onSelectOption(getOptionValue(option, idx))}
138
+ on:click={() => onSelectOption(null)}
159
139
  >
160
- {#if getOptionIcon(option, idx)}
161
- <span class="icon-Padding">
162
- <img
163
- src={getOptionIcon(option, idx)}
164
- alt="icon"
165
- width="20"
166
- height="15"
167
- />
168
- </span>
169
- {/if}
170
- <span class="spectrum-Menu-itemLabel">
171
- {getOptionLabel(option, idx)}
172
- </span>
140
+ <span class="spectrum-Menu-itemLabel">{placeholderOption}</span>
173
141
  <svg
174
142
  class="spectrum-Icon spectrum-UIIcon-Checkmark100 spectrum-Menu-checkmark spectrum-Menu-itemIcon"
175
143
  focusable="false"
@@ -178,11 +146,44 @@
178
146
  <use xlink:href="#spectrum-css-icon-Checkmark100" />
179
147
  </svg>
180
148
  </li>
181
- {/each}
182
- {/if}
183
- </ul>
184
- </div>
185
- {/if}
149
+ {/if}
150
+ {#if filteredOptions.length}
151
+ {#each filteredOptions as option, idx}
152
+ <li
153
+ class="spectrum-Menu-item"
154
+ class:is-selected={isOptionSelected(getOptionValue(option, idx))}
155
+ role="option"
156
+ aria-selected="true"
157
+ tabindex="0"
158
+ on:click={() => onSelectOption(getOptionValue(option, idx))}
159
+ >
160
+ {#if getOptionIcon(option, idx)}
161
+ <span class="icon-Padding">
162
+ <img
163
+ src={getOptionIcon(option, idx)}
164
+ alt="icon"
165
+ width="20"
166
+ height="15"
167
+ />
168
+ </span>
169
+ {/if}
170
+ <span class="spectrum-Menu-itemLabel">
171
+ {getOptionLabel(option, idx)}
172
+ </span>
173
+ <svg
174
+ class="spectrum-Icon spectrum-UIIcon-Checkmark100 spectrum-Menu-checkmark spectrum-Menu-itemIcon"
175
+ focusable="false"
176
+ aria-hidden="true"
177
+ >
178
+ <use xlink:href="#spectrum-css-icon-Checkmark100" />
179
+ </svg>
180
+ </li>
181
+ {/each}
182
+ {/if}
183
+ </ul>
184
+ </div>
185
+ {/if}
186
+ </div>
186
187
 
187
188
  <style>
188
189
  .spectrum-Popover {
@@ -1,6 +1,6 @@
1
1
  <script>
2
2
  import "@spectrum-css/textfield/dist/index-vars.css"
3
- import { createEventDispatcher } from "svelte"
3
+ import { createEventDispatcher, onMount } from "svelte"
4
4
 
5
5
  export let value = null
6
6
  export let placeholder = null
@@ -13,8 +13,11 @@
13
13
  export let quiet = false
14
14
  export let dataCy
15
15
  export let align
16
+ export let autofocus = false
16
17
 
17
18
  const dispatch = createEventDispatcher()
19
+
20
+ let field
18
21
  let focus = false
19
22
 
20
23
  const updateValue = newValue => {
@@ -58,6 +61,11 @@
58
61
  updateValue(event.target.value)
59
62
  }
60
63
  }
64
+
65
+ onMount(() => {
66
+ focus = autofocus
67
+ if (focus) field.focus()
68
+ })
61
69
  </script>
62
70
 
63
71
  <div
@@ -77,6 +85,7 @@
77
85
  </svg>
78
86
  {/if}
79
87
  <input
88
+ bind:this={field}
80
89
  {disabled}
81
90
  {readonly}
82
91
  {id}
@@ -3,6 +3,7 @@ export { default as CoreSelect } from "./Select.svelte"
3
3
  export { default as CoreMultiselect } from "./Multiselect.svelte"
4
4
  export { default as CoreCheckbox } from "./Checkbox.svelte"
5
5
  export { default as CoreRadioGroup } from "./RadioGroup.svelte"
6
+ export { default as CoreCheckboxGroup } from "./CheckboxGroup.svelte"
6
7
  export { default as CoreTextArea } from "./TextArea.svelte"
7
8
  export { default as CoreCombobox } from "./Combobox.svelte"
8
9
  export { default as CoreSwitch } from "./Switch.svelte"
@@ -11,6 +11,7 @@
11
11
  export let fileSizeLimit = undefined
12
12
  export let processFiles = undefined
13
13
  export let handleFileTooLarge = undefined
14
+ export let handleTooManyFiles = undefined
14
15
  export let gallery = true
15
16
  export let fileTags = []
16
17
  export let maximum = undefined
@@ -30,6 +31,7 @@
30
31
  {fileSizeLimit}
31
32
  {processFiles}
32
33
  {handleFileTooLarge}
34
+ {handleTooManyFiles}
33
35
  {gallery}
34
36
  {fileTags}
35
37
  {maximum}
@@ -14,6 +14,7 @@
14
14
  export let updateOnChange = true
15
15
  export let quiet = false
16
16
  export let dataCy
17
+ export let autofocus
17
18
 
18
19
  const dispatch = createEventDispatcher()
19
20
  const onChange = e => {
@@ -33,6 +34,7 @@
33
34
  {placeholder}
34
35
  {type}
35
36
  {quiet}
37
+ {autofocus}
36
38
  on:change={onChange}
37
39
  on:click
38
40
  on:input
@@ -40,6 +40,10 @@
40
40
  padding-left: var(--spacing-xl);
41
41
  padding-right: var(--spacing-xl);
42
42
  }
43
+ .paddingX-XXL {
44
+ padding-left: var(--spectrum-alias-grid-gutter-large);
45
+ padding-right: var(--spectrum-alias-grid-gutter-large);
46
+ }
43
47
  .paddingY-S {
44
48
  padding-top: var(--spacing-s);
45
49
  padding-bottom: var(--spacing-s);
@@ -56,6 +60,10 @@
56
60
  padding-top: var(--spacing-xl);
57
61
  padding-bottom: var(--spacing-xl);
58
62
  }
63
+ .paddingY-XXL {
64
+ padding-top: var(--spectrum-alias-grid-gutter-large);
65
+ padding-bottom: var(--spectrum-alias-grid-gutter-large);
66
+ }
59
67
  .gap-XXS {
60
68
  grid-gap: var(--spacing-xs);
61
69
  }
@@ -1,9 +1,10 @@
1
1
  <script>
2
2
  export let wide = false
3
3
  export let maxWidth = "80ch"
4
+ export let noPadding = false
4
5
  </script>
5
6
 
6
- <div style="--max-width: {maxWidth}" class:wide>
7
+ <div style="--max-width: {maxWidth}" class:wide class:noPadding>
7
8
  <slot />
8
9
  </div>
9
10
 
@@ -23,4 +24,9 @@
23
24
  max-width: none;
24
25
  margin: 0;
25
26
  }
27
+
28
+ .noPadding {
29
+ padding: 0px;
30
+ margin: 0px;
31
+ }
26
32
  </style>
@@ -7,6 +7,7 @@
7
7
  export let icon = ""
8
8
  export let selected = false
9
9
  export let disabled = false
10
+ export let dataCy
10
11
  </script>
11
12
 
12
13
  <li
@@ -14,6 +15,7 @@
14
15
  class:is-selected={selected}
15
16
  class:is-disabled={disabled}
16
17
  on:click
18
+ data-cy={dataCy}
17
19
  >
18
20
  {#if heading}
19
21
  <h2 class="spectrum-SideNav-heading" id="nav-heading-{heading}">
@@ -6,7 +6,7 @@
6
6
 
7
7
  const dispatch = createEventDispatcher()
8
8
  let selected = getContext("tab")
9
- let tab
9
+ let tab_internal
10
10
  let tabInfo
11
11
 
12
12
  const setTabInfo = () => {
@@ -16,7 +16,7 @@
16
16
  // We just need to get this off the main thread to fix this, by using
17
17
  // a 0ms timeout.
18
18
  setTimeout(() => {
19
- tabInfo = tab?.getBoundingClientRect()
19
+ tabInfo = tab_internal?.getBoundingClientRect()
20
20
  if (tabInfo && $selected.title === title) {
21
21
  $selected.info = tabInfo
22
22
  }
@@ -27,14 +27,30 @@
27
27
  setTabInfo()
28
28
  })
29
29
 
30
+ //Ensure that the underline is in the correct location
31
+ $: {
32
+ if ($selected.title === title && tab_internal) {
33
+ if ($selected.info?.left !== tab_internal.getBoundingClientRect().left) {
34
+ $selected = {
35
+ ...$selected,
36
+ info: tab_internal.getBoundingClientRect(),
37
+ }
38
+ }
39
+ }
40
+ }
41
+
30
42
  const onClick = () => {
31
- $selected = { ...$selected, title, info: tab.getBoundingClientRect() }
43
+ $selected = {
44
+ ...$selected,
45
+ title,
46
+ info: tab_internal.getBoundingClientRect(),
47
+ }
32
48
  dispatch("click")
33
49
  }
34
50
  </script>
35
51
 
36
52
  <div
37
- bind:this={tab}
53
+ bind:this={tab_internal}
38
54
  on:click={onClick}
39
55
  class:is-selected={$selected.title === title}
40
56
  class="spectrum-Tabs-item"