Merge branch 'js-ai-gen' of github.com:budibase/budibase into js-ai-gen
This commit is contained in:
commit
9b4a1b99c8
packages/bbui/src
Form
Icon
IconPicker
IconSideNav
InlineAlert
Input
Label
Layout
List
Markdown
Menu
Modal
Notification
Pagination
ProgressBar
ProgressCircle
Stores
Tooltip
index.ts
|
@ -1,132 +0,0 @@
|
||||||
<script>
|
|
||||||
import Field from "./Field.svelte"
|
|
||||||
import PickerDropdown from "./Core/PickerDropdown.svelte"
|
|
||||||
import { createEventDispatcher } from "svelte"
|
|
||||||
|
|
||||||
export let primaryValue = null
|
|
||||||
export let secondaryValue = null
|
|
||||||
export let inputType = "text"
|
|
||||||
export let label = null
|
|
||||||
export let labelPosition = "above"
|
|
||||||
export let secondaryPlaceholder = null
|
|
||||||
export let autocomplete
|
|
||||||
export let placeholder = null
|
|
||||||
export let disabled = false
|
|
||||||
export let readonly = false
|
|
||||||
export let error = null
|
|
||||||
export let getSecondaryOptionLabel = option =>
|
|
||||||
extractProperty(option, "label")
|
|
||||||
export let getSecondaryOptionValue = option =>
|
|
||||||
extractProperty(option, "value")
|
|
||||||
export let getSecondaryOptionColour = () => {}
|
|
||||||
export let getSecondaryOptionIcon = () => {}
|
|
||||||
export let quiet = false
|
|
||||||
export let autofocus
|
|
||||||
export let primaryOptions = []
|
|
||||||
export let secondaryOptions = []
|
|
||||||
export let searchTerm
|
|
||||||
export let showClearIcon = true
|
|
||||||
export let helpText = null
|
|
||||||
|
|
||||||
let primaryLabel
|
|
||||||
let secondaryLabel
|
|
||||||
const dispatch = createEventDispatcher()
|
|
||||||
|
|
||||||
$: secondaryFieldText = getSecondaryFieldText(
|
|
||||||
secondaryValue,
|
|
||||||
secondaryOptions,
|
|
||||||
secondaryPlaceholder
|
|
||||||
)
|
|
||||||
$: secondaryFieldIcon = getSecondaryFieldAttribute(
|
|
||||||
getSecondaryOptionIcon,
|
|
||||||
secondaryValue,
|
|
||||||
secondaryOptions
|
|
||||||
)
|
|
||||||
$: secondaryFieldColour = getSecondaryFieldAttribute(
|
|
||||||
getSecondaryOptionColour,
|
|
||||||
secondaryValue,
|
|
||||||
secondaryOptions
|
|
||||||
)
|
|
||||||
|
|
||||||
const getSecondaryFieldAttribute = (getAttribute, value, options) => {
|
|
||||||
// Wait for options to load if there is a value but no options
|
|
||||||
|
|
||||||
if (!options?.length) {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
const index = options.findIndex(
|
|
||||||
(option, idx) => getSecondaryOptionValue(option, idx) === value
|
|
||||||
)
|
|
||||||
|
|
||||||
return index !== -1 ? getAttribute(options[index], index) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
const getSecondaryFieldText = (value, options, placeholder) => {
|
|
||||||
// Always use placeholder if no value
|
|
||||||
if (value == null || value === "") {
|
|
||||||
return placeholder || "Choose an option"
|
|
||||||
}
|
|
||||||
|
|
||||||
return getSecondaryFieldAttribute(getSecondaryOptionLabel, value, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
const onPickPrimary = e => {
|
|
||||||
primaryLabel = e?.detail?.label || null
|
|
||||||
primaryValue = e?.detail?.value || null
|
|
||||||
dispatch("pickprimary", e?.detail?.value || {})
|
|
||||||
}
|
|
||||||
|
|
||||||
const onPickSecondary = e => {
|
|
||||||
secondaryValue = e.detail
|
|
||||||
dispatch("picksecondary", e.detail)
|
|
||||||
}
|
|
||||||
|
|
||||||
const extractProperty = (value, property) => {
|
|
||||||
if (value && typeof value === "object") {
|
|
||||||
return value[property]
|
|
||||||
}
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
const updateSearchTerm = e => {
|
|
||||||
searchTerm = e.detail
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<Field {helpText} {label} {labelPosition} {error}>
|
|
||||||
<PickerDropdown
|
|
||||||
{searchTerm}
|
|
||||||
{autocomplete}
|
|
||||||
{error}
|
|
||||||
{disabled}
|
|
||||||
{readonly}
|
|
||||||
{placeholder}
|
|
||||||
{inputType}
|
|
||||||
{quiet}
|
|
||||||
{autofocus}
|
|
||||||
{primaryOptions}
|
|
||||||
{secondaryOptions}
|
|
||||||
{getSecondaryOptionLabel}
|
|
||||||
{getSecondaryOptionValue}
|
|
||||||
{getSecondaryOptionIcon}
|
|
||||||
{getSecondaryOptionColour}
|
|
||||||
{secondaryFieldText}
|
|
||||||
{secondaryFieldIcon}
|
|
||||||
{secondaryFieldColour}
|
|
||||||
{primaryValue}
|
|
||||||
{secondaryValue}
|
|
||||||
{primaryLabel}
|
|
||||||
{secondaryLabel}
|
|
||||||
{showClearIcon}
|
|
||||||
on:pickprimary={onPickPrimary}
|
|
||||||
on:picksecondary={onPickSecondary}
|
|
||||||
on:search={updateSearchTerm}
|
|
||||||
on:click
|
|
||||||
on:input
|
|
||||||
on:blur
|
|
||||||
on:focus
|
|
||||||
on:keyup
|
|
||||||
on:closed
|
|
||||||
/>
|
|
||||||
</Field>
|
|
|
@ -1,16 +1,15 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import Icon from "./Icon.svelte"
|
import Icon from "./Icon.svelte"
|
||||||
|
|
||||||
import Tooltip from "../Tooltip/Tooltip.svelte"
|
import Tooltip from "../Tooltip/Tooltip.svelte"
|
||||||
import { fade } from "svelte/transition"
|
import { fade } from "svelte/transition"
|
||||||
|
|
||||||
export let icon
|
export let icon: string | undefined = undefined
|
||||||
export let background
|
export let background: string | undefined = undefined
|
||||||
export let color
|
export let color: string | undefined = undefined
|
||||||
export let size = "M"
|
export let size: "XS" | "S" | "M" | "L" = "M"
|
||||||
export let tooltip
|
export let tooltip: string | undefined = undefined
|
||||||
|
|
||||||
let showTooltip = false
|
let showTooltip: boolean = false
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
|
|
|
@ -1,19 +1,24 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import "@spectrum-css/popover/dist/index-vars.css"
|
import "@spectrum-css/popover/dist/index-vars.css"
|
||||||
import clickOutside from "../Actions/click_outside"
|
import clickOutside from "../Actions/click_outside"
|
||||||
import { fly } from "svelte/transition"
|
import { fly } from "svelte/transition"
|
||||||
import Icon from "../Icon/Icon.svelte"
|
import Icon from "../Icon/Icon.svelte"
|
||||||
import { createEventDispatcher } from "svelte"
|
import { createEventDispatcher } from "svelte"
|
||||||
|
|
||||||
export let value
|
export let value: string | undefined
|
||||||
export let size = "M"
|
export let size: "S" | "M" | "L" = "M"
|
||||||
export let alignRight = false
|
export let alignRight: boolean = false
|
||||||
|
|
||||||
let open = false
|
let open: boolean = false
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
const iconList = [
|
interface IconCategory {
|
||||||
|
label: string
|
||||||
|
icons: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const iconList: IconCategory[] = [
|
||||||
{
|
{
|
||||||
label: "Icons",
|
label: "Icons",
|
||||||
icons: [
|
icons: [
|
||||||
|
@ -45,12 +50,12 @@
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
const onChange = value => {
|
const onChange = (value: string) => {
|
||||||
dispatch("change", value)
|
dispatch("change", value)
|
||||||
open = false
|
open = false
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleOutsideClick = event => {
|
const handleOutsideClick = (event: MouseEvent) => {
|
||||||
if (open) {
|
if (open) {
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
open = false
|
open = false
|
||||||
|
@ -77,11 +82,11 @@
|
||||||
class="spectrum-Popover spectrum-Popover--bottom spectrum-Picker-popover is-open"
|
class="spectrum-Popover spectrum-Popover--bottom spectrum-Picker-popover is-open"
|
||||||
class:spectrum-Popover--align-right={alignRight}
|
class:spectrum-Popover--align-right={alignRight}
|
||||||
>
|
>
|
||||||
{#each iconList as icon}
|
{#each iconList as iconList}
|
||||||
<div class="category">
|
<div class="category">
|
||||||
<div class="heading">{icon.label}</div>
|
<div class="heading">{iconList.label}</div>
|
||||||
<div class="icons">
|
<div class="icons">
|
||||||
{#each icon.icons as icon}
|
{#each iconList.icons as icon}
|
||||||
<div
|
<div
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
onChange(icon)
|
onChange(icon)
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
<div class="icon-side-nav">
|
|
||||||
<slot />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.icon-side-nav {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
align-items: center;
|
|
||||||
padding: var(--spacing-s);
|
|
||||||
gap: var(--spacing-xs);
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,58 +0,0 @@
|
||||||
<script>
|
|
||||||
import Icon from "../Icon/Icon.svelte"
|
|
||||||
import Tooltip from "../Tooltip/Tooltip.svelte"
|
|
||||||
import { fade } from "svelte/transition"
|
|
||||||
|
|
||||||
export let icon
|
|
||||||
export let active = false
|
|
||||||
export let tooltip
|
|
||||||
|
|
||||||
let showTooltip = false
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
||||||
<div
|
|
||||||
class="icon-side-nav-item"
|
|
||||||
class:active
|
|
||||||
on:mouseover={() => (showTooltip = true)}
|
|
||||||
on:focus={() => (showTooltip = true)}
|
|
||||||
on:mouseleave={() => (showTooltip = false)}
|
|
||||||
on:click
|
|
||||||
>
|
|
||||||
<Icon name={icon} hoverable />
|
|
||||||
{#if tooltip && showTooltip}
|
|
||||||
<div class="tooltip" in:fade={{ duration: 130, delay: 250 }}>
|
|
||||||
<Tooltip textWrapping direction="right" text={tooltip} />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.icon-side-nav-item {
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
display: grid;
|
|
||||||
place-items: center;
|
|
||||||
border-radius: 4px;
|
|
||||||
position: relative;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: background 130ms ease-out;
|
|
||||||
}
|
|
||||||
.icon-side-nav-item:hover :global(svg),
|
|
||||||
.active :global(svg) {
|
|
||||||
color: var(--spectrum-global-color-gray-900);
|
|
||||||
}
|
|
||||||
.active {
|
|
||||||
background: var(--spectrum-global-color-gray-300);
|
|
||||||
}
|
|
||||||
.tooltip {
|
|
||||||
position: absolute;
|
|
||||||
pointer-events: none;
|
|
||||||
left: calc(100% - 4px);
|
|
||||||
top: 50%;
|
|
||||||
white-space: nowrap;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,22 +1,22 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import "@spectrum-css/inlinealert/dist/index-vars.css"
|
import "@spectrum-css/inlinealert/dist/index-vars.css"
|
||||||
import Button from "../Button/Button.svelte"
|
import Button from "../Button/Button.svelte"
|
||||||
import Icon from "../Icon/Icon.svelte"
|
import Icon from "../Icon/Icon.svelte"
|
||||||
|
|
||||||
export let type = "info"
|
export let type: "info" | "error" | "success" | "help" | "negative" = "info"
|
||||||
export let header = ""
|
export let header: string = ""
|
||||||
export let message = ""
|
export let message: string = ""
|
||||||
export let onConfirm = undefined
|
export let onConfirm: (() => void) | undefined = undefined
|
||||||
export let buttonText = ""
|
export let buttonText: string = ""
|
||||||
export let cta = false
|
export let cta: boolean = false
|
||||||
export let link = ""
|
export let link: string = ""
|
||||||
export let linkText = ""
|
export let linkText: string = ""
|
||||||
|
|
||||||
$: icon = selectIcon(type)
|
$: icon = selectIcon(type)
|
||||||
// if newlines used, convert them to different elements
|
// if newlines used, convert them to different elements
|
||||||
$: split = message.split("\n")
|
$: split = message.split("\n")
|
||||||
|
|
||||||
function selectIcon(alertType) {
|
function selectIcon(alertType: string): string {
|
||||||
switch (alertType) {
|
switch (alertType) {
|
||||||
case "error":
|
case "error":
|
||||||
case "negative":
|
case "negative":
|
||||||
|
|
|
@ -1,19 +1,21 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import Input from "../Form/Input.svelte"
|
import Input from "../Form/Input.svelte"
|
||||||
import Icon from "../Icon/Icon.svelte"
|
import Icon from "../Icon/Icon.svelte"
|
||||||
import { notifications } from "../Stores/notifications"
|
import { notifications } from "../Stores/notifications"
|
||||||
|
|
||||||
export let label = null
|
export let label: string | undefined = undefined
|
||||||
export let value
|
export let value: string | undefined = undefined
|
||||||
|
|
||||||
const copyToClipboard = val => {
|
const copyToClipboard = (val: string | undefined) => {
|
||||||
const dummy = document.createElement("textarea")
|
if (val) {
|
||||||
document.body.appendChild(dummy)
|
const dummy = document.createElement("textarea")
|
||||||
dummy.value = val
|
document.body.appendChild(dummy)
|
||||||
dummy.select()
|
dummy.value = val
|
||||||
document.execCommand("copy")
|
dummy.select()
|
||||||
document.body.removeChild(dummy)
|
document.execCommand("copy")
|
||||||
notifications.success(`Copied to clipboard`)
|
document.body.removeChild(dummy)
|
||||||
|
notifications.success(`Copied to clipboard`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import "@spectrum-css/fieldlabel/dist/index-vars.css"
|
import "@spectrum-css/fieldlabel/dist/index-vars.css"
|
||||||
import TooltipWrapper from "../Tooltip/TooltipWrapper.svelte"
|
import TooltipWrapper from "../Tooltip/TooltipWrapper.svelte"
|
||||||
|
|
||||||
export let size = "M"
|
export let size: "S" | "M" | "L" = "M"
|
||||||
export let tooltip = ""
|
export let tooltip: string = ""
|
||||||
export let muted = undefined
|
export let muted: boolean | undefined = undefined
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<TooltipWrapper {tooltip} {size}>
|
<TooltipWrapper {tooltip} {size}>
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
export let horizontal = false
|
export let horizontal: boolean = false
|
||||||
export let paddingX = "M"
|
export let paddingX: "S" | "M" | "L" | "XL" | "XXL" = "M"
|
||||||
export let paddingY = "M"
|
export let paddingY: "S" | "M" | "L" | "XL" | "XXL" = "M"
|
||||||
export let noPadding = false
|
export let noPadding: boolean = false
|
||||||
export let gap = "M"
|
export let gap: "XXS" | "XS" | "S" | "M" | "L" | "XL" = "M"
|
||||||
export let noGap = false
|
export let noGap: boolean = false
|
||||||
export let alignContent = "normal"
|
export let alignContent:
|
||||||
export let justifyItems = "stretch"
|
| "start"
|
||||||
|
| "center"
|
||||||
|
| "space-between"
|
||||||
|
| "space-around"
|
||||||
|
| "normal" = "normal"
|
||||||
|
export let justifyItems: "stretch" | "start" | "center" | "end" = "stretch"
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import { setContext } from "svelte"
|
import { setContext } from "svelte"
|
||||||
import clickOutside from "../Actions/click_outside"
|
import clickOutside from "../Actions/click_outside"
|
||||||
|
|
||||||
export let wide = false
|
export let wide: boolean = false
|
||||||
export let narrow = false
|
export let narrow: boolean = false
|
||||||
export let narrower = false
|
export let narrower: boolean = false
|
||||||
export let noPadding = false
|
export let noPadding: boolean = false
|
||||||
|
|
||||||
let sidePanelVisible = false
|
let sidePanelVisible: boolean = false
|
||||||
|
|
||||||
setContext("side-panel", {
|
setContext("side-panel", {
|
||||||
open: () => (sidePanelVisible = true),
|
open: () => (sidePanelVisible = true),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import Detail from "../Typography/Detail.svelte"
|
import Detail from "../Typography/Detail.svelte"
|
||||||
|
|
||||||
export let title = null
|
export let title: string | null = null
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import SpectrumMDE from "./SpectrumMDE.svelte"
|
import SpectrumMDE from "./SpectrumMDE.svelte"
|
||||||
import { createEventDispatcher } from "svelte"
|
import { createEventDispatcher } from "svelte"
|
||||||
|
|
||||||
export let value = null
|
export let value: string | null = null
|
||||||
export let height = null
|
export let height: string | null = null
|
||||||
export let placeholder = null
|
export let placeholder: string | null = null
|
||||||
export let id = null
|
export let id: string | null = null
|
||||||
export let fullScreenOffset = 0
|
export let fullScreenOffset: { x: string; y: string } | null = null
|
||||||
export let disabled = false
|
export let disabled: boolean = false
|
||||||
export let readonly = false
|
export let readonly: boolean = false
|
||||||
export let easyMDEOptions
|
export let easyMDEOptions: Record<string, any> = {}
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
let latestValue
|
let latestValue: string | null
|
||||||
let mde
|
let mde: any
|
||||||
|
|
||||||
// Ensure the value is updated if the value prop changes outside the editor's
|
// Ensure the value is updated if the value prop changes outside the editor's
|
||||||
// control
|
// control
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
mde?.togglePreview()
|
mde?.togglePreview()
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkValue = val => {
|
const checkValue = (val: string | null) => {
|
||||||
if (mde && val !== latestValue) {
|
if (mde && val !== latestValue) {
|
||||||
mde.value(val)
|
mde.value(val)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import SpectrumMDE from "./SpectrumMDE.svelte"
|
import SpectrumMDE from "./SpectrumMDE.svelte"
|
||||||
|
|
||||||
export let value
|
export let value: string | null = null
|
||||||
export let height
|
export let height: string | null = null
|
||||||
|
|
||||||
let mde
|
let mde: any
|
||||||
|
|
||||||
// Keep the value up to date
|
// Keep the value up to date
|
||||||
$: mde && mde.value(value || "")
|
$: mde && mde.value(value || "")
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import EasyMDE from "easymde"
|
import EasyMDE from "easymde"
|
||||||
import "easymde/dist/easymde.min.css"
|
import "easymde/dist/easymde.min.css"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
|
|
||||||
export let height = null
|
export let height: string | null = null
|
||||||
export let scroll = true
|
export let scroll: boolean = true
|
||||||
export let easyMDEOptions = null
|
export let easyMDEOptions: Record<string, any> | null = null
|
||||||
export let mde = null
|
export let mde: EasyMDE | null = null
|
||||||
export let id = null
|
export let id: string | null = null
|
||||||
export let fullScreenOffset = null
|
export let fullScreenOffset: { x: string; y: string } | null = null
|
||||||
export let disabled = false
|
export let disabled: boolean = false
|
||||||
|
|
||||||
let element
|
let element: HTMLTextAreaElement | undefined = undefined
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
height = height || "200px"
|
height = height || "200px"
|
||||||
|
@ -27,13 +27,13 @@
|
||||||
|
|
||||||
// Revert the editor when we unmount
|
// Revert the editor when we unmount
|
||||||
return () => {
|
return () => {
|
||||||
mde.toTextArea()
|
mde?.toTextArea()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
$: styleString = getStyleString(fullScreenOffset)
|
$: styleString = getStyleString(fullScreenOffset)
|
||||||
|
|
||||||
const getStyleString = offset => {
|
const getStyleString = (offset: { x?: string; y?: string } | null) => {
|
||||||
let string = ""
|
let string = ""
|
||||||
string += `--fullscreen-offset-x:${offset?.x || "0px"};`
|
string += `--fullscreen-offset-x:${offset?.x || "0px"};`
|
||||||
string += `--fullscreen-offset-y:${offset?.y || "0px"};`
|
string += `--fullscreen-offset-y:${offset?.y || "0px"};`
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import { createEventDispatcher, getContext } from "svelte"
|
import { createEventDispatcher, getContext } from "svelte"
|
||||||
import Icon from "../Icon/Icon.svelte"
|
import Icon from "../Icon/Icon.svelte"
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
const actionMenu = getContext("actionMenu")
|
const actionMenu = getContext("actionMenu") as { hideAll: () => void }
|
||||||
|
|
||||||
export let icon = undefined
|
export let icon: string | undefined = undefined
|
||||||
export let disabled = undefined
|
export let disabled: boolean | undefined = undefined
|
||||||
export let noClose = false
|
export let noClose: boolean = false
|
||||||
export let keyBind = undefined
|
export let keyBind: string | undefined = undefined
|
||||||
|
|
||||||
$: keys = getKeys(keyBind)
|
$: keys = getKeys(keyBind)
|
||||||
|
|
||||||
const getKeys = keyBind => {
|
const getKeys = (keyBind: string | undefined): string[] => {
|
||||||
let keys = keyBind?.split("+") || []
|
let keys = keyBind?.split("+") || []
|
||||||
for (let i = 0; i < keys.length; i++) {
|
for (let i = 0; i < keys.length; i++) {
|
||||||
if (
|
if (
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import "@spectrum-css/menu/dist/index-vars.css"
|
import "@spectrum-css/menu/dist/index-vars.css"
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
<script>
|
|
||||||
import Menu from './Menu.svelte'
|
|
||||||
import Separator from './Separator.svelte'
|
|
||||||
import Section from './Section.svelte'
|
|
||||||
import Item from './Item.svelte'
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<Menu>
|
|
||||||
<Section heading="Section heading">
|
|
||||||
<Item>Some Item 1</Item>
|
|
||||||
<Item>Some Item 2</Item>
|
|
||||||
<Item>Some Item 3</Item>
|
|
||||||
</Section>
|
|
||||||
<Separator />
|
|
||||||
<Section heading="Section heading">
|
|
||||||
<Item icon="SaveFloppy">Save</Item>
|
|
||||||
<Item disabled icon="DataDownload">Download</Item>
|
|
||||||
</Section>
|
|
||||||
</Menu>
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
export let heading
|
export let heading: string
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<li role="presentation">
|
<li role="presentation">
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import Input from "../Form/Input.svelte"
|
import Input from "../Form/Input.svelte"
|
||||||
|
|
||||||
let value = ""
|
let value: string = ""
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Input label="Your Name" bind:value />
|
<Input label="Your Name" bind:value />
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import { getContext } from "svelte"
|
import { getContext } from "svelte"
|
||||||
import Context from "../context"
|
import Context from "../context"
|
||||||
|
|
||||||
const { hide } = getContext(Context.Modal)
|
const { hide } = getContext(Context.Modal) as { hide: () => void }
|
||||||
|
|
||||||
let count = 0
|
let count: number = 0
|
||||||
const clicks = 5
|
const clicks: number = 5
|
||||||
$: if (count === clicks) hide()
|
$: if (count === clicks) hide()
|
||||||
$: remaining = clicks - count
|
$: remaining = clicks - count
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import "@spectrum-css/modal/dist/index-vars.css"
|
import "@spectrum-css/modal/dist/index-vars.css"
|
||||||
import "@spectrum-css/underlay/dist/index-vars.css"
|
import "@spectrum-css/underlay/dist/index-vars.css"
|
||||||
import { createEventDispatcher, setContext, tick, onMount } from "svelte"
|
import { createEventDispatcher, setContext, tick, onMount } from "svelte"
|
||||||
|
@ -6,33 +6,37 @@
|
||||||
import Portal from "svelte-portal"
|
import Portal from "svelte-portal"
|
||||||
import Context from "../context"
|
import Context from "../context"
|
||||||
|
|
||||||
export let fixed = false
|
export let fixed: boolean = false
|
||||||
export let inline = false
|
export let inline: boolean = false
|
||||||
export let disableCancel = false
|
export let disableCancel: boolean = false
|
||||||
export let autoFocus = true
|
export let autoFocus: boolean = true
|
||||||
export let zIndex = 1001
|
export let zIndex: number = 1001
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher<{
|
||||||
let visible = fixed || inline
|
show: void
|
||||||
let modal
|
hide: void
|
||||||
|
cancel: void
|
||||||
|
}>()
|
||||||
|
let visible: boolean = fixed || inline
|
||||||
|
let modal: HTMLElement | undefined
|
||||||
|
|
||||||
$: dispatch(visible ? "show" : "hide")
|
$: dispatch(visible ? "show" : "hide")
|
||||||
|
|
||||||
export function show() {
|
export function show(): void {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
visible = true
|
visible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hide() {
|
export function hide(): void {
|
||||||
if (!visible || fixed || inline) {
|
if (!visible || fixed || inline) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
visible = false
|
visible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toggle() {
|
export function toggle(): void {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
hide()
|
hide()
|
||||||
} else {
|
} else {
|
||||||
|
@ -40,7 +44,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function cancel() {
|
export function cancel(): void {
|
||||||
if (!visible || disableCancel) {
|
if (!visible || disableCancel) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -48,34 +52,33 @@
|
||||||
hide()
|
hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleKey(e) {
|
function handleKey(e: KeyboardEvent): void {
|
||||||
if (visible && e.key === "Escape") {
|
if (visible && e.key === "Escape") {
|
||||||
cancel()
|
cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function focusModal(node) {
|
function focusModal(node: HTMLElement): void {
|
||||||
if (!autoFocus) {
|
if (!autoFocus) return
|
||||||
return
|
tick().then(() => {
|
||||||
}
|
const inputs = node.querySelectorAll("input")
|
||||||
await tick()
|
if (inputs?.length) {
|
||||||
|
inputs[0].focus()
|
||||||
// Try to focus first input
|
} else if (modal) {
|
||||||
const inputs = node.querySelectorAll("input")
|
const confirm = modal.querySelector(".confirm-wrap .spectrum-Button")
|
||||||
if (inputs?.length) {
|
if (confirm) {
|
||||||
inputs[0].focus()
|
;(confirm as HTMLElement).focus()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise try to focus confirmation button
|
|
||||||
else if (modal) {
|
|
||||||
const confirm = modal.querySelector(".confirm-wrap .spectrum-Button")
|
|
||||||
if (confirm) {
|
|
||||||
confirm.focus()
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
setContext(Context.Modal, { show, hide, toggle, cancel })
|
setContext(Context.Modal, {
|
||||||
|
show,
|
||||||
|
hide,
|
||||||
|
toggle,
|
||||||
|
cancel,
|
||||||
|
} as { show: () => void; hide: () => void; toggle: () => void; cancel: () => void })
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
document.addEventListener("keydown", handleKey)
|
document.addEventListener("keydown", handleKey)
|
||||||
|
|
|
@ -1,116 +0,0 @@
|
||||||
<script>
|
|
||||||
import { View } from "svench";
|
|
||||||
import Modal from "./Modal.svelte";
|
|
||||||
import ModalContent from "./ModalContent.svelte";
|
|
||||||
import Button from "../Button/Button.svelte";
|
|
||||||
import Content from "./Content.svelte";
|
|
||||||
import QuizModal from "./QuizModal.svelte";
|
|
||||||
import CustomContent from "./CustomContent.svelte";
|
|
||||||
|
|
||||||
let modal1
|
|
||||||
let modal2
|
|
||||||
let modal3
|
|
||||||
|
|
||||||
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
|
|
||||||
async function longTask() {
|
|
||||||
await sleep(3000)
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
p, span {
|
|
||||||
font-size: var(--font-size-s);
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
display: inline-block;
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: var(--spacing-xs) var(--spacing-s);
|
|
||||||
background-color: var(--grey-2);
|
|
||||||
color: var(--red-dark);
|
|
||||||
border-radius: var(--spacing-xs);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<h3>Modals</h3>
|
|
||||||
<p>
|
|
||||||
Modals provide a means to render content in front of everything else on a page.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
The modal module in BBUI exposes two
|
|
||||||
separate components to provide this functionality; a <code>Modal</code> component to control visibility of content,
|
|
||||||
and a <code>ModalContent</code> component to quickly construct the typical content - although this is optional.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
One of the common problems with modals and popups is stale state reappearing after hiding and showing the content
|
|
||||||
again, since the state hasn't been garbage collected if a component controls its own visibility. This is handled for
|
|
||||||
you when using the <code>Modal</code> component as it will fully unmount child components, properly resetting state
|
|
||||||
every time it appears.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
<p>Use ModalContent to render typical modal content.</p>
|
|
||||||
<View name="Simple Confirmation Modal">
|
|
||||||
<Button primary on:click={modal1.show}>Delete Record</Button>
|
|
||||||
<Modal bind:this={modal1}>
|
|
||||||
<ModalContent title="Confirm Deletion" confirmText="Delete">
|
|
||||||
<span>Are you sure you want to delete this record?</span>
|
|
||||||
</ModalContent>
|
|
||||||
</Modal>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
<p>
|
|
||||||
Width can be specified as a prop to a <code>Modal</code>. Any additional <code>ModalContent</code> props provided
|
|
||||||
will be passed to the confirmation button.
|
|
||||||
</p>
|
|
||||||
<View name="Different Buttons and Width">
|
|
||||||
<Button primary on:click={modal3.show}>Open Modal</Button>
|
|
||||||
<Modal bind:this={modal3} width="250px">
|
|
||||||
<ModalContent
|
|
||||||
title="Confirmation Required"
|
|
||||||
showCancelButton={false}
|
|
||||||
showCloseIcon={false}
|
|
||||||
confirmText="I'm sure!"
|
|
||||||
green
|
|
||||||
large
|
|
||||||
wide
|
|
||||||
>
|
|
||||||
<span>Are you sure you want to do that?</span>
|
|
||||||
</ModalContent>
|
|
||||||
</Modal>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
<p>Any content can be rendered inside a <code>Modal</code>. Use context to close the modal from your own components.</p>
|
|
||||||
<View name="Custom Content">
|
|
||||||
<Button primary on:click={modal1.show}>Open Modal</Button>
|
|
||||||
<Modal bind:this={modal1} padding={false} border={false}>
|
|
||||||
<CustomContent/>
|
|
||||||
</Modal>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
<p>Async functions passed in as the onConfirm prop will make the modal wait until the callback is completed.</p>
|
|
||||||
<View name="Async Callbacks">
|
|
||||||
<Button primary on:click={modal2.show}>Long Task</Button>
|
|
||||||
<Modal bind:this={modal2}>
|
|
||||||
<ModalContent
|
|
||||||
title="Perform Long Task"
|
|
||||||
confirmText="Submit"
|
|
||||||
onConfirm={longTask}
|
|
||||||
>
|
|
||||||
<span>Pressing submit will wait 3 seconds before finishing and disable the confirm button until it's done.</span>
|
|
||||||
</ModalContent>
|
|
||||||
</Modal>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
<p>Returning false from a onConfirm callback will prevent the modal being closed.</p>
|
|
||||||
<View name="Callback Failure Handling">
|
|
||||||
<Button primary on:click={modal3.show}>Open Quiz</Button>
|
|
||||||
<Modal bind:this={modal3}>
|
|
||||||
<QuizModal />
|
|
||||||
</Modal>
|
|
||||||
</View>
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<script context="module">
|
<script context="module" lang="ts">
|
||||||
export const keepOpen = Symbol("keepOpen")
|
export const keepOpen = Symbol("keepOpen")
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script>
|
<script lang="ts">
|
||||||
import "@spectrum-css/dialog/dist/index-vars.css"
|
import "@spectrum-css/dialog/dist/index-vars.css"
|
||||||
import { getContext } from "svelte"
|
import { getContext } from "svelte"
|
||||||
import Button from "../Button/Button.svelte"
|
import Button from "../Button/Button.svelte"
|
||||||
|
@ -11,31 +11,36 @@
|
||||||
import Context from "../context"
|
import Context from "../context"
|
||||||
import ProgressCircle from "../ProgressCircle/ProgressCircle.svelte"
|
import ProgressCircle from "../ProgressCircle/ProgressCircle.svelte"
|
||||||
|
|
||||||
export let title = undefined
|
export let title: string | undefined = undefined
|
||||||
export let size = "S"
|
export let size: "S" | "M" | "L" | "XL" = "S"
|
||||||
export let cancelText = "Cancel"
|
export let cancelText: string = "Cancel"
|
||||||
export let confirmText = "Confirm"
|
export let confirmText: string = "Confirm"
|
||||||
export let showCancelButton = true
|
export let showCancelButton: boolean = true
|
||||||
export let showConfirmButton = true
|
export let showConfirmButton: boolean = true
|
||||||
export let showCloseIcon = true
|
export let showCloseIcon: boolean = true
|
||||||
export let onConfirm = undefined
|
export let onConfirm: (() => Promise<any> | any) | undefined = undefined
|
||||||
export let onCancel = undefined
|
export let onCancel: (() => Promise<any> | any) | undefined = undefined
|
||||||
export let disabled = false
|
export let disabled: boolean = false
|
||||||
export let showDivider = true
|
export let showDivider: boolean = true
|
||||||
|
|
||||||
export let showSecondaryButton = false
|
export let showSecondaryButton: boolean = false
|
||||||
export let secondaryButtonText = undefined
|
export let secondaryButtonText: string | undefined = undefined
|
||||||
export let secondaryAction = undefined
|
export let secondaryAction: ((_e: Event) => Promise<any> | any) | undefined =
|
||||||
export let secondaryButtonWarning = false
|
undefined
|
||||||
export let custom = false
|
export let secondaryButtonWarning: boolean = false
|
||||||
|
export let custom: boolean = false
|
||||||
|
|
||||||
const { hide, cancel } = getContext(Context.Modal)
|
const { hide, cancel } = getContext(Context.Modal) as {
|
||||||
|
hide: () => void
|
||||||
|
cancel: () => void
|
||||||
|
}
|
||||||
|
|
||||||
let loading = false
|
let loading: boolean = false
|
||||||
|
|
||||||
|
let confirmDisabled: boolean
|
||||||
$: confirmDisabled = disabled || loading
|
$: confirmDisabled = disabled || loading
|
||||||
|
|
||||||
async function secondary(e) {
|
async function secondary(e: Event): Promise<void> {
|
||||||
loading = true
|
loading = true
|
||||||
if (!secondaryAction || (await secondaryAction(e)) !== keepOpen) {
|
if (!secondaryAction || (await secondaryAction(e)) !== keepOpen) {
|
||||||
hide()
|
hide()
|
||||||
|
@ -43,7 +48,7 @@
|
||||||
loading = false
|
loading = false
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function confirm() {
|
export async function confirm(): Promise<void> {
|
||||||
loading = true
|
loading = true
|
||||||
if (!onConfirm || (await onConfirm()) !== keepOpen) {
|
if (!onConfirm || (await onConfirm()) !== keepOpen) {
|
||||||
hide()
|
hide()
|
||||||
|
@ -51,7 +56,7 @@
|
||||||
loading = false
|
loading = false
|
||||||
}
|
}
|
||||||
|
|
||||||
async function close() {
|
async function close(): Promise<void> {
|
||||||
loading = true
|
loading = true
|
||||||
if (!onCancel || (await onCancel()) !== keepOpen) {
|
if (!onCancel || (await onCancel()) !== keepOpen) {
|
||||||
cancel()
|
cancel()
|
||||||
|
@ -90,7 +95,6 @@
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<!-- TODO: Remove content-grid class once Layout components are in bbui -->
|
|
||||||
<section class="spectrum-Dialog-content content-grid">
|
<section class="spectrum-Dialog-content content-grid">
|
||||||
<slot {loading} />
|
<slot {loading} />
|
||||||
</section>
|
</section>
|
||||||
|
@ -102,7 +106,6 @@
|
||||||
{#if showSecondaryButton && secondaryButtonText && secondaryAction}
|
{#if showSecondaryButton && secondaryButtonText && secondaryAction}
|
||||||
<div class="secondary-action">
|
<div class="secondary-action">
|
||||||
<Button
|
<Button
|
||||||
group
|
|
||||||
secondary
|
secondary
|
||||||
warning={secondaryButtonWarning}
|
warning={secondaryButtonWarning}
|
||||||
on:click={secondary}>{secondaryButtonText}</Button
|
on:click={secondary}>{secondaryButtonText}</Button
|
||||||
|
@ -111,14 +114,13 @@
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if showCancelButton}
|
{#if showCancelButton}
|
||||||
<Button group secondary on:click={close}>
|
<Button secondary on:click={close}>
|
||||||
{cancelText}
|
{cancelText}
|
||||||
</Button>
|
</Button>
|
||||||
{/if}
|
{/if}
|
||||||
{#if showConfirmButton}
|
{#if showConfirmButton}
|
||||||
<span class="confirm-wrap">
|
<span class="confirm-wrap">
|
||||||
<Button
|
<Button
|
||||||
group
|
|
||||||
cta
|
cta
|
||||||
{...$$restProps}
|
{...$$restProps}
|
||||||
disabled={confirmDisabled}
|
disabled={confirmDisabled}
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
<script>
|
|
||||||
import ModalContent from "./ModalContent.svelte"
|
|
||||||
import Input from "../Form/Input.svelte"
|
|
||||||
|
|
||||||
let modal
|
|
||||||
let answer
|
|
||||||
let error
|
|
||||||
|
|
||||||
export function show() {
|
|
||||||
modal.show()
|
|
||||||
}
|
|
||||||
export function hide() {
|
|
||||||
modal.hide
|
|
||||||
}
|
|
||||||
|
|
||||||
function resetState() {
|
|
||||||
answer = undefined
|
|
||||||
error = undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
async function answerQuiz() {
|
|
||||||
const correct = answer === "8"
|
|
||||||
error = !correct
|
|
||||||
return correct
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<ModalContent
|
|
||||||
title="Quick Maths"
|
|
||||||
bind:this={modal}
|
|
||||||
confirmText="Submit"
|
|
||||||
onConfirm={answerQuiz}
|
|
||||||
on:show={resetState}
|
|
||||||
>
|
|
||||||
{#if error}
|
|
||||||
<p class="error">Wrong answer! Try again.</p>
|
|
||||||
{/if}
|
|
||||||
<p>What is 4 + 4?</p>
|
|
||||||
<Input label="Answer" bind:value={answer} />
|
|
||||||
</ModalContent>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
p {
|
|
||||||
margin: 0;
|
|
||||||
font-size: var(--font-size-s);
|
|
||||||
}
|
|
||||||
p.error {
|
|
||||||
color: #e26d69;
|
|
||||||
background-color: #ffe6e6;
|
|
||||||
padding: 8px;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,17 +1,17 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import { ActionButton } from "../"
|
import { ActionButton } from "../"
|
||||||
|
|
||||||
import { createEventDispatcher } from "svelte"
|
import { createEventDispatcher } from "svelte"
|
||||||
|
|
||||||
export let type = "info"
|
export let type: string = "info"
|
||||||
export let icon = "Info"
|
export let icon: string = "Info"
|
||||||
export let message = ""
|
export let message: string = ""
|
||||||
export let dismissable = false
|
export let dismissable: boolean = false
|
||||||
export let actionMessage = null
|
export let actionMessage: string | null = null
|
||||||
export let action = null
|
export let action: ((_dismiss: () => void) => void) | null = null
|
||||||
export let wide = false
|
export let wide: boolean = false
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher<{ dismiss: void }>()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="spectrum-Toast spectrum-Toast--{type}" class:wide>
|
<div class="spectrum-Toast spectrum-Toast--{type}" class:wide>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import "@spectrum-css/toast/dist/index-vars.css"
|
import "@spectrum-css/toast/dist/index-vars.css"
|
||||||
import Portal from "svelte-portal"
|
import Portal from "svelte-portal"
|
||||||
import { notifications } from "../Stores/notifications"
|
import { notifications } from "../Stores/notifications"
|
||||||
|
|
|
@ -1,20 +1,19 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import "@spectrum-css/pagination/dist/index-vars.css"
|
import "@spectrum-css/pagination/dist/index-vars.css"
|
||||||
import "@spectrum-css/actionbutton/dist/index-vars.css"
|
import "@spectrum-css/actionbutton/dist/index-vars.css"
|
||||||
import "@spectrum-css/typography/dist/index-vars.css"
|
import "@spectrum-css/typography/dist/index-vars.css"
|
||||||
|
|
||||||
export let page
|
export let page: number
|
||||||
export let goToPrevPage
|
export let goToPrevPage: () => void
|
||||||
export let goToNextPage
|
export let goToNextPage: () => void
|
||||||
export let hasPrevPage = true
|
export let hasPrevPage: boolean = true
|
||||||
export let hasNextPage = true
|
export let hasNextPage: boolean = true
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
<nav class="spectrum-Pagination spectrum-Pagination--explicit">
|
<nav class="spectrum-Pagination spectrum-Pagination--explicit">
|
||||||
<div
|
<div
|
||||||
href="#"
|
|
||||||
class="spectrum-ActionButton spectrum-ActionButton--sizeM spectrum-ActionButton--quiet spectrum-Pagination-prevButton"
|
class="spectrum-ActionButton spectrum-ActionButton--sizeM spectrum-ActionButton--quiet spectrum-Pagination-prevButton"
|
||||||
on:click={hasPrevPage ? goToPrevPage : null}
|
on:click={hasPrevPage ? goToPrevPage : null}
|
||||||
class:is-disabled={!hasPrevPage}
|
class:is-disabled={!hasPrevPage}
|
||||||
|
@ -32,7 +31,6 @@
|
||||||
Page {page}
|
Page {page}
|
||||||
</span>
|
</span>
|
||||||
<div
|
<div
|
||||||
href="#"
|
|
||||||
class="spectrum-ActionButton spectrum-ActionButton--sizeM spectrum-ActionButton--quiet spectrum-Pagination-nextButton"
|
class="spectrum-ActionButton spectrum-ActionButton--sizeM spectrum-ActionButton--quiet spectrum-Pagination-nextButton"
|
||||||
on:click={hasNextPage ? goToNextPage : null}
|
on:click={hasNextPage ? goToNextPage : null}
|
||||||
class:is-disabled={!hasNextPage}
|
class:is-disabled={!hasNextPage}
|
||||||
|
|
|
@ -1,25 +1,24 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import "@spectrum-css/progressbar/dist/index-vars.css"
|
import "@spectrum-css/progressbar/dist/index-vars.css"
|
||||||
|
|
||||||
export let value = false
|
export let value: number | boolean = false
|
||||||
export let duration = 1000
|
export let duration: number = 1000
|
||||||
export let width = false
|
export let width: string | boolean = false
|
||||||
export let sideLabel = false
|
export let sideLabel: boolean = false
|
||||||
export let hidePercentage = true
|
export let hidePercentage: boolean = true
|
||||||
export let color // red, green, default = blue
|
export let color: "red" | "green" | undefined = undefined // red, green, default = blue
|
||||||
export let size = "M"
|
export let size: string = "M"
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class:spectrum-ProgressBar--indeterminate={!value && value !== 0}
|
class:spectrum-ProgressBar--indeterminate={!value && value !== 0}
|
||||||
class:spectrum-ProgressBar--sideLabel={sideLabel}
|
class:spectrum-ProgressBar--sideLabel={sideLabel}
|
||||||
class="spectrum-ProgressBar spectrum-ProgressBar--size{size}"
|
class="spectrum-ProgressBar spectrum-ProgressBar--size{size}"
|
||||||
{value}
|
|
||||||
role="progressbar"
|
role="progressbar"
|
||||||
aria-valuenow={value}
|
aria-valuenow={typeof value === "number" ? value : undefined}
|
||||||
aria-valuemin="0"
|
aria-valuemin="0"
|
||||||
aria-valuemax="100"
|
aria-valuemax="100"
|
||||||
style={width ? `width: ${width};` : ""}
|
style={width ? `width: ${typeof width === "string" ? width : ""};` : ""}
|
||||||
>
|
>
|
||||||
{#if $$slots}
|
{#if $$slots}
|
||||||
<div
|
<div
|
||||||
|
@ -32,7 +31,7 @@
|
||||||
<div
|
<div
|
||||||
class="spectrum-FieldLabel spectrum-ProgressBar-percentage spectrum-FieldLabel--size{size}"
|
class="spectrum-FieldLabel spectrum-ProgressBar-percentage spectrum-FieldLabel--size{size}"
|
||||||
>
|
>
|
||||||
{Math.round(value)}%
|
{Math.round(Number(value))}%
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="spectrum-ProgressBar-track">
|
<div class="spectrum-ProgressBar-track">
|
||||||
|
@ -40,10 +39,12 @@
|
||||||
class="spectrum-ProgressBar-fill"
|
class="spectrum-ProgressBar-fill"
|
||||||
class:color-green={color === "green"}
|
class:color-green={color === "green"}
|
||||||
class:color-red={color === "red"}
|
class:color-red={color === "red"}
|
||||||
style="width: {value}%; --duration: {duration}ms;"
|
style="width: {typeof value === 'number'
|
||||||
|
? value
|
||||||
|
: 0}%; --duration: {duration}ms;"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="spectrum-ProgressBar-label" hidden="" />
|
<div class="spectrum-ProgressBar-label" hidden={false} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import "@spectrum-css/progresscircle/dist/index-vars.css"
|
import "@spectrum-css/progresscircle/dist/index-vars.css"
|
||||||
|
|
||||||
export let size = "M"
|
export let size: "S" | "M" | "L" = "M"
|
||||||
function convertSize(size) {
|
function convertSize(size: "S" | "M" | "L"): string | undefined {
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case "S":
|
case "S":
|
||||||
return "small"
|
return "small"
|
||||||
|
@ -13,18 +13,18 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export let value = null
|
export let value: number | null = null
|
||||||
export let minValue = 0
|
export let minValue: number = 0
|
||||||
export let maxValue = 100
|
export let maxValue: number = 100
|
||||||
|
|
||||||
let subMask1Style
|
let subMask1Style: string | undefined
|
||||||
let subMask2Style
|
let subMask2Style: string | undefined
|
||||||
$: calculateSubMasks(value)
|
$: calculateSubMasks(value)
|
||||||
|
|
||||||
function calculateSubMasks(value) {
|
function calculateSubMasks(value: number | null): void {
|
||||||
if (value) {
|
if (value) {
|
||||||
let percentage = ((value - minValue) / (maxValue - minValue)) * 100
|
let percentage = ((value - minValue) / (maxValue - minValue)) * 100
|
||||||
let angle
|
let angle: number
|
||||||
if (percentage > 0 && percentage <= 50) {
|
if (percentage > 0 && percentage <= 50) {
|
||||||
angle = -180 + (percentage / 50) * 180
|
angle = -180 + (percentage / 50) * 180
|
||||||
subMask1Style = `transform: rotate(${angle}deg);`
|
subMask1Style = `transform: rotate(${angle}deg);`
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export let overBackground = false
|
export let overBackground: boolean = false
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
<script>
|
|
||||||
import { flip } from 'svelte/animate';
|
|
||||||
import { fly } from "svelte/transition"
|
|
||||||
import { View } from "svench";
|
|
||||||
import { notifications } from "./notifications";
|
|
||||||
|
|
||||||
export let themes = {
|
|
||||||
danger: "#E26D69",
|
|
||||||
success: "#84C991",
|
|
||||||
warning: "#f0ad4e",
|
|
||||||
info: "#5bc0de",
|
|
||||||
default: "#aaaaaa",
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
## Notification Store
|
|
||||||
|
|
||||||
This custom can be used to display toast messages. It has 5 different methods: `send`, `danger`, `warning`, `success`, `info`.
|
|
||||||
|
|
||||||
|
|
||||||
<View name="danger">
|
|
||||||
<button on:click={() => notifications.error('This is a danger!')}>Danger</button>
|
|
||||||
</View>
|
|
||||||
<View name="warning">
|
|
||||||
<button on:click={() => notifications.warning('This is a warning!')}>Warning</button>
|
|
||||||
</View>
|
|
||||||
<View name="success">
|
|
||||||
<button on:click={() => notifications.success('This is a success!')}>Success</button>
|
|
||||||
</View>
|
|
||||||
<View name="info">
|
|
||||||
<button on:click={() => notifications.info('This is an info toast!')}>Info</button>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<div class="notifications">
|
|
||||||
{#each $notifications as notification (notification.id)}
|
|
||||||
<div
|
|
||||||
animate:flip
|
|
||||||
class="toast"
|
|
||||||
style="background: {themes[notification.type]};"
|
|
||||||
transition:fly={{ y: -30 }}>
|
|
||||||
<div class="content">{notification.message}</div>
|
|
||||||
{#if notification.icon}<i class={notification.icon} />{/if}
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.notifications {
|
|
||||||
position: fixed;
|
|
||||||
top: 10px;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 0;
|
|
||||||
z-index: 9999;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
align-items: center;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toast {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
border-radius: var(--border-radius-s);
|
|
||||||
/* The toasts now support being auto sized, so this static width could be removed */
|
|
||||||
width: 40vw;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
padding: 10px;
|
|
||||||
display: block;
|
|
||||||
color: white;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import AbsTooltip from "./AbsTooltip.svelte"
|
import AbsTooltip from "./AbsTooltip.svelte"
|
||||||
|
|
||||||
export let tooltip: string = ""
|
export let tooltip: string = ""
|
||||||
export let size: "S" | "M" = "M"
|
export let size: "S" | "M" | "L" = "M"
|
||||||
export let disabled: boolean = true
|
export let disabled: boolean = true
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ export { default as Toggle } from "./Form/Toggle.svelte"
|
||||||
export { default as RadioGroup } from "./Form/RadioGroup.svelte"
|
export { default as RadioGroup } from "./Form/RadioGroup.svelte"
|
||||||
export { default as Checkbox } from "./Form/Checkbox.svelte"
|
export { default as Checkbox } from "./Form/Checkbox.svelte"
|
||||||
export { default as InputDropdown } from "./Form/InputDropdown.svelte"
|
export { default as InputDropdown } from "./Form/InputDropdown.svelte"
|
||||||
export { default as PickerDropdown } from "./Form/PickerDropdown.svelte"
|
|
||||||
export { default as EnvDropdown } from "./Form/EnvDropdown.svelte"
|
export { default as EnvDropdown } from "./Form/EnvDropdown.svelte"
|
||||||
export { default as Multiselect } from "./Form/Multiselect.svelte"
|
export { default as Multiselect } from "./Form/Multiselect.svelte"
|
||||||
export { default as Search } from "./Form/Search.svelte"
|
export { default as Search } from "./Form/Search.svelte"
|
||||||
|
@ -87,8 +86,6 @@ export { default as MarkdownEditor } from "./Markdown/MarkdownEditor.svelte"
|
||||||
export { default as MarkdownViewer } from "./Markdown/MarkdownViewer.svelte"
|
export { default as MarkdownViewer } from "./Markdown/MarkdownViewer.svelte"
|
||||||
export { default as List } from "./List/List.svelte"
|
export { default as List } from "./List/List.svelte"
|
||||||
export { default as ListItem } from "./List/ListItem.svelte"
|
export { default as ListItem } from "./List/ListItem.svelte"
|
||||||
export { default as IconSideNav } from "./IconSideNav/IconSideNav.svelte"
|
|
||||||
export { default as IconSideNavItem } from "./IconSideNav/IconSideNavItem.svelte"
|
|
||||||
export { default as Accordion } from "./Accordion/Accordion.svelte"
|
export { default as Accordion } from "./Accordion/Accordion.svelte"
|
||||||
export { default as AbsTooltip } from "./Tooltip/AbsTooltip.svelte"
|
export { default as AbsTooltip } from "./Tooltip/AbsTooltip.svelte"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue