@budibase/bbui 0.0.1
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/LICENSE +375 -0
- package/README.md +42 -0
- package/dist/bbui.es.js +8 -0
- package/dist/bbui.es.js.map +1 -0
- package/package.json +94 -0
- package/src/Accordion/Accordion.svelte +58 -0
- package/src/ActionButton/ActionButton.svelte +132 -0
- package/src/ActionGroup/ActionGroup.svelte +26 -0
- package/src/ActionMenu/ActionMenu.svelte +43 -0
- package/src/Actions/ClickOutside.svench.svx +30 -0
- package/src/Actions/PositionDropdown.svench.svx +81 -0
- package/src/Actions/autoresize_textarea.js +14 -0
- package/src/Actions/click_outside.js +76 -0
- package/src/Actions/position_dropdown.js +116 -0
- package/src/Avatar/Avatar.svelte +63 -0
- package/src/Badge/Badge.svelte +42 -0
- package/src/Banner/Banner.svelte +72 -0
- package/src/Banner/BannerDisplay.svelte +41 -0
- package/src/Button/Button.svelte +118 -0
- package/src/Button/Button.svench +138 -0
- package/src/ButtonGroup/ButtonGroup.svelte +30 -0
- package/src/ClearButton/ClearButton.svelte +19 -0
- package/src/ColorPicker/ColorPicker.svelte +304 -0
- package/src/DetailSummary/DetailSummary.svelte +92 -0
- package/src/Divider/Divider.svelte +28 -0
- package/src/Drawer/Drawer.svelte +113 -0
- package/src/Drawer/Drawer.svench +42 -0
- package/src/Drawer/DrawerContent.svelte +45 -0
- 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 +109 -0
- package/src/FancyForm/FancySelect.svelte +147 -0
- package/src/FancyForm/index.js +6 -0
- package/src/Form/Checkbox.svelte +23 -0
- package/src/Form/Combobox.svelte +45 -0
- package/src/Form/Core/Checkbox.svelte +69 -0
- package/src/Form/Core/CheckboxGroup.svelte +68 -0
- package/src/Form/Core/Combobox.svelte +142 -0
- package/src/Form/Core/DatePicker.svelte +265 -0
- package/src/Form/Core/Dropzone.svelte +482 -0
- package/src/Form/Core/EnvDropdown.svelte +276 -0
- package/src/Form/Core/File.svelte +115 -0
- package/src/Form/Core/InputDropdown.svelte +235 -0
- package/src/Form/Core/Multiselect.svelte +99 -0
- package/src/Form/Core/Picker.svelte +314 -0
- package/src/Form/Core/PickerDropdown.svelte +431 -0
- package/src/Form/Core/RadioGroup.svelte +65 -0
- package/src/Form/Core/RichTextField.svelte +42 -0
- package/src/Form/Core/Search.svelte +105 -0
- package/src/Form/Core/Select.svelte +90 -0
- package/src/Form/Core/Slider.svelte +86 -0
- package/src/Form/Core/Stepper.svelte +172 -0
- package/src/Form/Core/Switch.svelte +35 -0
- package/src/Form/Core/TextArea.svelte +78 -0
- package/src/Form/Core/TextField.svelte +115 -0
- package/src/Form/Core/index.js +16 -0
- package/src/Form/DatePicker.svelte +46 -0
- package/src/Form/Dropzone.svelte +44 -0
- package/src/Form/EnvDropdown.svelte +50 -0
- package/src/Form/Field.svelte +42 -0
- package/src/Form/FieldLabel.svelte +32 -0
- package/src/Form/File.svelte +37 -0
- package/src/Form/Input.svelte +45 -0
- package/src/Form/InputDropdown.svelte +53 -0
- package/src/Form/Multiselect.svelte +49 -0
- package/src/Form/PickerDropdown.svelte +131 -0
- package/src/Form/RadioGroup.svelte +42 -0
- package/src/Form/RichTextField.svelte +36 -0
- package/src/Form/Search.svelte +36 -0
- package/src/Form/Select.svelte +67 -0
- package/src/Form/Slider.svelte +24 -0
- package/src/Form/Stepper.svelte +45 -0
- package/src/Form/TextArea.svelte +34 -0
- package/src/Form/Toggle.svelte +22 -0
- package/src/Icon/Icon.svelte +94 -0
- package/src/Icon/IconAvatar.svelte +61 -0
- package/src/IconPicker/IconPicker.svelte +184 -0
- package/src/IconSideNav/IconSideNav.svelte +14 -0
- package/src/IconSideNav/IconSideNavItem.svelte +56 -0
- package/src/InlineAlert/InlineAlert.svelte +63 -0
- package/src/Input/CopyInput.svelte +59 -0
- package/src/Label/Label.svelte +31 -0
- package/src/Layout/Layout.svelte +94 -0
- package/src/Layout/Page.svelte +101 -0
- package/src/Link/Link.svelte +27 -0
- package/src/List/List.svelte +28 -0
- package/src/List/ListItem.svelte +93 -0
- package/src/Markdown/MarkdownEditor.svelte +60 -0
- package/src/Markdown/MarkdownViewer.svelte +70 -0
- package/src/Markdown/SpectrumMDE.svelte +184 -0
- package/src/Menu/Item.svelte +94 -0
- package/src/Menu/Menu.svelte +7 -0
- package/src/Menu/Menu.svench +19 -0
- package/src/Menu/Section.svelte +10 -0
- package/src/Menu/Separator.svelte +1 -0
- package/src/Modal/Content.svelte +6 -0
- package/src/Modal/CustomContent.svelte +37 -0
- package/src/Modal/Modal.svelte +178 -0
- package/src/Modal/Modal.svench +116 -0
- package/src/Modal/ModalContent.svelte +190 -0
- package/src/Modal/QuizModal.svelte +53 -0
- package/src/Notification/Notification.svelte +74 -0
- package/src/Notification/NotificationDisplay.svelte +43 -0
- package/src/Pagination/Pagination.svelte +57 -0
- package/src/Popover/Popover.svelte +95 -0
- package/src/Popover/Popover.svench +120 -0
- package/src/ProgressBar/ProgressBar.svelte +67 -0
- package/src/ProgressCircle/ProgressCircle.svelte +62 -0
- package/src/SideNavigation/Item.svelte +59 -0
- package/src/SideNavigation/Navigation.svelte +12 -0
- package/src/StatusLight/StatusLight.svelte +80 -0
- package/src/Stores/Notifications.svench.svx +78 -0
- package/src/Stores/banner.js +65 -0
- package/src/Stores/notifications.js +84 -0
- package/src/Table/ArrayRenderer.svelte +18 -0
- package/src/Table/AttachmentRenderer.svelte +73 -0
- package/src/Table/BoldRenderer.svelte +15 -0
- package/src/Table/BooleanRenderer.svelte +42 -0
- package/src/Table/CellRenderer.svelte +70 -0
- package/src/Table/CodeRenderer.svelte +14 -0
- package/src/Table/DateTimeRenderer.svelte +29 -0
- package/src/Table/InternalRenderer.svelte +24 -0
- package/src/Table/RelationshipRenderer.svelte +35 -0
- package/src/Table/SelectEditRenderer.svelte +28 -0
- package/src/Table/StringRenderer.svelte +22 -0
- package/src/Table/Table.svelte +657 -0
- package/src/Table/index.js +1 -0
- package/src/Tabs/Tab.svelte +88 -0
- package/src/Tabs/Tabs.svelte +130 -0
- package/src/Tags/Tag.svelte +43 -0
- package/src/Tags/Tags.svelte +17 -0
- package/src/Tooltip/Tooltip.svelte +34 -0
- package/src/Tooltip/TooltipWrapper.svelte +60 -0
- package/src/TreeView/Item.svelte +41 -0
- package/src/TreeView/Tree.svelte +16 -0
- package/src/Typography/Body.svelte +22 -0
- package/src/Typography/Code.svelte +10 -0
- package/src/Typography/Detail.svelte +19 -0
- package/src/Typography/Heading.svelte +24 -0
- package/src/bbui.css +118 -0
- package/src/context.js +4 -0
- package/src/helpers.js +116 -0
- package/src/index.js +109 -0
- package/src/spectrum-icons-rollup.js +31 -0
- package/src/spectrum-icons-vite.js +31 -0
|
@@ -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,109 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { createEventDispatcher, onMount } 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 ref
|
|
18
|
+
let focused = false
|
|
19
|
+
let autofilled = false
|
|
20
|
+
|
|
21
|
+
$: placeholder = !autofilled && !focused && !value
|
|
22
|
+
|
|
23
|
+
const onChange = e => {
|
|
24
|
+
const newValue = e.target.value
|
|
25
|
+
dispatch("change", newValue)
|
|
26
|
+
value = newValue
|
|
27
|
+
if (validate) {
|
|
28
|
+
error = validate(newValue)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
onMount(() => {
|
|
33
|
+
// Start watching for autofill every 100ms
|
|
34
|
+
const interval = setInterval(() => {
|
|
35
|
+
autofilled = ref?.matches(":-webkit-autofill")
|
|
36
|
+
if (autofilled) {
|
|
37
|
+
clearInterval(interval)
|
|
38
|
+
}
|
|
39
|
+
}, 100)
|
|
40
|
+
|
|
41
|
+
// Give up after 2 seconds and assume autofill has not been used
|
|
42
|
+
const timeout = setTimeout(() => {
|
|
43
|
+
clearInterval(interval)
|
|
44
|
+
}, 2000)
|
|
45
|
+
|
|
46
|
+
// Cleanup
|
|
47
|
+
return () => {
|
|
48
|
+
clearInterval(interval)
|
|
49
|
+
clearTimeout(timeout)
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
</script>
|
|
53
|
+
|
|
54
|
+
<FancyField {error} {value} {validate} {disabled} {focused}>
|
|
55
|
+
{#if label}
|
|
56
|
+
<FancyFieldLabel {placeholder}>{label}</FancyFieldLabel>
|
|
57
|
+
{/if}
|
|
58
|
+
<input
|
|
59
|
+
{disabled}
|
|
60
|
+
value={value || ""}
|
|
61
|
+
type={type || "text"}
|
|
62
|
+
on:input={onChange}
|
|
63
|
+
on:focus={() => (focused = true)}
|
|
64
|
+
on:blur={() => (focused = false)}
|
|
65
|
+
class:placeholder
|
|
66
|
+
bind:this={ref}
|
|
67
|
+
/>
|
|
68
|
+
{#if suffix && !placeholder}
|
|
69
|
+
<div in:fade|local={{ duration: 130 }} class="suffix">{suffix}</div>
|
|
70
|
+
{/if}
|
|
71
|
+
</FancyField>
|
|
72
|
+
|
|
73
|
+
<style>
|
|
74
|
+
input {
|
|
75
|
+
width: 100%;
|
|
76
|
+
transition: transform 130ms ease-out;
|
|
77
|
+
transform: translateY(9px);
|
|
78
|
+
background: transparent;
|
|
79
|
+
font-size: 15px;
|
|
80
|
+
line-height: 17px;
|
|
81
|
+
font-family: var(--font-sans);
|
|
82
|
+
color: var(--spectrum-global-color-gray-900);
|
|
83
|
+
outline: none;
|
|
84
|
+
border: none;
|
|
85
|
+
padding: 0;
|
|
86
|
+
margin: 0;
|
|
87
|
+
}
|
|
88
|
+
input.placeholder {
|
|
89
|
+
transform: translateY(0);
|
|
90
|
+
position: absolute;
|
|
91
|
+
top: 0;
|
|
92
|
+
left: 0;
|
|
93
|
+
height: 100%;
|
|
94
|
+
}
|
|
95
|
+
.suffix {
|
|
96
|
+
color: var(--spectrum-global-color-gray-600);
|
|
97
|
+
transform: translateY(9px);
|
|
98
|
+
font-size: 15px;
|
|
99
|
+
line-height: 17px;
|
|
100
|
+
font-family: var(--font-sans);
|
|
101
|
+
}
|
|
102
|
+
input:-webkit-autofill {
|
|
103
|
+
border-radius: 2px;
|
|
104
|
+
-webkit-box-shadow: 0 0 0 100px var(--spectrum-global-color-gray-300) inset;
|
|
105
|
+
-webkit-text-fill-color: var(--spectrum-global-color-gray-900);
|
|
106
|
+
transition: -webkit-box-shadow 130ms 200ms, background-color 0s 86400s;
|
|
107
|
+
padding: 3px 8px 4px 8px;
|
|
108
|
+
}
|
|
109
|
+
</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"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import Field from "./Field.svelte"
|
|
3
|
+
import Checkbox from "./Core/Checkbox.svelte"
|
|
4
|
+
import { createEventDispatcher } from "svelte"
|
|
5
|
+
|
|
6
|
+
export let value = null
|
|
7
|
+
export let label = null
|
|
8
|
+
export let labelPosition = "above"
|
|
9
|
+
export let text = null
|
|
10
|
+
export let disabled = false
|
|
11
|
+
export let error = null
|
|
12
|
+
export let size = "M"
|
|
13
|
+
|
|
14
|
+
const dispatch = createEventDispatcher()
|
|
15
|
+
const onChange = e => {
|
|
16
|
+
value = e.detail
|
|
17
|
+
dispatch("change", e.detail)
|
|
18
|
+
}
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<Field {label} {labelPosition} {error}>
|
|
22
|
+
<Checkbox {error} {disabled} {text} {value} {size} on:change={onChange} />
|
|
23
|
+
</Field>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import Field from "./Field.svelte"
|
|
3
|
+
import Combobox from "./Core/Combobox.svelte"
|
|
4
|
+
import { createEventDispatcher } from "svelte"
|
|
5
|
+
|
|
6
|
+
export let value = null
|
|
7
|
+
export let label = undefined
|
|
8
|
+
export let disabled = false
|
|
9
|
+
export let readonly = false
|
|
10
|
+
export let labelPosition = "above"
|
|
11
|
+
export let error = null
|
|
12
|
+
export let placeholder = "Choose an option or type"
|
|
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
|
+
const onChange = e => {
|
|
19
|
+
value = e.detail
|
|
20
|
+
dispatch("change", e.detail)
|
|
21
|
+
}
|
|
22
|
+
const extractProperty = (value, property) => {
|
|
23
|
+
if (value && typeof value === "object") {
|
|
24
|
+
return value[property]
|
|
25
|
+
}
|
|
26
|
+
return value
|
|
27
|
+
}
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<Field {label} {labelPosition} {error}>
|
|
31
|
+
<Combobox
|
|
32
|
+
{error}
|
|
33
|
+
{disabled}
|
|
34
|
+
{value}
|
|
35
|
+
{options}
|
|
36
|
+
{placeholder}
|
|
37
|
+
{readonly}
|
|
38
|
+
{getOptionLabel}
|
|
39
|
+
{getOptionValue}
|
|
40
|
+
on:change={onChange}
|
|
41
|
+
on:pick
|
|
42
|
+
on:type
|
|
43
|
+
on:blur
|
|
44
|
+
/>
|
|
45
|
+
</Field>
|