@budibase/bbui 2.1.45 → 2.1.46-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.1.45",
4
+ "version": "2.1.46-alpha.0",
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": "^2.1.45",
41
+ "@budibase/string-templates": "2.1.46-alpha.0",
42
42
  "@spectrum-css/actionbutton": "^1.0.1",
43
43
  "@spectrum-css/actiongroup": "^1.0.1",
44
44
  "@spectrum-css/avatar": "^3.0.2",
@@ -67,19 +67,19 @@
67
67
  "@spectrum-css/search": "^3.0.2",
68
68
  "@spectrum-css/sidenav": "^3.0.2",
69
69
  "@spectrum-css/slider": "3.0.1",
70
- "@spectrum-css/statuslight": "^3.0.2",
71
- "@spectrum-css/stepper": "^3.0.3",
72
- "@spectrum-css/switch": "^1.0.2",
73
- "@spectrum-css/table": "^3.0.1",
74
- "@spectrum-css/tabs": "^3.2.12",
75
- "@spectrum-css/tags": "^3.0.2",
76
- "@spectrum-css/textfield": "^3.0.1",
77
- "@spectrum-css/toast": "^3.0.1",
78
- "@spectrum-css/tooltip": "^3.0.3",
79
- "@spectrum-css/treeview": "^3.0.2",
80
- "@spectrum-css/typography": "^3.0.1",
81
- "@spectrum-css/underlay": "^2.0.9",
82
- "@spectrum-css/vars": "^3.0.1",
70
+ "@spectrum-css/statuslight": "3.0.2",
71
+ "@spectrum-css/stepper": "3.0.3",
72
+ "@spectrum-css/switch": "1.0.2",
73
+ "@spectrum-css/table": "3.0.1",
74
+ "@spectrum-css/tabs": "3.2.12",
75
+ "@spectrum-css/tags": "3.0.2",
76
+ "@spectrum-css/textfield": "3.0.1",
77
+ "@spectrum-css/toast": "3.0.1",
78
+ "@spectrum-css/tooltip": "3.0.3",
79
+ "@spectrum-css/treeview": "3.0.2",
80
+ "@spectrum-css/typography": "3.0.1",
81
+ "@spectrum-css/underlay": "2.0.9",
82
+ "@spectrum-css/vars": "3.0.1",
83
83
  "dayjs": "^1.10.4",
84
84
  "easymde": "^2.16.1",
85
85
  "svelte-flatpickr": "^3.2.3",
@@ -88,5 +88,5 @@
88
88
  "resolutions": {
89
89
  "loader-utils": "1.4.1"
90
90
  },
91
- "gitHead": "4570e0cdf439ea7d89ba3b00875558f0a4b12bba"
91
+ "gitHead": "1c1f758ab9bbd9b841b1e759a872523aa31f53b4"
92
92
  }
