slate-vue3 0.3.3 → 0.3.5

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
@@ -5,34 +5,36 @@
5
5
  </p>
6
6
 
7
7
  <p align="center">
8
- <a href="https://unpkg.com/slate-vue3/dist/index.js">
9
- <img src="http://img.badgesize.io/https://unpkg.com/slate-vue3/dist/index.js?compression=gzip&amp;label=size">
8
+ <a href="https://www.npmjs.com/package/slate-vue3?activeTab=code">
9
+ <img src="https://img.shields.io/npm/unpacked-size/slate-vue3">
10
+ <img src="https://img.shields.io/bundlephobia/min/slate-vue3">
10
11
  </a>
11
12
  <a href="https://join.slack.com/t/slate-js/shared_invite/zt-f8t986ip-7dA1DyiqPpzootz1snKXkw">
12
13
  <img src="https://img.shields.io/badge/slack-slate--js-brightgreen.svg?logo=slack">
13
14
  </a>
14
- <a href="./packages/slate-vue3/package.json">
15
+ <a href="./package.json">
15
16
  <img src="https://img.shields.io/npm/v/slate-vue3.svg?maxAge=3600&label=version&colorB=007ec6">
16
17
  </a>
17
18
  </p>
18
19
  <br/>
19
20
 
20
- # Why use it?
21
+ ### Why use it?
21
22
 
22
23
  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
