Skip to content
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
069e2fd
feat: favorites
LittleSound Dec 20, 2025
296a9e1
feat: settings tab
LittleSound Dec 23, 2025
0d71d53
revert: settings tab + favorites
LittleSound Dec 23, 2025
4bdb441
feat: favorite + settings
LittleSound Dec 23, 2025
3013780
feat: settings
LittleSound Dec 23, 2025
9d83cd3
feat: tab nodes
LittleSound Dec 23, 2025
65a57d1
feat: group
LittleSound Dec 23, 2025
1fa6e13
feat: locate
LittleSound Dec 23, 2025
8293de2
fix: remove unused exports from favoritedWidgetsStore
LittleSound Dec 24, 2025
a032ac4
feat: widget actions
LittleSound Dec 26, 2025
b224e98
feat: drag and drop sorting in favorites
LittleSound Dec 29, 2025
b4d86d5
feat: favorite indicator
LittleSound Dec 29, 2025
ea8c41c
feat: show the node name from where this parameter comes from on subg…
LittleSound Dec 29, 2025
ab06fcd
feat: advance inputs
LittleSound Dec 29, 2025
87ed0c1
feat: show advance inputs button
LittleSound Dec 29, 2025
bd48922
fix: update favorites label for clarity
LittleSound Dec 30, 2025
4f95f0d
refactor: widget section and actions
LittleSound Dec 30, 2025
cbe4d59
refactor: the settings
LittleSound Dec 31, 2025
8597e06
refactor: flat and categorize selected items
LittleSound Jan 2, 2026
5b9a279
fix: groups title shown when select mulmultiple items
LittleSound Jan 2, 2026
7506e65
fix: prevent stack overflow in flatItems function by limiting recursi…
LittleSound Jan 2, 2026
c8a8256
feat: add parent group display for selected groups
LittleSound Jan 2, 2026
99095cc
feat: show groups info in more cases
LittleSound Jan 2, 2026
7e501f4
fix: add search state management for widget filtering
LittleSound Jan 5, 2026
c5563d4
fix: enhance accessibility by adding aria-label to locate button and …
LittleSound Jan 5, 2026
fd16859
fix: nodes without widgets cannot display the location and their group
LittleSound Jan 5, 2026
9650e85
fix: show node name in favorite widgets + improve labels layout
LittleSound Jan 5, 2026
ebb3cc3
show and hide input widgets do not work on subgraph
LittleSound Jan 6, 2026
5f066b4
fix: favorite feature does not work on subgraph
LittleSound Jan 6, 2026
86dac8c
feat: subgraph inputs rearranging
LittleSound Jan 6, 2026
8f0ed7d
fix: update the displayed name when a widget is renamed
LittleSound Jan 6, 2026
d6b6ae3
fix: layout of locate button
LittleSound Jan 6, 2026
59b561b
refactor: treat subgraph case as an independent tab component
LittleSound Jan 6, 2026
193fa0a
fix: rename proxy widget correctly
LittleSound Jan 6, 2026
acda492
refactor: global settings style reuse for node widgets forms
LittleSound Jan 6, 2026
486cad6
fix: update cursor style for tooltip in LayoutField component
LittleSound Jan 6, 2026
81200d5
refactor: remove search functionality from TabGlobalSettings
LittleSound Jan 6, 2026
7310683
fix: canvas does not update after modifying the subgraph's widgets value
LittleSound Jan 6, 2026
e01e5e1
fix(style): widget actions menu
LittleSound Jan 6, 2026
308b489
fix(style): button show advanced inputs
LittleSound Jan 6, 2026
e48894c
feat: interactive animation
LittleSound Jan 6, 2026
19e0a33
fix: improve search functionality to include node title matching
LittleSound Jan 6, 2026
8134e12
Merge branch 'main' into rizumu/feat/right-side-panel-v3
LittleSound Jan 6, 2026
2637255
fix: change useReactiveWidgetValue to a private function
LittleSound Jan 6, 2026
37f1e94
[automated] Apply ESLint and Prettier fixes
actions-user Jan 6, 2026
8a0217c
fix: drag-and-sort function is unavailable after the collapse panel i…
LittleSound Jan 6, 2026
932ca80
fix: background color does not follow the theme
LittleSound Jan 6, 2026
0135805
fix: search node titles + single-child group bugs
LittleSound Jan 7, 2026
a6f9f91
refactor: update favorited widgets storage to use workflow.extra data
LittleSound Jan 8, 2026
d4a6fde
fix: panel status not updated after switching workflows
LittleSound Jan 8, 2026
de9d3a4
fix(style): more gap between fields
LittleSound Jan 8, 2026
ebf8731
feat: add empty state display
LittleSound Jan 8, 2026
61ba51e
feat: right click to favorite widget
LittleSound Jan 8, 2026
55d4e02
fix: seed control button missing
LittleSound Jan 8, 2026
59b75ce
fix: widget select dropdown display in right side panel
LittleSound Jan 8, 2026
40faf68
refactor: widget enhancements for shared usage in Right Side Panel
LittleSound Jan 8, 2026
37e4d4d
feat: implement widget renaming functionality and improve title editi…
LittleSound Jan 8, 2026
c5f95bb
[automated] Apply ESLint and Prettier fixes
actions-user Jan 8, 2026
34eeb37
feat: persist panel switch state
LittleSound Jan 8, 2026
8bbb44e
feat: sync search status across multiple panels
LittleSound Jan 8, 2026
6bd8711
refactor: search component generalization
LittleSound Jan 8, 2026
17808d6
fix: error showing empty state
LittleSound Jan 8, 2026
7d2c3af
fix: dropdown menu is obscured in draggable widgets
LittleSound Jan 8, 2026
11f3a72
fix: unified the edit icon size
LittleSound Jan 9, 2026
e00be30
fix: button size of locate
LittleSound Jan 9, 2026
924d956
fix: based on the suggestion from coderabbitai
LittleSound Jan 9, 2026
f7be62a
Merge branch 'main' into rizumu/feat/right-side-panel-v3
LittleSound Jan 9, 2026
920072e
refactor: scrolling to advanced inputs
LittleSound Jan 12, 2026
950739e
feat: implement graph hierarchy management with findParentGroup function
LittleSound Jan 12, 2026
88c1380
refactor: simplified PropertiesAccordionItem parameters
LittleSound Jan 12, 2026
20350c4
refactor: use v-bind in MoreButton
LittleSound Jan 12, 2026
8a38897
refactor: optimize right side panel components and improve widget han…
LittleSound Jan 12, 2026
1516dba
chore: remove unsed exported types
LittleSound Jan 12, 2026
d2b59e4
[automated] Apply ESLint and Prettier fixes
actions-user Jan 12, 2026
f850fc5
Merge branch 'main' into rizumu/feat/right-side-panel-v3
LittleSound Jan 12, 2026
30f19df
[automated] Update test expectations
invalid-email-address Jan 13, 2026
838e006
test: update properties panel title assertions for selected nodes
LittleSound Jan 13, 2026
6e2308a
chore: remove mobile settings dialog snapshot
christian-byrne Jan 14, 2026
f8c2aa8
Merge remote-tracking branch 'origin/main' into pr-7812
christian-byrne Jan 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 45 additions & 24 deletions src/components/rightSidePanel/RightSidePanel.vue
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: The selection state logic seems like it might be worth refactoring into a separate module

Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ import { isLGraphNode } from '@/utils/litegraphUtil'
import { cn } from '@/utils/tailwindUtil'

