@budibase/bbui 2.2.26 → 2.2.27
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/dist/bbui.es.js +3 -3
- package/dist/bbui.es.js.map +1 -1
- package/package.json +4 -3
- package/src/Accordion/Accordion.svelte +58 -0
- package/src/ActionButton/ActionButton.svelte +2 -3
- package/src/ActionMenu/ActionMenu.svelte +1 -2
- package/src/Actions/click_outside.js +28 -9
- package/src/Actions/position_dropdown.js +85 -53
- package/src/Avatar/Avatar.svelte +1 -0
- package/src/Badge/Badge.svelte +13 -0
- package/src/Button/Button.svelte +8 -4
- package/src/Drawer/DrawerContent.svelte +0 -1
- package/src/FancyForm/FancyButton.svelte +30 -0
- package/src/FancyForm/FancyButtonRadio.svelte +70 -0
- package/src/FancyForm/FancyCheckbox.svelte +53 -0
- package/src/FancyForm/FancyField.svelte +126 -0
- package/src/FancyForm/FancyFieldLabel.svelte +25 -0
- package/src/FancyForm/FancyForm.svelte +40 -0
- package/src/FancyForm/FancyInput.svelte +77 -0
- package/src/FancyForm/FancySelect.svelte +147 -0
- package/src/FancyForm/index.js +6 -0
- package/src/Form/Core/DatePicker.svelte +1 -1
- package/src/Form/Core/Dropzone.svelte +71 -66
- package/src/Form/Core/EnvDropdown.svelte +276 -0
- package/src/Form/Core/Picker.svelte +141 -124
- package/src/Form/Core/Select.svelte +3 -0
- package/src/Form/Core/Switch.svelte +0 -2
- package/src/Form/Core/TextField.svelte +0 -6
- package/src/Form/EnvDropdown.svelte +50 -0
- package/src/Form/Input.svelte +0 -2
- package/src/Form/InputDropdown.svelte +0 -2
- package/src/Form/PickerDropdown.svelte +0 -2
- package/src/Form/Toggle.svelte +1 -2
- package/src/Icon/IconAvatar.svelte +3 -0
- package/src/InlineAlert/InlineAlert.svelte +1 -0
- package/src/Label/Label.svelte +1 -0
- package/src/Layout/Page.svelte +82 -13
- package/src/Link/Link.svelte +4 -1
- package/src/List/ListItem.svelte +6 -3
- package/src/Menu/Item.svelte +0 -2
- package/src/Modal/CustomContent.svelte +0 -1
- package/src/Modal/Modal.svench +0 -1
- package/src/Modal/ModalContent.svelte +4 -4
- package/src/Modal/QuizModal.svelte +0 -1
- package/src/Popover/Popover.svelte +35 -31
- package/src/Popover/Popover.svench +0 -1
- package/src/SideNavigation/Item.svelte +0 -2
- package/src/Table/RelationshipRenderer.svelte +3 -8
- package/src/Table/StringRenderer.svelte +9 -1
- package/src/Table/Table.svelte +30 -19
- package/src/Tabs/Tab.svelte +5 -5
- package/src/Tags/Tag.svelte +1 -1
- package/src/Tags/Tags.svelte +10 -0
- package/src/Typography/Heading.svelte +6 -0
- package/src/bbui.css +7 -3
- package/src/context.js +1 -0
- package/src/index.js +5 -0
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.
|
|
4
|
+
"version": "2.2.27",
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
6
|
"svelte": "src/index.js",
|
|
7
7
|
"module": "dist/bbui.es.js",
|
|
@@ -38,7 +38,8 @@
|
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@adobe/spectrum-css-workflow-icons": "1.2.1",
|
|
41
|
-
"@budibase/string-templates": "^2.2.
|
|
41
|
+
"@budibase/string-templates": "^2.2.27",
|
|
42
|
+
"@spectrum-css/accordion": "3.0.24",
|
|
42
43
|
"@spectrum-css/actionbutton": "1.0.1",
|
|
43
44
|
"@spectrum-css/actiongroup": "1.0.1",
|
|
44
45
|
"@spectrum-css/avatar": "3.0.2",
|
|
@@ -88,5 +89,5 @@
|
|
|
88
89
|
"resolutions": {
|
|
89
90
|
"loader-utils": "1.4.1"
|
|
90
91
|
},
|
|
91
|
-
"gitHead": "
|
|
92
|
+
"gitHead": "d5e24cc25f7eff877eb808046f0069359fddeb74"
|
|
92
93
|
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import "@spectrum-css/accordion"
|
|
3
|
+
|
|
4
|
+
export let itemName
|
|
5
|
+
export let initialOpen
|
|
6
|
+
export let header
|
|
7
|
+
|
|
8
|
+
let isOpen
|
|
9
|
+
|
|
10
|
+
function getOpenClass(isOpen) {
|
|
11
|
+
if (isOpen === undefined) {
|
|
12
|
+
isOpen = initialOpen
|
|
13
|
+
}
|
|
14
|
+
return isOpen ? "is-open" : ""
|
|
15
|
+
}
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<div class="spectrum-Accordion" role={itemName}>
|
|
19
|
+
<div class="spectrum-Accordion-item {getOpenClass(isOpen)}">
|
|
20
|
+
<h3 class="spectrum-Accordion-itemHeading">
|
|
21
|
+
<button
|
|
22
|
+
class="spectrum-Accordion-itemHeader"
|
|
23
|
+
type="button"
|
|
24
|
+
on:click={() => (isOpen = !isOpen)}
|
|
25
|
+
>
|
|
26
|
+
{header}
|
|
27
|
+
</button>
|
|
28
|
+
<svg
|
|
29
|
+
class="spectrum-Icon spectrum-UIIcon-ChevronRight100 spectrum-Accordion-itemIndicator"
|
|
30
|
+
focusable="false"
|
|
31
|
+
aria-hidden="true"
|
|
32
|
+
>
|
|
33
|
+
<use xlink:href="#spectrum-css-icon-Chevron100" />
|
|
34
|
+
</svg>
|
|
35
|
+
</h3>
|
|
36
|
+
<div class="spectrum-Accordion-itemContent" role={itemName}>
|
|
37
|
+
<slot />
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<style>
|
|
43
|
+
.spectrum-Accordion {
|
|
44
|
+
margin-left: -20px;
|
|
45
|
+
}
|
|
46
|
+
.spectrum-Accordion-item {
|
|
47
|
+
border: none;
|
|
48
|
+
}
|
|
49
|
+
.spectrum-Accordion-itemContent {
|
|
50
|
+
width: 97%;
|
|
51
|
+
padding-left: 30px;
|
|
52
|
+
}
|
|
53
|
+
.spectrum-Accordion-itemHeader {
|
|
54
|
+
text-transform: none;
|
|
55
|
+
font-weight: bold;
|
|
56
|
+
font-size: 0.875rem;
|
|
57
|
+
}
|
|
58
|
+
</style>
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
export let longPressable = false
|
|
10
10
|
export let disabled = false
|
|
11
11
|
export let icon = ""
|
|
12
|
-
export let dataCy = null
|
|
13
12
|
export let size = "M"
|
|
14
13
|
export let active = false
|
|
15
14
|
export let fullWidth = false
|
|
@@ -37,7 +36,6 @@
|
|
|
37
36
|
</script>
|
|
38
37
|
|
|
39
38
|
<button
|
|
40
|
-
data-cy={dataCy}
|
|
41
39
|
use:longPress
|
|
42
40
|
class:spectrum-ActionButton--quiet={quiet}
|
|
43
41
|
class:spectrum-ActionButton--emphasized={emphasized}
|
|
@@ -86,8 +84,9 @@
|
|
|
86
84
|
margin-left: 0;
|
|
87
85
|
transition: color ease-out 130ms;
|
|
88
86
|
}
|
|
89
|
-
.is-selected:not(.spectrum-ActionButton--emphasized) {
|
|
87
|
+
.is-selected:not(.spectrum-ActionButton--emphasized):not(.spectrum-ActionButton--quiet) {
|
|
90
88
|
background: var(--spectrum-global-color-gray-300);
|
|
89
|
+
border-color: var(--spectrum-global-color-gray-500);
|
|
91
90
|
}
|
|
92
91
|
.noPadding {
|
|
93
92
|
padding: 0;
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
export let disabled = false
|
|
7
7
|
export let align = "left"
|
|
8
8
|
export let portalTarget
|
|
9
|
-
export let dataCy
|
|
10
9
|
|
|
11
10
|
let anchor
|
|
12
11
|
let dropdown
|
|
@@ -37,7 +36,7 @@
|
|
|
37
36
|
<div use:getAnchor on:click={openMenu}>
|
|
38
37
|
<slot name="control" />
|
|
39
38
|
</div>
|
|
40
|
-
<Popover bind:this={dropdown} {anchor} {align} {portalTarget}
|
|
39
|
+
<Popover bind:this={dropdown} {anchor} {align} {portalTarget}>
|
|
41
40
|
<Menu>
|
|
42
41
|
<slot />
|
|
43
42
|
</Menu>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
const ignoredClasses = [".flatpickr-calendar", ".
|
|
1
|
+
const ignoredClasses = [".flatpickr-calendar", ".spectrum-Popover"]
|
|
2
2
|
let clickHandlers = []
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Handle a body click event
|
|
6
6
|
*/
|
|
7
7
|
const handleClick = event => {
|
|
8
|
-
// Ignore click if
|
|
8
|
+
// Ignore click if this is an ignored class
|
|
9
9
|
for (let className of ignoredClasses) {
|
|
10
10
|
if (event.target.closest(className)) {
|
|
11
11
|
return
|
|
@@ -14,9 +14,18 @@ const handleClick = event => {
|
|
|
14
14
|
|
|
15
15
|
// Process handlers
|
|
16
16
|
clickHandlers.forEach(handler => {
|
|
17
|
-
if (
|
|
18
|
-
|
|
17
|
+
if (handler.element.contains(event.target)) {
|
|
18
|
+
return
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Ignore clicks for modals, unless the handler is registered from a modal
|
|
22
|
+
const sourceInModal = handler.anchor.closest(".spectrum-Modal") != null
|
|
23
|
+
const clickInModal = event.target.closest(".spectrum-Modal") != null
|
|
24
|
+
if (clickInModal && !sourceInModal) {
|
|
25
|
+
return
|
|
19
26
|
}
|
|
27
|
+
|
|
28
|
+
handler.callback?.(event)
|
|
20
29
|
})
|
|
21
30
|
}
|
|
22
31
|
document.documentElement.addEventListener("click", handleClick, true)
|
|
@@ -24,10 +33,10 @@ document.documentElement.addEventListener("click", handleClick, true)
|
|
|
24
33
|
/**
|
|
25
34
|
* Adds or updates a click handler
|
|
26
35
|
*/
|
|
27
|
-
const updateHandler = (id, element, callback) => {
|
|
36
|
+
const updateHandler = (id, element, anchor, callback) => {
|
|
28
37
|
let existingHandler = clickHandlers.find(x => x.id === id)
|
|
29
38
|
if (!existingHandler) {
|
|
30
|
-
clickHandlers.push({ id, element, callback })
|
|
39
|
+
clickHandlers.push({ id, element, anchor, callback })
|
|
31
40
|
} else {
|
|
32
41
|
existingHandler.callback = callback
|
|
33
42
|
}
|
|
@@ -42,12 +51,22 @@ const removeHandler = id => {
|
|
|
42
51
|
|
|
43
52
|
/**
|
|
44
53
|
* Svelte action to apply a click outside handler for a certain element
|
|
54
|
+
* opts.anchor is an optional param specifying the real root source of the
|
|
55
|
+
* component being observed. This is required for things like popovers, where
|
|
56
|
+
* the element using the clickoutside action is the popover, but the popover is
|
|
57
|
+
* rendered at the root of the DOM somewhere, whereas the popover anchor is the
|
|
58
|
+
* element we actually want to consider when determining the source component.
|
|
45
59
|
*/
|
|
46
|
-
export default (element,
|
|
60
|
+
export default (element, opts) => {
|
|
47
61
|
const id = Math.random()
|
|
48
|
-
|
|
62
|
+
const update = newOpts => {
|
|
63
|
+
const callback = newOpts?.callback || newOpts
|
|
64
|
+
const anchor = newOpts?.anchor || element
|
|
65
|
+
updateHandler(id, element, anchor, callback)
|
|
66
|
+
}
|
|
67
|
+
update(opts)
|
|
49
68
|
return {
|
|
50
|
-
update
|
|
69
|
+
update,
|
|
51
70
|
destroy: () => removeHandler(id),
|
|
52
71
|
}
|
|
53
72
|
}
|
|
@@ -1,75 +1,107 @@
|
|
|
1
|
-
export default function positionDropdown(element,
|
|
2
|
-
let
|
|
3
|
-
let
|
|
4
|
-
let dimensions = getDimensions(anchor)
|
|
1
|
+
export default function positionDropdown(element, opts) {
|
|
2
|
+
let resizeObserver
|
|
3
|
+
let latestOpts = opts
|
|
5
4
|
|
|
6
|
-
function
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
width,
|
|
12
|
-
} = anchor.getBoundingClientRect()
|
|
13
|
-
const spaceBelow = window.innerHeight - bottom
|
|
14
|
-
const containerRect = element.getBoundingClientRect()
|
|
5
|
+
// We need a static reference to this function so that we can properly
|
|
6
|
+
// clean up the scroll listener.
|
|
7
|
+
const scrollUpdate = () => {
|
|
8
|
+
updatePosition(latestOpts)
|
|
9
|
+
}
|
|
15
10
|
|
|
16
|
-
|
|
11
|
+
// Updates the position of the dropdown
|
|
12
|
+
const updatePosition = opts => {
|
|
13
|
+
const { anchor, align, maxWidth, useAnchorWidth, offset = 5 } = opts
|
|
14
|
+
if (!anchor) {
|
|
15
|
+
return
|
|
16
|
+
}
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
// Compute bounds
|
|
19
|
+
const anchorBounds = anchor.getBoundingClientRect()
|
|
20
|
+
const elementBounds = element.getBoundingClientRect()
|
|
21
|
+
let styles = {
|
|
22
|
+
maxHeight: null,
|
|
23
|
+
minWidth: null,
|
|
24
|
+
maxWidth,
|
|
25
|
+
left: null,
|
|
26
|
+
top: null,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Determine vertical styles
|
|
30
|
+
if (align === "right-outside") {
|
|
31
|
+
styles.top = anchorBounds.top
|
|
32
|
+
} else if (window.innerHeight - anchorBounds.bottom < 100) {
|
|
33
|
+
styles.top = anchorBounds.top - elementBounds.height - offset
|
|
22
34
|
} else {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
maxHeight = spaceBelow - 20
|
|
35
|
+
styles.top = anchorBounds.bottom + offset
|
|
36
|
+
styles.maxHeight = window.innerHeight - anchorBounds.bottom - 20
|
|
26
37
|
}
|
|
27
38
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
// Determine horizontal styles
|
|
40
|
+
if (!maxWidth && useAnchorWidth) {
|
|
41
|
+
styles.maxWidth = anchorBounds.width
|
|
42
|
+
}
|
|
43
|
+
if (useAnchorWidth) {
|
|
44
|
+
styles.minWidth = anchorBounds.width
|
|
33
45
|
}
|
|
46
|
+
if (align === "right") {
|
|
47
|
+
styles.left = anchorBounds.left + anchorBounds.width - elementBounds.width
|
|
48
|
+
} else if (align === "right-outside") {
|
|
49
|
+
styles.left = anchorBounds.right + offset
|
|
50
|
+
} else {
|
|
51
|
+
styles.left = anchorBounds.left
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Apply styles
|
|
55
|
+
Object.entries(styles).forEach(([style, value]) => {
|
|
56
|
+
if (value) {
|
|
57
|
+
element.style[style] = `${value.toFixed(0)}px`
|
|
58
|
+
} else {
|
|
59
|
+
element.style[style] = null
|
|
60
|
+
}
|
|
61
|
+
})
|
|
34
62
|
}
|
|
35
63
|
|
|
36
|
-
|
|
37
|
-
|
|
64
|
+
// The actual svelte action callback which creates observers on the relevant
|
|
65
|
+
// DOM elements
|
|
66
|
+
const update = newOpts => {
|
|
67
|
+
latestOpts = newOpts
|
|
38
68
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
left = dimensions.left + dimensions.width
|
|
43
|
-
} else {
|
|
44
|
-
left = dimensions.left
|
|
69
|
+
// Cleanup old state
|
|
70
|
+
if (resizeObserver) {
|
|
71
|
+
resizeObserver.disconnect()
|
|
45
72
|
}
|
|
46
73
|
|
|
47
|
-
|
|
74
|
+
// Do nothing if no anchor
|
|
75
|
+
const { anchor } = newOpts
|
|
76
|
+
if (!anchor) {
|
|
77
|
+
return
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Observe both anchor and element and resize the popover as appropriate
|
|
81
|
+
resizeObserver = new ResizeObserver(() => updatePosition(newOpts))
|
|
82
|
+
resizeObserver.observe(anchor)
|
|
83
|
+
resizeObserver.observe(element)
|
|
84
|
+
resizeObserver.observe(document.body)
|
|
48
85
|
}
|
|
49
86
|
|
|
87
|
+
// Apply initial styles which don't need to change
|
|
50
88
|
element.style.position = "absolute"
|
|
51
89
|
element.style.zIndex = "9999"
|
|
52
|
-
if (maxWidth) {
|
|
53
|
-
element.style.maxWidth = `${maxWidth}px`
|
|
54
|
-
}
|
|
55
|
-
element.style.minWidth = `${dimensions.width}px`
|
|
56
|
-
element.style.maxHeight = `${maxHeight.toFixed(0)}px`
|
|
57
|
-
element.style.transformOrigin = `center ${positionSide}`
|
|
58
|
-
element.style[positionSide] = `${dimensions[positionSide]}px`
|
|
59
|
-
element.style.left = `${calcLeftPosition(dimensions).toFixed(0)}px`
|
|
60
90
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
})
|
|
68
|
-
resizeObserver.observe(anchor)
|
|
69
|
-
resizeObserver.observe(element)
|
|
91
|
+
// Set up a scroll listener
|
|
92
|
+
document.addEventListener("scroll", scrollUpdate, true)
|
|
93
|
+
|
|
94
|
+
// Perform initial update
|
|
95
|
+
update(opts)
|
|
96
|
+
|
|
70
97
|
return {
|
|
98
|
+
update,
|
|
71
99
|
destroy() {
|
|
72
|
-
|
|
100
|
+
// Cleanup
|
|
101
|
+
if (resizeObserver) {
|
|
102
|
+
resizeObserver.disconnect()
|
|
103
|
+
}
|
|
104
|
+
document.removeEventListener("scroll", scrollUpdate, true)
|
|
73
105
|
},
|
|
74
106
|
}
|
|
75
107
|
}
|
package/src/Avatar/Avatar.svelte
CHANGED
package/src/Badge/Badge.svelte
CHANGED
|
@@ -10,10 +10,13 @@
|
|
|
10
10
|
export let green = false
|
|
11
11
|
export let active = false
|
|
12
12
|
export let inactive = false
|
|
13
|
+
export let hoverable = false
|
|
13
14
|
</script>
|
|
14
15
|
|
|
15
16
|
<span
|
|
17
|
+
on:click
|
|
16
18
|
class="spectrum-Label"
|
|
19
|
+
class:hoverable
|
|
17
20
|
class:spectrum-Label--small={size === "S"}
|
|
18
21
|
class:spectrum-Label--large={size === "L"}
|
|
19
22
|
class:spectrum-Label--grey={grey}
|
|
@@ -27,3 +30,13 @@
|
|
|
27
30
|
>
|
|
28
31
|
<slot />
|
|
29
32
|
</span>
|
|
33
|
+
|
|
34
|
+
<style>
|
|
35
|
+
.spectrum-Label--grey {
|
|
36
|
+
background-color: var(--spectrum-global-color-gray-500);
|
|
37
|
+
font-weight: 600;
|
|
38
|
+
}
|
|
39
|
+
.hoverable:hover {
|
|
40
|
+
cursor: pointer;
|
|
41
|
+
}
|
|
42
|
+
</style>
|
package/src/Button/Button.svelte
CHANGED
|
@@ -13,13 +13,14 @@
|
|
|
13
13
|
export let icon = undefined
|
|
14
14
|
export let active = false
|
|
15
15
|
export let tooltip = undefined
|
|
16
|
-
export let
|
|
17
|
-
export let
|
|
16
|
+
export let newStyles = true
|
|
17
|
+
export let id
|
|
18
18
|
|
|
19
19
|
let showTooltip = false
|
|
20
20
|
</script>
|
|
21
21
|
|
|
22
22
|
<button
|
|
23
|
+
{id}
|
|
23
24
|
class:spectrum-Button--cta={cta}
|
|
24
25
|
class:spectrum-Button--primary={primary}
|
|
25
26
|
class:spectrum-Button--secondary={secondary}
|
|
@@ -28,9 +29,9 @@
|
|
|
28
29
|
class:spectrum-Button--quiet={quiet}
|
|
29
30
|
class:new-styles={newStyles}
|
|
30
31
|
class:active
|
|
32
|
+
class:disabled
|
|
31
33
|
class="spectrum-Button spectrum-Button--size{size.toUpperCase()}"
|
|
32
34
|
{disabled}
|
|
33
|
-
data-cy={dataCy}
|
|
34
35
|
on:click|preventDefault
|
|
35
36
|
on:mouseover={() => (showTooltip = true)}
|
|
36
37
|
on:focus={() => (showTooltip = true)}
|
|
@@ -108,7 +109,10 @@
|
|
|
108
109
|
border-color: transparent;
|
|
109
110
|
color: var(--spectrum-global-color-gray-900);
|
|
110
111
|
}
|
|
111
|
-
.spectrum-Button--secondary.new-styles:hover {
|
|
112
|
+
.spectrum-Button--secondary.new-styles:not(.disabled):hover {
|
|
112
113
|
background: var(--spectrum-global-color-gray-300);
|
|
113
114
|
}
|
|
115
|
+
.spectrum-Button--secondary.new-styles.disabled {
|
|
116
|
+
color: var(--spectrum-global-color-gray-500);
|
|
117
|
+
}
|
|
114
118
|
</style>
|
|
@@ -0,0 +1,30 @@
|
|
|
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
|
+
<slot name="icon" />
|
|
18
|
+
<div>
|
|
19
|
+
<slot />
|
|
20
|
+
</div>
|
|
21
|
+
</FancyField>
|
|
22
|
+
|
|
23
|
+
<style>
|
|
24
|
+
img {
|
|
25
|
+
width: 22px;
|
|
26
|
+
}
|
|
27
|
+
div {
|
|
28
|
+
font-size: var(--font-size-l);
|
|
29
|
+
}
|
|
30
|
+
</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>
|