25
- 4. :point_right: Check out the [**live demo**](https://guan-erjia.github.io/slate-vue3/examples/rich-text) of all of the examples
24
+ 2. :zap: Use `vue3` for high-performance rendering, and later connect to vapor mode
25
+ 3. :coffee: The **latest** version of the core, design tends to be stable
26
26
 
27
- # How to use?
27
+ <br />
28
28
 
29
- ## 1. Install slate-vue3
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
- ## 2. Now, you can use it in vue-sfc :point_right: [**live demo**](https://guan-erjia.github.io/slate-vue3/examples/rich-text)
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
- # FAQ
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) | ![](https://img.shields.io/npm/v/slate-vue3.svg?maxAge=3600&label=&colorB=007ec6) | slate's core data model logic. |
117
+ | [`slate-vue3/dom`](./packages/slate) | ![](https://img.shields.io/npm/v/slate-vue3.svg?maxAge=3600&label=&colorB=007ec6) | DOM implementation of slate |
118
+ | [`slate-vue3/history`](./packages/slate-history) | ![](https://img.shields.io/npm/v/slate-vue3.svg?maxAge=3600&label=&colorB=007ec6) | a plugin that adds undo/redo history to slate. |
119
+ | [`slate-vue3/hyperscript`](./packages/slate-hyperscript) | ![](https://img.shields.io/npm/v/slate-vue3.svg?maxAge=3600&label=&colorB=007ec6) | a hyperscript tool to write JSX slate documents! |
120
+ | [`slate-vue3/yjs`](./packages/slate-yjs) | ![](https://img.shields.io/npm/v/slate-vue3.svg?maxAge=3600&label=&colorB=007ec6) | 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
- ### 1. Why do I have to pass renderFunction into <Slate /> component ?
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
- ### 2. Can I use jsx in slate-vue3 ?
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
- ### 3. Why do rendering functions not use vue components ?
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
@@ -0,0 +1,25 @@
1
+ import { BaseRange, BaseText, NodeEntry } from '../../slate/index.ts';
2
+ import { DOMEditor } from '../../slate-dom/index.ts';
3
+ import { JsonObject } from '@liveblocks/client';
4
+ import { CursorEditor, CursorState } from '../plugins/withCursors';
5
+ export declare const REMOTE_CURSOR_DECORATION_PREFIX = "remote-cursor-";
6
+ export declare const REMOTE_CURSOR_CARET_DECORATION_PREFIX = "remote-caret-";
7
+ export type RemoteCaretDecoration<TCursorData extends JsonObject = JsonObject> = {
8
+ [key: `${typeof REMOTE_CURSOR_CARET_DECORATION_PREFIX}${string}`]: CursorState<TCursorData> & {
9
+ isBackward: boolean;
10
+ };
11
+ };
12
+ export type RemoteCursorDecoration<TCursorData extends JsonObject = JsonObject> = {
13
+ [key: `${typeof REMOTE_CURSOR_DECORATION_PREFIX}${string}`]: CursorState<TCursorData>;
14
+ };
15
+ export type RemoteCursorDecoratedRange<TCursorData extends JsonObject = JsonObject> = BaseRange & RemoteCursorDecoration<TCursorData>;
16
+ export type RemoteCaretDecoratedRange<TCursorData extends JsonObject = JsonObject> = BaseRange & RemoteCaretDecoration<TCursorData>;
17
+ export type TextWithRemoteCursors<TCursorData extends JsonObject = JsonObject> = BaseText & RemoteCursorDecoration<TCursorData> & RemoteCaretDecoration<TCursorData>;
18
+ export declare function getRemoteCursorsOnLeaf<TCursorData extends JsonObject, TLeaf extends TextWithRemoteCursors<TCursorData>>(leaf: TLeaf): CursorState<TCursorData>[];
19
+ export declare function getRemoteCaretsOnLeaf<TCursorData extends JsonObject, TLeaf extends TextWithRemoteCursors<TCursorData>>(leaf: TLeaf): (CursorState<TCursorData> & {
20
+ isBackward: boolean;
21
+ })[];
22
+ export type UseDecorateRemoteCursorsOptions = {
23
+ carets?: boolean;
24
+ };
25
+ export declare function useDecorateRemoteCursors<TCursorData extends JsonObject = JsonObject>(editor: CursorEditor<TCursorData> & DOMEditor, carets: boolean): (entry: NodeEntry) => (RemoteCursorDecoratedRange<TCursorData> | RemoteCaretDecoratedRange<TCursorData>)[];
@@ -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
- export declare function useUnsetCursorPositionOnBlur(): void;
1
+ import { JsonObject } from '@liveblocks/client';
2
+ export declare function useUnsetCursorPositionOnBlur<TCursor extends JsonObject>(): void;
@@ -2,9 +2,10 @@ 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, WithCursorsOptions, CursorState, RemoteCursorChangeEventListener, CursorStateChangeEvent, RelativeRange, CursorOverlayData, };
10
- export { YjsEditor, withYjs, withYHistory, withCursors, yTextToSlateElement, slateNodesToInsertDelta, slateRangeToRelativeRange, relativeRangeToSlateRange, slatePointToRelativePosition, relativePositionToSlatePoint, useRemoteCursorStates, useUnsetCursorPositionOnBlur, getCursorRange, useRemoteCursorOverlayPositions, };
9
+ import { getRemoteCaretsOnLeaf, getRemoteCursorsOnLeaf, REMOTE_CURSOR_CARET_DECORATION_PREFIX, REMOTE_CURSOR_DECORATION_PREFIX, RemoteCaretDecoratedRange, RemoteCaretDecoration, RemoteCursorDecoratedRange, RemoteCursorDecoration, TextWithRemoteCursors, useDecorateRemoteCursors, UseDecorateRemoteCursorsOptions } from './hooks/useDecorateRemoteCursors';
10
+ export type { WithYjsOptions, YHistoryEditor, WithYHistoryOptions, CursorState, CursorStore, CursorEditor, CursorOverlayData, WithCursorsOptions, RemoteCursorChangeEventListener, CursorStateChangeEvent, RelativeRange, UseDecorateRemoteCursorsOptions, RemoteCursorDecoration, RemoteCaretDecoration, RemoteCursorDecoratedRange, RemoteCaretDecoratedRange, TextWithRemoteCursors, };
11
+ export { YjsEditor, withYjs, withYHistory, withCursors, yTextToSlateElement, slateNodesToInsertDelta, slateRangeToRelativeRange, relativeRangeToSlateRange, slatePointToRelativePosition, relativePositionToSlatePoint, useRemoteCursorStates, useUnsetCursorPositionOnBlur, useRemoteCursorOverlayPositions, getCursorRange, getRemoteCursorsOnLeaf, getRemoteCaretsOnLeaf, useDecorateRemoteCursors, REMOTE_CURSOR_DECORATION_PREFIX, REMOTE_CURSOR_CARET_DECORATION_PREFIX };
package/dist/yjs.js CHANGED
@@ -1291,7 +1291,7 @@ function withCursors(editor, awareness, {
1291
1291
  return e;
1292
1292
  }
1293
1293
  const EDITOR_TO_CURSOR_STORE = new toRawWeakMap();
1294
- function useRemoteCursorStateStore() {
1294
+ function useRemoteCursorStates() {
1295
1295
  const editor = useEditor();
1296
1296
  const cursors = ref({});
1297
1297
  const changed = /* @__PURE__ */ new Set();
@@ -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();
@@ -1531,14 +1527,94 @@ function useRemoteCursorOverlayPositions(containerRef, shouldGenerateOverlay) {
1531
1527
  );
1532
1528
  return [overlayData, refresh];
1533
1529
  }
1530
+ const REMOTE_CURSOR_DECORATION_PREFIX = "remote-cursor-";
1531
+ const REMOTE_CURSOR_CARET_DECORATION_PREFIX = "remote-caret-";
1532
+ function getRemoteCursorsOnLeaf(leaf) {
1533
+ return Object.entries(leaf).filter(([key]) => key.startsWith(REMOTE_CURSOR_DECORATION_PREFIX)).map(([, data]) => data);
1534
+ }
1535
+ function getRemoteCaretsOnLeaf(leaf) {
1536
+ return Object.entries(leaf).filter(([key]) => key.startsWith(REMOTE_CURSOR_CARET_DECORATION_PREFIX)).map(([, data]) => data);
1537
+ }
1538
+ function getDecoration(clientId, state, range, caret) {
1539
+ if (!caret) {
1540
+ const key2 = `${REMOTE_CURSOR_DECORATION_PREFIX}${clientId}`;
1541
+ return { ...range, [key2]: state };
1542
+ }
1543
+ const key = `${REMOTE_CURSOR_CARET_DECORATION_PREFIX}${clientId}`;
1544
+ return {
1545
+ ...range,
1546
+ anchor: range.focus,
1547
+ [key]: state
1548
+ };
1549
+ }
1550
+ function useDecorateRemoteCursors(editor, carets) {
1551
+ const cursors = ref({});
1552
+ const changed = /* @__PURE__ */ new Set();
1553
+ const addChanged = changed.add.bind(changed);
1554
+ const changeHandler = (event) => {
1555
+ event.added.forEach(addChanged);
1556
+ event.removed.forEach(addChanged);
1557
+ event.updated.forEach(addChanged);
1558
+ if (changed.size === 0) {
1559
+ return cursors;
1560
+ }
1561
+ changed.forEach((clientId) => {
1562
+ const state = CursorEditor.cursorState(editor, clientId);
1563
+ if (state === null) {
1564
+ delete cursors.value[clientId.toString()];
1565
+ return;
1566
+ }
1567
+ cursors.value[clientId] = state;
1568
+ });
1569
+ changed.clear();
1570
+ };
1571
+ const subscribe = () => {
1572
+ CursorEditor.on(editor, "change", changeHandler);
1573
+ return () => CursorEditor.off(editor, "change", changeHandler);
1574
+ };
1575
+ let unsubscribe;
1576
+ onMounted(() => {
1577
+ unsubscribe = subscribe();
1578
+ });
1579
+ onUnmounted(() => {
1580
+ unsubscribe == null ? void 0 : unsubscribe();
1581
+ });
1582
+ return (entry) => {
1583
+ const [, path] = entry;
1584
+ if (path.length !== 1) {
1585
+ return [];
1586
+ }
1587
+ return Object.entries(cursors.value).flatMap(([clientId, state]) => {
1588
+ const range = getCursorRange(editor, state);
1589
+ if (!range) {
1590
+ return [];
1591
+ }
1592
+ if (carets && Range.isCollapsed(range)) {
1593
+ return getDecoration(clientId, state, range, true);
1594
+ }
1595
+ if (!carets) {
1596
+ return getDecoration(clientId, state, range, false);
1597
+ }
1598
+ return [
1599
+ getDecoration(clientId, state, range, false),
1600
+ getDecoration(clientId, state, range, true)
1601
+ ];
1602
+ });
1603
+ };
1604
+ }
1534
1605
  export {
1606
+ REMOTE_CURSOR_CARET_DECORATION_PREFIX,
1607
+ REMOTE_CURSOR_DECORATION_PREFIX,
1535
1608
  YjsEditor,
1536
1609
  getCursorRange,
1610
+ getRemoteCaretsOnLeaf,
1611
+ getRemoteCursorsOnLeaf,
1537
1612
  relativePositionToSlatePoint,
1538
1613
  relativeRangeToSlateRange,
1539
1614
  slateNodesToInsertDelta,
1540
1615
  slatePointToRelativePosition,
1541
1616
  slateRangeToRelativeRange,
1617
+ useDecorateRemoteCursors,
1542
1618
  useRemoteCursorOverlayPositions,
1543
1619
  useRemoteCursorStates,
1544
1620
  useUnsetCursorPositionOnBlur,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slate-vue3",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -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>;