@budibase/bbui 2.2.12-alpha.5 → 2.2.12-alpha.51

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 (46) hide show
  1. package/dist/bbui.es.js +3 -3
  2. package/dist/bbui.es.js.map +1 -1
  3. package/package.json +4 -3
  4. package/src/Accordion/Accordion.svelte +58 -0
  5. package/src/ActionButton/ActionButton.svelte +1 -0
  6. package/src/Actions/click_outside.js +28 -9
  7. package/src/Actions/position_dropdown.js +59 -52
  8. package/src/Avatar/Avatar.svelte +1 -0
  9. package/src/Button/Button.svelte +8 -2
  10. package/src/Drawer/DrawerContent.svelte +0 -1
  11. package/src/FancyForm/FancyButton.svelte +30 -0
  12. package/src/FancyForm/FancyButtonRadio.svelte +70 -0
  13. package/src/FancyForm/FancyCheckbox.svelte +53 -0
  14. package/src/FancyForm/FancyField.svelte +126 -0
  15. package/src/FancyForm/FancyFieldLabel.svelte +25 -0
  16. package/src/FancyForm/FancyForm.svelte +40 -0
  17. package/src/FancyForm/FancyInput.svelte +77 -0
  18. package/src/FancyForm/FancySelect.svelte +147 -0
  19. package/src/FancyForm/index.js +6 -0
  20. package/src/Form/Core/DatePicker.svelte +1 -1
  21. package/src/Form/Core/EnvDropdown.svelte +282 -0
  22. package/src/Form/Core/Picker.svelte +141 -124
  23. package/src/Form/Core/Select.svelte +3 -0
  24. package/src/Form/Core/TextField.svelte +0 -4
  25. package/src/Form/EnvDropdown.svelte +52 -0
  26. package/src/Icon/IconAvatar.svelte +3 -0
  27. package/src/InlineAlert/InlineAlert.svelte +1 -0
  28. package/src/Label/Label.svelte +1 -0
  29. package/src/Layout/Page.svelte +82 -13
  30. package/src/Link/Link.svelte +4 -1
  31. package/src/List/ListItem.svelte +6 -3
  32. package/src/Modal/CustomContent.svelte +0 -1
  33. package/src/Modal/Modal.svench +0 -1
  34. package/src/Modal/ModalContent.svelte +3 -2
  35. package/src/Modal/QuizModal.svelte +0 -1
  36. package/src/Popover/Popover.svelte +33 -14
  37. package/src/Popover/Popover.svench +0 -1
  38. package/src/Table/StringRenderer.svelte +9 -1
  39. package/src/Table/Table.svelte +30 -19
  40. package/src/Tabs/Tab.svelte +5 -5
  41. package/src/Tags/Tag.svelte +1 -1
  42. package/src/Tags/Tags.svelte +10 -0
  43. package/src/Typography/Heading.svelte +6 -0
  44. package/src/bbui.css +7 -3
  45. package/src/context.js +1 -0
  46. package/src/index.js +5 -0
