@ap666/office-word 0.1.3 → 0.1.6

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/README.md CHANGED
@@ -11,7 +11,7 @@ npm install @ap666/office-word
11
11
  If your package manager does not auto-install peer dependencies, install the required runtime peers as well:
12
12
 
13
13
  ```bash
14
- npm install vue @tiptap/core @tiptap/vue-3 @tiptap/pm @tiptap/starter-kit @tiptap/extension-placeholder @tiptap/extension-code-block @tiptap/extension-code-block-lowlight @tiptap/extension-font-family @tiptap/extension-subscript @tiptap/extension-superscript @tiptap/extension-table @tiptap/extension-table-cell @tiptap/extension-table-header @tiptap/extension-table-row @tiptap/extension-task-item @tiptap/extension-task-list @tiptap/extension-text-style @tiptap/extension-underline lowlight
14
+ npm install vue @tiptap/core @tiptap/vue-3 @tiptap/pm @tiptap/starter-kit @tiptap/extension-placeholder @tiptap/extension-code-block @tiptap/extension-code-block-lowlight @tiptap/extension-collaboration @tiptap/extension-collaboration-caret @tiptap/extension-font-family @tiptap/extension-subscript @tiptap/extension-superscript @tiptap/extension-table @tiptap/extension-table-cell @tiptap/extension-table-header @tiptap/extension-table-row @tiptap/extension-task-item @tiptap/extension-task-list @tiptap/extension-text-style @tiptap/extension-underline @tiptap/y-tiptap lowlight y-prosemirror yjs
15
15
  ```
16
16
 
17
17
  ## Basic Use
@@ -36,7 +36,99 @@ The package imports its own styles from the entry, so no extra CSS import is req
36
36
 
37
37
  - `modelValue?: JSONContent | null`
38
38
  - `editable?: boolean`
39
+ - `mode?: 'edit' | 'preview'`
40
+ - `outlinePlacement?: 'left' | 'right'`
41
+ - `enabledExportItems?: ('pdf' | 'html' | 'image' | 'print')[] | null`
42
+ - `enabledInsertMenuItems?: ('image' | 'video' | 'table' | 'local-file' | 'columns' | 'highlight-block' | 'date' | 'code-block' | 'formula' | 'blockquote' | 'emoji' | 'link' | 'divider' | 'countdown' | 'markdown-import')[] | null`
43
+ - `enabledToolbarActions?: ('blockquote')[] | null`
39
44
  - `placeholder?: string`
45
+ - `collaboration?: RichTextEditorCollaborationOptions | null`
46
+
47
+ When these whitelist props are omitted, all built-in options stay enabled. Once you pass a list, only the listed items remain visible and usable.
48
+
49
+ ```vue
50
+ <RichTextEditor
51
+ v-model="content"
52
+ :enabled-export-items="['html', 'image']"
53
+ :enabled-insert-menu-items="['image', 'local-file', 'blockquote']"
54
+ :enabled-toolbar-actions="['blockquote']"
55
+ />
56
+ ```
57
+
58
+ ## Preview Mode
59
+
60
+ Use `mode="preview"` to switch the component into a read-only preview shell. In preview mode, the toolbar is hidden, editing is disabled, and the outline can be placed on either side.
61
+
62
+ ```vue
63
+ <template>
64
+ <RichTextEditor
65
+ v-model="content"
66
+ mode="preview"
67
+ outline-placement="right"
68
+ />
69
+ </template>
70
+ ```
71
+
72
+ On narrow screens, preview mode automatically scales the page canvas down so the document stays readable on phones.
73
+
74
+ ## Collaboration
75
+
76
+ The same component supports both normal single-user editing and optional Yjs collaboration.
77
+
78
+ ```vue
79
+ <script setup lang="ts">
80
+ import { ref } from 'vue'
81
+ import * as Y from 'yjs'
82
+ import { WebsocketProvider } from 'y-websocket'
83
+ import type { JSONContent } from '@tiptap/core'
84
+ import { RichTextEditor } from '@ap666/office-word'
85
+
86
+ const ydoc = new Y.Doc()
87
+ const provider = new WebsocketProvider('ws://localhost:1234', 'office-word-demo', ydoc)
88
+ const content = ref<JSONContent | null>(null)
89
+ </script>
90
+
91
+ <template>
92
+ <RichTextEditor
93
+ v-model="content"
94
+ :collaboration="{
95
+ document: ydoc,
96
+ field: 'content',
97
+ provider,
98
+ user: {
99
+ name: '张三',
100
+ color: '#3b82f6',
101
+ },
102
+ }"
103
+ />
104
+ </template>
105
+ ```
106
+
107
+ In collaboration mode, the shared Yjs fragment becomes the source of truth. The component still emits JSON updates, but external `modelValue` changes are not pushed back into the editor. If you want remote cursors, also install `y-websocket` in the host project and pass `provider + user`.
108
+
109
+ Do not use `modelValue` as the initial seed source for a collaborative room. Seed the Yjs document before mounting the editor if the room needs default content.
110
+
111
+ ### Included Yjs Server Example
112
+
113
+ The published package also includes a minimal collaboration server under `yjs/`.
114
+
115
+ ```bash
116
+ cd node_modules/@ap666/office-word/yjs
117
+ npm install
118
+ npm run start
119
+ ```
120
+
121
+ Default address is `ws://0.0.0.0:1234`.
122
+
123
+ Use the same websocket address and room name on every client:
124
+
125
+ ```ts
126
+ import * as Y from 'yjs'
127
+ import { WebsocketProvider } from 'y-websocket'
128
+
129
+ const ydoc = new Y.Doc()
130
+ const provider = new WebsocketProvider('ws://127.0.0.1:1234', 'office-word-demo', ydoc)
131
+ ```
40
132
 