import TabInfo from './info/TabInfo.vue'
import TabGlobalParameters from './parameters/TabGlobalParameters.vue'
import TabNodes from './parameters/TabNodes.vue'
import TabParameters from './parameters/TabParameters.vue'
import TabGlobalSettings from './settings/TabGlobalSettings.vue'
import TabSettings from './settings/TabSettings.vue'
import SubgraphEditor from './subgraph/SubgraphEditor.vue'

Expand Down Expand Up @@ -45,10 +48,17 @@ const selectedNode = computed(() => {

const selectionCount = computed(() => selectedItems.value.length)

const rootLevelNodes = computed((): LGraphNode[] => {
return (canvasStore.canvas?.graph?._nodes ?? []) as LGraphNode[]
})

const panelTitle = computed(() => {
if (isSingleNodeSelected.value && selectedNode.value) {
return selectedNode.value.title || selectedNode.value.type || 'Node'
}
if (selectionCount.value === 0) {
return t('rightSidePanel.workflowOverview')
}
return t('rightSidePanel.title', { count: selectionCount.value })
})

Expand All @@ -62,25 +72,37 @@ type RightSidePanelTabList = Array<{
}>

const tabs = computed<RightSidePanelTabList>(() => {
const list: RightSidePanelTabList = [
{
label: () => t('rightSidePanel.parameters'),
value: 'parameters'
},
{
label: () => t('g.settings'),
value: 'settings'
}
]
if (
!hasSelection.value ||
(isSingleNodeSelected.value && !isSubgraphNode.value)
) {
const list: RightSidePanelTabList = []

list.push({
label: () => t('rightSidePanel.parameters'),
value: 'parameters'
})

if (!hasSelection.value) {
list.push({
label: () => t('rightSidePanel.info'),
value: 'info'
label: () => t('rightSidePanel.nodes'),
value: 'nodes'
})
}

if (hasSelection.value) {
if (isSingleNodeSelected.value && !isSubgraphNode.value) {
list.push({
label: () => t('rightSidePanel.info'),
value: 'info'
})
}
}

list.push({
label: () =>
hasSelection.value
? t('g.settings')
: t('rightSidePanel.globalSettings.title'),
value: 'settings'
})

return list
})

Expand Down Expand Up @@ -164,7 +186,7 @@ function handleTitleCancel() {
</Button>
</div>
</div>
<nav v-if="hasSelection" class="px-4 pb-2 pt-1">
<nav class="px-4 pb-2 pt-1">
<TabList
:model-value="activeTab"
@update:model-value="
Expand All @@ -187,12 +209,11 @@ function handleTitleCancel() {

<!-- Panel Content -->
<div class="scrollbar-thin flex-1 overflow-y-auto">
<div
v-if="!hasSelection"
class="flex size-full p-4 items-start justify-start text-sm text-muted-foreground"
>
{{ $t('rightSidePanel.noSelection') }}
</div>
<template v-if="!hasSelection">
<TabGlobalParameters v-if="activeTab === 'parameters'" />
<TabNodes v-else-if="activeTab === 'nodes'" :nodes="rootLevelNodes" />
<TabGlobalSettings v-else-if="activeTab === 'settings'" />
</template>
<SubgraphEditor
v-else-if="isSubgraphNode && isEditingSubgraph"
:node="selectedNode"
Expand All @@ -205,7 +226,7 @@ function handleTitleCancel() {
<TabInfo v-else-if="activeTab === 'info'" :nodes="selectedNodes" />
<TabSettings
v-else-if="activeTab === 'settings'"
:nodes="selectedNodes"
:nodes="selectedItems"
/>
</template>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
<script lang="ts" setup>
import { watch } from 'vue'

import { cn } from '@/utils/tailwindUtil'

defineProps<{
const props = defineProps<{
isEmpty?: boolean
defaultCollapse?: boolean
}>()
Comment on lines +8 to 13
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider Vue 3.5 reactive props destructuring.

Per coding guidelines, prefer destructuring props directly. This also allows setting defaults inline:

♻️ Suggested refactor
-const props = defineProps<{
+const {
+  disabled = false,
+  label,
+  enableEmptyState = false,
+  tooltip
+} = defineProps<{
   disabled?: boolean
   label?: string
   enableEmptyState?: boolean
   tooltip?: string
-}>()
+}>()

Then update line 17:

-const isExpanded = computed(() => !isCollapse.value && !props.disabled)
+const isExpanded = computed(() => !isCollapse.value && !disabled)

And lines 19-21:

 const tooltipConfig = computed(() => {
-  if (!props.tooltip) return undefined
-  return { value: props.tooltip, showDelay: 1000 }
+  if (!tooltip) return undefined
+  return { value: tooltip, showDelay: 1000 }
 })
🤖 Prompt for AI Agents
In @src/components/rightSidePanel/layout/PropertiesAccordionItem.vue around
lines 8 - 13, The props are currently accessed via defineProps(...) without
destructuring; change to destructure them inline so you can set defaults (e.g.,
const { disabled = false, label = '', enableEmptyState = true, tooltip = '' } =
defineProps<{ disabled?: boolean; label?: string; enableEmptyState?: boolean;
tooltip?: string }>()), then update usages in the template/logic (the references
around the current line 17 and lines 19-21) to use the destructured variables
(disabled, label, enableEmptyState, tooltip) instead of accessing them off the
props object.


const isCollapse = defineModel<boolean>('collapse', { default: false })

if (props.defaultCollapse) {
isCollapse.value = true
}
watch(
() => props.defaultCollapse,
(value) => (isCollapse.value = value)
)
</script>

<template>
Expand All @@ -32,7 +43,7 @@ const isCollapse = defineModel<boolean>('collapse', { default: false })
:disabled="isEmpty"
@click="isCollapse = !isCollapse"
Comment on lines 30 to 40
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add aria-expanded for accessibility.

The accordion button should communicate its expanded state to assistive technologies.

♿ Proposed fix
       <button
         v-tooltip="tooltipConfig"
         type="button"
+        :aria-expanded="isExpanded"
         :class="
           cn(
             'group min-h-12 bg-transparent border-0 outline-0 ring-0 w-full text-left flex items-center justify-between pl-4 pr-3',
             !disabled && 'cursor-pointer'
           )
         "
         :disabled="disabled"
         @click="isCollapse = !isCollapse"
       >
🤖 Prompt for AI Agents
In @src/components/rightSidePanel/layout/PropertiesAccordionItem.vue around
lines 30 - 40, The button currently toggles the panel via the isCollapse data
prop but doesn't expose its state to assistive tech; add an aria-expanded
binding to the button such as :aria-expanded="!isCollapse" (or the inverse if
your state semantics differ) so the button reports true when the panel is open;
update the <button> element that uses isCollapse, disabled, and tooltipConfig to
include this aria-expanded binding.

>
<span class="text-sm font-semibold line-clamp-2">
<span class="text-sm font-semibold line-clamp-2 flex-1">
<slot name="label" />
</span>

Expand Down
29 changes: 29 additions & 0 deletions src/components/rightSidePanel/layout/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { IBaseWidget } from '@/lib/litegraph/src/types/widgets'

/**
* Searches widgets in a list and returns search results.
* Filters by name, localized label, type, and user-input value.
* Performs basic tokenization of the query string.
*/
export function searchWidgets<T extends { widget: IBaseWidget }[]>(
list: T,
query: string
): T {
if (query.trim() === '') {
return list
}
const words = query.trim().toLowerCase().split(' ')
return list.filter(({ widget }) => {
const label = widget.label?.toLowerCase()
const name = widget.name.toLowerCase()
const type = widget.type.toLowerCase()
const value = widget.value?.toString().toLowerCase()
return words.every(
(word) =>
name.includes(word) ||
label?.includes(word) ||
type?.includes(word) ||
value?.includes(word)
)
}) as T
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Unsafe type assertion loses type safety.

The as T cast on line 28 is incorrect. The filter() method always returns T[number][] (the element type in an array), not the original tuple or specialized array type T. If T is a tuple type or has additional type constraints beyond { widget: IBaseWidget }[], this assertion will silently break type safety.

🔎 Proposed fix: Simplify the generic constraint
-export function searchWidgets<T extends { widget: IBaseWidget }[]>(
-  list: T,
-  query: string
-): T {
+export function searchWidgets<T extends { widget: IBaseWidget }>(
+  list: T[],
+  query: string
+): T[] {
   if (query.trim() === '') {
     return list
   }
   const words = query.trim().toLowerCase().split(' ')
   return list.filter(({ widget }) => {
     const label = widget.label?.toLowerCase()
     const name = widget.name.toLowerCase()
     const type = widget.type.toLowerCase()
     const value = widget.value?.toString().toLowerCase()
     return words.every(
       (word) =>
         name.includes(word) ||
         label?.includes(word) ||
         type?.includes(word) ||
         value?.includes(word)
     )
-  }) as T
+  })
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function searchWidgets<T extends { widget: IBaseWidget }[]>(
list: T,
query: string
): T {
if (query.trim() === '') {
return list
}
const words = query.trim().toLowerCase().split(' ')
return list.filter(({ widget }) => {
const label = widget.label?.toLowerCase()
const name = widget.name.toLowerCase()
const type = widget.type.toLowerCase()
const value = widget.value?.toString().toLowerCase()
return words.every(
(word) =>
name.includes(word) ||
label?.includes(word) ||
type?.includes(word) ||
value?.includes(word)
)
}) as T
}
export function searchWidgets<T extends { widget: IBaseWidget }>(
list: T[],
query: string
): T[] {
if (query.trim() === '') {
return list
}
const words = query.trim().toLowerCase().split(' ')
return list.filter(({ widget }) => {
const label = widget.label?.toLowerCase()
const name = widget.name.toLowerCase()
const type = widget.type.toLowerCase()
const value = widget.value?.toString().toLowerCase()
return words.every(
(word) =>
name.includes(word) ||
label?.includes(word) ||
type?.includes(word) ||
value?.includes(word)
)
})
}
🤖 Prompt for AI Agents
In src/components/rightSidePanel/layout/index.ts around lines 8 to 29, the
function uses an unsafe "as T" cast on the filtered result which loses type
safety; change the generic to represent the element type rather than the array
type (e.g. use a generic U extends { widget: IBaseWidget } and accept list:
U[]), have the function return U[] and let TypeScript infer the filter result as
U[] (remove the "as T" cast), and update the function signature and any call
sites accordingly so the return type correctly matches the element type of the
input array.

146 changes: 105 additions & 41 deletions src/components/rightSidePanel/parameters/SectionWidgets.vue
Original file line number Diff line number Diff line change
@@ -1,34 +1,56 @@
<script setup lang="ts">
import { computed, provide } from 'vue'
import {
computed,
provide,
ref,
shallowRef,
triggerRef,
watchEffect
} from 'vue'
import { useI18n } from 'vue-i18n'

import type { LGraphNode } from '@/lib/litegraph/src/litegraph'
import Button from '@/components/ui/button/Button.vue'
import type { LGraphNode, SubgraphNode } from '@/lib/litegraph/src/litegraph'
import type { IBaseWidget } from '@/lib/litegraph/src/types/widgets'
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
import WidgetLegacy from '@/renderer/extensions/vueNodes/widgets/components/WidgetLegacy.vue'
import {
getComponent,
shouldExpand
} from '@/renderer/extensions/vueNodes/widgets/registry/widgetRegistry'
import { cn } from '@/utils/tailwindUtil'

import PropertiesAccordionItem from '../layout/PropertiesAccordionItem.vue'
import WidgetItem from './WidgetItem.vue'

const { label, widgets } = defineProps<{
const {
label,
widgets: widgetsProp,
showLocateButton = false,
isDraggable = false,
hiddenFavoriteIndicator = false,
showNodeName = false,
defaultCollapse = false,
parents = [],
isShownOnParents = false
} = defineProps<{
label?: string
parents?: SubgraphNode[]
widgets: { widget: IBaseWidget; node: LGraphNode }[]
showLocateButton?: boolean
isDraggable?: boolean
hiddenFavoriteIndicator?: boolean
showNodeName?: boolean
defaultCollapse?: boolean
isShownOnParents?: boolean
}>()

const collapse = defineModel<boolean>('collapse')

const widgetsContainer = ref<HTMLElement>()

const widgets = shallowRef(widgetsProp)
watchEffect(() => (widgets.value = widgetsProp))

provide('hideLayoutField', true)

const canvasStore = useCanvasStore()
const { t } = useI18n()

function getWidgetComponent(widget: IBaseWidget) {
const component = getComponent(widget.type, widget.name)
return component || WidgetLegacy
}

function onWidgetValueChange(
widget: IBaseWidget,
value: string | number | boolean | object
Expand All @@ -38,7 +60,11 @@ function onWidgetValueChange(
canvasStore.canvas?.setDirty(true, true)
}

const isEmpty = computed(() => widgets.length === 0)
function onWidgetUpdate() {
triggerRef(widgets)
}
Comment on lines +62 to 83
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Harden proxyWidgets parsing and avoid == comparisons for ids.
If parents[0].properties/proxyWidgets is missing or malformed, parseProxyWidgets(...) may throw. Also, using == hides type bugs; prefer normalizing ids to numbers/strings and comparing with ===.


const isEmpty = computed(() => widgets.value.length === 0)

const displayLabel = computed(
() =>
Expand All @@ -47,40 +73,78 @@ const displayLabel = computed(
? t('rightSidePanel.inputsNone')
: t('rightSidePanel.inputs'))
)

const targetNode = computed<LGraphNode | null>(() => {
if (!showLocateButton || isEmpty.value) return null

const firstNodeId = widgets.value[0]?.node.id
const allSameNode = widgets.value.every(({ node }) => node.id === firstNodeId)

return allSameNode ? widgets.value[0].node : null
})

const canShowLocateButton = computed(
() => showLocateButton && targetNode.value !== null
)

function handleLocateNode() {
if (!targetNode.value || !canvasStore.canvas) return

const graphNode = canvasStore.canvas.graph?.getNodeById(targetNode.value.id)
if (graphNode) {
canvasStore.canvas.animateToBounds(graphNode.boundingRect)
}
}

defineExpose({
widgetsContainer
})
</script>

<template>
<PropertiesAccordionItem :is-empty>
<PropertiesAccordionItem
v-model:collapse="collapse"
:is-empty
:default-collapse="defaultCollapse"
>
<template #label>
<slot name="label">
{{ displayLabel }}
</slot>
<div class="flex items-center gap-2 flex-1 min-w-0">
<span class="truncate flex-1">
<slot name="label">
{{ displayLabel }}
</slot>
</span>
<Button
v-if="canShowLocateButton"
variant="textonly"
size="icon-sm"
class="shrink-0 mr-3"
:title="t('rightSidePanel.locateNode')"
@click.stop="handleLocateNode"
>
<i class="icon-[lucide--locate] size-4 text-muted-foreground" />
</Button>
</div>
</template>

<div v-if="!isEmpty" class="space-y-4 rounded-lg bg-interface-surface px-4">
<div
<div
v-if="!isEmpty"
ref="widgetsContainer"
class="space-y-2 rounded-lg px-4 pt-1"
>
<WidgetItem
v-for="({ widget, node }, index) in widgets"
:key="`widget-${index}-${widget.name}`"
class="widget-item gap-1.5 col-span-full grid grid-cols-subgrid"
>
<div class="min-h-8">
<p v-if="widget.name" class="text-sm leading-8 p-0 m-0 line-clamp-1">
{{ widget.label || widget.name }}
</p>
</div>
<component
:is="getWidgetComponent(widget)"
:widget="widget"
:model-value="widget.value"
:node-id="String(node.id)"
:node-type="node.type"
:class="cn('col-span-1', shouldExpand(widget.type) && 'min-h-36')"
@update:model-value="
(value: string | number | boolean | object) =>
onWidgetValueChange(widget, value)
"
/>
</div>
:widget="widget"
:node="node"
:is-draggable="isDraggable"
:hidden-favorite-indicator="hiddenFavoriteIndicator"
:show-node-name="showNodeName"
:parents="parents"
:is-shown-on-parents="isShownOnParents"
@value-change="onWidgetValueChange"
@widget-update="onWidgetUpdate"
/>
</div>
</PropertiesAccordionItem>
</template>
Loading