2024-07-12 06:03:23 -07:00
|
|
|
<script lang="ts" setup>
|
2023-11-07 01:06:08 -08:00
|
|
|
import { useStorage } from '@/composables/useStorage';
|
2022-09-22 08:41:15 -07:00
|
|
|
|
2023-04-24 03:18:24 -07:00
|
|
|
import type { INodeTypeDescription } from 'n8n-workflow';
|
2022-05-23 08:56:15 -07:00
|
|
|
import PanelDragButton from './PanelDragButton.vue';
|
|
|
|
|
2022-09-22 08:41:15 -07:00
|
|
|
import { LOCAL_STORAGE_MAIN_PANEL_RELATIVE_WIDTH, MAIN_NODE_PANEL_WIDTH } from '@/constants';
|
2023-05-05 01:41:54 -07:00
|
|
|
import { useNDVStore } from '@/stores/ndv.store';
|
2023-10-02 08:33:43 -07:00
|
|
|
import { ndvEventBus } from '@/event-bus';
|
2023-11-28 07:47:28 -08:00
|
|
|
import NDVFloatingNodes from '@/components/NDVFloatingNodes.vue';
|
2024-01-08 04:00:49 -08:00
|
|
|
import { useDebounce } from '@/composables/useDebounce';
|
2024-07-02 11:55:19 -07:00
|
|
|
import type { XYPosition } from '@/Interface';
|
2024-07-12 06:03:23 -07:00
|
|
|
import { ref, onMounted, onBeforeUnmount, computed, watch } from 'vue';
|
2022-09-22 08:41:15 -07:00
|
|
|
|
2022-05-23 08:56:15 -07:00
|
|
|
const SIDE_MARGIN = 24;
|
2022-09-22 08:41:15 -07:00
|
|
|
const SIDE_PANELS_MARGIN = 80;
|
|
|
|
const MIN_PANEL_WIDTH = 280;
|
|
|
|
const PANEL_WIDTH = 320;
|
|
|
|
const PANEL_WIDTH_LARGE = 420;
|
2024-07-12 06:03:23 -07:00
|
|
|
const MIN_WINDOW_WIDTH = 2 * (SIDE_MARGIN + SIDE_PANELS_MARGIN) + MIN_PANEL_WIDTH;
|
2022-09-22 08:41:15 -07:00
|
|
|
|
|
|
|
const initialMainPanelWidth: { [key: string]: number } = {
|
|
|
|
regular: MAIN_NODE_PANEL_WIDTH,
|
|
|
|
dragless: MAIN_NODE_PANEL_WIDTH,
|
|
|
|
unknown: MAIN_NODE_PANEL_WIDTH,
|
|
|
|
inputless: MAIN_NODE_PANEL_WIDTH,
|
|
|
|
wide: MAIN_NODE_PANEL_WIDTH * 2,
|
|
|
|
};
|
2022-05-23 08:56:15 -07:00
|
|
|
|
2024-07-12 06:03:23 -07:00
|
|
|
interface Props {
|
|
|
|
isDraggable: boolean;
|
|
|
|
hideInputAndOutput: boolean;
|
|
|
|
nodeType: INodeTypeDescription | null;
|
|
|
|
}
|
|
|
|
|
|
|
|
const { callDebounced } = useDebounce();
|
|
|
|
const ndvStore = useNDVStore();
|
|
|
|
|
|
|
|
const props = defineProps<Props>();
|
|
|
|
|
|
|
|
const windowWidth = ref<number>(1);
|
|
|
|
const isDragging = ref<boolean>(false);
|
|
|
|
const initialized = ref<boolean>(false);
|
|
|
|
|
|
|
|
const emit = defineEmits<{
|
|
|
|
init: [{ position: number }];
|
|
|
|
dragstart: [{ position: number }];
|
|
|
|
dragend: [{ position: number; windowWidth: number }];
|
|
|
|
switchSelectedNode: [string];
|
|
|
|
close: [];
|
|
|
|
}>();
|
|
|
|
|
|
|
|
const slots = defineSlots<{
|
|
|
|
input: unknown;
|
|
|
|
output: unknown;
|
|
|
|
main: unknown;
|
|
|
|
}>();
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
setTotalWidth();
|
|
|
|
|
|
|
|
/*
|
|
|
|
Only set(or restore) initial position if `mainPanelDimensions`
|
|
|
|
is at the default state({relativeLeft:1, relativeRight: 1, relativeWidth: 1}) to make sure we use store values if they are set
|
|
|
|
*/
|
|
|
|
if (
|
|
|
|
mainPanelDimensions.value.relativeLeft === 1 &&
|
|
|
|
mainPanelDimensions.value.relativeRight === 1
|
|
|
|
) {
|
|
|
|
setMainPanelWidth();
|
|
|
|
setPositions(getInitialLeftPosition(mainPanelDimensions.value.relativeWidth));
|
|
|
|
restorePositionData();
|
|
|
|
}
|
|
|
|
|
|
|
|
window.addEventListener('resize', setTotalWidth);
|
|
|
|
emit('init', { position: mainPanelDimensions.value.relativeLeft });
|
|
|
|
setTimeout(() => {
|
|
|
|
initialized.value = true;
|
|
|
|
}, 0);
|
|
|
|
|
|
|
|
ndvEventBus.on('setPositionByName', setPositionByName);
|
|
|
|
});
|
|
|
|
|
|
|
|
onBeforeUnmount(() => {
|
|
|
|
window.removeEventListener('resize', setTotalWidth);
|
|
|
|
ndvEventBus.off('setPositionByName', setPositionByName);
|
|
|
|
});
|
|
|
|
|
|
|
|
watch(windowWidth, (width) => {
|
|
|
|
const minRelativeWidth = pxToRelativeWidth(MIN_PANEL_WIDTH);
|
|
|
|
const isBelowMinWidthMainPanel = mainPanelDimensions.value.relativeWidth < minRelativeWidth;
|
2024-01-08 04:00:49 -08:00
|
|
|
|
2024-07-12 06:03:23 -07:00
|
|
|
// Prevent the panel resizing below MIN_PANEL_WIDTH whhile maintaing position
|
|
|
|
if (isBelowMinWidthMainPanel) {
|
|
|
|
setMainPanelWidth(minRelativeWidth);
|
|
|
|
}
|
|
|
|
|
|
|
|
const isBelowMinLeft = minimumLeftPosition.value > mainPanelDimensions.value.relativeLeft;
|
|
|
|
const isMaxRight = maximumRightPosition.value > mainPanelDimensions.value.relativeRight;
|
|
|
|
|
|
|
|
// When user is resizing from non-supported view(sub ~488px) we need to refit the panels
|
|
|
|
if (width > MIN_WINDOW_WIDTH && isBelowMinLeft && isMaxRight) {
|
|
|
|
setMainPanelWidth(minRelativeWidth);
|
|
|
|
setPositions(getInitialLeftPosition(mainPanelDimensions.value.relativeWidth));
|
|
|
|
}
|
|
|
|
|
|
|
|
setPositions(mainPanelDimensions.value.relativeLeft);
|
|
|
|
});
|
|
|
|
|
|
|
|
const currentNodePaneType = computed((): string => {
|
|
|
|
if (!hasInputSlot.value) return 'inputless';
|
|
|
|
if (!props.isDraggable) return 'dragless';
|
|
|
|
if (props.nodeType === null) return 'unknown';
|
|
|
|
return props.nodeType.parameterPane ?? 'regular';
|
|
|
|
});
|
|
|
|
|
|
|
|
const mainPanelDimensions = computed(
|
|
|
|
(): {
|
|
|
|
relativeWidth: number;
|
|
|
|
relativeLeft: number;
|
|
|
|
relativeRight: number;
|
|
|
|
} => {
|
|
|
|
return ndvStore.getMainPanelDimensions(currentNodePaneType.value);
|
2024-01-08 04:00:49 -08:00
|
|
|
},
|
2024-07-12 06:03:23 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
const calculatedPositions = computed(
|
|
|
|
(): { inputPanelRelativeRight: number; outputPanelRelativeLeft: number } => {
|
|
|
|
const hasInput = slots.input !== undefined;
|
|
|
|
const outputPanelRelativeLeft =
|
|
|
|
mainPanelDimensions.value.relativeLeft + mainPanelDimensions.value.relativeWidth;
|
|
|
|
|
|
|
|
const inputPanelRelativeRight = hasInput
|
|
|
|
? 1 - outputPanelRelativeLeft + mainPanelDimensions.value.relativeWidth
|
|
|
|
: 1 - pxToRelativeWidth(SIDE_MARGIN);
|
|
|
|
|
2022-05-23 08:56:15 -07:00
|
|
|
return {
|
2024-07-12 06:03:23 -07:00
|
|
|
inputPanelRelativeRight,
|
|
|
|
outputPanelRelativeLeft,
|
2022-05-23 08:56:15 -07:00
|
|
|
};
|
|
|
|
},
|
2024-07-12 06:03:23 -07:00
|
|
|
);
|
2022-05-23 08:56:15 -07:00
|
|
|
|
2024-07-12 06:03:23 -07:00
|
|
|
const outputPanelRelativeTranslate = computed((): number => {
|
|
|
|
const panelMinLeft = 1 - pxToRelativeWidth(MIN_PANEL_WIDTH + SIDE_MARGIN);
|
|
|
|
const currentRelativeLeftDelta = calculatedPositions.value.outputPanelRelativeLeft - panelMinLeft;
|
|
|
|
return currentRelativeLeftDelta > 0 ? currentRelativeLeftDelta : 0;
|
|
|
|
});
|
2022-09-22 08:41:15 -07:00
|
|
|
|
2024-07-12 06:03:23 -07:00
|
|
|
const supportedResizeDirections = computed((): string[] => {
|
|
|
|
const supportedDirections = ['right'];
|
2022-05-23 08:56:15 -07:00
|
|
|
|
2024-07-12 06:03:23 -07:00
|
|
|
if (props.isDraggable) supportedDirections.push('left');
|
|
|
|
return supportedDirections;
|
|
|
|
});
|
2022-09-22 08:41:15 -07:00
|
|
|
|
2024-07-12 06:03:23 -07:00
|
|
|
const hasInputSlot = computed((): boolean => {
|
|
|
|
return slots.input !== undefined;
|
|
|
|
});
|
2022-09-22 08:41:15 -07:00
|
|
|
|
2024-07-12 06:03:23 -07:00
|
|
|
const inputPanelMargin = computed(() => pxToRelativeWidth(SIDE_PANELS_MARGIN));
|
2022-09-22 08:41:15 -07:00
|
|
|
|
2024-07-12 06:03:23 -07:00
|
|
|
const minimumLeftPosition = computed((): number => {
|
|
|
|
if (windowWidth.value < MIN_WINDOW_WIDTH) return pxToRelativeWidth(1);
|
2022-09-22 08:41:15 -07:00
|
|
|
|
2024-07-12 06:03:23 -07:00
|
|
|
if (!hasInputSlot.value) return pxToRelativeWidth(SIDE_MARGIN);
|
|
|
|
return pxToRelativeWidth(SIDE_MARGIN + 20) + inputPanelMargin.value;
|
|
|
|
});
|
|
|
|
|
|
|
|
const maximumRightPosition = computed((): number => {
|
|
|
|
if (windowWidth.value < MIN_WINDOW_WIDTH) return pxToRelativeWidth(1);
|
|
|
|
|
|
|
|
return pxToRelativeWidth(SIDE_MARGIN + 20) + inputPanelMargin.value;
|
|
|
|
});
|
|
|
|
|
|
|
|
const canMoveLeft = computed((): boolean => {
|
|
|
|
return mainPanelDimensions.value.relativeLeft > minimumLeftPosition.value;
|
|
|
|
});
|
|
|
|
|
|
|
|
const canMoveRight = computed((): boolean => {
|
|
|
|
return mainPanelDimensions.value.relativeRight > maximumRightPosition.value;
|
|
|
|
});
|
|
|
|
|
|
|
|
const mainPanelStyles = computed((): { left: string; right: string } => {
|
|
|
|
return {
|
|
|
|
left: `${relativeWidthToPx(mainPanelDimensions.value.relativeLeft)}px`,
|
|
|
|
right: `${relativeWidthToPx(mainPanelDimensions.value.relativeRight)}px`,
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
const inputPanelStyles = computed((): { right: string } => {
|
|
|
|
return {
|
|
|
|
right: `${relativeWidthToPx(calculatedPositions.value.inputPanelRelativeRight)}px`,
|
|
|
|
};
|
2022-05-23 08:56:15 -07:00
|
|
|
});
|
2024-07-12 06:03:23 -07:00
|
|
|
|
|
|
|
const outputPanelStyles = computed((): { left: string; transform: string } => {
|
|
|
|
return {
|
|
|
|
left: `${relativeWidthToPx(calculatedPositions.value.outputPanelRelativeLeft)}px`,
|
|
|
|
transform: `translateX(-${relativeWidthToPx(outputPanelRelativeTranslate.value)}px)`,
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
const hasDoubleWidth = computed((): boolean => {
|
|
|
|
return props.nodeType?.parameterPane === 'wide';
|
|
|
|
});
|
|
|
|
|
|
|
|
const fixedPanelWidth = computed((): number => {
|
|
|
|
const multiplier = hasDoubleWidth.value ? 2 : 1;
|
|
|
|
|
|
|
|
if (windowWidth.value > 1700) {
|
|
|
|
return PANEL_WIDTH_LARGE * multiplier;
|
|
|
|
}
|
|
|
|
|
|
|
|
return PANEL_WIDTH * multiplier;
|
|
|
|
});
|
|
|
|
|
|
|
|
const onSwitchSelectedNode = (node: string) => emit('switchSelectedNode', node);
|
|
|
|
|
|
|
|
function getInitialLeftPosition(width: number): number {
|
|
|
|
if (currentNodePaneType.value === 'dragless')
|
|
|
|
return pxToRelativeWidth(SIDE_MARGIN + 1 + fixedPanelWidth.value);
|
|
|
|
|
|
|
|
return hasInputSlot.value ? 0.5 - width / 2 : minimumLeftPosition.value;
|
|
|
|
}
|
|
|
|
|
|
|
|
function setMainPanelWidth(relativeWidth?: number): void {
|
|
|
|
const mainPanelRelativeWidth =
|
|
|
|
relativeWidth || pxToRelativeWidth(initialMainPanelWidth[currentNodePaneType.value]);
|
|
|
|
|
|
|
|
ndvStore.setMainPanelDimensions({
|
|
|
|
panelType: currentNodePaneType.value,
|
|
|
|
dimensions: {
|
|
|
|
relativeWidth: mainPanelRelativeWidth,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function setPositions(relativeLeft: number): void {
|
|
|
|
const mainPanelRelativeLeft =
|
|
|
|
relativeLeft || 1 - calculatedPositions.value.inputPanelRelativeRight;
|
|
|
|
const mainPanelRelativeRight =
|
|
|
|
1 - mainPanelRelativeLeft - mainPanelDimensions.value.relativeWidth;
|
|
|
|
|
|
|
|
const isMaxRight = maximumRightPosition.value > mainPanelRelativeRight;
|
|
|
|
const isMinLeft = minimumLeftPosition.value > mainPanelRelativeLeft;
|
|
|
|
const isInputless = currentNodePaneType.value === 'inputless';
|
|
|
|
|
|
|
|
if (isMinLeft) {
|
|
|
|
ndvStore.setMainPanelDimensions({
|
|
|
|
panelType: currentNodePaneType.value,
|
|
|
|
dimensions: {
|
|
|
|
relativeLeft: minimumLeftPosition.value,
|
|
|
|
relativeRight: 1 - mainPanelDimensions.value.relativeWidth - minimumLeftPosition.value,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isMaxRight) {
|
|
|
|
ndvStore.setMainPanelDimensions({
|
|
|
|
panelType: currentNodePaneType.value,
|
|
|
|
dimensions: {
|
|
|
|
relativeLeft: 1 - mainPanelDimensions.value.relativeWidth - maximumRightPosition.value,
|
|
|
|
relativeRight: maximumRightPosition.value,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ndvStore.setMainPanelDimensions({
|
|
|
|
panelType: currentNodePaneType.value,
|
|
|
|
dimensions: {
|
|
|
|
relativeLeft: isInputless ? minimumLeftPosition.value : mainPanelRelativeLeft,
|
|
|
|
relativeRight: mainPanelRelativeRight,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function setPositionByName(position: 'minLeft' | 'maxRight' | 'initial') {
|
|
|
|
const positionByName: Record<string, number> = {
|
|
|
|
minLeft: minimumLeftPosition.value,
|
|
|
|
maxRight: maximumRightPosition.value,
|
|
|
|
initial: getInitialLeftPosition(mainPanelDimensions.value.relativeWidth),
|
|
|
|
};
|
|
|
|
|
|
|
|
setPositions(positionByName[position]);
|
|
|
|
}
|
|
|
|
|
|
|
|
function pxToRelativeWidth(px: number): number {
|
|
|
|
return px / windowWidth.value;
|
|
|
|
}
|
|
|
|
|
|
|
|
function relativeWidthToPx(relativeWidth: number) {
|
|
|
|
return relativeWidth * windowWidth.value;
|
|
|
|
}
|
|
|
|
|
|
|
|
function onResizeStart() {
|
|
|
|
setTotalWidth();
|
|
|
|
}
|
|
|
|
|
|
|
|
function onResizeEnd() {
|
|
|
|
storePositionData();
|
|
|
|
}
|
|
|
|
|
|
|
|
function onResizeDebounced(data: { direction: string; x: number; width: number }) {
|
|
|
|
if (initialized.value) {
|
|
|
|
void callDebounced(onResize, { debounceTime: 10, trailing: true }, data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function onResize({ direction, x, width }: { direction: string; x: number; width: number }) {
|
|
|
|
const relativeDistance = pxToRelativeWidth(x);
|
|
|
|
const relativeWidth = pxToRelativeWidth(width);
|
|
|
|
|
|
|
|
if (direction === 'left' && relativeDistance <= minimumLeftPosition.value) return;
|
|
|
|
if (direction === 'right' && 1 - relativeDistance <= maximumRightPosition.value) return;
|
|
|
|
if (width <= MIN_PANEL_WIDTH) return;
|
|
|
|
|
|
|
|
setMainPanelWidth(relativeWidth);
|
|
|
|
setPositions(direction === 'left' ? relativeDistance : mainPanelDimensions.value.relativeLeft);
|
|
|
|
}
|
|
|
|
|
|
|
|
function restorePositionData() {
|
|
|
|
const storedPanelWidthData = useStorage(
|
|
|
|
`${LOCAL_STORAGE_MAIN_PANEL_RELATIVE_WIDTH}_${currentNodePaneType.value}`,
|
|
|
|
).value;
|
|
|
|
|
|
|
|
if (storedPanelWidthData) {
|
|
|
|
const parsedWidth = parseFloat(storedPanelWidthData);
|
|
|
|
setMainPanelWidth(parsedWidth);
|
|
|
|
const initialPosition = getInitialLeftPosition(parsedWidth);
|
|
|
|
|
|
|
|
setPositions(initialPosition);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
function storePositionData() {
|
|
|
|
useStorage(`${LOCAL_STORAGE_MAIN_PANEL_RELATIVE_WIDTH}_${currentNodePaneType.value}`).value =
|
|
|
|
mainPanelDimensions.value.relativeWidth.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
function onDragStart() {
|
|
|
|
isDragging.value = true;
|
|
|
|
emit('dragstart', { position: mainPanelDimensions.value.relativeLeft });
|
|
|
|
}
|
|
|
|
|
|
|
|
function onDrag(position: XYPosition) {
|
|
|
|
const relativeLeft = pxToRelativeWidth(position[0]) - mainPanelDimensions.value.relativeWidth / 2;
|
|
|
|
|
|
|
|
setPositions(relativeLeft);
|
|
|
|
}
|
|
|
|
|
|
|
|
function onDragEnd() {
|
|
|
|
setTimeout(() => {
|
|
|
|
isDragging.value = false;
|
|
|
|
emit('dragend', {
|
|
|
|
windowWidth: windowWidth.value,
|
|
|
|
position: mainPanelDimensions.value.relativeLeft,
|
|
|
|
});
|
|
|
|
}, 0);
|
|
|
|
storePositionData();
|
|
|
|
}
|
|
|
|
|
|
|
|
function setTotalWidth() {
|
|
|
|
windowWidth.value = window.innerWidth;
|
|
|
|
}
|
2022-05-23 08:56:15 -07:00
|
|
|
</script>
|
|
|
|
|
2024-07-12 06:03:23 -07:00
|
|
|
<template>
|
|
|
|
<div>
|
|
|
|
<NDVFloatingNodes
|
|
|
|
v-if="ndvStore.activeNode"
|
|
|
|
:root-node="ndvStore.activeNode"
|
|
|
|
@switch-selected-node="onSwitchSelectedNode"
|
|
|
|
/>
|
|
|
|
<div v-if="!hideInputAndOutput" :class="$style.inputPanel" :style="inputPanelStyles">
|
|
|
|
<slot name="input"></slot>
|
|
|
|
</div>
|
|
|
|
<div v-if="!hideInputAndOutput" :class="$style.outputPanel" :style="outputPanelStyles">
|
|
|
|
<slot name="output"></slot>
|
|
|
|
</div>
|
|
|
|
<div :class="$style.mainPanel" :style="mainPanelStyles">
|
|
|
|
<n8n-resize-wrapper
|
|
|
|
:is-resizing-enabled="currentNodePaneType !== 'unknown'"
|
|
|
|
:width="relativeWidthToPx(mainPanelDimensions.relativeWidth)"
|
|
|
|
:min-width="MIN_PANEL_WIDTH"
|
|
|
|
:grid-size="20"
|
|
|
|
:supported-directions="supportedResizeDirections"
|
|
|
|
@resize="onResizeDebounced"
|
|
|
|
@resizestart="onResizeStart"
|
|
|
|
@resizeend="onResizeEnd"
|
|
|
|
>
|
|
|
|
<div :class="$style.dragButtonContainer">
|
|
|
|
<PanelDragButton
|
|
|
|
v-if="!hideInputAndOutput && isDraggable"
|
|
|
|
:class="{ [$style.draggable]: true, [$style.visible]: isDragging }"
|
|
|
|
:can-move-left="canMoveLeft"
|
|
|
|
:can-move-right="canMoveRight"
|
|
|
|
@dragstart="onDragStart"
|
|
|
|
@drag="onDrag"
|
|
|
|
@dragend="onDragEnd"
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
<div :class="{ [$style.mainPanelInner]: true, [$style.dragging]: isDragging }">
|
|
|
|
<slot name="main" />
|
|
|
|
</div>
|
|
|
|
</n8n-resize-wrapper>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
2022-05-23 08:56:15 -07:00
|
|
|
<style lang="scss" module>
|
|
|
|
.dataPanel {
|
|
|
|
position: absolute;
|
|
|
|
height: calc(100% - 2 * var(--spacing-l));
|
|
|
|
position: absolute;
|
|
|
|
top: var(--spacing-l);
|
|
|
|
z-index: 0;
|
2022-09-22 08:41:15 -07:00
|
|
|
min-width: 280px;
|
2022-05-23 08:56:15 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
.inputPanel {
|
|
|
|
composes: dataPanel;
|
|
|
|
left: var(--spacing-l);
|
|
|
|
|
|
|
|
> * {
|
|
|
|
border-radius: var(--border-radius-large) 0 0 var(--border-radius-large);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.outputPanel {
|
|
|
|
composes: dataPanel;
|
|
|
|
right: var(--spacing-l);
|
|
|
|
|
|
|
|
> * {
|
|
|
|
border-radius: 0 var(--border-radius-large) var(--border-radius-large) 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.mainPanel {
|
|
|
|
position: absolute;
|
|
|
|
height: 100%;
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
.draggable {
|
|
|
|
visibility: visible;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-22 08:41:15 -07:00
|
|
|
.mainPanelInner {
|
|
|
|
height: 100%;
|
|
|
|
border: var(--border-base);
|
|
|
|
border-radius: var(--border-radius-large);
|
|
|
|
box-shadow: 0 4px 16px rgb(50 61 85 / 10%);
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
|
|
&.dragging {
|
|
|
|
border-color: var(--color-primary);
|
|
|
|
box-shadow: 0px 6px 16px rgba(255, 74, 51, 0.15);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-23 08:56:15 -07:00
|
|
|
.draggable {
|
|
|
|
visibility: hidden;
|
|
|
|
}
|
|
|
|
|
2023-04-25 07:57:21 -07:00
|
|
|
.double-width {
|
|
|
|
left: 90%;
|
|
|
|
}
|
|
|
|
|
2022-05-23 08:56:15 -07:00
|
|
|
.dragButtonContainer {
|
|
|
|
position: absolute;
|
|
|
|
top: -12px;
|
2022-09-22 08:41:15 -07:00
|
|
|
width: 100%;
|
2022-05-23 08:56:15 -07:00
|
|
|
height: 12px;
|
2022-09-22 08:41:15 -07:00
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
pointer-events: none;
|
2022-05-23 08:56:15 -07:00
|
|
|
|
2022-09-22 08:41:15 -07:00
|
|
|
.draggable {
|
|
|
|
pointer-events: all;
|
|
|
|
}
|
2022-05-23 08:56:15 -07:00
|
|
|
&:hover .draggable {
|
|
|
|
visibility: visible;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.visible {
|
|
|
|
visibility: visible;
|
|
|
|
}
|
|
|
|
</style>
|