41
133
  ## Instance API
42
134
 
@@ -64,9 +156,29 @@ Available methods:
64
156
  - `insertImage(payload | payload[]): boolean`
65
157
  - `insertVideo(payload): boolean`
66
158
  - `insertFile(payload): boolean`
159
+ - `insertLocalFile(payload): boolean`
160
+ - `openLocalFilePicker(): void`
67
161
  - `focus(): void`
68
162
  - `getJSON(): JSONContent | null`
69
163
 
164
+ ## Local File Block
165
+
166
+ The insert menu now supports `Local File`, and the component instance also exposes local-file insertion APIs.
167
+
168
+ ```ts
169
+ editorRef.value?.insertLocalFile({
170
+ url: 'https://cdn.example.com/files/demo.txt',
171
+ name: 'demo.txt',
172
+ size: 2048,
173
+ mimeType: 'text/plain',
174
+ })
175
+ ```
176
+
177
+ Listen for local file events from the component:
178
+
179
+ - `@local-file-upload`: emitted after a local file is selected from the editor picker and inserted
180
+ - `@local-file-download`: emitted when the file card download button is clicked
181
+
70
182
  ## Export Example
71
183
 
72
184
  ```ts
@@ -167,6 +279,9 @@ async function uploadFile(file: File) {
167
279
 
168
280
  ```ts
