mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-25 04:34:06 -08:00
feat(editor): Update new canvas node handle label rendering mechanism and design (no-changelog) (#10611)
This commit is contained in:
parent
402a8b40c0
commit
38eb00a643
|
@ -72,6 +72,12 @@
|
||||||
--color-canvas-read-only-line: var(--prim-gray-800);
|
--color-canvas-read-only-line: var(--prim-gray-800);
|
||||||
--color-canvas-selected: var(--prim-gray-0-alpha-025);
|
--color-canvas-selected: var(--prim-gray-0-alpha-025);
|
||||||
--color-canvas-selected-transparent: var(--color-canvas-selected);
|
--color-canvas-selected-transparent: var(--color-canvas-selected);
|
||||||
|
--color-canvas-label-background: hsla(
|
||||||
|
var(--color-canvas-background-h),
|
||||||
|
var(--color-canvas-background-s),
|
||||||
|
var(--color-canvas-background-l),
|
||||||
|
0.85
|
||||||
|
);
|
||||||
|
|
||||||
// Nodes
|
// Nodes
|
||||||
--color-node-background: var(--prim-gray-740);
|
--color-node-background: var(--prim-gray-740);
|
||||||
|
|
|
@ -80,6 +80,12 @@
|
||||||
--color-canvas-read-only-line: var(--prim-gray-30);
|
--color-canvas-read-only-line: var(--prim-gray-30);
|
||||||
--color-canvas-selected: var(--prim-gray-70);
|
--color-canvas-selected: var(--prim-gray-70);
|
||||||
--color-canvas-selected-transparent: hsla(var(--prim-gray-h), 47%, 30%, 0.1);
|
--color-canvas-selected-transparent: hsla(var(--prim-gray-h), 47%, 30%, 0.1);
|
||||||
|
--color-canvas-label-background: hsla(
|
||||||
|
var(--color-canvas-background-h),
|
||||||
|
var(--color-canvas-background-s),
|
||||||
|
var(--color-canvas-background-l),
|
||||||
|
0.85
|
||||||
|
);
|
||||||
|
|
||||||
// Nodes
|
// Nodes
|
||||||
--color-node-background: var(--color-background-xlight);
|
--color-node-background: var(--color-background-xlight);
|
||||||
|
|
|
@ -22,13 +22,14 @@ const handleClasses = 'target';
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 20px;
|
top: 50%;
|
||||||
left: 50%;
|
left: calc(var(--spacing-xs) * -1);
|
||||||
transform: translate(-50%, 0);
|
transform: translate(-100%, -50%);
|
||||||
font-size: var(--font-size-2xs);
|
font-size: var(--font-size-2xs);
|
||||||
color: var(--color-foreground-xdark);
|
color: var(--color-foreground-xdark);
|
||||||
background: var(--color-background-light);
|
background: var(--color-canvas-label-background);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,17 +1,31 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useCanvasNodeHandle } from '@/composables/useCanvasNodeHandle';
|
import { useCanvasNodeHandle } from '@/composables/useCanvasNodeHandle';
|
||||||
|
import { useCanvasNode } from '@/composables/useCanvasNode';
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
|
import type { CanvasNodeDefaultRender } from '@/types';
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
add: [];
|
add: [];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const { render } = useCanvasNode();
|
||||||
const { label, isConnected, isConnecting } = useCanvasNodeHandle();
|
const { label, isConnected, isConnecting } = useCanvasNodeHandle();
|
||||||
|
|
||||||
const handleClasses = 'source';
|
const handleClasses = 'source';
|
||||||
|
const isHovered = ref(false);
|
||||||
|
|
||||||
|
const renderOptions = computed(() => render.value.options as CanvasNodeDefaultRender['options']);
|
||||||
|
|
||||||
const isHandlePlusVisible = computed(() => !isConnecting.value || isHovered.value);
|
const isHandlePlusVisible = computed(() => !isConnecting.value || isHovered.value);
|
||||||
const isHovered = ref(false);
|
|
||||||
|
const plusLineSize = computed(
|
||||||
|
() =>
|
||||||
|
({
|
||||||
|
small: 46,
|
||||||
|
medium: 66,
|
||||||
|
large: 80,
|
||||||
|
})[renderOptions.value.outputs?.labelSize ?? 'small'],
|
||||||
|
);
|
||||||
|
|
||||||
function onMouseEnter() {
|
function onMouseEnter() {
|
||||||
isHovered.value = true;
|
isHovered.value = true;
|
||||||
|
@ -33,6 +47,7 @@ function onClickAdd() {
|
||||||
<CanvasHandlePlus
|
<CanvasHandlePlus
|
||||||
v-if="!isConnected"
|
v-if="!isConnected"
|
||||||
v-show="isHandlePlusVisible"
|
v-show="isHandlePlusVisible"
|
||||||
|
:line-size="plusLineSize"
|
||||||
:handle-classes="handleClasses"
|
:handle-classes="handleClasses"
|
||||||
@mouseenter="onMouseEnter"
|
@mouseenter="onMouseEnter"
|
||||||
@mouseleave="onMouseLeave"
|
@mouseleave="onMouseLeave"
|
||||||
|
@ -53,12 +68,16 @@ function onClickAdd() {
|
||||||
.label {
|
.label {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
left: var(--spacing-s);
|
left: var(--spacing-m);
|
||||||
transform: translate(0, -50%);
|
transform: translate(0, -50%);
|
||||||
font-size: var(--font-size-2xs);
|
font-size: var(--font-size-2xs);
|
||||||
color: var(--color-foreground-xdark);
|
color: var(--color-foreground-xdark);
|
||||||
background: var(--color-background-light);
|
background: var(--color-canvas-label-background);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
max-width: calc(100% - var(--spacing-m) - 24px);
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
|
@ -67,9 +67,10 @@ function onClickAdd() {
|
||||||
transform: translate(-50%, 0);
|
transform: translate(-50%, 0);
|
||||||
font-size: var(--font-size-2xs);
|
font-size: var(--font-size-2xs);
|
||||||
color: var(--color-foreground-xdark);
|
color: var(--color-foreground-xdark);
|
||||||
background: var(--color-background-light);
|
background: var(--color-canvas-label-background);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,9 @@ const handleClasses = 'source';
|
||||||
transform: translate(0%, 0);
|
transform: translate(0%, 0);
|
||||||
font-size: var(--font-size-2xs);
|
font-size: var(--font-size-2xs);
|
||||||
color: var(--color-foreground-xdark);
|
color: var(--color-foreground-xdark);
|
||||||
background: var(--color-background-light);
|
background: var(--color-canvas-label-background);
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.vue-flow__handle:not(.connectionindicator)) .plus {
|
:global(.vue-flow__handle:not(.connectionindicator)) .plus {
|
||||||
|
|
|
@ -5,10 +5,14 @@ const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
position?: 'top' | 'right' | 'bottom' | 'left';
|
position?: 'top' | 'right' | 'bottom' | 'left';
|
||||||
handleClasses?: string;
|
handleClasses?: string;
|
||||||
|
plusSize?: number;
|
||||||
|
lineSize?: number;
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
position: 'right',
|
position: 'right',
|
||||||
handleClasses: undefined,
|
handleClasses: undefined,
|
||||||
|
plusSize: 24,
|
||||||
|
lineSize: 46,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -20,46 +24,48 @@ const style = useCssModule();
|
||||||
|
|
||||||
const classes = computed(() => [style.wrapper, style[props.position], props.handleClasses]);
|
const classes = computed(() => [style.wrapper, style[props.position], props.handleClasses]);
|
||||||
|
|
||||||
const plusSize = 24;
|
|
||||||
const lineSize = 46;
|
|
||||||
|
|
||||||
const viewBox = computed(() => {
|
const viewBox = computed(() => {
|
||||||
switch (props.position) {
|
switch (props.position) {
|
||||||
case 'bottom':
|
case 'bottom':
|
||||||
case 'top':
|
case 'top':
|
||||||
return {
|
return {
|
||||||
width: plusSize,
|
width: props.plusSize,
|
||||||
height: lineSize + plusSize,
|
height: props.lineSize + props.plusSize,
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
return {
|
return {
|
||||||
width: lineSize + plusSize,
|
width: props.lineSize + props.plusSize,
|
||||||
height: plusSize,
|
height: props.plusSize,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const styles = computed(() => ({
|
||||||
|
width: `${viewBox.value.width}px`,
|
||||||
|
height: `${viewBox.value.height}px`,
|
||||||
|
}));
|
||||||
|
|
||||||
const linePosition = computed(() => {
|
const linePosition = computed(() => {
|
||||||
switch (props.position) {
|
switch (props.position) {
|
||||||
case 'top':
|
case 'top':
|
||||||
return [
|
return [
|
||||||
[viewBox.value.width / 2, viewBox.value.height - lineSize + 1],
|
[viewBox.value.width / 2, viewBox.value.height - props.lineSize + 1],
|
||||||
[viewBox.value.width / 2, viewBox.value.height],
|
[viewBox.value.width / 2, viewBox.value.height],
|
||||||
];
|
];
|
||||||
case 'bottom':
|
case 'bottom':
|
||||||
return [
|
return [
|
||||||
[viewBox.value.width / 2, 0],
|
[viewBox.value.width / 2, 0],
|
||||||
[viewBox.value.width / 2, lineSize + 1],
|
[viewBox.value.width / 2, props.lineSize + 1],
|
||||||
];
|
];
|
||||||
case 'left':
|
case 'left':
|
||||||
return [
|
return [
|
||||||
[viewBox.value.width - lineSize - 1, viewBox.value.height / 2],
|
[viewBox.value.width - props.lineSize - 1, viewBox.value.height / 2],
|
||||||
[viewBox.value.width, viewBox.value.height / 2],
|
[viewBox.value.width, viewBox.value.height / 2],
|
||||||
];
|
];
|
||||||
default:
|
default:
|
||||||
return [
|
return [
|
||||||
[0, viewBox.value.height / 2],
|
[0, viewBox.value.height / 2],
|
||||||
[lineSize + 1, viewBox.value.height / 2],
|
[props.lineSize + 1, viewBox.value.height / 2],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -67,13 +73,13 @@ const linePosition = computed(() => {
|
||||||
const plusPosition = computed(() => {
|
const plusPosition = computed(() => {
|
||||||
switch (props.position) {
|
switch (props.position) {
|
||||||
case 'bottom':
|
case 'bottom':
|
||||||
return [0, viewBox.value.height - plusSize];
|
return [0, viewBox.value.height - props.plusSize];
|
||||||
case 'top':
|
case 'top':
|
||||||
return [0, 0];
|
return [0, 0];
|
||||||
case 'left':
|
case 'left':
|
||||||
return [0, 0];
|
return [0, 0];
|
||||||
default:
|
default:
|
||||||
return [viewBox.value.width - plusSize, 0];
|
return [viewBox.value.width - props.plusSize, 0];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -83,7 +89,7 @@ function onClick(event: MouseEvent) {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<svg :class="classes" :viewBox="`0 0 ${viewBox.width} ${viewBox.height}`">
|
<svg :class="classes" :viewBox="`0 0 ${viewBox.width} ${viewBox.height}`" :style="styles">
|
||||||
<line
|
<line
|
||||||
:class="handleClasses"
|
:class="handleClasses"
|
||||||
:x1="linePosition[0][0]"
|
:x1="linePosition[0][0]"
|
||||||
|
@ -121,18 +127,6 @@ function onClick(event: MouseEvent) {
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
.wrapper {
|
.wrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
&.top,
|
|
||||||
&.bottom {
|
|
||||||
width: 24px;
|
|
||||||
height: 70px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.left,
|
|
||||||
&.right {
|
|
||||||
width: 70px;
|
|
||||||
height: 24px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.plus {
|
.plus {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
exports[`CanvasHandleDiamond > should render with default props 1`] = `
|
exports[`CanvasHandleDiamond > should render with default props 1`] = `
|
||||||
"<svg class="wrapper right" viewBox="0 0 70 24">
|
"<svg class="wrapper right" viewBox="0 0 70 24" style="width: 70px; height: 24px;">
|
||||||
<line class="" x1="0" y1="12" x2="47" y2="12" stroke="var(--color-foreground-xdark)" stroke-width="2"></line>
|
<line class="" x1="0" y1="12" x2="47" y2="12" stroke="var(--color-foreground-xdark)" stroke-width="2"></line>
|
||||||
<g class="plus clickable" transform="translate(46, 0)">
|
<g class="plus clickable" transform="translate(46, 0)">
|
||||||
<rect class="clickable" x="2" y="2" width="20" height="20" stroke="var(--color-foreground-xdark)" stroke-width="2" rx="4" fill="#ffffff"></rect>
|
<rect class="clickable" x="2" y="2" width="20" height="20" stroke="var(--color-foreground-xdark)" stroke-width="2" rx="4" fill="#ffffff"></rect>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
exports[`CanvasHandlePlus > should render with default props 1`] = `
|
exports[`CanvasHandlePlus > should render with default props 1`] = `
|
||||||
"<svg class="wrapper right" viewBox="0 0 70 24">
|
"<svg class="wrapper right" viewBox="0 0 70 24" style="width: 70px; height: 24px;">
|
||||||
<line class="" x1="0" y1="12" x2="47" y2="12" stroke="var(--color-foreground-xdark)" stroke-width="2"></line>
|
<line class="" x1="0" y1="12" x2="47" y2="12" stroke="var(--color-foreground-xdark)" stroke-width="2"></line>
|
||||||
<g class="plus clickable" transform="translate(46, 0)">
|
<g class="plus clickable" transform="translate(46, 0)">
|
||||||
<rect class="clickable" x="2" y="2" width="20" height="20" stroke="var(--color-foreground-xdark)" stroke-width="2" rx="4" fill="#ffffff"></rect>
|
<rect class="clickable" x="2" y="2" width="20" height="20" stroke="var(--color-foreground-xdark)" stroke-width="2" rx="4" fill="#ffffff"></rect>
|
||||||
|
|
|
@ -133,6 +133,12 @@ describe('useCanvasMapping', () => {
|
||||||
configurable: false,
|
configurable: false,
|
||||||
configuration: false,
|
configuration: false,
|
||||||
trigger: true,
|
trigger: true,
|
||||||
|
inputs: {
|
||||||
|
labelSize: 'small',
|
||||||
|
},
|
||||||
|
outputs: {
|
||||||
|
labelSize: 'small',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -264,6 +270,12 @@ describe('useCanvasMapping', () => {
|
||||||
configurable: false,
|
configurable: false,
|
||||||
configuration: false,
|
configuration: false,
|
||||||
trigger: true,
|
trigger: true,
|
||||||
|
inputs: {
|
||||||
|
labelSize: 'small',
|
||||||
|
},
|
||||||
|
outputs: {
|
||||||
|
labelSize: 'small',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,6 +16,7 @@ import type {
|
||||||
CanvasNodeAddNodesRender,
|
CanvasNodeAddNodesRender,
|
||||||
CanvasNodeData,
|
CanvasNodeData,
|
||||||
CanvasNodeDefaultRender,
|
CanvasNodeDefaultRender,
|
||||||
|
CanvasNodeDefaultRenderLabelSize,
|
||||||
CanvasNodeStickyNoteRender,
|
CanvasNodeStickyNoteRender,
|
||||||
} from '@/types';
|
} from '@/types';
|
||||||
import { CanvasConnectionMode, CanvasNodeRenderType } from '@/types';
|
import { CanvasConnectionMode, CanvasNodeRenderType } from '@/types';
|
||||||
|
@ -31,7 +32,7 @@ import type {
|
||||||
ITaskData,
|
ITaskData,
|
||||||
Workflow,
|
Workflow,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeHelpers } from 'n8n-workflow';
|
import { NodeConnectionType, NodeHelpers } from 'n8n-workflow';
|
||||||
import type { INodeUi } from '@/Interface';
|
import type { INodeUi } from '@/Interface';
|
||||||
import { CUSTOM_API_CALL_KEY, STICKY_NODE_TYPE, WAIT_TIME_UNLIMITED } from '@/constants';
|
import { CUSTOM_API_CALL_KEY, STICKY_NODE_TYPE, WAIT_TIME_UNLIMITED } from '@/constants';
|
||||||
import { sanitizeHtml } from '@/utils/htmlUtils';
|
import { sanitizeHtml } from '@/utils/htmlUtils';
|
||||||
|
@ -78,6 +79,12 @@ export function useCanvasMapping({
|
||||||
trigger: nodeTypesStore.isTriggerNode(node.type),
|
trigger: nodeTypesStore.isTriggerNode(node.type),
|
||||||
configuration: nodeTypesStore.isConfigNode(workflowObject.value, node, node.type),
|
configuration: nodeTypesStore.isConfigNode(workflowObject.value, node, node.type),
|
||||||
configurable: nodeTypesStore.isConfigurableNode(workflowObject.value, node, node.type),
|
configurable: nodeTypesStore.isConfigurableNode(workflowObject.value, node, node.type),
|
||||||
|
inputs: {
|
||||||
|
labelSize: nodeInputLabelSizeById.value[node.id],
|
||||||
|
},
|
||||||
|
outputs: {
|
||||||
|
labelSize: nodeOutputLabelSizeById.value[node.id],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -142,6 +149,48 @@ export function useCanvasMapping({
|
||||||
}, {}),
|
}, {}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
function getLabelSize(label: string = ''): number {
|
||||||
|
if (label.length <= 2) {
|
||||||
|
return 0;
|
||||||
|
} else if (label.length <= 6) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMaxNodePortsLabelSize(
|
||||||
|
ports: CanvasConnectionPort[],
|
||||||
|
): CanvasNodeDefaultRenderLabelSize {
|
||||||
|
const labelSizes: CanvasNodeDefaultRenderLabelSize[] = ['small', 'medium', 'large'];
|
||||||
|
const labelSizeIndexes = ports.reduce<number[]>(
|
||||||
|
(sizeAcc, input) => {
|
||||||
|
if (input.type === NodeConnectionType.Main) {
|
||||||
|
sizeAcc.push(getLabelSize(input.label ?? ''));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sizeAcc;
|
||||||
|
},
|
||||||
|
[0],
|
||||||
|
);
|
||||||
|
|
||||||
|
return labelSizes[Math.max(...labelSizeIndexes)];
|
||||||
|
}
|
||||||
|
|
||||||
|
const nodeInputLabelSizeById = computed(() =>
|
||||||
|
nodes.value.reduce<Record<string, CanvasNodeDefaultRenderLabelSize>>((acc, node) => {
|
||||||
|
acc[node.id] = getMaxNodePortsLabelSize(nodeInputsById.value[node.id]);
|
||||||
|
return acc;
|
||||||
|
}, {}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const nodeOutputLabelSizeById = computed(() =>
|
||||||
|
nodes.value.reduce<Record<string, CanvasNodeDefaultRenderLabelSize>>((acc, node) => {
|
||||||
|
acc[node.id] = getMaxNodePortsLabelSize(nodeOutputsById.value[node.id]);
|
||||||
|
return acc;
|
||||||
|
}, {}),
|
||||||
|
);
|
||||||
|
|
||||||
const nodeOutputsById = computed(() =>
|
const nodeOutputsById = computed(() =>
|
||||||
nodes.value.reduce<Record<string, CanvasConnectionPort[]>>((acc, node) => {
|
nodes.value.reduce<Record<string, CanvasConnectionPort[]>>((acc, node) => {
|
||||||
const nodeTypeDescription = nodeTypesStore.getNodeType(node.type, node.typeVersion);
|
const nodeTypeDescription = nodeTypesStore.getNodeType(node.type, node.typeVersion);
|
||||||
|
|
|
@ -44,12 +44,20 @@ export const enum CanvasNodeRenderType {
|
||||||
AddNodes = 'n8n-nodes-internal.addNodes',
|
AddNodes = 'n8n-nodes-internal.addNodes',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type CanvasNodeDefaultRenderLabelSize = 'small' | 'medium' | 'large';
|
||||||
|
|
||||||
export type CanvasNodeDefaultRender = {
|
export type CanvasNodeDefaultRender = {
|
||||||
type: CanvasNodeRenderType.Default;
|
type: CanvasNodeRenderType.Default;
|
||||||
options: Partial<{
|
options: Partial<{
|
||||||
configurable: boolean;
|
configurable: boolean;
|
||||||
configuration: boolean;
|
configuration: boolean;
|
||||||
trigger: boolean;
|
trigger: boolean;
|
||||||
|
inputs: {
|
||||||
|
labelSize: CanvasNodeDefaultRenderLabelSize;
|
||||||
|
};
|
||||||
|
outputs: {
|
||||||
|
labelSize: CanvasNodeDefaultRenderLabelSize;
|
||||||
|
};
|
||||||
}>;
|
}>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue