@cou.sh/nuxt 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": "^3.0.0 || ^4.0.0"
6
6
  },
7
- "version": "1.0.1",
7
+ "version": "1.0.2",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -71,8 +71,7 @@ const module$1 = defineNuxtModule({
71
71
  nuxt.options.build.transpile = nuxt.options.build.transpile || [];
72
72
  nuxt.options.build.transpile.push("@rgby/collab-core", "@rgby/collab-vue");
73
73
  addPlugin({
74
- src: resolver.resolve("./runtime/plugin"),
75
- mode: "client"
74
+ src: resolver.resolve("./runtime/plugin")
76
75
  });
77
76
  addComponentsDir({
78
77
  path: resolver.resolve("./runtime/components"),
@@ -1,4 +1,18 @@
1
1
  <script setup>
2
+ import { computed, watch, useTemplateRef } from "vue";
3
+ import { useCollabClient, useAuth, useSyncedMap } from "@rgby/collab-vue";
4
+ import { useCollabStatus } from "../composables/useCollabStatus";
5
+ import {
6
+ useEditorCollaboration,
7
+ COLORS,
8
+ getRandomColor
9
+ } from "../composables/useEditorCollaboration";
10
+ import { useEditorCompletion } from "../composables/useEditorCompletion";
11
+ import { useEditorDragHandle } from "../composables/useEditorDragHandle";
12
+ import { useEditorEmojis } from "../composables/useEditorEmojis";
13
+ import { useEditorMentions } from "../composables/useEditorMentions";
14
+ import { useEditorSuggestions } from "../composables/useEditorSuggestions";
15
+ import { useEditorToolbar } from "../composables/useEditorToolbar";
2
16
  import { Emoji } from "@tiptap/extension-emoji";
3
17
  import { TaskList, TaskItem } from "@tiptap/extension-list";
4
18
  import { TableKit } from "@tiptap/extension-table";
@@ -32,7 +46,11 @@ const user = computed(() => {
32
46
  };
33
47
  });
34
48
  const editorRef = useTemplateRef("editorRef");
35
- const { extension: Completion, handlers: aiHandlers, isLoading: aiLoading } = useEditorCompletion(editorRef);
49
+ const {
50
+ extension: Completion,
51
+ handlers: aiHandlers,
52
+ isLoading: aiLoading
53
+ } = useEditorCompletion(editorRef);
36
54
  const {
37
55
  enabled: collaborationEnabled,
38
56
  ready: collaborationReady,
@@ -51,19 +69,27 @@ const {
51
69
  color: user.value.color
52
70
  }
53
71
  });
54
- watch([collaborationReady, provider], ([ready, prov]) => {
55
- if (ready && prov) {
56
- emit("ready", prov);
57
- }
58
- }, { immediate: true });
59
- watch(user, (newUser) => {
60
- updateUser({
61
- name: newUser.name,
62
- color: newUser.color,
63
- avatar: newUser.avatar
64
- // Pass avatar if supported by CollaborationUser
65
- });
66
- }, { deep: true });
72
+ watch(
73
+ [collaborationReady, provider],
74
+ ([ready, prov]) => {
75
+ if (ready && prov) {
76
+ emit("ready", prov);
77
+ }
78
+ },
79
+ { immediate: true }
80
+ );
81
+ watch(
82
+ user,
83
+ (newUser) => {
84
+ updateUser({
85
+ name: newUser.name,
86
+ color: newUser.color,
87
+ avatar: newUser.avatar
88
+ // Pass avatar if supported by CollaborationUser
89
+ });
90
+ },
91
+ { deep: true }
92
+ );
67
93
  const customHandlers = {
68
94
  imageUpload: {
69
95
  canExecute: (editor) => editor.can().insertContent({ type: "imageUpload" }),
@@ -120,8 +146,14 @@ const customHandlers = {
120
146
  isDisabled: void 0
121
147
  },
122
148
  scrollAreaWidget: {
123
- canExecute: (editor) => editor.can().insertContent({ type: "scrollAreaWidget", content: [{ type: "paragraph" }] }),
124
- execute: (editor) => editor.chain().focus().insertContent({ type: "scrollAreaWidget", content: [{ type: "paragraph" }] }),
149
+ canExecute: (editor) => editor.can().insertContent({
150
+ type: "scrollAreaWidget",
151
+ content: [{ type: "paragraph" }]
152
+ }),
153
+ execute: (editor) => editor.chain().focus().insertContent({
154
+ type: "scrollAreaWidget",
155
+ content: [{ type: "paragraph" }]
156
+ }),
125
157
  isActive: (editor) => editor.isActive("scrollAreaWidget"),
126
158
  isDisabled: void 0
127
159
  },
@@ -136,8 +168,16 @@ const customHandlers = {
136
168
  execute: (editor) => editor.chain().focus().insertContent({
137
169
  type: "tabsWidget",
138
170
  content: [
139
- { type: "tabPanel", attrs: { label: "Tab 1" }, content: [{ type: "paragraph" }] },
140
- { type: "tabPanel", attrs: { label: "Tab 2" }, content: [{ type: "paragraph" }] }
171
+ {
172
+ type: "tabPanel",
173
+ attrs: { label: "Tab 1" },
174
+ content: [{ type: "paragraph" }]
175
+ },
176
+ {
177
+ type: "tabPanel",
178
+ attrs: { label: "Tab 2" },
179
+ content: [{ type: "paragraph" }]
180
+ }
141
181
  ]
142
182
  }),
143
183
  isActive: (editor) => editor.isActive("tabsWidget"),
@@ -149,7 +189,12 @@ const { items: emojiItems } = useEditorEmojis();
149
189
  const { items: mentionItems } = useEditorMentions(connectedUsers);
150
190
  const { items: suggestionItems } = useEditorSuggestions(customHandlers);
151
191
  const { getItems: getDragHandleItems, onNodeChange } = useEditorDragHandle(customHandlers);
152
- const { toolbarItems, bubbleToolbarItems, getImageToolbarItems, getTableToolbarItems } = useEditorToolbar(customHandlers, { aiLoading });
192
+ const {
193
+ toolbarItems,
194
+ bubbleToolbarItems,
195
+ getImageToolbarItems,
196
+ getTableToolbarItems
197
+ } = useEditorToolbar(customHandlers, { aiLoading });
153
198
  const metadata = useSyncedMap(doc, "metadata");
154
199
  const {
155
200
  label: statusLabel,
@@ -218,111 +263,112 @@ const extensions = computed(() => [
218
263
  </template>
219
264
 
220
265
  <template #body>
266
+ <UEditorToolbar
267
+ v-if="editorRef?.editor"
268
+ :editor="editorRef.editor"
269
+ :items="toolbarItems"
270
+ />
271
+
272
+ <UEditor
273
+ v-if="collaborationReady"
274
+ ref="editorRef"
275
+ v-slot="{ editor, handlers }"
276
+ content-type="markdown"
277
+ :extensions="extensions"
278
+ :starter-kit="{ history: false, undoRedo: false, codeBlock: false }"
279
+ :handlers="customHandlers"
280
+ autofocus
281
+ placeholder="Write, type '/' for commands..."
282
+ class="min-h-screen"
283
+ @create="onCreate"
284
+ >
285
+ <UEditorToolbar
286
+ :editor="editor"
287
+ :items="bubbleToolbarItems"
288
+ layout="bubble"
289
+ :should-show="
290
+ ({ editor: editor2, view, state }) => {
291
+ if (editor2.isActive('imageUpload') || editor2.isActive('image') || state.selection instanceof CellSelection) {
292
+ return false;
293
+ }
294
+ const { selection } = state;
295
+ return view.hasFocus() && !selection.empty;
296
+ }
297
+ "
298
+ >
299
+ <template #link>
300
+ <CollabEditorLinkPopover :editor="editor" />
301
+ </template>
302
+ </UEditorToolbar>
303
+
221
304
  <UEditorToolbar
222
- v-if="editorRef?.editor"
223
- :editor="editorRef.editor"
224
- :items="toolbarItems"
305
+ :editor="editor"
306
+ :items="getImageToolbarItems(editor)"
307
+ layout="bubble"
308
+ :should-show="
309
+ ({ editor: editor2, view }) => {
310
+ return editor2.isActive('image') && view.hasFocus();
311
+ }
312
+ "
225
313
  />
226
314
 
227
- <UEditor
228
- v-if="collaborationReady"
229
- ref="editorRef"
230
- v-slot="{ editor, handlers }"
231
- content-type="markdown"
232
- :extensions="extensions"
233
- :starter-kit="{ history: false, undoRedo: false, codeBlock: false }"
234
- :handlers="customHandlers"
235
- autofocus
236
- placeholder="Write, type '/' for commands..."
237
- class="min-h-screen"
238
- @create="onCreate"
239
- >
240
- <UEditorToolbar
241
- :editor="editor"
242
- :items="bubbleToolbarItems"
243
- layout="bubble"
244
- :should-show="({ editor: editor2, view, state }) => {
245
- if (editor2.isActive('imageUpload') || editor2.isActive('image') || state.selection instanceof CellSelection) {
246
- return false;
315
+ <UEditorToolbar
316
+ :editor="editor"
317
+ :items="getTableToolbarItems(editor)"
318
+ layout="bubble"
319
+ :should-show="
320
+ ({ editor: editor2, view }) => {
321
+ return editor2.state.selection instanceof CellSelection && view.hasFocus();
247
322
  }
248
- const { selection } = state;
249
- return view.hasFocus() && !selection.empty;
250
- }"
251
- >
252
- <template #link>
253
- <CollabEditorLinkPopover :editor="editor" />
254
- </template>
255
- </UEditorToolbar>
323
+ "
324
+ />
256
325
 
257
- <UEditorToolbar
258
- :editor="editor"
259
- :items="getImageToolbarItems(editor)"
260
- layout="bubble"
261
- :should-show="({ editor: editor2, view }) => {
262
- return editor2.isActive('image') && view.hasFocus();
263
- }"
264
- />
326
+ <UEditorDragHandle
327
+ v-slot="{ ui, onClick }"
328
+ :editor="editor"
329
+ @node-change="onNodeChange"
330
+ >
331
+ <UButton
332
+ icon="i-lucide-plus"
333
+ color="neutral"
334
+ variant="ghost"
335
+ size="sm"
336
+ :class="ui.handle()"
337
+ @click="
338
+ (e) => {
339
+ e.stopPropagation();
340
+ const node = onClick();
341
+ handlers.suggestion?.execute(editor, { pos: node?.pos }).run();
342
+ }
343
+ "
344
+ />
265
345
 
266
- <UEditorToolbar
267
- :editor="editor"
268
- :items="getTableToolbarItems(editor)"
269
- layout="bubble"
270
- :should-show="({ editor: editor2, view }) => {
271
- return editor2.state.selection instanceof CellSelection && view.hasFocus();
272
- }"
346
+ <UDropdownMenu
347
+ v-slot="{ open }"
348
+ :modal="false"
349
+ :items="getDragHandleItems(editor)"
350
+ :content="{ side: 'left' }"
351
+ :ui="{ content: 'w-48', label: 'text-xs' }"
352
+ @update:open="
353
+ editor.chain().setMeta('lockDragHandle', $event).run()
354
+ "
355
+ >
356
+ <UButton
357
+ color="neutral"
358
+ variant="ghost"
359
+ active-variant="soft"
360
+ size="sm"
361
+ icon="i-lucide-grip-vertical"
362
+ :active="open"
363
+ :class="ui.handle()"
273
364
  />
365
+ </UDropdownMenu>
366
+ </UEditorDragHandle>
274
367
 
275
- <UEditorDragHandle
276
- v-slot="{ ui, onClick }"
277
- :editor="editor"
278
- @node-change="onNodeChange"
279
- >
280
- <UButton
281
- icon="i-lucide-plus"
282
- color="neutral"
283
- variant="ghost"
284
- size="sm"
285
- :class="ui.handle()"
286
- @click="(e) => {
287
- e.stopPropagation();
288
- const node = onClick();
289
- handlers.suggestion?.execute(editor, { pos: node?.pos }).run();
290
- }"
291
- />
292
-
293
- <UDropdownMenu
294
- v-slot="{ open }"
295
- :modal="false"
296
- :items="getDragHandleItems(editor)"
297
- :content="{ side: 'left' }"
298
- :ui="{ content: 'w-48', label: 'text-xs' }"
299
- @update:open="editor.chain().setMeta('lockDragHandle', $event).run()"
300
- >
301
- <UButton
302
- color="neutral"
303
- variant="ghost"
304
- active-variant="soft"
305
- size="sm"
306
- icon="i-lucide-grip-vertical"
307
- :active="open"
308
- :class="ui.handle()"
309
- />
310
- </UDropdownMenu>
311
- </UEditorDragHandle>
312
-
313
- <UEditorEmojiMenu
314
- :editor="editor"
315
- :items="emojiItems"
316
- />
317
- <UEditorMentionMenu
318
- :editor="editor"
319
- :items="mentionItems"
320
- />
321
- <UEditorSuggestionMenu
322
- :editor="editor"
323
- :items="suggestionItems"
324
- />
325
- </UEditor>
368
+ <UEditorEmojiMenu :editor="editor" :items="emojiItems" />
369
+ <UEditorMentionMenu :editor="editor" :items="mentionItems" />
370
+ <UEditorSuggestionMenu :editor="editor" :items="suggestionItems" />
371
+ </UEditor>
326
372
  </template>
327
373
  </UDashboardPanel>
328
374
  </template>
@@ -5,6 +5,6 @@ import { type Ref } from "vue";
5
5
  */
6
6
  export declare function useCollabStatus(status: Ref<"disconnected" | "connecting" | "connected">, synced: Ref<boolean>): {
7
7
  label: import("vue").ComputedRef<"Saved" | "Syncing" | "Connecting" | "Offline">;
8
- color: import("vue").ComputedRef<"success" | "info" | "warning" | "error">;
8
+ color: import("vue").ComputedRef<"error" | "success" | "info" | "warning">;
9
9
  icon: import("vue").ComputedRef<"i-lucide-cloud-check" | "i-lucide-cloud-upload" | "i-lucide-cloud" | "i-lucide-cloud-off">;
10
10
  };
@@ -1,7 +1,6 @@
1
- import { CollabClient } from "@rgby/collab-core";
2
1
  declare const _default: import("#app").Plugin<{
3
- collabClient: CollabClient;
2
+ collabClient: any;
4
3
  }> & import("#app").ObjectPlugin<{
5
- collabClient: CollabClient;
4
+ collabClient: any;
6
5
  }>;
7
6
  export default _default;
@@ -14,20 +14,43 @@ export default defineNuxtPlugin({
14
14
  refreshBuffer: config.auth.refreshBuffer ?? 3600
15
15
  }
16
16
  } : {};
17
- const client = new CollabClient({
18
- baseUrl: config.baseUrl || "http://localhost:8000",
19
- ...authConfig,
20
- offline: {
21
- enablePersistence: config.offline?.enablePersistence ?? true,
22
- enableUploadQueue: config.offline?.enableUploadQueue ?? true,
23
- persistenceDbName: config.offline?.persistenceDbName ?? "collab"
24
- }
25
- });
26
- if (config.debug) {
27
- console.log("[Collab] Client initialized", {
28
- baseUrl: config.baseUrl,
29
- auth: config.auth?.mode
17
+ let client;
18
+ if (process.server) {
19
+ console.log("[Collab Plugin] Running on server - using mock client");
20
+ client = {
21
+ authManager: {
22
+ getSession: () => null,
23
+ subscribe: () => () => {
24
+ },
25
+ getToken: () => null
26
+ },
27
+ login: () => Promise.reject(new Error("Cannot login on server")),
28
+ signup: () => Promise.reject(new Error("Cannot signup on server")),
29
+ logout: () => Promise.resolve(),
30
+ getProvider: () => {
31
+ throw new Error("Cannot get provider on server");
32
+ },
33
+ spaces: { list: async () => [], get: async () => ({}), create: async () => ({}) },
34
+ documents: { list: async () => ({ items: [] }), create: async () => ({}) },
35
+ comments: { list: async () => ({ threads: [] }), create: async () => ({}) }
36
+ };
37
+ } else {
38
+ console.log("[Collab Plugin] Running on client - initializing real client");
39
+ client = new CollabClient({
40
+ baseUrl: config.baseUrl || "http://localhost:8000",
41
+ ...authConfig,
42
+ offline: {
43
+ enablePersistence: config.offline?.enablePersistence ?? true,
44
+ enableUploadQueue: config.offline?.enableUploadQueue ?? true,
45
+ persistenceDbName: config.offline?.persistenceDbName ?? "collab"
46
+ }
30
47
  });
48
+ if (config.debug) {
49
+ console.log("[Collab] Client initialized", {
50
+ baseUrl: config.baseUrl,
51
+ auth: config.auth?.mode
52
+ });
53
+ }
31
54
  }
32
55
  nuxtApp.vueApp.provide(CollabClientKey, client);
33
56
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cou.sh/nuxt",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "CoUnit Nuxt Module",
5
5
  "repository": "@cou.sh/nuxt",
6
6
  "private": false,
@@ -31,7 +31,7 @@
31
31
  "dev": "NODE_OPTIONS='--max-old-space-size=8192' bun run dev:prepare && NODE_OPTIONS='--max-old-space-size=8192' nuxt dev playground",
32
32
  "dev:build": "NODE_OPTIONS='--max-old-space-size=8192' nuxt build playground",
33
33
  "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxt prepare playground",
34
- "release": "bun run prepack && changelogen --release && npm publish && git push --follow-tags",
34
+ "release": "bun run prepack && changelogen --release && npm publish --access=public && git push --follow-tags",
35
35
  "lint": "eslint .",
36
36
  "test": "vitest run",
37
37
  "test:watch": "vitest watch",