Canvas CSS update
This commit is contained in:
parent
c694d28982
commit
2a8abb4796
8
app.vue
8
app.vue
|
|
@ -1,14 +1,9 @@
|
||||||
<style>
|
<style>
|
||||||
/* width */
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 12px;
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Track */
|
|
||||||
::-webkit-scrollbar-track {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle */
|
|
||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
@apply bg-light-40;
|
@apply bg-light-40;
|
||||||
@apply dark:bg-dark-40;
|
@apply dark:bg-dark-40;
|
||||||
|
|
@ -19,7 +14,6 @@
|
||||||
@apply bg-clip-padding;
|
@apply bg-clip-padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle on hover */
|
|
||||||
::-webkit-scrollbar-thumb:hover {
|
::-webkit-scrollbar-thumb:hover {
|
||||||
@apply bg-light-50;
|
@apply bg-light-50;
|
||||||
@apply dark:bg-dark-50;
|
@apply dark:bg-dark-50;
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@ const isDark = computed({
|
||||||
</span>
|
</span>
|
||||||
<div class="
|
<div class="
|
||||||
before:absolute before:top-0 before:left-0 before:right-0 before:bottom-0 before:opacity-0 before:block before:z-10
|
before:absolute before:top-0 before:left-0 before:right-0 before:bottom-0 before:opacity-0 before:block before:z-10
|
||||||
after:transition-all after:w-4 after:h-4 after:border after:border-light-30 dark:after:border-dark-30 after:block after:m-[3px] after:top-[-1px] after:pointer-events-none after:absolute after:left-0 after:bg-light-0 after:rounded-full after:translate-x-[1px] dark:after:translate-x-[26px]
|
after:transition-all after:w-4 after:h-4 after:border after:border-light-30 dark:after:border-dark-30 after:block after:m-[3px] after:top-[-1px] after:pointer-events-none after:absolute after:left-0 after:bg-light-0 after:translate-x-[1px] dark:after:translate-x-[26px]
|
||||||
inline-block relative cursor-pointer w-[50px] h-[22px] select-none rounded-full border border-light-30 dark:border-dark-30 bg-light-0 dark:bg-dark-30 dark:hover:border-dark-35" @click="isDark = !isDark"></div>
|
inline-block relative cursor-pointer w-[50px] h-[22px] select-none border border-light-35 dark:border-dark-35 bg-light-0 dark:bg-dark-30 dark:hover:border-dark-35" @click="isDark = !isDark"></div>
|
||||||
<span class="block dark:hidden absolute top-[3px] left-[22px] z-[1] px-[5px]">
|
<span class="block dark:hidden absolute top-[3px] left-[22px] z-[1] px-[5px]">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4 stroke-light-100 dark:stroke-dark-100 ">
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4 stroke-light-100 dark:stroke-dark-100 ">
|
||||||
<circle cx="12" cy="12" r="4"></circle>
|
<circle cx="12" cy="12" r="4"></circle>
|
||||||
|
|
|
||||||
|
|
@ -1,43 +1,33 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import type { CanvasColor } from "~/types/canvas";
|
||||||
|
|
||||||
|
type Direction = 'bottom' | 'top' | 'left' | 'right';
|
||||||
interface Props
|
interface Props
|
||||||
{
|
{
|
||||||
path: {
|
path: {
|
||||||
path: string;
|
path: string;
|
||||||
from: { x: number; y: number };
|
from: { x: number; y: number };
|
||||||
to: { x: number; y: number };
|
to: { x: number; y: number };
|
||||||
side: 'bottom' | 'top' | 'left' | 'right';
|
side: Direction;
|
||||||
};
|
};
|
||||||
color?: string;
|
color?: CanvasColor;
|
||||||
label?: string;
|
label?: string;
|
||||||
}
|
}
|
||||||
const props = defineProps<Props>();
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
const rotation = {
|
const rotation: Record<Direction, string> = {
|
||||||
top: "180",
|
top: "180",
|
||||||
bottom: "0",
|
bottom: "0",
|
||||||
left: "90",
|
left: "90",
|
||||||
right: "270"
|
right: "270"
|
||||||
};
|
};
|
||||||
|
|
||||||
function hexToRgb(hex: string): string {
|
|
||||||
return `${parseInt(hex.substring(1, 3), 16)}, ${parseInt(hex.substring(3, 5), 16)}, ${parseInt(hex.substring(5, 7), 16)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const classes: any = { 'is-themed': props.color !== undefined, 'mod-canvas-color-custom': (props?.color?.startsWith('#') ?? false) };
|
|
||||||
|
|
||||||
if (props.color !== undefined) {
|
|
||||||
if (!props.color.startsWith('#'))
|
|
||||||
classes['mod-canvas-color-' + props.color] = true;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<g :class="classes"
|
<g>
|
||||||
:style="{ '--canvas-color': props?.color?.startsWith('#') ? hexToRgb(props.color) : undefined }">
|
<path :style="`stroke-linecap: butt; stroke-width: calc(3px * var(--zoom-multiplier)); --canvas-color: ${color?.hex}`" :class="(color?.class ?? undefined) ?? ((color && color?.hex !== undefined) ? 'stroke-[var(--canvas-color)]' : 'stroke-light-40 dark:stroke-dark-40')" class="fill-none stroke-[4px]" :d="path.path"></path>
|
||||||
<path class="canvas-display-path" :d="props.path.path"></path>
|
|
||||||
</g>
|
</g>
|
||||||
<g :class="classes"
|
<g :style="`transform: translate(${path.to.x}px, ${path.to.y}px) scale(var(--zoom-multiplier)) rotate(${rotation[path.side]}deg); --canvas-color: ${color?.hex}`">
|
||||||
:style="{ '--canvas-color': props?.color?.startsWith('#') ? hexToRgb(props.color) : undefined, transform: `translate(${props.path.to.x}px, ${props.path.to.y}px) rotate(${rotation[props.path.side]}deg)` }">
|
<polygon :class="(color?.class ?? undefined) ?? ((color && color?.hex !== undefined) ? 'fill-[var(--canvas-color)]' : 'fill-light-40 dark:fill-dark-40')" points="0,0 6.5,10.4 -6.5,10.4"></polygon>
|
||||||
<polygon class="canvas-path-end" points="0,0 6.5,10.4 -6.5,10.4"></polygon>
|
|
||||||
</g>
|
</g>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -25,35 +25,20 @@ function darken(rgb: string): boolean
|
||||||
|
|
||||||
const props = defineProps<Props>();
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
const classes: Record<string, boolean> = { 'canvas-node-group': props.node.type === 'group', 'is-themed': props.node.color !== undefined, 'mod-canvas-color-custom': (props.node?.color?.startsWith('#') ?? false) };
|
|
||||||
const size = Math.max(props.node.width, props.node.height);
|
const size = Math.max(props.node.width, props.node.height);
|
||||||
|
|
||||||
if(props.node.color !== undefined)
|
|
||||||
{
|
|
||||||
if (!props.node.color.startsWith('#'))
|
|
||||||
classes['mod-canvas-color-' + props.node.color] = true;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="canvas-node" :class="classes"
|
<div class="absolute" :style="{transform: `translate(${node.x}px, ${node.y}px)`, width: `${node.width}px`, height: `${node.height}px`}">
|
||||||
:style="{transform: `translate(${node.x}px, ${node.y}px)`, width: `${node.width}px`, height: `${node.height}px`, '--canvas-node-width': `${node.width}px`, '--canvas-node-height': `${node.height}px`, '--canvas-color': node?.color?.startsWith('#') ? hexToRgb(node.color) : undefined}">
|
<div :class="{'z-0': node.type === 'group', 'z-[2]': node.type !== 'group'}" class="border-2 border-light-40 dark:border-dark-40 bg-light-20 dark:bg-dark-20 overflow-hidden contain-strict w-full h-full py-2 px-4 flex">
|
||||||
<div class="canvas-node-container">
|
|
||||||
<template v-if="node.type === 'group' || zoom > Math.min(0.38, 1000 / size)">
|
<template v-if="node.type === 'group' || zoom > Math.min(0.38, 1000 / size)">
|
||||||
<div class="canvas-node-content markdown-embed">
|
<div v-if="node.text?.length > 0" class="flex items-center">
|
||||||
<div v-if="node.text?.length > 0" class="markdown-embed-content node-insert-event" style="">
|
<Markdown v-model="node.text" />
|
||||||
<div
|
|
||||||
class="markdown-preview-view markdown-rendered node-insert-event show-indentation-guide allow-fold-headings allow-fold-lists">
|
|
||||||
<div class="markdown-preview-sizer markdown-preview-section">
|
|
||||||
<Markdown v-model="node.text" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="canvas-node-placeholder">
|
<div class="flex flex-1 justify-center items-center bg-light-30 dark:bg-dark-30">
|
||||||
<div class="canvas-icon-placeholder">
|
<div class="">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||||
class="svg-icon lucide-align-left">
|
class="svg-icon lucide-align-left">
|
||||||
|
|
@ -65,8 +50,6 @@ if(props.node.color !== undefined)
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<ClientOnly><div v-if="node.type === 'group' && node.label !== undefined" class="canvas-group-label"
|
<div v-if="node.type === 'group' && node.label !== undefined" style="max-width: 100%; font-size: calc(16px * var(--zoom-multiplier))" class="origin-bottom-left tracking-wider truncate inline-block bg-light-40 dark:bg-dark-40 text-light-100 dark:text-dark-100 absolute bottom-[100%] mb-2 px-2 py-1 font-thin">{{ node.label }}</div>
|
||||||
:class="{ 'mod-foreground-dark': darken(getColor(props.node?.color ?? '')), 'mod-foreground-light': !darken(getColor(props.node?.color ?? ''))}">
|
|
||||||
{{ node.label }}</div></ClientOnly>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -47,7 +47,7 @@ const onResize = (event?: Event) => {
|
||||||
maxX.value = _maxX = _maxX + 32;
|
maxX.value = _maxX = _maxX + 32;
|
||||||
maxY.value = _maxY = _maxY + 32;
|
maxY.value = _maxY = _maxY + 32;
|
||||||
|
|
||||||
minZoom.value = Math.min((canvas.value?.clientWidth ?? 1920) / (_maxX - _minX), (canvas.value?.clientHeight ?? 1080) / (_maxY - _minY)) * 0.9;
|
minZoom.value = Math.min((canvas.value?.clientWidth ?? 1920) / (_maxX - _minX), (canvas.value?.clientHeight ?? 1080) / (_maxY - _minY), 0.01) * 0.9;
|
||||||
zoom.value = clamp(zoom.value, minZoom.value, 3);
|
zoom.value = clamp(zoom.value, minZoom.value, 3);
|
||||||
|
|
||||||
bbox.value = (canvas.value ?? document.getElementById('canvas'))?.getBoundingClientRect();
|
bbox.value = (canvas.value ?? document.getElementById('canvas'))?.getBoundingClientRect();
|
||||||
|
|
@ -216,7 +216,7 @@ function getCenter(n: { x: number, y: number }, i: { x: number, y: number }, r:
|
||||||
<Suspense>
|
<Suspense>
|
||||||
<template #default>
|
<template #default>
|
||||||
<div id="canvas" ref="canvas" @pointerdown="onPointerDown" @wheel.passive="onWheel" @touchstart.passive="onTouchStart"
|
<div id="canvas" ref="canvas" @pointerdown="onPointerDown" @wheel.passive="onWheel" @touchstart.passive="onTouchStart"
|
||||||
@dragstart.prevent="" class="relative overflow-hidden"
|
@dragstart.prevent="" class="absolute top-0 left-0 overflow-hidden w-full h-full"
|
||||||
:style="{ '--zoom-multiplier': (1 / Math.pow(zoom, 0.7)) }">
|
:style="{ '--zoom-multiplier': (1 / Math.pow(zoom, 0.7)) }">
|
||||||
<div class="border border-light-35 dark:border-dark-35 bg-light-10 dark:bg-dark-10 absolute top-2 left-2 z-[100] overflow-hidden">
|
<div class="border border-light-35 dark:border-dark-35 bg-light-10 dark:bg-dark-10 absolute top-2 left-2 z-[100] overflow-hidden">
|
||||||
<div @click="zoom = clamp(zoom * 1.1, minZoom, 3)" class="w-8 h-8 flex justify-center items-center p-2 hover:bg-light-30 dark:hover:bg-dark-30 cursor-pointer"
|
<div @click="zoom = clamp(zoom * 1.1, minZoom, 3)" class="w-8 h-8 flex justify-center items-center p-2 hover:bg-light-30 dark:hover:bg-dark-30 cursor-pointer"
|
||||||
|
|
@ -257,18 +257,18 @@ function getCenter(n: { x: number, y: number }, i: { x: number, y: number }, r:
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="canvas"
|
<div class="absolute top-0 left-0 w-full h-full origin-top pointer-events-none z-10"
|
||||||
:style="{transform: `translate(${centerX}px, ${centerY}px) scale(${zoom}) translate(${dispX}px, ${dispY}px)`}">
|
:style="{transform: `translate(${centerX}px, ${centerY}px) scale(${zoom}) translate(${dispX}px, ${dispY}px)`}">
|
||||||
<svg class="canvas-edges">
|
<svg class="absolute top-0 left-0 overflow-visible w-full h-full origin-top pointer-events-none z-[1]">
|
||||||
<CanvasEdge v-for="edge of props.canvas.edges" :key="edge.id"
|
<CanvasEdge v-for="edge of props.canvas.edges" :key="edge.id"
|
||||||
:path="path(getNode(edge.fromNode)!, edge.fromSide, getNode(edge.toNode)!, edge.toSide)"
|
:path="path(getNode(edge.fromNode)!, edge.fromSide, getNode(edge.toNode)!, edge.toSide)"
|
||||||
:color="edge.color" :label="edge.label" />
|
:color="edge.color" :label="edge.label" />
|
||||||
</svg>
|
</svg>
|
||||||
<CanvasNode v-for="node of props.canvas.nodes" :key="node.id" :node="node" :zoom="zoom" />
|
<CanvasNode v-for="node of props.canvas.nodes" :key="node.id" :node="node" :zoom="zoom" />
|
||||||
<template v-for="edge of props.canvas.edges">
|
<template v-for="edge of props.canvas.edges">
|
||||||
<div :key="edge.id" v-if="edge.label" class="canvas-path-label-wrapper"
|
<div :key="edge.id" v-if="edge.label" class="absolute z-10"
|
||||||
:style="{ transform: labelCenter(getNode(edge.fromNode)!, edge.fromSide, getNode(edge.toNode)!, edge.toSide) }">
|
:style="{ transform: labelCenter(getNode(edge.fromNode)!, edge.fromSide, getNode(edge.toNode)!, edge.toSide) }">
|
||||||
<div class="canvas-path-label">{{ edge.label }}</div>
|
<div class="relative bg-light-20 dark:bg-dark-20 border border-light-35 dark:border-dark-35 px-4 py-2 -translate-x-[50%] -translate-y-[50%]">{{ edge.label }}</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -278,4 +278,34 @@ function getCenter(n: { x: number, y: number }, i: { x: number, y: number }, r:
|
||||||
<div class="loading"></div>
|
<div class="loading"></div>
|
||||||
</template>
|
</template>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.useless
|
||||||
|
{
|
||||||
|
@apply fill-light-red;
|
||||||
|
@apply dark:fill-dark-red;
|
||||||
|
@apply stroke-light-red;
|
||||||
|
@apply dark:stroke-dark-red;
|
||||||
|
@apply fill-light-orange;
|
||||||
|
@apply dark:fill-dark-orange;
|
||||||
|
@apply stroke-light-orange;
|
||||||
|
@apply dark:stroke-dark-orange;
|
||||||
|
@apply fill-light-yellow;
|
||||||
|
@apply dark:fill-dark-yellow;
|
||||||
|
@apply stroke-light-yellow;
|
||||||
|
@apply dark:stroke-dark-yellow;
|
||||||
|
@apply fill-light-green;
|
||||||
|
@apply dark:fill-dark-green;
|
||||||
|
@apply stroke-light-green;
|
||||||
|
@apply dark:stroke-dark-green;
|
||||||
|
@apply fill-light-cyan;
|
||||||
|
@apply dark:fill-dark-cyan;
|
||||||
|
@apply stroke-light-cyan;
|
||||||
|
@apply dark:stroke-dark-cyan;
|
||||||
|
@apply fill-light-purple;
|
||||||
|
@apply dark:fill-dark-purple;
|
||||||
|
@apply stroke-light-purple;
|
||||||
|
@apply dark:stroke-dark-purple;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
<p>Copyright Peaceultime - 2024</p>
|
<p>Copyright Peaceultime - 2024</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-1 flex items-baseline overflow-auto">
|
<div class="flex-1 flex items-baseline overflow-auto p-8 relative">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
<p>Copyright Peaceultime - 2024</p>
|
<p>Copyright Peaceultime - 2024</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-1 flex items-baseline overflow-auto">
|
<div class="flex-1 flex items-baseline overflow-auto p-8 relative">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -9,6 +9,7 @@ export default defineNuxtConfig({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
tailwindcss: {
|
tailwindcss: {
|
||||||
|
viewer: false,
|
||||||
config: {
|
config: {
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
import useDatabase from "~/composables/useDatabase";
|
import useDatabase from "~/composables/useDatabase";
|
||||||
import { extname, basename } from 'node:path';
|
import { extname, basename } from 'node:path';
|
||||||
import type { File } from '~/types/api';
|
import type { File, FileType } from '~/types/api';
|
||||||
|
import { InputTypeHTMLAttribute } from "vue";
|
||||||
|
import { CanvasColor, CanvasContent } from "~/types/canvas";
|
||||||
|
|
||||||
const typeMapping: Record<string, string> = {
|
const typeMapping: Record<string, FileType> = {
|
||||||
".md": "Markdown",
|
".md": "Markdown",
|
||||||
".canvas": "Canvas"
|
".canvas": "Canvas"
|
||||||
}
|
}
|
||||||
|
|
@ -36,7 +38,7 @@ export default defineTask({
|
||||||
order: order && order[1] ? order[1] : 50,
|
order: order && order[1] ? order[1] : 50,
|
||||||
title: order && order[2] ? order[2] : title,
|
title: order && order[2] ? order[2] : title,
|
||||||
type: 'Folder',
|
type: 'Folder',
|
||||||
content: undefined
|
content: null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,13 +46,14 @@ export default defineTask({
|
||||||
const title = basename(e.path, extension);
|
const title = basename(e.path, extension);
|
||||||
const order = /(\d+)\. ?(.+)/gsmi.exec(title);
|
const order = /(\d+)\. ?(.+)/gsmi.exec(title);
|
||||||
const path = (e.path as string).split('/').map(f => { const check = /(\d+)\. ?(.+)/gsmi.exec(f); return check && check[2] ? check[2] : f }).join('/');
|
const path = (e.path as string).split('/').map(f => { const check = /(\d+)\. ?(.+)/gsmi.exec(f); return check && check[2] ? check[2] : f }).join('/');
|
||||||
|
const content = (await $fetch(`https://git.peaceultime.com/api/v1/repos/peaceultime/system-aspect/raw/${encodeURIComponent(e.path)}`));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
path: (extension === '.md' ? path.replace(extension, '') : path).toLowerCase().replaceAll(" ", "-").normalize("NFD").replace(/[\u0300-\u036f]/g, ""),
|
path: (extension === '.md' ? path.replace(extension, '') : path).toLowerCase().replaceAll(" ", "-").normalize("NFD").replace(/[\u0300-\u036f]/g, ""),
|
||||||
order: order && order[1] ? order[1] : 50,
|
order: order && order[1] ? order[1] : 50,
|
||||||
title: order && order[2] ? order[2] : title,
|
title: order && order[2] ? order[2] : title,
|
||||||
type: (typeMapping[extension] ?? 'File'),
|
type: (typeMapping[extension] ?? 'File'),
|
||||||
content: await $fetch(`https://git.peaceultime.com/api/v1/repos/peaceultime/system-aspect/raw/${encodeURIComponent(e.path)}`)
|
content: reshapeContent(content as string, typeMapping[extension] ?? 'File')
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
@ -100,4 +103,37 @@ export default defineTask({
|
||||||
return { result: false };
|
return { result: false };
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function reshapeContent(content: string, type: FileType): string | null
|
||||||
|
{
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case "Markdown":
|
||||||
|
case "File":
|
||||||
|
return content;
|
||||||
|
case "Canvas":
|
||||||
|
const data = JSON.parse(content) as CanvasContent;
|
||||||
|
data.edges.forEach(e => e.color = typeof e.color === 'string' ? getColor(e.color) : undefined);
|
||||||
|
data.nodes.forEach(e => e.color = typeof e.color === 'string' ? getColor(e.color) : undefined);
|
||||||
|
return JSON.stringify(data);
|
||||||
|
default:
|
||||||
|
case 'Folder':
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getColor(color: string): CanvasColor
|
||||||
|
{
|
||||||
|
const colors: Record<string, string> = {
|
||||||
|
'1': 'fill-light-red dark:fill-dark-red stroke-light-red dark:stroke-dark-red',
|
||||||
|
'2': 'fill-light-orange dark:fill-dark-orange stroke-light-orange dark:stroke-dark-orange',
|
||||||
|
'3': 'fill-light-yellow dark:fill-dark-yellow stroke-light-yellow dark:stroke-dark-yellow',
|
||||||
|
'4': 'fill-light-green dark:fill-dark-green stroke-light-green dark:stroke-dark-green',
|
||||||
|
'5': 'fill-light-cyan dark:fill-dark-cyan stroke-light-cyan dark:stroke-dark-cyan',
|
||||||
|
'6': 'fill-light-purple dark:fill-dark-purple stroke-light-purple dark:stroke-dark-purple',
|
||||||
|
};
|
||||||
|
if(colors.hasOwnProperty(color))
|
||||||
|
return { class: colors[color] };
|
||||||
|
else
|
||||||
|
return { hex: color };
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,11 @@ export interface CanvasContent {
|
||||||
edges: CanvasEdge[];
|
edges: CanvasEdge[];
|
||||||
groups: CanvasGroup[];
|
groups: CanvasGroup[];
|
||||||
}
|
}
|
||||||
|
export type CanvasColor = {
|
||||||
|
class?: string;
|
||||||
|
} & {
|
||||||
|
hex?: string;
|
||||||
|
}
|
||||||
export interface CanvasNode {
|
export interface CanvasNode {
|
||||||
type: 'group' | 'text';
|
type: 'group' | 'text';
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -10,7 +15,7 @@ export interface CanvasNode {
|
||||||
y: number;
|
y: number;
|
||||||
width: number;
|
width: number;
|
||||||
height: number;
|
height: number;
|
||||||
color?: string;
|
color?: CanvasColor;
|
||||||
label?: string;
|
label?: string;
|
||||||
text?: any;
|
text?: any;
|
||||||
};
|
};
|
||||||
|
|
@ -20,7 +25,7 @@ export interface CanvasEdge {
|
||||||
fromSide: 'bottom' | 'top' | 'left' | 'right';
|
fromSide: 'bottom' | 'top' | 'left' | 'right';
|
||||||
toNode: string;
|
toNode: string;
|
||||||
toSide: 'bottom' | 'top' | 'left' | 'right';
|
toSide: 'bottom' | 'top' | 'left' | 'right';
|
||||||
color?: string;
|
color?: CanvasColor;
|
||||||
label?: string;
|
label?: string;
|
||||||
};
|
};
|
||||||
export interface CanvasGroup {
|
export interface CanvasGroup {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue