Initial release: Ironpad v0.1.0 - Local-first, file-based project and knowledge management system. Rust backend, Vue 3 frontend, Milkdown editor, Git integration, cross-platform builds. Built with AI using Open Method.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
skepsismusic
2026-02-06 00:13:31 +01:00
commit ebe3e2aa8f
97 changed files with 25033 additions and 0 deletions

View File

@@ -0,0 +1,108 @@
<script setup lang="ts">
import { ref, computed } from 'vue'
import { MilkdownProvider } from '@milkdown/vue'
import { Crepe } from '@milkdown/crepe'
import { useThemeStore } from '../stores'
import { assetsApi } from '../api/client'
import MilkdownEditorCore from './MilkdownEditorCore.vue'
const props = defineProps<{
modelValue: string
readonly?: boolean
placeholder?: string
projectId?: string
editorKey?: string | number
}>()
const emit = defineEmits<{
'update:modelValue': [value: string]
}>()
const themeStore = useThemeStore()
const uploading = ref(false)
const editorInstance = ref<Crepe | null>(null)
const isDarkMode = computed(() => themeStore.getEffectiveTheme() === 'dark')
// Handle content updates from the core editor
function handleContentUpdate(value: string) {
emit('update:modelValue', value)
}
// Store editor instance when ready
function handleEditorReady(crepe: Crepe) {
editorInstance.value = crepe
}
</script>
<template>
<div
class="milkdown-editor-wrapper"
:class="{
readonly,
uploading,
'dark-mode': isDarkMode
}"
>
<!-- Upload indicator -->
<div v-if="uploading" class="upload-indicator">
Uploading image...
</div>
<!-- Milkdown Editor with Crepe (includes built-in toolbar) -->
<!-- CRITICAL: Key the entire container to force full remount when switching notes/tasks -->
<!-- This ensures the Milkdown editor instance is completely recreated, not just updated -->
<div :key="editorKey" class="milkdown-container" :class="{ 'is-readonly': readonly }">
<MilkdownProvider>
<MilkdownEditorCore
:model-value="modelValue"
:readonly="readonly"
@update:model-value="handleContentUpdate"
@editor-ready="handleEditorReady"
/>
</MilkdownProvider>
</div>
</div>
</template>
<style scoped>
.milkdown-editor-wrapper {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
position: relative;
}
.milkdown-container {
flex: 1;
display: flex;
flex-direction: column;
overflow: auto;
}
.milkdown-container.is-readonly {
pointer-events: none;
opacity: 0.7;
}
.upload-indicator {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: var(--color-bg-secondary);
border: 1px solid var(--color-border);
padding: 12px 24px;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
z-index: 10;
font-size: 13px;
color: var(--color-text);
}
.milkdown-editor-wrapper.uploading .milkdown-container {
opacity: 0.5;
pointer-events: none;
}
</style>