169
281
  import type {
282
+ RichTextEditorCollaborationProvider,
283
+ RichTextEditorCollaborationUser,
284
+ RichTextEditorCollaborationOptions,
170
285
  RichTextEditorFilePayload,
171
286
  RichTextEditorImageExportOptions,
172
287
  RichTextEditorImagePayload,
@@ -178,3 +293,4 @@ import type {
178
293
  ## Package Docs
179
294
 
180
295
  - usage guide: `docs/usage.md`
296
+ - bundled Yjs server example: `yjs/README.md`
@@ -0,0 +1,3 @@
1
+ import { NodeViewProps } from '@tiptap/vue-3';
2
+ declare const _default: import('vue').DefineComponent<NodeViewProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<NodeViewProps> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
3
+ export default _default;
@@ -1,5 +1,6 @@
1
1
  type __VLS_Props = {
2
2
  open: boolean;
3
+ placement: 'left' | 'right';
3
4
  items: Array<{
4
5
  pos: number;
5
6
  level: number;
@@ -1,5 +1,5 @@
1
1
  import { JSONContent } from '@tiptap/core';
2
- import { RichTextEditorFilePayload, RichTextEditorImageExportOptions, RichTextEditorImagePayload, RichTextEditorProps, RichTextEditorVideoPayload } from '../types';
2
+ import { RichTextEditorFilePayload, RichTextEditorImageExportOptions, RichTextEditorImagePayload, RichTextEditorLocalFilePayload, RichTextEditorProps, RichTextEditorVideoPayload } from '../types';
3
3
  declare const _default: import('vue').DefineComponent<RichTextEditorProps, {
4
4
  exportPdf: () => Promise<Blob | null>;
5
5
  exportImage: (options?: RichTextEditorImageExportOptions) => Promise<Blob | null>;
@@ -7,18 +7,26 @@ declare const _default: import('vue').DefineComponent<RichTextEditorProps, {
7
7
  insertImage: (payload: RichTextEditorImagePayload | RichTextEditorImagePayload[]) => boolean;
8
8
  insertVideo: (payload: RichTextEditorVideoPayload) => boolean;
9
9
  insertFile: (payload: RichTextEditorFilePayload) => boolean;
10
+ insertLocalFile: (payload: RichTextEditorLocalFilePayload) => boolean;
11
+ openLocalFilePicker: () => void;
10
12
  focus: () => void;
11
13
  getJSON: () => JSONContent | null;
12
14
  }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
13
15
  change: (value: JSONContent) => any;
14
16
  "update:modelValue": (value: JSONContent) => any;
17
+ "local-file-upload": (value: RichTextEditorLocalFilePayload) => any;
18
+ "local-file-download": (value: RichTextEditorLocalFilePayload) => any;
15
19
  }, string, import('vue').PublicProps, Readonly<RichTextEditorProps> & Readonly<{
16
20
  onChange?: ((value: JSONContent) => any) | undefined;
17
21
  "onUpdate:modelValue"?: ((value: JSONContent) => any) | undefined;
22
+ "onLocal-file-upload"?: ((value: RichTextEditorLocalFilePayload) => any) | undefined;
23
+ "onLocal-file-download"?: ((value: RichTextEditorLocalFilePayload) => any) | undefined;
18
24
  }>, {
19
25
  placeholder: string;
26
+ mode: "edit" | "preview";
20
27
  editable: boolean;
21
28
  modelValue: JSONContent | null;
29
+ outlinePlacement: "left" | "right";
22
30
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
23
31
  rootRef: HTMLDivElement;
24
32
  insertMenuRef: HTMLDivElement;
@@ -47,5 +55,6 @@ declare const _default: import('vue').DefineComponent<RichTextEditorProps, {
47
55
  countdownBubbleMenuRef: HTMLDivElement;
48
56
  countdownBubbleEditButtonRef: HTMLButtonElement;
49
57
  markdownImportInputRef: HTMLInputElement;
58
+ localFileInputRef: HTMLInputElement;
50
59
  }, HTMLDivElement>;
51
60
  export default _default;
@@ -1,8 +1,16 @@
1
1
  import { JSONContent } from '@tiptap/core';
2
+ import { RichTextEditorCollaborationOptions } from '../types';
2
3
  type UseRichTextEditorOptions = {
3
4
  content: JSONContent;
4
5
  editable: boolean;
5
6
  placeholder: string;
7
+ collaboration?: RichTextEditorCollaborationOptions | null;
8
+ onLocalFileDownload?: (payload: {
9
+ url: string;
10
+ name: string;
11
+ size?: number;
12
+ mimeType?: string;
13
+ }) => void;
6
14
  onUpdate: (value: JSONContent) => void;
7
15
  };
8
16
  export declare function useRichTextEditor(options: UseRichTextEditorOptions): import('vue').ShallowRef<import('@tiptap/vue-3').Editor | undefined, import('@tiptap/vue-3').Editor | undefined>;
@@ -0,0 +1,2 @@
1
+ import { Node } from '@tiptap/core';
2
+ export declare const LocalFileBlock: Node<any, any>;
package/dist/index.d.ts CHANGED
@@ -4,5 +4,5 @@ import { default as RichTextEditor } from './components/RichTextEditor.vue';
4
4
  import { default as ScrollArea } from './components/ScrollArea.vue';
5
5
  export { OfficeColorIcon, OfficeIcon, RichTextEditor, ScrollArea };
6
6
  export { colorIconNames, monoIconNames } from './icons';
7
- export type { OfficeColorIconProps, OfficeIconProps, RichTextEditorFilePayload, RichTextEditorImageExportOptions, RichTextEditorImagePayload, RichTextEditorInstance, RichTextEditorProps, RichTextEditorVideoPayload, } from './types';
7
+ export type { OfficeColorIconProps, OfficeIconProps, RichTextEditorCollaborationAwareness, RichTextEditorCollaborationDocument, RichTextEditorCollaborationOptions, RichTextEditorCollaborationProvider, RichTextEditorCollaborationUser, RichTextEditorFilePayload, RichTextEditorExportItemKey, RichTextEditorImageExportOptions, RichTextEditorImagePayload, RichTextEditorInstance, RichTextEditorInsertMenuItemKey, RichTextEditorLocalFilePayload, RichTextEditorProps, RichTextEditorToolbarActionKey, RichTextEditorVideoPayload, } from './types';
8
8
  export default RichTextEditor;