@budibase/bbui 1.0.56 → 1.0.59

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.56",
4
+ "version": "1.0.59",
5
5
  "license": "MPL-2.0",
6
6
  "svelte": "src/index.js",
7
7
  "module": "dist/bbui.es.js",
@@ -83,5 +83,5 @@
83
83
  "svelte-flatpickr": "^3.2.3",
84
84
  "svelte-portal": "^1.0.0"
85
85
  },
86
- "gitHead": "dc9d8b926198fc581281654cbb756fa58b17e3f8"
86
+ "gitHead": "ac163154169db8c04a6ed148091cf41d1135d668"
87
87
  }
@@ -1,5 +1,6 @@
1
1
  <script>
2
2
  import "@spectrum-css/button/dist/index-vars.css"
3
+ import Tooltip from "../Tooltip/Tooltip.svelte"
3
4
 
4
5
  export let disabled = false
5
6
  export let size = "M"
@@ -11,36 +12,67 @@
11
12
  export let quiet = false
12
13
  export let icon = undefined
13
14
  export let active = false
15
+ export let tooltip = undefined
16
+
17
+ let showTooltip = false
14
18
  </script>
15
19
 
16
- <button
17
- class:spectrum-Button--cta={cta}
18
- class:spectrum-Button--primary={primary}
19
- class:spectrum-Button--secondary={secondary}
20
- class:spectrum-Button--warning={warning}
21
- class:spectrum-Button--overBackground={overBackground}
22
- class:spectrum-Button--quiet={quiet}
23
- class:active
24
- class="spectrum-Button spectrum-Button--size{size.toUpperCase()}"
25
- {disabled}
26
- on:click|preventDefault
27
- >
28
- {#if icon}
29
- <svg
30
- class="spectrum-Icon spectrum-Icon--size{size.toUpperCase()}"
31
- focusable="false"
32
- aria-hidden="true"
33
- aria-label={icon}
34
- >
35
- <use xlink:href="#spectrum-icon-18-{icon}" />
36
- </svg>
37
- {/if}
38
- {#if $$slots}
39
- <span class="spectrum-Button-label"><slot /></span>
20
+ <div class:container={!!tooltip}>
21
+ <button
22
+ class:spectrum-Button--cta={cta}
23
+ class:spectrum-Button--primary={primary}
24
+ class:spectrum-Button--secondary={secondary}
25
+ class:spectrum-Button--warning={warning}
26
+ class:spectrum-Button--overBackground={overBackground}
27
+ class:spectrum-Button--quiet={quiet}
28
+ class:active
29
+ class="spectrum-Button spectrum-Button--size{size.toUpperCase()}"
30
+ {disabled}
31
+ on:click|preventDefault
32
+ on:mouseover={() => (showTooltip = true)}
33
+ on:mouseleave={() => (showTooltip = false)}
34
+ >
35
+ {#if icon}
36
+ <svg
37
+ class="spectrum-Icon spectrum-Icon--size{size.toUpperCase()}"
38
+ focusable="false"
39
+ aria-hidden="true"
40
+ aria-label={icon}
41
+ >
42
+ <use xlink:href="#spectrum-icon-18-{icon}" />
43
+ </svg>
44
+ {/if}
45
+ {#if $$slots}
46
+ <span class="spectrum-Button-label"><slot /></span>
47
+ {/if}
48
+ {#if !disabled && tooltip}
49
+ <div class="tooltip-icon">
50
+ <svg
51
+ class="spectrum-Icon spectrum-Icon--size{size.toUpperCase()}"
52
+ focusable="false"
53
+ aria-hidden="true"
54
+ aria-label="Info"
55
+ >
56
+ <use xlink:href="#spectrum-icon-18-InfoOutline" />
57
+ </svg>
58
+ </div>
59
+ {/if}
60
+ </button>
61
+ {#if showTooltip && tooltip}
62
+ <div class="position">
63
+ <div class="tooltip">
64
+ <Tooltip textWrapping={true} direction={"bottom"} text={tooltip} />
65
+ </div>
66
+ </div>
40
67
  {/if}
41
- </button>
68
+ </div>
42
69
 
43
70
  <style>
71
+ .container {
72
+ display: flex;
73
+ align-items: center;
74
+ flex-direction: column;
75
+ }
44
76
  .spectrum-Button-label {
45
77
  white-space: nowrap;
46
78
  overflow: hidden;
@@ -49,4 +81,23 @@
49
81
  .active {
50
82
  color: var(--spectrum-global-color-blue-600) !important;
51
83
  }
84
+ .tooltip {
85
+ position: absolute;
86
+ display: flex;
87
+ justify-content: center;
88
+ z-index: 100;
89
+ width: 160px;
90
+ text-align: center;
91
+ transform: translateX(-50%);
92
+ top: -5px;
93
+ }
94
+ .position {
95
+ position: relative;
96
+ width: 0;
97
+ height: 0;
98
+ }
99
+ .tooltip-icon {
100
+ padding-left: var(--spacing-m);
101
+ line-height: 0;
102
+ }
52
103
  </style>
@@ -5,7 +5,7 @@
5
5
  import { fly } from "svelte/transition"
6
6
  import Icon from "../Icon/Icon.svelte"
7
7
  import Input from "../Form/Input.svelte"
8
- import { capitalise } from "../utils/helpers"
8
+ import { capitalise } from "../helpers"
9
9
 
10
10
  export let value
11
11
  export let size = "M"
@@ -5,7 +5,7 @@
5
5
  import "@spectrum-css/textfield/dist/index-vars.css"
6
6
  import "@spectrum-css/picker/dist/index-vars.css"
7
7
  import { createEventDispatcher } from "svelte"
8
- import { generateID } from "../../utils/helpers"
8
+ import { uuid } from "../../helpers"
9
9
 
10
10
  export let id = null
11
11
  export let disabled = false
@@ -14,16 +14,20 @@
14
14
  export let value = null
15
15
  export let placeholder = null
16
16
  export let appendTo = undefined
17
+ export let timeOnly = false
17
18
 
18
19
  const dispatch = createEventDispatcher()
19
- const flatpickrId = `${generateID()}-wrapper`
20
+ const flatpickrId = `${uuid()}-wrapper`
20
21
  let open = false
21
- let flatpickr
22
+ let flatpickr, flatpickrOptions, isTimeOnly
23
+
24
+ $: isTimeOnly = !timeOnly && value ? !isNaN(new Date(`0-${value}`)) : timeOnly
22
25
  $: flatpickrOptions = {
23
26
  element: `#${flatpickrId}`,
24
- enableTime: enableTime || false,
27
+ enableTime: isTimeOnly || enableTime || false,
28
+ noCalendar: isTimeOnly || false,
25
29
  altInput: true,
26
- altFormat: enableTime ? "F j Y, H:i" : "F j, Y",
30
+ altFormat: isTimeOnly ? "H:i" : enableTime ? "F j Y, H:i" : "F j, Y",
27
31
  wrap: true,
28
32
  appendTo,
29
33
  disableMobile: "true",
@@ -35,6 +39,11 @@
35
39
  if (newValue) {
36
40
  newValue = newValue.toISOString()
37
41
  }
42
+ // if time only set date component to today
43
+ if (timeOnly) {
44
+ const todayDate = new Date().toISOString().split("T")[0]
45
+ newValue = `${todayDate}T${newValue.split("T")[1]}`
46
+ }
38
47
  dispatch("change", newValue)
39
48
  }
40
49
 
@@ -67,7 +76,11 @@
67
76
  return null
68
77
  }
69
78
  let date
70
- if (val instanceof Date) {
79
+ let time = new Date(`0-${val}`)
80
+ // it is a string like 00:00:00, just time
81
+ if (timeOnly || (typeof val === "string" && !isNaN(time))) {
82
+ date = time
83
+ } else if (val instanceof Date) {
71
84
  // Use real date obj if already parsed
72
85
  date = val
73
86
  } else if (isNaN(val)) {
@@ -77,7 +90,7 @@
77
90
  // Treat as numerical timestamp
78
91
  date = new Date(parseInt(val))
79
92
  }
80
- const time = date.getTime()
93
+ time = date.getTime()
81
94
  if (isNaN(time)) {
82
95
  return null
83
96
  }
@@ -88,69 +101,71 @@
88
101
  }
89
102
  </script>
90
103
 
91
- <Flatpickr
92
- bind:flatpickr
93
- value={parseDate(value)}
94
- on:open={onOpen}
95
- on:close={onClose}
96
- options={flatpickrOptions}
97
- on:change={handleChange}
98
- element={`#${flatpickrId}`}
99
- >
100
- <div
101
- id={flatpickrId}
102
- class:is-disabled={disabled}
103
- class:is-invalid={!!error}
104
- class="flatpickr spectrum-InputGroup spectrum-Datepicker"
105
- class:is-focused={open}
106
- aria-readonly="false"
107
- aria-required="false"
108
- aria-haspopup="true"
104
+ {#key isTimeOnly}
105
+ <Flatpickr
106
+ bind:flatpickr
107
+ value={parseDate(value)}
108
+ on:open={onOpen}
109
+ on:close={onClose}
110
+ options={flatpickrOptions}
111
+ on:change={handleChange}
112
+ element={`#${flatpickrId}`}
109
113
  >
110
114
  <div
111
- on:click={flatpickr?.open}
112
- class="spectrum-Textfield spectrum-InputGroup-textfield"
115
+ id={flatpickrId}
113
116
  class:is-disabled={disabled}
114
117
  class:is-invalid={!!error}
118
+ class="flatpickr spectrum-InputGroup spectrum-Datepicker"
119
+ class:is-focused={open}
120
+ aria-readonly="false"
121
+ aria-required="false"
122
+ aria-haspopup="true"
115
123
  >
116
- {#if !!error}
124
+ <div
125
+ on:click={flatpickr?.open}
126
+ class="spectrum-Textfield spectrum-InputGroup-textfield"
127
+ class:is-disabled={disabled}
128
+ class:is-invalid={!!error}
129
+ >
130
+ {#if !!error}
131
+ <svg
132
+ class="spectrum-Icon spectrum-Icon--sizeM spectrum-Textfield-validationIcon"
133
+ focusable="false"
134
+ aria-hidden="true"
135
+ >
136
+ <use xlink:href="#spectrum-icon-18-Alert" />
137
+ </svg>
138
+ {/if}
139
+ <input
140
+ data-input
141
+ type="text"
142
+ {disabled}
143
+ class="spectrum-Textfield-input spectrum-InputGroup-input"
144
+ {placeholder}
145
+ {id}
146
+ {value}
147
+ />
148
+ </div>
149
+ <button
150
+ type="button"
151
+ class="spectrum-Picker spectrum-Picker--sizeM spectrum-InputGroup-button"
152
+ tabindex="-1"
153
+ {disabled}
154
+ class:is-invalid={!!error}
155
+ on:click={flatpickr?.open}
156
+ >
117
157
  <svg
118
- class="spectrum-Icon spectrum-Icon--sizeM spectrum-Textfield-validationIcon"
158
+ class="spectrum-Icon spectrum-Icon--sizeM"
119
159
  focusable="false"
120
160
  aria-hidden="true"
161
+ aria-label="Calendar"
121
162
  >
122
- <use xlink:href="#spectrum-icon-18-Alert" />
163
+ <use xlink:href="#spectrum-icon-18-Calendar" />
123
164
  </svg>
124
- {/if}
125
- <input
126
- data-input
127
- type="text"
128
- {disabled}
129
- class="spectrum-Textfield-input spectrum-InputGroup-input"
130
- {placeholder}
131
- {id}
132
- {value}
133
- />
165
+ </button>
134
166
  </div>
135
- <button
136
- type="button"
137
- class="spectrum-Picker spectrum-Picker--sizeM spectrum-InputGroup-button"
138
- tabindex="-1"
139
- {disabled}
140
- class:is-invalid={!!error}
141
- on:click={flatpickr?.open}
142
- >
143
- <svg
144
- class="spectrum-Icon spectrum-Icon--sizeM"
145
- focusable="false"
146
- aria-hidden="true"
147
- aria-label="Calendar"
148
- >
149
- <use xlink:href="#spectrum-icon-18-Calendar" />
150
- </svg>
151
- </button>
152
- </div>
153
- </Flatpickr>
167
+ </Flatpickr>
168
+ {/key}
154
169
  {#if open}
155
170
  <div class="overlay" on:mousedown|self={flatpickr?.close} />
156
171
  {/if}
@@ -3,7 +3,7 @@
3
3
  import "@spectrum-css/typography/dist/index-vars.css"
4
4
  import "@spectrum-css/illustratedmessage/dist/index-vars.css"
5
5
  import { createEventDispatcher } from "svelte"
6
- import { generateID } from "../../utils/helpers"
6
+ import { uuid } from "../../helpers"
7
7
  import Icon from "../../Icon/Icon.svelte"
8
8
  import Link from "../../Link/Link.svelte"
9
9
  import Tag from "../../Tags/Tag.svelte"
@@ -37,7 +37,7 @@
37
37
  "jfif",
38
38
  ]
39
39
 
40
- const fieldId = id || generateID()
40
+ const fieldId = id || uuid()
41
41
  let selectedImageIdx = 0
42
42
  let fileDragged = false
43
43
  let selectedUrl
@@ -9,6 +9,7 @@
9
9
  export let disabled = false
10
10
  export let error = null
11
11
  export let enableTime = true
12
+ export let timeOnly = false
12
13
  export let placeholder = null
13
14
  export let appendTo = undefined
14
15
 
@@ -27,6 +28,7 @@
27
28
  {value}
28
29
  {placeholder}
29
30
  {enableTime}
31
+ {timeOnly}
30
32
  {appendTo}
31
33
  on:change={onChange}
32
34
  />
@@ -2,9 +2,18 @@
2
2
  import dayjs from "dayjs"
3
3
 
4
4
  export let value
5
+
6
+ // adding the 0- will turn a string like 00:00:00 into a valid ISO
7
+ // date, but will make actual ISO dates invalid
8
+ $: time = new Date(`0-${value}`)
9
+ $: isTime = !isNaN(time)
5
10
  </script>
6
11
 
7
- <div>{dayjs(value).format("MMMM D YYYY, HH:mm")}</div>
12
+ <div>
13
+ {dayjs(isTime ? time : value).format(
14
+ isTime ? "HH:mm:ss" : "MMMM D YYYY, HH:mm"
15
+ )}
16
+ </div>
8
17
 
9
18
  <style>
10
19
  div {
@@ -4,7 +4,7 @@
4
4
  import CellRenderer from "./CellRenderer.svelte"
5
5
  import SelectEditRenderer from "./SelectEditRenderer.svelte"
6
6
  import { cloneDeep } from "lodash"
7
- import { deepGet } from "../utils/helpers"
7
+ import { deepGet } from "../helpers"
8
8
 
9
9
  /**
10
10
  * The expected schema is our normal couch schemas for our tables.
@@ -17,6 +17,7 @@
17
17
  class:icon-small={size === "M" || size === "S"}
18
18
  on:mouseover={() => (showTooltip = true)}
19
19
  on:mouseleave={() => (showTooltip = false)}
20
+ on:focus
20
21
  >
21
22
  <Icon name="InfoOutline" size="S" disabled={true} />
22
23
  </div>
@@ -47,7 +48,7 @@
47
48
  display: flex;
48
49
  justify-content: center;
49
50
  top: 15px;
50
- z-index: 1;
51
+ z-index: 100;
51
52
  width: 160px;
52
53
  }
53
54
  .icon {
@@ -1,11 +1,45 @@
1
- export const generateID = () => {
2
- const rand = Math.random().toString(32).substring(2)
1
+ /**
2
+ * Generates a DOM safe UUID.
3
+ * Starting with a letter is important to make it DOM safe.
4
+ * @return {string} a random DOM safe UUID
5
+ */
6
+ export function uuid() {
7
+ return "cxxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx".replace(/[xy]/g, c => {
8
+ const r = (Math.random() * 16) | 0
9
+ const v = c === "x" ? r : (r & 0x3) | 0x8
10
+ return v.toString(16)
11
+ })
12
+ }
3
13
 
4
- // Starts with a letter so that its a valid DOM ID
5
- return `A${rand}`
14
+ /**
15
+ * Capitalises a string
16
+ * @param string the string to capitalise
17
+ * @return {string} the capitalised string
18
+ */
19
+ export const capitalise = string => {
20
+ if (!string) {
21
+ return string
22
+ }
23
+ return string.substring(0, 1).toUpperCase() + string.substring(1)
6
24
  }
7
25
 
8
- export const capitalise = s => s.substring(0, 1).toUpperCase() + s.substring(1)
26
+ /**
27
+ * Computes a short hash of a string
28
+ * @param string the string to compute a hash of
29
+ * @return {string} the hash string
30
+ */
31
+ export const hashString = string => {
32
+ if (!string) {
33
+ return "0"
34
+ }
35
+ let hash = 0
36
+ for (let i = 0; i < string.length; i++) {
37
+ let char = string.charCodeAt(i)
38
+ hash = (hash << 5) - hash + char
39
+ hash = hash & hash // Convert to 32bit integer
40
+ }
41
+ return hash.toString()
42
+ }
9
43
 
10
44
  /**
11
45
  * Gets a key within an object. The key supports dot syntax for retrieving deep
package/src/index.js CHANGED
@@ -85,5 +85,5 @@ export { default as clickOutside } from "./Actions/click_outside"
85
85
  // Stores
86
86
  export { notifications, createNotificationStore } from "./Stores/notifications"
87
87
 
88
- // Utils
89
- export * from "./utils/helpers"
88
+ // Helpers
89
+ export * as Helpers from "./helpers"