@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.
Files changed (149) hide show
  1. package/LICENSE +375 -0
  2. package/README.md +42 -0
  3. package/dist/bbui.es.js +8 -0
  4. package/dist/bbui.es.js.map +1 -0
  5. package/package.json +94 -0
  6. package/src/Accordion/Accordion.svelte +58 -0
  7. package/src/ActionButton/ActionButton.svelte +132 -0
  8. package/src/ActionGroup/ActionGroup.svelte +26 -0
  9. package/src/ActionMenu/ActionMenu.svelte +43 -0
  10. package/src/Actions/ClickOutside.svench.svx +30 -0
  11. package/src/Actions/PositionDropdown.svench.svx +81 -0
  12. package/src/Actions/autoresize_textarea.js +14 -0
  13. package/src/Actions/click_outside.js +76 -0
  14. package/src/Actions/position_dropdown.js +116 -0
  15. package/src/Avatar/Avatar.svelte +63 -0
  16. package/src/Badge/Badge.svelte +42 -0
  17. package/src/Banner/Banner.svelte +72 -0
  18. package/src/Banner/BannerDisplay.svelte +41 -0
  19. package/src/Button/Button.svelte +118 -0
  20. package/src/Button/Button.svench +138 -0
  21. package/src/ButtonGroup/ButtonGroup.svelte +30 -0
  22. package/src/ClearButton/ClearButton.svelte +19 -0
  23. package/src/ColorPicker/ColorPicker.svelte +304 -0
  24. package/src/DetailSummary/DetailSummary.svelte +92 -0
  25. package/src/Divider/Divider.svelte +28 -0
  26. package/src/Drawer/Drawer.svelte +113 -0
  27. package/src/Drawer/Drawer.svench +42 -0
  28. package/src/Drawer/DrawerContent.svelte +45 -0
  29. package/src/FancyForm/FancyButton.svelte +30 -0
  30. package/src/FancyForm/FancyButtonRadio.svelte +70 -0
  31. package/src/FancyForm/FancyCheckbox.svelte +53 -0
  32. package/src/FancyForm/FancyField.svelte +126 -0
  33. package/src/FancyForm/FancyFieldLabel.svelte +25 -0
  34. package/src/FancyForm/FancyForm.svelte +40 -0
  35. package/src/FancyForm/FancyInput.svelte +109 -0
  36. package/src/FancyForm/FancySelect.svelte +147 -0
  37. package/src/FancyForm/index.js +6 -0
  38. package/src/Form/Checkbox.svelte +23 -0
  39. package/src/Form/Combobox.svelte +45 -0
  40. package/src/Form/Core/Checkbox.svelte +69 -0
  41. package/src/Form/Core/CheckboxGroup.svelte +68 -0
  42. package/src/Form/Core/Combobox.svelte +142 -0
  43. package/src/Form/Core/DatePicker.svelte +265 -0
  44. package/src/Form/Core/Dropzone.svelte +482 -0
  45. package/src/Form/Core/EnvDropdown.svelte +276 -0
  46. package/src/Form/Core/File.svelte +115 -0
  47. package/src/Form/Core/InputDropdown.svelte +235 -0
  48. package/src/Form/Core/Multiselect.svelte +99 -0
  49. package/src/Form/Core/Picker.svelte +314 -0
  50. package/src/Form/Core/PickerDropdown.svelte +431 -0
  51. package/src/Form/Core/RadioGroup.svelte +65 -0
  52. package/src/Form/Core/RichTextField.svelte +42 -0
  53. package/src/Form/Core/Search.svelte +105 -0
  54. package/src/Form/Core/Select.svelte +90 -0
  55. package/src/Form/Core/Slider.svelte +86 -0
  56. package/src/Form/Core/Stepper.svelte +172 -0
  57. package/src/Form/Core/Switch.svelte +35 -0
  58. package/src/Form/Core/TextArea.svelte +78 -0
  59. package/src/Form/Core/TextField.svelte +115 -0
  60. package/src/Form/Core/index.js +16 -0
  61. package/src/Form/DatePicker.svelte +46 -0
  62. package/src/Form/Dropzone.svelte +44 -0
  63. package/src/Form/EnvDropdown.svelte +50 -0
  64. package/src/Form/Field.svelte +42 -0
  65. package/src/Form/FieldLabel.svelte +32 -0
  66. package/src/Form/File.svelte +37 -0
  67. package/src/Form/Input.svelte +45 -0
  68. package/src/Form/InputDropdown.svelte +53 -0
  69. package/src/Form/Multiselect.svelte +49 -0
  70. package/src/Form/PickerDropdown.svelte +131 -0
  71. package/src/Form/RadioGroup.svelte +42 -0
  72. package/src/Form/RichTextField.svelte +36 -0
  73. package/src/Form/Search.svelte +36 -0
  74. package/src/Form/Select.svelte +67 -0
  75. package/src/Form/Slider.svelte +24 -0
  76. package/src/Form/Stepper.svelte +45 -0
  77. package/src/Form/TextArea.svelte +34 -0
  78. package/src/Form/Toggle.svelte +22 -0
  79. package/src/Icon/Icon.svelte +94 -0
  80. package/src/Icon/IconAvatar.svelte +61 -0
  81. package/src/IconPicker/IconPicker.svelte +184 -0
  82. package/src/IconSideNav/IconSideNav.svelte +14 -0
  83. package/src/IconSideNav/IconSideNavItem.svelte +56 -0
  84. package/src/InlineAlert/InlineAlert.svelte +63 -0
  85. package/src/Input/CopyInput.svelte +59 -0
  86. package/src/Label/Label.svelte +31 -0
  87. package/src/Layout/Layout.svelte +94 -0
  88. package/src/Layout/Page.svelte +101 -0
  89. package/src/Link/Link.svelte +27 -0
  90. package/src/List/List.svelte +28 -0
  91. package/src/List/ListItem.svelte +93 -0
  92. package/src/Markdown/MarkdownEditor.svelte +60 -0
  93. package/src/Markdown/MarkdownViewer.svelte +70 -0
  94. package/src/Markdown/SpectrumMDE.svelte +184 -0
  95. package/src/Menu/Item.svelte +94 -0
  96. package/src/Menu/Menu.svelte +7 -0
  97. package/src/Menu/Menu.svench +19 -0
  98. package/src/Menu/Section.svelte +10 -0
  99. package/src/Menu/Separator.svelte +1 -0
  100. package/src/Modal/Content.svelte +6 -0
  101. package/src/Modal/CustomContent.svelte +37 -0
  102. package/src/Modal/Modal.svelte +178 -0
  103. package/src/Modal/Modal.svench +116 -0
  104. package/src/Modal/ModalContent.svelte +190 -0
  105. package/src/Modal/QuizModal.svelte +53 -0
  106. package/src/Notification/Notification.svelte +74 -0
  107. package/src/Notification/NotificationDisplay.svelte +43 -0
  108. package/src/Pagination/Pagination.svelte +57 -0
  109. package/src/Popover/Popover.svelte +95 -0
  110. package/src/Popover/Popover.svench +120 -0
  111. package/src/ProgressBar/ProgressBar.svelte +67 -0
  112. package/src/ProgressCircle/ProgressCircle.svelte +62 -0
  113. package/src/SideNavigation/Item.svelte +59 -0
  114. package/src/SideNavigation/Navigation.svelte +12 -0
  115. package/src/StatusLight/StatusLight.svelte +80 -0
  116. package/src/Stores/Notifications.svench.svx +78 -0
  117. package/src/Stores/banner.js +65 -0
  118. package/src/Stores/notifications.js +84 -0
  119. package/src/Table/ArrayRenderer.svelte +18 -0
  120. package/src/Table/AttachmentRenderer.svelte +73 -0
  121. package/src/Table/BoldRenderer.svelte +15 -0
  122. package/src/Table/BooleanRenderer.svelte +42 -0
  123. package/src/Table/CellRenderer.svelte +70 -0
  124. package/src/Table/CodeRenderer.svelte +14 -0
  125. package/src/Table/DateTimeRenderer.svelte +29 -0
  126. package/src/Table/InternalRenderer.svelte +24 -0
  127. package/src/Table/RelationshipRenderer.svelte +35 -0
  128. package/src/Table/SelectEditRenderer.svelte +28 -0
  129. package/src/Table/StringRenderer.svelte +22 -0
  130. package/src/Table/Table.svelte +657 -0
  131. package/src/Table/index.js +1 -0
  132. package/src/Tabs/Tab.svelte +88 -0
  133. package/src/Tabs/Tabs.svelte +130 -0
  134. package/src/Tags/Tag.svelte +43 -0
  135. package/src/Tags/Tags.svelte +17 -0
  136. package/src/Tooltip/Tooltip.svelte +34 -0
  137. package/src/Tooltip/TooltipWrapper.svelte +60 -0
  138. package/src/TreeView/Item.svelte +41 -0
  139. package/src/TreeView/Tree.svelte +16 -0
  140. package/src/Typography/Body.svelte +22 -0
  141. package/src/Typography/Code.svelte +10 -0
  142. package/src/Typography/Detail.svelte +19 -0
  143. package/src/Typography/Heading.svelte +24 -0
  144. package/src/bbui.css +118 -0
  145. package/src/context.js +4 -0
  146. package/src/helpers.js +116 -0
  147. package/src/index.js +109 -0
  148. package/src/spectrum-icons-rollup.js +31 -0
  149. package/src/spectrum-icons-vite.js +31 -0
