Răsfoiți Sursa

refactor(editor): restructure as Nuxt module, fix DnD for Tauri/Safari

Architecture:
- Add @enesis/editor/nuxt module with addComponentsDir for auto-import
- Switch from Vite aliases to proper package exports (development condition)
- Migrate imports from @/ to ./ relative paths for library compatibility
- Add module.ts as second build entry point (ESM + CJS output)
- Externalize @nuxt/kit, @nuxt/schema, builtinModules from lib build

SPA splash:
- Replace Vue-rendered branded splash with spa-loading-template.html
- Remove splash via watch(ready) + nextTick to prevent blank flash
- Gate WelcomeScreen/Layout on ready to avoid rendering during init

Drag-and-drop (Tauri/Safari):
- Disable Tauri's native dragDropEnabled (interferes with DOM DnD)
- Add @dragenter.prevent on insertion zones (Safari requires it)
- Add debug logging to all DnD handlers (dragstart, enter, over, leave, drop, end)

Bug fixes:
- Fix style.css: invalid @apply mb-[calc(4)] -> mb-4
- Register all exported components in Vue plugin install()
Zander Hawke 7 ore în urmă
părinte
comite
5b71d90140

+ 16 - 9
apps/tauri/nuxt.config.ts

@@ -1,13 +1,12 @@
 import { resolve } from "node:path"
 
