Merge
This commit is contained in:
parent
447523a4b8
commit
07e5f04b6a
|
@ -1,21 +0,0 @@
|
||||||
<script>
|
|
||||||
import { getContext } from "svelte"
|
|
||||||
|
|
||||||
export let title
|
|
||||||
|
|
||||||
const createPaneStore = getContext("createPaneStore")
|
|
||||||
|
|
||||||
$: paneStore = createPaneStore(title)
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{#if $paneStore}
|
|
||||||
<div class="pane">
|
|
||||||
<slot />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.pane {
|
|
||||||
padding: var(--spacing-l);
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,112 +0,0 @@
|
||||||
<script>
|
|
||||||
import { setContext } from "svelte"
|
|
||||||
import { writable, get } from "svelte/store"
|
|
||||||
import { Icon, Body, Button } from "@budibase/bbui"
|
|
||||||
|
|
||||||
export let icon
|
|
||||||
export let title
|
|
||||||
|
|
||||||
let panes = {}
|
|
||||||
let selectedPaneIdStore = writable(null)
|
|
||||||
|
|
||||||
const createPaneStore = pane => {
|
|
||||||
const id = crypto.randomUUID()
|
|
||||||
|
|
||||||
return {
|
|
||||||
subscribe: callback => {
|
|
||||||
panes[id] = pane
|
|
||||||
|
|
||||||
if (get(selectedPaneIdStore) === null) {
|
|
||||||
selectedPaneIdStore.set(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsubscribeSelectedPaneIdStore = selectedPaneIdStore.subscribe(
|
|
||||||
selectedPaneId => callback(selectedPaneId === id)
|
|
||||||
)
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
delete panes[id]
|
|
||||||
panes = panes
|
|
||||||
unsubscribeSelectedPaneIdStore()
|
|
||||||
|
|
||||||
if (get(selectedPaneIdStore) === id) {
|
|
||||||
const ids = Object.keys(panes)
|
|
||||||
|
|
||||||
if (ids.length > 0) {
|
|
||||||
selectedPaneIdStore.set(ids[0])
|
|
||||||
} else {
|
|
||||||
selectedPaneIdStore.set(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setContext("createPaneStore", createPaneStore)
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="panel">
|
|
||||||
<div class="header">
|
|
||||||
<div class="icon">
|
|
||||||
<Icon name={icon} />
|
|
||||||
</div>
|
|
||||||
<Body>{title}</Body>
|
|
||||||
</div>
|
|
||||||
<div class="controls">
|
|
||||||
{#each Object.entries(panes) as [id, pane]}
|
|
||||||
<div class="button" class:active={$selectedPaneIdStore === id}>
|
|
||||||
<Button on:click={() => selectedPaneIdStore.set(id)}>{pane}</Button>
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
<div class="divider" />
|
|
||||||
|
|
||||||
<slot />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.panel {
|
|
||||||
width: 310px;
|
|
||||||
background: var(--background);
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
display: flex;
|
|
||||||
padding: 16px 14px;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
color: var(--grey-6);
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.controls {
|
|
||||||
padding: 0 14px 16px;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button:first-child {
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button :global(button) {
|
|
||||||
border-radius: 4px;
|
|
||||||
border: none;
|
|
||||||
background-color: var(--grey-1);
|
|
||||||
color: var(--ink);
|
|
||||||
}
|
|
||||||
|
|
||||||
.button :global(button):hover {
|
|
||||||
background-color: var(--grey-2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.button.active :global(button) {
|
|
||||||
background-color: var(--grey-2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.divider {
|
|
||||||
border-top: 1px solid var(--grey-3);
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,10 +1,8 @@
|
||||||
<script>
|
<script>
|
||||||
import Panel from "components/design/Panel.svelte"
|
|
||||||
import { get } from "svelte/store"
|
import { get } from "svelte/store"
|
||||||
import { Helpers } from "@budibase/bbui"
|
import { Helpers } from "@budibase/bbui"
|
||||||
import {
|
import {
|
||||||
Input,
|
Input,
|
||||||
Layout,
|
|
||||||
Checkbox,
|
Checkbox,
|
||||||
Banner,
|
Banner,
|
||||||
Select,
|
Select,
|
||||||
|
@ -133,33 +131,24 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Panel
|
{#if $selectedScreen.layoutId}
|
||||||
title={$selectedScreen.routing.route}
|
<Banner
|
||||||
icon={$selectedScreen.routing.route === "/" ? "Home" : "WebPage"}
|
type="warning"
|
||||||
borderLeft
|
extraButtonText="Detach custom layout"
|
||||||
wide
|
extraButtonAction={removeCustomLayout}
|
||||||
>
|
showCloseButton={false}
|
||||||
<Layout gap="S" paddingX="L" paddingY="XL">
|
>
|
||||||
{#if $selectedScreen.layoutId}
|
This screen uses a custom layout, which is deprecated
|
||||||
<Banner
|
</Banner>
|
||||||
type="warning"
|
{/if}
|
||||||
extraButtonText="Detach custom layout"
|
{#each screenSettings as setting (setting.key)}
|
||||||
extraButtonAction={removeCustomLayout}
|
<PropertyControl
|
||||||
showCloseButton={false}
|
control={setting.control}
|
||||||
>
|
label={setting.label}
|
||||||
This screen uses a custom layout, which is deprecated
|
key={setting.key}
|
||||||
</Banner>
|
value={Helpers.deepGet($selectedScreen, setting.key)}
|
||||||
{/if}
|
onChange={val => setScreenSetting(setting, val)}
|
||||||
{#each screenSettings as setting (setting.key)}
|
props={{ ...setting.props, error: errors[setting.key] }}
|
||||||
<PropertyControl
|
{bindings}
|
||||||
control={setting.control}
|
/>
|
||||||
label={setting.label}
|
{/each}
|
||||||
key={setting.key}
|
|
||||||
value={Helpers.deepGet($selectedScreen, setting.key)}
|
|
||||||
onChange={val => setScreenSetting(setting, val)}
|
|
||||||
props={{ ...setting.props, error: errors[setting.key] }}
|
|
||||||
{bindings}
|
|
||||||
/>
|
|
||||||
{/each}
|
|
||||||
</Layout>
|
|
||||||
</Panel>
|
|
|
@ -1,98 +0,0 @@
|
||||||
<script>
|
|
||||||
import Pane from "components/design/Pane.svelte"
|
|
||||||
import {
|
|
||||||
Layout,
|
|
||||||
Label,
|
|
||||||
ColorPicker,
|
|
||||||
notifications,
|
|
||||||
Icon,
|
|
||||||
Body,
|
|
||||||
} from "@budibase/bbui"
|
|
||||||
import { store } from "builderStore"
|
|
||||||
import { get } from "svelte/store"
|
|
||||||
import { DefaultAppTheme } from "constants"
|
|
||||||
|
|
||||||
//These were shifted technically the /theme url is unnecessary
|
|
||||||
import AppThemeSelect from "./theme/AppThemeSelect.svelte"
|
|
||||||
import ButtonRoundnessSelect from "./theme/ButtonRoundnessSelect.svelte"
|
|
||||||
import PropertyControl from "components/design/settings/controls/PropertyControl.svelte"
|
|
||||||
|
|
||||||
$: customTheme = $store.customTheme || {}
|
|
||||||
|
|
||||||
const update = async (property, value) => {
|
|
||||||
try {
|
|
||||||
store.actions.customTheme.save({
|
|
||||||
...get(store).customTheme,
|
|
||||||
[property]: value,
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
notifications.error("Error updating custom theme")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<Pane title="Theme">
|
|
||||||
<div class="info">
|
|
||||||
<div class="infoHeader">
|
|
||||||
<Icon name="InfoOutline" size="S" />
|
|
||||||
<Body size="XS">CHANGES WILL APPLY TO ALL SCREENS</Body>
|
|
||||||
</div>
|
|
||||||
<Body size="S">
|
|
||||||
Your theme is configured for all the screens within your app.
|
|
||||||
</Body>
|
|
||||||
</div>
|
|
||||||
<Layout noPadding gap="S">
|
|
||||||
<Layout noPadding gap="XS">
|
|
||||||
<AppThemeSelect />
|
|
||||||
</Layout>
|
|
||||||
<Layout noPadding gap="XS">
|
|
||||||
<Label>Button roundness</Label>
|
|
||||||
<ButtonRoundnessSelect
|
|
||||||
{customTheme}
|
|
||||||
on:change={e => update("buttonBorderRadius", e.detail)}
|
|
||||||
/>
|
|
||||||
</Layout>
|
|
||||||
<PropertyControl
|
|
||||||
label="Accent color"
|
|
||||||
control={ColorPicker}
|
|
||||||
value={customTheme.primaryColor || DefaultAppTheme.primaryColor}
|
|
||||||
onChange={val => update("primaryColor", val)}
|
|
||||||
props={{
|
|
||||||
spectrumTheme: $store.theme,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<PropertyControl
|
|
||||||
label="Hover"
|
|
||||||
control={ColorPicker}
|
|
||||||
value={customTheme.primaryColorHover || DefaultAppTheme.primaryColorHover}
|
|
||||||
onChange={val => update("primaryColorHover", val)}
|
|
||||||
props={{
|
|
||||||
spectrumTheme: $store.theme,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Layout>
|
|
||||||
</Pane>
|
|
||||||
|
|
||||||
<!-- Add this to its own component -->
|
|
||||||
<style>
|
|
||||||
.infoHeader {
|
|
||||||
display: flex;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.infoHeader :global(svg) {
|
|
||||||
margin-right: 5px;
|
|
||||||
color: var(--grey-6);
|
|
||||||
}
|
|
||||||
|
|
||||||
.infoHeader :global(p) {
|
|
||||||
color: var(--grey-6);
|
|
||||||
}
|
|
||||||
|
|
||||||
.info {
|
|
||||||
background-color: var(--background-alt);
|
|
||||||
padding: 12px;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
Layout,
|
||||||
|
Label,
|
||||||
|
ColorPicker,
|
||||||
|
notifications,
|
||||||
|
Icon,
|
||||||
|
Body,
|
||||||
|
} from "@budibase/bbui"
|
||||||
|
import { store } from "builderStore"
|
||||||
|
import { get } from "svelte/store"
|
||||||
|
import { DefaultAppTheme } from "constants"
|
||||||
|
import AppThemeSelect from "./AppThemeSelect.svelte"
|
||||||
|
import ButtonRoundnessSelect from "./ButtonRoundnessSelect.svelte"
|
||||||
|
import PropertyControl from "components/design/settings/controls/PropertyControl.svelte"
|
||||||
|
|
||||||
|
$: customTheme = $store.customTheme || {}
|
||||||
|
|
||||||
|
const update = async (property, value) => {
|
||||||
|
try {
|
||||||
|
store.actions.customTheme.save({
|
||||||
|
...get(store).customTheme,
|
||||||
|
[property]: value,
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
notifications.error("Error updating custom theme")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="info">
|
||||||
|
<div class="infoHeader">
|
||||||
|
<Icon name="InfoOutline" size="S" />
|
||||||
|
<Body size="XS">CHANGES WILL APPLY TO ALL SCREENS</Body>
|
||||||
|
</div>
|
||||||
|
<Body size="S">
|
||||||
|
Your theme is configured for all the screens within your app.
|
||||||
|
</Body>
|
||||||
|
</div>
|
||||||
|
<Layout noPadding gap="S">
|
||||||
|
<Layout noPadding gap="XS">
|
||||||
|
<AppThemeSelect />
|
||||||
|
</Layout>
|
||||||
|
<Layout noPadding gap="XS">
|
||||||
|
<Label>Button roundness</Label>
|
||||||
|
<ButtonRoundnessSelect
|
||||||
|
{customTheme}
|
||||||
|
on:change={e => update("buttonBorderRadius", e.detail)}
|
||||||
|
/>
|
||||||
|
</Layout>
|
||||||
|
<PropertyControl
|
||||||
|
label="Accent color"
|
||||||
|
control={ColorPicker}
|
||||||
|
value={customTheme.primaryColor || DefaultAppTheme.primaryColor}
|
||||||
|
onChange={val => update("primaryColor", val)}
|
||||||
|
props={{
|
||||||
|
spectrumTheme: $store.theme,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<PropertyControl
|
||||||
|
label="Hover"
|
||||||
|
control={ColorPicker}
|
||||||
|
value={customTheme.primaryColorHover || DefaultAppTheme.primaryColorHover}
|
||||||
|
onChange={val => update("primaryColorHover", val)}
|
||||||
|
props={{
|
||||||
|
spectrumTheme: $store.theme,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Layout>
|
||||||
|
|
||||||
|
<!-- Add this to its own component -->
|
||||||
|
<style>
|
||||||
|
.infoHeader {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoHeader :global(svg) {
|
||||||
|
margin-right: 5px;
|
||||||
|
color: var(--grey-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.infoHeader :global(p) {
|
||||||
|
color: var(--grey-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
background-color: var(--background-alt);
|
||||||
|
padding: 12px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,15 +1,51 @@
|
||||||
<script>
|
<script>
|
||||||
import RightPanel from "components/design/RightPanel.svelte"
|
import GeneralPanel from "./GeneralPanel.svelte"
|
||||||
import GeneralPane from "./GeneralPane.svelte"
|
import ThemePanel from "./ThemePanel.svelte"
|
||||||
import ThemePane from "./ThemePane.svelte"
|
|
||||||
|
|
||||||
import { selectedScreen } from "builderStore"
|
import { selectedScreen } from "builderStore"
|
||||||
|
import Panel from "components/design/Panel.svelte"
|
||||||
|
import { capitalise } from "helpers"
|
||||||
|
import { ActionButton, Layout } from "@budibase/bbui"
|
||||||
|
|
||||||
|
let activeTab = "settings"
|
||||||
|
const tabs = ["settings", "theme"]
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<RightPanel
|
<Panel
|
||||||
title={$selectedScreen.routing.route}
|
title={$selectedScreen.routing.route}
|
||||||
icon={$selectedScreen.routing.route === "/" ? "Home" : "WebPage"}
|
icon={$selectedScreen.routing.route === "/" ? "Home" : "WebPage"}
|
||||||
|
borderLeft
|
||||||
|
wide
|
||||||
>
|
>
|
||||||
<GeneralPane />
|
<div slot="panel-header-content">
|
||||||
<ThemePane />
|
<div class="settings-tabs">
|
||||||
</RightPanel>
|
{#each tabs as tab}
|
||||||
|
<ActionButton
|
||||||
|
size="M"
|
||||||
|
quiet
|
||||||
|
selected={activeTab === tab}
|
||||||
|
on:click={() => {
|
||||||
|
activeTab = tab
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{capitalise(tab)}
|
||||||
|
</ActionButton>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Layout gap="S" paddingX="L" paddingY="XL">
|
||||||
|
{#if activeTab === "theme"}
|
||||||
|
<ThemePanel />
|
||||||
|
{:else}
|
||||||
|
<GeneralPanel />
|
||||||
|
{/if}
|
||||||
|
</Layout>
|
||||||
|
</Panel>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.settings-tabs {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--spacing-s);
|
||||||
|
padding: 0 var(--spacing-l);
|
||||||
|
padding-bottom: var(--spacing-l);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue