fix: stabilize custom sidebar active state

This commit is contained in:
SethBurkart123
2026-08-27 09:06:08 +10:00
parent 8ccddc1ae0
commit 9f80ba11f1
8 changed files with 112 additions and 137 deletions
+23 -15
View File
@@ -704,20 +704,23 @@ html.bsplus-custom-title-pending #title > :not(#bsplus-title-root),
/* Native list may keep `.active` after click-through; force our rows clickable, /* Native list may keep `.active` after click-through; force our rows clickable,
then lock siblings only while a custom drill `.sub` is open. */ then lock siblings only while a custom drill `.sub` is open. */
> #bsplus-sidebar-root > li.item { > #bsplus-sidebar-root .bsplus-sidebar-item {
pointer-events: auto !important;
width: auto !important; width: auto !important;
max-width: none !important; max-width: none !important;
margin: 0 6px 8px !important; margin: 0 6px 8px !important;
box-sizing: border-box !important; box-sizing: border-box !important;
} }
&:has(> #bsplus-sidebar-root > li.hasChildren.active > .sub) > #bsplus-sidebar-root > li.item {
pointer-events: auto !important;
}
&:has(> #bsplus-sidebar-root > li.hasChildren.bsplus-active > .sub)
> #bsplus-sidebar-root > #bsplus-sidebar-root
> li:not(.hasChildren.active), > li:not(.hasChildren.bsplus-active),
&:has(> #bsplus-sidebar-root > li.hasChildren.active > .sub) &:has(> #bsplus-sidebar-root > li.hasChildren.bsplus-active > .sub)
> #bsplus-sidebar-root > #bsplus-sidebar-root
> li:not(.hasChildren.active) > li:not(.hasChildren.bsplus-active)
* { * {
pointer-events: none !important; pointer-events: none !important;
} }
@@ -733,17 +736,21 @@ html.bsplus-custom-title-pending #title > :not(#bsplus-title-root),
pointer-events: none; pointer-events: none;
} }
> #bsplus-sidebar-root li.hasChildren.active > .sub { > #bsplus-sidebar-root li.hasChildren.bsplus-active > .sub {
pointer-events: auto; pointer-events: auto;
transform: none;
background: transparent !important; background: transparent !important;
background-image: none !important; background-image: none !important;
} }
> #bsplus-sidebar-root li.hasChildren.active > .sub:has(.hasChildren.active) { > #bsplus-sidebar-root li.hasChildren.bsplus-active
> .sub:has(.hasChildren.bsplus-active) {
pointer-events: none !important; pointer-events: none !important;
} }
> #bsplus-sidebar-root li.hasChildren.active .hasChildren.active > .sub { > #bsplus-sidebar-root li.hasChildren.bsplus-active
.hasChildren.bsplus-active
> .sub {
pointer-events: auto !important; pointer-events: auto !important;
background: transparent !important; background: transparent !important;
background-image: none !important; background-image: none !important;
@@ -765,17 +772,17 @@ html.bsplus-custom-title-pending #title > :not(#bsplus-title-root),
background-image: none !important; background-image: none !important;
} }
> #bsplus-sidebar-root > li.hasChildren.active > label, > #bsplus-sidebar-root > li.hasChildren.bsplus-active > label,
> #bsplus-sidebar-root.drilling > li.hasChildren > label { > #bsplus-sidebar-root.drilling > li.hasChildren > label {
pointer-events: none !important; pointer-events: none !important;
} }
/* Theme decorations on root leaves (Beach palm/sand) must not show through /* Theme decorations on root leaves (Beach palm/sand) must not show through
the transparent drill `.sub` panel. */ the transparent drill `.sub` panel. */
> #bsplus-sidebar-root:has(> li.hasChildren.active > .sub) > #bsplus-sidebar-root:has(> li.hasChildren.bsplus-active > .sub)
> li:not(.hasChildren.active)::before, > li:not(.hasChildren.bsplus-active)::before,
> #bsplus-sidebar-root:has(> li.hasChildren.active > .sub) > #bsplus-sidebar-root:has(> li.hasChildren.bsplus-active > .sub)
> li:not(.hasChildren.active)::after { > li:not(.hasChildren.bsplus-active)::after {
content: none !important; content: none !important;
display: none !important; display: none !important;
animation: none !important; animation: none !important;
@@ -812,8 +819,9 @@ html.bsplus-custom-title-pending #title > :not(#bsplus-title-root),
#bsplus-sidebar-root .sub > ul { #bsplus-sidebar-root .sub > ul {
list-style: none; list-style: none;
margin: 0; margin: 0;
padding: 0 0 16px; padding: 8px 0 16px;
} }
} }
#menu li > label > svg, #menu li > label > svg,
+49 -20
View File
@@ -1,20 +1,22 @@
#menu ul:has(li.hasChildren.active) li.hasChildren.active { #menu ul:has(li.hasChildren:is(.active, .bsplus-active))
li.hasChildren:is(.active, .bsplus-active) {
box-shadow: inset 0px 0 var(--item-colour, transparent) !important; box-shadow: inset 0px 0 var(--item-colour, transparent) !important;
background: transparent !important; background: transparent !important;
} }
#menu ul:not(:has(li.hasChildren.active)) { #menu ul:not(:has(li.hasChildren:is(.active, .bsplus-active))) {
overflow-y: scroll !important; overflow-y: scroll !important;
} }
#menu > ul:has(li.hasChildren.active) > li::before, #menu > ul:has(li.hasChildren:is(.active, .bsplus-active)) > li::before,
#menu > ul:has(li.hasChildren.active) > li::after, #menu > ul:has(li.hasChildren:is(.active, .bsplus-active)) > li::after,
#menu > ul ul:has(li.hasChildren.active) > li::before, #menu > ul ul:has(li.hasChildren:is(.active, .bsplus-active)) > li::before,
#menu > ul ul:has(li.hasChildren.active) > li::after, #menu > ul ul:has(li.hasChildren:is(.active, .bsplus-active)) > li::after,
#menu > ul:has(li.hasChildren.active) > li > label, #menu > ul:has(li.hasChildren:is(.active, .bsplus-active)) > li > label,
#menu > ul:has(li.hasChildren.active) > li > svg, #menu > ul:has(li.hasChildren:is(.active, .bsplus-active)) > li > svg,
#menu > ul ul:has(li.hasChildren.active) > li > label, #menu > ul ul:has(li.hasChildren:is(.active, .bsplus-active)) > li > label,
#menu > ul ul:has(li.hasChildren.active) > li > svg { #menu > ul ul:has(li.hasChildren:is(.active, .bsplus-active)) > li > svg {
/* !important beats theme animations (e.g. Beach palm-slide forwards). */
transform: translateX(-320px) !important; transform: translateX(-320px) !important;
animation: none !important; animation: none !important;
} }
@@ -28,12 +30,13 @@
transition: transform 0.3s ease, left 0.4s cubic-bezier(0.4, 0, 0.2, 1); transition: transform 0.3s ease, left 0.4s cubic-bezier(0.4, 0, 0.2, 1);
} }
#menu > ul:has(li.hasChildren.active) > li.active { #menu > ul:has(li.hasChildren:is(.active, .bsplus-active))
> li:is(.active, .bsplus-active) {
background: transparent !important; background: transparent !important;
} }
#menu li.hasChildren:not(.active) li .sub { #menu li.hasChildren:not(:is(.active, .bsplus-active)) li .sub {
display: none; display: none; // improves performance
} }
.sub .sub { .sub .sub {
@@ -41,16 +44,42 @@
padding-top: 2px; padding-top: 2px;
} }
.sub:has(ul > li.hasChildren.active) > .nav > .back { .sub:has(ul > li.hasChildren:is(.active, .bsplus-active)) > .nav > .back {
display: none !important; display: none !important;
} }
body.icon-only-sidebar:not(:has(#menu li.hasChildren.active)) #menu > ul:has(li.hasChildren.active) > li::before, /* Icon-only collapsed: submenu slides over narrow icons */
body.icon-only-sidebar:not(:has(#menu li.hasChildren.active)) #menu > ul ul:has(li.hasChildren.active) > li::before, body.icon-only-sidebar:not(:has(#menu li.hasChildren:is(.active, .bsplus-active)))
body.icon-only-sidebar:not(:has(#menu li.hasChildren.active)) #menu > ul:has(li.hasChildren.active) > li > label, #menu
body.icon-only-sidebar:not(:has(#menu li.hasChildren.active)) #menu > ul:has(li.hasChildren.active) > li > svg, > ul:has(li.hasChildren:is(.active, .bsplus-active))
body.icon-only-sidebar:not(:has(#menu li.hasChildren.active)) #menu > ul ul:has(li.hasChildren.active) > li > label, > li::before,
body.icon-only-sidebar:not(:has(#menu li.hasChildren.active)) #menu > ul ul:has(li.hasChildren.active) > li > svg { body.icon-only-sidebar:not(:has(#menu li.hasChildren:is(.active, .bsplus-active)))
#menu
> ul
ul:has(li.hasChildren:is(.active, .bsplus-active))
> li::before,
body.icon-only-sidebar:not(:has(#menu li.hasChildren:is(.active, .bsplus-active)))
#menu
> ul:has(li.hasChildren:is(.active, .bsplus-active))
> li
> label,
body.icon-only-sidebar:not(:has(#menu li.hasChildren:is(.active, .bsplus-active)))
#menu
> ul:has(li.hasChildren:is(.active, .bsplus-active))
> li
> svg,
body.icon-only-sidebar:not(:has(#menu li.hasChildren:is(.active, .bsplus-active)))
#menu
> ul
ul:has(li.hasChildren:is(.active, .bsplus-active))
> li
> label,
body.icon-only-sidebar:not(:has(#menu li.hasChildren:is(.active, .bsplus-active)))
#menu
> ul
ul:has(li.hasChildren:is(.active, .bsplus-active))
> li
> svg {
transform: translateX(-70px); transform: translateX(-70px);
} }
+6 -4
View File
@@ -19,9 +19,9 @@ $sidebar-motion: 0.4s cubic-bezier(0.4, 0, 0.2, 1);
} }
#menu.bsplus-custom-sidebar { #menu.bsplus-custom-sidebar {
$item: "> #bsplus-sidebar-root > li.item:not(.bsplus-sidebar-edit-header):not(.bsplus-sidebar-edit-actions)"; $item: "> #bsplus-sidebar-root .bsplus-sidebar-item";
$label: "> #bsplus-sidebar-root > li.item > label:not(.toggle)"; $label: "> #bsplus-sidebar-root .bsplus-sidebar-item > label:not(.toggle)";
$active: "> #bsplus-sidebar-root > li.item.active:not(.hasChildren)"; $active: "> #bsplus-sidebar-root .bsplus-sidebar-item.bsplus-active:not(.hasChildren)";
/* Look: base radius (pill / sharp / strip override). /* Look: base radius (pill / sharp / strip override).
Density/radius animate with the same easing as sidebar width. */ Density/radius animate with the same easing as sidebar width. */
@@ -37,6 +37,7 @@ $sidebar-motion: 0.4s cubic-bezier(0.4, 0, 0.2, 1);
} }
#{$label} { #{$label} {
min-height: 28px !important;
transition: transition:
font-size $sidebar-motion, font-size $sidebar-motion,
line-height $sidebar-motion, line-height $sidebar-motion,
@@ -147,7 +148,7 @@ $sidebar-motion: 0.4s cubic-bezier(0.4, 0, 0.2, 1);
margin: 0 !important; margin: 0 !important;
font-size: 13px !important; font-size: 13px !important;
line-height: 1.2 !important; line-height: 1.2 !important;
min-height: 0 !important; min-height: 20px !important;
height: auto !important; height: auto !important;
white-space: nowrap !important; white-space: nowrap !important;
@@ -169,6 +170,7 @@ $sidebar-motion: 0.4s cubic-bezier(0.4, 0, 0.2, 1);
padding: 0 !important; padding: 0 !important;
font-size: 17px !important; font-size: 17px !important;
line-height: 1.25 !important; line-height: 1.25 !important;
min-height: 30px !important;
> svg { > svg {
width: 30px !important; width: 30px !important;
@@ -1,3 +1,4 @@
import { getNativeMenuList } from "@/seqta/ui/sidebar/parseNativeMenu";
import { settingsState } from "@/seqta/utils/listeners/SettingsState"; import { settingsState } from "@/seqta/utils/listeners/SettingsState";
import { waitForElm } from "@/seqta/utils/waitForElm"; import { waitForElm } from "@/seqta/utils/waitForElm";
import { renderAnalyticsPage } from "./ui"; import { renderAnalyticsPage } from "./ui";
@@ -23,10 +24,11 @@ export async function loadAnalyticsPage(): Promise<void> {
async function loadAnalyticsPageInner(): Promise<void> { async function loadAnalyticsPageInner(): Promise<void> {
document.title = "Analytics ― SEQTA Learn"; document.title = "Analytics ― SEQTA Learn";
document.querySelectorAll("#menu .item").forEach((item) => { const menu = getNativeMenuList();
menu?.querySelectorAll(".item").forEach((item) => {
item.classList.remove("active"); item.classList.remove("active");
}); });
document.querySelector('[data-key="analytics"]')?.classList.add("active"); menu?.querySelector('[data-key="analytics"]')?.classList.add("active");
let main: HTMLElement; let main: HTMLElement;
try { try {
+4 -16
View File
@@ -2,10 +2,7 @@
import { onDestroy } from "svelte"; import { onDestroy } from "svelte";
import Sortable from "sortablejs"; import Sortable from "sortablejs";
import { settingsState } from "@/seqta/utils/listeners/SettingsState"; import { settingsState } from "@/seqta/utils/listeners/SettingsState";
import { import { sidebarState } from "./sidebarState.svelte";
restoreCustomMenuActive,
sidebarState,
} from "./sidebarState.svelte";
import SidebarItem from "./SidebarItem.svelte"; import SidebarItem from "./SidebarItem.svelte";
import type { import type {
SidebarDrillFrame, SidebarDrillFrame,
@@ -102,7 +99,7 @@
`${Math.round(width)}px`, `${Math.round(width)}px`,
); );
// Fallback clone is created just after onStart; pin size + drop // Fallback clone is created just after onStart; pin size + drop
// `.active` so theme/active rules don't expand it to full width. // Active styling makes fallback clones wider; keep the source width.
requestAnimationFrame(() => { requestAnimationFrame(() => {
const dragEl = document.querySelector( const dragEl = document.querySelector(
".bsplus-sortable-drag", ".bsplus-sortable-drag",
@@ -110,7 +107,7 @@
if (!dragEl) return; if (!dragEl) return;
dragEl.style.width = `${Math.round(width)}px`; dragEl.style.width = `${Math.round(width)}px`;
dragEl.style.maxWidth = `${Math.round(width)}px`; dragEl.style.maxWidth = `${Math.round(width)}px`;
dragEl.classList.remove("active"); dragEl.classList.remove("bsplus-active");
}); });
}, },
onEnd: (evt) => { onEnd: (evt) => {
@@ -156,15 +153,6 @@
}; };
}); });
// SEQTA strips `.active` from `#menu li` after clicks — re-apply from state.
// Do NOT MutationObserver class changes here: restore writes `.active`, SEQTA
// strips it again, and the feedback loop freezes the tab.
$effect(() => {
void sidebarState.activeKey;
void sidebarState.isDrilling;
restoreCustomMenuActive();
});
// Drill `.sub` is position:absolute inside this scrollport — if the list was // Drill `.sub` is position:absolute inside this scrollport — if the list was
// scrolled down (e.g. Folios/Goals near the bottom), the panel sits under the // scrolled down (e.g. Folios/Goals near the bottom), the panel sits under the
// logo until we reset. Also reset when going back up the stack. // logo until we reset. Also reset when going back up the stack.
@@ -269,7 +257,7 @@
{@const folder = current.folder} {@const folder = current.folder}
<li <li
class="item hasChildren bsplus-sidebar-item" class="item hasChildren bsplus-sidebar-item"
class:active={true} class:bsplus-active={true}
data-key={current.frame.key} data-key={current.frame.key}
data-path={folder?.path ?? undefined} data-path={folder?.path ?? undefined}
style:--item-colour={folder?.itemColour || undefined} style:--item-colour={folder?.itemColour || undefined}
+12 -14
View File
@@ -29,17 +29,18 @@
const GRIP_SVG = `<svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"><circle cx="5" cy="3" r="1.35" fill="currentColor"/><circle cx="11" cy="3" r="1.35" fill="currentColor"/><circle cx="5" cy="8" r="1.35" fill="currentColor"/><circle cx="11" cy="8" r="1.35" fill="currentColor"/><circle cx="5" cy="13" r="1.35" fill="currentColor"/><circle cx="11" cy="13" r="1.35" fill="currentColor"/></svg>`; const GRIP_SVG = `<svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"><circle cx="5" cy="3" r="1.35" fill="currentColor"/><circle cx="11" cy="3" r="1.35" fill="currentColor"/><circle cx="5" cy="8" r="1.35" fill="currentColor"/><circle cx="11" cy="8" r="1.35" fill="currentColor"/><circle cx="5" cy="13" r="1.35" fill="currentColor"/><circle cx="11" cy="13" r="1.35" fill="currentColor"/></svg>`;
</script> </script>
<!-- SEQTA class names (item / hasChildren / active) so theme CSS keeps matching. --> <!-- Keep SEQTA's structural attributes so existing themes recognize each row. -->
<!-- svelte-ignore a11y_no_noninteractive_element_to_interactive_role --> <!-- svelte-ignore a11y_no_noninteractive_element_to_interactive_role -->
<li <li
class="item bsplus-sidebar-item" class="item bsplus-sidebar-item"
class:active={active} class:bsplus-active={active}
class:hasChildren={item.hasChildren} class:hasChildren={item.hasChildren}
class:edit-mode={editMode} class:edit-mode={editMode}
class:hidden-item={editMode && !visible} class:hidden-item={editMode && !visible}
class:compact={compact} class:compact={compact}
class:draggable={editMode} class:draggable={editMode}
style:--item-colour={item.itemColour || undefined} style:--item-colour={item.itemColour || undefined}
data-colour={item.itemColour || undefined}
data-key={item.key} data-key={item.key}
data-path={item.path ?? undefined} data-path={item.path ?? undefined}
data-betterseqta={item.betterseqta ? "true" : undefined} data-betterseqta={item.betterseqta ? "true" : undefined}
@@ -131,7 +132,7 @@
color: inherit; color: inherit;
} }
.bsplus-sidebar-item:hover:not(.active) { .bsplus-sidebar-item:hover:not(.bsplus-active) {
background: rgba(0, 0, 0, 0.15); background: rgba(0, 0, 0, 0.15);
} }
@@ -140,8 +141,8 @@
box-shadow: 0 0 0 2px var(--theme-primary, #fff); box-shadow: 0 0 0 2px var(--theme-primary, #fff);
} }
.bsplus-sidebar-item.active:not(.hasChildren), .bsplus-sidebar-item.bsplus-active:not(.hasChildren),
.bsplus-sidebar-item.active:not(.hasChildren):hover { .bsplus-sidebar-item.bsplus-active:not(.hasChildren):hover {
background: rgba(0, 0, 0, 0.35); background: rgba(0, 0, 0, 0.35);
color: #fff; color: #fff;
} }
@@ -250,18 +251,15 @@
.colour-bar { .colour-bar {
position: absolute; position: absolute;
top: 0; inset: 0;
left: 0; border-radius: inherit;
bottom: 0; box-shadow: inset 3px 0 var(--item-colour, transparent);
width: 3px; transition: box-shadow 100ms ease;
border-radius: 8px 0 0 8px;
background: var(--item-colour, transparent);
transition: width 100ms ease;
pointer-events: none; pointer-events: none;
} }
.bsplus-sidebar-item:hover .colour-bar, .bsplus-sidebar-item:hover .colour-bar,
.bsplus-sidebar-item.active .colour-bar { .bsplus-sidebar-item.bsplus-active .colour-bar {
width: 6px; box-shadow: inset 6px 0 var(--item-colour, transparent);
} }
</style> </style>
+4 -64
View File
@@ -37,12 +37,6 @@ function filterVisible(items: SidebarItem[]): SidebarItem[] {
return items.filter((item) => menuItems[item.key]?.toggle !== false); return items.filter((item) => menuItems[item.key]?.toggle !== false);
} }
function ensureActive(el: Element | null | undefined) {
if (el instanceof HTMLElement && !el.classList.contains("active")) {
el.classList.add("active");
}
}
function resetSidebarScroll() { function resetSidebarScroll() {
const root = document.getElementById("bsplus-sidebar-root"); const root = document.getElementById("bsplus-sidebar-root");
if (!(root instanceof HTMLElement)) return; if (!(root instanceof HTMLElement)) return;
@@ -52,52 +46,6 @@ function resetSidebarScroll() {
}); });
} }
/**
* SEQTA (and some themes) strip `.active` from `#menu li` after navigation.
* Theme decorations and drill `.sub` chrome depend on that class on our list.
*
* While drilling, never re-apply route-active on root leaves themes like Beach
* paint palm/sand on `#menu > ul > li:not(.hasChildren).active`, and our `.sub`
* is transparent so those decorations show through over folder contents.
*/
export function restoreCustomMenuActive() {
const root = document.getElementById("bsplus-sidebar-root");
if (!root) return;
for (const li of root.querySelectorAll("li.hasChildren")) {
if (!(li instanceof HTMLElement)) continue;
if (!li.querySelector(":scope > .sub")) continue;
ensureActive(li);
}
const activeKey = sidebarState.activeKey;
const drilling = sidebarState.isDrilling;
if (drilling) {
if (activeKey) {
ensureActive(
root.querySelector(`.sub li.item[data-key="${CSS.escape(activeKey)}"]`),
);
}
for (const li of root.querySelectorAll(
'.sub li.item[aria-current="page"]',
)) {
ensureActive(li);
}
return;
}
if (activeKey) {
ensureActive(
root.querySelector(`li.item[data-key="${CSS.escape(activeKey)}"]`),
);
}
for (const li of root.querySelectorAll('li.item[aria-current="page"]')) {
ensureActive(li);
}
}
/** Clear native drill state so it cannot steal pointer-events from the custom list. */ /** Clear native drill state so it cannot steal pointer-events from the custom list. */
export function clearNativeDrillActive(menu: HTMLElement) { export function clearNativeDrillActive(menu: HTMLElement) {
getNativeMenuList(menu) getNativeMenuList(menu)
@@ -251,7 +199,10 @@ class SidebarState {
for (const frame of this.drillStack) { for (const frame of this.drillStack) {
const folder = cursor.find((item) => item.key === frame.key); const folder = cursor.find((item) => item.key === frame.key);
if (!folder?.hasChildren) break; if (!folder?.hasChildren) {
next.push(...this.drillStack.slice(next.length));
break;
}
const children = filterVisible(folder.children); const children = filterVisible(folder.children);
next.push({ key: folder.key, label: folder.label, items: children }); next.push({ key: folder.key, label: folder.label, items: children });
cursor = children; cursor = children;
@@ -380,18 +331,7 @@ class SidebarState {
const native = findNativeMenuEntry(menu, item); const native = findNativeMenuEntry(menu, item);
if (native) { if (native) {
// Clear native drill once only — repeating clearNativeDrillActive fights
// SEQTA (it re-adds .active) and used to freeze the tab via menu sync.
clearNativeDrillActive(menu);
native.click(); native.click();
clearNativeDrillActive(menu);
restoreCustomMenuActive();
requestAnimationFrame(() => {
clearNativeDrillActive(menu);
restoreCustomMenuActive();
});
// Later pass restores custom `.active` only (no native clear loop).
setTimeout(() => restoreCustomMenuActive(), 50);
return; return;
} }
+10 -2
View File
@@ -55,6 +55,10 @@ function sendPayload(payload: Record<string, unknown>): void {
bridge.setAttribute("data-rev", String(Number(bridge.getAttribute("data-rev") || "0") + 1)); bridge.setAttribute("data-rev", String(Number(bridge.getAttribute("data-rev") || "0") + 1));
} }
function preserveCustomSidebarActive(css: string): string {
return css.replace(/\.active(?![\w-])/g, ":is(.active, .bsplus-active)");
}
export async function syncThemeToPage(input: ThemePageSyncInput): Promise<void> { export async function syncThemeToPage(input: ThemePageSyncInput): Promise<void> {
if (input.clear) { if (input.clear) {
sendPayload({ clear: true }); sendPayload({ clear: true });
@@ -63,8 +67,12 @@ export async function syncThemeToPage(input: ThemePageSyncInput): Promise<void>
const payload: Record<string, unknown> = {}; const payload: Record<string, unknown> = {};
if (input.clearPreview) payload.clearPreview = true; if (input.clearPreview) payload.clearPreview = true;
if (input.customCss !== undefined) payload.customCss = input.customCss; if (input.customCss !== undefined) {
if (input.previewCss !== undefined) payload.previewCss = input.previewCss; payload.customCss = preserveCustomSidebarActive(input.customCss);
}
if (input.previewCss !== undefined) {
payload.previewCss = preserveCustomSidebarActive(input.previewCss);
}
if (input.images !== undefined) { if (input.images !== undefined) {
payload.images = await Promise.all( payload.images = await Promise.all(
input.images.map(async (image) => ({ input.images.map(async (image) => ({