@@ -0,0 +1,40 @@
1
+ <script>
2
+ import { setContext } from "svelte"
3
+
4
+ let fields = {}
5
+
6
+ setContext("fancy-form", {
7
+ registerField: (id, api) => {
8
+ fields = { ...fields, [id]: api }
9
+ },
10
+ unregisterField: id => {
11
+ delete fields[id]
12
+ fields = fields
13
+ },
14
+ })
15
+
16
+ export const validate = () => {
17
+ let valid = true
18
+ Object.values(fields).forEach(api => {
19
+ if (!api.validate()) {
20
+ valid = false
21
+ }
22
+ })
23
+ return valid
24
+ }
25
+ </script>
26
+
27
+ <div class="fancy-form">
28
+ <slot />
29
+ </div>
30
+
31
+ <style>
32
+ .fancy-form :global(.fancy-field:not(:first-of-type)) {
33
+ border-top-left-radius: 0;
34
+ border-top-right-radius: 0;
35
+ }
36
+ .fancy-form :global(.fancy-field:not(:last-of-type)) {
37
+ border-bottom-left-radius: 0;
38
+ border-bottom-right-radius: 0;
39
+ }
40
+ </style>
@@ -0,0 +1,77 @@
1
+ <script>
2
+ import { createEventDispatcher } from "svelte"
3
+ import FancyField from "./FancyField.svelte"
4
+ import FancyFieldLabel from "./FancyFieldLabel.svelte"
5
+ import { fade } from "svelte/transition"
6
+
7
+ export let label
8
+ export let value
9
+ export let type = "text"
10
+ export let disabled = false
11
+ export let error = null
12
+ export let validate = null
13
+ export let suffix = null
14
+
15
+ const dispatch = createEventDispatcher()
16
+
17
+ let focused = false
18
+ $: placeholder = !focused && !value
19
+
20
+ const onChange = e => {
21
+ const newValue = e.target.value
22
+ dispatch("change", newValue)
23
+ value = newValue
24
+ if (validate) {
25
+ error = validate(newValue)
26
+ }
27
+ }
28
+ </script>
29
+
30
+ <FancyField {error} {value} {validate} {disabled} {focused}>
31
+ {#if label}
32
+ <FancyFieldLabel {placeholder}>{label}</FancyFieldLabel>
33
+ {/if}
34
+ <input
35
+ {disabled}
36
+ value={value || ""}
37
+ type={type || "text"}
38
+ on:input={onChange}
39
+ on:focus={() => (focused = true)}
40
+ on:blur={() => (focused = false)}
41
+ class:placeholder
42
+ />
43
+ {#if suffix && !placeholder}
44
+ <div in:fade|local={{ duration: 130 }} class="suffix">{suffix}</div>
45
+ {/if}
46
+ </FancyField>
47
+
48
+ <style>
49
+ input {
50
+ width: 100%;
51
+ transition: transform 130ms ease-out;
52
+ transform: translateY(9px);
53
+ background: transparent;
54
+ font-size: 15px;
55
+ line-height: 17px;
56
+ font-family: var(--font-sans);
57
+ color: var(--spectrum-global-color-gray-900);
58
+ outline: none;
59
+ border: none;
60
+ padding: 0;
61
+ margin: 0;
62
+ }
63
+ input.placeholder {
64
+ transform: translateY(0);
65
+ position: absolute;
66
+ top: 0;
67
+ left: 0;
68
+ height: 100%;
69
+ }
70
+ .suffix {
71
+ color: var(--spectrum-global-color-gray-600);
72
+ transform: translateY(9px);
73
+ font-size: 15px;
74
+ line-height: 17px;
75
+ font-family: var(--font-sans);
76
+ }
77
+ </style>
@@ -0,0 +1,147 @@
1
+ <script>
2
+ import { createEventDispatcher } from "svelte"
3
+ import FancyField from "./FancyField.svelte"
4
+ import Icon from "../Icon/Icon.svelte"
5
+ import Popover from "../Popover/Popover.svelte"
6
+ import FancyFieldLabel from "./FancyFieldLabel.svelte"
7
+
8
+ export let label
9
+ export let value
10
+ export let disabled = false
11
+ export let error = null
12
+ export let validate = null
13
+ export let options = []
14
+ export let getOptionLabel = option => extractProperty(option, "label")
15
+ export let getOptionValue = option => extractProperty(option, "value")
16
+
17
+ const dispatch = createEventDispatcher()
18
+
19
+ let open = false
20
+ let popover
21
+ let wrapper
22
+
23
+ $: placeholder = !value
24
+ $: selectedLabel = getSelectedLabel(value)
25
+
26
+ const extractProperty = (value, property) => {
27
+ if (value && typeof value === "object") {
28
+ return value[property]
29
+ }
30
+ return value
31
+ }
32
+
33
+ const onChange = newValue => {
34
+ dispatch("change", newValue)
35
+ value = newValue
36
+ if (validate) {
37
+ error = validate(newValue)
38
+ }
39
+ open = false
40
+ }
41
+
42
+ const getSelectedLabel = value => {
43
+ if (!value || !options?.length) {
44
+ return ""
45
+ }
46
+ const selectedOption = options.find(x => getOptionValue(x) === value)
47
+ if (!selectedOption) {
48
+ return value
49
+ }
50
+ return getOptionLabel(selectedOption)
51
+ }
52
+ </script>
53
+
54
+ <FancyField
55
+ bind:ref={wrapper}
56
+ {error}
57
+ {value}
58
+ {validate}
59
+ {disabled}
60
+ clickable
61
+ on:click={() => (open = true)}
62
+ >
63
+ {#if label}
64
+ <FancyFieldLabel {placeholder}>{label}</FancyFieldLabel>
65
+ {/if}
66
+
67
+ <div class="value" class:placeholder>
68
+ {selectedLabel || ""}
69
+ </div>
70
+
71
+ <div class="arrow">
72
+ <Icon name="ChevronDown" />
73
+ </div>
74
+ </FancyField>
75
+
76
+ <Popover
77
+ anchor={wrapper}
78
+ align="left"
79
+ portalTarget={document.documentElement}
80
+ bind:this={popover}
81
+ {open}
82
+ on:close={() => (open = false)}
83
+ useAnchorWidth={true}
84
+ maxWidth={null}
85
+ >
86
+ <div class="popover-content">
87
+ {#if options.length}
88
+ {#each options as option, idx}
89
+ <div
90
+ class="popover-option"
91
+ tabindex="0"
92
+ on:click={() => onChange(getOptionValue(option, idx))}
93
+ >
94
+ <span class="option-text">
95
+ {getOptionLabel(option, idx)}
96
+ </span>
97
+ {#if value === getOptionValue(option, idx)}
98
+ <Icon name="Checkmark" />
99
+ {/if}
100
+ </div>
101
+ {/each}
102
+ {/if}
103
+ </div>
104
+ </Popover>
105
+
106
+ <style>
107
+ .value {
108
+ display: block;
109
+ flex: 1 1 auto;
110
+ font-size: 15px;
111
+ line-height: 17px;
112
+ color: var(--spectrum-global-color-gray-900);
113
+ transition: transform 130ms ease-out, opacity 130ms ease-out;
114
+ opacity: 1;
115
+ white-space: nowrap;
116
+ text-overflow: ellipsis;
117
+ overflow: hidden;
118
+ width: 0;
119
+ transform: translateY(9px);
120
+ }
121
+ .value.placeholder {
122
+ transform: translateY(0);
123
+ opacity: 0;
124
+ pointer-events: none;
125
+ margin-top: 0;
126
+ }
127
+ .popover-content {
128
+ display: flex;
129
+ flex-direction: column;
130
+ justify-content: flex-start;
131
+ align-items: stretch;
132
+ padding: 7px 0;
133
+ }
134
+ .popover-option {
135
+ display: flex;
136
+ flex-direction: row;
137
+ justify-content: space-between;
138
+ align-items: center;
139
+ padding: 7px 16px;
140
+ transition: background 130ms ease-out;
141
+ font-size: 15px;
142
+ }
143
+ .popover-option:hover {
144
+ background: var(--spectrum-global-color-gray-200);
145
+ cursor: pointer;
146
+ }
147
+ </style>
@@ -0,0 +1,6 @@
1
+ export { default as FancyInput } from "./FancyInput.svelte"
2
+ export { default as FancyCheckbox } from "./FancyCheckbox.svelte"
3
+ export { default as FancySelect } from "./FancySelect.svelte"
4
+ export { default as FancyButton } from "./FancyButton.svelte"
5
+ export { default as FancyForm } from "./FancyForm.svelte"
6
+ export { default as FancyButtonRadio } from "./FancyButtonRadio.svelte"
@@ -264,7 +264,7 @@
264
264
  max-height: 100%;
265
265
  }
266
266
  :global(.flatpickr-calendar) {
267
- font-family: "Source Sans Pro", sans-serif;
267
+ font-family: var(--font-sans);
268
268
  }
269
269
  .is-disabled {
270
270
  pointer-events: none !important;
@@ -0,0 +1,282 @@
1
+ <script>
2
+ import "@spectrum-css/textfield/dist/index-vars.css"
3
+ import { createEventDispatcher, onMount } from "svelte"
4
+ import clickOutside from "../../Actions/click_outside"
5
+ import Divider from "../../Divider/Divider.svelte"
6
+
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 dataCy
15
+ export let align
16
+ export let autofocus = false
17
+ export let variables
18
+ export let showModal
19
+ export let environmentVariablesEnabled
20
+ export let handleUpgradePanel
21
+ const dispatch = createEventDispatcher()
22
+
23
+ let field
24
+ let focus = false
25
+ let iconFocused = false
26
+ let open = false
27
+
28
+ //eslint-disable-next-line
29
+ const STRIP_NAME_REGEX = /(?<=\.)(.*?)(?=\ })/g
30
+
31
+ // Strips the name out of the value which is {{ env.Variable }} resulting in an array like ["Variable"]
32
+ $: hbsValue = String(value)?.match(STRIP_NAME_REGEX) || []
33
+
34
+ const updateValue = newValue => {
35
+ if (readonly) {
36
+ return
37
+ }
38
+ if (type === "number") {
39
+ const float = parseFloat(newValue)
40
+ newValue = isNaN(float) ? null : float
41
+ }
42
+ dispatch("change", newValue)
43
+ }
44
+
45
+ const onFocus = () => {
46
+ if (readonly) {
47
+ return
48
+ }
49
+ focus = true
50
+ }
51
+
52
+ const onBlur = event => {
53
+ if (readonly) {
54
+ return
55
+ }
56
+ focus = false
57
+ updateValue(event.target.value)
58
+ }
59
+
60
+ const onInput = event => {
61
+ if (readonly || !updateOnChange) {
62
+ return
63
+ }
64
+ updateValue(event.target.value)
65
+ }
66
+
67
+ const handleOutsideClick = event => {
68
+ if (open) {
69
+ event.stopPropagation()
70
+ open = false
71
+ focus = false
72
+ iconFocused = false
73
+ dispatch("closed")
74
+ }
75
+ }
76
+
77
+ const handleVarSelect = variable => {
78
+ open = false
79
+ focus = false
80
+ iconFocused = false
81
+ updateValue(`{{ env.${variable} }}`)
82
+ }
83
+
84
+ onMount(() => {
85
+ focus = autofocus
86
+ if (focus) field.focus()
87
+ })
88
+
89
+ function removeVariable() {
90
+ updateValue("")
91
+ }
92
+
93
+ function openPopover() {
94
+ open = true
95
+ focus = true
96
+ iconFocused = true
97
+ }
98
+ </script>
99
+
100
+ <div class="spectrum-InputGroup">
101
+ <div
102
+ class:is-disabled={disabled || hbsValue.length}
103
+ class:is-focused={focus}
104
+ class="spectrum-Textfield"
105
+ >
106
+ <svg
107
+ class:close-color={hbsValue.length}
108
+ class:focused={iconFocused}
109
+ class="hoverable icon-position spectrum-Icon spectrum-Icon--sizeS spectrum-Textfield-validationIcon"
110
+ focusable="false"
111
+ aria-hidden="true"
112
+ on:click={() => {
113
+ hbsValue.length ? removeVariable() : openPopover()
114
+ }}
115
+ >
116
+ <use
117
+ xlink:href={`#spectrum-icon-18-${!hbsValue.length ? "Key" : "Close"}`}
118
+ />
119
+ </svg>
120
+
121
+ <input
122
+ bind:this={field}
123
+ disabled={hbsValue.length || disabled}
124
+ {readonly}
125
+ {id}
126
+ data-cy={dataCy}
127
+ value={hbsValue.length ? `{{ ${hbsValue[0]} }}` : value}
128
+ placeholder={placeholder || ""}
129
+ on:click
130
+ on:blur
131
+ on:focus
132
+ on:input
133
+ on:keyup
134
+ on:blur={onBlur}
135
+ on:focus={onFocus}
136
+ on:input={onInput}
137
+ type={hbsValue.length ? "text" : type}
138
+ style={align ? `text-align: ${align};` : ""}
139
+ class="spectrum-Textfield-input"
140
+ inputmode={type === "number" ? "decimal" : "text"}
141
+ />
142
+ </div>
143
+ {#if open}
144
+ <div
145
+ use:clickOutside={handleOutsideClick}
146
+ class="spectrum-Popover spectrum-Popover--bottom spectrum-Picker-popover is-open"
147
+ >
148
+ <ul class="spectrum-Menu" role="listbox">
149
+ {#if !environmentVariablesEnabled}
150
+ <div class="no-variables-text primary-text">
151
+ Upgrade your plan to get environment variables
152
+ </div>
153
+ {:else if variables.length}
154
+ <div style="max-height: 100px">
155
+ {#each variables as variable, idx}
156
+ <li
157
+ class="spectrum-Menu-item"
158
+ role="option"
159
+ aria-selected="true"
160
+ tabindex="0"
161
+ on:click={() => handleVarSelect(variable.name)}
162
+ >
163
+ <span class="spectrum-Menu-itemLabel">
164
+ <div class="primary-text">
165
+ {variable.name}
166
+ <span />
167
+ </div>
168
+ <svg
169
+ class="spectrum-Icon spectrum-UIIcon-Checkmark100 spectrum-Menu-checkmark spectrum-Menu-itemIcon"
170
+ focusable="false"
171
+ aria-hidden="true"
172
+ >
173
+ <use xlink:href="#spectrum-css-icon-Checkmark100" />
174
+ </svg>
175
+ </span>
176
+ </li>
177
+ {/each}
178
+ </div>
179
+ {:else}
180
+ <div class="no-variables-text primary-text">
181
+ You don't have any environment variables yet
182
+ </div>
183
+ {/if}
184
+ </ul>
185
+ <Divider noMargin />
186
+ {#if environmentVariablesEnabled}
187
+ <div on:click={() => showModal()} class="add-variable">
188
+ <svg
189
+ class="spectrum-Icon spectrum-Icon--sizeS "
190
+ focusable="false"
191
+ aria-hidden="true"
192
+ >
193
+ <use xlink:href="#spectrum-icon-18-Add" />
194
+ </svg>
195
+ <div class="primary-text">Add Variable</div>
196
+ </div>
197
+ {:else}
198
+ <div on:click={() => handleUpgradePanel()} class="add-variable">
199
+ <svg
200
+ class="spectrum-Icon spectrum-Icon--sizeS "
201
+ focusable="false"
202
+ aria-hidden="true"
203
+ >
204
+ <use xlink:href="#spectrum-icon-18-ArrowUp" />
205
+ </svg>
206
+ <div class="primary-text">Upgrade plan</div>
207
+ </div>
208
+ {/if}
209
+ </div>
210
+ {/if}
211
+ </div>
212
+
213
+ <style>
214
+ .spectrum-Textfield {
215
+ width: 100%;
216
+ }
217
+
218
+ .icon-position {
219
+ position: absolute;
220
+ top: 25%;
221
+ right: 2%;
222
+ }
223
+
224
+ .hoverable:hover {
225
+ cursor: pointer;
226
+ color: var(--spectrum-global-color-blue-400);
227
+ }
228
+
229
+ .primary-text {
230
+ white-space: nowrap;
231
+ overflow: hidden;
232
+ text-overflow: ellipsis;
233
+ }
234
+
235
+ .spectrum-InputGroup {
236
+ min-width: 0;
237
+ width: 100%;
238
+ }
239
+
240
+ .spectrum-Popover {
241
+ max-height: 240px;
242
+ z-index: 999;
243
+ top: 100%;
244
+ }
245
+
246
+ .spectrum-Popover.spectrum-Popover--bottom.spectrum-Picker-popover.is-open {
247
+ width: 100%;
248
+ }
249
+
250
+ .no-variables-height {
251
+ height: 100px;
252
+ }
253
+
254
+ .no-variables-text {
255
+ padding: var(--spacing-m);
256
+ color: var(--spectrum-global-color-gray-600);
257
+ }
258
+
259
+ .add-variable {
260
+ display: flex;
261
+ padding: var(--spacing-m) 0 var(--spacing-m) var(--spacing-m);
262
+ align-items: center;
263
+ gap: var(--spacing-s);
264
+ cursor: pointer;
265
+ }
266
+
267
+ .focused {
268
+ color: var(--spectrum-global-color-blue-400);
269
+ }
270
+
271
+ .add-variable:hover {
272
+ background: var(--grey-1);
273
+ }
274
+
275
+ .close-color {
276
+ color: var(--spectrum-global-color-gray-900) !important;
277
+ }
278
+
279
+ .close-color:hover {
280
+ color: var(--spectrum-global-color-blue-400) !important;
281
+ }
282
+ </style>