-const EDITOR_ROOT = resolve(__dirname, "../../packages/editor")
-
 export default defineNuxtConfig({
   ssr: false,
+  spaLoadingTemplate: true,
 
-  modules: ["@nuxt/ui", "@pinia/nuxt"],
+  modules: ["@nuxt/ui", "@pinia/nuxt", "@enesis/editor/nuxt"],
 
-  css: ["~/assets/main.css", `${EDITOR_ROOT}/src/assets/style.css`],
+  css: ["~/assets/main.css"],
 
   colorMode: {
     classSuffix: "",
@@ -21,7 +20,6 @@ export default defineNuxtConfig({
     head: {
       title: "Enesis Editor",
       link: [{ rel: "icon", type: "image/svg+xml", href: "/favicon.svg" }],
-      style: [{ textContent: "html { background-color: #121212 }" }],
     },
   },
 
@@ -30,11 +28,20 @@ export default defineNuxtConfig({
     envPrefix: ["VITE_", "TAURI_"],
     server: {
       strictPort: true,
+      watch: {
+        ignored: ['!**/node_modules/@enesis/editor/**'],
+      },
     },
-    resolve: {
-      alias: [
-        { find: /^@\//, replacement: `${EDITOR_ROOT}/src/` },
-        { find: "@enesis/editor", replacement: `${EDITOR_ROOT}/src/index.ts` },
+    optimizeDeps: {
+      exclude: ['@enesis/editor'],
+      include: [
+        '@tauri-apps/api/core',
+        '@tauri-apps/api/event',
+        '@tauri-apps/api/menu',
+        '@tauri-apps/plugin-dialog',
+        '@tauri-apps/plugin-sql',
+        '@tauri-apps/plugin-store',
+        '@vueuse/core',
       ],
     },
   },

+ 2 - 1
apps/tauri/src-tauri/tauri.conf.json

@@ -15,7 +15,8 @@
         "title": "Enesis Editor",
         "width": 1200,
         "height": 800,
-        "backgroundColor": "#121212"
+        "backgroundColor": "#1c1917",
+        "dragDropEnabled": false
       }
     ],
     "security": {

+ 12 - 37
apps/tauri/src/app.vue

@@ -13,7 +13,7 @@
  */
 import { invoke } from "@tauri-apps/api/core"
 import { Menu, MenuItem, Submenu } from "@tauri-apps/api/menu"
-import { watch } from "vue"
+import { nextTick, watch } from "vue"
 import WelcomeScreen from "~/components/WelcomeScreen.vue"
 import { useFileSystem } from "~/composables/useFileSystem"
 import type { InitResult } from "~/stores/workspace"
@@ -164,6 +164,11 @@ onMounted(async () => {
   ready.value = true
 })
 
+// Remove the SPA splash overlay once the view has rendered
+watch(ready, (isReady) => {
+  if (isReady) nextTick(() => document.getElementById("splash")?.remove())
+}, { once: true })
+
 // Build the menu once the app is ready — always visible
 watch(
   ready,
@@ -185,49 +190,19 @@ watch(
 
 <template>
   <UApp>
-    <!-- 1. Loading — branded splash while workspace initializes -->
-    <!-- Uses inline styles, not CSS variables — Nuxt UI theme isn't ready yet -->
-    <div
-      v-if="!ready"
-      class="flex h-screen items-center justify-center select-none"
-      style="background-color: #121212"
-    >
-      <div class="text-center" style="display: flex; flex-direction: column; gap: 1.5rem; align-items: center">
-        <svg
-          width="64" height="56" viewBox="0 0 160 140"
-          aria-hidden="true"
-        >
-          <polygon points="80,10 140,30 80,50 20,30"   fill="#c25f34" opacity="0.85" />
-          <polygon points="20,30 80,50 80,80 20,60"   fill="#c25f34" opacity="0.65" />
-          <polygon points="80,50 140,30 140,60 80,80"   fill="#c25f34" opacity="0.55" />
-          <polygon points="20,60 80,80 80,110 20,90"   fill="#c25f34" opacity="0.45" />
-          <polygon points="80,80 140,60 140,90 80,110"   fill="#c25f34" opacity="0.35" />
-          <polygon points="20,90 80,110 80,140 20,120"   fill="#c25f34" opacity="0.25" />
-          <polygon points="80,110 140,90 140,120 80,140"   fill="#c25f34" opacity="0.15" />
-        </svg>
-
-        <div>
-          <p style="margin: 0; font-size: 1.5rem; font-family: serif; color: #e4e4e7; letter-spacing: -0.025em">
-            Enesis
-          </p>
-          <p style="margin: 0.75rem 0 0; font-size: 0.875rem; color: #a1a1aa">
-            Your thinking space
-          </p>
-        </div>
-      </div>
-    </div>
-
-    <!-- 2. Needs onboarding — no workspace or stale path -->
+    <!-- 1. Needs onboarding — no workspace or stale path -->
     <WelcomeScreen
-      v-else-if="!hasWorkspace"
+      v-if="ready && !hasWorkspace"
       :stale-path="stalePath"
       :recent-paths="workspace.recentWorkspaces"
       @complete="hasWorkspace = true"
     />
 
-    <!-- 3. Ready — normal app chrome -->
-    <NuxtLayout v-else>
+    <!-- 2. Ready — normal app chrome -->
+    <NuxtLayout v-else-if="ready && hasWorkspace">
       <NuxtPage :key="workspace.workspacePath" />
     </NuxtLayout>
+
+    <!-- 3. Initializing — nothing rendered (SPA template covers this phase) -->
   </UApp>
 </template>

+ 4 - 4
apps/tauri/src/assets/main.css

@@ -1,6 +1,8 @@
 @import "tailwindcss";
 @import "@nuxt/ui";
-@source "../../../../packages/editor/src";
+
+@import "../../../../packages/editor/src/assets/style.css";
+@source "../../../../packages/editor/src/components/**/*.vue";
 
 @theme {
   --font-sans: "Lora", serif;
@@ -24,6 +26,4 @@
   --ui-radius: 0.375rem;
 }
 
-html {
-  font-family: var(--font-sans);
-}
+html { background-color: oklch(21.6% 0.006 56.043); }

+ 48 - 0
apps/tauri/src/spa-loading-template.html

@@ -0,0 +1,48 @@
+<div id="splash">
+  <div id="splash-inner">
+    <svg width="64" height="56" viewBox="0 0 160 140" aria-hidden="true">
+      <polygon points="80,10 140,30 80,50 20,30"   fill="#c25f34" opacity="0.85" />
+      <polygon points="20,30 80,50 80,80 20,60"   fill="#c25f34" opacity="0.65" />
+      <polygon points="80,50 140,30 140,60 80,80"   fill="#c25f34" opacity="0.55" />
+      <polygon points="20,60 80,80 80,110 20,90"   fill="#c25f34" opacity="0.45" />
+      <polygon points="80,80 140,60 140,90 80,110"   fill="#c25f34" opacity="0.35" />
+      <polygon points="20,90 80,110 80,140 20,120"   fill="#c25f34" opacity="0.25" />
+      <polygon points="80,110 140,90 140,120 80,140"   fill="#c25f34" opacity="0.15" />
+    </svg>
+    <div>
+      <p id="title">Enesis</p>
+      <p id="tagline">Your thinking space</p>
+    </div>
+  </div>
+  <style>
+    #splash {
+      position: fixed;
+      inset: 0;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      background: #1c1917;
+      z-index: 9999;
+    }
+    #splash-inner {
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      gap: 1.5rem;
+    }
+    #title {
+      margin: 0;
+      font-size: 1.5rem;
+      font-family: serif;
+      color: #e4e4e7;
+      letter-spacing: -0.025em;
+      text-align: center;
+    }
+    #tagline {
+      margin: 0.75rem 0 0;
+      font-size: 0.875rem;
+      color: #a1a1aa;
+      text-align: center;
+    }
+  </style>
+</div>

+ 12 - 5
packages/editor/package.json

@@ -7,7 +7,13 @@
       "types": "./dist/index.d.ts",
       "style": "./dist/index.css"
     },
-    "./dist/index.css": "./dist/index.css"
+    "./dist/index.css": "./dist/index.css",
+    "./nuxt": {
+      "development": "./src/module.ts",
+      "import": "./dist/module.js",
+      "require": "./dist/module.cjs",
+      "types": "./dist/module.d.ts"
+    }
   },
   "main": "./dist/index.js",
   "types": "./dist/index.d.ts",
@@ -36,7 +42,6 @@
     "@vue/tsconfig": "^0.9.1",
     "@vueuse/core": "^14.3.0",
     "jsdom": "^29.1.1",
-    "pinia": "^3.0.4",
     "typescript": "^6.0.3",
     "vite": "^8.0.16",
     "vitest": "^4.1.9",
@@ -45,8 +50,10 @@
   },
   "peerDependencies": {
     "@nuxt/ui": "^4.7.1",
+    "@tailwindcss/vite": "^4.3.1",
     "@vueuse/core": "^14.3.0",
     "pinia": "^3.0.4",
+    "tailwindcss": "^4.3.1",
     "vue": "^3.5.34"
   },
   "dependencies": {
@@ -66,7 +73,8 @@
     "@lezer/common": "^1.2.2",
     "@lezer/highlight": "^1.2.3",
     "@lezer/markdown": "^1.6.4",
-    "@tailwindcss/vite": "^4.3.1",
+    "@nuxt/kit": "^4.4.8",
+    "@nuxt/schema": "^4.4.8",
     "katex": "^0.17.0",
     "nanoid": "^5.1.15",
     "prosemirror-commands": "^1.7.1",
@@ -75,7 +83,6 @@
     "prosemirror-model": "^1.25.9",
     "prosemirror-state": "^1.4.3",
     "prosemirror-transform": "^1.12.0",
-    "prosemirror-view": "^1.41.9",
-    "tailwindcss": "^4.3.1"
+    "prosemirror-view": "^1.41.9"
   }
 }

+ 2 - 2
packages/editor/src/assets/style.css

@@ -126,11 +126,11 @@
 
 /* Property lines — no spacing between them, but margin after the last one */
 .ProseMirror .md-property {
-  margin: 0;
+  @apply m-0;
 }
 
 .ProseMirror .md-property:last-child {
-  margin-bottom: calc(var(--spacing) * 4);
+  @apply mb-4;
 }
 .md-property-delimiter {
   @apply text-(--ui-border) mx-1 select-none;

+ 22 - 2
packages/editor/src/components/Editor.vue

@@ -182,24 +182,37 @@ function onDragStart(
   if (event.dataTransfer) {
     event.dataTransfer.effectAllowed = "move"
   }
+  log.info("dragstart", { index, blockId, effectAllowed: "move", types: event.dataTransfer?.types })
+}
+
+function onDragEnterZone(zoneIndex: number, event: DragEvent) {
+  log.info("dragenter", { zoneIndex, hasDragState: !!dragState.value })
+  onDragOverZone(zoneIndex, event)
 }
 
 function onDragOverZone(zoneIndex: number, event: DragEvent) {
   if (!dragState.value) {
-    dropZoneIndex.value = null
+    if (dropZoneIndex.value === zoneIndex) dropZoneIndex.value = null
     return
   }
+  const changed = dropZoneIndex.value !== zoneIndex
+  const prev = dropZoneIndex.value
   dropZoneIndex.value = zoneIndex
   event.dataTransfer!.dropEffect = "move"
+  if (changed) {
+    log.debug("dragover", { zoneIndex, from: prev, to: zoneIndex })
+  }
 }
 
 function onDragLeaveZone(zoneIndex: number) {
+  log.info("dragleave", { zoneIndex, hadHighlight: dropZoneIndex.value === zoneIndex })
   if (dropZoneIndex.value === zoneIndex) {
     dropZoneIndex.value = null
   }
 }
 
 function onDragEnd() {
+  log.info("dragend", { hadState: !!dragState.value, hadHighlight: dropZoneIndex.value !== null })
   dragState.value = null
   dropZoneIndex.value = null
 }
@@ -207,6 +220,7 @@ function onDragEnd() {
 function onDropOnZone(zoneIndex: number) {
   const state = dragState.value
   if (!state) {
+    log.warn("drop with no dragState", { zoneIndex })
     dragState.value = null
     dropZoneIndex.value = null
     return
@@ -216,6 +230,8 @@ function onDropOnZone(zoneIndex: number) {
   // if fromIndex < zoneIndex, the zone shifts left by 1.
   const targetIndex = state.fromIndex < zoneIndex ? zoneIndex - 1 : zoneIndex
 
+  log.info("drop", { fromIndex: state.fromIndex, toIndex: targetIndex, zoneIndex, blockId: state.blockId })
+
   if (state.fromIndex === targetIndex) {
     dragState.value = null
     dropZoneIndex.value = null
@@ -1037,6 +1053,7 @@ defineExpose({
         @blur="onZoneBlur"
         @navigate-up="onZoneNavigateUp(i)"
         @navigate-down="onZoneNavigateDown(i)"
+        @dragenter.prevent="onDragEnterZone(i, $event)"
         @dragover.prevent="onDragOverZone(i, $event)"
         @dragleave="onDragLeaveZone(i)"
         @drop="onDropOnZone(i)"
@@ -1055,7 +1072,7 @@ defineExpose({
           class="flex items-center justify-center cursor-grab active:cursor-grabbing rounded transition-all"
           data-drag-handle
           :class="dragState?.blockId === block.id ? 'size-7 text-(--ui-primary)'
-            : 'size-6 text-(--ui-text-muted) opacity-30 group-hover/block:opacity-100 group-hover/block:text-(--ui-primary)'"
+            : 'size-6 text-(--ui-text-muted) group-hover/block:opacity-100 group-hover/block:text-(--ui-primary)'"
           @dragstart="onDragStart(i, block.id, block.content, block.depth, $event)"
           @dragend="onDragEnd"
         >
@@ -1113,6 +1130,7 @@ defineExpose({
       @blur="onZoneBlur"
       @navigate-up="onZoneNavigateUp(blocks.length)"
       @navigate-down="onZoneNavigateDown(blocks.length)"
+      @dragenter.prevent="onDragEnterZone(blocks.length, $event)"
       @dragover.prevent="onDragOverZone(blocks.length, $event)"
       @dragleave="onDragLeaveZone(blocks.length)"
       @drop="onDropOnZone(blocks.length)"
@@ -1120,3 +1138,5 @@ defineExpose({
     </div>
   </div>
 </template>
+
+

+ 28 - 24
packages/editor/src/index.ts

@@ -1,25 +1,25 @@
 import type { App } from "vue"
-import Editor from "@/components/Editor.vue"
-import EditorBlock from "@/components/EditorBlock.vue"
-import EditorSuggestionMenu from "@/components/EditorSuggestionMenu.vue"
-import EditorToolbar from "@/components/EditorToolbar.vue"
+import Editor from "./components/Editor.vue"
+import EditorBlock from "./components/EditorBlock.vue"
+import EditorSuggestionMenu from "./components/EditorSuggestionMenu.vue"
+import EditorToolbar from "./components/EditorToolbar.vue"
 
 import "katex/dist/katex.css"
-import "@/assets/style.css"
+import "./assets/style.css"
 
-export type { EditorFocusTarget } from "@/components/Editor.vue"
-export type { ToolbarMode } from "@/components/EditorToolbar.vue"
-export type { FocusTarget } from "@/composables/useFocusRegistry"
+export type { EditorFocusTarget } from "./components/Editor.vue"
+export type { ToolbarMode } from "./components/EditorToolbar.vue"
+export type { FocusTarget } from "./composables/useFocusRegistry"
 export type {
   KeyBinding,
   KeyboardAction,
   KeyboardConfig,
-} from "@/composables/useKeyboard"
+} from "./composables/useKeyboard"
 export {
   defaultKeyBinding,
   useKeyboard,
   vimKeyBinding,
-} from "@/composables/useKeyboard"
+} from "./composables/useKeyboard"
 export type {
   PatternClosePayload,
   PatternKind,
@@ -27,34 +27,34 @@ export type {
   PatternSession,
   PatternSpec,
   PatternUpdatePayload,
-} from "@/composables/usePatternPlugin"
+} from "./composables/usePatternPlugin"
 export type {
   MentionData,
   MentionItem,
   SuggestionActionItem,
-} from "@/composables/useSuggestionGroups"
+} from "./composables/useSuggestionGroups"
 export {
   buildMentionGroups,
   buildSlashGroups,
   useMentionGroups,
   useSlashGroups,
-} from "@/composables/useSuggestionGroups"
+} from "./composables/useSuggestionGroups"
 export {
   extractEmbeddedId,
   generateBlockId,
   splitMarkdownIntoBlocks,
   stampBlockId,
-} from "@/lib/block-parser"
-export { moveBlock } from "@/lib/editor-operations"
-export type { FormattingHandlers } from "@/lib/formatting"
-export type { MarkdownPattern } from "@/lib/markdown-extensions"
+} from "./lib/block-parser"
+export { moveBlock } from "./lib/editor-operations"
+export type { FormattingHandlers } from "./lib/formatting"
+export type { MarkdownPattern } from "./lib/markdown-extensions"
 export type {
   BlockRule,
   MarkdownRule,
   ParsedDecorations,
-} from "@/lib/markdown-rules"
-export { MarkdownRuleEngine } from "@/lib/markdown-rules"
-export { registerNodeView } from "@/lib/node-view-registry"
+} from "./lib/markdown-rules"
+export { MarkdownRuleEngine } from "./lib/markdown-rules"
+export { registerNodeView } from "./lib/node-view-registry"
 export type {
   DeleteBlockOp,
   EditorOperation,
@@ -67,27 +67,31 @@ export type {
   OutdentBlockOp,
   SetBlockContentOp,
   SplitBlockOp,
-} from "@/lib/operation-history"
+} from "./lib/operation-history"
 export {
   computeInverse,
   createOperationHistory,
   setTimeSource,
-} from "@/lib/operation-history"
+} from "./lib/operation-history"
 export type {
   EditorTheme,
   ThemeColors,
   ThemeInput,
   ThemeSyntax,
-} from "@/lib/theme"
+} from "./lib/theme"
 export {
   resolveTheme,
   themePresets,
   themeToCSSVars,
-} from "@/lib/theme"
+} from "./lib/theme"
+
 export { Editor, EditorBlock, EditorSuggestionMenu, EditorToolbar }
 
 export default {
   install(app: App) {
+    app.component("Editor", Editor)
     app.component("EditorBlock", EditorBlock)
+    app.component("EditorSuggestionMenu", EditorSuggestionMenu)
+    app.component("EditorToolbar", EditorToolbar)
   },
 }

+ 23 - 0
packages/editor/src/module.ts

@@ -0,0 +1,23 @@
+import { defineNuxtModule, createResolver, addComponentsDir } from '@nuxt/kit'
+import type { Nuxt } from '@nuxt/schema'
+
+export interface ModuleOptions {}
+
+export default defineNuxtModule<ModuleOptions>({
+  meta: {
+    name: '@enesis/editor',
+    configKey: 'enesis',
+    compatibility: {
+      nuxt: '^4.0.0'
+    }
+  },
+  setup(_options: ModuleOptions, _nuxt: Nuxt) {
+    const resolver = createResolver(import.meta.url)
+
+    addComponentsDir({
+      path: resolver.resolve('./components'),
+      global: true,
+      watch: true,
+    })
+  }
+})

+ 23 - 4
packages/editor/vite.config.ts

@@ -3,6 +3,7 @@ import ui from "@nuxt/ui/vite"
 import tailwindcss from "@tailwindcss/vite"
 import vue from "@vitejs/plugin-vue"
 import { defineConfig } from "vite"
+import { builtinModules } from "module"
 
 export default defineConfig({
   plugins: [vue(), tailwindcss(), ui()],
@@ -11,12 +12,30 @@ export default defineConfig({
   },
   build: {
     lib: {
-      entry: resolve(__dirname, "src/index.ts"),
-      fileName: "index",
-      formats: ["es"],
+      entry: {
+        index: resolve(__dirname, "src/index.ts"),
+        module: resolve(__dirname, "src/module.ts"),
+      },
+      formats: ["es", "cjs"],
+      fileName: (format, entryName) => `${entryName}.${format === 'es' ? 'js' : 'cjs'}`,
     },
     rollupOptions: {
-      external: ["vue", "@nuxt/ui", "tailwindcss", "pinia"],
+      external: [
+        "vue",
+        "@nuxt/ui",
+        "tailwindcss",
+        "@vueuse/core",
+        "@nuxt/ui",
+        "@nuxt/kit",
+        "@nuxt/schema",
+        ...builtinModules,
+        ...builtinModules.map(m => `node:${m}`)
+      ],
+      output: {
+        globals: {
+          vue: "Vue",
+        },
+      },
     },
     cssCodeSplit: false,
     cssMinify: "lightningcss",

+ 170 - 42
pnpm-lock.yaml

@@ -31,7 +31,7 @@ importers:
         version: 1.2.86
       '@nuxt/ui':
         specifier: ^4.9.0
-        version: 4.9.0(5675fc70f939c4eaa8007c47ad9cdf31)
+        version: 4.9.0(ba8c0e94730163fcee6f96ba93882599)
       motion-v:
         specifier: ^2.3.0
         version: 2.3.0(@vueuse/[email protected]([email protected]([email protected])))([email protected]([email protected]))
@@ -193,6 +193,12 @@ importers:
       '@lezer/markdown':
         specifier: ^1.6.4
         version: 1.6.4
+      '@nuxt/kit':
+        specifier: ^4.4.8
+        version: 4.4.8([email protected])
+      '@nuxt/schema':
+        specifier: ^4.4.8
+        version: 4.4.8
       '@tailwindcss/vite':
         specifier: ^4.3.1
         version: 4.3.1([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))
@@ -202,6 +208,9 @@ importers:
       nanoid:
         specifier: ^5.1.15
         version: 5.1.15
+      pinia:
+        specifier: ^3.0.4
+        version: 3.0.4([email protected])([email protected]([email protected]))
       prosemirror-commands:
         specifier: ^1.7.1
         version: 1.7.1
@@ -257,9 +266,6 @@ importers:
       jsdom:
         specifier: ^29.1.1
         version: 29.1.1
-      pinia:
-        specifier: ^3.0.4
-        version: 3.0.4([email protected])([email protected]([email protected]))
       typescript:
         specifier: ^6.0.3
         version: 6.0.3
@@ -1230,10 +1236,6 @@ packages:
   '@nuxt/[email protected]':
     resolution: {integrity: sha512-2HWDoMRWGSOWl7fu8wvvLTjoiaEwM7tSDww+6n4yVrNzKJFNAOLpYB9UevEf0CrK32q2JuA7TZnVpdwiPPdQSQ==}
 
-  '@nuxt/[email protected]':
-    resolution: {integrity: sha512-AzsqBJeG7b3whIciyzkz4nBossEotM314KzKAptc8kH07ORBIR8Qh3QYKepo2YZwtxiDP2Y9aqzAztwpSEDHtw==}
-    engines: {node: '>=18.12.0'}
-
   '@nuxt/[email protected]':
     resolution: {integrity: sha512-ZUlZ5iYfyfJFDPluhn6ZxFWcsuxWbLnZBc8w3MAROcQ4lYfZ+qFpALBLSNlpc0zhOa++33EE+5PEbOAdVIY+dw==}
     engines: {node: '>=18.12.0'}
@@ -6577,7 +6579,7 @@ snapshots:
   '@dxup/[email protected]([email protected])([email protected])':
     dependencies:
       '@dxup/unimport': 0.1.2
-      '@nuxt/kit': 4.4.6([email protected])
+      '@nuxt/kit': 4.4.8([email protected])
       chokidar: 5.0.0
       pathe: 2.0.3
       tinyglobby: 0.2.17
@@ -6974,7 +6976,7 @@ snapshots:
       https-proxy-agent: 7.0.6
       node-fetch: 2.7.0
       nopt: 8.1.0
-      semver: 7.8.4
+      semver: 7.8.5
       tar: 7.5.16
     transitivePeerDependencies:
       - encoding
@@ -7072,7 +7074,7 @@ snapshots:
 
   '@nuxt/[email protected]([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))':
     dependencies:
-      '@nuxt/kit': 4.4.6([email protected])
+      '@nuxt/kit': 4.4.8([email protected])
       execa: 8.0.1
       vite: 8.0.16(@types/[email protected])([email protected])([email protected])([email protected])([email protected])
     transitivePeerDependencies:
@@ -7093,7 +7095,7 @@ snapshots:
     dependencies:
       '@nuxt/devtools-kit': 3.2.4([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))
       '@nuxt/devtools-wizard': 3.2.4
-      '@nuxt/kit': 4.4.6([email protected])
+      '@nuxt/kit': 4.4.8([email protected])
       '@vue/devtools-core': 8.1.3([email protected]([email protected]))
       '@vue/devtools-kit': 8.1.3
       birpc: 4.0.0
@@ -7120,7 +7122,7 @@ snapshots:
       structured-clone-es: 2.0.0
       tinyglobby: 0.2.17
       vite: 8.0.16(@types/[email protected])([email protected])([email protected])([email protected])([email protected])
-      vite-plugin-inspect: 11.4.1(@nuxt/[email protected].6([email protected]))([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))
+      vite-plugin-inspect: 11.4.1(@nuxt/[email protected].8([email protected]))([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))
       vite-plugin-vue-tracer: 1.4.0([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))([email protected]([email protected]))
       which: 6.0.1
       ws: 8.21.0
@@ -7170,6 +7172,46 @@ snapshots:
       - uploadthing
       - vite
 
+  '@nuxt/[email protected]([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))':
+    dependencies:
+      '@nuxt/devtools-kit': 3.2.4([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))
+      '@nuxt/kit': 4.4.8([email protected])
+      consola: 3.4.2
+      defu: 6.1.7
+      fontless: 0.2.1([email protected]([email protected]))([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))
+      h3: 1.15.11
+      magic-regexp: 0.10.0
+      ofetch: 1.5.1
+      pathe: 2.0.3
+      sirv: 3.0.2
+      tinyglobby: 0.2.17
+      ufo: 1.6.4
+      unifont: 0.7.4
+      unplugin: 3.0.0
+      unstorage: 1.17.5([email protected]([email protected]))([email protected])
+    transitivePeerDependencies:
+      - '@azure/app-configuration'
+      - '@azure/cosmos'
+      - '@azure/data-tables'
+      - '@azure/identity'
+      - '@azure/keyvault-secrets'
+      - '@azure/storage-blob'
+      - '@capacitor/preferences'
+      - '@deno/kv'
+      - '@netlify/blobs'
+      - '@planetscale/database'
+      - '@upstash/redis'
+      - '@vercel/blob'
+      - '@vercel/functions'
+      - '@vercel/kv'
+      - aws4fetch
+      - db0
+      - idb-keyval
+      - ioredis
+      - magicast
+      - uploadthing
+      - vite
+
   '@nuxt/[email protected]([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))([email protected]([email protected]))':
     dependencies:
       '@iconify/collections': 1.0.698
@@ -7191,31 +7233,6 @@ snapshots:
       - vite
       - vue
 
-  '@nuxt/[email protected]([email protected])':
-    dependencies:
-      c12: 3.3.4([email protected])
-      consola: 3.4.2
-      defu: 6.1.7
-      destr: 2.0.5
-      errx: 0.1.0
-      exsolve: 1.0.8
-      ignore: 7.0.5
-      jiti: 2.7.0
-      klona: 2.0.6
-      mlly: 1.8.2
-      ohash: 2.0.11
-      pathe: 2.0.3
-      pkg-types: 2.3.1
-      rc9: 3.0.1
-      scule: 1.3.0
-      semver: 7.8.0
-      tinyglobby: 0.2.17
-      ufo: 1.6.4
-      unctx: 2.5.0
-      untyped: 2.0.0
-    transitivePeerDependencies:
-      - magicast
-
   '@nuxt/[email protected]([email protected])':
     dependencies:
       c12: 3.3.4([email protected])
@@ -7233,7 +7250,7 @@ snapshots:
       pkg-types: 2.3.1
       rc9: 3.0.1
       scule: 1.3.0
-      semver: 7.8.4
+      semver: 7.8.5
       tinyglobby: 0.2.17
       ufo: 1.6.4
       unctx: 2.5.0
@@ -7438,6 +7455,117 @@ snapshots:
       - vite
       - vue
 
+  '@nuxt/[email protected](ba8c0e94730163fcee6f96ba93882599)':
+    dependencies:
+      '@floating-ui/dom': 1.7.6
+      '@iconify/vue': 5.0.1([email protected]([email protected]))
+      '@nuxt/fonts': 0.14.0([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))
+      '@nuxt/icon': 2.2.3([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))([email protected]([email protected]))
+      '@nuxt/kit': 4.4.8([email protected])
+      '@nuxt/schema': 4.4.8
+      '@nuxtjs/color-mode': 4.0.1([email protected])
+      '@standard-schema/spec': 1.1.0
+      '@tailwindcss/postcss': 4.3.1
+      '@tailwindcss/vite': 4.3.1([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))
+      '@tanstack/vue-table': 8.21.3([email protected]([email protected]))
+      '@tanstack/vue-virtual': 3.13.29([email protected]([email protected]))
+      '@tiptap/core': 3.23.5(@tiptap/[email protected])
+      '@tiptap/extension-bubble-menu': 3.23.5(@tiptap/[email protected](@tiptap/[email protected]))(@tiptap/[email protected])
+      '@tiptap/extension-code': 3.23.5(@tiptap/[email protected](@tiptap/[email protected]))
+      '@tiptap/extension-collaboration': 3.23.5(@tiptap/[email protected](@tiptap/[email protected]))(@tiptap/[email protected])(@tiptap/[email protected]([email protected])([email protected])([email protected])([email protected]([email protected]))([email protected]))([email protected])
+      '@tiptap/extension-drag-handle': 3.23.5(@tiptap/[email protected](@tiptap/[email protected]))(@tiptap/[email protected](@tiptap/[email protected](@tiptap/[email protected]))(@tiptap/[email protected])(@tiptap/[email protected]([email protected])([email protected])([email protected])([email protected]([email protected]))([email protected]))([email protected]))(@tiptap/[email protected](@tiptap/[email protected](@tiptap/[email protected]))(@tiptap/[email protected]))(@tiptap/[email protected])(@tiptap/[email protected]([email protected])([email protected])([email protected])([email protected]([email protected]))([email protected]))
+      '@tiptap/extension-drag-handle-vue-3': 3.23.5(@tiptap/[email protected](@tiptap/[email protected](@tiptap/[email protected]))(@tiptap/[email protected](@tiptap/[email protected](@tiptap/[email protected]))(@tiptap/[email protected])(@tiptap/[email protected]([email protected])([email protected])([email protected])([email protected]([email protected]))([email protected]))([email protected]))(@tiptap/[email protected](@tiptap/[email protected](@tiptap/[email protected]))(@tiptap/[email protected]))(@tiptap/[email protected])(@tiptap/[email protected]([email protected])([email protected])([email protected])([email protected]([email protected]))([email protected])))(@tiptap/[email protected])(@tiptap/[email protected](@floating-ui/[email protected])(@tiptap/[email protected](@tiptap/[email protected]))(@tiptap/[email protected])([email protected]([email protected])))([email protected]([email protected]))
+      '@tiptap/extension-floating-menu': 3.23.5(@floating-ui/[email protected])(@tiptap/[email protected](@tiptap/[email protected]))(@tiptap/[email protected])
+      '@tiptap/extension-horizontal-rule': 3.23.5(@tiptap/[email protected](@tiptap/[email protected]))(@tiptap/[email protected])
+      '@tiptap/extension-image': 3.23.5(@tiptap/[email protected](@tiptap/[email protected]))
+      '@tiptap/extension-mention': 3.23.5(@tiptap/[email protected](@tiptap/[email protected]))(@tiptap/[email protected])(@tiptap/[email protected](@tiptap/[email protected](@tiptap/[email protected]))(@tiptap/[email protected]))
+      '@tiptap/extension-node-range': 3.23.5(@tiptap/[email protected](@tiptap/[email protected]))(@tiptap/[email protected])
+      '@tiptap/extension-placeholder': 3.23.5(@tiptap/[email protected](@tiptap/[email protected](@tiptap/[email protected]))(@tiptap/[email protected]))
+      '@tiptap/markdown': 3.23.5(@tiptap/[email protected](@tiptap/[email protected]))(@tiptap/[email protected])
+      '@tiptap/pm': 3.23.5
+      '@tiptap/starter-kit': 3.23.5
+      '@tiptap/suggestion': 3.23.5(@tiptap/[email protected](@tiptap/[email protected]))(@tiptap/[email protected])
+      '@tiptap/vue-3': 3.23.5(@floating-ui/[email protected])(@tiptap/[email protected](@tiptap/[email protected]))(@tiptap/[email protected])([email protected]([email protected]))
+      '@unhead/vue': 2.1.15([email protected]([email protected]))
+      '@vueuse/core': 14.3.0([email protected]([email protected]))
+      '@vueuse/integrations': 14.3.0([email protected])([email protected]([email protected]))
+      '@vueuse/shared': 14.3.0([email protected]([email protected]))
+      colortranslator: 5.0.0
+      consola: 3.4.2
+      defu: 6.1.7
+      embla-carousel-auto-height: 8.6.0([email protected])
+      embla-carousel-auto-scroll: 8.6.0([email protected])
+      embla-carousel-autoplay: 8.6.0([email protected])
+      embla-carousel-class-names: 8.6.0([email protected])
+      embla-carousel-fade: 8.6.0([email protected])
+      embla-carousel-vue: 8.6.0([email protected]([email protected]))
+      embla-carousel-wheel-gestures: 8.1.0([email protected])
+      fuse.js: 7.4.2
+      hookable: 6.1.1
+      knitwork: 1.3.0
+      magic-string: 0.30.21
+      mlly: 1.8.2
+      motion-v: 2.3.0(@vueuse/[email protected]([email protected]([email protected])))([email protected]([email protected]))
+      ohash: 2.0.11
+      pathe: 2.0.3
+      reka-ui: 2.9.10([email protected]([email protected]))
+      scule: 1.3.0
+      tailwind-merge: 3.6.0
+      tailwind-variants: 3.2.2([email protected])([email protected])
+      tailwindcss: 4.3.1
+      tinyglobby: 0.2.17
+      typescript: 6.0.3
+      ufo: 1.6.4
+      unplugin: 3.0.0
+      unplugin-auto-import: 21.0.0(@nuxt/[email protected]([email protected]))(@vueuse/[email protected]([email protected]([email protected])))
+      unplugin-vue-components: 32.1.0(@nuxt/[email protected]([email protected]))([email protected]([email protected]))
+      vaul-vue: 0.4.1([email protected]([email protected]([email protected])))([email protected]([email protected]))
+      vue-component-type-helpers: 3.3.5
+    optionalDependencies:
+      '@internationalized/date': 3.12.1
+      '@internationalized/number': 3.6.6
+      valibot: 1.4.1([email protected])
+      vue-router: 5.1.0(@vue/[email protected])([email protected]([email protected])([email protected]([email protected])))([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))([email protected]([email protected]))
+      zod: 4.4.3
+    transitivePeerDependencies:
+      - '@azure/app-configuration'
+      - '@azure/cosmos'
+      - '@azure/data-tables'
+      - '@azure/identity'
+      - '@azure/keyvault-secrets'
+      - '@azure/storage-blob'
+      - '@capacitor/preferences'
+      - '@deno/kv'
+      - '@emotion/is-prop-valid'
+      - '@netlify/blobs'
+      - '@planetscale/database'
+      - '@upstash/redis'
+      - '@vercel/blob'
+      - '@vercel/functions'
+      - '@vercel/kv'
+      - '@vue/composition-api'
+      - async-validator
+      - aws4fetch
+      - axios
+      - change-case
+      - db0
+      - drauu
+      - embla-carousel
+      - focus-trap
+      - idb-keyval
+      - ioredis
+      - jwt-decode
+      - magicast
+      - nprogress
+      - qrcode
+      - react
+      - react-dom
+      - sortablejs
+      - universal-cookie
+      - uploadthing
+      - vite
+      - vue
+
   '@nuxt/[email protected](@babel/[email protected](@babel/[email protected]))(@biomejs/[email protected])(@types/[email protected])([email protected])([email protected])([email protected](@babel/[email protected](@babel/[email protected]))(@babel/[email protected](@babel/[email protected]))(@biomejs/[email protected])(@parcel/[email protected])(@types/[email protected])(@vue/[email protected])([email protected])([email protected])([email protected]([email protected]))([email protected])([email protected])([email protected])([email protected]([email protected])([email protected]([email protected])))([email protected])([email protected]([email protected])([email protected]))([email protected])([email protected])([email protected])([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))([email protected]([email protected]))([email protected]))([email protected])([email protected]([email protected])([email protected]))([email protected])([email protected])([email protected])([email protected]([email protected]))([email protected]([email protected]))([email protected])':
     dependencies:
       '@nuxt/kit': 4.4.8([email protected])
@@ -10282,7 +10410,7 @@ snapshots:
       rollup: 4.62.0
       rollup-plugin-visualizer: 7.0.1([email protected])([email protected])
       scule: 1.3.0
-      semver: 7.8.0
+      semver: 7.8.5
       serve-placeholder: 2.0.2
       serve-static: 2.2.1
       source-map: 0.7.6
@@ -11813,7 +11941,7 @@ snapshots:
       typescript: 6.0.3
       vue-tsc: 3.3.5([email protected])
 
-  [email protected](@nuxt/[email protected].6([email protected]))([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected])):
+  [email protected](@nuxt/[email protected].8([email protected]))([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected])):
     dependencies:
       ansis: 4.3.1
       error-stack-parser-es: 1.0.5
@@ -11826,7 +11954,7 @@ snapshots:
       vite: 8.0.16(@types/[email protected])([email protected])([email protected])([email protected])([email protected])
       vite-dev-rpc: 2.0.0([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))
     optionalDependencies:
-      '@nuxt/kit': 4.4.6([email protected])
+      '@nuxt/kit': 4.4.8([email protected])
 
   [email protected]([email protected](@types/[email protected])([email protected])([email protected])([email protected])([email protected]))([email protected]([email protected])):
     dependencies: