This commit is contained in:
Martin McKeaveney 2021-06-21 11:19:22 +01:00
commit 03c5640856
51 changed files with 5048 additions and 671 deletions

View File

@ -63,9 +63,9 @@
on:focus={() => (focus = true)}
on:blur={() => (focus = false)}
on:change={onChange}
{value}
value={value || ""}
placeholder={placeholder || ""}
{disabled}
{placeholder}
class="spectrum-Textfield-input spectrum-InputGroup-input"
/>
</div>

View File

@ -359,7 +359,7 @@
background-color: var(--spectrum-alias-background-color-secondary);
overflow: hidden;
position: relative;
z-index: 1;
z-index: 0;
}
.container {

View File

@ -78,7 +78,7 @@
"posthog-js": "1.4.5",
"remixicon": "2.5.0",
"shortid": "2.2.15",
"svelte-dnd-action": "^0.8.9",
"svelte-dnd-action": "^0.9.8",
"svelte-loading-spinners": "^0.1.1",
"svelte-portal": "0.1.0",
"uuid": "8.3.1",

View File

@ -333,7 +333,7 @@ const buildFormSchema = component => {
*/
export function removeBindings(obj) {
for (let [key, value] of Object.entries(obj)) {
if (typeof value === "object") {
if (value && typeof value === "object") {
obj[key] = removeBindings(value)
} else if (typeof value === "string") {
obj[key] = value.replace(CAPTURE_HBS_TEMPLATE, "Invalid binding")

View File

@ -305,7 +305,6 @@ export const getFrontendStore = () => {
_id: uuid(),
_component: definition.component,
_styles: { normal: {}, hover: {}, active: {} },
_transition: "",
_instanceName: `New ${definition.name}`,
...cloneDeep(props),
...extras,
@ -508,15 +507,6 @@ export const getFrontendStore = () => {
selected._styles = { normal: {}, hover: {}, active: {} }
await store.actions.preview.saveSelected()
},
updateTransition: async transition => {
const selected = get(selectedComponent)
if (transition == null || transition === "") {
selected._transition = ""
} else {
selected._transition = transition
}
await store.actions.preview.saveSelected()
},
updateProp: async (name, value) => {
let component = get(selectedComponent)
if (!name || !component) {
@ -536,7 +526,19 @@ export const getFrontendStore = () => {
return
}
// Find a nav bar in the main layout
// Add link setting to main layout
if (layout.props._component.endsWith("layout")) {
// If using a new SDK, add to the layout component settings
if (!layout.props.links) {
layout.props.links = []
}
layout.props.links.push({
text: title,
url,
})
} else {
// If using an old SDK, add to the navigation component
// TODO: remove this when we can assume everyone has updated
const nav = findComponentType(
layout.props,
"@budibase/standard-components/navigation"
@ -563,10 +565,11 @@ export const getFrontendStore = () => {
text: title,
_instanceName: `${title} Link`,
}
nav._children = [...nav._children, newLink]
}
}
// Save layout
nav._children = [...nav._children, newLink]
await store.actions.layouts.save(layout)
},
},

View File

@ -128,7 +128,6 @@ const createScreen = table => {
background: "white",
"border-radius": "0.5rem",
"box-shadow": "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
"margin-top": "20px",
"border-width": "2px",
"border-color": "rgba(0, 0, 0, 0.1)",
"border-style": "None",
@ -136,7 +135,6 @@ const createScreen = table => {
"padding-bottom": "48px",
"padding-right": "48px",
"padding-left": "48px",
"margin-bottom": "20px",
})
.customProps({
direction: "column",

View File

@ -14,7 +14,6 @@ export class Component extends BaseStructure {
active: {},
selected: {},
},
_transition: "",
_instanceName: "",
_children: [],
}
@ -40,11 +39,6 @@ export class Component extends BaseStructure {
return this
}
transition(transition) {
this._json._transition = transition
return this
}
// Shorthand for custom props "type"
type(type) {
this._json.type = type

View File

@ -40,12 +40,10 @@ export function makeMainForm() {
padding: "0px",
"border-radius": "0.5rem",
"box-shadow": "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
"margin-top": "20px",
"padding-top": "48px",
"padding-bottom": "48px",
"padding-right": "48px",
"padding-left": "48px",
"margin-bottom": "20px",
})
.instanceName("Form")
}
@ -58,6 +56,8 @@ export function makeBreadcrumbContainer(tableName, text, capitalise = false) {
.normalStyle({
"margin-right": "4px",
"margin-left": "4px",
"margin-top": "0px",
"margin-bottom": "0px",
})
.customStyle(spectrumColor(700))
.text(">")
@ -65,6 +65,8 @@ export function makeBreadcrumbContainer(tableName, text, capitalise = false) {
const textStyling = {
color: "#000000",
"margin-top": "0px",
"margin-bottom": "0px",
}
if (capitalise) {
textStyling["text-transform"] = "capitalize"
@ -140,10 +142,6 @@ export function makeTitleContainer(title) {
const heading = new Component("@budibase/standard-components/heading")
.normalStyle({
margin: "0px",
"margin-bottom": "0px",
"margin-right": "0px",
"margin-top": "0px",
"margin-left": "0px",
flex: "1 1 auto",
})
.customStyle(spectrumColor(900))

View File

@ -1,10 +1,17 @@
<script>
import { ActionMenu, ActionButton, MenuItem, Icon } from "@budibase/bbui"
import { store, currentAssetName } from "builderStore"
import { store, currentAssetName, selectedComponent } from "builderStore"
import structure from "./componentStructure.json"
$: enrichedStructure = enrichStructure(structure, $store.components)
const isChildAllowed = ({ name }, selectedComponent) => {
const currentComponent = store.actions.components.getDefinition(
selectedComponent?._component
)
return currentComponent?.illegalChildren?.includes(name.toLowerCase())
}
const enrichStructure = (structure, definitions) => {
let enrichedStructure = []
structure.forEach(item => {
@ -39,6 +46,7 @@
<ActionMenu disabled={!item.isCategory}>
<ActionButton
icon={item.icon}
disabled={isChildAllowed(item, $selectedComponent)}
quiet
size="S"
slot="control"

View File

@ -1,4 +1,5 @@
[
"section",
"container",
"dataprovider",
"table",
@ -61,8 +62,7 @@
"name": "Other",
"icon": "More",
"children": [
"screenslot",
"navigation"
"screenslot"
]
}
]

View File

@ -12,16 +12,24 @@ export default `
rel="stylesheet"
/>
<style>
html,
body {
margin: 0;
html, body {
padding: 0;
height: 100%;
width: 100%;
margin: 0;
}
html {
height: calc(100% - 16px);
width: calc(100% - 16px);
overflow: hidden;
margin: 8px;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.1);
}
body {
padding: 2px;
flex: 1 1 auto;
overflow: hidden;
}
*,

View File

@ -10,11 +10,10 @@
$: screen = $allScreens.find(screen => screen._id === screenId)
const deleteScreen = () => {
const deleteScreen = async () => {
try {
store.actions.screens.delete(screen)
store.actions.routing.fetch()
confirmDeleteDialog.hide()
await store.actions.screens.delete(screen)
await store.actions.routing.fetch()
$goto("../")
notifications.success("Deleted screen successfully.")
} catch (err) {

View File

@ -55,7 +55,6 @@
if (routeError) return false
draftScreen.props._instanceName = name
draftScreen.props._transition = "fade"
draftScreen.props._component = baseComponent
draftScreen.routing = { route, roleId }

View File

@ -1,5 +1,5 @@
<script>
import { TextArea, DetailSummary, Button, Select } from "@budibase/bbui"
import { TextArea, DetailSummary, Button } from "@budibase/bbui"
import PropertyGroup from "./PropertyControls/PropertyGroup.svelte"
import FlatButtonGroup from "./PropertyControls/FlatButtonGroup"
import { allStyles } from "./componentStyles"
@ -8,7 +8,6 @@
export let componentInstance = {}
export let onStyleChanged = () => {}
export let onCustomStyleChanged = () => {}
export let onUpdateTransition = () => {}
export let onResetStyles = () => {}
let selectedCategory = "normal"
@ -24,16 +23,6 @@
{ value: "active", text: "Active" },
]
const transitions = [
"none",
"fade",
"blur",
"fly",
"scale", // slide is hidden because it does not seem to result in any effect
]
const capitalize = ([first, ...rest]) => first.toUpperCase() + rest.join("")
$: groups = componentDefinition?.styleable ? Object.keys(allStyles) : []
</script>
@ -78,18 +67,6 @@
{/if}
</div>
</div>
{#if componentDefinition?.transitionable}
<div class="transitions">
<Select
value={componentInstance._transition}
on:change={event => onUpdateTransition(event.detail)}
name="transition"
label="Transition"
options={transitions}
getOptionLabel={capitalize}
/>
</div>
{/if}
</div>
<style>

View File

@ -8,7 +8,7 @@
import { setWith } from "lodash"
$: definition = store.actions.components.getDefinition(
$selectedComponent._component
$selectedComponent?._component
)
$: isComponentOrScreen =
$store.currentView === "component" ||
@ -18,7 +18,6 @@
const onStyleChanged = store.actions.components.updateStyle
const onCustomStyleChanged = store.actions.components.updateCustomStyle
const onUpdateTransition = store.actions.components.updateTransition
const onResetStyles = store.actions.components.resetStyles
function setAssetProps(name, value) {
@ -64,7 +63,6 @@
componentDefinition={definition}
{onStyleChanged}
{onCustomStyleChanged}
{onUpdateTransition}
{onResetStyles}
/>
</div>

View File

@ -1,5 +1,5 @@
<script>
import { Button, Drawer } from "@budibase/bbui"
import { ActionButton, Button, Drawer } from "@budibase/bbui"
import { createEventDispatcher } from "svelte"
import { notifications } from "@budibase/bbui"
import EventEditor from "./EventEditor.svelte"
@ -51,7 +51,7 @@
}
</script>
<Button secondary on:click={drawer.show}>Define Actions</Button>
<ActionButton on:click={drawer.show}>Define Actions</ActionButton>
<Drawer bind:this={drawer} title={"Actions"}>
<svelte:fragment slot="description">
Define what actions to run.

View File

@ -1,6 +1,7 @@
<script>
import {
notifications,
ActionButton,
Button,
Drawer,
Body,
@ -46,7 +47,7 @@
}
</script>
<Button secondary on:click={drawer.show}>Define Filters</Button>
<ActionButton on:click={drawer.show}>Define Filters</ActionButton>
<Drawer bind:this={drawer} title="Filtering">
<Button cta slot="buttons" on:click={saveFilter}>Save</Button>
<DrawerContent slot="body">

View File

@ -8,7 +8,7 @@
</script>
<script>
import { Popover, Button, Input } from "@budibase/bbui"
import { Popover, ActionButton, Button, Input } from "@budibase/bbui"
import { createEventDispatcher, tick } from "svelte"
const dispatch = createEventDispatcher()
@ -117,7 +117,7 @@
</script>
<div bind:this={buttonAnchor}>
<Button secondary small on:click={dropdown.show}>{displayValue}</Button>
<ActionButton on:click={dropdown.show}>{displayValue}</ActionButton>
</div>
<Popover bind:this={dropdown} on:open={setSelectedUI} anchor={buttonAnchor}>
<div class="container">

View File

@ -0,0 +1,114 @@
<script>
import {
Button,
Icon,
DrawerContent,
Layout,
Input,
Combobox,
} from "@budibase/bbui"
import { flip } from "svelte/animate"
import { dndzone } from "svelte-dnd-action"
import { generate } from "shortid"
import { store } from "builderStore"
export let links = []
const flipDurationMs = 150
$: links.forEach(link => {
if (!link.id) {
link.id = generate()
}
})
$: urlOptions = $store.screens
.map(screen => screen.routing?.route)
.filter(x => x != null)
const addLink = () => {
links = [...links, {}]
}
const removeLink = id => {
links = links.filter(link => link.id !== id)
}
const updateLinks = e => {
links = e.detail.items
}
</script>
<DrawerContent>
<div class="container">
<Layout>
{#if links?.length}
<div
class="links"
use:dndzone={{
items: links,
flipDurationMs,
dropTargetStyle: { outline: "none" },
}}
on:finalize={updateLinks}
on:consider={updateLinks}
>
{#each links as link (link.id)}
<div class="link" animate:flip={{ duration: flipDurationMs }}>
<Icon name="DragHandle" size="XL" />
<Input bind:value={link.text} placeholder="Text" />
<Combobox
bind:value={link.url}
placeholder="URL"
options={urlOptions}
/>
<Icon
name="Close"
hoverable
size="S"
on:click={() => removeLink(link.id)}
/>
</div>
{/each}
</div>
{/if}
<div class="button-container">
<Button secondary icon="Add" on:click={addLink}>Add Link</Button>
</div>
</Layout>
</div>
</DrawerContent>
<style>
.container {
width: 100%;
max-width: 600px;
margin: var(--spacing-m) auto;
}
.links {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
}
.link {
padding: 4px 8px;
gap: var(--spacing-l);
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
border-radius: var(--border-radius-s);
transition: background-color ease-in-out 130ms;
}
.link:hover {
background-color: var(--spectrum-global-color-gray-100);
}
.link > :global(.spectrum-Form-item) {
flex: 1 1 auto;
width: 0;
}
.button-container {
margin-left: var(--spacing-l);
}
</style>

View File

@ -0,0 +1,23 @@
<script>
import { Button, ActionButton, Drawer } from "@budibase/bbui"
import { createEventDispatcher } from "svelte"
import NavigationDrawer from "./NavigationDrawer.svelte"
export let value = []
let drawer
const dispatch = createEventDispatcher()
const save = () => {
dispatch("change", value)
drawer.hide()
}
</script>
<ActionButton on:click={drawer.show}>Configure Links</ActionButton>
<Drawer bind:this={drawer} title={"Navigation Links"}>
<svelte:fragment slot="description">
Configure the links in your navigation bar.
</svelte:fragment>
<Button cta slot="buttons" on:click={save}>Save</Button>
<NavigationDrawer slot="body" bind:links={value} />
</Drawer>

View File

@ -0,0 +1,75 @@
<script>
import { createEventDispatcher } from "svelte"
import { ActionButton, Body, Icon, Modal, ModalContent } from "@budibase/bbui"
const dispatch = createEventDispatcher()
export let value = ""
let selected = value
let modal
let layoutMap = {
mainSidebar: {
name: "Main with Sidebar",
icon: "ColumnTwoB",
},
sidebarMain: {
name: "Sidebar with Main",
icon: "ColumnTwoC",
},
twoColumns: {
name: "Two columns",
icon: "ColumnTwoA",
},
threeColumns: {
name: "Three columns",
icon: "ViewColumn",
},
}
</script>
<ActionButton on:click={modal.show}>{layoutMap[value].name}</ActionButton>
<Modal bind:this={modal}>
<ModalContent
onConfirm={() => dispatch("change", selected)}
size="L"
title="Select layout"
>
<div class="container">
{#each Object.entries(layoutMap) as [key, value]}
<button
class:selected={selected === key}
on:click={() => (selected = key)}
class="layout"
>
<Icon color="white" size="L" name={value.icon} />
<Body size="XS">{value.name}</Body>
</button>
{/each}
</div>
</ModalContent>
</Modal>
<style>
.container {
display: grid;
grid-gap: 20px;
grid-template-columns: 1fr 1fr 1fr;
}
.layout {
color: var(--spectrum-body-m-text-color, var(--spectrum-alias-text-color));
border: none;
box-sizing: border-box;
display: grid;
place-items: center;
background: var(--background-alt);
grid-gap: var(--spectrum-alias-grid-margin-xsmall);
padding: var(--spectrum-alias-item-padding-s);
transition: 0.3s all;
border-radius: var(--spacing-s);
}
.selected {
background: var(--spectrum-alias-background-color-tertiary);
}
</style>

View File

@ -15,6 +15,8 @@
import FieldSelect from "./PropertyControls/FieldSelect.svelte"
import MultiFieldSelect from "./PropertyControls/MultiFieldSelect.svelte"
import SchemaSelect from "./PropertyControls/SchemaSelect.svelte"
import SectionSelect from "./PropertyControls/SectionSelect.svelte"
import NavigationEditor from "./PropertyControls/NavigationEditor/NavigationEditor.svelte"
import EventsEditor from "./PropertyControls/EventsEditor"
import FilterEditor from "./PropertyControls/FilterEditor/FilterEditor.svelte"
import { IconSelect } from "./PropertyControls/IconSelect"
@ -62,6 +64,8 @@
field: FieldSelect,
multifield: MultiFieldSelect,
schema: SchemaSelect,
section: SectionSelect,
navigation: NavigationEditor,
filter: FilterEditor,
"field/string": StringFieldSelect,
"field/number": NumberFieldSelect,

View File

@ -1,54 +0,0 @@
<script>
import { Button } from "@budibase/bbui"
export let remove = false
</script>
<div class="container">
<div class="content">
<div class="img"><img src="https://picsum.photos/60/60" alt="zoom" /></div>
<div class="body">
<div class="title">Zoom</div>
<div class="description">
Lorem, ipsum dolor sit amet consectetur adipisicing elit
</div>
</div>
</div>
<div class="footer">
<Button wide error={remove} secondary={!remove} on:click>
<span>{remove ? "Remove" : "Add"}</span>
</Button>
</div>
</div>
<style>
.container {
display: grid;
padding: 12px;
background: var(--light-grey);
grid-gap: 20px;
}
span {
font-size: 12px;
font-weight: bold;
}
.content {
display: grid;
grid-gap: 12px;
grid-template-columns: 60px auto;
}
.title {
font-size: 14px;
font-weight: bold;
}
.description {
font-size: 12px;
}
.img {
border-radius: 3px;
overflow: hidden;
}
img {
height: 60px;
width: 60px;
}
</style>

View File

@ -1,33 +0,0 @@
<script>
import SettingsModal from "./SettingsModal.svelte"
import { Modal, Icon } from "@budibase/bbui"
let modal
</script>
<div
class="topnavitemright settings"
data-cy="settings-icon"
on:click={modal.show}
>
<Icon hoverable name="Settings" />
</div>
<Modal bind:this={modal} width="600px">
<SettingsModal />
</Modal>
<style>
.topnavitemright {
cursor: pointer;
color: var(--grey-7);
margin: 0 12px 0 0;
font-weight: 600;
font-size: 1rem;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
height: 24px;
width: 24px;
}
</style>

View File

@ -1,34 +0,0 @@
<script>
import { General, DangerZone } from "./tabs"
import { ModalContent, Tab, Tabs } from "@budibase/bbui"
</script>
<ModalContent
title="Settings"
showConfirmButton={false}
showCancelButton={false}
>
<div class="container">
<Tabs selected="General">
<Tab title="General">
<General />
</Tab>
<!-- <Tab title="API Keys">
<APIKeys />
</Tab> -->
<Tab title="Danger Zone">
<DangerZone />
</Tab>
</Tabs>
</div>
</ModalContent>
<style>
.container :global(section > header) {
/* Fix margin defined in BBUI as L rather than XL */
margin-bottom: var(--spacing-xl);
}
.container :global(textarea) {
min-height: 60px;
}
</style>

View File

@ -1,62 +0,0 @@
<script>
import { Input, Label, Link } from "@budibase/bbui"
import api from "builderStore/api"
import { notifications } from "@budibase/bbui"
import { database } from "stores/backend"
import analytics from "analytics"
let keys = { budibase: "" }
async function updateKey([key, value]) {
if (key === "budibase") {
const isValid = await analytics.identifyByApiKey(value)
if (!isValid) {
notifications.error("Your API Key is invalid.")
keys = { ...keys }
return
}
}
const response = await api.put(`/api/keys/${key}`, { value })
const res = await response.json()
keys = { ...keys, ...res }
notifications.success("API Key saved.")
}
// Get Keys
async function fetchKeys() {
const response = await api.get(`/api/keys/`)
const res = await response.json()
// dont want this to ever be editable, as its fetched based on Api Key
if (res.userId) delete res.userId
keys = res
}
fetchKeys()
</script>
<div class="container">
<Input
on:change={e => updateKey(["budibase", e.detail])}
value={keys.budibase}
label="Budibase Cloud API Key"
/>
<Link primary href="https://portal.budi.live">
Log in to the Budibase Hosting Portal to get your API Key. →
</Link>
<div>
<Label extraSmall grey>Instance ID (Webhooks)</Label>
<span>{$database._id}</span>
</div>
</div>
<style>
.container {
display: grid;
grid-gap: var(--spacing-xl);
}
span {
font-size: var(--font-size-xs);
font-weight: 600;
}
</style>

View File

@ -1,56 +0,0 @@
<script>
import { params, goto } from "@roxi/routify"
import { Input, Button, Body } from "@budibase/bbui"
import { del } from "builderStore/api"
let value = ""
let loading = false
async function deleteApp() {
loading = true
const id = $params.application
await del(`/api/applications/${id}`)
loading = false
$goto("/builder")
}
</script>
<div class="background">
<Body>
Type
<b>DELETE</b>
into the textbox, then click the following button to delete your entire web app.
</Body>
<Input
on:change={e => (value = e.detail)}
disabled={loading}
placeholder=""
/>
<div class="buttons">
<Button
warning
disabled={value !== "DELETE" || loading}
on:click={deleteApp}
>
Delete Entire App
</Button>
</div>
</div>
<style>
.background {
display: grid;
grid-gap: var(--spacing-xl);
}
.background :global(p) {
line-height: 1.2;
margin: 0;
}
.buttons {
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
}
</style>

View File

@ -1,97 +0,0 @@
<script>
import { Input, TextArea } from "@budibase/bbui"
import { store, hostingStore } from "builderStore"
import api from "builderStore/api"
import { object, string } from "yup"
import { onMount } from "svelte"
import { get } from "svelte/store"
let nameValidation, nameError
let urlValidation, urlError
$: checkName($store.name)
$: checkUrl($store.url)
async function updateApplication(data) {
const response = await api.put(`/api/applications/${$store.appId}`, data)
await response.json()
store.update(state => {
state = {
...state,
...data,
}
return state
})
}
async function checkValidation(input, validation) {
if (!input || !validation) {
return
}
try {
await object(validation).validate(input, { abortEarly: false })
} catch (error) {
if (!error || !error.inner) return ""
return error.inner.reduce((acc, err) => {
return acc + err.message
}, "")
}
}
async function checkName(name) {
nameError = await checkValidation({ name }, nameValidation)
}
async function checkUrl(url) {
urlError = await checkValidation({ url: url.toLowerCase() }, urlValidation)
}
onMount(async () => {
const nameError = "Your application must have a name.",
urlError = "Your application must have a URL."
await hostingStore.actions.fetchDeployedApps()
const existingAppNames = get(hostingStore).deployedAppNames
const existingAppUrls = get(hostingStore).deployedAppUrls
const nameIdx = existingAppNames.indexOf(get(store).name)
const urlIdx = existingAppUrls.indexOf(get(store).url)
if (nameIdx !== -1) {
existingAppNames.splice(nameIdx, 1)
}
if (urlIdx !== -1) {
existingAppUrls.splice(urlIdx, 1)
}
nameValidation = {
name: string().required(nameError).notOneOf(existingAppNames),
}
urlValidation = {
url: string().required(urlError).notOneOf(existingAppUrls),
}
})
</script>
<div class="container">
<Input
on:change={e => updateApplication({ name: e.detail })}
value={$store.name}
error={nameError}
label="App Name"
/>
<Input
on:change={e => updateApplication({ url: e.detail })}
value={$store.url}
error={urlError}
label="App URL"
/>
<TextArea
on:change={e => updateApplication({ description: e.detail })}
value={$store.description}
label="App Description"
/>
</div>
<style>
.container {
display: grid;
grid-gap: var(--spacing-xl);
}
</style>

View File

@ -1,40 +0,0 @@
<script>
import Integration from "../Integration.svelte"
</script>
<div class="container">
<div class="title">Your Integrations</div>
<div class="integrations">
<Integration remove />
<Integration remove />
<Integration remove />
<Integration remove />
</div>
<div class="apps">Recommended apps</div>
<div class="integrations">
<Integration />
<Integration />
<Integration />
<Integration />
</div>
</div>
<style>
.container {
display: grid;
grid-gap: 16px;
}
.integrations {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 20px;
}
.title {
font-size: 18px;
font-weight: bold;
}
.apps {
font-size: 14px;
font-weight: bold;
}
</style>

View File

@ -1,5 +0,0 @@
export { default as General } from "./General.svelte"
export { default as Integrations } from "./Integrations.svelte"
export { default as Permissions } from "./Permissions.svelte"
export { default as APIKeys } from "./APIKeys.svelte"
export { default as DangerZone } from "./DangerZone.svelte"

View File

@ -190,11 +190,10 @@
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
gap: var(--spacing-l);
padding: var(--spacing-l) 40px var(--spacing-xl) 40px;
gap: var(--spacing-m);
padding: var(--spacing-xl) 40px;
}
.preview-content {
box-shadow: 0 0 12px rgba(0, 0, 0, 0.05);
flex: 1 1 auto;
}

File diff suppressed because it is too large Load Diff

View File

@ -65,7 +65,9 @@
>
<Provider key="user" data={$authStore} {actions}>
<div id="app-root">
{#key $screenStore.activeLayout._id}
<Component instance={$screenStore.activeLayout.props} />
{/key}
</div>
<NotificationDisplay />
<!-- Key block needs to be outside the if statement or it breaks -->
@ -95,8 +97,6 @@
#app-root {
height: 100%;
width: 100%;
overflow-y: auto;
overflow-x: hidden;
position: relative;
}
</style>

View File

@ -54,7 +54,6 @@
children: children.length,
styles: { ...instance._styles, id, empty, interactive },
empty,
transition: instance._transition,
selected,
props: componentProps,
name,

View File

@ -41,6 +41,5 @@
<style>
div {
position: relative;
overflow-x: auto;
}
</style>

View File

@ -34,7 +34,7 @@
// Vertically, always render above unless no room, then render inside
let newTop = elBounds.top + scrollY - verticalOffset - height
if (newTop < 0) {
newTop = elBounds.top + scrollY + verticalOffset
newTop = 0
}
// Horizontally, try to center first.

View File

@ -7,7 +7,6 @@ import {
builderStore,
} from "./store"
import { styleable } from "./utils/styleable"
import transition from "./utils/transition"
import { linkable } from "./utils/linkable"
import { getAction } from "./utils/getAction"
import Provider from "./components/Provider.svelte"
@ -21,7 +20,6 @@ export default {
screenStore,
builderStore,
styleable,
transition,
linkable,
getAction,
Provider,

View File

@ -1,16 +0,0 @@
import { fade, blur, scale, fly } from "svelte/transition"
// Default options
const transitions = new Map([
["fade", { tn: fade, opt: {} }],
["blur", { tn: blur, opt: {} }],
// This one seems to not result in any effect
// ["slide", { tn: slide, opt: {} }],
["scale", { tn: scale, opt: {} }],
["fly", { tn: fly, opt: { y: 80 } }],
])
export default function transition(node, { type, options = {} }) {
const { tn, opt } = transitions.get(type) || { tn: () => {}, opt: {} }
return tn(node, { ...opt, ...options })
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,7 @@
const { EMPTY_LAYOUT } = require("../../constants/layouts")
const {
EMPTY_LAYOUT,
BASE_LAYOUT_PROP_IDS,
} = require("../../constants/layouts")
const CouchDB = require("../../db")
const { generateLayoutID, getScreenParams } = require("../../db/utils")
@ -26,6 +29,9 @@ exports.destroy = async function (ctx) {
const layoutId = ctx.params.layoutId,
layoutRev = ctx.params.layoutRev
if (Object.values(BASE_LAYOUT_PROP_IDS).includes(layoutId)) {
ctx.throw(400, "Cannot delete a built-in layout")
} else {
const layoutsUsedByScreens = (
await db.allDocs(
getScreenParams(null, {
@ -36,6 +42,7 @@ exports.destroy = async function (ctx) {
if (layoutsUsedByScreens.includes(layoutId)) {
ctx.throw(400, "Cannot delete a layout that's being used by a screen")
}
}
await db.remove(layoutId, layoutRev)
ctx.body = { message: "Layout deleted successfully" }

View File

@ -10,7 +10,7 @@ const EMPTY_LAYOUT = {
stylesheets: [],
props: {
_id: "30b8822a-d07b-49f4-9531-551e37c6899b",
_component: "@budibase/standard-components/container",
_component: "@budibase/standard-components/layout",
_children: [
{
_id: "7fcf11e4-6f5b-4085-8e0d-9f3d44c98967",
@ -22,9 +22,6 @@ const EMPTY_LAYOUT = {
"flex-direction": "column",
"justify-content": "flex-start",
"align-items": "stretch",
"max-width": "100%",
width: "1400px",
padding: "20px",
},
hover: {},
active: {},
@ -36,16 +33,17 @@ const EMPTY_LAYOUT = {
_styles: {
active: {},
hover: {},
normal: {
"min-height": "100%",
"background-image": "#f5f5f5",
},
normal: {},
selected: {},
},
direction: "column",
hAlign: "center",
vAlign: "top",
size: "grow",
navigation: "Top",
width: "Large",
links: [
{
text: "Home",
url: "/",
},
],
},
}
@ -56,83 +54,11 @@ const BASE_LAYOUTS = [
title: "{{ name }}",
favicon: "./_shared/favicon.png",
stylesheets: [],
name: "Top Navigation Layout",
name: "Navigation Layout",
props: {
_id: "4f569166-a4f3-47ea-a09e-6d218c75586f",
_component: "@budibase/standard-components/container",
_component: "@budibase/standard-components/layout",
_children: [
{
_id: "c74f07266980c4b6eafc33e2a6caa783d",
_component: "@budibase/standard-components/container",
_styles: {
normal: {
background: "#fff",
width: "100%",
"box-shadow": "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
},
hover: {},
active: {},
selected: {},
},
_instanceName: "Header",
_children: [
{
_id: "49e0e519-9e5e-4127-885a-ee6a0a49e2c1",
_component: "@budibase/standard-components/navigation",
_styles: {
normal: {
"max-width": "1400px",
padding: "20px",
"font-weight": "400",
"font-size": "16px",
flex: "1 1 auto",
},
hover: {},
active: {},
selected: {},
},
title: "",
backgroundColor: "",
color: "",
borderWidth: "",
borderColor: "",
borderStyle: "",
_instanceName: "Navigation",
_children: [
{
_id: "48b35328-4c91-4343-a6a3-1a1fd77b3386",
_component: "@budibase/standard-components/link",
_styles: {
normal: {
"font-weight": "600",
"text-decoration-line": "none",
"font-size": "16px",
},
hover: {
color: "#4285f4",
},
active: {},
selected: {},
},
url: "/",
openInNewTab: false,
text: "Home",
color: "",
hoverColor: "",
underline: false,
fontSize: "",
fontFamily: "initial",
_instanceName: "Home Link",
_children: [],
},
],
},
],
direction: "row",
hAlign: "center",
vAlign: "middle",
size: "shrink",
},
{
_id: "7fcf11e4-6f5b-4085-8e0d-9f3d44c98967",
_component: "@budibase/standard-components/screenslot",
@ -143,9 +69,6 @@ const BASE_LAYOUTS = [
"flex-direction": "column",
"justify-content": "flex-start",
"align-items": "stretch",
"max-width": "100%",
width: "1400px",
padding: "20px",
},
hover: {},
active: {},
@ -157,16 +80,17 @@ const BASE_LAYOUTS = [
_styles: {
active: {},
hover: {},
normal: {
"min-height": "100%",
background: "#f5f5f5",
},
normal: {},
selected: {},
},
direction: "column",
hAlign: "center",
vAlign: "top",
size: "grow",
navigation: "Top",
width: "Large",
links: [
{
text: "Home",
url: "/",
},
],
},
},
{
@ -178,7 +102,7 @@ const BASE_LAYOUTS = [
name: "Empty Layout",
props: {
_id: "3723ffa1-f9e0-4c05-8013-98195c788ed6",
_component: "@budibase/standard-components/container",
_component: "@budibase/standard-components/layout",
_children: [
{
_id: "7fcf11e4-6f5b-4085-8e0d-9f3d44c98967",
@ -190,9 +114,6 @@ const BASE_LAYOUTS = [
"flex-direction": "column",
"justify-content": "flex-start",
"align-items": "stretch",
"max-width": "100%",
width: "1400px",
padding: "20px",
},
hover: {},
active: {},
@ -204,16 +125,17 @@ const BASE_LAYOUTS = [
_styles: {
active: {},
hover: {},
normal: {
"min-height": "100%",
background: "#f5f5f5",
},
normal: {},
selected: {},
},
direction: "column",
hAlign: "center",
vAlign: "top",
size: "grow",
navigation: "Top",
width: "Large",
links: [
{
text: "Home",
url: "/",
},
],
},
},
]

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,67 @@
{
"layout": {
"name": "Layout",
"description": "This component is specific only to layouts",
"icon": "Sandbox",
"hasChildren": true,
"styleable": true,
"illegalChildren": [],
"settings": [
{
"type": "text",
"label": "Logo URL",
"key": "logoUrl"
},
{
"type": "text",
"label": "Title",
"key": "title"
},
{
"type": "select",
"label": "Navigation",
"key": "navigation",
"options": ["Top", "Left", "None"],
"defaultValue": "Top"
},
{
"type": "select",
"label": "Width",
"key": "width",
"options": ["Small", "Medium", "Large"],
"defaultValue": "Large"
},
{
"type": "navigation",
"label": "Links",
"key": "links"
},
{
"type": "boolean",
"label": "Hide title",
"key": "hideTitle",
"defaultValue": false
},
{
"type": "boolean",
"label": "Hide logo",
"key": "hideLogo",
"defaultValue": false
},
{
"type": "boolean",
"label": "Sticky header",
"key": "sticky",
"defaultValue": false
}
]
},
"container": {
"name": "Container",
"description": "This component contains things within itself",
"icon": "Sandbox",
"hasChildren": true,
"styleable": true,
"transitionable": true,
"showSettingsBar": true,
"settings": [
{
@ -118,6 +174,23 @@
}
]
},
"section": {
"name": "Section",
"description": "Add a section to your application",
"icon": "ColumnTwoB",
"hasChildren": true,
"styleable": true,
"illegalChildren": ["section"],
"showEmptyState": false,
"settings": [
{
"type": "section",
"label": "Type",
"key": "type",
"defaultValue": "mainSidebar"
}
]
},
"screenslot": {
"name": "Screenslot",
"icon": "WebPage",
@ -128,6 +201,7 @@
"name": "Button",
"description": "A basic html button that is ready for styling",
"icon": "Button",
"illegalChildren": ["section"],
"styleable": true,
"settings": [
{
@ -158,6 +232,11 @@
"type": "event",
"label": "On Click",
"key": "onClick"
},
{
"type": "boolean",
"label": "Disabled",
"key": "disabled"
}
]
},
@ -166,6 +245,7 @@
"description": "A configurable data list that attaches to your backend tables.",
"icon": "ViewList",
"styleable": true,
"illegalChildren": ["section"],
"hasChildren": true,
"settings": [
{
@ -194,6 +274,7 @@
"icon": "TaskList",
"description": "A basic card component that can contain content and actions.",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "text",
@ -223,6 +304,7 @@
"description": "A basic card component that can contain content and actions.",
"icon": "ViewColumn",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "text",
@ -283,6 +365,7 @@
"description": "A component for displaying paragraph text.",
"icon": "TextParagraph",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "text",
@ -296,6 +379,7 @@
"icon": "TextBold",
"description": "A component for displaying heading text",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "text",
@ -316,6 +400,7 @@
"description": "A basic component for displaying images",
"icon": "Image",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "text",
@ -329,6 +414,7 @@
"description": "A background image",
"icon": "Images",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "text",
@ -386,6 +472,7 @@
"description": "A basic component for displaying icons",
"icon": "Bell",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "icon",
@ -433,6 +520,7 @@
"description": "A component for handling the navigation within your app.",
"icon": "BreadcrumbNavigation",
"styleable": true,
"illegalChildren": ["section"],
"hasChildren": true,
"settings": [
{
@ -453,6 +541,7 @@
"description": "A basic link component for internal and external links",
"icon": "Link",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "text",
@ -482,6 +571,7 @@
"description": "A basic card component that can contain content and actions.",
"icon": "ViewRow",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "text",
@ -554,6 +644,7 @@
"description": "A card component for displaying numbers.",
"icon": "Card",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "text",
@ -580,6 +671,7 @@
"icon": "Code",
"description": "Embed content from 3rd party sources",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "text",
@ -593,6 +685,7 @@
"description": "Bar chart",
"icon": "GraphBarVertical",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "text",
@ -693,6 +786,7 @@
"description": "Line chart",
"icon": "GraphTrend",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "text",
@ -794,6 +888,7 @@
"description": "Line chart",
"icon": "GraphAreaStacked",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "text",
@ -907,6 +1002,7 @@
"description": "Pie chart",
"icon": "GraphPie",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "text",
@ -984,6 +1080,7 @@
"description": "Donut chart",
"icon": "GraphDonut",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "text",
@ -1061,6 +1158,7 @@
"description": "Candlestick chart",
"icon": "GraphBarVerticalStacked",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "text",
@ -1143,6 +1241,7 @@
"icon": "Form",
"styleable": true,
"hasChildren": true,
"illegalChildren": ["section"],
"actions": [
"ValidateForm"
],
@ -1214,6 +1313,7 @@
"name": "Field Group",
"icon": "Group",
"styleable": true,
"illegalChildren": ["section"],
"hasChildren": true,
"settings": [
{
@ -1242,6 +1342,7 @@
"name": "Text Field",
"icon": "Text",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "field/string",
@ -1270,6 +1371,7 @@
"name": "Number Field",
"icon": "123",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "field/number",
@ -1298,6 +1400,7 @@
"name": "Password Field",
"icon": "LockClosed",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "field/string",
@ -1326,6 +1429,7 @@
"name": "Options Picker",
"icon": "ViewList",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "field/options",
@ -1355,6 +1459,7 @@
"name": "Checkbox",
"icon": "Checkmark",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "field/boolean",
@ -1383,6 +1488,7 @@
"name": "Rich Text",
"icon": "TextParagraph",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "field/longform",
@ -1412,6 +1518,7 @@
"name": "Date Picker",
"icon": "DateInput",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "field/datetime",
@ -1446,6 +1553,7 @@
"name": "Attachment",
"icon": "Attach",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "field/attachment",
@ -1469,6 +1577,7 @@
"name": "Relationship Picker",
"icon": "TaskList",
"styleable": true,
"illegalChildren": ["section"],
"settings": [
{
"type": "field/link",
@ -1498,6 +1607,7 @@
"info": "Pagination is only available for data stored in internal tables.",
"icon": "Data",
"styleable": false,
"illegalChildren": ["section"],
"hasChildren": true,
"settings": [
{
@ -1561,6 +1671,7 @@
"name": "Table",
"icon": "Table",
"styleable": true,
"illegalChildren": ["section"],
"hasChildren": true,
"showEmptyState": false,
"settings": [

View File

@ -33,6 +33,7 @@
"license": "MIT",
"gitHead": "d1836a898cab3f8ab80ee6d8f42be1a9eed7dcdc",
"dependencies": {
"@spectrum-css/link": "^3.1.3",
"@budibase/bbui": "^0.9.53",
"@spectrum-css/page": "^3.0.1",
"@spectrum-css/vars": "^3.0.1",

View File

@ -1,7 +1,7 @@
<script>
import { getContext } from "svelte"
const { styleable, transition } = getContext("sdk")
const { styleable } = getContext("sdk")
const component = getContext("component")
export let direction
@ -17,7 +17,6 @@
<div
class={[directionClass, hAlignClass, vAlignClass, sizeClass].join(" ")}
in:transition={{ type: $component.transition }}
use:styleable={$component.styles}
>
<slot />

View File

@ -0,0 +1,337 @@
<script>
import { getContext } from "svelte"
import { Heading, Icon } from "@budibase/bbui"
const { styleable, linkable } = getContext("sdk")
const component = getContext("component")
export let title
export let hideTitle = false
export let logoUrl
export let hideLogo = false
export let navigation = "Top"
export let sticky = false
export let links
export let width = "Large"
const navigationClasses = {
Top: "top",
Left: "left",
None: "none",
}
const widthClasses = {
Large: "l",
Medium: "m",
Small: "s",
}
$: validLinks = links?.filter(link => link.text && link.url) || []
$: typeClass = navigationClasses[navigation] || "none"
$: widthClass = widthClasses[width] || "l"
let mobileOpen = false
const isInternal = url => {
return url.startsWith("/")
}
const ensureExternal = url => {
return !url.startsWith("http") ? `http://${url}` : url
}
const close = () => {
mobileOpen = false
}
</script>
<div class="layout layout--{typeClass}" use:styleable={$component.styles}>
{#if typeClass !== "none"}
<div class="nav-wrapper" class:sticky>
<div class="nav nav--{typeClass} size--{widthClass}">
<div class="nav-header">
{#if validLinks?.length}
<div class="burger">
<Icon
hoverable
name="ShowMenu"
on:click={() => (mobileOpen = !mobileOpen)}
/>
</div>
{/if}
<div class="logo">
{#if !hideLogo}
<img
src={logoUrl || "https://i.imgur.com/Xhdt1YP.png"}
alt={title}
/>
{/if}
{#if !hideTitle && title}
<Heading size="S">{title}</Heading>
{/if}
</div>
<div class="portal">
<Icon
hoverable
name="Apps"
on:click={() => (window.location.href = "/builder/apps")}
/>
</div>
</div>
<div
class="mobile-click-handler"
class:visible={mobileOpen}
on:click={() => (mobileOpen = false)}
/>
{#if validLinks?.length}
<div class="links" class:visible={mobileOpen}>
{#each validLinks as { text, url }}
{#if isInternal(url)}
<a class="link" href={url} use:linkable on:click={close}>
{text}
</a>
{:else}
<a class="link" href={ensureExternal(url)} on:click={close}>
{text}
</a>
{/if}
{/each}
<div class="close">
<Icon
hoverable
name="Close"
on:click={() => (mobileOpen = false)}
/>
</div>
</div>
{/if}
</div>
</div>
{/if}
<div class="main-wrapper">
<div class="main size--{widthClass}">
<slot />
</div>
</div>
</div>
<style>
/* Main components */
.layout {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
height: 100%;
overflow: auto;
}
.nav-wrapper {
display: flex;
flex-direction: row;
justify-content: center;
align-items: stretch;
background: white;
z-index: 1;
box-shadow: 0 0 8px -1px rgba(0, 0, 0, 0.075);
}
.layout--top .nav-wrapper.sticky {
position: sticky;
top: 0;
left: 0;
}
.nav {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
padding: var(--spacing-xl) 32px;
max-width: 100%;
gap: var(--spacing-xl);
}
.nav-header {
flex: 0 0 auto;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
gap: var(--spacing-xl);
}
.main-wrapper {
display: flex;
flex-direction: row;
justify-content: center;
align-items: stretch;
flex: 1 1 auto;
}
.main {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
max-width: 100%;
position: relative;
padding: 32px;
}
.size--s {
width: 800px;
}
.size--m {
width: 1100px;
}
.size--l {
width: 1400px;
}
/* Nav components */
.burger {
display: none;
}
.logo {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
gap: var(--spacing-m);
flex: 1 1 auto;
}
.logo img {
height: 36px;
}
.logo :global(h1) {
font-weight: 600;
flex: 1 1 auto;
width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.portal {
display: grid;
place-items: center;
}
.links {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
gap: var(--spacing-xl);
margin-top: var(--spacing-xl);
}
.link {
color: var(--spectrum-alias-text-color);
font-size: var(--spectrum-global-dimension-font-size-200);
font-weight: 600;
transition: color 130ms ease-out;
}
.link:hover {
color: var(--spectrum-global-color-blue-600);
}
.close {
display: none;
position: absolute;
top: var(--spacing-xl);
right: var(--spacing-xl);
}
.mobile-click-handler {
display: none;
}
/* Desktop nav overrides */
@media (min-width: 600px) {
.layout--left {
flex-direction: row;
overflow: hidden;
}
.layout--left .main-wrapper {
height: 100%;
overflow: auto;
}
.nav--left {
width: 250px;
padding: var(--spacing-xl);
}
.nav--left .links {
margin-top: var(--spacing-m);
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
}
.nav--left .link {
font-size: var(--spectrum-global-dimension-font-size-150);
}
}
/* Mobile nav overrides */
@media (max-width: 600px) {
.nav-wrapper {
position: sticky;
top: 0;
left: 0;
box-shadow: 0 0 8px -1px rgba(0, 0, 0, 0.075);
}
/* Show close button in drawer */
.close {
display: block;
}
/* Force standard top bar */
.nav {
padding: var(--spacing-m) 16px;
}
.burger {
display: grid;
place-items: center;
}
.logo {
flex: 0 0 auto;
}
.logo :global(h1) {
display: none;
}
/* Reduce padding */
.main {
padding: 16px;
}
/* Transform links into drawer */
.links {
margin-top: 0;
position: fixed;
top: 0;
left: -250px;
transform: translateX(0);
width: 250px;
transition: transform 0.26s ease-in-out, opacity 0.26s ease-in-out;
height: 100vh;
opacity: 0;
background: white;
z-index: 999;
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
padding: var(--spacing-xl);
}
.link {
width: calc(100% - 30px);
font-size: 120%;
}
.links.visible {
opacity: 1;
transform: translateX(250px);
box-shadow: 0 0 40px 20px rgba(0, 0, 0, 0.1);
}
.mobile-click-handler.visible {
position: fixed;
display: block;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 998;
}
}
</style>

View File

@ -7,7 +7,7 @@
const component = getContext("component")
</script>
<div use:styleable={$component.styles}>
<div use:styleable={{ ...$component.styles, empty: true }}>
<h1>Screen Slot</h1>
<span>
The screens that you create will be displayed inside this box.
@ -20,13 +20,16 @@
div {
display: flex !important;
flex-direction: column !important;
align-items: center !important;
justify-content: center !important;
padding: 20px !important;
align-items: center !important;
padding: 32px !important;
text-align: center !important;
border-style: dashed !important;
border-width: 1px !important;
color: #000000 !important;
background-color: rgba(0, 0, 0, 0.05) !important;
}
h1 {
color: var(--spectrum-alias-text-color);
}
span {
font-size: var(--font-size-s);
color: var(--grey-6);
}
</style>

View File

@ -0,0 +1,73 @@
<script>
import { getContext } from "svelte"
import Placeholder from "./Placeholder.svelte"
const { styleable, builderStore } = getContext("sdk")
const component = getContext("component")
export let type = "mainSidebar"
export let minSize = 250
let layoutMap = {
mainSidebar: 2,
sidebarMain: 2,
twoColumns: 2,
threeColumns: 3,
}
let containerWidth
$: columnsDependingOnSize = calculateColumns(containerWidth)
function calculateColumns(parentWidth) {
const numberOfAllowedColumns = Math.floor(parentWidth / minSize) || 100
if (layoutMap[type] <= numberOfAllowedColumns) {
return false
} else if (layoutMap[type] > numberOfAllowedColumns) {
return numberOfAllowedColumns
}
}
</script>
<div
bind:clientWidth={containerWidth}
class="{type} columns-{columnsDependingOnSize}"
use:styleable={$component.styles}
>
<slot />
{#if layoutMap[type] - $component.children > 0}
{#each new Array(layoutMap[type] - $component.children) as _}
<div class:placeholder={$builderStore.inBuilder}>
<Placeholder />
</div>
{/each}
{/if}
</div>
<style>
div {
display: grid;
grid-gap: 16px;
}
.mainSidebar {
grid-template-columns: 3fr 1fr;
}
.sidebarMain {
grid-template-columns: 1fr 3fr;
}
.twoColumns {
grid-template-columns: 1fr 1fr;
}
.threeColumns {
grid-template-columns: 1fr 1fr 1fr;
}
.columns-1 {
grid-template-columns: 1fr;
}
.columns-2 {
grid-template-columns: 1fr 1fr;
}
.placeholder {
border: 2px dashed var(--grey-5);
padding: var(--spacing-l);
}
</style>

View File

@ -15,6 +15,7 @@ export { default as Placeholder } from "./Placeholder.svelte"
// User facing components
export { default as container } from "./Container.svelte"
export { default as section } from "./Section.svelte"
export { default as dataprovider } from "./DataProvider.svelte"
export { default as screenslot } from "./ScreenSlot.svelte"
export { default as button } from "./Button.svelte"
@ -23,6 +24,7 @@ export { default as stackedlist } from "./StackedList.svelte"
export { default as card } from "./Card.svelte"
export { default as text } from "./Text.svelte"
export { default as navigation } from "./Navigation.svelte"
export { default as layout } from "./Layout.svelte"
export { default as link } from "./Link.svelte"
export { default as heading } from "./Heading.svelte"
export { default as image } from "./Image.svelte"

View File

@ -2,6 +2,59 @@
# yarn lockfile v1
"@adobe/spectrum-css-workflow-icons@^1.2.1":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@adobe/spectrum-css-workflow-icons/-/spectrum-css-workflow-icons-1.2.1.tgz#7e2cb3fcfb5c8b12d7275afafbb6ec44913551b4"
integrity sha512-uVgekyBXnOVkxp+CUssjN/gefARtudZC8duEn1vm0lBQFwGRZFlDEzU1QC+aIRWCrD1Z8OgRpmBYlSZ7QS003w==
"@budibase/bbui@^0.9.53":
version "0.9.53"
resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.53.tgz#b6841a31ff2c28feb929c57f7f10a1dae1b3aea3"
integrity sha512-jO11Ky1KhPGRv922jMRO49FeTY1TeF3u2JaBJYBkVY95il3uPOI20M1AdA6w2emppDlyP6FSEHk+prdra4Lndw==
dependencies:
"@adobe/spectrum-css-workflow-icons" "^1.2.1"
"@spectrum-css/actionbutton" "^1.0.1"
"@spectrum-css/actiongroup" "^1.0.1"
"@spectrum-css/avatar" "^3.0.2"
"@spectrum-css/button" "^3.0.1"
"@spectrum-css/buttongroup" "^3.0.2"
"@spectrum-css/checkbox" "^3.0.2"
"@spectrum-css/dialog" "^3.0.1"
"@spectrum-css/divider" "^1.0.1"
"@spectrum-css/dropzone" "^3.0.2"
"@spectrum-css/fieldgroup" "^3.0.2"
"@spectrum-css/fieldlabel" "^3.0.1"
"@spectrum-css/icon" "^3.0.1"
"@spectrum-css/illustratedmessage" "^3.0.2"
"@spectrum-css/inputgroup" "^3.0.2"
"@spectrum-css/label" "^2.0.10"
"@spectrum-css/link" "^3.1.1"
"@spectrum-css/menu" "^3.0.1"
"@spectrum-css/modal" "^3.0.1"
"@spectrum-css/pagination" "^3.0.3"
"@spectrum-css/picker" "^1.0.1"
"@spectrum-css/popover" "^3.0.1"
"@spectrum-css/progressbar" "^1.0.2"
"@spectrum-css/progresscircle" "^1.0.2"
"@spectrum-css/radio" "^3.0.2"
"@spectrum-css/search" "^3.0.2"
"@spectrum-css/sidenav" "^3.0.2"
"@spectrum-css/statuslight" "^3.0.2"
"@spectrum-css/switch" "^1.0.2"
"@spectrum-css/table" "^3.0.1"
"@spectrum-css/tabs" "^3.0.1"
"@spectrum-css/tags" "^3.0.2"
"@spectrum-css/textfield" "^3.0.1"
"@spectrum-css/toast" "^3.0.1"
"@spectrum-css/tooltip" "^3.0.3"
"@spectrum-css/treeview" "^3.0.2"
"@spectrum-css/typography" "^3.0.1"
"@spectrum-css/underlay" "^2.0.9"
"@spectrum-css/vars" "^3.0.1"
dayjs "^1.10.4"
svelte-flatpickr "^3.1.0"
svelte-portal "^1.0.0"
"@rollup/pluginutils@^4.1.0":
version "4.1.0"
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.1.0.tgz#0dcc61c780e39257554feb7f77207dceca13c838"
@ -10,6 +63,98 @@
estree-walker "^2.0.1"
picomatch "^2.2.2"
"@spectrum-css/actionbutton@^1.0.1":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/actionbutton/-/actionbutton-1.0.3.tgz#8f7342a69b303c5acdcfa0a59f5e9267b9f3cb30"
integrity sha512-P9qoCPSiZ1SB6ZYqK5hub0vGty00YYqonQE0KTjtb1i+T1nYR/87vWqVPERx9j63uhgZncjwFYaThTvRqye7eQ==
"@spectrum-css/actiongroup@^1.0.1":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/actiongroup/-/actiongroup-1.0.3.tgz#4713ce65e6f5c72c404a7b638fbc3b4fd7e3874f"
integrity sha512-NlB9Q4ZlWixXxymoPIYG6g2hkwAGKFodHWPFfxHD8ddkjXWRB9G2akUP7cfsJ4DcYn4VisUORCOYQwqDiSmboQ==
"@spectrum-css/avatar@^3.0.2":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@spectrum-css/avatar/-/avatar-3.0.2.tgz#4f1826223eae330e64b6d3cc899e9bc2e98dac95"
integrity sha512-wEczvSqxttTWSiL3cOvXV/RmGRwSkw2w6+slcHhnf0kb7ovymMM+9oz8vvEpEsSeo5u598bc+7ktrKFpAd6soQ==
"@spectrum-css/button@^3.0.1":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/button/-/button-3.0.3.tgz#2df1efaab6c7e0b3b06cb4b59e1eae59c7f1fc84"
integrity sha512-6CnLPqqtaU/PcSSIGeGRi0iFIIxIUByYLKFO6zn5NEUc12KQ28dJ4PLwB6WBa0L8vRoAGlnWWH2ZZweTijbXgg==
"@spectrum-css/buttongroup@^3.0.2":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/buttongroup/-/buttongroup-3.0.3.tgz#719d868845ac9d2c4f939c1b9f6044507902d5aa"
integrity sha512-eXl8U4QWMWXqyTu654FdQdEGnmczgOYlpIFSHyCMVjhtPqZp2xwnLFiGh6LKw+bLio6eeOZ0L+vpk1GcoYqgkw==
"@spectrum-css/checkbox@^3.0.2":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/checkbox/-/checkbox-3.0.3.tgz#8577067fc8b97e4609f92bd242364937a533a7bb"
integrity sha512-QVG9uMHq+lh70Dh6mDNnY+vEvNz2p7VC6xgLfDYfijp2qeiqYPq72fQK6p/SiyqPk96ZACzNRwgeROU6Xf6Wgg==
"@spectrum-css/dialog@^3.0.1":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/dialog/-/dialog-3.0.3.tgz#7715a4ea435e753afb623d99ca5917ed1bcd6f34"
integrity sha512-AhmKgfRIVyTe3ABiJ8lLUQL34VB/H6fN16na2LlbDRJvyRMzkdN1Xf2i6U3f4OMd3qQ8Gm5xat4BvMxIQPBAUQ==
"@spectrum-css/divider@^1.0.1":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/divider/-/divider-1.0.3.tgz#639e2ebaa0834efa40f42397668bbd5c153ea385"
integrity sha512-Zy4Rn40w8UtzMh3wx/U9+CepSCpm1aOCGftHgWDub0XZuVTzh0c1WwyzTuLCx2Hf21z5VRGNiDh8bGEEzSbtNA==
dependencies:
"@spectrum-css/vars" "^3.0.2"
"@spectrum-css/dropzone@^3.0.2":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/dropzone/-/dropzone-3.0.3.tgz#aee71697a2c195947599d7541b858c3c198741dc"
integrity sha512-ujrswdtB6bHigklyHsm6zomFd6rUnKJ3xVVRjroVF4+ouK4DxK5tX0iVd0EW6AOfOjx4Cc28uyFot3fpxp+MQw==
"@spectrum-css/fieldgroup@^3.0.2":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/fieldgroup/-/fieldgroup-3.0.3.tgz#85d85da048d08200f25ceab378026dd2b11e0bb2"
integrity sha512-wXUXTXN1CPnR7M4Ltd+3uh7BfcNGUV1+Xe0/h0tCpq/j+S2Sd4xo7/pUMdU19sIDrAAtpEFp1tt+nouHcU5HGQ==
"@spectrum-css/fieldlabel@^3.0.1":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/fieldlabel/-/fieldlabel-3.0.3.tgz#f73c04d20734d4718ffb620dc46458904685b449"
integrity sha512-nEvIkEXCD5n4fW67Unq6Iu7VXoauEd/JGpfTY02VsC5p4FJLnwKfPDbJUuUsqClAxqw7nAsmXVKtn4zQFf5yPQ==
"@spectrum-css/icon@^3.0.1":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/icon/-/icon-3.0.3.tgz#5c612822380927087aebd526855d82ed2c3e2cba"
integrity sha512-hyloKOejPCXhP3MBNsm3SjR9j8xT1R1S19p32KW/0Qhj+VMUtfyEPmevyFptpn7wcovQccdl/vZVIVDuML/imw==
"@spectrum-css/illustratedmessage@^3.0.2":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@spectrum-css/illustratedmessage/-/illustratedmessage-3.0.2.tgz#6a480be98b027e050b086e7899e40d87adb0a8c0"
integrity sha512-dqnE8X27bGcO0HN8+dYx8O4o0dNNIAqeivOzDHhe2El+V4dTzMrNIerF6G0NLm3GjVf6XliwmitsZK+K6FmbtA==
"@spectrum-css/inputgroup@^3.0.2":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/inputgroup/-/inputgroup-3.0.3.tgz#00c9a370ddc2c55cf0f37dd6069faa9501fd7eb5"
integrity sha512-FqRJTiLL7jiGfzDVXWUGVLqHryJjCcqQIrqAi+Tq0oenapzsBe2qc/zIrKgh2wtMI+NTIBLXTECvij3L1HlqAg==
"@spectrum-css/label@^2.0.10":
version "2.0.10"
resolved "https://registry.yarnpkg.com/@spectrum-css/label/-/label-2.0.10.tgz#2368651d7636a19385b5d300cdf6272db1916001"
integrity sha512-xCbtEiQkZIlLdWFikuw7ifDCC21DOC/KMgVrrVJHXFc4KRQe9LTZSqmGF3tovm+CSq1adE59mYoTbojVQ9YuEQ==
"@spectrum-css/link@^3.1.1", "@spectrum-css/link@^3.1.3":
version "3.1.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/link/-/link-3.1.3.tgz#b0e560a7e0acdb4a2b329b6669696aa3438f5993"
integrity sha512-8Pmy5d73MwKcATTPaj+fSrZYnIw7GmfX40AvpC1xx5LauOxsbUb4AVNp1kn2H8rrOBmxF7czyhoBBhEiv66QUg==
"@spectrum-css/menu@^3.0.1":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/menu/-/menu-3.0.3.tgz#46a9b221bb5f470a2f8a934bdfd512d84d2fdc4d"
integrity sha512-qKA9J/MrikNKIpCEHsAazG2vY3im5tjGCmo6p9Pdnu8/aQMsiuZDHZayukeCttJUZkrb9guDVL9OIHlK5RZvcQ==
"@spectrum-css/modal@^3.0.1":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@spectrum-css/modal/-/modal-3.0.2.tgz#58b6621cab65f90788d310374f40df1f7090473f"
integrity sha512-YnIivJhoaao7Otu+HV7sgebPyFbO6sd/oMvTN/Rb2wwgnaMnIIuIRdGandSrcgotN2uNgs+P0knG6mv/xA1/dg==
"@spectrum-css/page@^3.0.1":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@spectrum-css/page/-/page-3.0.2.tgz#8f0c03d25f5565fb13115541a8fcaf0e1d3a8ee0"
@ -17,6 +162,101 @@
dependencies:
"@spectrum-css/vars" "^3.0.2"
"@spectrum-css/pagination@^3.0.3":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/pagination/-/pagination-3.0.3.tgz#b204c3ada384c4af751a354bc428346d82eeea65"
integrity sha512-OJ/v9GeNXJOZ9Yr9LDBYPrR2NCiLOWP9wANT/a5sqFuugRnQbn/HYMnRp9TBxwpDY6ihaPo0T/wi7kLiAJFdDw==
"@spectrum-css/picker@^1.0.1":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/picker/-/picker-1.0.3.tgz#21379bcf8ae94277deeb6ad65dcd9e2bbfacb487"
integrity sha512-oHLGxBx5BwVCSGo7/T1C9PTHX1+/5AmVjyLiTJ4UoIdSJmOERw9YcRZbcGZgBJNWbxcjr4TyGtwj1EcSjEy97w==
"@spectrum-css/popover@^3.0.1":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/popover/-/popover-3.0.3.tgz#6fb69873474fb968afb738eacb9e121f93e83a09"
integrity sha512-KvmXv4TV19FBx39KfmgVlDYtvtBqv/8RRK7RRLDDHGViTxZtShjVsVpwIgfkfgn4iJztCnXpWzFqRXWUu2XCpQ==
"@spectrum-css/progressbar@^1.0.2":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/progressbar/-/progressbar-1.0.3.tgz#f70bcc38a2a21cff2f422ec825724ebbb9455e67"
integrity sha512-vJHplefUuy8+NjCw1X7fLbqHVGNVBpvGFXNAeaIj4SFf4ygxiUq/5c9iRhhsCQixEsJlfD/b7BnGXU7BUDkr6Q==
"@spectrum-css/progresscircle@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@spectrum-css/progresscircle/-/progresscircle-1.0.2.tgz#258ea9170fb70f795edda03e38a61d93bef4487c"
integrity sha512-JLULpyzjIY95lzlWR1yE1gv4l1K6p+scQ+edmuZZUHBzwM3pUtkvHJmUlA9TYdResUYW6Uka60VRdY6lZ8gnFQ==
"@spectrum-css/radio@^3.0.2":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/radio/-/radio-3.0.3.tgz#25c3bc5e9c30a8a8ae728717b7c7fb736cdae640"
integrity sha512-LaLGfz/eGNR2iyqouXYILIA+pKRqF769iPdwM0REm5RpWvMQDD7rPZ/kWlg18owjaFsyllEp25gEjmhRJIIVOw==
"@spectrum-css/search@^3.0.2":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/search/-/search-3.0.3.tgz#3415dc106aca0d5dd996e87084a1b47c2b95a882"
integrity sha512-kdLpKTt0obljuhS1q1tukujRlvSs8sBwij76D4Qp8KpMzwePfZyvv1kYzuWPNZfTeISxWsmyZ6Wxd1uvzjn+UA==
"@spectrum-css/sidenav@^3.0.2":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/sidenav/-/sidenav-3.0.3.tgz#132141fbd2500a927c312fa4e1d712c438b3d597"
integrity sha512-cQ+CgwjxGftrcc79i1XnGd66QTl7H7zopSU0UTV4Qq7hvqfrjjWxfZ6b+3tezrrhNlDope1ff9o8sm67PsPXtg==
"@spectrum-css/statuslight@^3.0.2":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@spectrum-css/statuslight/-/statuslight-3.0.2.tgz#dc54b6cd113413dcdb909c486b5d7bae60db65c5"
integrity sha512-xodB8g8vGJH20XmUj9ZsPlM1jHrGeRbvmVXkz0q7YvQrYAhim8pP3W+XKKZAletPFAuu8cmUOc6SWn6i4X4z6w==
"@spectrum-css/switch@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@spectrum-css/switch/-/switch-1.0.2.tgz#f0b4c69271964573e02b08e90998096e49e1de44"
integrity sha512-zqmHpgWPNg1gEwdUNFYV3CBX5JaeALfIqcJIxE0FLZqr9d1C4+oLE0ItIFzt1bwr4bFAOmkEpvtiY+amluzGxQ==
"@spectrum-css/table@^3.0.1":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/table/-/table-3.0.3.tgz#7f7f19905ef3275cbf907ce3a5818e63c30b2caf"
integrity sha512-nxwzVjLPsXoY/v4sdxOVYLcC+cEbGgJyLcLclT5LT9MGSbngFeUMJzzVR4EvehzuN4dH7hrATG7Mbuq29Mf0Hg==
"@spectrum-css/tabs@^3.0.1":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/tabs/-/tabs-3.0.3.tgz#51dd6f168c897b0fdc3a7e9f901df7bd2288b4fc"
integrity sha512-iLP1I72bJWz9APdQB1jiw+pOv5a7N+hYOCJvRoc56Us/hJKVzowkyGRe3uH+8v36nCG9bHxiAQNLoU8eXisVrg==
"@spectrum-css/tags@^3.0.2":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/tags/-/tags-3.0.3.tgz#fc76d2735cdc442de91b7eb3bee49a928c0767ac"
integrity sha512-SL8vPxVDfWcY5VdIuyl0TImEXcOU1I7yCyXkk7MudMwfnYs81FaIyY32hFV9OHj0Tz/36UzRzc7AVMSuRQ53pw==
"@spectrum-css/textfield@^3.0.1":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@spectrum-css/textfield/-/textfield-3.0.2.tgz#907f62d2dc82852dd6236a820be99e252b531631"
integrity sha512-nkFgAb0cP4jUodkUBErMNfyF78jJLtgL1Mrr9/rvGpGobo10IAbb8zZY4CkZ64o8XmMy/85+wZTKcx+KHatqpg==
"@spectrum-css/toast@^3.0.1":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/toast/-/toast-3.0.3.tgz#97c1527384707600832ecda35643ed304615250f"
integrity sha512-CjLeaMs+cjUXojCCRtbj0YkD2BoZW16kjj2o5omkEpUTjA34IJ8xJ1a+CCtDILWekhXvN0MBN4sbumcnwcnx8w==
"@spectrum-css/tooltip@^3.0.3":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/tooltip/-/tooltip-3.0.3.tgz#26b8ca3b3d30e29630244d85eb4fc11d0c841281"
integrity sha512-ztRF7WW1FzyNavXBRc+80z67UoOrY9wl3cMYsVD3MpDnyxdzP8cjza1pCcolKBaFqRTcQKkxKw3GWtGICRKR5A==
"@spectrum-css/treeview@^3.0.2":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@spectrum-css/treeview/-/treeview-3.0.3.tgz#aeda5175158b9f8d7529cb2b394428eb2a428046"
integrity sha512-D5gGzZC/KtRArdx86Mesc9+99W9nTbUOeyYGqoJoAfJSOttoT6Tk5CrDvlCmAqjKf5rajemAkGri1ChqvUIwkw==
"@spectrum-css/typography@^3.0.1":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@spectrum-css/typography/-/typography-3.0.2.tgz#ea3ca0a60e18064527819d48c8c4364cab4fcd38"
integrity sha512-5ZOLmQe0edzsDMyhghUd4hBb5uxGsFrxzf+WasfcUw9klSfTsRZ09n1BsaaWbgrLjlMQ+EEHS46v5VNo0Ms2CA==
"@spectrum-css/underlay@^2.0.9":
version "2.0.10"
resolved "https://registry.yarnpkg.com/@spectrum-css/underlay/-/underlay-2.0.10.tgz#8b75b646605a311850f6620caa18d4996cd64ed7"
integrity sha512-PmsmkzeGD/rY4pp3ILXHt9w8BW7uaEqXe08hQRS7rGki7wqCpG4mE0/8N3yEcA3QxWQclmG9gdkg5uz6wMmYzA==
"@spectrum-css/vars@^3.0.1", "@spectrum-css/vars@^3.0.2":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@spectrum-css/vars/-/vars-3.0.2.tgz#ea9062c3c98dfc6ba59e5df14a03025ad8969999"
@ -80,7 +320,7 @@ colorette@^1.2.2:
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94"
integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==
dayjs@^1.10.5:
dayjs@^1.10.4, dayjs@^1.10.5:
version "1.10.5"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.5.tgz#5600df4548fc2453b3f163ebb2abbe965ccfb986"
integrity sha512-BUFis41ikLz+65iH6LHQCDm4YPMj5r1YFLdupPIyM4SGcXMmtiLQ7U37i+hGS8urIuqe7I/ou3IS1jVc4nbN4g==
@ -231,6 +471,11 @@ svelte-hmr@^0.14.2:
resolved "https://registry.yarnpkg.com/svelte-hmr/-/svelte-hmr-0.14.4.tgz#b7ef2bfeef23916e0e912828c50645ca572ac355"
integrity sha512-kItFF7vqzStckSigoFmMnxJpTOdB9TWnQAW6Js+yAB4277tLbJIIE5KBlGHNmJNpA7MguqidsPB27Uw5UzQPCA==
svelte-portal@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/svelte-portal/-/svelte-portal-1.0.0.tgz#36a47c5578b1a4d9b4dc60fa32a904640ec4cdd3"
integrity sha512-nHf+DS/jZ6jjnZSleBMSaZua9JlG5rZv9lOGKgJuaZStfevtjIlUJrkLc3vbV8QdBvPPVmvcjTlazAzfKu0v3Q==
svelte@^3.38.2:
version "3.38.2"
resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.38.2.tgz#55e5c681f793ae349b5cc2fe58e5782af4275ef5"