Compare commits

...
Author SHA1 Message Date
Sidharth Vinod d1fd4dc244 feat: More edit modes in CTA 2026-04-02 17:33:52 +05:30
Sidharth Vinod 9436f8ddda chore: Remove canonical 2026-04-01 22:43:58 +05:30
4 changed files with 123 additions and 37 deletions
-1
View File
@@ -5,7 +5,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Online FlowChart &amp; Diagrams Editor - Mermaid Live Editor</title> <title>Online FlowChart &amp; Diagrams Editor - Mermaid Live Editor</title>
<meta name="og:image" content="%sveltekit.assets%/favicon.svg" /> <meta name="og:image" content="%sveltekit.assets%/favicon.svg" />
<link rel="canonical" href="https://mermaid.ai/live" />
<meta <meta
name="description" name="description"
content="Simplify documentation and avoid heavy tools. Open source Visio Alternative. Commonly used for explaining your code! Mermaid is a simple markdown-like script language for generating charts from text via javascript." /> content="Simplify documentation and avoid heavy tools. Open source Visio Alternative. Commonly used for explaining your code! Mermaid is a simple markdown-like script language for generating charts from text via javascript." />
@@ -0,0 +1,118 @@
<script lang="ts">
import McWrapper from '$/components/McWrapper.svelte';
import MermaidChartIcon from '$/components/MermaidChartIcon.svelte';
import { Button } from '$/components/ui/button';
import { standardizeDiagramType } from '$/util/mermaid';
import { stateStore, urlsStore } from '$/util/state';
import { logMermaidChartClick } from '$/util/stats';
import { quintInOut } from 'svelte/easing';
import { slide } from 'svelte/transition';
const visualEditDiagramTypes = new Set([
'flowchart',
'stateDiagram',
'classDiagram',
'sequenceDiagram',
'er',
'requirement',
'mindmap'
]);
const diagramType = $derived.by(() => {
const dt = $stateStore.diagramType;
return dt ? standardizeDiagramType(dt) : undefined;
});
const showVisualEdit = $derived.by(() => {
return diagramType ? visualEditDiagramTypes.has(diagramType) : false;
});
interface EnhancedEditAction {
campaign: string;
label: string;
medium: 'ai_edit' | 'visual_edit' | 'voice_edit';
source: string;
}
let currentActionMedium = $state<EnhancedEditAction['medium'] | undefined>(undefined);
let previousDiagramType = $state<string | undefined>(undefined);
const availableActions = $derived.by<EnhancedEditAction[]>(() => {
if (!$stateStore.diagramType) {
return [];
}
const actions: EnhancedEditAction[] = [
{ campaign: 'ai_1', label: 'with AI', medium: 'ai_edit', source: 'aiEdit' },
{ campaign: 'voice_1', label: 'with Voice', medium: 'voice_edit', source: 'voiceEdit' }
];
if (showVisualEdit) {
actions.unshift({
campaign: 'visual_1',
label: 'Visually',
medium: 'visual_edit',
source: 'visualEdit'
});
}
return actions;
});
const currentAction = $derived.by(() => {
const actions = availableActions;
if (actions.length === 0) {
return undefined;
}
return actions.find(({ medium }) => medium === currentActionMedium) ?? actions[0];
});
$effect(() => {
const actions = availableActions;
if (!diagramType || actions.length === 0) {
return;
}
const hasCurrentAction = actions.some(({ medium }) => medium === currentActionMedium);
if (diagramType !== previousDiagramType || !hasCurrentAction) {
currentActionMedium = actions[Math.floor(Math.random() * actions.length)].medium;
previousDiagramType = diagramType;
}
});
$effect(() => {
if (diagramType) {
return;
}
previousDiagramType = undefined;
});
</script>
{#if currentAction}
<McWrapper>
<Button
variant="secondary"
size="sm"
href={$urlsStore.mermaidChart({
medium: currentAction.medium,
campaign: currentAction.campaign
}).save}
target="_blank"
onclick={() => logMermaidChartClick(currentAction.source)}>
<MermaidChartIcon />
Edit
{#key currentAction.label}
<span
class="-ml-1"
in:slide={{ axis: 'x', easing: quintInOut, delay: 400 }}
out:slide={{ axis: 'x', easing: quintInOut }}>
{currentAction.label}
</span>
{/key}
</Button>
</McWrapper>
{/if}
+3 -1
View File
@@ -142,11 +142,13 @@ export const urlsStore = derived([stateStore], ([{ code, serialized }]) => {
}: { }: {
medium: medium:
| 'ai_repair' | 'ai_repair'
| 'ai_edit'
| 'main_menu' | 'main_menu'
| 'save_diagram' | 'save_diagram'
| 'share' | 'share'
| 'vibe_diagramming' | 'vibe_diagramming'
| 'visual_edit'; | 'visual_edit'
| 'voice_edit';
campaign?: string; campaign?: string;
}) => { }) => {
const utmSource = getUTMSource(); const utmSource = getUTMSource();
+2 -35
View File
@@ -3,6 +3,7 @@
import Card from '$/components/Card/Card.svelte'; import Card from '$/components/Card/Card.svelte';
import DiagramDocButton from '$/components/DiagramDocumentationButton.svelte'; import DiagramDocButton from '$/components/DiagramDocumentationButton.svelte';
import Editor from '$/components/Editor.svelte'; import Editor from '$/components/Editor.svelte';
import EnhancedEditsButton from '$/components/EnhancedEditsButton.svelte';
import History from '$/components/History/History.svelte'; import History from '$/components/History/History.svelte';
import McWrapper from '$/components/McWrapper.svelte'; import McWrapper from '$/components/McWrapper.svelte';
import MermaidChartIcon from '$/components/MermaidChartIcon.svelte'; import MermaidChartIcon from '$/components/MermaidChartIcon.svelte';
@@ -19,15 +20,12 @@
import VersionSecurityToolbar from '$/components/VersionSecurityToolbar.svelte'; import VersionSecurityToolbar from '$/components/VersionSecurityToolbar.svelte';
import View from '$/components/View.svelte'; import View from '$/components/View.svelte';
import type { EditorMode, Tab } from '$/types'; import type { EditorMode, Tab } from '$/types';
import { standardizeDiagramType } from '$/util/mermaid';
import { shouldShowEditorChooser } from '$/util/migration/domainMigration'; import { shouldShowEditorChooser } from '$/util/migration/domainMigration';
import { PanZoomState } from '$/util/panZoom'; import { PanZoomState } from '$/util/panZoom';
import { stateStore, updateCodeStore, urlsStore } from '$/util/state'; import { stateStore, updateCodeStore, urlsStore } from '$/util/state';
import { logEvent, logMermaidChartClick } from '$/util/stats'; import { logEvent, logMermaidChartClick } from '$/util/stats';
import { initHandler } from '$/util/util'; import { initHandler } from '$/util/util';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { quintInOut } from 'svelte/easing';
import { slide } from 'svelte/transition';
import CodeIcon from '~icons/custom/code'; import CodeIcon from '~icons/custom/code';
import HistoryIcon from '~icons/material-symbols/history'; import HistoryIcon from '~icons/material-symbols/history';
import GearIcon from '~icons/material-symbols/settings-outline-rounded'; import GearIcon from '~icons/material-symbols/settings-outline-rounded';
@@ -65,20 +63,6 @@
}); });
}); });
const visualEditDiagramTypes = new Set([
'flowchart',
'stateDiagram',
'classDiagram',
'sequenceDiagram',
'er',
'requirement',
'mindmap'
]);
const showVisualEdit = $derived.by(() => {
const dt = $stateStore.diagramType;
return dt ? visualEditDiagramTypes.has(standardizeDiagramType(dt)) : false;
});
let isHistoryOpen = $state(false); let isHistoryOpen = $state(false);
let editorPane: Resizable.Pane | undefined; let editorPane: Resizable.Pane | undefined;
@@ -153,24 +137,7 @@
<Resizable.Handle class="mr-1 hidden opacity-0 sm:block" /> <Resizable.Handle class="mr-1 hidden opacity-0 sm:block" />
<Resizable.Pane minSize={15} class="relative flex h-full flex-1 flex-col overflow-hidden"> <Resizable.Pane minSize={15} class="relative flex h-full flex-1 flex-col overflow-hidden">
<View {panZoomState} shouldShowGrid={$stateStore.grid} /> <View {panZoomState} shouldShowGrid={$stateStore.grid} />
{#if showVisualEdit} <div class="absolute top-0 left-5 hidden md:block"><EnhancedEditsButton /></div>
<div
class="absolute top-0 left-5 hidden md:block"
transition:slide={{ axis: 'x', easing: quintInOut }}>
<McWrapper>
<Button
variant="secondary"
size="sm"
href={$urlsStore.mermaidChart({ medium: 'visual_edit', campaign: 'visual_1' })
.save}
target="_blank"
onclick={() => logMermaidChartClick('visualEdit')}>
<MermaidChartIcon />
Edit Visually
</Button>
</McWrapper>
</div>
{/if}
<div class="absolute top-0 right-0"><PanZoomToolbar {panZoomState} /></div> <div class="absolute top-0 right-0"><PanZoomToolbar {panZoomState} /></div>
<div class="absolute right-0 bottom-0"><VersionSecurityToolbar /></div> <div class="absolute right-0 bottom-0"><VersionSecurityToolbar /></div>
<div class="absolute bottom-0 left-0 sm:left-5"><SyncRoughToolbar /></div> <div class="absolute bottom-0 left-0 sm:left-5"><SyncRoughToolbar /></div>