@budibase/bbui 3.5.3 → 3.7.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": "3.5.3",
4
+ "version": "3.7.0",
5
5
  "license": "MPL-2.0",
6
6
  "svelte": "src/index.ts",
7
7
  "module": "dist/bbui.mjs",
@@ -99,5 +99,5 @@
99
99
  }
100
100
  }
101
101
  },
102
- "gitHead": "0f586f33c25c04b35a7dc72b7217fdbaa3e843c0"
102
+ "gitHead": "701aef170adfb9552bb88b97a0231e31e6054f64"
103
103
  }
@@ -1,25 +1,26 @@
1
- <script>
1
+ <script lang="ts">
2
2
  import { setContext, getContext } from "svelte"
3
3
  import Popover from "../Popover/Popover.svelte"
4
4
  import Menu from "../Menu/Menu.svelte"
5
+ import type { PopoverAlignment } from "../constants"
5
6
 
6
- export let disabled = false
7
- export let align = "left"
8
- export let portalTarget
9
- export let openOnHover = false
10
- export let animate
11
- export let offset
7
+ export let disabled: boolean = false
8
+ export let align: `${PopoverAlignment}` = "left"
9
+ export let portalTarget: string | undefined = undefined
10
+ export let openOnHover: boolean = false
11
+ export let animate: boolean | undefined = true
12
+ export let offset: number | undefined = undefined
12
13
 
13
14
  const actionMenuContext = getContext("actionMenu")
14
15
 
15
- let anchor
16
- let dropdown
17
- let timeout
16
+ let anchor: HTMLElement | undefined
17
+ let dropdown: Popover
18
+ let timeout: ReturnType<typeof setTimeout>
18
19
 
19
20
  // This is needed because display: contents is considered "invisible".
20
21
  // It should only ever be an action button, so should be fine.
