Allow custom CSS to be bindable and allow overriding via conditional UI
This commit is contained in:
parent
eb8171dde1
commit
178dc26c16
|
@ -57,8 +57,8 @@
|
||||||
|
|
||||||
let dragDisabled = true
|
let dragDisabled = true
|
||||||
$: settings = getComponentSettings($selectedComponent?._component)?.concat({
|
$: settings = getComponentSettings($selectedComponent?._component)?.concat({
|
||||||
label: "CSS",
|
label: "Custom CSS",
|
||||||
key: "css",
|
key: "_css",
|
||||||
type: "text",
|
type: "text",
|
||||||
})
|
})
|
||||||
$: settingOptions = settings.map(setting => ({
|
$: settingOptions = settings.map(setting => ({
|
||||||
|
|
|
@ -1,30 +1,41 @@
|
||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
TextArea,
|
|
||||||
DetailSummary,
|
DetailSummary,
|
||||||
ActionButton,
|
ActionButton,
|
||||||
Drawer,
|
Drawer,
|
||||||
DrawerContent,
|
|
||||||
Layout,
|
|
||||||
Body,
|
|
||||||
Button,
|
Button,
|
||||||
notifications,
|
notifications,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { store } from "builderStore"
|
import { selectedScreen, store } from "builderStore"
|
||||||
|
import ClientBindingPanel from "components/common/bindings/ClientBindingPanel.svelte"
|
||||||
|
import {
|
||||||
|
getBindableProperties,
|
||||||
|
readableToRuntimeBinding,
|
||||||
|
runtimeToReadableBinding,
|
||||||
|
} from "builderStore/dataBinding"
|
||||||
|
|
||||||
export let componentInstance
|
export let componentInstance
|
||||||
|
|
||||||
let tempValue
|
let tempValue
|
||||||
let drawer
|
let drawer
|
||||||
|
|
||||||
|
$: bindings = getBindableProperties(
|
||||||
|
$selectedScreen,
|
||||||
|
$store.selectedComponentId
|
||||||
|
)
|
||||||
|
|
||||||
const openDrawer = () => {
|
const openDrawer = () => {
|
||||||
tempValue = componentInstance?._styles?.custom
|
tempValue = runtimeToReadableBinding(
|
||||||
|
bindings,
|
||||||
|
componentInstance?._styles?.custom
|
||||||
|
)
|
||||||
drawer.show()
|
drawer.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
const save = async () => {
|
const save = async () => {
|
||||||
try {
|
try {
|
||||||
await store.actions.components.updateCustomStyle(tempValue)
|
const value = readableToRuntimeBinding(bindings, tempValue)
|
||||||
|
await store.actions.components.updateCustomStyle(value)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
notifications.error("Error updating custom style")
|
notifications.error("Error updating custom style")
|
||||||
}
|
}
|
||||||
|
@ -42,26 +53,17 @@
|
||||||
</DetailSummary>
|
</DetailSummary>
|
||||||
{#key componentInstance?._id}
|
{#key componentInstance?._id}
|
||||||
<Drawer bind:this={drawer} title="Custom CSS">
|
<Drawer bind:this={drawer} title="Custom CSS">
|
||||||
|
<svelte:fragment slot="description">
|
||||||
|
Custom CSS overrides all other component styles.
|
||||||
|
</svelte:fragment>
|
||||||
<Button cta slot="buttons" on:click={save}>Save</Button>
|
<Button cta slot="buttons" on:click={save}>Save</Button>
|
||||||
<DrawerContent slot="body">
|
<svelte:component
|
||||||
<div class="content">
|
this={ClientBindingPanel}
|
||||||
<Layout gap="S" noPadding>
|
slot="body"
|
||||||
<Body size="S">Custom CSS overrides all other component styles.</Body>
|
value={tempValue}
|
||||||
<TextArea bind:value={tempValue} placeholder="Enter some CSS..." />
|
on:change={event => (tempValue = event.detail)}
|
||||||
</Layout>
|
allowJS
|
||||||
</div>
|
{bindings}
|
||||||
</DrawerContent>
|
/>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
{/key}
|
{/key}
|
||||||
|
|
||||||
<style>
|
|
||||||
.content {
|
|
||||||
max-width: 800px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
.content :global(textarea) {
|
|
||||||
font-family: monospace;
|
|
||||||
min-height: 240px !important;
|
|
||||||
font-size: var(--font-size-s);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -142,6 +142,10 @@
|
||||||
// Determine and apply settings to the component
|
// Determine and apply settings to the component
|
||||||
$: applySettings(staticSettings, enrichedSettings, conditionalSettings)
|
$: applySettings(staticSettings, enrichedSettings, conditionalSettings)
|
||||||
|
|
||||||
|
// Determine custom css.
|
||||||
|
// Broken out as a separate variable to minimize reactivity updates.
|
||||||
|
$: customCSS = cachedSettings?._css
|
||||||
|
|
||||||
// Scroll the selected element into view
|
// Scroll the selected element into view
|
||||||
$: selected && scrollIntoView()
|
$: selected && scrollIntoView()
|
||||||
|
|
||||||
|
@ -151,6 +155,7 @@
|
||||||
children: children.length,
|
children: children.length,
|
||||||
styles: {
|
styles: {
|
||||||
...instance._styles,
|
...instance._styles,
|
||||||
|
custom: customCSS,
|
||||||
id,
|
id,
|
||||||
empty: emptyState,
|
empty: emptyState,
|
||||||
interactive,
|
interactive,
|
||||||
|
@ -259,14 +264,18 @@
|
||||||
// Get raw settings
|
// Get raw settings
|
||||||
let settings = {}
|
let settings = {}
|
||||||
Object.entries(instance)
|
Object.entries(instance)
|
||||||
.filter(([name]) => name === "_conditions" || !name.startsWith("_"))
|
.filter(([name]) => !name.startsWith("_"))
|
||||||
.forEach(([key, value]) => {
|
.forEach(([key, value]) => {
|
||||||
settings[key] = value
|
settings[key] = value
|
||||||
})
|
})
|
||||||
|
|
||||||
// Derive static, dynamic and nested settings if the instance changed
|
|
||||||
let newStaticSettings = { ...settings }
|
let newStaticSettings = { ...settings }
|
||||||
let newDynamicSettings = { ...settings }
|
let newDynamicSettings = { ...settings }
|
||||||
|
|
||||||
|
// Attach some internal properties
|
||||||
|
newDynamicSettings["_conditions"] = instance._conditions
|
||||||
|
newDynamicSettings["_css"] = instance._styles?.custom
|
||||||
|
|
||||||
|
// Derive static, dynamic and nested settings if the instance changed
|
||||||
settingsDefinition?.forEach(setting => {
|
settingsDefinition?.forEach(setting => {
|
||||||
if (setting.nested) {
|
if (setting.nested) {
|
||||||
delete newDynamicSettings[setting.key]
|
delete newDynamicSettings[setting.key]
|
||||||
|
@ -372,6 +381,10 @@
|
||||||
initialSettings = cachedSettings
|
initialSettings = cachedSettings
|
||||||
} else {
|
} else {
|
||||||
Object.keys(allSettings).forEach(key => {
|
Object.keys(allSettings).forEach(key => {
|
||||||
|
if (key === "_css") {
|
||||||
|
console.log(enrichedSettings._css)
|
||||||
|
}
|
||||||
|
|
||||||
const same = propsAreSame(allSettings[key], cachedSettings[key])
|
const same = propsAreSame(allSettings[key], cachedSettings[key])
|
||||||
if (!same) {
|
if (!same) {
|
||||||
// Updated cachedSettings (which is assigned by reference to
|
// Updated cachedSettings (which is assigned by reference to
|
||||||
|
@ -379,8 +392,10 @@
|
||||||
// initial props are up to date. By setting it this way rather than
|
// initial props are up to date. By setting it this way rather than
|
||||||
// setting it on initialSettings directly, we avoid a double render.
|
// setting it on initialSettings directly, we avoid a double render.
|
||||||
cachedSettings[key] = allSettings[key]
|
cachedSettings[key] = allSettings[key]
|
||||||
if (key === "css") {
|
|
||||||
instance._styles.custom = cachedSettings[key]
|
// Don't update components for internal properties
|
||||||
|
if (key.startsWith("_")) {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ref?.$$set) {
|
if (ref?.$$set) {
|
||||||
|
|
Loading…
Reference in New Issue