@budibase/bbui 1.0.0 → 1.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 (128) hide show
  1. package/LICENSE +375 -0
  2. package/README.md +19 -17
  3. package/dist/bbui.es.js +2 -0
  4. package/dist/bbui.es.js.map +1 -0
  5. package/package.json +68 -26
  6. package/src/ActionButton/ActionButton.svelte +83 -0
  7. package/src/ActionGroup/ActionGroup.svelte +26 -0
  8. package/src/ActionMenu/ActionMenu.svelte +43 -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 +66 -0
  14. package/src/Avatar/Avatar.svelte +49 -0
  15. package/src/Badge/Badge.svelte +29 -0
  16. package/src/Button/Button.svelte +52 -0
  17. package/src/Button/Button.svench +138 -0
  18. package/src/ButtonGroup/ButtonGroup.svelte +19 -0
  19. package/src/ClearButton/ClearButton.svelte +19 -0
  20. package/src/ColorPicker/ColorPicker.svelte +292 -0
  21. package/src/DetailSummary/DetailSummary.svelte +83 -0
  22. package/src/Divider/Divider.svelte +25 -0
  23. package/src/Drawer/Drawer.svelte +85 -0
  24. package/src/Drawer/Drawer.svench +42 -0
  25. package/src/Drawer/DrawerContent.svelte +46 -0
  26. package/src/Form/Checkbox.svelte +23 -0
  27. package/src/Form/Combobox.svelte +44 -0
  28. package/src/Form/Core/Checkbox.svelte +67 -0
  29. package/src/Form/Core/Combobox.svelte +156 -0
  30. package/src/Form/Core/DatePicker.svelte +183 -0
  31. package/src/Form/Core/Dropzone.svelte +393 -0
  32. package/src/Form/Core/Multiselect.svelte +88 -0
  33. package/src/Form/Core/Picker.svelte +241 -0
  34. package/src/Form/Core/RadioGroup.svelte +47 -0
  35. package/src/Form/Core/Search.svelte +101 -0
  36. package/src/Form/Core/Select.svelte +81 -0
  37. package/src/Form/Core/Stepper.svelte +172 -0
  38. package/src/Form/Core/Switch.svelte +35 -0
  39. package/src/Form/Core/TextArea.svelte +60 -0
  40. package/src/Form/Core/TextField.svelte +104 -0
  41. package/src/Form/Core/index.js +12 -0
  42. package/src/Form/DatePicker.svelte +33 -0
  43. package/src/Form/Dropzone.svelte +34 -0
  44. package/src/Form/Field.svelte +41 -0
  45. package/src/Form/FieldLabel.svelte +27 -0
  46. package/src/Form/Input.svelte +38 -45
  47. package/src/Form/Multiselect.svelte +39 -0
  48. package/src/Form/RadioGroup.svelte +38 -0
  49. package/src/Form/Search.svelte +32 -0
  50. package/src/Form/Select.svelte +45 -43
  51. package/src/Form/Stepper.svelte +45 -0
  52. package/src/Form/TextArea.svelte +25 -44
  53. package/src/Form/Toggle.svelte +23 -0
  54. package/src/Icon/Icon.svelte +47 -0
  55. package/src/InlineAlert/InlineAlert.svelte +56 -0
  56. package/src/Label/Label.svelte +67 -0
  57. package/src/Layout/Layout.svelte +75 -0
  58. package/src/Layout/Page.svelte +25 -0
  59. package/src/Link/Link.svelte +22 -0
  60. package/src/List/Items/DetailSummary.svench +53 -0
  61. package/src/Menu/Item.svelte +45 -0
  62. package/src/Menu/Menu.svelte +7 -0
  63. package/src/Menu/Menu.svench +19 -0
  64. package/src/Menu/Section.svelte +10 -0
  65. package/src/Menu/Separator.svelte +1 -0
  66. package/src/Modal/Content.svelte +6 -0
  67. package/src/Modal/CustomContent.svelte +38 -0
  68. package/src/Modal/Modal.svelte +133 -0
  69. package/src/Modal/Modal.svench +117 -0
  70. package/src/Modal/ModalContent.svelte +139 -0
  71. package/src/Modal/QuizModal.svelte +54 -0
  72. package/src/Notification/Notification.svelte +20 -0
  73. package/src/Notification/NotificationDisplay.svelte +36 -0
  74. package/src/Pagination/Pagination.svelte +57 -0
  75. package/src/Popover/Popover.svelte +52 -0
  76. package/src/Popover/Popover.svench +121 -0
  77. package/src/ProgressBar/ProgressBar.svelte +54 -0
  78. package/src/ProgressCircle/ProgressCircle.svelte +62 -0
  79. package/src/SideNavigation/Item.svelte +45 -0
  80. package/src/SideNavigation/Navigation.svelte +12 -0
  81. package/src/StatusLight/StatusLight.svelte +41 -0
  82. package/src/Stores/Notifications.svench.svx +78 -0
  83. package/src/Stores/notifications.js +56 -0
  84. package/src/Table/ArrayRenderer.svelte +17 -0
  85. package/src/Table/AttachmentRenderer.svelte +55 -0
  86. package/src/Table/BooleanRenderer.svelte +42 -0
  87. package/src/Table/CellRenderer.svelte +37 -0
  88. package/src/Table/DateTimeRenderer.svelte +13 -0
  89. package/src/Table/InternalRenderer.svelte +28 -0
  90. package/src/Table/RelationshipRenderer.svelte +40 -0
  91. package/src/Table/SelectEditRenderer.svelte +16 -0
  92. package/src/Table/StringRenderer.svelte +13 -0
  93. package/src/Table/Table.svelte +506 -0
  94. package/src/Table/index.js +1 -0
  95. package/src/Tabs/Tab.svelte +66 -0
  96. package/src/Tabs/Tabs.svelte +105 -0
  97. package/src/Tags/Tag.svelte +43 -0
  98. package/src/Tags/Tags.svelte +7 -0
  99. package/src/Tooltip/Tooltip.svelte +24 -0
  100. package/src/TreeView/Item.svelte +41 -0
  101. package/src/TreeView/Tree.svelte +16 -0
  102. package/src/Typography/Body.svelte +19 -0
  103. package/src/Typography/Code.svelte +10 -0
  104. package/src/Typography/Detail.svelte +15 -0
  105. package/src/Typography/Heading.svelte +16 -0
  106. package/src/bbui.css +96 -0
  107. package/src/context.js +3 -0
  108. package/src/index.js +75 -10
  109. package/src/spectrum-icons-rollup.js +31 -0
  110. package/src/spectrum-icons-vite.js +31 -0
  111. package/src/utils/helpers.js +8 -0
  112. package/dist/bundle.css +0 -6
  113. package/dist/bundle.css.map +0 -18
  114. package/dist/index.js +0 -919
  115. package/dist/index.mjs +0 -906
  116. package/src/Branding/Budibase-logo.svelte +0 -68
  117. package/src/Branding/Logo.svelte +0 -16
  118. package/src/Branding/Logo.svench +0 -8
  119. package/src/Form/Button.svelte +0 -52
  120. package/src/Form/Button.svench +0 -26
  121. package/src/Form/Input.svench +0 -8
  122. package/src/Form/Select.svench +0 -8
  123. package/src/Form/TextArea.svench +0 -8
  124. package/src/Links/Home.svelte +0 -49
  125. package/src/Links/Home.svench +0 -19
  126. package/src/actions/autoresize_textarea.js +0 -14
  127. package/src/icons/Contribution.svelte +0 -14
  128. package/src/index.svench.svx +0 -35
@@ -0,0 +1,75 @@
1
+ <script>
2
+ export let horizontal = false
3
+ export let paddingX = "M"
4
+ export let paddingY = "M"
5
+ export let noPadding = false
6
+ export let gap = "M"
7
+ export let noGap = false
8
+ export let alignContent = "normal"
9
+ export let justifyItems = "stretch"
10
+ </script>
11
+
12
+ <div
13
+ style="align-content:{alignContent};justify-items:{justifyItems};"
14
+ class:horizontal
15
+ class="container paddingX-{!noPadding && paddingX} paddingY-{!noPadding &&
16
+ paddingY} gap-{!noGap && gap}"
17
+ >
18
+ <slot />
19
+ </div>
20
+
21
+ <style>
22
+ .container {
23
+ display: grid;
24
+ grid-template-columns: 1fr;
25
+ position: relative;
26
+ }
27
+ .paddingX-S {
28
+ padding-left: var(--spacing-s);
29
+ padding-right: var(--spacing-s);
30
+ }
31
+ .paddingX-M {
32
+ padding-left: var(--spacing-m);
33
+ padding-right: var(--spacing-m);
34
+ }
35
+ .paddingX-L {
36
+ padding-left: var(--spacing-l);
37
+ padding-right: var(--spacing-l);
38
+ }
39
+ .paddingY-S {
40
+ padding-top: var(--spacing-s);
41
+ padding-bottom: var(--spacing-s);
42
+ }
43
+ .paddingY-M {
44
+ padding-top: var(--spacing-m);
45
+ padding-bottom: var(--spacing-m);
46
+ }
47
+ .paddingY-L {
48
+ padding-top: var(--spacing-l);
49
+ padding-bottom: var(--spacing-l);
50
+ }
51
+ .gap-XXS {
52
+ grid-gap: var(--spacing-xs);
53
+ }
54
+ .gap-XS {
55
+ grid-gap: var(--spacing-s);
56
+ }
57
+ .gap-S {
58
+ grid-gap: var(--spectrum-alias-grid-gutter-xsmall);
59
+ }
60
+ .gap-M {
61
+ grid-gap: var(--spectrum-alias-grid-gutter-small);
62
+ }
63
+ .gap-L {
64
+ grid-gap: var(--spectrum-alias-grid-gutter-medium);
65
+ }
66
+ .horizontal.gap-S :global(*) + :global(*) {
67
+ margin-left: var(--spectrum-alias-grid-gutter-xsmall);
68
+ }
69
+ .horizontal.gap-M :global(*) + :global(*) {
70
+ margin-left: var(--spectrum-alias-grid-gutter-small);
71
+ }
72
+ .horizontal.gap-L :global(*) + :global(*) {
73
+ margin-left: var(--spectrum-alias-grid-gutter-medium);
74
+ }
75
+ </style>
@@ -0,0 +1,25 @@
1
+ <script>
2
+ export let wide = false
3
+ </script>
4
+
5
+ <div class:wide>
6
+ <slot />
7
+ </div>
8
+
9
+ <style>
10
+ div {
11
+ display: flex;
12
+ flex-direction: column;
13
+ justify-content: flex-start;
14
+ align-items: stretch;
15
+ max-width: 80ch;
16
+ margin: 0 auto;
17
+ padding: calc(var(--spacing-xl) * 2);
18
+ min-height: calc(100% - var(--spacing-xl) * 4);
19
+ }
20
+
21
+ .wide {
22
+ max-width: none;
23
+ margin: 0;
24
+ }
25
+ </style>
@@ -0,0 +1,22 @@
1
+ <script>
2
+ import "@spectrum-css/link/dist/index-vars.css"
3
+
4
+ export let href = "#"
5
+ export let size = "M"
6
+ export let quiet = false
7
+ export let primary = false
8
+ export let secondary = false
9
+ export let overBackground = false
10
+ export let target
11
+ </script>
12
+
13
+ <a
14
+ on:click
15
+ {href}
16
+ {target}
17
+ class:spectrum-Link--primary={primary}
18
+ class:spectrum-Link--secondary={secondary}
19
+ class:spectrum-Link--overBackground={overBackground}
20
+ class:spectrum-Link--quiet={quiet}
21
+ class="spectrum-Link spectrum-Link--size{size}"><slot /></a
22
+ >
@@ -0,0 +1,53 @@
1
+ <script>
2
+ import { View } from "svench";
3
+ import DetailSummary from "./DetailSummary.svelte";
4
+ </script>
5
+
6
+ <svelte:head>
7
+ <link href="https://cdn.jsdelivr.net/npm/remixicon@2.5.0/fonts/remixicon.css" rel="stylesheet">
8
+ </svelte:head>
9
+
10
+ <style>
11
+ div {
12
+ display: flex;
13
+ flex-direction: column;
14
+ justify-content: flex-start;
15
+ align-items: stretch;
16
+ gap: var(--spacing-m);
17
+ width: 120px;
18
+ }
19
+ </style>
20
+
21
+ <View name="default">
22
+ <div>
23
+ <DetailSummary name="Category 1">
24
+ <span>1</span>
25
+ <span>2</span>
26
+ <span>3</span>
27
+ <span>4</span>
28
+ </DetailSummary>
29
+ <DetailSummary name="Category 2">
30
+ <span>1</span>
31
+ <span>2</span>
32
+ <span>3</span>
33
+ <span>4</span>
34
+ </DetailSummary>
35
+ </div>
36
+ </View>
37
+
38
+ <View name="thin">
39
+ <div>
40
+ <DetailSummary thin name="Category 1">
41
+ <span>1</span>
42
+ <span>2</span>
43
+ <span>3</span>
44
+ <span>4</span>
45
+ </DetailSummary>
46
+ <DetailSummary thin name="Category 2">
47
+ <span>1</span>
48
+ <span>2</span>
49
+ <span>3</span>
50
+ <span>4</span>
51
+ </DetailSummary>
52
+ </div>
53
+ </View>
@@ -0,0 +1,45 @@
1
+ <script>
2
+ import { createEventDispatcher, getContext } from "svelte"
3
+
4
+ const dispatch = createEventDispatcher()
5
+ const actionMenu = getContext("actionMenu")
6
+
7
+ export let dataCy
8
+ export let icon = undefined
9
+ export let disabled = undefined
10
+ export let noClose = false
11
+
12
+ const onClick = () => {
13
+ if (actionMenu && !noClose) {
14
+ actionMenu.hide()
15
+ }
16
+ dispatch("click")
17
+ }
18
+ </script>
19
+
20
+ <li
21
+ data-cy={dataCy}
22
+ on:click|preventDefault={disabled ? null : onClick}
23
+ class="spectrum-Menu-item"
24
+ class:is-disabled={disabled}
25
+ role="menuitem"
26
+ tabindex="0"
27
+ >
28
+ {#if icon}
29
+ <svg
30
+ class="spectrum-Icon spectrum-Icon--sizeS spectrum-Menu-itemIcon"
31
+ focusable="false"
32
+ aria-hidden="true"
33
+ aria-label={icon}
34
+ >
35
+ <use xlink:href="#spectrum-icon-18-{icon}" />
36
+ </svg>
37
+ {/if}
38
+ <span class="spectrum-Menu-itemLabel"><slot /></span>
39
+ </li>
40
+
41
+ <style>
42
+ .spectrum-Menu-itemIcon {
43
+ align-self: center;
44
+ }
45
+ </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,38 @@
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-family: var(--font-sans);
30
+ font-weight: bold;
31
+ text-align: center;
32
+ user-select: none;
33
+ font-size: 20px;
34
+ }
35
+ div:hover {
36
+ cursor: pointer;
37
+ }
38
+ </style>
@@ -0,0 +1,133 @@
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
+ $: dispatch(visible ? "show" : "hide")
15
+
16
+ export function show() {
17
+ if (visible) {
18
+ return
19
+ }
20
+ visible = true
21
+ }
22
+
23
+ export function hide() {
24
+ if (!visible || fixed || inline) {
25
+ return
26
+ }
27
+ visible = false
28
+ }
29
+
30
+ export function cancel() {
31
+ if (!visible) {
32
+ return
33
+ }
34
+ dispatch("cancel")
35
+ hide()
36
+ }
37
+
38
+ function handleKey(e) {
39
+ if (visible && e.key === "Escape") {
40
+ cancel()
41
+ }
42
+ }
43
+
44
+ async function focusFirstInput(node) {
45
+ const inputs = node.querySelectorAll("input")
46
+ if (inputs?.length) {
47
+ await tick()
48
+ inputs[0].focus()
49
+ }
50
+ }
51
+
52
+ setContext(Context.Modal, { show, hide, cancel })
53
+ </script>
54
+
55
+ <svelte:window on:keydown={handleKey} />
56
+
57
+ <!-- These svelte if statements need to be defined like this. -->
58
+ <!-- The modal transitions do not work if nested inside more than one "if" -->
59
+ {#if visible && inline}
60
+ <div use:focusFirstInput class="spectrum-Modal inline is-open">
61
+ <slot />
62
+ </div>
63
+ {:else if visible}
64
+ <Portal target=".modal-container">
65
+ <div
66
+ class="spectrum-Underlay is-open"
67
+ in:fade={{ duration: 200 }}
68
+ out:fade|local={{ duration: 200 }}
69
+ on:mousedown|self={cancel}
70
+ >
71
+ <div class="modal-wrapper" on:mousedown|self={cancel}>
72
+ <div class="modal-inner-wrapper" on:mousedown|self={cancel}>
73
+ <slot name="outside" />
74
+ <div
75
+ use:focusFirstInput
76
+ class="spectrum-Modal is-open"
77
+ in:fly={{ y: 30, duration: 200 }}
78
+ out:fly|local={{ y: 30, duration: 200 }}
79
+ >
80
+ <slot />
81
+ </div>
82
+ </div>
83
+ </div>
84
+ </div>
85
+ </Portal>
86
+ {/if}
87
+
88
+ <style>
89
+ .spectrum-Underlay {
90
+ display: flex;
91
+ flex-direction: row;
92
+ justify-content: center;
93
+ align-items: center;
94
+ z-index: 999;
95
+ overflow: auto;
96
+ overflow-x: hidden;
97
+ background: rgba(0, 0, 0, 0.75);
98
+ }
99
+
100
+ .modal-wrapper {
101
+ flex: 1 1 auto;
102
+ display: flex;
103
+ flex-direction: row;
104
+ -moz-box-pack: center;
105
+ justify-content: center;
106
+ align-items: flex-start;
107
+ max-height: 100%;
108
+ }
109
+ .modal-inner-wrapper {
110
+ flex: 1 1 auto;
111
+ display: flex;
112
+ flex-direction: row;
113
+ -moz-box-pack: center;
114
+ justify-content: center;
115
+ align-items: flex-start;
116
+ width: 0;
117
+ position: relative;
118
+ }
119
+
120
+ .spectrum-Modal {
121
+ overflow: visible;
122
+ max-height: none;
123
+ margin: 40px 0;
124
+ transform: none;
125
+ --spectrum-dialog-confirm-border-radius: var(
126
+ --spectrum-global-dimension-size-100
127
+ );
128
+ max-width: 100%;
129
+ }
130
+ :global(.spectrum--lightest .spectrum-Modal.inline) {
131
+ border: var(--border-light);
132
+ }
133
+ </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,139 @@
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
+
9
+ export let title = undefined
10
+ export let size = "S"
11
+ export let cancelText = "Cancel"
12
+ export let confirmText = "Confirm"
13
+ export let showCancelButton = true
14
+ export let showConfirmButton = true
15
+ export let showCloseIcon = true
16
+ export let onConfirm = undefined
17
+ export let onCancel = undefined
18
+ export let disabled = false
19
+ export let showDivider = true
20
+
21
+ const { hide, cancel } = getContext(Context.Modal)
22
+ let loading = false
23
+ $: confirmDisabled = disabled || loading
24
+
25
+ async function confirm() {
26
+ loading = true
27
+ if (!onConfirm || (await onConfirm()) !== false) {
28
+ hide()
29
+ }
30
+ loading = false
31
+ }
32
+
33
+ async function close() {
34
+ loading = true
35
+ if (!onCancel || (await onCancel()) !== false) {
36
+ cancel()
37
+ }
38
+ loading = false
39
+ }
40
+ </script>
41
+
42
+ <div
43
+ class="spectrum-Dialog"
44
+ class:spectrum-Dialog--small={size === "S"}
45
+ class:spectrum-Dialog--medium={size === "M"}
46
+ class:spectrum-Dialog--large={size === "L"}
47
+ class:spectrum-Dialog--extraLarge={size === "XL"}
48
+ style="position: relative;"
49
+ role="dialog"
50
+ tabindex="-1"
51
+ aria-modal="true"
52
+ >
53
+ <div class="spectrum-Dialog-grid">
54
+ {#if title}
55
+ <h1
56
+ class="spectrum-Dialog-heading spectrum-Dialog-heading--noHeader"
57
+ class:noDivider={!showDivider}
58
+ class:header-spacing={$$slots.header}
59
+ >
60
+ {title}
61
+ <slot name="header" />
62
+ </h1>
63
+ {#if showDivider}
64
+ <Divider size="M" />
65
+ {/if}
66
+ {/if}
67
+ <!-- TODO: Remove content-grid class once Layout components are in bbui -->
68
+ <section class="spectrum-Dialog-content content-grid">
69
+ <slot />
70
+ </section>
71
+ {#if showCancelButton || showConfirmButton}
72
+ <div
73
+ class="spectrum-ButtonGroup spectrum-Dialog-buttonGroup spectrum-Dialog-buttonGroup--noFooter"
74
+ >
75
+ <slot name="footer" />
76
+ {#if showCancelButton}
77
+ <Button group secondary on:click={close}>{cancelText}</Button>
78
+ {/if}
79
+ {#if showConfirmButton}
80
+ <Button
81
+ group
82
+ cta
83
+ {...$$restProps}
84
+ disabled={confirmDisabled}
85
+ on:click={confirm}
86
+ >
87
+ {confirmText}
88
+ </Button>
89
+ {/if}
90
+ </div>
91
+ {/if}
92
+ {#if showCloseIcon}
93
+ <div class="close-icon">
94
+ <Icon hoverable name="Close" on:click={cancel} />
95
+ </div>
96
+ {/if}
97
+ </div>
98
+ </div>
99
+
100
+ <style>
101
+ .spectrum-Dialog--extraLarge {
102
+ width: 1000px;
103
+ }
104
+
105
+ .content-grid {
106
+ display: grid;
107
+ position: relative;
108
+ gap: var(--spacing-xl);
109
+ }
110
+
111
+ .spectrum-Dialog-content {
112
+ overflow: visible;
113
+ }
114
+ .spectrum-Dialog-heading {
115
+ font-family: var(--font-sans);
116
+ }
117
+ .spectrum-Dialog-heading.noDivider {
118
+ margin-bottom: 12px;
119
+ }
120
+
121
+ .spectrum-Dialog-buttonGroup {
122
+ gap: var(--spectrum-global-dimension-static-size-200);
123
+ }
124
+
125
+ .close-icon {
126
+ position: absolute;
127
+ top: 15px;
128
+ right: 15px;
129
+ font-size: var(--font-size-m);
130
+ }
131
+ .close-icon :global(svg) {
132
+ margin-right: 0;
133
+ }
134
+
135
+ .header-spacing {
136
+ display: flex;
137
+ justify-content: space-between;
138
+ }
139
+ </style>