@budibase/bbui 1.4.1 → 1.4.2

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 (154) hide show
  1. package/LICENSE +375 -0
  2. package/README.md +19 -17
  3. package/dist/bbui.es.js +14 -0
  4. package/dist/bbui.es.js.map +1 -0
  5. package/package.json +71 -26
  6. package/src/ActionButton/ActionButton.svelte +102 -0
  7. package/src/ActionGroup/ActionGroup.svelte +26 -0
  8. package/src/ActionMenu/ActionMenu.svelte +44 -0
  9. package/src/Actions/ClickOutside.svench.svx +30 -0
  10. package/src/Actions/PositionDropdown.svench.svx +81 -0
  11. package/src/Actions/autoresize_textarea.js +14 -0
  12. package/src/Actions/click_outside.js +18 -0
  13. package/src/Actions/position_dropdown.js +75 -0
  14. package/src/Avatar/Avatar.svelte +62 -0
  15. package/src/Badge/Badge.svelte +29 -0
  16. package/src/Banner/Banner.svelte +72 -0
  17. package/src/Banner/BannerDisplay.svelte +41 -0
  18. package/src/Button/Button.svelte +114 -0
  19. package/src/Button/Button.svench +138 -0
  20. package/src/ButtonGroup/ButtonGroup.svelte +30 -0
  21. package/src/ClearButton/ClearButton.svelte +19 -0
  22. package/src/ColorPicker/ColorPicker.svelte +297 -0
  23. package/src/DetailSummary/DetailSummary.svelte +83 -0
  24. package/src/Divider/Divider.svelte +28 -0
  25. package/src/Drawer/Drawer.svelte +113 -0
  26. package/src/Drawer/Drawer.svench +42 -0
  27. package/src/Drawer/DrawerContent.svelte +46 -0
  28. package/src/Form/Checkbox.svelte +23 -0
  29. package/src/Form/Combobox.svelte +45 -0
  30. package/src/Form/Core/Checkbox.svelte +69 -0
  31. package/src/Form/Core/CheckboxGroup.svelte +68 -0
  32. package/src/Form/Core/Combobox.svelte +142 -0
  33. package/src/Form/Core/DatePicker.svelte +257 -0
  34. package/src/Form/Core/Dropzone.svelte +450 -0
  35. package/src/Form/Core/InputDropdown.svelte +228 -0
  36. package/src/Form/Core/Multiselect.svelte +90 -0
  37. package/src/Form/Core/Picker.svelte +259 -0
  38. package/src/Form/Core/PickerDropdown.svelte +436 -0
  39. package/src/Form/Core/RadioGroup.svelte +48 -0
  40. package/src/Form/Core/RichTextField.svelte +42 -0
  41. package/src/Form/Core/Search.svelte +105 -0
  42. package/src/Form/Core/Select.svelte +75 -0
  43. package/src/Form/Core/Slider.svelte +86 -0
  44. package/src/Form/Core/Stepper.svelte +172 -0
  45. package/src/Form/Core/Switch.svelte +37 -0
  46. package/src/Form/Core/TextArea.svelte +78 -0
  47. package/src/Form/Core/TextField.svelte +119 -0
  48. package/src/Form/Core/index.js +15 -0
  49. package/src/Form/DatePicker.svelte +39 -0
  50. package/src/Form/Dropzone.svelte +42 -0
  51. package/src/Form/Field.svelte +42 -0
  52. package/src/Form/FieldLabel.svelte +32 -0
  53. package/src/Form/Input.svelte +40 -45
  54. package/src/Form/InputDropdown.svelte +55 -0
  55. package/src/Form/Multiselect.svelte +40 -0
  56. package/src/Form/PickerDropdown.svelte +134 -0
  57. package/src/Form/RadioGroup.svelte +42 -0
  58. package/src/Form/RichTextField.svelte +36 -0
  59. package/src/Form/Search.svelte +36 -0
  60. package/src/Form/Select.svelte +48 -43
  61. package/src/Form/Slider.svelte +24 -0
  62. package/src/Form/Stepper.svelte +45 -0
  63. package/src/Form/TextArea.svelte +29 -44
  64. package/src/Form/Toggle.svelte +23 -0
  65. package/src/Icon/Icon.svelte +91 -0
  66. package/src/IconPicker/IconPicker.svelte +177 -0
  67. package/src/IconSideNav/IconSideNav.svelte +14 -0
  68. package/src/IconSideNav/IconSideNavItem.svelte +56 -0
  69. package/src/InlineAlert/InlineAlert.svelte +60 -0
  70. package/src/Label/Label.svelte +29 -0
  71. package/src/Layout/Layout.svelte +94 -0
  72. package/src/Layout/Page.svelte +32 -0
  73. package/src/Link/Link.svelte +24 -0
  74. package/src/List/List.svelte +28 -0
  75. package/src/List/ListItem.svelte +98 -0
  76. package/src/Markdown/MarkdownEditor.svelte +60 -0
  77. package/src/Markdown/MarkdownViewer.svelte +70 -0
  78. package/src/Markdown/SpectrumMDE.svelte +184 -0
  79. package/src/Menu/Item.svelte +96 -0
  80. package/src/Menu/Menu.svelte +7 -0
  81. package/src/Menu/Menu.svench +19 -0
  82. package/src/Menu/Section.svelte +10 -0
  83. package/src/Menu/Separator.svelte +1 -0
  84. package/src/Modal/Content.svelte +6 -0
  85. package/src/Modal/CustomContent.svelte +38 -0
  86. package/src/Modal/Modal.svelte +165 -0
  87. package/src/Modal/Modal.svench +117 -0
  88. package/src/Modal/ModalContent.svelte +190 -0
  89. package/src/Modal/QuizModal.svelte +54 -0
  90. package/src/Notification/Notification.svelte +70 -0
  91. package/src/Notification/NotificationDisplay.svelte +43 -0
  92. package/src/Pagination/Pagination.svelte +57 -0
  93. package/src/Popover/Popover.svelte +78 -0
  94. package/src/Popover/Popover.svench +121 -0
  95. package/src/ProgressBar/ProgressBar.svelte +67 -0
  96. package/src/ProgressCircle/ProgressCircle.svelte +62 -0
  97. package/src/SideNavigation/Item.svelte +61 -0
  98. package/src/SideNavigation/Navigation.svelte +12 -0
  99. package/src/StatusLight/StatusLight.svelte +80 -0
  100. package/src/Stores/Notifications.svench.svx +78 -0
  101. package/src/Stores/banner.js +65 -0
  102. package/src/Stores/notifications.js +84 -0
  103. package/src/Table/ArrayRenderer.svelte +17 -0
  104. package/src/Table/AttachmentRenderer.svelte +67 -0
  105. package/src/Table/BoldRenderer.svelte +15 -0
  106. package/src/Table/BooleanRenderer.svelte +42 -0
  107. package/src/Table/CellRenderer.svelte +69 -0
  108. package/src/Table/CodeRenderer.svelte +14 -0
  109. package/src/Table/DateTimeRenderer.svelte +29 -0
  110. package/src/Table/InternalRenderer.svelte +24 -0
  111. package/src/Table/RelationshipRenderer.svelte +40 -0
  112. package/src/Table/SelectEditRenderer.svelte +28 -0
  113. package/src/Table/StringRenderer.svelte +14 -0
  114. package/src/Table/Table.svelte +635 -0
  115. package/src/Table/index.js +1 -0
  116. package/src/Tabs/Tab.svelte +88 -0
  117. package/src/Tabs/Tabs.svelte +130 -0
  118. package/src/Tags/Tag.svelte +43 -0
  119. package/src/Tags/Tags.svelte +7 -0
  120. package/src/Tooltip/Tooltip.svelte +34 -0
  121. package/src/Tooltip/TooltipWrapper.svelte +60 -0
  122. package/src/TreeView/Item.svelte +41 -0
  123. package/src/TreeView/Tree.svelte +16 -0
  124. package/src/Typography/Body.svelte +21 -0
  125. package/src/Typography/Code.svelte +10 -0
  126. package/src/Typography/Detail.svelte +19 -0
  127. package/src/Typography/Heading.svelte +17 -0
  128. package/src/bbui.css +96 -0
  129. package/src/context.js +3 -0
  130. package/src/helpers.js +134 -0
  131. package/src/index.js +98 -12
  132. package/src/spectrum-icons-rollup.js +31 -0
  133. package/src/spectrum-icons-vite.js +31 -0
  134. package/dist/bundle.css +0 -8
  135. package/dist/bundle.css.map +0 -22
  136. package/dist/index.js +0 -1275
  137. package/dist/index.mjs +0 -1260
  138. package/src/Branding/Budibase-logo.svelte +0 -68
  139. package/src/Branding/Logo.svelte +0 -16
  140. package/src/Branding/Logo.svench +0 -8
  141. package/src/Form/Button.svelte +0 -131
  142. package/src/Form/Button.svench +0 -49
  143. package/src/Form/Input.svench +0 -8
  144. package/src/Form/Select.svench +0 -8
  145. package/src/Form/TextArea.svench +0 -8
  146. package/src/Links/Home.svelte +0 -49
  147. package/src/Links/Home.svench +0 -19
  148. package/src/List/Items/DetailSummary.svelte +0 -66
  149. package/src/List/Items/DetailSummary.svench +0 -15
  150. package/src/Switcher/Switcher.svelte +0 -39
  151. package/src/Switcher/Switcher.svench +0 -25
  152. package/src/actions/autoresize_textarea.js +0 -14
  153. package/src/icons/Contribution.svelte +0 -14
  154. package/src/index.svench.svx +0 -35
@@ -0,0 +1,165 @@
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 } 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 cancel() {
33
+ if (!visible) {
34
+ return
35
+ }
36
+ dispatch("cancel")
37
+ hide()
38
+ }
39
+
40
+ function handleKey(e) {
41
+ if (visible && e.key === "Escape") {
42
+ cancel()
43
+ }
44
+ }
45
+
46
+ async function focusModal(node) {
47
+ await tick()
48
+
49
+ // Try to focus first input
50
+ const inputs = node.querySelectorAll("input")
51
+ if (inputs?.length) {
52
+ inputs[0].focus()
53
+ }
54
+
55
+ // Otherwise try to focus confirmation button
56
+ else if (modal) {
57
+ const confirm = modal.querySelector(".confirm-wrap .spectrum-Button")
58
+ if (confirm) {
59
+ confirm.focus()
60
+ }
61
+ }
62
+ }
63
+
64
+ setContext(Context.Modal, { show, hide, cancel })
65
+ </script>
66
+
67
+ <svelte:window on:keydown={handleKey} />
68
+
69
+ {#if inline}
70
+ {#if visible}
71
+ <div use:focusModal bind:this={modal} class="spectrum-Modal inline is-open">
72
+ <slot />
73
+ </div>
74
+ {/if}
75
+ {:else}
76
+ <!--
77
+ We cannot conditionally render the portal as this leads to a missing
78
+ insertion point when using nested modals. Therefore we just conditionally
79
+ render the content of the portal.
80
+ It still breaks the modal animation, but its better than soft bricking the
81
+ screen.
82
+ -->
83
+ <Portal target=".modal-container">
84
+ {#if visible}
85
+ <div class="spectrum-Underlay is-open" on:mousedown|self={cancel}>
86
+ <div
87
+ class="background"
88
+ in:fade={{ duration: 200 }}
89
+ out:fade|local={{ duration: 200 }}
90
+ />
91
+ <div class="modal-wrapper" on:mousedown|self={cancel}>
92
+ <div class="modal-inner-wrapper" on:mousedown|self={cancel}>
93
+ <slot name="outside" />
94
+ <div
95
+ use:focusModal
96
+ bind:this={modal}
97
+ class="spectrum-Modal is-open"
98
+ in:fly={{ y: 30, duration: 200 }}
99
+ out:fly|local={{ y: 30, duration: 200 }}
100
+ >
101
+ <slot />
102
+ </div>
103
+ </div>
104
+ </div>
105
+ </div>
106
+ {/if}
107
+ </Portal>
108
+ {/if}
109
+
110
+ <style>
111
+ .spectrum-Underlay {
112
+ display: flex;
113
+ flex-direction: row;
114
+ justify-content: center;
115
+ align-items: center;
116
+ z-index: 999;
117
+ overflow: auto;
118
+ overflow-x: hidden;
119
+ background: transparent;
120
+ }
121
+ .background {
122
+ background: var(--modal-background, rgba(0, 0, 0, 0.75));
123
+ position: fixed;
124
+ top: 0;
125
+ left: 0;
126
+ height: 100vh;
127
+ width: 100vw;
128
+ opacity: 0.65;
129
+ pointer-events: none;
130
+ }
131
+
132
+ .modal-wrapper {
133
+ flex: 1 1 auto;
134
+ display: flex;
135
+ flex-direction: row;
136
+ -moz-box-pack: center;
137
+ justify-content: center;
138
+ align-items: flex-start;
139
+ max-height: 100%;
140
+ }
141
+ .modal-inner-wrapper {
142
+ flex: 1 1 auto;
143
+ display: flex;
144
+ flex-direction: row;
145
+ -moz-box-pack: center;
146
+ justify-content: center;
147
+ align-items: flex-start;
148
+ width: 0;
149
+ position: relative;
150
+ }
151
+
152
+ .spectrum-Modal {
153
+ overflow: visible;
154
+ max-height: none;
155
+ margin: 40px 0;
156
+ transform: none;
157
+ --spectrum-dialog-confirm-border-radius: var(
158
+ --spectrum-global-dimension-size-100
159
+ );
160
+ max-width: 100%;
161
+ }
162
+ :global(.spectrum--lightest .spectrum-Modal.inline) {
163
+ border: var(--border-light);
164
+ }
165
+ </style>
@@ -0,0 +1,117 @@
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-family: var(--font-sans);
23
+ font-size: var(--font-size-s);
24
+ }
25
+
26
+ code {
27
+ display: inline-block;
28
+ box-sizing: border-box;
29
+ padding: var(--spacing-xs) var(--spacing-s);
30
+ background-color: var(--grey-2);
31
+ color: var(--red-dark);
32
+ border-radius: var(--spacing-xs);
33
+ }
34
+ </style>
35
+
36
+ <h3>Modals</h3>
37
+ <p>
38
+ Modals provide a means to render content in front of everything else on a page.
39
+ </p>
40
+ <p>
41
+ The modal module in BBUI exposes two
42
+ separate components to provide this functionality; a <code>Modal</code> component to control visibility of content,
43
+ and a <code>ModalContent</code> component to quickly construct the typical content - although this is optional.
44
+ </p>
45
+ <p>
46
+ One of the common problems with modals and popups is stale state reappearing after hiding and showing the content
47
+ again, since the state hasn't been garbage collected if a component controls its own visibility. This is handled for
48
+ you when using the <code>Modal</code> component as it will fully unmount child components, properly resetting state
49
+ every time it appears.
50
+ </p>
51
+
52
+ <br/>
53
+ <p>Use ModalContent to render typical modal content.</p>
54
+ <View name="Simple Confirmation Modal">
55
+ <Button primary on:click={modal1.show}>Delete Record</Button>
56
+ <Modal bind:this={modal1}>
57
+ <ModalContent title="Confirm Deletion" confirmText="Delete">
58
+ <span>Are you sure you want to delete this record?</span>
59
+ </ModalContent>
60
+ </Modal>
61
+ </View>
62
+
63
+ <br/>
64
+ <p>
65
+ Width can be specified as a prop to a <code>Modal</code>. Any additional <code>ModalContent</code> props provided
66
+ will be passed to the confirmation button.
67
+ </p>
68
+ <View name="Different Buttons and Width">
69
+ <Button primary on:click={modal3.show}>Open Modal</Button>
70
+ <Modal bind:this={modal3} width="250px">
71
+ <ModalContent
72
+ title="Confirmation Required"
73
+ showCancelButton={false}
74
+ showCloseIcon={false}
75
+ confirmText="I'm sure!"
76
+ green
77
+ large
78
+ wide
79
+ >
80
+ <span>Are you sure you want to do that?</span>
81
+ </ModalContent>
82
+ </Modal>
83
+ </View>
84
+
85
+ <br/>
86
+ <p>Any content can be rendered inside a <code>Modal</code>. Use context to close the modal from your own components.</p>
87
+ <View name="Custom Content">
88
+ <Button primary on:click={modal1.show}>Open Modal</Button>
89
+ <Modal bind:this={modal1} padding={false} border={false}>
90
+ <CustomContent/>
91
+ </Modal>
92
+ </View>
93
+
94
+ <br/>
95
+ <p>Async functions passed in as the onConfirm prop will make the modal wait until the callback is completed.</p>
96
+ <View name="Async Callbacks">
97
+ <Button primary on:click={modal2.show}>Long Task</Button>
98
+ <Modal bind:this={modal2}>
99
+ <ModalContent
100
+ title="Perform Long Task"
101
+ confirmText="Submit"
102
+ onConfirm={longTask}
103
+ >
104
+ <span>Pressing submit will wait 3 seconds before finishing and disable the confirm button until it's done.</span>
105
+ </ModalContent>
106
+ </Modal>
107
+ </View>
108
+
109
+ <br/>
110
+ <p>Returning false from a onConfirm callback will prevent the modal being closed.</p>
111
+ <View name="Callback Failure Handling">
112
+ <Button primary on:click={modal3.show}>Open Quiz</Button>
113
+ <Modal bind:this={modal3}>
114
+ <QuizModal />
115
+ </Modal>
116
+ </View>
117
+
@@ -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
+ export let dataCy = null
27
+ const { hide, cancel } = getContext(Context.Modal)
28
+ let loading = false
29
+ $: confirmDisabled = disabled || loading
30
+
31
+ async function secondary() {
32
+ loading = true
33
+ if (!secondaryAction || (await secondaryAction()) !== 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
+ data-cy={dataCy}
67
+ >
68
+ <div class="spectrum-Dialog-grid">
69
+ {#if title || $$slots.header}
70
+ <h1
71
+ class="spectrum-Dialog-heading spectrum-Dialog-heading--noHeader"
72
+ class:noDivider={!showDivider}
73
+ class:header-spacing={$$slots.header}
74
+ >
75
+ {#if title}
76
+ {title}
77
+ {:else if $$slots.header}
78
+ <slot name="header" />
79
+ {/if}
80
+ </h1>
81
+ {#if showDivider}
82
+ <Divider size="M" />
83
+ {/if}
84
+ {/if}
85
+
86
+ <!-- TODO: Remove content-grid class once Layout components are in bbui -->
87
+ <section class="spectrum-Dialog-content content-grid">
88
+ <slot />
89
+ </section>
90
+ {#if showCancelButton || showConfirmButton || $$slots.footer}
91
+ <div
92
+ class="spectrum-ButtonGroup spectrum-Dialog-buttonGroup spectrum-Dialog-buttonGroup--noFooter"
93
+ >
94
+ <slot name="footer" />
95
+ {#if showSecondaryButton && secondaryButtonText && secondaryAction}
96
+ <div class="secondary-action">
97
+ <Button
98
+ group
99
+ secondary
100
+ warning={secondaryButtonWarning}
101
+ on:click={secondary}>{secondaryButtonText}</Button
102
+ >
103
+ </div>
104
+ {/if}
105
+
106
+ {#if showCancelButton}
107
+ <Button group secondary newStyles on:click={close}>
108
+ {cancelText}
109
+ </Button>
110
+ {/if}
111
+ {#if showConfirmButton}
112
+ <span class="confirm-wrap">
113
+ <Button
114
+ group
115
+ cta
116
+ {...$$restProps}
117
+ disabled={confirmDisabled}
118
+ on:click={confirm}
119
+ >
120
+ {#if loading}
121
+ <ProgressCircle overBackground={true} size="S" />
122
+ {/if}
123
+ {#if !loading}
124
+ {confirmText}
125
+ {/if}
126
+ </Button>
127
+ </span>
128
+ {/if}
129
+ </div>
130
+ {/if}
131
+ {#if showCloseIcon}
132
+ <div class="close-icon">
133
+ <Icon hoverable name="Close" on:click={cancel} />
134
+ </div>
135
+ {/if}
136
+ </div>
137
+ </div>
138
+
139
+ <style>
140
+ .spectrum-Dialog--extraLarge {
141
+ width: 1000px;
142
+ }
143
+
144
+ .content-grid {
145
+ display: grid;
146
+ position: relative;
147
+ gap: var(--spacing-xl);
148
+ }
149
+
150
+ .spectrum-Dialog-content {
151
+ overflow: visible;
152
+ }
153
+ .spectrum-Dialog-heading {
154
+ font-family: var(--font-sans);
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>
@@ -0,0 +1,54 @@
1
+ <script>
2
+ import ModalContent from "./ModalContent.svelte"
3
+ import Input from "../Form/Input.svelte"
4
+
5
+ let modal
6
+ let answer
7
+ let error
8
+
9
+ export function show() {
10
+ modal.show()
11
+ }
12
+ export function hide() {
13
+ modal.hide
14
+ }
15
+
16
+ function resetState() {
17
+ answer = undefined
18
+ error = undefined
19
+ }
20
+
21
+ async function answerQuiz() {
22
+ const correct = answer === "8"
23
+ error = !correct
24
+ return correct
25
+ }
26
+ </script>
27
+
28
+ <ModalContent
29
+ title="Quick Maths"
30
+ bind:this={modal}
31
+ confirmText="Submit"
32
+ onConfirm={answerQuiz}
33
+ on:show={resetState}
34
+ >
35
+ {#if error}
36
+ <p class="error">Wrong answer! Try again.</p>
37
+ {/if}
38
+ <p>What is 4 + 4?</p>
39
+ <Input label="Answer" bind:value={answer} />
40
+ </ModalContent>
41
+
42
+ <style>
43
+ p {
44
+ margin: 0;
45
+ font-family: var(--font-sans);
46
+ font-size: var(--font-size-s);
47
+ }
48
+ p.error {
49
+ color: #e26d69;
50
+ background-color: #ffe6e6;
51
+ padding: 8px;
52
+ border-radius: 4px;
53
+ }
54
+ </style>
@@ -0,0 +1,70 @@
1
+ <script>
2
+ import { ActionButton } from "../"
3
+
4
+ import { createEventDispatcher } from "svelte"
5
+
6
+ export let type = "info"
7
+ export let icon = "Info"
8
+ export let message = ""
9
+ export let dismissable = false
10
+ export let actionMessage = null
11
+ export let action = null
12
+ export let wide = false
13
+
14
+ const dispatch = createEventDispatcher()
15
+ </script>
16
+
17
+ <div class="spectrum-Toast spectrum-Toast--{type}" class:wide>
18
+ {#if icon}
19
+ <svg
20
+ class="spectrum-Icon spectrum-Icon--sizeM spectrum-Toast-typeIcon"
21
+ focusable="false"
22
+ aria-hidden="true"
23
+ >
24
+ <use xlink:href="#spectrum-icon-18-{icon}" />
25
+ </svg>
26
+ {/if}
27
+ <div class="spectrum-Toast-body" class:actionBody={!!action}>
28
+ <div class="spectrum-Toast-content">{message || ""}</div>
29
+ {#if action}
30
+ <ActionButton quiet emphasized on:click={action}>
31
+ <div style="color: white; font-weight: 600;">{actionMessage}</div>
32
+ </ActionButton>
33
+ {/if}
34
+ </div>
35
+ {#if dismissable}
36
+ <div class="spectrum-Toast-buttons">
37
+ <button
38
+ class="spectrum-ClearButton spectrum-ClearButton--overBackground spectrum-ClearButton--sizeM"
39
+ on:click={() => dispatch("dismiss")}
40
+ >
41
+ <div class="spectrum-ClearButton-fill">
42
+ <svg
43
+ class="spectrum-ClearButton-icon spectrum-Icon spectrum-UIIcon-Cross100"
44
+ focusable="false"
45
+ aria-hidden="true"
46
+ >
47
+ <use xlink:href="#spectrum-css-icon-Cross100" />
48
+ </svg>
49
+ </div>
50
+ </button>
51
+ </div>
52
+ {/if}
53
+ </div>
54
+
55
+ <style>
56
+ .spectrum-Toast {
57
+ pointer-events: all;
58
+ }
59
+
60
+ .wide {
61
+ width: 100%;
62
+ }
63
+
64
+ .actionBody {
65
+ justify-content: space-between;
66
+ display: flex;
67
+ width: 100%;
68
+ align-items: center;
69
+ }
70
+ </style>
@@ -0,0 +1,43 @@
1
+ <script>
2
+ import "@spectrum-css/toast/dist/index-vars.css"
3
+ import Portal from "svelte-portal"
4
+ import { notifications } from "../Stores/notifications"
5
+ import Notification from "./Notification.svelte"
6
+ import { fly } from "svelte/transition"
7
+ </script>
8
+
9
+ <Portal target=".modal-container">
10
+ <div class="notifications">
11
+ {#each $notifications as { type, icon, message, id, dismissable, action, wide } (id)}
12
+ <div transition:fly={{ y: 30 }}>
13
+ <Notification
14
+ {type}
15
+ {icon}
16
+ {message}
17
+ {dismissable}
18
+ {action}
19
+ {wide}
20
+ on:dismiss={() => notifications.dismiss(id)}
21
+ />
22
+ </div>
23
+ {/each}
24
+ </div>
25
+ </Portal>
26
+
27
+ <style>
28
+ .notifications {
29
+ position: fixed;
30
+ bottom: 40px;
31
+ left: 0;
32
+ right: 0;
33
+ margin: 0 auto;
34
+ padding: 0;
35
+ z-index: 9999;
36
+ display: flex;
37
+ flex-direction: column;
38
+ justify-content: flex-start;
39
+ align-items: center;
40
+ pointer-events: none;
41
+ gap: 10px;
42
+ }
43
+ </style>
@@ -0,0 +1,57 @@
1
+ <script>
2
+ import "@spectrum-css/pagination/dist/index-vars.css"
3
+ import "@spectrum-css/actionbutton/dist/index-vars.css"
4
+ import "@spectrum-css/typography/dist/index-vars.css"
5
+
6
+ export let page
7
+ export let goToPrevPage
8
+ export let goToNextPage
9
+ export let hasPrevPage = true
10
+ export let hasNextPage = true
11
+ </script>
12
+
13
+ <nav class="spectrum-Pagination spectrum-Pagination--explicit">
14
+ <div
15
+ href="#"
16
+ class="spectrum-ActionButton spectrum-ActionButton--sizeM spectrum-ActionButton--quiet spectrum-Pagination-prevButton"
17
+ on:click={hasPrevPage ? goToPrevPage : null}
18
+ class:is-disabled={!hasPrevPage}
19
+ >
20
+ <svg
21
+ class="spectrum-Icon spectrum-UIIcon-ChevronLeft100"
22
+ focusable="false"
23
+ aria-hidden="true"
24
+ aria-label="ChevronLeft"
25
+ >
26
+ <use xlink:href="#spectrum-css-icon-Chevron100" />
27
+ </svg>
28
+ </div>
29
+ <span class="spectrum-Body--secondary spectrum-Pagination-counter">
30
+ Page {page}
31
+ </span>
32
+ <div
33
+ href="#"
34
+ class="spectrum-ActionButton spectrum-ActionButton--sizeM spectrum-ActionButton--quiet spectrum-Pagination-nextButton"
35
+ on:click={hasNextPage ? goToNextPage : null}
36
+ class:is-disabled={!hasNextPage}
37
+ >
38
+ <svg
39
+ class="spectrum-Icon spectrum-UIIcon-ChevronRight100"
40
+ focusable="false"
41
+ aria-hidden="true"
42
+ aria-label="ChevronLeft"
43
+ >
44
+ <use xlink:href="#spectrum-css-icon-Chevron100" />
45
+ </svg>
46
+ </div>
47
+ </nav>
48
+
49
+ <style>
50
+ .spectrum-Pagination-counter {
51
+ margin-left: 0;
52
+ user-select: none;
53
+ }
54
+ .is-disabled:hover {
55
+ cursor: initial;
56
+ }
57
+ </style>