slate-vue3 0.3.2 → 0.3.4
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 +69 -11
- package/dist/slate-yjs/hooks/useRemoteCursorOverlayPositions.d.ts +1 -2
- package/dist/slate-yjs/hooks/useRemoteCursorStates.d.ts +2 -0
- package/dist/slate-yjs/hooks/useUnsetCursorPositionOnBlur.d.ts +2 -1
- package/dist/slate-yjs/index.d.ts +3 -3
- package/dist/yjs.js +14 -14
- package/package.json +1 -1
- package/dist/slate-yjs/hooks/useRemoteCursorStateStore.d.ts +0 -5
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
8
|
<a href="https://unpkg.com/slate-vue3/dist/index.js">
|
|
9
|
-
<img src="
|
|
9
|
+
<img src="https://packagephobia.com/badge?p=slate-vue3">
|
|
10
10
|
</a>
|
|
11
11
|
<a href="https://join.slack.com/t/slate-js/shared_invite/zt-f8t986ip-7dA1DyiqPpzootz1snKXkw">
|
|
12
12
|
<img src="https://img.shields.io/badge/slack-slate--js-brightgreen.svg?logo=slack">
|
|
@@ -17,22 +17,24 @@
|
|
|
17
17
|
</p>
|
|
18
18
|
<br/>
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
### Why use it?
|
|
21
21
|
|
|
22
22
|
1. :sparkles: Highly customizable features, use slate core at the bottom level
|
|
23
|
-
2. :zap: Use vue3 for high-performance rendering, and later connect to vapor mode
|
|
24
|
-
3. :coffee: The latest version of the core, design tends to be stable
|
|
23
|
+
2. :zap: Use `vue3` for high-performance rendering, and later connect to vapor mode
|
|
24
|
+
3. :coffee: The **latest** version of the core, design tends to be stable
|
|
25
25
|
4. :point_right: Check out the [**live demo**](https://guan-erjia.github.io/slate-vue3/examples/rich-text) of all of the examples
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
<br />
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
### How to use?
|
|
30
|
+
|
|
31
|
+
#### 1. Install slate-vue3
|
|
30
32
|
|
|
31
33
|
```sh
|
|
32
34
|
npm install slate-vue3
|
|
33
35
|
```
|
|
34
36
|
|
|
35
|
-
|
|
37
|
+
#### 2. Now, you can use it in vue-sfc :point_right: [**live demo**](https://guan-erjia.github.io/slate-vue3/examples/rich-text)
|
|
36
38
|
|
|
37
39
|
```vue
|
|
38
40
|
<script setup lang="ts">
|
|
@@ -71,16 +73,72 @@ editor.children = initialValue;
|
|
|
71
73
|
</template>
|
|
72
74
|
```
|
|
73
75
|
|
|
74
|
-
|
|
76
|
+
<br />
|
|
77
|
+
|
|
78
|
+
### Examples
|
|
79
|
+
|
|
80
|
+
To get a sense for how you might use Slate, check out a few of the examples:
|
|
81
|
+
|
|
82
|
+
- [**Rich text**](https://guan-erjia.github.io/slate-vue3/examples/rich-text) — the features you'd expect from a basic editor.
|
|
83
|
+
- [**Collaborative editing**](https://guan-erjia.github.io/slate-vue3/examples/remote-cursor) — to achieve collaborative editing and cursor.
|
|
84
|
+
- [**Markdown preview**](https://guan-erjia.github.io/slate-vue3/examples/markdown-preview) — to add key handlers for Markdown-like shortcuts.
|
|
85
|
+
- [**Inlines**](https://guan-erjia.github.io/slate-vue3/examples/inlines) — wrap text in inline nodes with associated data.
|
|
86
|
+
- [**Images**](https://guan-erjia.github.io/slate-vue3/examples/images) — to use void (text-less) nodes to add images.
|
|
87
|
+
- [**Hovering toolbar**](https://guan-erjia.github.io/slate-vue3/examples/hovering-toolbar) — a hovering toolbar can be implemented.
|
|
88
|
+
- [**Tables**](https://guan-erjia.github.io/slate-vue3/examples/tables) — to nest blocks to render more advanced components.
|
|
89
|
+
- [**Paste HTML**](https://guan-erjia.github.io/slate-vue3/examples/paste-html) — to use an HTML serializer to handle pasted HTML.
|
|
90
|
+
- [**Mentions**](https://guan-erjia.github.io/slate-vue3/examples/mentions) — to use inline void nodes for simple @-mentions.
|
|
91
|
+
- [**See all the examples...**](https://guan-erjia.github.io/slate-vue3)
|
|
92
|
+
|
|
93
|
+
If you have an idea for an example that shows a common use case, pull request it!
|
|
94
|
+
|
|
95
|
+
<br/>
|
|
96
|
+
|
|
97
|
+
### Documentation
|
|
98
|
+
|
|
99
|
+
This [**`document`**](https://guan-erjia.github.io/slate-vue3) serves only as a supplement to the slate document and mainly provides case studies and differences between `slate-vue3` and `slate-react`
|
|
100
|
+
|
|
101
|
+
If you're using `slate` for the first time, check out the [Getting Started](https://docs.slatejs.org/walkthroughs/01-installing-slate) walkthroughs and the [Concepts](http://docs.slatejs.org/concepts) to familiarize yourself with slate's architecture and mental models.
|
|
102
|
+
|
|
103
|
+
- [**Walkthroughs**](https://docs.slatejs.org/walkthroughs/01-installing-slate)
|
|
104
|
+
- [**Concepts**](https://docs.slatejs.org/concepts)
|
|
105
|
+
- [**FAQ**](https://docs.slatejs.org/general/faq)
|
|
106
|
+
- [**Resources**](https://docs.slatejs.org/general/resources)
|
|
107
|
+
|
|
108
|
+
<br/>
|
|
109
|
+
|
|
110
|
+
### Sub packages
|
|
111
|
+
|
|
112
|
+
Due to the complexity of maintaining multiple packages and the lack of reusability of sub packages in other frameworks, slate-vue3 does not use workspace and only performs sub packaging during packaging
|
|
113
|
+
|
|
114
|
+
| **Package** | **Version** | **Description** |
|
|
115
|
+
| :------------------------------------------------------- | --------------------------------------------------------------------------------: | :----------------------------------------------- |
|
|
116
|
+
| [`slate-vue3/core`](./packages/slate) |  | slate's core data model logic. |
|
|
117
|
+
| [`slate-vue3/dom`](./packages/slate) |  | DOM implementation of slate |
|
|
118
|
+
| [`slate-vue3/history`](./packages/slate-history) |  | a plugin that adds undo/redo history to slate. |
|
|
119
|
+
| [`slate-vue3/hyperscript`](./packages/slate-hyperscript) |  | a hyperscript tool to write JSX slate documents! |
|
|
120
|
+
| [`slate-vue3/yjs`](./packages/slate-yjs) |  | integration of `slate-yjs` |
|
|
121
|
+
|
|
122
|
+
<br />
|
|
123
|
+
|
|
124
|
+
### Contributing!
|
|
125
|
+
|
|
126
|
+
Welcome to provide suggestions on the issue, it would be even better if **`PR`** could be mentioned along with it
|
|
127
|
+
|
|
128
|
+
slate-vue3 is [MIT-licensed](./License.md).
|
|
129
|
+
|
|
130
|
+
<br/>
|
|
131
|
+
|
|
132
|
+
### FAQ
|
|
75
133
|
|
|
76
|
-
|
|
134
|
+
##### 1. Why do I have to pass renderFunction into <Slate /> component ?
|
|
77
135
|
|
|
78
136
|
This ensures that your rich text is as expected, and slate-vue3 provides some default rendering functions, you can directly use the default rendering behavior
|
|
79
137
|
|
|
80
|
-
|
|
138
|
+
##### 2. Can I use jsx in slate-vue3 ?
|
|
81
139
|
|
|
82
140
|
Of coures yes, but we do not recommend it unless you have already configured jsx in the project, as a branch, using the h function directly is already simple enough
|
|
83
141
|
|
|
84
|
-
|
|
142
|
+
##### 3. Why do rendering functions not use vue components ?
|
|
85
143
|
|
|
86
144
|
Vue uses lazy updates, rendering with components generates additional state, which can cause unexpected results during updates, it would be better to use functions as branches directly
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Ref } from 'vue';
|
|
2
2
|
import { BaseRange, NodeMatch, Text } from '../../slate/index.ts';
|
|
3
|
-
import { toRawWeakMap as WeakMap } from '../../share-tools/index.ts';
|
|
4
3
|
import { JsonObject } from '@liveblocks/client';
|
|
5
4
|
import { CursorState } from '../plugins/withCursors';
|
|
6
5
|
import { CaretPosition, SelectionRect } from './utils';
|
|
@@ -9,4 +8,4 @@ export type CursorOverlayData<TCursorData extends JsonObject> = CursorState<TCur
|
|
|
9
8
|
caretPosition: CaretPosition | null;
|
|
10
9
|
selectionRects: SelectionRect[];
|
|
11
10
|
};
|
|
12
|
-
export declare function useRemoteCursorOverlayPositions<TCursorData extends JsonObject, TContainer extends HTMLElement = HTMLDivElement>(containerRef: Ref<TContainer>, shouldGenerateOverlay?: NodeMatch<Text>): readonly [import('vue').ComputedRef<CursorOverlayData<TCursorData>[]>, () =>
|
|
11
|
+
export declare function useRemoteCursorOverlayPositions<TCursorData extends JsonObject, TContainer extends HTMLElement = HTMLDivElement>(containerRef: Ref<TContainer>, shouldGenerateOverlay?: NodeMatch<Text>): readonly [import('vue').ComputedRef<CursorOverlayData<TCursorData>[]>, () => void];
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { Ref } from 'vue';
|
|
2
2
|
import { JsonObject } from '@liveblocks/client';
|
|
3
|
+
import { Store } from './utils';
|
|
3
4
|
import { CursorState } from '../plugins/withCursors';
|
|
5
|
+
export type CursorStore<TCursorData extends JsonObject = JsonObject> = Store<Record<string, CursorState<TCursorData>>>;
|
|
4
6
|
export declare function useRemoteCursorStates<TCursorData extends JsonObject = JsonObject>(): Ref<Record<string, CursorState<TCursorData>>>;
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { JsonObject } from '@liveblocks/client';
|
|
2
|
+
export declare function useUnsetCursorPositionOnBlur<TCursor extends JsonObject>(): void;
|
|
@@ -2,9 +2,9 @@ import { RelativeRange } from './model/types';
|
|
|
2
2
|
import { CursorEditor, CursorState, CursorStateChangeEvent, RemoteCursorChangeEventListener, WithCursorsOptions, WithYHistoryOptions, WithYjsOptions, YHistoryEditor, withCursors, withYHistory, withYjs, YjsEditor } from './plugins';
|
|
3
3
|
import { slateNodesToInsertDelta, yTextToSlateElement } from './utils/convert';
|
|
4
4
|
import { relativePositionToSlatePoint, relativeRangeToSlateRange, slatePointToRelativePosition, slateRangeToRelativeRange } from './utils/position';
|
|
5
|
-
import { useRemoteCursorStates } from './hooks/useRemoteCursorStates';
|
|
5
|
+
import { CursorStore, useRemoteCursorStates } from './hooks/useRemoteCursorStates';
|
|
6
6
|
import { useUnsetCursorPositionOnBlur } from './hooks/useUnsetCursorPositionOnBlur';
|
|
7
7
|
import { getCursorRange } from './hooks/utils';
|
|
8
8
|
import { CursorOverlayData, useRemoteCursorOverlayPositions } from './hooks/useRemoteCursorOverlayPositions';
|
|
9
|
-
export type { WithYjsOptions, YHistoryEditor, WithYHistoryOptions, CursorEditor,
|
|
10
|
-
export { YjsEditor, withYjs, withYHistory, withCursors, yTextToSlateElement, slateNodesToInsertDelta, slateRangeToRelativeRange, relativeRangeToSlateRange, slatePointToRelativePosition, relativePositionToSlatePoint, useRemoteCursorStates, useUnsetCursorPositionOnBlur,
|
|
9
|
+
export type { WithYjsOptions, YHistoryEditor, WithYHistoryOptions, CursorState, CursorStore, CursorEditor, CursorOverlayData, WithCursorsOptions, RemoteCursorChangeEventListener, CursorStateChangeEvent, RelativeRange, };
|
|
10
|
+
export { YjsEditor, withYjs, withYHistory, withCursors, yTextToSlateElement, slateNodesToInsertDelta, slateRangeToRelativeRange, relativeRangeToSlateRange, slatePointToRelativePosition, relativePositionToSlatePoint, useRemoteCursorStates, useUnsetCursorPositionOnBlur, useRemoteCursorOverlayPositions, getCursorRange, };
|
package/dist/yjs.js
CHANGED
|
@@ -1291,19 +1291,19 @@ function withCursors(editor, awareness, {
|
|
|
1291
1291
|
return e;
|
|
1292
1292
|
}
|
|
1293
1293
|
const EDITOR_TO_CURSOR_STORE = new toRawWeakMap();
|
|
1294
|
-
function
|
|
1294
|
+
function useRemoteCursorStates() {
|
|
1295
1295
|
const editor = useEditor();
|
|
1296
1296
|
const cursors = ref({});
|
|
1297
|
-
const changed =
|
|
1298
|
-
const addChanged = changed.
|
|
1297
|
+
const changed = /* @__PURE__ */ new Set();
|
|
1298
|
+
const addChanged = changed.add.bind(changed);
|
|
1299
1299
|
const changeHandler = (event) => {
|
|
1300
1300
|
event.added.forEach(addChanged);
|
|
1301
1301
|
event.removed.forEach(addChanged);
|
|
1302
1302
|
event.updated.forEach(addChanged);
|
|
1303
|
-
if (changed.
|
|
1303
|
+
if (changed.size === 0) {
|
|
1304
1304
|
return cursors;
|
|
1305
1305
|
}
|
|
1306
|
-
changed.
|
|
1306
|
+
changed.forEach((clientId) => {
|
|
1307
1307
|
const state = CursorEditor.cursorState(editor, clientId);
|
|
1308
1308
|
if (state === null) {
|
|
1309
1309
|
delete cursors.value[clientId.toString()];
|
|
@@ -1311,7 +1311,7 @@ function useRemoteCursorStateStore() {
|
|
|
1311
1311
|
}
|
|
1312
1312
|
cursors.value[clientId] = state;
|
|
1313
1313
|
});
|
|
1314
|
-
changed.
|
|
1314
|
+
changed.clear();
|
|
1315
1315
|
};
|
|
1316
1316
|
const subscribe = () => {
|
|
1317
1317
|
CursorEditor.on(editor, "change", changeHandler);
|
|
@@ -1319,10 +1319,6 @@ function useRemoteCursorStateStore() {
|
|
|
1319
1319
|
};
|
|
1320
1320
|
const store = [subscribe, cursors];
|
|
1321
1321
|
EDITOR_TO_CURSOR_STORE.set(editor, store);
|
|
1322
|
-
return store;
|
|
1323
|
-
}
|
|
1324
|
-
function useRemoteCursorStates() {
|
|
1325
|
-
const [subscribe, cursors] = useRemoteCursorStateStore();
|
|
1326
1322
|
let unsubscribe;
|
|
1327
1323
|
onMounted(() => {
|
|
1328
1324
|
unsubscribe = subscribe();
|
|
@@ -1479,8 +1475,7 @@ function useRemoteCursorOverlayPositions(containerRef, shouldGenerateOverlay) {
|
|
|
1479
1475
|
const cursorStates = useRemoteCursorStates();
|
|
1480
1476
|
const overlayPositionCache = ref(new toRawWeakMap());
|
|
1481
1477
|
const overlayPositions = ref({});
|
|
1482
|
-
|
|
1483
|
-
onUpdated(() => {
|
|
1478
|
+
const flushOverlayCursor = () => {
|
|
1484
1479
|
if (!containerRef.value) {
|
|
1485
1480
|
return;
|
|
1486
1481
|
}
|
|
@@ -1511,7 +1506,13 @@ function useRemoteCursorOverlayPositions(containerRef, shouldGenerateOverlay) {
|
|
|
1511
1506
|
if (overlayPositionsChanged) {
|
|
1512
1507
|
overlayPositions.value = updated;
|
|
1513
1508
|
}
|
|
1514
|
-
}
|
|
1509
|
+
};
|
|
1510
|
+
const refresh = () => {
|
|
1511
|
+
overlayPositionCache.value = new toRawWeakMap();
|
|
1512
|
+
flushOverlayCursor();
|
|
1513
|
+
};
|
|
1514
|
+
useOnResize(containerRef, refresh);
|
|
1515
|
+
onUpdated(flushOverlayCursor);
|
|
1515
1516
|
const overlayData = computed(
|
|
1516
1517
|
() => Object.entries(cursorStates.value).map(([clientId, state]) => {
|
|
1517
1518
|
const range = state.selection && getCursorRange(editor, state);
|
|
@@ -1524,7 +1525,6 @@ function useRemoteCursorOverlayPositions(containerRef, shouldGenerateOverlay) {
|
|
|
1524
1525
|
};
|
|
1525
1526
|
})
|
|
1526
1527
|
);
|
|
1527
|
-
const refresh = () => overlayPositionCache.value = new toRawWeakMap();
|
|
1528
1528
|
return [overlayData, refresh];
|
|
1529
1529
|
}
|
|
1530
1530
|
export {
|
package/package.json
CHANGED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { JsonObject } from '@liveblocks/client';
|
|
2
|
-
import { Store } from './utils';
|
|
3
|
-
import { CursorState } from '../plugins/withCursors';
|
|
4
|
-
export type CursorStore<TCursorData extends JsonObject = JsonObject> = Store<Record<string, CursorState<TCursorData>>>;
|
|
5
|
-
export declare function useRemoteCursorStateStore<TCursorData extends JsonObject = JsonObject>(): CursorStore<TCursorData>;
|