@budibase/bbui 1.58.13 → 2.0.1

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 (181) hide show
  1. package/LICENSE +375 -0
  2. package/dist/bbui.es.js +14 -0
  3. package/dist/bbui.es.js.map +1 -0
  4. package/package.json +68 -32
  5. package/src/ActionButton/ActionButton.svelte +102 -0
  6. package/src/ActionGroup/ActionGroup.svelte +26 -0
  7. package/src/ActionMenu/ActionMenu.svelte +44 -0
  8. package/src/Actions/autoresize_textarea.js +9 -9
  9. package/src/Actions/click_outside.js +5 -5
  10. package/src/Actions/position_dropdown.js +46 -37
  11. package/src/Avatar/Avatar.svelte +62 -0
  12. package/src/Badge/Badge.svelte +29 -0
  13. package/src/Banner/Banner.svelte +72 -0
  14. package/src/Banner/BannerDisplay.svelte +41 -0
  15. package/src/Button/Button.svelte +102 -200
  16. package/src/ButtonGroup/ButtonGroup.svelte +30 -0
  17. package/src/ClearButton/ClearButton.svelte +19 -0
  18. package/src/ColorPicker/ColorPicker.svelte +297 -0
  19. package/src/DetailSummary/DetailSummary.svelte +83 -0
  20. package/src/Divider/Divider.svelte +28 -0
  21. package/src/Drawer/Drawer.svelte +76 -51
  22. package/src/Drawer/DrawerContent.svelte +46 -0
  23. package/src/Form/Checkbox.svelte +21 -132
  24. package/src/Form/Combobox.svelte +45 -0
  25. package/src/Form/Core/Checkbox.svelte +69 -0
  26. package/src/Form/Core/CheckboxGroup.svelte +68 -0
  27. package/src/Form/Core/Combobox.svelte +142 -0
  28. package/src/Form/Core/DatePicker.svelte +257 -0
  29. package/src/Form/Core/Dropzone.svelte +453 -0
  30. package/src/Form/Core/InputDropdown.svelte +228 -0
  31. package/src/Form/Core/Multiselect.svelte +90 -0
  32. package/src/Form/Core/Picker.svelte +259 -0
  33. package/src/Form/Core/PickerDropdown.svelte +415 -0
  34. package/src/Form/Core/RadioGroup.svelte +48 -0
  35. package/src/Form/Core/RichTextField.svelte +42 -0
  36. package/src/Form/Core/Search.svelte +105 -0
  37. package/src/Form/Core/Select.svelte +75 -0
  38. package/src/Form/Core/Slider.svelte +86 -0
  39. package/src/Form/Core/Stepper.svelte +172 -0
  40. package/src/Form/Core/Switch.svelte +37 -0
  41. package/src/Form/Core/TextArea.svelte +78 -0
  42. package/src/Form/Core/TextField.svelte +119 -0
  43. package/src/Form/Core/index.js +15 -0
  44. package/src/Form/DatePicker.svelte +39 -0
  45. package/src/Form/Dropzone.svelte +42 -0
  46. package/src/Form/Field.svelte +42 -0
  47. package/src/Form/FieldLabel.svelte +32 -0
  48. package/src/Form/Input.svelte +41 -187
  49. package/src/Form/InputDropdown.svelte +55 -0
  50. package/src/Form/Multiselect.svelte +36 -320
  51. package/src/Form/PickerDropdown.svelte +132 -0
  52. package/src/Form/RadioGroup.svelte +42 -0
  53. package/src/Form/RichTextField.svelte +36 -0
  54. package/src/Form/Search.svelte +36 -0
  55. package/src/Form/Select.svelte +48 -88
  56. package/src/Form/Slider.svelte +16 -91
  57. package/src/Form/Stepper.svelte +45 -0
  58. package/src/Form/TextArea.svelte +30 -128
  59. package/src/Form/Toggle.svelte +20 -110
  60. package/src/Icon/Icon.svelte +91 -0
  61. package/src/Icon/IconAvatar.svelte +58 -0
  62. package/src/IconPicker/IconPicker.svelte +177 -0
  63. package/src/IconSideNav/IconSideNav.svelte +14 -0
  64. package/src/IconSideNav/IconSideNavItem.svelte +56 -0
  65. package/src/InlineAlert/InlineAlert.svelte +60 -0
  66. package/src/Label/Label.svelte +29 -0
  67. package/src/Layout/Layout.svelte +94 -0
  68. package/src/Layout/Page.svelte +32 -0
  69. package/src/Link/Link.svelte +24 -0
  70. package/src/List/List.svelte +28 -0
  71. package/src/List/ListItem.svelte +90 -0
  72. package/src/Markdown/MarkdownEditor.svelte +60 -0
  73. package/src/Markdown/MarkdownViewer.svelte +70 -0
  74. package/src/Markdown/SpectrumMDE.svelte +184 -0
  75. package/src/Menu/Item.svelte +96 -0
  76. package/src/Menu/Menu.svelte +7 -0
  77. package/src/Menu/Menu.svench +19 -0
  78. package/src/Menu/Section.svelte +10 -0
  79. package/src/Menu/Separator.svelte +1 -0
  80. package/src/Modal/Content.svelte +0 -11
  81. package/src/Modal/CustomContent.svelte +9 -6
  82. package/src/Modal/Modal.svelte +104 -51
  83. package/src/Modal/ModalContent.svelte +131 -73
  84. package/src/Modal/QuizModal.svelte +16 -17
  85. package/src/Notification/Notification.svelte +70 -0
  86. package/src/Notification/NotificationDisplay.svelte +43 -0
  87. package/src/Pagination/Pagination.svelte +57 -0
  88. package/src/Popover/Popover.svelte +43 -33
  89. package/src/ProgressBar/ProgressBar.svelte +67 -0
  90. package/src/ProgressCircle/ProgressCircle.svelte +62 -0
  91. package/src/SideNavigation/Item.svelte +61 -0
  92. package/src/SideNavigation/Navigation.svelte +12 -0
  93. package/src/StatusLight/StatusLight.svelte +80 -0
  94. package/src/Stores/Notifications.svench.svx +1 -1
  95. package/src/Stores/banner.js +65 -0
  96. package/src/Stores/notifications.js +75 -38
  97. package/src/Table/ArrayRenderer.svelte +17 -0
  98. package/src/Table/AttachmentRenderer.svelte +73 -0
  99. package/src/Table/BoldRenderer.svelte +15 -0
  100. package/src/Table/BooleanRenderer.svelte +42 -0
  101. package/src/Table/CellRenderer.svelte +69 -0
  102. package/src/Table/CodeRenderer.svelte +14 -0
  103. package/src/Table/DateTimeRenderer.svelte +29 -0
  104. package/src/Table/InternalRenderer.svelte +24 -0
  105. package/src/Table/RelationshipRenderer.svelte +40 -0
  106. package/src/Table/SelectEditRenderer.svelte +28 -0
  107. package/src/Table/StringRenderer.svelte +14 -0
  108. package/src/Table/Table.svelte +635 -0
  109. package/src/Table/index.js +1 -0
  110. package/src/Tabs/Tab.svelte +88 -0
  111. package/src/Tabs/Tabs.svelte +130 -0
  112. package/src/Tags/Tag.svelte +43 -0
  113. package/src/Tags/Tags.svelte +7 -0
  114. package/src/Tooltip/Tooltip.svelte +34 -0
  115. package/src/Tooltip/TooltipWrapper.svelte +60 -0
  116. package/src/TreeView/Item.svelte +41 -0
  117. package/src/TreeView/Tree.svelte +16 -0
  118. package/src/Typography/Body.svelte +21 -0
  119. package/src/Typography/Code.svelte +10 -0
  120. package/src/Typography/Detail.svelte +19 -0
  121. package/src/Typography/Heading.svelte +17 -0
  122. package/{dist → src}/bbui.css +2 -99
  123. package/src/context.js +1 -1
  124. package/src/helpers.js +134 -0
  125. package/src/index.js +95 -40
  126. package/src/spectrum-icons-rollup.js +31 -0
  127. package/src/spectrum-icons-vite.js +31 -0
  128. package/dist/dist/bundle.css +0 -42
  129. package/dist/dist/bundle.css.map +0 -64
  130. package/dist/index.js +0 -36193
  131. package/dist/index.mjs +0 -36147
  132. package/src/Button/Close.svelte +0 -59
  133. package/src/Button/Close.svench +0 -36
  134. package/src/Button/TextButton.svelte +0 -128
  135. package/src/Button/TextButton.svench +0 -69
  136. package/src/DatePicker/DatePicker.svelte +0 -45
  137. package/src/DatePicker/DatePicker.svench +0 -17
  138. package/src/DropdownMenu/DropdownMenu.svelte +0 -77
  139. package/src/DropdownMenu/DropdownMenu.svench +0 -161
  140. package/src/Dropzone/Dropzone.svelte +0 -294
  141. package/src/Dropzone/Dropzone.svench +0 -17
  142. package/src/Dropzone/fileTypes.js +0 -5
  143. package/src/Form/Checkbox.svench.svx +0 -67
  144. package/src/Form/DataList.svelte +0 -158
  145. package/src/Form/DataList.svench +0 -57
  146. package/src/Form/Input.svench +0 -62
  147. package/src/Form/Multiselect.svench +0 -63
  148. package/src/Form/Radio.svelte +0 -133
  149. package/src/Form/Radio.svench.svx +0 -64
  150. package/src/Form/RichText.svelte +0 -61
  151. package/src/Form/RichText.svench.svx +0 -40
  152. package/src/Form/Select.svench +0 -62
  153. package/src/Form/Slider.svench +0 -26
  154. package/src/Form/TextArea.svench +0 -30
  155. package/src/Form/Toggle.svench +0 -21
  156. package/src/Icons/Contribution.svelte +0 -14
  157. package/src/Icons/Icon.svelte +0 -36
  158. package/src/Icons/Icon.svench +0 -109
  159. package/src/Icons/icon-paths.js +0 -136
  160. package/src/Links/Home.svelte +0 -51
  161. package/src/Links/Home.svench +0 -19
  162. package/src/List/Items/DetailSummary.svelte +0 -85
  163. package/src/List/Items/DetailSummary.svench +0 -53
  164. package/src/List/Search.svelte +0 -34
  165. package/src/List/Search.svench +0 -8
  166. package/src/Spacer/Spacer.svelte +0 -50
  167. package/src/Spacer/Spacer.svench +0 -51
  168. package/src/Styleguide/Body.svelte +0 -72
  169. package/src/Styleguide/Borders.svench +0 -175
  170. package/src/Styleguide/Budibase-logo.svelte +0 -68
  171. package/src/Styleguide/Color.svench +0 -201
  172. package/src/Styleguide/Heading.svelte +0 -74
  173. package/src/Styleguide/Label.svelte +0 -70
  174. package/src/Styleguide/Logo.svelte +0 -16
  175. package/src/Styleguide/Logo.svench +0 -8
  176. package/src/Styleguide/Spacing.svench +0 -191
  177. package/src/Styleguide/Typography.svench +0 -227
  178. package/src/Switcher/Switcher.svelte +0 -47
  179. package/src/Switcher/Switcher.svench +0 -27
  180. package/src/index.svench.svx +0 -35
  181. package/src/utils/buildStyle.js +0 -14
@@ -0,0 +1,453 @@
1
+ <script>
2
+ import "@spectrum-css/dropzone/dist/index-vars.css"
3
+ import "@spectrum-css/typography/dist/index-vars.css"
4
+ import "@spectrum-css/illustratedmessage/dist/index-vars.css"
5
+ import { createEventDispatcher } from "svelte"
6
+ import { uuid } from "../../helpers"
7
+ import Icon from "../../Icon/Icon.svelte"
8
+ import Link from "../../Link/Link.svelte"
9
+ import Tag from "../../Tags/Tag.svelte"
10
+ import Tags from "../../Tags/Tags.svelte"
11
+
12
+ const BYTES_IN_KB = 1000
13
+ const BYTES_IN_MB = 1000000
14
+
15
+ export let value = []
16
+ export let id = null
17
+ export let disabled = false
18
+ export let fileSizeLimit = BYTES_IN_MB * 20
19
+ export let processFiles = null
20
+ export let deleteAttachments = null
21
+ export let handleFileTooLarge = null
22
+ export let handleTooManyFiles = null
23
+ export let gallery = true
24
+ export let error = null
25
+ export let fileTags = []
26
+ export let maximum = null
27
+ export let extensions = "*"
28
+
29
+ const dispatch = createEventDispatcher()
30
+ const imageExtensions = [
31
+ "png",
32
+ "tiff",
33
+ "gif",
34
+ "raw",
35
+ "jpg",
36
+ "jpeg",
37
+ "svg",
38
+ "bmp",
39
+ "jfif",
40
+ ]
41
+
42
+ const fieldId = id || uuid()
43
+ let selectedImageIdx = 0
44
+ let fileDragged = false
45
+ let selectedUrl
46
+ $: selectedImage = value?.[selectedImageIdx] ?? null
47
+ $: fileCount = value?.length ?? 0
48
+ $: isImage =
49
+ imageExtensions.includes(selectedImage?.extension?.toLowerCase()) ||
50
+ selectedImage?.type?.startsWith("image")
51
+
52
+ $: {
53
+ if (selectedImage?.url) {
54
+ selectedUrl = selectedImage?.url
55
+ } else if (selectedImage) {
56
+ try {
57
+ let reader = new FileReader()
58
+ reader.readAsDataURL(selectedImage)
59
+ reader.onload = e => {
60
+ selectedUrl = e.target.result
61
+ }
62
+ } catch (error) {
63
+ selectedUrl = null
64
+ }
65
+ }
66
+ }
67
+
68
+ $: showDropzone =
69
+ (!maximum || (maximum && value?.length < maximum)) && !disabled
70
+
71
+ async function processFileList(fileList) {
72
+ if (
73
+ handleFileTooLarge &&
74
+ Array.from(fileList).some(file => file.size >= fileSizeLimit)
75
+ ) {
76
+ handleFileTooLarge(fileSizeLimit, value)
77
+ return
78
+ }
79
+
80
+ const fileCount = fileList.length + value.length
81
+ if (handleTooManyFiles && maximum && fileCount > maximum) {
82
+ handleTooManyFiles(maximum)
83
+ return
84
+ }
85
+
86
+ if (processFiles) {
87
+ const processedFiles = await processFiles(fileList)
88
+ const newValue = [...value, ...processedFiles]
89
+ dispatch("change", newValue)
90
+ selectedImageIdx = newValue.length - 1
91
+ } else {
92
+ dispatch("change", fileList)
93
+ }
94
+ }
95
+
96
+ async function removeFile() {
97
+ dispatch(
98
+ "change",
99
+ value.filter((x, idx) => idx !== selectedImageIdx)
100
+ )
101
+ if (deleteAttachments) {
102
+ await deleteAttachments(
103
+ value.filter((x, idx) => idx === selectedImageIdx).map(item => item.key)
104
+ )
105
+ }
106
+ selectedImageIdx = 0
107
+ }
108
+
109
+ function navigateLeft() {
110
+ selectedImageIdx -= 1
111
+ }
112
+
113
+ function navigateRight() {
114
+ selectedImageIdx += 1
115
+ }
116
+
117
+ function handleFile(evt) {
118
+ processFileList(evt.target.files)
119
+ }
120
+
121
+ function handleDragOver(evt) {
122
+ evt.preventDefault()
123
+ fileDragged = true
124
+ }
125
+
126
+ function handleDragLeave(evt) {
127
+ evt.preventDefault()
128
+ fileDragged = false
129
+ }
130
+
131
+ function handleDrop(evt) {
132
+ evt.preventDefault()
133
+ processFileList(evt.dataTransfer.files)
134
+ fileDragged = false
135
+ }
136
+ </script>
137
+
138
+ <div class="container">
139
+ {#if selectedImage}
140
+ {#if gallery}
141
+ <div class="gallery">
142
+ <div class="title">
143
+ <div class="filename">
144
+ {#if selectedUrl}
145
+ <Link
146
+ target="_blank"
147
+ download={selectedImage.name}
148
+ href={selectedUrl}
149
+ >
150
+ {selectedImage.name}
151
+ </Link>
152
+ {:else}
153
+ {selectedImage.name}
154
+ {/if}
155
+ </div>
156
+ {#if selectedImage.size}
157
+ <div class="filesize">
158
+ {#if selectedImage.size <= BYTES_IN_MB}
159
+ {`${selectedImage.size / BYTES_IN_KB} KB`}
160
+ {:else}{`${selectedImage.size / BYTES_IN_MB} MB`}{/if}
161
+ </div>
162
+ {/if}
163
+ {#if !disabled}
164
+ <div class="delete-button" on:click={removeFile}>
165
+ <Icon name="Close" />
166
+ </div>
167
+ {/if}
168
+ </div>
169
+ {#if isImage}
170
+ <img alt="preview" src={selectedUrl} />
171
+ {:else}
172
+ <div class="placeholder">
173
+ <div class="extension">
174
+ {selectedImage.name || "Unknown file"}
175
+ </div>
176
+ <div>Preview not supported</div>
177
+ </div>
178
+ {/if}
179
+ <div
180
+ class="nav left"
181
+ class:visible={selectedImageIdx > 0}
182
+ on:click={navigateLeft}
183
+ >
184
+ <Icon name="ChevronLeft" />
185
+ </div>
186
+ <div
187
+ class="nav right"
188
+ class:visible={selectedImageIdx < fileCount - 1}
189
+ on:click={navigateRight}
190
+ >
191
+ <Icon name="ChevronRight" />
192
+ </div>
193
+ <div class="footer">File {selectedImageIdx + 1} of {fileCount}</div>
194
+ </div>
195
+ {:else if value?.length}
196
+ {#each value as file}
197
+ <div class="gallery">
198
+ <div class="title">
199
+ <div class="filename">{file.name}</div>
200
+ {#if file.size}
201
+ <div class="filesize">
202
+ {#if file.size <= BYTES_IN_MB}
203
+ {`${file.size / BYTES_IN_KB} KB`}
204
+ {:else}{`${file.size / BYTES_IN_MB} MB`}{/if}
205
+ </div>
206
+ {/if}
207
+ {#if !disabled}
208
+ <div class="delete-button" on:click={removeFile}>
209
+ <Icon name="Close" />
210
+ </div>
211
+ {/if}
212
+ </div>
213
+ </div>
214
+ {/each}
215
+ {/if}
216
+ {/if}
217
+ {#if showDropzone}
218
+ <div
219
+ class="spectrum-Dropzone"
220
+ class:is-invalid={!!error}
221
+ class:disabled
222
+ role="region"
223
+ tabindex="0"
224
+ on:dragover={handleDragOver}
225
+ on:dragleave={handleDragLeave}
226
+ on:dragenter={handleDragOver}
227
+ on:drop={handleDrop}
228
+ class:is-dragged={fileDragged}
229
+ >
230
+ <div class="spectrum-IllustratedMessage spectrum-IllustratedMessage--cta">
231
+ <input
232
+ id={fieldId}
233
+ {disabled}
234
+ type="file"
235
+ multiple
236
+ accept={extensions}
237
+ on:change={handleFile}
238
+ />
239
+ <svg
240
+ class="spectrum-IllustratedMessage-illustration"
241
+ width="125"
242
+ height="60"
243
+ viewBox="0 0 199 97.7"
244
+ >
245
+ <defs>
246
+ <style>
247
+ .cls-1,
248
+ .cls-2 {
249
+ fill: none;
250
+ stroke-linecap: round;
251
+ stroke-linejoin: round;
252
+ }
253
+ .cls-1 {
254
+ stroke-width: 3px;
255
+ }
256
+ .cls-2 {
257
+ stroke-width: 2px;
258
+ }
259
+ </style>
260
+ </defs>
261
+ <path
262
+ class="cls-1"
263
+ d="M110.53,85.66,100.26,95.89a1.09,1.09,0,0,1-1.52,0L88.47,85.66"
264
+ />
265
+ <line class="cls-1" x1="99.5" y1="95.5" x2="99.5" y2="58.5" />
266
+ <path class="cls-1" d="M105.5,73.5h19a2,2,0,0,0,2-2v-43" />
267
+ <path
268
+ class="cls-1"
269
+ d="M126.5,22.5h-19a2,2,0,0,1-2-2V1.5h-31a2,2,0,0,0-2,2v68a2,2,0,0,0,2,2h19"
270
+ />
271
+ <line class="cls-1" x1="105.5" y1="1.5" x2="126.5" y2="22.5" />
272
+ <path
273
+ class="cls-2"
274
+ d="M47.93,50.49a5,5,0,1,0-4.83-5A4.93,4.93,0,0,0,47.93,50.49Z"
275
+ />
276
+ <path
277
+ class="cls-2"
278
+ d="M36.6,65.93,42.05,60A2.06,2.06,0,0,1,45,60l12.68,13.2"
279
+ />
280
+ <path
281
+ class="cls-2"
282
+ d="M3.14,73.23,22.42,53.76a1.65,1.65,0,0,1,2.38,0l19.05,19.7"
283
+ />
284
+ <path
285
+ class="cls-1"
286
+ d="M139.5,36.5H196A1.49,1.49,0,0,1,197.5,38V72A1.49,1.49,0,0,1,196,73.5H141A1.49,1.49,0,0,1,139.5,72V32A1.49,1.49,0,0,1,141,30.5H154a2.43,2.43,0,0,1,1.67.66l6,5.66"
287
+ />
288
+ <rect
289
+ class="cls-1"
290
+ x="1.5"
291
+ y="34.5"
292
+ width="58"
293
+ height="39"
294
+ rx="2"
295
+ ry="2"
296
+ />
297
+ </svg>
298
+ <h2
299
+ class="spectrum-Heading spectrum-Heading--sizeL spectrum-Heading--light spectrum-IllustratedMessage-heading"
300
+ >
301
+ Drag and drop your file
302
+ </h2>
303
+ {#if !disabled}
304
+ <p
305
+ class="spectrum-Body spectrum-Body--sizeS spectrum-IllustratedMessage-description"
306
+ >
307
+ <label for={fieldId} class="spectrum-Link">
308
+ Select a file to upload
309
+ </label>
310
+ <br />
311
+ from your computer
312
+ </p>
313
+ {#if fileTags.length}
314
+ <Tags>
315
+ <div class="tags">
316
+ {#each fileTags as tag}
317
+ <div class="tag">
318
+ <Tag>
319
+ {tag}
320
+ </Tag>
321
+ </div>
322
+ {/each}
323
+ </div>
324
+ </Tags>
325
+ {/if}
326
+ {/if}
327
+ </div>
328
+ </div>
329
+ {/if}
330
+ </div>
331
+
332
+ <style>
333
+ .container {
334
+ --spectrum-dropzone-padding: var(--spectrum-global-dimension-size-400);
335
+ --spectrum-heading-l-text-size: var(
336
+ --spectrum-global-dimension-font-size-400
337
+ );
338
+ }
339
+
340
+ .gallery,
341
+ .spectrum-Dropzone {
342
+ user-select: none;
343
+ }
344
+ .spectrum-Dropzone.is-invalid {
345
+ border-color: var(--spectrum-global-color-red-400);
346
+ }
347
+ input[type="file"] {
348
+ display: none;
349
+ }
350
+
351
+ .gallery {
352
+ display: flex;
353
+ flex-direction: column;
354
+ justify-content: flex-start;
355
+ align-items: stretch;
356
+ background-color: var(--spectrum-global-color-gray-50);
357
+ color: var(--spectrum-alias-text-color);
358
+ font-size: var(--spectrum-alias-item-text-size-m);
359
+ box-sizing: border-box;
360
+ border: var(--spectrum-alias-border-size-thin)
361
+ var(--spectrum-alias-border-color) solid;
362
+ border-radius: var(--spectrum-alias-border-radius-regular);
363
+ padding: 10px;
364
+ margin-bottom: 10px;
365
+ position: relative;
366
+ }
367
+ .placeholder,
368
+ img {
369
+ height: 120px;
370
+ max-width: 100%;
371
+ object-fit: contain;
372
+ margin: 20px 30px;
373
+ }
374
+ .title {
375
+ display: flex;
376
+ flex-direction: row;
377
+ justify-content: flex-start;
378
+ align-items: center;
379
+ }
380
+ .filename {
381
+ flex: 1 1 auto;
382
+ overflow: hidden;
383
+ text-overflow: ellipsis;
384
+ white-space: nowrap;
385
+ width: 0;
386
+ margin-right: 10px;
387
+ user-select: all;
388
+ }
389
+ .placeholder {
390
+ display: flex;
391
+ flex-direction: column;
392
+ justify-content: center;
393
+ align-items: center;
394
+ text-align: center;
395
+ }
396
+ .extension {
397
+ color: var(--spectrum-global-color-gray-600);
398
+ text-transform: uppercase;
399
+ font-weight: 600;
400
+ margin-bottom: 5px;
401
+ user-select: all;
402
+ }
403
+
404
+ .nav {
405
+ padding: var(--spacing-xs);
406
+ position: absolute;
407
+ top: 50%;
408
+ border-radius: 5px;
409
+ display: none;
410
+ transition: all 0.3s;
411
+ }
412
+ .nav.visible {
413
+ display: block;
414
+ }
415
+ .nav:hover {
416
+ cursor: pointer;
417
+ color: var(--blue);
418
+ }
419
+ .left {
420
+ left: 5px;
421
+ }
422
+ .right {
423
+ right: 5px;
424
+ }
425
+ .delete-button {
426
+ transition: all 0.3s;
427
+ margin-left: 10px;
428
+ display: flex;
429
+ }
430
+ .delete-button:hover {
431
+ cursor: pointer;
432
+ color: var(--red);
433
+ }
434
+
435
+ .spectrum-Dropzone.disabled {
436
+ pointer-events: none;
437
+ background-color: var(--spectrum-global-color-gray-200);
438
+ }
439
+ .disabled .spectrum-Heading--sizeL {
440
+ color: var(--spectrum-alias-text-color-disabled);
441
+ }
442
+
443
+ .tags {
444
+ margin-top: 20px;
445
+ display: flex;
446
+ flex-wrap: wrap;
447
+ justify-content: center;
448
+ }
449
+
450
+ .tag {
451
+ margin-top: 8px;
452
+ }
453
+ </style>
@@ -0,0 +1,228 @@
1
+ <script>
2
+ import "@spectrum-css/inputgroup/dist/index-vars.css"
3
+ import "@spectrum-css/popover/dist/index-vars.css"
4
+ import "@spectrum-css/menu/dist/index-vars.css"
5
+ import { fly } from "svelte/transition"
6
+ import { createEventDispatcher } from "svelte"
7
+ import clickOutside from "../../Actions/click_outside"
8
+
9
+ export let inputValue
10
+ export let dropdownValue
11
+ export let id = null
12
+ export let inputType = "text"
13
+ export let placeholder = "Choose an option or type"
14
+ export let disabled = false
15
+ export let readonly = false
16
+ export let updateOnChange = true
17
+ export let error = null
18
+ export let options = []
19
+ export let getOptionLabel = option => extractProperty(option, "label")
20
+ export let getOptionValue = option => extractProperty(option, "value")
21
+
22
+ export let isOptionSelected = () => false
23
+
24
+ const dispatch = createEventDispatcher()
25
+ let open = false
26
+ let focus = false
27
+
28
+ $: fieldText = getFieldText(dropdownValue, options, placeholder)
29
+
30
+ const getFieldText = (dropdownValue, options, placeholder) => {
31
+ // Always use placeholder if no value
32
+ if (dropdownValue == null || dropdownValue === "") {
33
+ return placeholder || "Choose an option or type"
34
+ }
35
+
36
+ // Wait for options to load if there is a value but no options
37
+ if (!options?.length) {
38
+ return ""
39
+ }
40
+
41
+ // Render the label if the selected option is found, otherwise raw value
42
+ const selected = options.find(
43
+ option => getOptionValue(option) === dropdownValue
44
+ )
45
+ return selected ? getOptionLabel(selected) : dropdownValue
46
+ }
47
+
48
+ const updateValue = newValue => {
49
+ if (readonly) {
50
+ return
51
+ }
52
+ dispatch("change", newValue)
53
+ }
54
+
55
+ const onFocus = () => {
56
+ if (readonly) {
57
+ return
58
+ }
59
+ focus = true
60
+ }
61
+
62
+ const onBlur = event => {
63
+ if (readonly) {
64
+ return
65
+ }
66
+ focus = false
67
+ updateValue(event.target.value)
68
+ }
69
+
70
+ const onInput = event => {
71
+ if (readonly || !updateOnChange) {
72
+ return
73
+ }
74
+ updateValue(event.target.value)
75
+ }
76
+
77
+ const updateValueOnEnter = event => {
78
+ if (readonly) {
79
+ return
80
+ }
81
+ if (event.key === "Enter") {
82
+ updateValue(event.target.value)
83
+ }
84
+ }
85
+
86
+ const onClick = () => {
87
+ dispatch("click")
88
+ if (readonly) {
89
+ return
90
+ }
91
+ open = true
92
+ }
93
+
94
+ const onPick = newValue => {
95
+ dispatch("pick", newValue)
96
+ open = false
97
+ }
98
+
99
+ const extractProperty = (value, property) => {
100
+ if (value && typeof value === "object") {
101
+ return value[property]
102
+ }
103
+ return value
104
+ }
105
+ </script>
106
+
107
+ <div
108
+ class="spectrum-InputGroup"
109
+ class:is-invalid={!!error}
110
+ class:is-disabled={disabled}
111
+ >
112
+ <div
113
+ class="spectrum-Textfield spectrum-InputGroup-textfield"
114
+ class:is-invalid={!!error}
115
+ class:is-disabled={disabled}
116
+ class:is-focused={focus}
117
+ >
118
+ {#if error}
119
+ <svg
120
+ class="spectrum-Icon spectrum-Icon--sizeM spectrum-Textfield-validationIcon"
121
+ focusable="false"
122
+ aria-hidden="true"
123
+ >
124
+ <use xlink:href="#spectrum-icon-18-Alert" />
125
+ </svg>
126
+ {/if}
127
+
128
+ <input
129
+ {id}
130
+ on:click
131
+ on:blur
132
+ on:focus
133
+ on:input
134
+ on:keyup
135
+ on:blur={onBlur}
136
+ on:focus={onFocus}
137
+ on:input={onInput}
138
+ on:keyup={updateValueOnEnter}
139
+ value={inputValue || ""}
140
+ placeholder={placeholder || ""}
141
+ {disabled}
142
+ {readonly}
143
+ {inputType}
144
+ class="spectrum-Textfield-input spectrum-InputGroup-input"
145
+ />
146
+ </div>
147
+ <div style="width: 30%">
148
+ <button
149
+ {id}
150
+ class="spectrum-Picker spectrum-Picker--sizeM override-borders"
151
+ {disabled}
152
+ class:is-open={open}
153
+ aria-haspopup="listbox"
154
+ on:mousedown={onClick}
155
+ >
156
+ <span class="spectrum-Picker-label">
157
+ <div>
158
+ {fieldText}
159
+ </div></span
160
+ >
161
+ <svg
162
+ class="spectrum-Icon spectrum-UIIcon-ChevronDown100 spectrum-Picker-menuIcon"
163
+ focusable="false"
164
+ aria-hidden="true"
165
+ >
166
+ <use xlink:href="#spectrum-css-icon-Chevron100" />
167
+ </svg>
168
+ </button>
169
+ {#if open}
170
+ <div
171
+ use:clickOutside={() => (open = false)}
172
+ transition:fly|local={{ y: -20, duration: 200 }}
173
+ class="spectrum-Popover spectrum-Popover--bottom spectrum-Picker-popover is-open"
174
+ >
175
+ <ul class="spectrum-Menu" role="listbox">
176
+ {#each options as option, idx}
177
+ <li
178
+ class="spectrum-Menu-item"
179
+ class:is-selected={isOptionSelected(getOptionValue(option, idx))}
180
+ role="option"
181
+ aria-selected="true"
182
+ tabindex="0"
183
+ on:click={() => onPick(getOptionValue(option, idx))}
184
+ >
185
+ <span class="spectrum-Menu-itemLabel">
186
+ {getOptionLabel(option, idx)}
187
+ </span>
188
+ <svg
189
+ class="spectrum-Icon spectrum-UIIcon-Checkmark100 spectrum-Menu-checkmark spectrum-Menu-itemIcon"
190
+ focusable="false"
191
+ aria-hidden="true"
192
+ >
193
+ <use xlink:href="#spectrum-css-icon-Checkmark100" />
194
+ </svg>
195
+ </li>
196
+ {/each}
197
+ </ul>
198
+ </div>
199
+ {/if}
200
+ </div>
201
+ </div>
202
+
203
+ <style>
204
+ .spectrum-InputGroup {
205
+ min-width: 0;
206
+ width: 100%;
207
+ }
208
+
209
+ .spectrum-InputGroup-input {
210
+ border-right-width: 1px;
211
+ }
212
+ .spectrum-Textfield {
213
+ width: 100%;
214
+ }
215
+ .spectrum-Textfield-input {
216
+ width: 0;
217
+ }
218
+
219
+ .override-borders {
220
+ border-top-left-radius: 0px;
221
+ border-bottom-left-radius: 0px;
222
+ }
223
+ .spectrum-Popover {
224
+ max-height: 240px;
225
+ z-index: 999;
226
+ top: 100%;
227
+ }
228
+ </style>