dev(frontend) move component options into editor menu (#4221)

* dev(frontend) move component options into editor menu

* dev(frontend) move component options into editor menu

* dev(frontend) add editor menu popovers

---------

Co-authored-by: Guilhem Le Mouel <guilhem.le-mouel.ext@altran.com>
This commit is contained in:
Guilhem
2024-08-11 01:09:14 +02:00
committed by Ruben Fiszel
parent e46c2ea513
commit f25a927b44
7 changed files with 351 additions and 203 deletions
+2 -2
View File
@@ -350,7 +350,7 @@ pub async fn renew_license_key() -> Result<String> {
pub async fn renew_license_key(Extension(db): Extension<DB>, authed: ApiAuthed) -> Result<String> {
require_super_admin(&db, &authed.email).await?;
windmill_common::stats_ee::send_stats(&"manual".to_string(), &HTTP_CLIENT, &db).await?;
let result = windmill_common::ee::renew_license_key(&HTTP_CLIENT, &db).await;
let result = windmill_common::ee::renew_license_key(&HTTP_CLIENT, &db, None).await;
if result != "success" {
return Err(error::Error::BadRequest(format!(
@@ -371,7 +371,7 @@ pub async fn create_customer_portal_session() -> Result<String> {
#[cfg(feature = "enterprise")]
pub async fn create_customer_portal_session() -> Result<String> {
let url = windmill_common::ee::create_customer_portal_session(&HTTP_CLIENT).await?;
let url = windmill_common::ee::create_customer_portal_session(&HTTP_CLIENT, None).await?;
return Ok(url);
}
@@ -1,7 +1,7 @@
<script lang="ts">
import { classNames } from '$lib/utils'
import type { AppViewerContext } from '../types'
import { Anchor, ArrowDownFromLine, Bug, Expand, Move, Network, Pen, Plug2 } from 'lucide-svelte'
import { Anchor, ArrowDownFromLine, Bug, Network, Pen, Plug2 } from 'lucide-svelte'
import { createEventDispatcher, getContext } from 'svelte'
import Popover from '$lib/components/Popover.svelte'
import { Button, Popup } from '$lib/components/common'
@@ -22,12 +22,40 @@
export let inlineEditorOpened: boolean = false
export let errorHandledByComponent: boolean = false
export let fullHeight: boolean = false
export let componentContainerWidth: number
//export let willNotDisplay: boolean = false
const DECISION_TREE_THRESHOLD = 300
const STEPPER_THRESHOLD = 180
const CONDITIONAL_WRAPPER_THRESHOLD = 200
const MINIMUM_WIDTH = 20
let maxWidth = 10
let isManuallySelected = false
let componentIsDebugging = false
$: maxWidth = Math.max(Math.round(0.2 * componentContainerWidth), MINIMUM_WIDTH)
const dispatch = createEventDispatcher()
const { errorByComponent, openDebugRun, connectingInput } =
getContext<AppViewerContext>('AppViewerContext')
// Function to check if any condition is met
function checkComponentOptions(): boolean {
const componentOptions = {
isEditable: hasInlineEditor,
isConditionalWrapper: component.type === 'conditionalwrapper',
hasTabs:
component.type === 'steppercomponent' ||
(component.type === 'tabscomponent' &&
component.configuration.tabsKind.type === 'static' &&
component.configuration.tabsKind.value === 'invisibleOnView'),
isDecisionTree: component.type === 'decisiontreecomponent'
}
return Object.values(componentOptions).some((value) => value)
}
</script>
{#if connecting}
@@ -54,142 +82,153 @@
{#if selected || hover}
<!-- svelte-ignore a11y-no-static-element-interactions -->
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
<span
on:mouseover|stopPropagation={() => {
dispatch('mouseover')
}}
on:mousedown|stopPropagation|capture
draggable="false"
title={`Id: ${component.id}`}
class={twMerge(
'px-2 text-2xs font-semibold w-fit absolute shadow -top-[9px] -left-[8px] border rounded-sm z-50 cursor-move',
selected
? 'bg-indigo-500/90 border-indigo-600 text-white'
: $connectingInput.opened
? 'bg-red-500/90 border-red-600 text-white'
: 'bg-blue-500/90 border-blue-600 text-white'
)}
>
{component.id}
</span>
{/if}
{#if selected && !connecting}
<div class="top-[-9px] -right-[8px] flex flex-row absolute gap-1.5 z-50">
{#if hasInlineEditor}
<button
title="Edit"
class={classNames(
'px-1 text-2xs py-0.5 font-bold w-fit border cursor-pointer rounded-sm',
'bg-indigo-100 text-indigo-600 border-indigo-500 hover:bg-indigo-200 hover:text-indigo-800'
)}
on:click={() => dispatch('triggerInlineEditor')}
on:pointerdown|stopPropagation
>
{#if inlineEditorOpened}
<Pen aria-label="Unlock position" size={14} class="text-orange-500" />
{:else}
<Pen aria-label="Lock position" size={14} />
{/if}
</button>
{/if}
{#if component.type === 'conditionalwrapper'}
<TabsDebug id={component.id} tabs={component.conditions ?? []} isConditionalDebugMode />
{:else if component.type === 'steppercomponent' || (component.type === 'tabscomponent' && component.configuration.tabsKind.type === 'static' && component.configuration.tabsKind.value === 'invisibleOnView')}
<TabsDebug id={component.id} tabs={component.tabs ?? []} />
{:else if component.type === 'decisiontreecomponent'}
<button
title={'Open Decision Tree Editor'}
class={classNames(
'text-2xs py-0.5 px-1 font-bold w-fit border cursor-pointer rounded-sm',
'bg-indigo-100 text-indigo-600 border-indigo-500 hover:bg-indigo-200 hover:text-indigo-800'
)}
on:click={() => {
const element = document.getElementById(`decision-tree-graph-editor`)
if (element) {
element.click()
}
}}
on:pointerdown|stopPropagation
>
<Network size={14} />
</button>
<DecisionTreeDebug id={component.id} nodes={component.nodes ?? []} />
{/if}
<!-- {#if willNotDisplay}
<Popover>
<svelte:fragment slot="text">
This component won't render, because an other component above it is set to fill the
height.
</svelte:fragment>
<div
title="Fill height"
class={classNames(
'px-1 text-2xs py-0.5 font-bold w-fit border cursor-pointer rounded-sm',
'bg-red-100 text-red-600 border-red-500 hover:bg-red-200 hover:text-red-800'
)}
>
<EyeOff aria-label="Expand position" size={14} />
</div>
</Popover>
{/if} -->
<button
title="Fill height"
class={classNames(
'px-1 text-2xs py-0.5 font-bold w-fit border cursor-pointer rounded-sm',
'bg-indigo-100 text-indigo-600 border-indigo-500 hover:bg-indigo-200 hover:text-indigo-800'
)}
on:click={() => dispatch('fillHeight')}
on:pointerdown|stopPropagation
>
<ArrowDownFromLine
aria-label="Expand position"
size={14}
class={fullHeight ? 'text-orange-500' : ''}
/>
</button>
<button
title="Expand"
class={classNames(
'px-1 text-2xs py-0.5 font-bold w-fit border cursor-pointer rounded-sm',
'bg-indigo-100 text-indigo-600 border-indigo-500 hover:bg-indigo-200 hover:text-indigo-800'
)}
on:click={() => dispatch('expand')}
on:pointerdown|stopPropagation
>
<Expand aria-label="Expand position" size={14} />
</button>
<button
title="Lock Position"
class={classNames(
'px-1 text-2xs py-0.5 font-bold w-fit border rounded-sm cursor-pointer',
'bg-indigo-100 text-indigo-600 border-indigo-500 hover:bg-indigo-200 hover:text-indigo-800'
)}
on:click={() => dispatch('lock')}
on:pointerdown|stopPropagation
>
{#if locked}
<Anchor aria-label="Unlock position" size={14} class="text-orange-500" />
{:else}
<Anchor aria-label="Lock position" size={14} />
{/if}
</button>
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div class="-top-[18px] -left-[8px] flex flex-row flex-nowrap w-fit h-fit absolute gap-0.5">
<div
draggable="false"
title="Move"
on:mouseover|stopPropagation={() => {
dispatch('mouseover')
}}
on:mousedown|stopPropagation|capture
class={classNames(
'px-1 text-2xs py-0.5 font-bold w-fit border cursor-move rounded-sm',
'bg-indigo-100 text-indigo-600 border-indigo-500 hover:bg-indigo-200 hover:text-indigo-800',
'flex items-center justify-center'
draggable="false"
title={`Id: ${component.id}`}
class={twMerge(
'py-0.5 text-2xs w-fit h-full min-h-5 border rounded z-50 cursor-move flex flex-row flex-nowrap font-semibold items-center shadow',
selected
? 'bg-indigo-500/90 border-indigo-500 text-white'
: $connectingInput.opened
? 'bg-red-500/90 border-red-600 text-white'
: 'bg-blue-500/90 border-blue-600 text-white'
)}
>
<Move size={14} />
<div class={`px-1 text-2xs w-full min-w-4 h-full truncate`} style="max-width: {maxWidth}px;">
{component.id}
</div>
{#if !connecting}
<div class="flex flex-row px-1 py-0 gap-0.5">
<button
title="Fill height"
class={twMerge(
'px-1 py-0.5 text-2xs font-bold rounded cursor-pointer w-fit h-full',
fullHeight
? ' bg-indigo-800 text-indigo-200'
: 'text-white hover:bg-indigo-700 hover:text-indigo-200'
)}
on:click={() => dispatch('fillHeight')}
on:pointerdown|stopPropagation
>
<ArrowDownFromLine aria-label="Expand position" size={11} />
</button>
<button
title="Lock Position"
class={twMerge(
'px-1 py-0.5 text-2xs font-bold rounded cursor-pointer w-fit h-full',
locked
? ' bg-indigo-800 text-indigo-200'
: 'text-white hover:bg-indigo-700 hover:text-indigo-200'
)}
on:click={() => dispatch('lock')}
on:pointerdown|stopPropagation
>
{#if locked}
<Anchor aria-label="Unlock position" size={11} />
{:else}
<Anchor aria-label="Lock position" size={11} />
{/if}
</button>
</div>
{/if}
</div>
{#if selected && !connecting && checkComponentOptions()}
<div
class={twMerge(
'px-1 py-0.5 text-2xs font-semibold w-fit min-h-5 border shadow rounded z-50 flex flex-row items-center flex-nowrap',
isManuallySelected || componentIsDebugging
? 'bg-red-100 text-red-600 border-red-500'
: 'bg-indigo-100/90 border-indigo-200 text-indigo-600'
)}
>
{#if hasInlineEditor}
<button
title="Edit"
class={twMerge(
'px-1 py-0.5 text-2xs font-bold rounded cursor-pointer w-fit h-full',
inlineEditorOpened
? 'bg-indigo-300 text-indigo-800'
: 'text-indigo-600 hover:bg-indigo-300 hover:text-indigo-800'
)}
on:click={() => dispatch('triggerInlineEditor')}
on:pointerdown|stopPropagation
>
{#if inlineEditorOpened}
<Pen aria-label="Unlock position" size={11} />
{:else}
<Pen aria-label="Lock position" size={11} />
{/if}
</button>
{/if}
{#if component.type === 'conditionalwrapper'}
<TabsDebug
id={component.id}
tabs={component.conditions ?? []}
isConditionalDebugMode
isSmall={componentContainerWidth < CONDITIONAL_WRAPPER_THRESHOLD}
bind:isManuallySelected
/>
{:else if component.type === 'steppercomponent' || (component.type === 'tabscomponent' && component.configuration.tabsKind.type === 'static' && component.configuration.tabsKind.value === 'invisibleOnView')}
<TabsDebug
id={component.id}
tabs={component.tabs ?? []}
isSmall={componentContainerWidth < STEPPER_THRESHOLD}
bind:isManuallySelected
/>
{:else if component.type === 'decisiontreecomponent'}
<button
title={'Open Decision Tree Editor'}
class={twMerge(
'px-1 py-0.5 text-2xs font-bold rounded cursor-pointer w-fit h-full',
componentIsDebugging
? 'text-red-600 hover:bg-red-300 hover:text-red-800'
: 'text-indigo-600 hover:bg-indigo-300 hover:text-indigo-800'
)}
on:click={() => {
const element = document.getElementById(`decision-tree-graph-editor`)
if (element) {
element.click()
}
}}
on:pointerdown|stopPropagation
>
<Network size={11} />
</button>
<DecisionTreeDebug
id={component.id}
nodes={component.nodes ?? []}
isSmall={componentContainerWidth < DECISION_TREE_THRESHOLD}
bind:componentIsDebugging
/>
{/if}
<!-- {#if willNotDisplay}
<Popover>
<svelte:fragment slot="text">
This component won't render, because an other component above it is set to fill the
height.
</svelte:fragment>
<div
title="Fill height"
class={classNames(
'px-1 text-2xs py-0.5 font-bold w-fit border cursor-pointer rounded-sm',
'bg-red-100 text-red-600 border-red-500 hover:bg-red-200 hover:text-red-800'
)}
>
<EyeOff aria-label="Expand position" size={14} />
</div>
</Popover>
{/if} -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
</div>
{/if}
</div>
{/if}
@@ -6,10 +6,14 @@
import type { AppViewerContext } from '../types'
import type { DecisionTreeNode } from './component'
import { isDebugging } from './settingsPanel/decisionTree/utils'
import { X } from 'lucide-svelte'
import { X, Bug } from 'lucide-svelte'
export let nodes: DecisionTreeNode[] = []
export let id: string
export let isSmall = false
export let componentIsDebugging = false
$: componentIsDebugging = isDebugging($debuggingComponents, id)
const { componentControl, debuggingComponents, worldStore } =
getContext<AppViewerContext>('AppViewerContext')
@@ -71,20 +75,20 @@
<button
title={'Debug tabs'}
class={classNames(
'text-2xs py-0.5 font-bold w-fit border cursor-pointer rounded-sm',
isDebugging($debuggingComponents, id)
? 'bg-red-100 text-red-600 border-red-500 hover:bg-red-200 hover:text-red-800'
: 'bg-indigo-100 text-indigo-600 border-indigo-500 hover:bg-indigo-200 hover:text-indigo-800'
'px-1 text-2xs font-bold rounded cursor-pointer w-fit h-full',
componentIsDebugging
? ' hover:bg-red-300 hover:text-red-800'
: ' hover:bg-indigo-300 hover:text-indigo-800'
)}
on:click={() => dispatch('triggerInlineEditor')}
on:pointerdown|stopPropagation
>
<ButtonDropdown hasPadding={false}>
<svelte:fragment slot="buttonReplacement">
<div class="px-1">
{#if isDebugging($debuggingComponents, id)}
<div class="px-1 w-fit">
{#if componentIsDebugging}
<div class="flex flex-row items-center gap-2">
{`Debugging node ${nodes[$debuggingComponents[id] ?? 0]?.id}`}
{`${isSmall ? '' : 'Debugging node'} ${nodes[$debuggingComponents[id] ?? 0]?.id}`}
<button
on:click={() => {
$componentControl?.[id]?.setTab?.(0)
@@ -94,12 +98,14 @@
)
}}
>
<X size={14} />
<X size={11} />
</button>
</div>
{:else}
{`Debug nodes (current node: ${currentNodeId})`}
{/if}
{:else if isSmall}
<div class="flex h-full w-fit items-center"><Bug size={11} /></div>
{:else}<div class="whitespace-nowrap h-full"
>{`Debug nodes (current node: ${currentNodeId})`}</div
>{/if}
</div>
</svelte:fragment>
<svelte:fragment slot="items">
@@ -45,6 +45,23 @@
.flatMap((id) => dfs($app.grid, id, $app.subgrids ?? {}))
.filter((x) => x != undefined) as string[]
}
function handleLock(id: string) {
const gridItem = findGridItem($app, id)
if (gridItem) {
toggleFixed(gridItem)
}
$app = $app
}
function handleFillHeight(id: string) {
const gridItem = findGridItem($app, id)
const b = $breakpoint === 'sm' ? 3 : 12
if (gridItem?.[b]) {
gridItem[b].fullHeight = !gridItem[b].fullHeight
}
$app = $app
}
</script>
<div class="w-full z-[1000] overflow-visible h-full">
@@ -137,7 +154,23 @@
Boolean($selectedComponent?.includes(dataItem.id)) ? 'active-grid-item' : ''
)}
>
<GridEditorMenu id={dataItem.id}>
<GridEditorMenu
id={dataItem.id}
on:expand={() => {
push(history, $app)
$selectedComponent = [dataItem.id]
expandGriditem($app.grid, dataItem.id, $breakpoint)
$app = $app
}}
on:lock={() => {
handleLock(dataItem.id)
}}
on:fillHeight={() => {
handleFillHeight(dataItem.id)
}}
locked={isFixed(dataItem)}
fullHeight={dataItem?.[$breakpoint === 'sm' ? 3 : 12]?.fullHeight}
>
<Component
{hidden}
render={true}
@@ -146,25 +179,10 @@
locked={isFixed(dataItem)}
fullHeight={dataItem?.[$breakpoint === 'sm' ? 3 : 12]?.fullHeight}
on:lock={() => {
const gridItem = findGridItem($app, dataItem.id)
if (gridItem) {
toggleFixed(gridItem)
}
$app = $app
}}
on:expand={() => {
push(history, $app)
$selectedComponent = [dataItem.id]
expandGriditem($app.grid, dataItem.id, $breakpoint)
$app = $app
handleLock(dataItem.id)
}}
on:fillHeight={() => {
const gridItem = findGridItem($app, dataItem.id)
const b = $breakpoint === 'sm' ? 3 : 12
if (gridItem?.[b]) {
gridItem[b].fullHeight = !gridItem[b].fullHeight
}
$app = $app
handleFillHeight(dataItem.id)
}}
/>
</GridEditorMenu>
@@ -1,5 +1,6 @@
<script context="module" lang="ts">
import { writable } from 'svelte/store'
import Popover from '../../Popover.svelte'
interface ContextMenuRegistry {
id: string
@@ -13,9 +14,18 @@
<script lang="ts">
import { getModifierKey } from '$lib/utils'
import { Copy, Paintbrush2, Scissors, Trash } from 'lucide-svelte'
import {
Anchor,
ArrowDownFromLine,
Copy,
Expand,
ExternalLink,
Paintbrush2,
Scissors,
Trash
} from 'lucide-svelte'
import ComponentCallbacks from './component/ComponentCallbacks.svelte'
import { getContext } from 'svelte'
import { createEventDispatcher, getContext } from 'svelte'
import type { AppEditorContext, AppViewerContext } from '../types'
import DeleteComponent from './settingsPanel/DeleteComponent.svelte'
import { secondaryMenuLeft } from './settingsPanel/secondaryMenu'
@@ -27,6 +37,9 @@
let menuX = 0
let menuY = 0
export let locked: boolean = false
export let fullHeight: boolean = false
function handleRightClick(event: MouseEvent) {
event.preventDefault()
contextMenuVisible = true
@@ -61,11 +74,13 @@
const { selectedComponent } = getContext<AppViewerContext>('AppViewerContext')
const { movingcomponents, stylePanel } = getContext<AppEditorContext>('AppEditorContext')
const dispatch = createEventDispatcher()
let deleteComponent: DeleteComponent | undefined = undefined
const menuItems = [
{
label: 'Cut',
label: () => 'Cut',
onClick: () => {
componentCallbacks?.handleCut(new KeyboardEvent('keydown'))
},
@@ -74,7 +89,7 @@
disabled: $movingcomponents?.includes($selectedComponent?.[0] ?? '')
},
{
label: 'Copy',
label: () => 'Copy',
onClick: () => {
componentCallbacks?.handleCopy(new KeyboardEvent('keydown'))
},
@@ -82,16 +97,53 @@
shortcut: `${getModifierKey()}C`
},
{
label: 'Show style panel',
label: () => (fullHeight ? 'Undo fill height' : 'Fill height'),
onClick: () => {
dispatch('fillHeight')
},
icon: ArrowDownFromLine,
tooltip: {
text: 'When set to full height, a component will extend its height to fill the entire parent container (or canvas).',
link: 'https://www.windmill.dev/docs/apps/app_configuration_settings/app_styling#full-height'
}
},
{
label: () => 'Expand',
onClick: () => {
dispatch('expand')
},
icon: Expand,
tooltip: {
text: "Clicking the expand button maximizes the component's width and height, respecting other components' position.",
link: 'https://www.windmill.dev/docs/apps/canvas#expand-a-component'
}
},
{
label: () => (locked ? 'Unlock' : 'Lock'),
onClick: () => {
dispatch('lock')
},
icon: Anchor,
tooltip: {
text: 'Lock the component to prevent it from being repositioned by other components.',
link: 'https://www.windmill.dev/docs/apps/canvas#lock-the-position-of-a-component'
}
},
{
label: () => 'Show style panel',
onClick: () => {
secondaryMenuLeft?.toggle(stylePanel(), { type: 'style' })
},
icon: Paintbrush2,
disabled: $secondaryMenuLeft.isOpen
disabled: $secondaryMenuLeft.isOpen,
tooltip: {
text: 'Use style panel to define custom CSS and Tailwind classes for the components.',
link: 'https://www.windmill.dev/docs/apps/app_configuration_settings/app_styling'
}
},
{
label: 'Delete',
label: () => 'Delete',
onClick: () => {
deleteComponent?.removeGridElement()
},
@@ -122,30 +174,51 @@
{#each menuItems as item}
<!-- svelte-ignore a11y-no-static-element-interactions -->
<!-- svelte-ignore a11y-click-events-have-key-events -->
<button
class={twMerge(
'flex items-center p-2 hover:bg-surface-hover cursor-pointer transition-all rounded-md w-full',
item.color === 'red' && 'text-red-500',
item.color === 'green' && 'text-green-500',
item.color === 'blue' && 'text-blue-500',
item.disabled && 'opacity-50 cursor-not-allowed'
)}
on:click={() => {
item.onClick()
closeContextMenu()
}}
disabled={item.disabled}
>
<!-- svelte-ignore missing-declaration -->
<svelte:component this={item.icon} class="w-4 h-4" />
<span class="ml-2 text-xs">{item.label}</span>
{#if item.shortcut}
<span class="ml-auto text-xs text-gray-400">
{item.shortcut}
</span>
{/if}
</button>
<Popover
notClickable
placement="right"
popupClass="z-[7000]"
disablePopup={!item.tooltip}
appearTimeout={800}
>
<svelte:fragment slot="text"
>{item.tooltip?.text}
{#if item.tooltip?.link}
<a href={item.tooltip.link} target="_blank" class="text-blue-300 text-xs">
<div class="flex flex-row gap-2 mt-4">
See documentation
<ExternalLink size="16" />
</div>
</a>
{/if}</svelte:fragment
>
<button
class={twMerge(
'flex items-center p-2 hover:bg-surface-hover cursor-pointer transition-all rounded-md w-full',
item.color === 'red' && 'text-red-500',
item.color === 'green' && 'text-green-500',
item.color === 'blue' && 'text-blue-500',
item.disabled && 'opacity-50 cursor-not-allowed'
)}
on:click={() => {
item.onClick()
closeContextMenu()
}}
disabled={item.disabled}
>
<!-- svelte-ignore missing-declaration -->
<svelte:component this={item.icon} class="w-4 h-4" />
<span class="ml-2 text-xs">{item.label()}</span>
{#if item.shortcut}
<span class="ml-auto text-xs text-gray-400">
{item.shortcut}
</span>
{/if}
</button>
</Popover>
{/each}
</div>
</div>
@@ -4,26 +4,28 @@
import { MenuItem } from '@rgossiaux/svelte-headlessui'
import { createEventDispatcher, getContext } from 'svelte'
import type { AppViewerContext } from '../types'
import { Bug } from 'lucide-svelte'
export let tabs: any[] = []
export let id: string
export let isConditionalDebugMode: boolean = false
export let isSmall = false
const { componentControl } = getContext<AppViewerContext>('AppViewerContext')
const dispatch = createEventDispatcher()
let isManuallySelected: boolean = false
export let isManuallySelected: boolean = false
let selected: number | null = null
</script>
<button
title={isConditionalDebugMode ? 'Debug conditions' : 'Debug tabs'}
class={classNames(
'text-2xs py-0.5 font-bold w-fit border cursor-pointer rounded-sm',
'text-2xs font-bold w-fit h-full cursor-pointer rounded',
isManuallySelected
? 'bg-red-100 text-red-600 border-red-500 hover:bg-red-200 hover:text-red-800'
: 'bg-indigo-100 text-indigo-600 border-indigo-500 hover:bg-indigo-200 hover:text-indigo-800'
? 'hover:bg-red-200 hover:text-red-800'
: ' hover:text-indigo-800 hover:bg-indigo-300'
)}
on:click={() => dispatch('triggerInlineEditor')}
on:pointerdown|stopPropagation
@@ -32,14 +34,21 @@
<svelte:fragment slot="buttonReplacement">
<div class="px-1">
{#if isManuallySelected}
<div>
<div class="whitespace-nowrap">
{#if selected === tabs.length - 1}
{isConditionalDebugMode ? `Debug default condition` : `Debug tab ${selected + 1}`}
{#if isSmall}
{isConditionalDebugMode ? `df` : `t ${selected + 1}`}
{:else}
{isConditionalDebugMode ? `Debug default condition` : `Debug tab ${selected + 1}`}
{/if}
{:else if isSmall}
{`${isConditionalDebugMode ? 'c' : 't'} ${(selected ?? 0) + 1}`}
{:else}
{`Debugging ${isConditionalDebugMode ? 'condition' : 'tab'} ${(selected ?? 0) + 1}`}
{/if}
{`Debugging ${isConditionalDebugMode ? 'condition' : 'tab'} ${
(selected ?? 0) + 1
}`}{/if}
</div>
{:else}
{:else if isSmall}<Bug size={11} />{:else}
{isConditionalDebugMode ? `Debug conditions` : `Debug tabs`}
{/if}
</div>
@@ -99,6 +99,7 @@
let initializing: boolean | undefined = undefined
let errorHandledByComponent: boolean = false
let componentContainerHeight: number = 0
let componentContainerWidth: number = 0
let inlineEditorOpened: boolean = false
@@ -158,6 +159,7 @@
inlineEditorOpened = !inlineEditorOpened
}}
{errorHandledByComponent}
{componentContainerWidth}
/>
{/if}
@@ -191,6 +193,7 @@
)}
style={$app.css?.['app']?.['component']?.style}
bind:clientHeight={componentContainerHeight}
bind:clientWidth={componentContainerWidth}
>
{#if component.type === 'displaycomponent'}
<AppDisplayComponent