vuewrite 0.0.7 → 0.0.8

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.
@@ -29,6 +29,7 @@ export declare type Block = {
29
29
  text: string;
30
30
  type?: string;
31
31
  styles: Style[];
32
+ editable?: boolean;
32
33
  };
33
34
 
34
35
  export declare type Decorator = (style: Style) => HTMLAttributes | undefined;
@@ -63,6 +64,7 @@ end: number;
63
64
  style: string;
64
65
  meta?: any;
65
66
  }[];
67
+ editable?: boolean | undefined;
66
68
  } | null>;
67
69
  isCollapsed: ComputedRef<boolean>;
68
70
  selection: {
@@ -135,6 +137,7 @@ declare class TextEditorStore {
135
137
  style: string;
136
138
  meta?: any;
137
139
  }[];
140
+ editable?: boolean | undefined;
138
141
  }[];
139
142
  selection: {
140
143
  anchor: {
@@ -159,6 +162,7 @@ declare class TextEditorStore {
159
162
  style: string;
160
163
  meta?: any;
161
164
  }[];
165
+ editable?: boolean | undefined;
162
166
  } | null>;
163
167
  get currentBlock(): {
164
168
  id: string;
@@ -170,10 +174,12 @@ declare class TextEditorStore {
170
174
  style: string;
171
175
  meta?: any;
172
176
  }[];
177
+ editable?: boolean | undefined;
173
178
  } | null;
174
179
  _selectedText: ComputedRef<string>;
175
180
  get selectedText(): string;
176
181
  moveOffset(newOffset: number): void;
182
+ concatBlocks(start: Block, end: Block): void;
177
183
  removeNewLine(): void;
178
184
  onInput(_e: Event): void;
179
185
  addNewLine(): void;
package/dist/vuewrite.js CHANGED
@@ -202,18 +202,33 @@ class TextEditorStore {
202
202
  this.selection.anchor.offset = newOffset;
203
203
  this.selection.focus.offset = newOffset;
204
204
  }
205
+ concatBlocks(start, end) {
206
+ for (let style of end.styles) {
207
+ style.start += start.text.length;
208
+ style.end += start.text.length;
209
+ start.styles.push(style);
210
+ }
211
+ start.text = start.text + end.text;
212
+ }
205
213
  removeNewLine() {
206
214
  const blockIndex = this.blocks.findIndex((item) => item.id === this.selection.anchor.blockId);
207
215
  if (blockIndex < 1)
208
216
  return;
217
+ if (this.blocks[blockIndex - 1].editable === false) {
218
+ this.blocks.splice(blockIndex - 1, 1);
219
+ } else {
220
+ this.concatBlocks(this.blocks[blockIndex - 1], this.blocks[blockIndex]);
221
+ this.blocks.splice(blockIndex, 1);
222
+ }
209
223
  this.selection.anchor.blockId = this.blocks[blockIndex - 1].id;
210
224
  this.selection.focus.blockId = this.blocks[blockIndex - 1].id;
211
225
  this.selection.anchor.offset = this.blocks[blockIndex - 1].text.length;
212
226
  this.selection.focus.offset = this.blocks[blockIndex - 1].text.length;
213
- this.blocks.splice(blockIndex, 1);
214
227
  }
215
228
  onInput(_e) {
216
229
  const ev = _e;
230
+ if (ev.defaultPrevented)
231
+ return;
217
232
  ev.preventDefault();
218
233
  const collapsed = this.isCollapsed;
219
234
  if (!collapsed)
@@ -224,7 +239,11 @@ class TextEditorStore {
224
239
  if ((ev.inputType === "deleteContentBackward" || ev.inputType === "deleteContentForward") && collapsed) {
225
240
  if (ev.inputType === "deleteContentBackward") {
226
241
  if (this.selection.anchor.offset === 0) {
227
- this.removeNewLine();
242
+ if (block.type) {
243
+ delete block.type;
244
+ } else {
245
+ this.removeNewLine();
246
+ }
228
247
  } else {
229
248
  const offset = Math.max(0, this.selection.focus.offset - 1);
230
249
  block.text = block.text.slice(0, offset) + block.text.slice(this.selection.focus.offset);
@@ -234,7 +253,11 @@ class TextEditorStore {
234
253
  if (ev.inputType === "deleteContentForward") {
235
254
  const blockIndex = this.blocks.findIndex((item) => item.id === this.selection.anchor.blockId);
236
255
  if (this.selection.anchor.offset === this.blocks[blockIndex].text.length) {
237
- this.blocks.splice(blockIndex + 1, 1);
256
+ const nextBlock = this.blocks[blockIndex + 1];
257
+ if (nextBlock) {
258
+ this.blocks.splice(blockIndex + 1, 1);
259
+ this.concatBlocks(this.blocks[blockIndex - 1], this.blocks[blockIndex]);
260
+ }
238
261
  } else {
239
262
  block.text = block.text.slice(0, this.selection.focus.offset) + block.text.slice(this.selection.focus.offset + 1);
240
263
  this.moveStyles(block, this.selection.focus.offset + 1, 1);
@@ -277,6 +300,9 @@ class TextEditorStore {
277
300
  Object.assign(this.selection, selection);
278
301
  }
279
302
  Object.assign(this.currentBlock, blockData);
303
+ if (blockData.editable === false && this.currentBlock === this.blocks[this.blocks.length - 1]) {
304
+ this.addNewLine();
305
+ }
280
306
  }
281
307
  get startAndEnd() {
282
308
  const a = this.blocks.findIndex((block) => block.id === this.selection.anchor.blockId);
@@ -505,6 +531,8 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
505
531
  };
506
532
  const content = () => {
507
533
  const block = props.block;
534
+ if (block.editable === false)
535
+ return null;
508
536
  if (block.text.length === 0) {
509
537
  cleanTree(1);
510
538
  return [h("br")];
@@ -627,16 +655,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
627
655
  store.addNewLine();
628
656
  }
629
657
  }
630
- if (e.code === "Backspace") {
631
- if (store.isCollapsed && store.selection.anchor.offset === 0) {
632
- e.preventDefault();
633
- if (store.currentBlock && store.currentBlock.type) {
634
- delete store.currentBlock.type;
635
- } else {
636
- store.removeNewLine();
637
- }
638
- }
639
- }
640
658
  if ((e.ctrlKey || e.metaKey) && !e.shiftKey && !e.altKey) {
641
659
  if (e.code === "KeyB" || e.code === "KeyI" || e.code === "KeyU") {
642
660
  e.preventDefault();
@@ -646,21 +664,22 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
646
664
  let cachedSelection = {};
647
665
  useEventListener(document, "selectionchange", () => {
648
666
  const sel = window.getSelection();
649
- const anchor = findParent(sel.anchorNode, (el) => el.hasAttribute("data-vw-block-id"));
667
+ const anchor = findParent(sel.anchorNode, (el) => el.hasAttribute("data-vw-block-id") && el.parentElement === textEditorRef.value);
650
668
  if (anchor) {
651
669
  const offset = anchor === sel.anchorNode ? 0 : calcOffsetToNode(anchor, sel.anchorNode) + sel.anchorOffset;
652
670
  store.selection.anchor = { blockId: anchor.getAttribute("data-vw-block-id"), offset };
653
671
  }
654
- const focus = findParent(sel.focusNode, (el) => el.hasAttribute("data-vw-block-id"));
672
+ const focus = findParent(sel.focusNode, (el) => el.hasAttribute("data-vw-block-id") && el.parentElement === textEditorRef.value);
655
673
  if (focus) {
656
674
  const offset = anchor === sel.focusNode ? 0 : calcOffsetToNode(focus, sel.focusNode) + sel.focusOffset;
657
675
  store.selection.focus = { blockId: focus.getAttribute("data-vw-block-id"), offset };
658
676
  }
659
- if (store.isFocused.value !== !!focus || !!anchor) {
677
+ if (store.isFocused.value !== (!!focus || !!anchor)) {
660
678
  store.isFocused.value = !!focus || !!anchor;
661
679
  }
662
- if (!anchor && !focus)
680
+ if (!anchor && !focus) {
663
681
  cachedSelection = JSON.parse(JSON.stringify(store.selection));
682
+ }
664
683
  });
665
684
  let postRendered = false;
666
685
  const onPostRender = () => {
@@ -688,6 +707,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
688
707
  }
689
708
  if (isEqual(store.selection, cachedSelection))
690
709
  return;
710
+ if (store.selection.anchor.blockId === store.selection.focus.blockId && store.currentBlock && store.currentBlock.editable === false) {
711
+ return;
712
+ }
691
713
  const anchor = getNode(store.selection.anchor.blockId);
692
714
  const focus = getNode(store.selection.focus.blockId);
693
715
  const nativeSelection = window.getSelection();
@@ -760,7 +782,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
760
782
  ref_key: "textEditorRef",
761
783
  ref: textEditorRef,
762
784
  contenteditable: "",
763
- onInput: _cache[0] || (_cache[0] = //@ts-ignore
785
+ onBeforeinput: _cache[0] || (_cache[0] = //@ts-ignore
764
786
  (...args) => unref(store).onInput && unref(store).onInput(...args)),
765
787
  onKeydown: onKeyDown,
766
788
  onCopy,
@@ -776,7 +798,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
776
798
  onPostrender: onPostRender
777
799
  }, null, 8, ["block", "slots", "decorator"]);
778
800
  }), 128)),
779
- unref(store).blocks.length === 1 && unref(store).blocks[0].text === "" ? renderSlot(_ctx.$slots, "placeholder", { key: 0 }) : createCommentVNode("", true)
801
+ unref(store).blocks.length === 1 && unref(store).blocks[0].text === "" && !unref(store).blocks[0].type ? renderSlot(_ctx.$slots, "placeholder", { key: 0 }) : createCommentVNode("", true)
780
802
  ], 544);
781
803
  };
782
804
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "vuewrite",
3
3
  "description": "Rich Text Editor based on Vue3 reactivity",
4
4
  "private": false,
5
- "version": "0.0.7",
5
+ "version": "0.0.8",
6
6
  "type": "module",
7
7
  "license": "MIT",
8
8
  "author": "den59k",