@budibase/bbui 2.2.12-alpha.32 → 2.2.12-alpha.33

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.2.12-alpha.32",
4
+ "version": "2.2.12-alpha.33",
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.2.12-alpha.32",
41
+ "@budibase/string-templates": "2.2.12-alpha.33",
42
42
  "@spectrum-css/actionbutton": "1.0.1",
43
43
  "@spectrum-css/actiongroup": "1.0.1",
44
44
  "@spectrum-css/avatar": "3.0.2",
@@ -88,5 +88,5 @@
88
88
  "resolutions": {
89
89
  "loader-utils": "1.4.1"
90
90
  },
91
- "gitHead": "80b040aa15f2dd9bbbdf5e8fe0f74f47a14b74c8"
91
+ "gitHead": "f4e3f6f831617139f96c7de9ac12e458ccbc599d"
92
92
  }
@@ -88,6 +88,7 @@
88
88
  }
89
89
  .is-selected:not(.spectrum-ActionButton--emphasized) {
90
90
  background: var(--spectrum-global-color-gray-300);
91
+ border-color: var(--spectrum-global-color-gray-700);
91
92
  }
92
93
  .noPadding {
93
94
  padding: 0;
@@ -0,0 +1,29 @@
1
+ <script>
2
+ import Icon from "../Icon/Icon.svelte"
3
+ import FancyField from "./FancyField.svelte"
4
+
5
+ export let icon
6
+ export let disabled
7
+ </script>
8
+
9
+ <FancyField on:click clickable {disabled}>
10
+ {#if icon}
11
+ {#if icon.includes("/")}
12
+ <img src={icon} alt="button" />
13
+ {:else}
14
+ <Icon name={icon} />
15
+ {/if}
16
+ {/if}
17
+ <div>
18
+ <slot />
19
+ </div>
20
+ </FancyField>
21
+
22
+ <style>
23
+ img {
24
+ width: 22px;
25
+ }
26
+ div {
27
+ font-size: var(--font-size-l);
28
+ }
29
+ </style>
@@ -0,0 +1,70 @@
1
+ <script>
2
+ import { createEventDispatcher } from "svelte"
3
+ import FancyField from "./FancyField.svelte"
4
+ import FancyFieldLabel from "./FancyFieldLabel.svelte"
5
+ import ActionButton from "../ActionButton/ActionButton.svelte"
6
+
7
+ export let label
8
+ export let value
9
+ export let disabled = false
10
+ export let error = null
11
+ export let validate = null
12
+ export let options = []
13
+ export let getOptionLabel = option => extractProperty(option, "label")
14
+ export let getOptionValue = option => extractProperty(option, "value")
15
+
16
+ const dispatch = createEventDispatcher()
17
+
18
+ $: placeholder = !value
19
+
20
+ const extractProperty = (value, property) => {
21
+ if (value && typeof value === "object") {
22
+ return value[property]
23
+ }
24
+ return value
25
+ }
26
+
27
+ const onChange = newValue => {
28
+ dispatch("change", newValue)
29
+ value = newValue
30
+ if (validate) {
31
+ error = validate(newValue)
32
+ }
33
+ }
34
+ </script>
35
+
36
+ <FancyField {error} {value} {validate} {disabled} autoHeight>
37
+ {#if label}
38
+ <FancyFieldLabel placeholder={false}>{label}</FancyFieldLabel>
39
+ {/if}
40
+
41
+ <div class="options">
42
+ {#each options as option}
43
+ <ActionButton
44
+ selected={getOptionValue(option) === value}
45
+ on:click={() => onChange(getOptionValue(option))}
46
+ >
47
+ {getOptionLabel(option)}
48
+ </ActionButton>
49
+ {/each}
50
+ </div>
51
+ </FancyField>
52
+
53
+ <style>
54
+ .options {
55
+ margin-top: 34px;
56
+ margin-bottom: 14px;
57
+ display: flex;
58
+ flex-direction: row;
59
+ justify-content: flex-start;
60
+ align-items: center;
61
+ gap: 6px;
62
+ flex-wrap: wrap;
63
+ }
64
+ .options :global(.spectrum-ActionButton) {
65
+ font-size: 15px;
66
+ line-height: 17px;
67
+ height: auto;
68
+ padding: 6px 10px;
69
+ }
70
+ </style>
@@ -0,0 +1,53 @@
1
+ <script>
2
+ import { createEventDispatcher } from "svelte"
3
+ import FancyField from "./FancyField.svelte"
4
+ import Checkbox from "../Form/Core/Checkbox.svelte"
5
+
6
+ export let value
7
+ export let text
8
+ export let disabled = false
9
+ export let error = null
10
+ export let validate = null
11
+
12
+ const dispatch = createEventDispatcher()
13
+
14
+ const onChange = () => {
15
+ const newValue = !value
16
+ dispatch("change", newValue)
17
+ value = newValue
18
+ if (validate) {
19
+ error = validate(newValue)
20
+ }
21
+ }
22
+ </script>
23
+
24
+ <FancyField {error} {value} {validate} {disabled} clickable on:click={onChange}>
25
+ <span>
26
+ <Checkbox {disabled} {value} />
27
+ </span>
28
+ <div class="text">
29
+ {#if text}
30
+ {text}
31
+ {/if}
32
+ <slot />
33
+ </div>
34
+ </FancyField>
35
+
36
+ <style>
37
+ span {
38
+ pointer-events: none;
39
+ }
40
+ .text {
41
+ font-size: 15px;
42
+ line-height: 17px;
43
+ overflow: hidden;
44
+ text-overflow: ellipsis;
45
+ display: -webkit-box;
46
+ -webkit-line-clamp: 2;
47
+ line-clamp: 2;
48
+ -webkit-box-orient: vertical;
49
+ }
50
+ .text > :global(*) {
51
+ font-size: inherit !important;
52
+ }
53
+ </style>
@@ -0,0 +1,126 @@
1
+ <script>
2
+ import Icon from "../Icon/Icon.svelte"
3
+ import { getContext, onMount } from "svelte"
4
+ import { slide } from "svelte/transition"
5
+
6
+ export let disabled = false
7
+ export let error = null
8
+ export let focused = false
9
+ export let clickable = false
10
+ export let validate
11
+ export let value
12
+ export let ref
13
+ export let autoHeight
14
+
15
+ const formContext = getContext("fancy-form")
16
+ const id = Math.random()
17
+ const API = {
18
+ validate: () => {
19
+ if (validate) {
20
+ error = validate(value)
21
+ }
22
+ return !error
23
+ },
24
+ }
25
+
26
+ onMount(() => {
27
+ if (formContext) {
28
+ formContext.registerField(id, API)
29
+ }
30
+ return () => {
31
+ if (formContext) {
32
+ formContext.unregisterField(id)
33
+ }
34
+ }
35
+ })
36
+ </script>
37
+
38
+ <div
39
+ bind:this={ref}
40
+ class="fancy-field"
41
+ class:error
42
+ class:disabled
43
+ class:focused
44
+ class:clickable
45
+ class:auto-height={autoHeight}
46
+ >
47
+ <div class="content" on:click>
48
+ <div class="field">
49
+ <slot />
50
+ </div>
51
+ {#if error}
52
+ <div class="error-icon">
53
+ <Icon name="Alert" />
54
+ </div>
55
+ {/if}
56
+ </div>
57
+ {#if error}
58
+ <div transition:slide|local={{ duration: 130 }} class="error-message">
59
+ {error}
60
+ </div>
61
+ {/if}
62
+ </div>
63
+
64
+ <style>
65
+ .fancy-field {
66
+ max-width: 400px;
67
+ background: var(--spectrum-global-color-gray-75);
68
+ border: 1px solid var(--spectrum-global-color-gray-300);
69
+ border-radius: 4px;
70
+ box-sizing: border-box;
71
+ transition: border-color 130ms ease-out, background 130ms ease-out,
72
+ background 130ms ease-out;
73
+ color: var(--spectrum-global-color-gray-800);
74
+ }
75
+ .fancy-field:hover {
76
+ border-color: var(--spectrum-global-color-gray-400);
77
+ }
78
+ .fancy-field.clickable:hover {
79
+ background: var(--spectrum-global-color-gray-200);
80
+ cursor: pointer;
81
+ }
82
+ .fancy-field.focused {
83
+ border-color: var(--spectrum-global-color-blue-400);
84
+ }
85
+ .fancy-field.error {
86
+ border-color: var(--spectrum-global-color-red-400);
87
+ }
88
+ .fancy-field.disabled {
89
+ background: var(--spectrum-global-color-gray-200);
90
+ color: var(--spectrum-global-color-gray-400);
91
+ border: 1px solid var(--spectrum-global-color-gray-300);
92
+ pointer-events: none;
93
+ }
94
+ .content {
95
+ position: relative;
96
+ height: 64px;
97
+ padding: 0 16px;
98
+ }
99
+ .fancy-field.auto-height .content {
100
+ height: auto;
101
+ }
102
+ .content,
103
+ .field {
104
+ display: flex;
105
+ flex-direction: row;
106
+ justify-content: flex-start;
107
+ align-items: center;
108
+ gap: 16px;
109
+ }
110
+ .field {
111
+ flex: 1 1 auto;
112
+ }
113
+ .error-message {
114
+ background: var(--spectrum-global-color-red-400);
115
+ color: white;
116
+ font-size: 14px;
117
+ padding: 6px 16px;
118
+ font-weight: 500;
119
+ }
120
+ .error-icon {
121
+ flex: 0 0 auto;
122
+ }
123
+ .error-icon :global(.spectrum-Icon) {
124
+ fill: var(--spectrum-global-color-red-400);
125
+ }
126
+ </style>
@@ -0,0 +1,25 @@
1
+ <script>
2
+ export let placeholder = true
3
+ </script>
4
+
5
+ <div class:placeholder>
6
+ <slot />
7
+ </div>
8
+
9
+ <style>
10
+ div {
11
+ font-size: 14px;
12
+ line-height: 15px;
13
+ font-weight: 500;
14
+ position: absolute;
15
+ top: 10px;
16
+ color: var(--spectrum-global-color-gray-600);
17
+ transition: font-size 130ms ease-out, top 130ms ease-out,
18
+ transform 130ms ease-out;
19
+ }
20
+ div.placeholder {
21
+ top: 50%;
22
+ font-size: 15px;
23
+ transform: translateY(-50%);
24
+ }
25
+ </style>
@@ -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,63 @@
1
+ <script>
2
+ import { createEventDispatcher } from "svelte"
3
+ import FancyField from "./FancyField.svelte"
4
+ import FancyFieldLabel from "./FancyFieldLabel.svelte"
5
+
6
+ export let label
7
+ export let value
8
+ export let type = "text"
9
+ export let disabled = false
10
+ export let error = null
11
+ export let validate = null
12
+
13
+ const dispatch = createEventDispatcher()
14
+
15
+ let focused = false
16
+ $: placeholder = !focused && !value
17
+
18
+ const onChange = e => {
19
+ const newValue = e.target.value
20
+ dispatch("change", newValue)
21
+ value = newValue
22
+ if (validate) {
23
+ error = validate(newValue)
24
+ }
25
+ }
26
+ </script>
27
+
28
+ <FancyField {error} {value} {validate} {disabled} {focused}>
29
+ {#if label}
30
+ <FancyFieldLabel {placeholder}>{label}</FancyFieldLabel>
31
+ {/if}
32
+ <input
33
+ {disabled}
34
+ value={value || ""}
35
+ type={type || "text"}
36
+ on:input={onChange}
37
+ on:focus={() => (focused = true)}
38
+ on:blur={() => (focused = false)}
39
+ class:placeholder
40
+ />
41
+ </FancyField>
42
+
43
+ <style>
44
+ input {
45
+ width: 100%;
46
+ transition: transform 130ms ease-out;
47
+ transform: translateY(9px);
48
+ background: transparent;
49
+ font-size: 15px;
50
+ line-height: 17px;
51
+ font-family: var(--font-sans);
52
+ color: var(--spectrum-global-color-gray-900);
53
+ outline: none;
54
+ border: none;
55
+ }
56
+ input.placeholder {
57
+ transform: translateY(0);
58
+ position: absolute;
59
+ top: 0;
60
+ left: 0;
61
+ height: 100%;
62
+ }
63
+ </style>
@@ -0,0 +1,135 @@
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
+
25
+ const extractProperty = (value, property) => {
26
+ if (value && typeof value === "object") {
27
+ return value[property]
28
+ }
29
+ return value
30
+ }
31
+
32
+ const onChange = newValue => {
33
+ dispatch("change", newValue)
34
+ value = newValue
35
+ if (validate) {
36
+ error = validate(newValue)
37
+ }
38
+ open = false
39
+ }
40
+ </script>
41
+
42
+ <FancyField
43
+ bind:ref={wrapper}
44
+ {error}
45
+ {value}
46
+ {validate}
47
+ {disabled}
48
+ clickable
49
+ on:click={() => (open = true)}
50
+ >
51
+ {#if label}
52
+ <FancyFieldLabel {placeholder}>{label}</FancyFieldLabel>
53
+ {/if}
54
+
55
+ <div class="value" class:placeholder>
56
+ {value || ""}
57
+ </div>
58
+
59
+ <div class="arrow">
60
+ <Icon name="ChevronDown" />
61
+ </div>
62
+ </FancyField>
63
+
64
+ <Popover
65
+ anchor={wrapper}
66
+ align="left"
67
+ portalTarget={document.documentElement}
68
+ bind:this={popover}
69
+ {open}
70
+ on:close={() => (open = false)}
71
+ useAnchorWidth={true}
72
+ maxWidth={null}
73
+ >
74
+ <div class="popover-content">
75
+ {#if options.length}
76
+ {#each options as option, idx}
77
+ <div
78
+ class="popover-option"
79
+ tabindex="0"
80
+ on:click={() => onChange(getOptionValue(option, idx))}
81
+ >
82
+ <span class="option-text">
83
+ {getOptionLabel(option, idx)}
84
+ </span>
85
+ {#if value === getOptionValue(option, idx)}
86
+ <Icon name="Checkmark" />
87
+ {/if}
88
+ </div>
89
+ {/each}
90
+ {/if}
91
+ </div>
92
+ </Popover>
93
+
94
+ <style>
95
+ .value {
96
+ display: block;
97
+ flex: 1 1 auto;
98
+ font-size: 15px;
99
+ line-height: 17px;
100
+ color: var(--spectrum-global-color-gray-900);
101
+ transition: transform 130ms ease-out, opacity 130ms ease-out;
102
+ opacity: 1;
103
+ white-space: nowrap;
104
+ text-overflow: ellipsis;
105
+ overflow: hidden;
106
+ width: 0;
107
+ transform: translateY(9px);
108
+ }
109
+ .value.placeholder {
110
+ transform: translateY(0);
111
+ opacity: 0;
112
+ pointer-events: none;
113
+ margin-top: 0;
114
+ }
115
+ .popover-content {
116
+ display: flex;
117
+ flex-direction: column;
118
+ justify-content: flex-start;
119
+ align-items: stretch;
120
+ padding: 7px 0;
121
+ }
122
+ .popover-option {
123
+ display: flex;
124
+ flex-direction: row;
125
+ justify-content: space-between;
126
+ align-items: center;
127
+ padding: 7px 16px;
128
+ transition: background 130ms ease-out;
129
+ font-size: 15px;
130
+ }
131
+ .popover-option:hover {
132
+ background: var(--spectrum-global-color-gray-200);
133
+ cursor: pointer;
134
+ }
135
+ </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"
@@ -18,8 +18,11 @@
18
18
  export let autoWidth = false
19
19
  export let autocomplete = false
20
20
  export let sort = false
21
+
21
22
  const dispatch = createEventDispatcher()
23
+
22
24
  let open = false
25
+
23
26
  $: fieldText = getFieldText(value, options, placeholder)
24
27
  $: fieldIcon = getFieldAttribute(getOptionIcon, value, options)
25
28
  $: fieldColour = getFieldAttribute(getOptionColour, value, options)
@@ -18,6 +18,7 @@
18
18
  <div class="main">
19
19
  <div class="content" class:wide class:noPadding class:narrow>
20
20
  <slot />
21
+ <div class="fix-scroll-padding" />
21
22
  </div>
22
23
  </div>
23
24
  <div
@@ -55,9 +56,14 @@
55
56
  max-width: 1080px;
56
57
  margin: 0 auto;
57
58
  flex: 1 1 auto;
58
- padding: 50px;
59
+ padding: 50px 50px 0 50px;
59
60
  z-index: 1;
60
61
  }
62
+ .fix-scroll-padding {
63
+ content: "";
64
+ display: block;
65
+ flex: 0 0 50px;
66
+ }
61
67
  .content.wide {
62
68
  max-width: none;
63
69
  }
@@ -1,5 +1,6 @@
1
1
  <script>
2
2
  import "@spectrum-css/link/dist/index-vars.css"
3
+ import { createEventDispatcher } from "svelte"
3
4
 
4
5
  export let href = "#"
5
6
  export let size = "M"
@@ -9,10 +10,12 @@
9
10
  export let overBackground = false
10
11
  export let target
11
12
  export let download
13
+
14
+ const dispatch = createEventDispatcher()
12
15
  </script>
13
16
 
14
17
  <a
15
- on:click
18
+ on:click={e => dispatch("click") && e.stopPropagation()}
16
19
  {href}
17
20
  {target}
18
21
  {download}
package/src/index.js CHANGED
@@ -101,3 +101,6 @@ export { banner, BANNER_TYPES } from "./Stores/banner"
101
101
 
102
102
  // Helpers
103
103
  export * as Helpers from "./helpers"
104
+
105
+ // Fancy form components
106
+ export * from "./FancyForm"