vuewrite 0.0.1 → 0.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/README.md CHANGED
@@ -11,26 +11,33 @@ You can watch the demo [here](https://vuewrite.easix.ru)
11
11
 
12
12
  ```vue
13
13
  <template>
14
- <TextEditor
15
- :store="textEditorStore"
16
- class="text-editor"
17
- :decorator="decorator"
18
- @keydown="onKeyDown"
19
- />
14
+ <TextEditor
15
+ ref="textEditorRef"
16
+ v-model="modelValue"
17
+ single
18
+ class="text-editor"
19
+ :decorator="decorator"
20
+ @keydown="onKeyDown"
21
+ />
20
22
  </template>
21
23
 
22
24
  <script lang="ts">
25
+ import { TextEditor, TextEditorRef } from 'vuewrite'
26
+
27
+ const textEditorRef = shallowRef<TextEditorRef>()
28
+ const modelValue = ref("")
23
29
 
24
30
  const onKeyDown = (e: KeyboardEvent) => {
31
+ if (!textEditorRef.value) return
25
32
  if ((e.ctrlKey || e.metaKey) && !e.shiftKey && !e.altKey) {
26
33
  if (e.code === "KeyB") {
27
- textEditorStore.toggleStyle("bold")
34
+ textEditorRef.value.toggleStyle("bold")
28
35
  }
29
36
  if (e.code === "KeyI") {
30
- textEditorStore.toggleStyle("italic")
37
+ textEditorRef.value.toggleStyle("italic")
31
38
  }
32
39
  if (e.code === "KeyU") {
33
- textEditorStore.toggleStyle("underline")
40
+ textEditorRef.value.toggleStyle("underline")
34
41
  }
35
42
  }
36
43
  }
@@ -1,4 +1,5 @@
1
1
  import { ComponentOptionsMixin } from 'vue';
2
+ import { ComputedRef } from 'vue';
2
3
  import { DefineComponent } from 'vue';
3
4
  import { ExtractPropTypes } from 'vue';
4
5
  import { HTMLAttributes } from 'vue';
@@ -39,24 +40,58 @@ export declare type Style = {
39
40
  };
40
41
 
41
42
  export declare const TextEditor: __VLS_WithTemplateSlots<DefineComponent<__VLS_TypePropsToRuntimeProps<{
42
- store: TextEditorStore;
43
- placeholder?: string | undefined;
44
43
  decorator?: Decorator | undefined;
44
+ single?: boolean | undefined;
45
+ modelValue?: string | string[] | undefined;
46
+ styles?: Style[] | Style[][] | undefined;
45
47
  }>, {
46
- store: TextEditorStore;
48
+ currentStyles: ComputedRef<Map<string, Style>>;
49
+ currentBlock: ComputedRef< {
50
+ id: string;
51
+ text: string;
52
+ type?: string | undefined;
53
+ styles: {
54
+ start: number;
55
+ end: number;
56
+ style: string;
57
+ meta?: any;
58
+ }[];
59
+ } | null>;
60
+ isCollapsed: ComputedRef<boolean>;
61
+ selection: {
62
+ anchor: {
63
+ blockId: string;
64
+ offset: number;
65
+ };
66
+ focus: {
67
+ blockId: string;
68
+ offset: number;
69
+ };
70
+ };
71
+ toggleStyle: (style: string) => void;
72
+ applyStyle: (_style: string, meta?: any) => void;
73
+ removeStyle: (_style: string) => void;
74
+ insertText: (data: string) => void;
47
75
  }, unknown, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
48
76
  keydown: (...args: any[]) => void;
77
+ "update:modelValue": (...args: any[]) => void;
78
+ "update:styles": (...args: any[]) => void;
49
79
  }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
50
- store: TextEditorStore;
51
- placeholder?: string | undefined;
52
80
  decorator?: Decorator | undefined;
81
+ single?: boolean | undefined;
82
+ modelValue?: string | string[] | undefined;
83
+ styles?: Style[] | Style[][] | undefined;
53
84
  }>>> & {
54
85
  onKeydown?: ((...args: any[]) => any) | undefined;
86
+ "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
87
+ "onUpdate:styles"?: ((...args: any[]) => any) | undefined;
55
88
  }, {}, {}>, {
56
89
  placeholder?(_: {}): any;
57
90
  }>;
58
91
 
59
- export declare class TextEditorStore {
92
+ export declare type TextEditorRef = Pick<TextEditorStore, "currentStyles" | "currentBlock" | "isCollapsed" | "selection" | "toggleStyle" | "applyStyle" | "removeStyle" | "insertText">;
93
+
94
+ declare class TextEditorStore {
60
95
  blocks: {
61
96
  id: string;
62
97
  text: string;
@@ -78,9 +113,19 @@ export declare class TextEditorStore {
78
113
  offset: number;
79
114
  };
80
115
  };
81
- private _isCollapsed;
116
+ _isCollapsed: ComputedRef<boolean>;
82
117
  get isCollapsed(): boolean;
83
- private _currentBlock;
118
+ _currentBlock: ComputedRef< {
119
+ id: string;
120
+ text: string;
121
+ type?: string | undefined;
122
+ styles: {
123
+ start: number;
124
+ end: number;
125
+ style: string;
126
+ meta?: any;
127
+ }[];
128
+ } | null>;
84
129
  get currentBlock(): {
85
130
  id: string;
86
131
  text: string;
@@ -105,7 +150,7 @@ export declare class TextEditorStore {
105
150
  }, number, number];
106
151
  private moveStyles;
107
152
  deleteSelected(): void;
108
- private _currentStyles;
153
+ _currentStyles: ComputedRef<Map<string, Style>>;
109
154
  get currentStyles(): Map<string, Style>;
110
155
  applyStyle(_style: string, meta?: any): void;
111
156
  removeStyleAt(block: Block, _start: number, _end: number, _style?: string): void;
package/dist/vuewrite.js CHANGED
@@ -158,6 +158,8 @@ class TextEditorStore {
158
158
  __publicField(this, "_currentStyles", computed(() => {
159
159
  const [start, end, startIndex, endIndex] = this.startAndEnd;
160
160
  const styles = /* @__PURE__ */ new Map();
161
+ if (startIndex < 0)
162
+ return styles;
161
163
  for (let i = startIndex; i <= endIndex; i++) {
162
164
  for (let style of this.blocks[i].styles) {
163
165
  if (i === startIndex && start.offset < style.start)
@@ -516,24 +518,64 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
516
518
  const _sfc_main = /* @__PURE__ */ defineComponent({
517
519
  __name: "TextEditor",
518
520
  props: {
519
- store: {},
520
- placeholder: {},
521
- decorator: { type: Function }
521
+ decorator: { type: Function },
522
+ single: { type: Boolean },
523
+ modelValue: {},
524
+ styles: {}
522
525
  },
523
- emits: ["keydown"],
526
+ emits: ["keydown", "update:modelValue", "update:styles"],
524
527
  setup(__props, { expose: __expose, emit: __emit }) {
525
528
  const props = __props;
526
529
  const emit = __emit;
527
530
  const slots = useSlots();
528
531
  const textEditorRef = ref();
529
- const store = props.store ?? new TextEditorStore();
532
+ const store = new TextEditorStore();
533
+ let modelValue = "";
534
+ watch(() => props.modelValue, (newValue) => {
535
+ if (newValue === void 0 || newValue === null || newValue === modelValue)
536
+ return;
537
+ if (!Array.isArray(newValue)) {
538
+ store.blocks[0].text = newValue;
539
+ return;
540
+ } else {
541
+ for (let i = store.blocks.length; i < newValue.length; i++) {
542
+ store.blocks.push({ id: uid(), text: "", styles: [] });
543
+ }
544
+ store.blocks.length = newValue.length;
545
+ for (let i = 0; i < newValue.length; i++) {
546
+ store.blocks[i].text = newValue[i];
547
+ }
548
+ }
549
+ }, { immediate: true });
550
+ let styles;
551
+ watch(() => props.styles, (newStyles) => {
552
+ if (!newStyles || newStyles.length === 0 || newStyles === styles)
553
+ return;
554
+ for (let i = 0; i < store.blocks.length; i++) {
555
+ if (newStyles.length <= i)
556
+ break;
557
+ const style = props.single ? newStyles : newStyles[i];
558
+ store.blocks[i].styles = style;
559
+ }
560
+ }, { immediate: true });
561
+ watch(() => store.blocks, () => {
562
+ if (props.single) {
563
+ modelValue = store.blocks[0].text;
564
+ styles = store.blocks[0].styles;
565
+ } else {
566
+ modelValue = store.blocks.map((item) => item.text);
567
+ styles = store.blocks.map((item) => item.styles);
568
+ }
569
+ emit("update:modelValue", modelValue);
570
+ emit("update:styles", styles);
571
+ }, { deep: true });
530
572
  const onKeyDown = (e) => {
531
573
  emit("keydown", e);
532
574
  if (e.defaultPrevented)
533
575
  return;
534
576
  if (e.code === "Enter") {
535
577
  e.preventDefault();
536
- if (e.shiftKey) {
578
+ if (e.shiftKey || props.single) {
537
579
  store.insertText("\n");
538
580
  } else {
539
581
  store.addNewLine();
@@ -600,7 +642,14 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
600
642
  };
601
643
  watch(() => store.selection, applySelection, { deep: true, flush: "post" });
602
644
  __expose({
603
- store
645
+ currentStyles: store._currentStyles,
646
+ currentBlock: store._currentBlock,
647
+ isCollapsed: store._isCollapsed,
648
+ selection: store.selection,
649
+ toggleStyle: store.toggleStyle.bind(store),
650
+ applyStyle: store.applyStyle.bind(store),
651
+ removeStyle: store.removeStyle.bind(store),
652
+ insertText: store.insertText.bind(store)
604
653
  });
605
654
  return (_ctx, _cache) => {
606
655
  return openBlock(), createElementBlock("div", {
@@ -616,7 +665,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
616
665
  key: block.id,
617
666
  block,
618
667
  slots: unref(slots),
619
- decorator: _ctx.decorator,
668
+ decorator: props.decorator,
620
669
  onPostrender: onPostRender
621
670
  }, null, 8, ["block", "slots", "decorator"]);
622
671
  }), 128)),
@@ -626,6 +675,5 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
626
675
  }
627
676
  });
628
677
  export {
629
- _sfc_main as TextEditor,
630
- TextEditorStore
678
+ _sfc_main as TextEditor
631
679
  };
package/package.json CHANGED
@@ -2,8 +2,9 @@
2
2
  "name": "vuewrite",
3
3
  "description": "Rich Text Editor based on Vue3 reactivity",
4
4
  "private": false,
5
- "version": "0.0.1",
5
+ "version": "0.0.2",
6
6
  "type": "module",
7
+ "license": "MIT",
7
8
  "author": "den59k",
8
9
  "repository": {
9
10
  "type": "git",