@@ -0,0 +1,94 @@
1
+ <script>
2
+ import { createEventDispatcher, getContext } from "svelte"
3
+ import Icon from "../Icon/Icon.svelte"
4
+
5
+ const dispatch = createEventDispatcher()
6
+ const actionMenu = getContext("actionMenu")
7
+
8
+ export let icon = undefined
9
+ export let disabled = undefined
10
+ export let noClose = false
11
+ export let keyBind = undefined
12
+
13
+ $: keys = getKeys(keyBind)
14
+
15
+ const getKeys = keyBind => {
16
+ let keys = keyBind?.split("+") || []
17
+ for (let i = 0; i < keys.length; i++) {
18
+ if (
19
+ keys[i].toLowerCase() === "ctrl" &&
20
+ navigator.platform.startsWith("Mac")
21
+ ) {
22
+ keys[i] = "⌘"
23
+ }
24
+ }
25
+ return keys
26
+ }
27
+
28
+ const onClick = () => {
29
+ if (actionMenu && !noClose) {
30
+ actionMenu.hide()
31
+ }
32
+ dispatch("click")
33
+ }
34
+ </script>
35
+
36
+ <li
37
+ on:click|preventDefault={disabled ? null : onClick}
38
+ class="spectrum-Menu-item"
39
+ class:is-disabled={disabled}
40
+ role="menuitem"
41
+ tabindex="0"
42
+ >
43
+ {#if icon}
44
+ <div class="icon">
45
+ <Icon name={icon} size="S" />
46
+ </div>
47
+ {/if}
48
+ <span class="spectrum-Menu-itemLabel"><slot /></span>
49
+ {#if keys?.length}
50
+ <div class="keys">
51
+ {#each keys as key}
52
+ <div class="key">
53
+ {#if key.startsWith("!")}
54
+ <Icon size="XS" name={key.split("!")[1]} />
55
+ {:else}
56
+ {key}
57
+ {/if}
58
+ </div>
59
+ {/each}
60
+ </div>
61
+ {/if}
62
+ </li>
63
+
64
+ <style>
65
+ .icon {
66
+ align-self: center;
67
+ margin-right: var(--spacing-s);
68
+ }
69
+ .keys {
70
+ margin-left: 30px;
71
+ display: flex;
72
+ flex-direction: row;
73
+ justify-content: flex-end;
74
+ align-items: center;
75
+ gap: 4px;
76
+ }
77
+ .key {
78
+ color: var(--spectrum-global-color-gray-900);
79
+ padding: 2px 4px;
80
+ font-size: 12px;
81
+ font-weight: 600;
82
+ background-color: var(--spectrum-global-color-gray-300);
83
+ border-radius: 4px;
84
+ min-width: 12px;
85
+ height: 16px;
86
+ text-align: center;
87
+ margin: -1px 0;
88
+ display: grid;
89
+ place-items: center;
90
+ }
91
+ .is-disabled .key {
92
+ color: var(--spectrum-global-color-gray-600);
93
+ }
94
+ </style>
@@ -0,0 +1,7 @@
1
+ <script>
2
+ import "@spectrum-css/menu/dist/index-vars.css"
3
+ </script>
4
+
5
+ <ul class="spectrum-Menu" role="menu">
6
+ <slot />
7
+ </ul>
@@ -0,0 +1,19 @@
1
+ <script>
2
+ import Menu from './Menu.svelte'
3
+ import Separator from './Separator.svelte'
4
+ import Section from './Section.svelte'
5
+ import Item from './Item.svelte'
6
+ </script>
7
+
8
+ <Menu>
9
+ <Section heading="Section heading">
10
+ <Item>Some Item 1</Item>
11
+ <Item>Some Item 2</Item>
12
+ <Item>Some Item 3</Item>
13
+ </Section>
14
+ <Separator />
15
+ <Section heading="Section heading">
16
+ <Item icon="SaveFloppy">Save</Item>
17
+ <Item disabled icon="DataDownload">Download</Item>
18
+ </Section>
19
+ </Menu>
@@ -0,0 +1,10 @@
1
+ <script>
2
+ export let heading
3
+ </script>
4
+
5
+ <li role="presentation">
6
+ <span class="spectrum-Menu-sectionHeading">{heading}</span>
7
+ <ul class="spectrum-Menu" role="group">
8
+ <slot />
9
+ </ul>
10
+ </li>
@@ -0,0 +1 @@
1
+ <li class="spectrum-Menu-divider" role="separator" />
@@ -0,0 +1,6 @@
1
+ <script>
2
+ import Input from "../Form/Input.svelte"
3
+ let value = ""
4
+ </script>
5
+
6
+ <Input label="Your Name" bind:value />
@@ -0,0 +1,37 @@
1
+ <script>
2
+ import { getContext } from "svelte"
3
+ import Context from "../context"
4
+
5
+ const { hide } = getContext(Context.Modal)
6
+
7
+ let count = 0
8
+ const clicks = 5
9
+ $: if (count === clicks) hide()
10
+ $: remaining = clicks - count
11
+
12
+ function increment() {
13
+ count++
14
+ }
15
+ </script>
16
+
17
+ <div on:click={increment}>
18
+ Click me
19
+ {remaining}
20
+ more time{remaining === 1 ? "" : "s"}
21
+ to close this modal!
22
+ </div>
23
+
24
+ <style>
25
+ div {
26
+ padding: 40px;
27
+ background-color: var(--purple);
28
+ color: white;
29
+ font-weight: bold;
30
+ text-align: center;
31
+ user-select: none;
32
+ font-size: 20px;
33
+ }
34
+ div:hover {
35
+ cursor: pointer;
36
+ }
37
+ </style>
@@ -0,0 +1,178 @@
1
+ <script>
2
+ import "@spectrum-css/modal/dist/index-vars.css"
3
+ import "@spectrum-css/underlay/dist/index-vars.css"
4
+ import { createEventDispatcher, setContext, tick, onMount } from "svelte"
5
+ import { fade, fly } from "svelte/transition"
6
+ import Portal from "svelte-portal"
7
+ import Context from "../context"
8
+
9
+ export let fixed = false
10
+ export let inline = false
11
+
12
+ const dispatch = createEventDispatcher()
13
+ let visible = fixed || inline
14
+ let modal
15
+
16
+ $: dispatch(visible ? "show" : "hide")
17
+
18
+ export function show() {
19
+ if (visible) {
20
+ return
21
+ }
22
+ visible = true
23
+ }
24
+
25
+ export function hide() {
26
+ if (!visible || fixed || inline) {
27
+ return
28
+ }
29
+ visible = false
30
+ }
31
+
32
+ export function toggle() {
33
+ if (visible) {
34
+ hide()
35
+ } else {
36
+ show()
37
+ }
38
+ }
39
+
40
+ export function cancel() {
41
+ if (!visible) {
42
+ return
43
+ }
44
+ dispatch("cancel")
45
+ hide()
46
+ }
47
+
48
+ function handleKey(e) {
49
+ if (visible && e.key === "Escape") {
50
+ cancel()
51
+ }
52
+ }
53
+
54
+ async function focusModal(node) {
55
+ await tick()
56
+
57
+ // Try to focus first input
58
+ const inputs = node.querySelectorAll("input")
59
+ if (inputs?.length) {
60
+ inputs[0].focus()
61
+ }
62
+
63
+ // Otherwise try to focus confirmation button
64
+ else if (modal) {
65
+ const confirm = modal.querySelector(".confirm-wrap .spectrum-Button")
66
+ if (confirm) {
67
+ confirm.focus()
68
+ }
69
+ }
70
+ }
71
+
72
+ setContext(Context.Modal, { show, hide, toggle, cancel })
73
+
74
+ onMount(() => {
75
+ document.addEventListener("keydown", handleKey)
76
+ return () => {
77
+ document.removeEventListener("keydown", handleKey)
78
+ }
79
+ })
80
+ </script>
81
+
82
+ {#if inline}
83
+ {#if visible}
84
+ <div use:focusModal bind:this={modal} class="spectrum-Modal inline is-open">
85
+ <slot />
86
+ </div>
87
+ {/if}
88
+ {:else}
89
+ <!--
90
+ We cannot conditionally render the portal as this leads to a missing
91
+ insertion point when using nested modals. Therefore we just conditionally
92
+ render the content of the portal.
93
+ It still breaks the modal animation, but its better than soft bricking the
94
+ screen.
95
+ -->
96
+ <Portal target=".modal-container">
97
+ {#if visible}
98
+ <div class="spectrum-Underlay is-open" on:mousedown|self={cancel}>
99
+ <div
100
+ class="background"
101
+ in:fade={{ duration: 200 }}
102
+ out:fade|local={{ duration: 200 }}
103
+ />
104
+ <div class="modal-wrapper" on:mousedown|self={cancel}>
105
+ <div class="modal-inner-wrapper" on:mousedown|self={cancel}>
106
+ <slot name="outside" />
107
+ <div
108
+ use:focusModal
109
+ bind:this={modal}
110
+ class="spectrum-Modal is-open"
111
+ in:fly={{ y: 30, duration: 200 }}
112
+ out:fly|local={{ y: 30, duration: 200 }}
113
+ >
114
+ <slot />
115
+ </div>
116
+ </div>
117
+ </div>
118
+ </div>
119
+ {/if}
120
+ </Portal>
121
+ {/if}
122
+
123
+ <style>
124
+ .spectrum-Underlay {
125
+ display: flex;
126
+ flex-direction: row;
127
+ justify-content: center;
128
+ align-items: center;
129
+ z-index: 999;
130
+ overflow: auto;
131
+ overflow-x: hidden;
132
+ background: transparent;
133
+ }
134
+ .background {
135
+ background: var(--modal-background, rgba(0, 0, 0, 0.75));
136
+ position: fixed;
137
+ top: 0;
138
+ left: 0;
139
+ height: 100vh;
140
+ width: 100vw;
141
+ opacity: 0.65;
142
+ pointer-events: none;
143
+ }
144
+
145
+ .modal-wrapper {
146
+ flex: 1 1 auto;
147
+ display: flex;
148
+ flex-direction: row;
149
+ -moz-box-pack: center;
150
+ justify-content: center;
151
+ align-items: flex-start;
152
+ max-height: 100%;
153
+ }
154
+ .modal-inner-wrapper {
155
+ flex: 1 1 auto;
156
+ display: flex;
157
+ flex-direction: row;
158
+ -moz-box-pack: center;
159
+ justify-content: center;
160
+ align-items: flex-start;
161
+ width: 0;
162
+ position: relative;
163
+ }
164
+
165
+ .spectrum-Modal {
166
+ overflow: visible;
167
+ max-height: none;
168
+ margin: 40px 0;
169
+ transform: none;
170
+ --spectrum-dialog-confirm-border-radius: var(
171
+ --spectrum-global-dimension-size-100
172
+ );
173
+ max-width: 100%;
174
+ }
175
+ :global(.spectrum--lightest .spectrum-Modal.inline) {
176
+ border: var(--border-light);
177
+ }
178
+ </style>
@@ -0,0 +1,116 @@
1
+ <script>
2
+ import { View } from "svench";
3
+ import Modal from "./Modal.svelte";
4
+ import ModalContent from "./ModalContent.svelte";
5
+ import Button from "../Button/Button.svelte";
6
+ import Content from "./Content.svelte";
7
+ import QuizModal from "./QuizModal.svelte";
8
+ import CustomContent from "./CustomContent.svelte";
9
+
10
+ let modal1
11
+ let modal2
12
+ let modal3
13
+
14
+ const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
15
+ async function longTask() {
16
+ await sleep(3000)
17
+ }
18
+ </script>
19
+
20
+ <style>
21
+ p, span {
22
+ font-size: var(--font-size-s);
23
+ }
24
+
25
+ code {
26
+ display: inline-block;
27
+ box-sizing: border-box;
28
+ padding: var(--spacing-xs) var(--spacing-s);
29
+ background-color: var(--grey-2);
30
+ color: var(--red-dark);
31
+ border-radius: var(--spacing-xs);
32
+ }
33
+ </style>
34
+
35
+ <h3>Modals</h3>
36
+ <p>
37
+ Modals provide a means to render content in front of everything else on a page.
38
+ </p>
39
+ <p>
40
+ The modal module in BBUI exposes two
41
+ separate components to provide this functionality; a <code>Modal</code> component to control visibility of content,
42
+ and a <code>ModalContent</code> component to quickly construct the typical content - although this is optional.
43
+ </p>
44
+ <p>
45
+ One of the common problems with modals and popups is stale state reappearing after hiding and showing the content
46
+ again, since the state hasn't been garbage collected if a component controls its own visibility. This is handled for
47
+ you when using the <code>Modal</code> component as it will fully unmount child components, properly resetting state
48
+ every time it appears.
49
+ </p>
50
+
51
+ <br/>
52
+ <p>Use ModalContent to render typical modal content.</p>
53
+ <View name="Simple Confirmation Modal">
54
+ <Button primary on:click={modal1.show}>Delete Record</Button>
55
+ <Modal bind:this={modal1}>
56
+ <ModalContent title="Confirm Deletion" confirmText="Delete">
57
+ <span>Are you sure you want to delete this record?</span>
58
+ </ModalContent>
59
+ </Modal>
60
+ </View>
61
+
62
+ <br/>
63
+ <p>
64
+ Width can be specified as a prop to a <code>Modal</code>. Any additional <code>ModalContent</code> props provided
65
+ will be passed to the confirmation button.
66
+ </p>
67
+ <View name="Different Buttons and Width">
68
+ <Button primary on:click={modal3.show}>Open Modal</Button>
69
+ <Modal bind:this={modal3} width="250px">
70
+ <ModalContent
71
+ title="Confirmation Required"
72
+ showCancelButton={false}
73
+ showCloseIcon={false}
74
+ confirmText="I'm sure!"
75
+ green
76
+ large
77
+ wide
78
+ >
79
+ <span>Are you sure you want to do that?</span>
80
+ </ModalContent>
81
+ </Modal>
82
+ </View>
83
+
84
+ <br/>
85
+ <p>Any content can be rendered inside a <code>Modal</code>. Use context to close the modal from your own components.</p>
86
+ <View name="Custom Content">
87
+ <Button primary on:click={modal1.show}>Open Modal</Button>
88
+ <Modal bind:this={modal1} padding={false} border={false}>
89
+ <CustomContent/>
90
+ </Modal>
91
+ </View>
92
+
93
+ <br/>
94
+ <p>Async functions passed in as the onConfirm prop will make the modal wait until the callback is completed.</p>
95
+ <View name="Async Callbacks">
96
+ <Button primary on:click={modal2.show}>Long Task</Button>
97
+ <Modal bind:this={modal2}>
98
+ <ModalContent
99
+ title="Perform Long Task"
100
+ confirmText="Submit"
101
+ onConfirm={longTask}
102
+ >
103
+ <span>Pressing submit will wait 3 seconds before finishing and disable the confirm button until it's done.</span>
104
+ </ModalContent>
105
+ </Modal>
106
+ </View>
107
+
108
+ <br/>
109
+ <p>Returning false from a onConfirm callback will prevent the modal being closed.</p>
110
+ <View name="Callback Failure Handling">
111
+ <Button primary on:click={modal3.show}>Open Quiz</Button>
112
+ <Modal bind:this={modal3}>
113
+ <QuizModal />
114
+ </Modal>
115
+ </View>
116
+
@@ -0,0 +1,190 @@
1
+ <script>
2
+ import "@spectrum-css/dialog/dist/index-vars.css"
3
+ import { getContext } from "svelte"
4
+ import Button from "../Button/Button.svelte"
5
+ import Divider from "../Divider/Divider.svelte"
6
+ import Icon from "../Icon/Icon.svelte"
7
+ import Context from "../context"
8
+ import ProgressCircle from "../ProgressCircle/ProgressCircle.svelte"
9
+
10
+ export let title = undefined
11
+ export let size = "S"
12
+ export let cancelText = "Cancel"
13
+ export let confirmText = "Confirm"
14
+ export let showCancelButton = true
15
+ export let showConfirmButton = true
16
+ export let showCloseIcon = true
17
+ export let onConfirm = undefined
18
+ export let onCancel = undefined
19
+ export let disabled = false
20
+ export let showDivider = true
21
+
22
+ export let showSecondaryButton = false
23
+ export let secondaryButtonText = undefined
24
+ export let secondaryAction = undefined
25
+ export let secondaryButtonWarning = false
26
+
27
+ const { hide, cancel } = getContext(Context.Modal)
28
+ let loading = false
29
+ $: confirmDisabled = disabled || loading
30
+
31
+ async function secondary(e) {
32
+ loading = true
33
+ if (!secondaryAction || (await secondaryAction(e)) !== false) {
34
+ hide()
35
+ }
36
+ loading = false
37
+ }
38
+
39
+ async function confirm() {
40
+ loading = true
41
+ if (!onConfirm || (await onConfirm()) !== false) {
42
+ hide()
43
+ }
44
+ loading = false
45
+ }
46
+
47
+ async function close() {
48
+ loading = true
49
+ if (!onCancel || (await onCancel()) !== false) {
50
+ cancel()
51
+ }
52
+ loading = false
53
+ }
54
+ </script>
55
+
56
+ <div
57
+ class="spectrum-Dialog"
58
+ class:spectrum-Dialog--small={size === "S"}
59
+ class:spectrum-Dialog--medium={size === "M"}
60
+ class:spectrum-Dialog--large={size === "L"}
61
+ class:spectrum-Dialog--extraLarge={size === "XL"}
62
+ style="position: relative;"
63
+ role="dialog"
64
+ tabindex="-1"
65
+ aria-modal="true"
66
+ >
67
+ <div class="spectrum-Dialog-grid">
68
+ {#if title || $$slots.header}
69
+ <h1
70
+ class="spectrum-Dialog-heading spectrum-Dialog-heading--noHeader"
71
+ class:noDivider={!showDivider}
72
+ class:header-spacing={$$slots.header}
73
+ >
74
+ {#if title}
75
+ {title}
76
+ {:else if $$slots.header}
77
+ <slot name="header" />
78
+ {/if}
79
+ </h1>
80
+ {#if showDivider}
81
+ <Divider />
82
+ {/if}
83
+ {/if}
84
+
85
+ <!-- TODO: Remove content-grid class once Layout components are in bbui -->
86
+ <section class="spectrum-Dialog-content content-grid">
87
+ <slot />
88
+ </section>
89
+ {#if showCancelButton || showConfirmButton || $$slots.footer}
90
+ <div
91
+ class="spectrum-ButtonGroup spectrum-Dialog-buttonGroup spectrum-Dialog-buttonGroup--noFooter"
92
+ >
93
+ <slot name="footer" />
94
+ {#if showSecondaryButton && secondaryButtonText && secondaryAction}
95
+ <div class="secondary-action">
96
+ <Button
97
+ group
98
+ secondary
99
+ warning={secondaryButtonWarning}
100
+ on:click={secondary}>{secondaryButtonText}</Button
101
+ >
102
+ </div>
103
+ {/if}
104
+
105
+ {#if showCancelButton}
106
+ <Button group secondary on:click={close}>
107
+ {cancelText}
108
+ </Button>
109
+ {/if}
110
+ {#if showConfirmButton}
111
+ <span class="confirm-wrap">
112
+ <Button
113
+ group
114
+ cta
115
+ {...$$restProps}
116
+ disabled={confirmDisabled}
117
+ on:click={confirm}
118
+ >
119
+ {#if loading}
120
+ <ProgressCircle overBackground={true} size="S" />
121
+ {/if}
122
+ {#if !loading}
123
+ {confirmText}
124
+ {/if}
125
+ </Button>
126
+ </span>
127
+ {/if}
128
+ </div>
129
+ {/if}
130
+ {#if showCloseIcon}
131
+ <div class="close-icon">
132
+ <Icon hoverable name="Close" on:click={cancel} />
133
+ </div>
134
+ {/if}
135
+ </div>
136
+ </div>
137
+
138
+ <style>
139
+ .spectrum-Dialog--extraLarge {
140
+ width: 1000px;
141
+ }
142
+
143
+ .content-grid {
144
+ display: grid;
145
+ position: relative;
146
+ gap: var(--spacing-xl);
147
+ }
148
+
149
+ .spectrum-Dialog-content {
150
+ overflow: visible;
151
+ }
152
+ .spectrum-Dialog-heading {
153
+ font-family: var(--font-accent);
154
+ font-weight: 600;
155
+ }
156
+ .spectrum-Dialog-heading.noDivider {
157
+ margin-bottom: 12px;
158
+ }
159
+
160
+ .spectrum-Dialog-buttonGroup {
161
+ gap: var(--spectrum-global-dimension-static-size-200);
162
+ }
163
+
164
+ .close-icon {
165
+ position: absolute;
166
+ top: 15px;
167
+ right: 15px;
168
+ font-size: var(--font-size-m);
169
+ }
170
+ .close-icon :global(svg) {
171
+ margin-right: 0;
172
+ }
173
+
174
+ .header-spacing {
175
+ display: flex;
176
+ justify-content: space-between;
177
+ }
178
+
179
+ .secondary-action {
180
+ margin-right: auto;
181
+ }
182
+
183
+ .spectrum-Dialog-buttonGroup {
184
+ padding-left: 0;
185
+ }
186
+
187
+ .confirm-wrap :global(.spectrum-Button-label) {
188
+ display: contents;
189
+ }
190
+ </style>