@@ -1,18 +1,53 @@
1
- export default function clickOutside(element, callbackFunction) {
2
- function onClick(event) {
3
- if (!element.contains(event.target)) {
4
- callbackFunction(event)
1
+ const ignoredClasses = [".flatpickr-calendar", ".modal-container"]
2
+ let clickHandlers = []
3
+
4
+ /**
5
+ * Handle a body click event
6
+ */
7
+ const handleClick = event => {
8
+ // Ignore click if needed
9
+ for (let className of ignoredClasses) {
10
+ if (event.target.closest(className)) {
11
+ return
12
+ }
13
+ }
14
+
15
+ // Process handlers
16
+ clickHandlers.forEach(handler => {
17
+ if (!handler.element.contains(event.target)) {
18
+ handler.callback?.(event)
5
19
  }
20
+ })
21
+ }
22
+ document.documentElement.addEventListener("click", handleClick, true)
23
+
24
+ /**
25
+ * Adds or updates a click handler
26
+ */
27
+ const updateHandler = (id, element, callback) => {
28
+ let existingHandler = clickHandlers.find(x => x.id === id)
29
+ if (!existingHandler) {
30
+ clickHandlers.push({ id, element, callback })
31
+ } else {
32
+ existingHandler.callback = callback
6
33
  }
34
+ }
7
35
 
8
- document.body.addEventListener("click", onClick, true)
36
+ /**
37
+ * Removes a click handler
38
+ */
39
+ const removeHandler = id => {
40
+ clickHandlers = clickHandlers.filter(x => x.id !== id)
41
+ }
9
42
 
43
+ /**
44
+ * Svelte action to apply a click outside handler for a certain element
45
+ */
46
+ export default (element, callback) => {
47
+ const id = Math.random()
48
+ updateHandler(id, element, callback)
10
49
  return {
11
- update(newCallbackFunction) {
12
- callbackFunction = newCallbackFunction
13
- },
14
- destroy() {
15
- document.body.removeEventListener("click", onClick, true)
16
- },
50
+ update: newCallback => updateHandler(id, element, newCallback),
51
+ destroy: () => removeHandler(id),
17
52
  }
18
53
  }
@@ -19,13 +19,19 @@
19
19
  </script>
20
20
 
21
21
  <div class="property-group-container">
22
- <div class="property-group-name" on:click={onHeaderClick}>
23
- <div class="name">{name}</div>
24
- {#if collapsible}
25
- <Icon size="S" name={show ? "Remove" : "Add"} />
26
- {/if}
27
- </div>
28
- <div class="property-panel" class:show={show || !collapsible}>
22
+ {#if name}
23
+ <div class="property-group-name" on:click={onHeaderClick}>
24
+ <div class="name">{name}</div>
25
+ {#if collapsible}
26
+ <Icon size="S" name={show ? "Remove" : "Add"} />
27
+ {/if}
28
+ </div>
29
+ {/if}
30
+ <div
31
+ class="property-panel"
32
+ class:show={show || !collapsible}
33
+ class:no-title={!name}
34
+ >
29
35
  <slot />
30
36
  </div>
31
37
  </div>
@@ -72,6 +78,9 @@
72
78
  padding: var(--spacing-s) var(--spacing-xl) var(--spacing-xl)
73
79
  var(--spacing-xl);
74
80
  }
81
+ .property-panel.no-title {
82
+ padding: var(--spacing-xl);
83
+ }
75
84
 
76
85
  .show {
77
86
  display: flex;
@@ -23,6 +23,15 @@
23
23
  let open = false
24
24
  let flatpickr, flatpickrOptions
25
25
 
26
+ // Another classic flatpickr issue. Errors were randomly being thrown due to
27
+ // flatpickr internal code. Making sure that "destroy" is a valid function
28
+ // fixes it. The sooner we remove flatpickr the better.
29
+ $: {
30
+ if (flatpickr && !flatpickr.destroy) {
31
+ flatpickr.destroy = () => {}
32
+ }
33
+ }
34
+
26
35
  const resolveTimeStamp = timestamp => {
27
36
  let maskedDate = new Date(`0-${timestamp}`)
28
37
 
@@ -252,6 +261,7 @@
252
261
  width: 100vw;
253
262
  height: 100vh;
254
263
  z-index: 999;
264
+ max-height: 100%;
255
265
  }
256
266
  :global(.flatpickr-calendar) {
257
267
  font-family: "Source Sans Pro", sans-serif;
@@ -205,7 +205,10 @@
205
205
  width: 100%;
206
206
  }
207
207
  .spectrum-Popover.auto-width :global(.spectrum-Menu-itemLabel) {
208
+ max-width: 400px;
208
209
  white-space: nowrap;
210
+ overflow: hidden;
211
+ text-overflow: ellipsis;
209
212
  }
210
213
  .spectrum-Picker {
211
214
  width: 100%;
@@ -64,7 +64,7 @@
64
64
  transition: color var(--spectrum-global-animation-duration-100, 130ms);
65
65
  }
66
66
  svg.hoverable:hover {
67
- color: var(--spectrum-alias-icon-color-selected-hover);
67
+ color: var(--spectrum-alias-icon-color-selected-hover) !important;
68
68
  cursor: pointer;
69
69
  }
70
70
 
@@ -28,9 +28,9 @@
28
28
  let loading = false
29
29
  $: confirmDisabled = disabled || loading
30
30
 
31
- async function secondary() {
31
+ async function secondary(e) {
32
32
  loading = true
33
- if (!secondaryAction || (await secondaryAction()) !== false) {
33
+ if (!secondaryAction || (await secondaryAction(e)) !== false) {
34
34
  hide()
35
35
  }
36
36
  loading = false
@@ -25,7 +25,7 @@
25
25
  </svg>
26
26
  {/if}
27
27
  <div class="spectrum-Toast-body" class:actionBody={!!action}>
28
- <div class="spectrum-Toast-content">{message || ""}</div>
28
+ <div class="wrap spectrum-Toast-content">{message || ""}</div>
29
29
  {#if action}
30
30
  <ActionButton quiet emphasized on:click={action}>
31
31
  <div style="color: white; font-weight: 600;">{actionMessage}</div>
@@ -53,6 +53,10 @@
53
53
  </div>
54
54
 
55
55
  <style>
56
+ .wrap {
57
+ overflow-wrap: anywhere;
58
+ }
59
+
56
60
  .spectrum-Toast {
57
61
  pointer-events: all;
58
62
  }
@@ -0,0 +1,56 @@
1
+ <div class="skeleton">
2
+ <div class="children">
3
+ <slot />
4
+ </div>
5
+ </div>
6
+
7
+ <style>
8
+ .skeleton {
9
+ height: 100%;
10
+ width: 100%;
11
+ opacity: 0;
12
+ background-color: var(--spectrum-global-color-gray-200) !important;
13
+ border-radius: 7px;
14
+ overflow: hidden;
15
+ position: relative;
16
+ animation: fadeIn 130ms ease 0s 1 normal forwards;
17
+ }
18
+
19
+ .children {
20
+ pointer-events: none;
21
+ opacity: 0;
22
+ }
23
+
24
+ .skeleton::after {
25
+ position: absolute;
26
+ top: 0;
27
+ right: 0;
28
+ bottom: 0;
29
+ left: 0;
30
+ transform: translateX(-100%);
31
+ background-image: linear-gradient(
32
+ 90deg,
33
+ rgba(255, 255, 255, 0) 0,
34
+ rgba(255, 255, 255, 0.15) 20%,
35
+ rgba(255, 255, 255, 0.3) 60%,
36
+ rgba(255, 255, 255, 0)
37
+ );
38
+ animation: shimmer 2s infinite;
39
+ content: "";
40
+ }
41
+
42
+ @keyframes fadeIn {
43
+ 0% {
44
+ opacity: 0;
45
+ }
46
+ 100% {
47
+ opacity: 0.75;
48
+ }
49
+ }
50
+
51
+ @keyframes shimmer {
52
+ 100% {
53
+ transform: translateX(100%);
54
+ }
55
+ }
56
+ </style>
@@ -71,7 +71,8 @@
71
71
  visibleRowCount,
72
72
  rowCount,
73
73
  totalRowCount,
74
- rowHeight
74
+ rowHeight,
75
+ loading
75
76
  )
76
77
  $: sortedRows = sortRows(rows, sortColumn, sortOrder)
77
78
  $: gridStyle = getGridStyle(fields, schema, showEditColumn)
@@ -120,8 +121,12 @@
120
121
  visibleRowCount,
121
122
  rowCount,
122
123
  totalRowCount,
123
- rowHeight
124
+ rowHeight,
125
+ loading
124
126
  ) => {
127
+ if (loading) {
128
+ return `height: ${headerHeight + visibleRowCount * rowHeight}px;`
129
+ }
125
130
  if (!rowCount || !visibleRowCount || totalRowCount <= rowCount) {
126
131
  return ""
127
132
  }
@@ -270,155 +275,159 @@
270
275
  }
271
276
  </script>
272
277
 
273
- <div
274
- class="wrapper"
275
- class:wrapper--quiet={quiet}
276
- class:wrapper--compact={compact}
277
- bind:offsetHeight={height}
278
- style={`--row-height: ${rowHeight}px; --header-height: ${headerHeight}px;`}
279
- >
280
- {#if !loaded}
281
- <div class="loading" style={heightStyle}>
282
- <ProgressCircle />
283
- </div>
284
- {:else}
285
- <div class="spectrum-Table" style={`${heightStyle}${gridStyle}`}>
286
- {#if fields.length}
287
- <div class="spectrum-Table-head">
288
- {#if showEditColumn}
289
- <div
290
- class:noBorderHeader={!showHeaderBorder}
291
- class="spectrum-Table-headCell spectrum-Table-headCell--divider spectrum-Table-headCell--edit"
292
- >
293
- {#if allowSelectRows}
294
- <Checkbox
295
- bind:value={checkboxStatus}
296
- on:change={toggleSelectAll}
297
- />
298
- {:else}
299
- Edit
300
- {/if}
301
- </div>
302
- {/if}
303
- {#each fields as field}
304
- <div
305
- class="spectrum-Table-headCell"
306
- class:noBorderHeader={!showHeaderBorder}
307
- class:spectrum-Table-headCell--alignCenter={schema[field]
308
- .align === "Center"}
309
- class:spectrum-Table-headCell--alignRight={schema[field].align ===
310
- "Right"}
311
- class:is-sortable={schema[field].sortable !== false}
312
- class:is-sorted-desc={sortColumn === field &&
313
- sortOrder === "Descending"}
314
- class:is-sorted-asc={sortColumn === field &&
315
- sortOrder === "Ascending"}
316
- on:click={() => sortBy(schema[field])}
317
- >
318
- <div class="title">{getDisplayName(schema[field])}</div>
319
- {#if schema[field]?.autocolumn}
320
- <svg
321
- class="spectrum-Icon spectrum-Table-autoIcon"
322
- focusable="false"
323
- >
324
- <use xlink:href="#spectrum-icon-18-MagicWand" />
325
- </svg>
326
- {/if}
327
- {#if sortColumn === field}
328
- <svg
329
- class="spectrum-Icon spectrum-UIIcon-ArrowDown100 spectrum-Table-sortedIcon"
330
- focusable="false"
331
- aria-hidden="true"
332
- >
333
- <use xlink:href="#spectrum-css-icon-Arrow100" />
334
- </svg>
335
- {/if}
336
- {#if allowEditColumns && schema[field]?.editable !== false}
337
- <svg
338
- class="spectrum-Icon spectrum-Table-editIcon"
339
- focusable="false"
340
- on:click={e => editColumn(e, field)}
341
- >
342
- <use xlink:href="#spectrum-icon-18-Edit" />
343
- </svg>
344
- {/if}
345
- </div>
346
- {/each}
347
- </div>
348
- {/if}
349
- {#if sortedRows?.length}
350
- {#each sortedRows as row, idx}
351
- <div class="spectrum-Table-row">
278
+ {#key fields?.length}
279
+ <div
280
+ class="wrapper"
281
+ class:wrapper--quiet={quiet}
282
+ class:wrapper--compact={compact}
283
+ bind:offsetHeight={height}
284
+ style={`--row-height: ${rowHeight}px; --header-height: ${headerHeight}px;`}
285
+ >
286
+ {#if loading}
287
+ <div class="loading" style={heightStyle}>
288
+ <slot name="loadingIndicator">
289
+ <ProgressCircle />
290
+ </slot>
291
+ </div>
292
+ {:else}
293
+ <div class="spectrum-Table" style={`${heightStyle}${gridStyle}`}>
294
+ {#if fields.length}
295
+ <div class="spectrum-Table-head">
352
296
  {#if showEditColumn}
353
297
  <div
354
- class:noBorderCheckbox={!showHeaderBorder}
355
- class="spectrum-Table-cell spectrum-Table-cell--divider spectrum-Table-cell--edit"
356
- on:click={e => {
357
- toggleSelectRow(row)
358
- e.stopPropagation()
359
- }}
298
+ class:noBorderHeader={!showHeaderBorder}
299
+ class="spectrum-Table-headCell spectrum-Table-headCell--divider spectrum-Table-headCell--edit"
360
300
  >
361
- <SelectEditRenderer
362
- data={row}
363
- selected={selectedRows.findIndex(
364
- selectedRow => selectedRow._id === row._id
365
- ) !== -1}
366
- onEdit={e => editRow(e, row)}
367
- {allowSelectRows}
368
- {allowEditRows}
369
- />
301
+ {#if allowSelectRows}
302
+ <Checkbox
303
+ bind:value={checkboxStatus}
304
+ on:change={toggleSelectAll}
305
+ />
306
+ {:else}
307
+ Edit
308
+ {/if}
370
309
  </div>
371
310
  {/if}
372
311
  {#each fields as field}
373
312
  <div
374
- class="spectrum-Table-cell"
375
- class:spectrum-Table-cell--divider={!!schema[field].divider}
376
- style={cellStyles[field]}
377
- on:click={() => {
378
- if (!schema[field]?.preventSelectRow) {
379
- dispatch("click", row)
380
- toggleSelectRow(row)
381
- }
382
- }}
313
+ class="spectrum-Table-headCell"
314
+ class:noBorderHeader={!showHeaderBorder}
315
+ class:spectrum-Table-headCell--alignCenter={schema[field]
316
+ .align === "Center"}
317
+ class:spectrum-Table-headCell--alignRight={schema[field]
318
+ .align === "Right"}
319
+ class:is-sortable={schema[field].sortable !== false}
320
+ class:is-sorted-desc={sortColumn === field &&
321
+ sortOrder === "Descending"}
322
+ class:is-sorted-asc={sortColumn === field &&
323
+ sortOrder === "Ascending"}
324
+ on:click={() => sortBy(schema[field])}
383
325
  >
384
- <CellRenderer
385
- {customRenderers}
386
- {row}
387
- schema={schema[field]}
388
- value={deepGet(row, field)}
389
- on:clickrelationship
390
- on:buttonclick
391
- >
392
- <slot />
393
- </CellRenderer>
326
+ <div class="title">{getDisplayName(schema[field])}</div>
327
+ {#if schema[field]?.autocolumn}
328
+ <svg
329
+ class="spectrum-Icon spectrum-Table-autoIcon"
330
+ focusable="false"
331
+ >
332
+ <use xlink:href="#spectrum-icon-18-MagicWand" />
333
+ </svg>
334
+ {/if}
335
+ {#if sortColumn === field}
336
+ <svg
337
+ class="spectrum-Icon spectrum-UIIcon-ArrowDown100 spectrum-Table-sortedIcon"
338
+ focusable="false"
339
+ aria-hidden="true"
340
+ >
341
+ <use xlink:href="#spectrum-css-icon-Arrow100" />
342
+ </svg>
343
+ {/if}
344
+ {#if allowEditColumns && schema[field]?.editable !== false}
345
+ <svg
346
+ class="spectrum-Icon spectrum-Table-editIcon"
347
+ focusable="false"
348
+ on:click={e => editColumn(e, field)}
349
+ >
350
+ <use xlink:href="#spectrum-icon-18-Edit" />
351
+ </svg>
352
+ {/if}
394
353
  </div>
395
354
  {/each}
396
355
  </div>
397
- {/each}
398
- {:else}
399
- <div
400
- class="placeholder"
401
- class:placeholder--custom={customPlaceholder}
402
- class:placeholder--no-fields={!fields?.length}
403
- >
404
- {#if customPlaceholder}
405
- <slot name="placeholder" />
406
- {:else}
407
- <div class="placeholder-content">
408
- <svg
409
- class="spectrum-Icon spectrum-Icon--sizeXXL"
410
- focusable="false"
411
- >
412
- <use xlink:href="#spectrum-icon-18-Table" />
413
- </svg>
414
- <div>{placeholderText}</div>
356
+ {/if}
357
+ {#if sortedRows?.length}
358
+ {#each sortedRows as row, idx}
359
+ <div class="spectrum-Table-row">
360
+ {#if showEditColumn}
361
+ <div
362
+ class:noBorderCheckbox={!showHeaderBorder}
363
+ class="spectrum-Table-cell spectrum-Table-cell--divider spectrum-Table-cell--edit"
364
+ on:click={e => {
365
+ toggleSelectRow(row)
366
+ e.stopPropagation()
367
+ }}
368
+ >
369
+ <SelectEditRenderer
370
+ data={row}
371
+ selected={selectedRows.findIndex(
372
+ selectedRow => selectedRow._id === row._id
373
+ ) !== -1}
374
+ onEdit={e => editRow(e, row)}
375
+ {allowSelectRows}
376
+ {allowEditRows}
377
+ />
378
+ </div>
379
+ {/if}
380
+ {#each fields as field}
381
+ <div
382
+ class="spectrum-Table-cell"
383
+ class:spectrum-Table-cell--divider={!!schema[field].divider}
384
+ style={cellStyles[field]}
385
+ on:click={() => {
386
+ if (!schema[field]?.preventSelectRow) {
387
+ dispatch("click", row)
388
+ toggleSelectRow(row)
389
+ }
390
+ }}
391
+ >
392
+ <CellRenderer
393
+ {customRenderers}
394
+ {row}
395
+ schema={schema[field]}
396
+ value={deepGet(row, field)}
397
+ on:clickrelationship
398
+ on:buttonclick
399
+ >
400
+ <slot />
401
+ </CellRenderer>
402
+ </div>
403
+ {/each}
415
404
  </div>
416
- {/if}
417
- </div>
418
- {/if}
419
- </div>
420
- {/if}
421
- </div>
405
+ {/each}
406
+ {:else}
407
+ <div
408
+ class="placeholder"
409
+ class:placeholder--custom={customPlaceholder}
410
+ class:placeholder--no-fields={!fields?.length}
411
+ >
412
+ {#if customPlaceholder}
413
+ <slot name="placeholder" />
414
+ {:else}
415
+ <div class="placeholder-content">
416
+ <svg
417
+ class="spectrum-Icon spectrum-Icon--sizeXXL"
418
+ focusable="false"
419
+ >
420
+ <use xlink:href="#spectrum-icon-18-Table" />
421
+ </svg>
422
+ <div>{placeholderText}</div>
423
+ </div>
424
+ {/if}
425
+ </div>
426
+ {/if}
427
+ </div>
428
+ {/if}
429
+ </div>
430
+ {/key}
422
431
 
423
432
  <style>
424
433
  /* Wrapper */
@@ -438,9 +447,10 @@
438
447
 
439
448
  /* Loading */
440
449
  .loading {
441
- display: grid;
442
- place-items: center;
450
+ display: flex;
451
+ align-items: center;
443
452
  min-height: 100px;
453
+ justify-content: center;
444
454
  }
445
455
 
446
456
  /* Table */
package/src/index.js CHANGED
@@ -4,6 +4,7 @@ import "./bbui.css"
4
4
  import "@spectrum-css/icon/dist/index-vars.css"
5
5
 
6
6
  // Components
7
+ export { default as Skeleton } from "./Skeleton/Skeleton.svelte"
7
8
  export { default as Input } from "./Form/Input.svelte"
8
9
  export { default as Stepper } from "./Form/Stepper.svelte"
9
10
  export { default as TextArea } from "./Form/TextArea.svelte"