21
- function getAnchor(node) {
22
- anchor = node.firstChild
22
+ function getAnchor(node: HTMLDivElement) {
23
+ anchor = (node.firstChild as HTMLElement) ?? undefined
23
24
  }
24
25
 
25
26
  export const show = () => {
@@ -37,7 +38,7 @@
37
38
  actionMenuContext?.hide()
38
39
  }
39
40
 
40
- const openMenu = event => {
41
+ const openMenu = (event: Event) => {
41
42
  if (!disabled) {
42
43
  event.stopPropagation()
43
44
  show()
@@ -14,7 +14,7 @@
14
14
  export let url = ""
15
15
  export let disabled = false
16
16
  export let initials = "JD"
17
- export let color = null
17
+ export let color = ""
18
18
 
19
19
  const DefaultColor = "#3aab87"
20
20
 
@@ -1,4 +1,4 @@
1
- <script>
1
+ <script lang="ts">
2
2
  import Popover from "../Popover/Popover.svelte"
3
3
  import Layout from "../Layout/Layout.svelte"
4
4
  import { createEventDispatcher } from "svelte"
@@ -11,15 +11,17 @@
11
11
  getThemeClassNames,
12
12
  DefaultAppTheme,
13
13
  } from "@budibase/shared-core"
14
+ import type { Theme } from "@budibase/types"
15
+ import type { PopoverAlignment } from "../constants"
14
16
 
15
- export let value
16
- export let size = "M"
17
- export let spectrumTheme
18
- export let offset
19
- export let align
17
+ export let value: string | undefined = undefined
18
+ export let size: "S" | "M" | "L" = "M"
19
+ export let spectrumTheme: Theme | undefined = undefined
20
+ export let offset: number | undefined = undefined
21
+ export let align: PopoverAlignment | undefined = undefined
20
22
 
21
- let dropdown
22
- let preview
23
+ let dropdown: Popover | undefined
24
+ let preview: HTMLElement | undefined
23
25
 
24
26
  $: customValue = getCustomValue(value)
25
27
  $: checkColor = getCheckColor(value)
@@ -28,23 +30,7 @@
28
30
  const dispatch = createEventDispatcher()
29
31
  const categories = [
30
32
  {
31
- label: "Theme",
32
- colors: [
33
- "gray-50",
34
- "gray-75",
35
- "gray-100",
36
- "gray-200",
37
- "gray-300",
38
- "gray-400",
39
- "gray-500",
40
- "gray-600",
41
- "gray-700",
42
- "gray-800",
43
- "gray-900",
44
- ],
45
- },
46
- {
47
- label: "Colors",
33
+ label: "Theme colors",
48
34
  colors: [
49
35
  "red-100",
50
36
  "orange-100",
@@ -91,13 +77,56 @@
91
77
  "indigo-700",
92
78
  "magenta-700",
93
79
 
80
+ "gray-50",
81
+ "gray-75",
82
+ "gray-100",
83
+ "gray-200",
84
+ "gray-300",
85
+ "gray-400",
86
+ "gray-500",
87
+ "gray-600",
88
+ "gray-700",
89
+ "gray-800",
90
+ "gray-900",
91
+ ],
92
+ },
93
+ {
94
+ label: "Static colors",
95
+ colors: [
96
+ "static-red-400",
97
+ "static-orange-400",
98
+ "static-yellow-400",
99
+ "static-green-400",
100
+ "static-seafoam-400",
101
+ "static-blue-400",
102
+ "static-indigo-400",
103
+ "static-magenta-400",
104
+
105
+ "static-red-800",
106
+ "static-orange-800",
107
+ "static-yellow-800",
108
+ "static-green-800",
109
+ "static-seafoam-800",
110
+ "static-blue-800",
111
+ "static-indigo-800",
112
+ "static-magenta-800",
113
+
114
+ "static-red-1200",
115
+ "static-orange-1200",
116
+ "static-yellow-1200",
117
+ "static-green-1200",
118
+ "static-seafoam-1200",
119
+ "static-blue-1200",
120
+ "static-indigo-1200",
121
+ "static-magenta-1200",
122
+
94
123
  "static-white",
95
124
  "static-black",
96
125
  ],
97
126
  },
98
127
  ]
99
128
 
100
- const getThemeClasses = theme => {
129
+ const getThemeClasses = (theme: Theme | undefined) => {
101
130
  if (!theme) {
102
131
  return ""
103
132
  }
@@ -105,12 +134,12 @@
105
134
  return getThemeClassNames(theme)
106
135
  }
107
136
 
108
- const onChange = value => {
137
+ const onChange = (value: string | null) => {
109
138
  dispatch("change", value)
110
- dropdown.hide()
139
+ dropdown?.hide()
111
140
  }
112
141
 
113
- const getCustomValue = value => {
142
+ const getCustomValue = (value: string | undefined) => {
114
143
  if (!value) {
115
144
  return value
116
145
  }
@@ -125,11 +154,11 @@
125
154
  return found ? null : value
126
155
  }
127
156
 
128
- const prettyPrint = color => {
157
+ const prettyPrint = (color: string) => {
129
158
  return capitalise(color.split("-").join(" "))
130
159
  }
131
160
 
132
- const getCheckColor = value => {
161
+ const getCheckColor = (value: string | undefined) => {
133
162
  // Use dynamic color for theme grays
134
163
  if (value?.includes("-gray-")) {
135
164
  return /^.*(gray-(50|75|100|200|300|400|500))\)$/.test(value)
@@ -137,10 +166,13 @@
137
166
  : "var(--spectrum-global-color-gray-50)"
138
167
  }
139
168
 
140
- // Use contrasating check for the dim colours
169
+ // Use contrasting check for the dim colours
141
170
  if (value?.includes("-100")) {
142
171
  return "var(--spectrum-global-color-gray-900)"
143
172
  }
173
+ if (value?.includes("-1200") || value?.includes("-800")) {
174
+ return "var(--spectrum-global-color-static-gray-50)"
175
+ }
144
176
 
145
177
  // Use black check for static white
146
178
  if (value?.includes("static-black")) {
@@ -157,7 +189,7 @@
157
189
  bind:this={preview}
158
190
  class="preview size--{size || 'M'}"
159
191
  on:click={() => {
160
- dropdown.toggle()
192
+ dropdown?.toggle()
161
193
  }}
162
194
  >
163
195
  <div
@@ -169,7 +201,7 @@
169
201
 
170
202
  <!-- svelte-ignore a11y-no-static-element-interactions -->
171
203
  <!-- svelte-ignore a11y-click-events-have-key-events -->
172
- <Popover bind:this={dropdown} anchor={preview} maxHeight={320} {offset} {align}>
204
+ <Popover bind:this={dropdown} anchor={preview} maxHeight={350} {offset} {align}>
173
205
  <Layout paddingX="XL" paddingY="L">
174
206
  <div class="container">
175
207
  {#each categories as category}
@@ -1,36 +1,36 @@
1
- <script>
1
+ <script lang="ts">
2
2
  import "@spectrum-css/textfield/dist/index-vars.css"
3
3
  import { createEventDispatcher, onMount } from "svelte"
4
4
  import clickOutside from "../../Actions/click_outside"
5
5
  import Divider from "../../Divider/Divider.svelte"
6
+ import type { EnvDropdownType } from "../../types"
6
7
 
7
- export let value = null
8
- export let placeholder = null
9
- export let type = "text"
10
- export let disabled = false
11
- export let id = null
12
- export let readonly = false
13
- export let updateOnChange = true
14
- export let align
15
- export let autofocus = false
8
+ export let value: string | number | undefined = undefined
9
+ export let placeholder: string | undefined = undefined
10
+ export let type: EnvDropdownType = "text"
11
+ export let disabled: boolean = false
12
+ export let id: string | undefined = undefined
13
+ export let readonly: boolean = false
14
+ export let updateOnChange: boolean = true
15
+ export let align: string | undefined = undefined
16
+ export let autofocus: boolean = false
16
17
  export let variables
17
- export let showModal
18
+ export let showModal: () => void
18
19
  export let environmentVariablesEnabled
19
- export let handleUpgradePanel
20
+ export let handleUpgradePanel: () => void
20
21
  const dispatch = createEventDispatcher()
21
22
 
22
- let field
23
+ let field: HTMLInputElement
23
24
  let focus = false
24
25
  let iconFocused = false
25
26
  let open = false
26
27
 
27
- //eslint-disable-next-line
28
- const STRIP_NAME_REGEX = /(\w+?)(?=\ })/g
28
+ const STRIP_NAME_REGEX = /{{\s*env\.([^\s]+)\s*}}/g
29
29
 
30
30
  // Strips the name out of the value which is {{ env.Variable }} resulting in an array like ["Variable"]
31
- $: hbsValue = String(value)?.match(STRIP_NAME_REGEX) || []
31
+ $: hbsValue = (String(value) && STRIP_NAME_REGEX.exec(String(value))) || []
32
32
 
33
- const updateValue = newValue => {
33
+ const updateValue = (newValue: any) => {
34
34
  if (readonly) {
35
35
  return
36
36
  }
@@ -48,7 +48,7 @@
48
48
  focus = true
49
49
  }
50
50
 
51
- const onBlur = event => {
51
+ const onBlur = (event: any) => {
52
52
  if (readonly) {
53
53
  return
54
54
  }
@@ -56,14 +56,14 @@
56
56
  updateValue(event.target.value)
57
57
  }
58
58
 
59
- const onInput = event => {
59
+ const onInput = (event: any) => {
60
60
  if (readonly || !updateOnChange) {
61
61
  return
62
62
  }
63
63
  updateValue(event.target.value)
64
64
  }
65
65
 
66
- const handleOutsideClick = event => {
66
+ const handleOutsideClick = (event: Event) => {
67
67
  if (open) {
68
68
  event.stopPropagation()
69
69
  open = false
@@ -73,7 +73,7 @@
73
73
  }
74
74
  }
75
75
 
76
- const handleVarSelect = variable => {
76
+ const handleVarSelect = (variable: string) => {
77
77
  open = false
78
78
  focus = false
79
79
  iconFocused = false
@@ -121,10 +121,10 @@
121
121
 
122
122
  <input
123
123
  bind:this={field}
124
- disabled={hbsValue.length || disabled}
124
+ disabled={!!hbsValue.length || disabled}
125
125
  {readonly}
126
126
  {id}
127
- value={hbsValue.length ? `{{ ${hbsValue[0]} }}` : value}
127
+ value={(hbsValue.length ? `{{ ${hbsValue[1]} }}` : value) ?? ""}
128
128
  placeholder={placeholder || ""}
129
129
  on:click
130
130
  on:blur
@@ -1,43 +1,47 @@
1
- <script>
1
+ <script lang="ts">
2
2
  import ActionButton from "../../ActionButton/ActionButton.svelte"
3
3
  import { uuid } from "../../helpers"
4
4
  import Icon from "../../Icon/Icon.svelte"
5
5
  import { createEventDispatcher } from "svelte"
6
6
 
7
- export let value = null
8
- export let title = "Upload file"
9
- export let disabled = false
10
- export let allowClear = null
11
- export let extensions = null
12
- export let handleFileTooLarge = null
13
- export let fileSizeLimit = BYTES_IN_MB * 20
14
- export let id = null
15
- export let previewUrl = null
7
+ const BYTES_IN_MB = 1000000
8
+
9
+ export let value: File | undefined = undefined
10
+ export let title: string = "Upload file"
11
+ export let disabled: boolean = false
12
+ export let allowClear: boolean | undefined = undefined
13
+ export let extensions: string[] | undefined = undefined
14
+ export let handleFileTooLarge: ((_file: File) => void) | undefined = undefined
15
+ export let fileSizeLimit: number = BYTES_IN_MB * 20
16
+ export let id: string | undefined = undefined
17
+ export let previewUrl: string | undefined = undefined
16
18
 
17
19
  const fieldId = id || uuid()
18
20
  const BYTES_IN_KB = 1000
19
- const BYTES_IN_MB = 1000000
20
21
 
21
22
  const dispatch = createEventDispatcher()
22
23
 
23
- let fileInput
24
+ let fileInput: HTMLInputElement | undefined
24
25
 
25
26
  $: inputAccept = Array.isArray(extensions) ? extensions.join(",") : "*"
26
27
 
27
- async function processFile(targetFile) {
28
- if (handleFileTooLarge && targetFile?.size >= fileSizeLimit) {
29
- handleFileTooLarge(targetFile)
30
- return
28
+ async function processFile(targetFile: File | undefined) {
29
+ if (targetFile) {
30
+ if (handleFileTooLarge && targetFile.size >= fileSizeLimit) {
31
+ handleFileTooLarge(targetFile)
32
+ return
33
+ }
34
+ dispatch("change", targetFile)
31
35
  }
32
- dispatch("change", targetFile)
33
36
  }
34
37
 
35
- function handleFile(evt) {
36
- processFile(evt.target.files[0])
38
+ function handleFile(evt: Event) {
39
+ const target = evt.target as HTMLInputElement
40
+ processFile(target.files?.[0])
37
41
  }
38
42
 
39
43
  function clearFile() {
40
- dispatch("change", null)
44
+ dispatch("change", undefined)
41
45
  }
42
46
  </script>
43
47
 
@@ -75,7 +79,9 @@
75
79
  {/if}
76
80
  </div>
77
81
  {/if}
78
- <ActionButton {disabled} on:click={fileInput.click()}>{title}</ActionButton>
82
+ <ActionButton {disabled} on:click={() => fileInput?.click()}>
83
+ {title}
84
+ </ActionButton>
79
85
  </div>
80
86
 
81
87
  <style>
@@ -20,7 +20,7 @@
20
20
  export let searchTerm: string | null = null
21
21
  export let customPopoverHeight: string | undefined = undefined
22
22
  export let open: boolean = false
23
- export let loading: boolean
23
+ export let loading: boolean = false
24
24
  export let onOptionMouseenter = () => {}
25
25
  export let onOptionMouseleave = () => {}
26
26
 
@@ -1,24 +1,31 @@
1
1
  <script lang="ts">
2
2
  import "@spectrum-css/textfield/dist/index-vars.css"
3
3
  import { createEventDispatcher } from "svelte"
4
- import type { FocusEventHandler } from "svelte/elements"
5
4
 
6
- export let value: string | null = null
7
- export let placeholder: string | null = null
8
- export let disabled = false
9
- export let readonly = false
10
- export let id: string | null = null
11
- export let height: number | null = null
12
- export let minHeight: number | null = null
5
+ export let value: string | undefined = ""
6
+ export let placeholder: string | undefined = undefined
7
+ export let disabled: boolean = false
8
+ export let readonly: boolean = false
9
+ export let id: string | undefined = undefined
10
+ export let height: string | number | undefined = undefined
11
+ export let minHeight: string | number | undefined = undefined
13
12
  export let align = null
13
+ export let updateOnChange: boolean = false
14
+
15
+ export const getCaretPosition = () => ({
16
+ start: textarea.selectionStart,
17
+ end: textarea.selectionEnd,
18
+ })
19
+
20
+ const dispatch = createEventDispatcher()
14
21
 
15
22
  let isFocused = false
16
23
  let textarea: HTMLTextAreaElement
17
- const dispatch = createEventDispatcher<{ change: string }>()
18
- const onChange: FocusEventHandler<HTMLTextAreaElement> = event => {
19
- dispatch("change", event.currentTarget.value)
20
- isFocused = false
21
- }
24
+ let scrollable = false
25
+
26
+ $: heightString = getStyleString("height", height)
27
+ $: minHeightString = getStyleString("min-height", minHeight)
28
+ $: dispatch("scrollable", scrollable)
22
29
 
23
30
  export function focus() {
24
31
  textarea.focus()
@@ -28,18 +35,38 @@
28
35
  return textarea.value
29
36
  }
30
37
 
31
- const getStyleString = (attribute: string, value: number | null) => {
32
- if (!attribute || value == null) {
38
+ const onBlur = () => {
39
+ isFocused = false
40
+ updateValue()
41
+ }
42
+
43
+ const onChange = () => {
44
+ scrollable = textarea.clientHeight < textarea.scrollHeight
45
+ if (!updateOnChange) {
46
+ return
47
+ }
48
+ updateValue()
49
+ }
50
+
51
+ const updateValue = () => {
52
+ if (readonly || disabled) {
53
+ return
54
+ }
55
+ dispatch("change", textarea.value)
56
+ }
57
+
58
+ const getStyleString = (
59
+ attribute: string,
60
+ value: string | number | undefined
61
+ ) => {
62
+ if (value == null) {
33
63
  return ""
34
64
  }
35
- if (typeof value === "number" && isNaN(value)) {
65
+ if (typeof value !== "number" || isNaN(value)) {
36
66
  return `${attribute}:${value};`
37
67
  }
38
68
  return `${attribute}:${value}px;`
39
69
  }
40
-
41
- $: heightString = getStyleString("height", height)
42
- $: minHeightString = getStyleString("min-height", minHeight)
43
70
  </script>
44
71
 
45
72
  <div
@@ -57,8 +84,10 @@
57
84
  {disabled}
58
85
  {readonly}
59
86
  {id}
87
+ on:input={onChange}
60
88
  on:focus={() => (isFocused = true)}
61
- on:blur={onChange}
89
+ on:blur={onBlur}
90
+ on:blur
62
91
  on:keypress
63
92
  >{value || ""}</textarea>
64
93
  </div>
@@ -13,7 +13,7 @@
13
13
  export let quiet = false
14
14
  export let align: "left" | "right" | "center" | undefined = undefined
15
15
  export let autofocus: boolean | null = false
16
- export let autocomplete: boolean | undefined
16
+ export let autocomplete: boolean | string | undefined
17
17
 
18
18
  const dispatch = createEventDispatcher()
19
19
 
@@ -3,7 +3,7 @@
3
3
  import DatePicker from "./Core/DatePicker/DatePicker.svelte"
4
4
  import { createEventDispatcher } from "svelte"
5
5
 
6
- export let value = null
6
+ export let value = undefined
7
7
  export let label = null
8
8
  export let labelPosition = "above"
9
9
  export let disabled = false
@@ -1,26 +1,26 @@
1
- <script>
1
+ <script lang="ts">
2
2
  import Field from "./Field.svelte"
3
3
  import EnvDropdown from "./Core/EnvDropdown.svelte"
4
4
  import { createEventDispatcher } from "svelte"
5
+ import type { EnvDropdownType } from "../types"
5
6
 
6
- export let value = null
7
- export let label = null
8
- export let labelPosition = "above"
9
- export let placeholder = null
10
- export let type = "text"
7
+ export let value: string | undefined = undefined
8
+ export let label: string | undefined = undefined
9
+ export let labelPosition: string = "above"
10
+ export let placeholder: string | undefined = undefined
11
+ export let type: EnvDropdownType = "text"
11
12
  export let disabled = false
12
13
  export let readonly = false
13
- export let error = null
14
+ export let error: string | undefined = undefined
14
15
  export let updateOnChange = true
15
- export let quiet = false
16
- export let autofocus
17
- export let variables
18
- export let showModal
19
- export let helpText = null
20
- export let environmentVariablesEnabled
21
- export let handleUpgradePanel
16
+ export let autofocus: boolean = false
17
+ export let variables: { name: string }[] = []
18
+ export let showModal: () => void
19
+ export let helpText: string | undefined = undefined
20
+ export let environmentVariablesEnabled: boolean = false
21
+ export let handleUpgradePanel: () => void = () => {}
22
22
  const dispatch = createEventDispatcher()
23
- const onChange = e => {
23
+ const onChange = (e: any) => {
24
24
  value = e.detail
25
25
  dispatch("change", e.detail)
26
26
  }
@@ -29,13 +29,11 @@
29
29
  <Field {helpText} {label} {labelPosition} {error}>
30
30
  <EnvDropdown
31
31
  {updateOnChange}
32
- {error}
33
32
  {disabled}
34
33
  {readonly}
35
34
  {value}
36
35
  {placeholder}
37
36
  {type}
38
- {quiet}
39
37
  {autofocus}
40
38
  {variables}
41
39
  {showModal}
@@ -1,23 +1,23 @@
1
- <script>
1
+ <script lang="ts">
2
2
  import Field from "./Field.svelte"
3
3
  import { CoreFile } from "./Core"
4
4
  import { createEventDispatcher } from "svelte"
5
5
 
6
- export let label = null
7
- export let labelPosition = "above"
8
- export let disabled = false
9
- export let allowClear = null
10
- export let handleFileTooLarge = () => {}
11
- export let previewUrl = null
12
- export let extensions = null
13
- export let error = null
14
- export let title = null
15
- export let value = null
16
- export let tooltip = null
17
- export let helpText = null
6
+ export let label: string | undefined = undefined
7
+ export let labelPosition: string = "above"
8
+ export let disabled: boolean = false
9
+ export let allowClear: boolean | undefined = undefined
10
+ export let handleFileTooLarge: (_file: File) => void = () => {}
11
+ export let previewUrl: string | undefined = undefined
12
+ export let extensions: string[] | undefined = undefined
13
+ export let error: string | undefined = undefined
14
+ export let title: string | undefined = undefined
15
+ export let value: File | undefined = undefined
16
+ export let tooltip: string | undefined = undefined
17
+ export let helpText: string | undefined = undefined
18
18
 
19
19
  const dispatch = createEventDispatcher()
20
- const onChange = e => {
20
+ const onChange = (e: CustomEvent) => {
21
21
  value = e.detail
22
22
  dispatch("change", e.detail)
23
23
  }
@@ -25,7 +25,6 @@
25
25
 
26
26
  <Field {helpText} {label} {labelPosition} {error} {tooltip}>
27
27
  <CoreFile
28
- {error}
29
28
  {disabled}
30
29
  {allowClear}
31
30
  {title}
@@ -14,7 +14,7 @@
14
14
  export let updateOnChange = true
15
15
  export let quiet = false
16
16
  export let autofocus: boolean | undefined = undefined
17
- export let autocomplete: boolean | undefined = undefined
17
+ export let autocomplete: boolean | string | undefined = undefined
18
18
  export let helpText: string | undefined = undefined
19
19
 
20
20
  const dispatch = createEventDispatcher()