fix: improve style panel reactivity and CSS defaults (#7935)

This commit is contained in:
Ruben Fiszel
2026-02-13 12:22:58 +00:00
committed by GitHub
parent 791cb3e225
commit eacbee38cb
4 changed files with 88 additions and 37 deletions
@@ -50,7 +50,7 @@ type GridItemLocation =
subgridItemIndex: number
subgridKey: string
}
interface GridItemWithLocation {
export interface GridItemWithLocation {
location: GridItemLocation
item: GridItem
parent: string | undefined
@@ -37,7 +37,7 @@
let {
name,
value = $bindable({}),
value = $bindable(),
forceStyle = false,
forceClass = false,
quickStyleProperties = undefined,
@@ -61,6 +61,7 @@
})
function toggleQuickMenu() {
if (!value) return
try {
if (!value.style) {
value.style = ''
@@ -1,9 +1,9 @@
<script lang="ts">
import { Tab, TabContent } from '$lib/components/common'
import { sendUserToast } from '$lib/toast'
import { getContext } from 'svelte'
import { getContext, untrack } from 'svelte'
import type { AppViewerContext, ComponentCssProperty } from '../../types'
import { ccomponents, components, type AppComponent } from '../component'
import { ccomponents, components } from '../component'
import CssProperty from '../componentsPanel/CssProperty.svelte'
import { quickStyleProperties } from '../componentsPanel/quickStyleProperties'
import Tabs from '$lib/components/common/tabs/Tabs.svelte'
@@ -16,25 +16,59 @@
import CssMigrationModal from './CSSMigrationModal.svelte'
import CssPropertyWrapper from './CssPropertyWrapper.svelte'
import { onMount } from 'svelte'
import { findComponentSettings } from '../appUtils'
import { findGridItemWithLocation, type GridItemWithLocation } from '../appUtils'
const { app, cssEditorOpen, selectedComponent } = getContext<AppViewerContext>('AppViewerContext')
let component: AppComponent | undefined
$: {
const newComponent = findComponentSettings($app, $selectedComponent?.[0])?.item?.data
if (component != newComponent) {
component = newComponent
let tab: 'local' | 'global' = $state('local')
let overrideGlobalCSS: (() => void) | undefined = $state(undefined)
let overrideLocalCSS: (() => void) | undefined = $state(undefined)
let componentWithLocation: GridItemWithLocation | undefined = $derived(
findGridItemWithLocation($app, $selectedComponent?.[0] ?? '')
)
let component = $derived(componentWithLocation?.item.data)
let type = $derived(component?.type)
function updateComponentData(
loc: GridItemWithLocation,
updater: (data: typeof loc.item.data) => typeof loc.item.data
) {
const { location } = loc
if (location.type === 'subgrid') {
const item = $app.subgrids?.[location.subgridKey]?.[location.subgridItemIndex]
if (item) {
item.data = updater(item.data)
}
} else {
const item = $app.grid[location.gridItemIndex]
if (item) {
item.data = updater(item.data)
}
}
app.set($app)
}
let tab: 'local' | 'global' = 'local'
let overrideGlobalCSS: (() => void) | undefined = undefined
let overrideLocalCSS: (() => void) | undefined = undefined
$: type = component?.type
let migrationModal: CssMigrationModal | undefined = undefined
$effect.pre(() => {
if (
(componentWithLocation && component?.customCss === undefined) ||
(Object.keys(component?.customCss ?? {}).length === 0 &&
Object.keys(ccomponents[component?.type ?? '']?.customCss ?? {}).length > 0)
) {
untrack(() => {
if (componentWithLocation) {
updateComponentData(componentWithLocation, (data) => ({
...data,
customCss: structuredClone(ccomponents[component?.type ?? '']?.customCss ?? {})
}))
}
})
}
})
$: customCssByComponentType =
let migrationModal: CssMigrationModal | undefined = $state(undefined)
let customCssByComponentType = $derived(
component?.type && $app.css
? Object.entries($app.css[component.type] || {}).map(([id, v]) => ({
id,
@@ -42,6 +76,7 @@
forceClass: v?.['class'] != undefined
}))
: undefined
)
function copyLocalToGlobal(name: string, value: ComponentCssProperty | undefined) {
if (!value) {
@@ -53,7 +88,7 @@
if (hasStyleValue($app.css?.[type]?.[name])) {
overrideGlobalCSS = () => {
$app.css![type]![name] = JSON.parse(JSON.stringify(value))
$app.css![type]![name] = structuredClone(value)
app.set($app)
}
} else {
@@ -61,7 +96,7 @@
initGlobalCss()
}
$app.css![type]![name] = JSON.parse(JSON.stringify(value))
$app.css![type]![name] = structuredClone(value)
app.set($app)
sendUserToast('Global CSS copied')
}
@@ -74,12 +109,10 @@
} else {
if (hasStyleValue(value)) {
overrideLocalCSS = () => {
component!.customCss![id] = JSON.parse(JSON.stringify(value))
app.set($app)
updateCssProperty(id, structuredClone(value))
}
} else {
component!.customCss![id] = JSON.parse(JSON.stringify(value))
app.set($app)
updateCssProperty(id, structuredClone(value))
sendUserToast('Local CSS copied')
}
}
@@ -101,11 +134,22 @@
components[component.type] &&
$app.css[component.type] === undefined
) {
$app.css[component.type] = JSON.parse(JSON.stringify(components[component.type].customCss))
$app.css[component.type] = structuredClone(components[component.type].customCss)
app.set($app)
}
}
function updateCssProperty(name: string, cssValue: ComponentCssProperty | undefined) {
if (!componentWithLocation || !cssValue) return
updateComponentData(componentWithLocation, (data) => ({
...data,
customCss: {
...(data?.customCss ?? {}),
[name]: cssValue
}
}))
}
function getSelector(key: string) {
return customisationByComponent
.find((c) => c.components.includes(component?.type ?? ''))
@@ -197,8 +241,10 @@
{name}
wmClass={getSelector(name)}
componentType={component.type}
bind:value={component.customCss[name]}
on:change={() => app.set($app)}
value={component.customCss[name]}
on:change={(e) => {
updateCssProperty(name, e.detail)
}}
shouldDisplayRight={hasStyleValue(component.customCss[name])}
on:right={() => {
copyLocalToGlobal(name, component?.customCss?.[name])
@@ -210,6 +256,8 @@
</div>
{/each}
</div>
{:else}
<div class="text-sm text-secondary mx-2">No local CSS to display</div>
{/if}
</TabContent>
<TabContent value="global">
@@ -1,3 +1,5 @@
import { ccomponents } from '../apps/editor/component'
export function createAppFromScript(path: string, schema: Record<string, any> | undefined) {
return {
grid: [
@@ -22,7 +24,7 @@ export function createAppFromScript(path: string, schema: Record<string, any> |
type: 'verticalsplitpanescomponent',
configuration: {},
panes: [50, 50],
customCss: {},
customCss: structuredClone(ccomponents['verticalsplitpanescomponent'].customCss),
numberOfSubgrids: 2,
id: 'a'
},
@@ -103,7 +105,7 @@ export function createAppFromScript(path: string, schema: Record<string, any> |
fieldType: 'schema',
value: schema
},
customCss: {},
customCss: structuredClone(ccomponents['schemaformcomponent'].customCss),
id: 'c'
},
id: 'c'
@@ -291,7 +293,7 @@ export function createAppFromScript(path: string, schema: Record<string, any> |
autoRefresh: true,
recomputeOnInputChanged: true
},
customCss: {},
customCss: structuredClone(ccomponents['buttoncomponent'].customCss),
recomputeIds: [],
horizontalAlignment: 'right',
verticalAlignment: 'center',
@@ -327,7 +329,7 @@ export function createAppFromScript(path: string, schema: Record<string, any> |
}
},
tabs: ['Result', 'Logs'],
customCss: {},
customCss: structuredClone(ccomponents['tabscomponent'].customCss),
numberOfSubgrids: 2,
id: 'b',
disabledTabs: [
@@ -375,7 +377,7 @@ export function createAppFromScript(path: string, schema: Record<string, any> |
path: 'result'
}
},
customCss: {},
customCss: structuredClone(ccomponents['displaycomponent'].customCss),
id: 'e'
},
id: 'e'
@@ -410,7 +412,7 @@ export function createAppFromScript(path: string, schema: Record<string, any> |
}
}
},
customCss: {},
customCss: structuredClone(ccomponents['jobidlogcomponent'].customCss),
id: 'f'
},
id: 'f'
@@ -589,7 +591,7 @@ export function createAppFromFlow(path: string, schema: Record<string, any> | un
type: 'verticalsplitpanescomponent',
configuration: {},
panes: [50, 50],
customCss: {},
customCss: structuredClone(ccomponents['verticalsplitpanescomponent'].customCss),
numberOfSubgrids: 2,
id: 'a'
},
@@ -669,7 +671,7 @@ export function createAppFromFlow(path: string, schema: Record<string, any> | un
fieldType: 'schema',
value: schema
},
customCss: {},
customCss: structuredClone(ccomponents['schemaformcomponent'].customCss),
id: 'c'
},
id: 'c'
@@ -857,7 +859,7 @@ export function createAppFromFlow(path: string, schema: Record<string, any> | un
autoRefresh: false,
recomputeOnInputChanged: false
},
customCss: {},
customCss: structuredClone(ccomponents['buttoncomponent'].customCss),
recomputeIds: [],
horizontalAlignment: 'right',
verticalAlignment: 'center',
@@ -893,7 +895,7 @@ export function createAppFromFlow(path: string, schema: Record<string, any> | un
}
},
tabs: ['Result', 'Logs'],
customCss: {},
customCss: structuredClone(ccomponents['tabscomponent'].customCss),
numberOfSubgrids: 2,
id: 'b',
disabledTabs: [
@@ -942,7 +944,7 @@ export function createAppFromFlow(path: string, schema: Record<string, any> | un
}
}
},
customCss: {},
customCss: structuredClone(ccomponents['jobidflowstatuscomponent'].customCss),
id: 'e'
},
id: 'e'
@@ -977,7 +979,7 @@ export function createAppFromFlow(path: string, schema: Record<string, any> | un
}
}
},
customCss: {},
customCss: structuredClone(ccomponents['jobidlogcomponent'].customCss),
id: 'f'
},
id: 'f'