@mekari/pixel3-rich-text-editor 0.1.3 → 0.2.0-dev.0
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/dist/{chunk-6O4HSL2C.mjs → chunk-B5BN5T5O.mjs} +6 -2
- package/dist/{chunk-4ZCPCZD2.mjs → chunk-E4R6ETA7.mjs} +16 -9
- package/dist/{chunk-4TUA5VF4.mjs → chunk-ELFAGDKG.mjs} +17 -3
- package/dist/{chunk-4KJOYLJI.mjs → chunk-RTEK53TL.mjs} +47 -15
- package/dist/{chunk-BA5A7DIS.mjs → chunk-RVXAG7LK.mjs} +3 -3
- package/dist/editor-toolbar.mjs +4 -4
- package/dist/extensions/index.mjs +9 -9
- package/dist/extensions/mention-list-extension.d.mts +9 -0
- package/dist/extensions/mention-list-extension.d.ts +9 -0
- package/dist/extensions/mention-list-extension.js +16 -2
- package/dist/extensions/mention-list-extension.mjs +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +79 -22
- package/dist/index.mjs +13 -13
- package/dist/metafile-cjs.json +1 -1
- package/dist/metafile-esm.json +1 -1
- package/dist/modules/rich-text-editor.props.d.mts +7 -3
- package/dist/modules/rich-text-editor.props.d.ts +7 -3
- package/dist/modules/rich-text-editor.props.js +6 -2
- package/dist/modules/rich-text-editor.props.mjs +1 -1
- package/dist/modules/rich-text-editor.types.d.mts +12 -3
- package/dist/modules/rich-text-editor.types.d.ts +12 -3
- package/dist/rich-text-editor.d.mts +15 -5
- package/dist/rich-text-editor.d.ts +15 -5
- package/dist/rich-text-editor.js +79 -22
- package/dist/rich-text-editor.mjs +12 -12
- package/dist/rte-style-provider.js +1 -1
- package/dist/rte-style-provider.mjs +2 -2
- package/dist/rte-suggestion.d.mts +7 -3
- package/dist/rte-suggestion.d.ts +7 -3
- package/dist/rte-suggestion.js +62 -16
- package/dist/rte-suggestion.mjs +2 -2
- package/package.json +6 -5
- package/dist/{chunk-G4CGNV6P.mjs → chunk-RX7ZEE2M.mjs} +6 -6
|
@@ -29,9 +29,13 @@ var richTextEditorProps = {
|
|
|
29
29
|
default: true
|
|
30
30
|
},
|
|
31
31
|
suggestions: {
|
|
32
|
-
type: Array,
|
|
32
|
+
type: [Array, Function],
|
|
33
33
|
default: () => []
|
|
34
34
|
},
|
|
35
|
+
maxSuggestions: {
|
|
36
|
+
type: Number,
|
|
37
|
+
default: 50
|
|
38
|
+
},
|
|
35
39
|
variables: {
|
|
36
40
|
type: Array,
|
|
37
41
|
default: () => []
|
|
@@ -48,7 +52,7 @@ var RTEStyleProviderProps = {
|
|
|
48
52
|
type: String
|
|
49
53
|
}
|
|
50
54
|
};
|
|
51
|
-
var richTextEditorEmits = declareEmit(["change", "blur", "focus", "action", "paste"]);
|
|
55
|
+
var richTextEditorEmits = declareEmit(["change", "blur", "focus", "action", "paste", "suggestionsChange"]);
|
|
52
56
|
|
|
53
57
|
export {
|
|
54
58
|
richTextEditorProps,
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EditorToolbar
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-RX7ZEE2M.mjs";
|
|
4
4
|
import {
|
|
5
5
|
Variable
|
|
6
6
|
} from "./chunk-ENKUUZPM.mjs";
|
|
7
7
|
import {
|
|
8
8
|
MpRTEStyleProvider
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-RVXAG7LK.mjs";
|
|
10
|
+
import {
|
|
11
|
+
useRichTextEditor
|
|
12
|
+
} from "./chunk-ZRAXSVO5.mjs";
|
|
10
13
|
import {
|
|
11
14
|
richTextEditorEmits,
|
|
12
15
|
richTextEditorProps
|
|
13
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-B5BN5T5O.mjs";
|
|
14
17
|
import {
|
|
15
18
|
createMentionSuggestion
|
|
16
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-RTEK53TL.mjs";
|
|
17
20
|
import {
|
|
18
21
|
createVariableSuggestion
|
|
19
22
|
} from "./chunk-BWRU2WZN.mjs";
|
|
20
|
-
import {
|
|
21
|
-
useRichTextEditor
|
|
22
|
-
} from "./chunk-ZRAXSVO5.mjs";
|
|
23
23
|
import {
|
|
24
24
|
__name
|
|
25
25
|
} from "./chunk-QZ7VFGWC.mjs";
|
|
@@ -93,8 +93,15 @@ var MpRichTextEditor = defineComponent({
|
|
|
93
93
|
CharacterCount.configure({
|
|
94
94
|
limit: api.value.maxlength
|
|
95
95
|
}),
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
// Extensions are registered once at mount, so the array-length check
|
|
97
|
+
// here can't be reactive. A resolver function always registers the
|
|
98
|
+
// extension — use that form when suggestions are loaded dynamically
|
|
99
|
+
// (e.g. fetched from an API after mount).
|
|
100
|
+
...typeof props.suggestions === "function" || props.suggestions && props.suggestions.length > 0 ? [Mention.configure({
|
|
101
|
+
suggestion: createMentionSuggestion(() => props.suggestions, {
|
|
102
|
+
maxItems: props.maxSuggestions,
|
|
103
|
+
onSuggestionsChange: (items) => emit("suggestionsChange", items)
|
|
104
|
+
})
|
|
98
105
|
})] : [],
|
|
99
106
|
...props.variables && props.variables.length > 0 ? [Variable.configure({
|
|
100
107
|
suggestion: createVariableSuggestion(() => props.variables || [])
|
|
@@ -3,12 +3,13 @@ import {
|
|
|
3
3
|
} from "./chunk-QZ7VFGWC.mjs";
|
|
4
4
|
|
|
5
5
|
// src/extensions/mention-list-extension.tsx
|
|
6
|
-
import {
|
|
6
|
+
import { createTextVNode as _createTextVNode, createVNode as _createVNode } from "vue";
|
|
7
7
|
import { defineComponent, nextTick, ref, watch } from "vue";
|
|
8
8
|
import { css } from "@mekari/pixel3-styled-system/css";
|
|
9
9
|
import { MpAvatar } from "@mekari/pixel3-avatar";
|
|
10
10
|
import { MpPopover, MpPopoverContent, MpPopoverList, MpPopoverListItem } from "@mekari/pixel3-popover";
|
|
11
11
|
import { MpText } from "@mekari/pixel3-text";
|
|
12
|
+
import { MpSpinner } from "@mekari/pixel3-spinner";
|
|
12
13
|
var avatarVariantColors = ["violet", "lime", "amber", "sky", "pink", "teal", "rose", "stone"];
|
|
13
14
|
var getAvatarVariantColor = /* @__PURE__ */ __name((index) => {
|
|
14
15
|
return avatarVariantColors[index % avatarVariantColors.length];
|
|
@@ -23,6 +24,10 @@ var MentionList = defineComponent({
|
|
|
23
24
|
command: {
|
|
24
25
|
type: Function,
|
|
25
26
|
required: true
|
|
27
|
+
},
|
|
28
|
+
isLoading: {
|
|
29
|
+
type: Boolean,
|
|
30
|
+
default: false
|
|
26
31
|
}
|
|
27
32
|
},
|
|
28
33
|
setup(props, {
|
|
@@ -107,7 +112,16 @@ var MentionList = defineComponent({
|
|
|
107
112
|
},
|
|
108
113
|
"data-pixel-rte": true
|
|
109
114
|
}, {
|
|
110
|
-
default: () => [
|
|
115
|
+
default: () => [props.isLoading && _createVNode("div", {
|
|
116
|
+
"class": css({
|
|
117
|
+
display: "flex",
|
|
118
|
+
justifyContent: "center",
|
|
119
|
+
px: "3",
|
|
120
|
+
py: "3"
|
|
121
|
+
})
|
|
122
|
+
}, [_createVNode(MpSpinner, {
|
|
123
|
+
"size": "sm"
|
|
124
|
+
}, null)]), !props.isLoading && !props.items.length && _createVNode(MpText, {
|
|
111
125
|
"color": "text.secondary",
|
|
112
126
|
"class": css({
|
|
113
127
|
px: "3",
|
|
@@ -115,7 +129,7 @@ var MentionList = defineComponent({
|
|
|
115
129
|
})
|
|
116
130
|
}, {
|
|
117
131
|
default: () => [_createTextVNode("No result")]
|
|
118
|
-
}), props.items.map((item, index) => {
|
|
132
|
+
}), !props.isLoading && props.items.map((item, index) => {
|
|
119
133
|
return _createVNode(MpPopoverListItem, {
|
|
120
134
|
"key": `${item.id}-${index}`,
|
|
121
135
|
"is-active": selectedIndex.value === index,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MentionList
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ELFAGDKG.mjs";
|
|
4
4
|
import {
|
|
5
5
|
__name
|
|
6
6
|
} from "./chunk-QZ7VFGWC.mjs";
|
|
@@ -8,8 +8,7 @@ import {
|
|
|
8
8
|
// src/rte-suggestion.ts
|
|
9
9
|
import { VueRenderer } from "@tiptap/vue-3";
|
|
10
10
|
import { createPopper } from "@popperjs/core";
|
|
11
|
-
var
|
|
12
|
-
var getFilteredSuggestionItems = /* @__PURE__ */ __name((items, query) => {
|
|
11
|
+
var getFilteredSuggestionItems = /* @__PURE__ */ __name((items, query, maxItems) => {
|
|
13
12
|
const normalizedQuery = query.trim().toLowerCase();
|
|
14
13
|
return items.filter((item) => {
|
|
15
14
|
var _a, _b;
|
|
@@ -20,14 +19,25 @@ var getFilteredSuggestionItems = /* @__PURE__ */ __name((items, query) => {
|
|
|
20
19
|
const label = ((_a = item.name) != null ? _a : "").toLowerCase();
|
|
21
20
|
const description = ((_b = item.description) != null ? _b : "").toLowerCase();
|
|
22
21
|
return id.includes(normalizedQuery) || label.includes(normalizedQuery) || description.includes(normalizedQuery);
|
|
23
|
-
}).slice(0,
|
|
22
|
+
}).slice(0, maxItems);
|
|
24
23
|
}, "getFilteredSuggestionItems");
|
|
25
|
-
var createMentionSuggestion = /* @__PURE__ */ __name((
|
|
24
|
+
var createMentionSuggestion = /* @__PURE__ */ __name((getSuggestionSource = () => [], options = {}) => {
|
|
25
|
+
var _a;
|
|
26
|
+
const maxItems = (_a = options.maxItems) != null ? _a : 50;
|
|
26
27
|
return {
|
|
27
|
-
items: ({
|
|
28
|
+
items: async ({
|
|
28
29
|
query
|
|
29
30
|
}) => {
|
|
30
|
-
|
|
31
|
+
var _a2, _b, _c;
|
|
32
|
+
const source = getSuggestionSource();
|
|
33
|
+
if (typeof source === "function") {
|
|
34
|
+
const items2 = ((_a2 = await source(query)) != null ? _a2 : []).slice(0, maxItems);
|
|
35
|
+
(_b = options.onSuggestionsChange) == null ? void 0 : _b.call(options, items2);
|
|
36
|
+
return items2;
|
|
37
|
+
}
|
|
38
|
+
const items = getFilteredSuggestionItems(source != null ? source : [], query, maxItems);
|
|
39
|
+
(_c = options.onSuggestionsChange) == null ? void 0 : _c.call(options, items);
|
|
40
|
+
return items;
|
|
31
41
|
},
|
|
32
42
|
render: () => {
|
|
33
43
|
let component = null;
|
|
@@ -88,8 +98,8 @@ var createMentionSuggestion = /* @__PURE__ */ __name((getSuggestionItems = () =>
|
|
|
88
98
|
}
|
|
89
99
|
return {
|
|
90
100
|
getBoundingClientRect: () => {
|
|
91
|
-
var
|
|
92
|
-
return (
|
|
101
|
+
var _a2;
|
|
102
|
+
return (_a2 = clientRectProvider == null ? void 0 : clientRectProvider()) != null ? _a2 : new DOMRect();
|
|
93
103
|
}
|
|
94
104
|
};
|
|
95
105
|
}, "getVirtualElement");
|
|
@@ -118,14 +128,18 @@ var createMentionSuggestion = /* @__PURE__ */ __name((getSuggestionItems = () =>
|
|
|
118
128
|
popperInstance.update();
|
|
119
129
|
}, "updatePopoverPosition");
|
|
120
130
|
return {
|
|
121
|
-
|
|
131
|
+
// Fires synchronously before `items()` resolves, so the popover can
|
|
132
|
+
// mount showing a loading state instead of a blank/"No result" flash
|
|
133
|
+
// while the (possibly async) suggestion source is fetched.
|
|
134
|
+
onBeforeStart: (props) => {
|
|
122
135
|
clientRectProvider = props.clientRect;
|
|
123
136
|
editorElement = props.editor.view.dom;
|
|
124
137
|
component = new VueRenderer(MentionList, {
|
|
125
138
|
editor: props.editor,
|
|
126
139
|
props: {
|
|
127
|
-
items:
|
|
128
|
-
command: props.command
|
|
140
|
+
items: [],
|
|
141
|
+
command: props.command,
|
|
142
|
+
isLoading: true
|
|
129
143
|
}
|
|
130
144
|
});
|
|
131
145
|
popoverWrapper = document.createElement("div");
|
|
@@ -138,21 +152,39 @@ var createMentionSuggestion = /* @__PURE__ */ __name((getSuggestionItems = () =>
|
|
|
138
152
|
setupOutsideListeners();
|
|
139
153
|
updatePopoverPosition();
|
|
140
154
|
},
|
|
155
|
+
onStart: (props) => {
|
|
156
|
+
clientRectProvider = props.clientRect;
|
|
157
|
+
component == null ? void 0 : component.updateProps({
|
|
158
|
+
items: props.items,
|
|
159
|
+
command: props.command,
|
|
160
|
+
isLoading: false
|
|
161
|
+
});
|
|
162
|
+
updatePopoverPosition();
|
|
163
|
+
},
|
|
164
|
+
// Fires before every re-fetch triggered by a query change — flips
|
|
165
|
+
// back to the loading state until the new `items()` call resolves.
|
|
166
|
+
onBeforeUpdate: (props) => {
|
|
167
|
+
clientRectProvider = props.clientRect;
|
|
168
|
+
component == null ? void 0 : component.updateProps({
|
|
169
|
+
isLoading: true
|
|
170
|
+
});
|
|
171
|
+
},
|
|
141
172
|
onUpdate: (props) => {
|
|
142
173
|
clientRectProvider = props.clientRect;
|
|
143
174
|
component == null ? void 0 : component.updateProps({
|
|
144
175
|
items: props.items,
|
|
145
|
-
command: props.command
|
|
176
|
+
command: props.command,
|
|
177
|
+
isLoading: false
|
|
146
178
|
});
|
|
147
179
|
updatePopoverPosition();
|
|
148
180
|
},
|
|
149
181
|
onKeyDown: (props) => {
|
|
150
|
-
var
|
|
182
|
+
var _a2, _b;
|
|
151
183
|
if (props.event.key === "Escape") {
|
|
152
184
|
destroyMentionPopover();
|
|
153
185
|
return true;
|
|
154
186
|
}
|
|
155
|
-
return (_b = (
|
|
187
|
+
return (_b = (_a2 = component == null ? void 0 : component.ref) == null ? void 0 : _a2.onKeyDown(props)) != null ? _b : false;
|
|
156
188
|
},
|
|
157
189
|
onExit: () => {
|
|
158
190
|
destroyMentionPopover();
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
RTEStyleProviderProps
|
|
3
|
-
} from "./chunk-6O4HSL2C.mjs";
|
|
4
1
|
import {
|
|
5
2
|
useRTEStyleProvider
|
|
6
3
|
} from "./chunk-ZRAXSVO5.mjs";
|
|
4
|
+
import {
|
|
5
|
+
RTEStyleProviderProps
|
|
6
|
+
} from "./chunk-B5BN5T5O.mjs";
|
|
7
7
|
|
|
8
8
|
// src/rte-style-provider.tsx
|
|
9
9
|
import { createVNode as _createVNode } from "vue";
|
package/dist/editor-toolbar.mjs
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EditorToolbar
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-RX7ZEE2M.mjs";
|
|
4
4
|
import "./chunk-HIHIKPNN.mjs";
|
|
5
|
+
import "./chunk-X2CB42A3.mjs";
|
|
6
|
+
import "./chunk-COZ45QUD.mjs";
|
|
5
7
|
import "./chunk-FCLBNBXD.mjs";
|
|
6
8
|
import "./chunk-ENKUUZPM.mjs";
|
|
9
|
+
import "./chunk-76GEEOAG.mjs";
|
|
7
10
|
import "./chunk-YWVVMJGP.mjs";
|
|
8
11
|
import "./chunk-Y6UPQ6EU.mjs";
|
|
9
|
-
import "./chunk-X2CB42A3.mjs";
|
|
10
|
-
import "./chunk-COZ45QUD.mjs";
|
|
11
12
|
import "./chunk-IFRJVX2K.mjs";
|
|
12
|
-
import "./chunk-76GEEOAG.mjs";
|
|
13
13
|
import "./chunk-QZ7VFGWC.mjs";
|
|
14
14
|
export {
|
|
15
15
|
EditorToolbar
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
import "../chunk-HIHIKPNN.mjs";
|
|
2
|
+
import {
|
|
3
|
+
HeadingExtention
|
|
4
|
+
} from "../chunk-X2CB42A3.mjs";
|
|
5
|
+
import {
|
|
6
|
+
LinkExtension
|
|
7
|
+
} from "../chunk-COZ45QUD.mjs";
|
|
2
8
|
import {
|
|
3
9
|
SingleExtention
|
|
4
10
|
} from "../chunk-FCLBNBXD.mjs";
|
|
5
11
|
import {
|
|
6
12
|
Variable
|
|
7
13
|
} from "../chunk-ENKUUZPM.mjs";
|
|
14
|
+
import {
|
|
15
|
+
VariableList
|
|
16
|
+
} from "../chunk-76GEEOAG.mjs";
|
|
8
17
|
import {
|
|
9
18
|
AlignExtention
|
|
10
19
|
} from "../chunk-YWVVMJGP.mjs";
|
|
11
20
|
import {
|
|
12
21
|
ColorExtension
|
|
13
22
|
} from "../chunk-Y6UPQ6EU.mjs";
|
|
14
|
-
import {
|
|
15
|
-
HeadingExtention
|
|
16
|
-
} from "../chunk-X2CB42A3.mjs";
|
|
17
|
-
import {
|
|
18
|
-
LinkExtension
|
|
19
|
-
} from "../chunk-COZ45QUD.mjs";
|
|
20
23
|
import "../chunk-IFRJVX2K.mjs";
|
|
21
|
-
import {
|
|
22
|
-
VariableList
|
|
23
|
-
} from "../chunk-76GEEOAG.mjs";
|
|
24
24
|
import "../chunk-QZ7VFGWC.mjs";
|
|
25
25
|
export {
|
|
26
26
|
AlignExtention,
|
|
@@ -15,6 +15,10 @@ declare const MentionList: vue.DefineComponent<{
|
|
|
15
15
|
}) => void>;
|
|
16
16
|
required: true;
|
|
17
17
|
};
|
|
18
|
+
isLoading: {
|
|
19
|
+
type: BooleanConstructor;
|
|
20
|
+
default: boolean;
|
|
21
|
+
};
|
|
18
22
|
}, () => vue_jsx_runtime.JSX.Element, unknown, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
|
|
19
23
|
items: {
|
|
20
24
|
type: PropType<MentionSuggestionItem[]>;
|
|
@@ -26,7 +30,12 @@ declare const MentionList: vue.DefineComponent<{
|
|
|
26
30
|
}) => void>;
|
|
27
31
|
required: true;
|
|
28
32
|
};
|
|
33
|
+
isLoading: {
|
|
34
|
+
type: BooleanConstructor;
|
|
35
|
+
default: boolean;
|
|
36
|
+
};
|
|
29
37
|
}>>, {
|
|
38
|
+
isLoading: boolean;
|
|
30
39
|
items: MentionSuggestionItem[];
|
|
31
40
|
}, {}>;
|
|
32
41
|
|
|
@@ -15,6 +15,10 @@ declare const MentionList: vue.DefineComponent<{
|
|
|
15
15
|
}) => void>;
|
|
16
16
|
required: true;
|
|
17
17
|
};
|
|
18
|
+
isLoading: {
|
|
19
|
+
type: BooleanConstructor;
|
|
20
|
+
default: boolean;
|
|
21
|
+
};
|
|
18
22
|
}, () => vue_jsx_runtime.JSX.Element, unknown, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
|
|
19
23
|
items: {
|
|
20
24
|
type: PropType<MentionSuggestionItem[]>;
|
|
@@ -26,7 +30,12 @@ declare const MentionList: vue.DefineComponent<{
|
|
|
26
30
|
}) => void>;
|
|
27
31
|
required: true;
|
|
28
32
|
};
|
|
33
|
+
isLoading: {
|
|
34
|
+
type: BooleanConstructor;
|
|
35
|
+
default: boolean;
|
|
36
|
+
};
|
|
29
37
|
}>>, {
|
|
38
|
+
isLoading: boolean;
|
|
30
39
|
items: MentionSuggestionItem[];
|
|
31
40
|
}, {}>;
|
|
32
41
|
|
|
@@ -30,6 +30,7 @@ var import_css = require("@mekari/pixel3-styled-system/css");
|
|
|
30
30
|
var import_pixel3_avatar = require("@mekari/pixel3-avatar");
|
|
31
31
|
var import_pixel3_popover = require("@mekari/pixel3-popover");
|
|
32
32
|
var import_pixel3_text = require("@mekari/pixel3-text");
|
|
33
|
+
var import_pixel3_spinner = require("@mekari/pixel3-spinner");
|
|
33
34
|
var avatarVariantColors = ["violet", "lime", "amber", "sky", "pink", "teal", "rose", "stone"];
|
|
34
35
|
var getAvatarVariantColor = /* @__PURE__ */ __name((index) => {
|
|
35
36
|
return avatarVariantColors[index % avatarVariantColors.length];
|
|
@@ -44,6 +45,10 @@ var MentionList = (0, import_vue2.defineComponent)({
|
|
|
44
45
|
command: {
|
|
45
46
|
type: Function,
|
|
46
47
|
required: true
|
|
48
|
+
},
|
|
49
|
+
isLoading: {
|
|
50
|
+
type: Boolean,
|
|
51
|
+
default: false
|
|
47
52
|
}
|
|
48
53
|
},
|
|
49
54
|
setup(props, {
|
|
@@ -128,7 +133,16 @@ var MentionList = (0, import_vue2.defineComponent)({
|
|
|
128
133
|
},
|
|
129
134
|
"data-pixel-rte": true
|
|
130
135
|
}, {
|
|
131
|
-
default: () => [
|
|
136
|
+
default: () => [props.isLoading && (0, import_vue.createVNode)("div", {
|
|
137
|
+
"class": (0, import_css.css)({
|
|
138
|
+
display: "flex",
|
|
139
|
+
justifyContent: "center",
|
|
140
|
+
px: "3",
|
|
141
|
+
py: "3"
|
|
142
|
+
})
|
|
143
|
+
}, [(0, import_vue.createVNode)(import_pixel3_spinner.MpSpinner, {
|
|
144
|
+
"size": "sm"
|
|
145
|
+
}, null)]), !props.isLoading && !props.items.length && (0, import_vue.createVNode)(import_pixel3_text.MpText, {
|
|
132
146
|
"color": "text.secondary",
|
|
133
147
|
"class": (0, import_css.css)({
|
|
134
148
|
px: "3",
|
|
@@ -136,7 +150,7 @@ var MentionList = (0, import_vue2.defineComponent)({
|
|
|
136
150
|
})
|
|
137
151
|
}, {
|
|
138
152
|
default: () => [(0, import_vue.createTextVNode)("No result")]
|
|
139
|
-
}), props.items.map((item, index) => {
|
|
153
|
+
}), !props.isLoading && props.items.map((item, index) => {
|
|
140
154
|
return (0, import_vue.createVNode)(import_pixel3_popover.MpPopoverListItem, {
|
|
141
155
|
"key": `${item.id}-${index}`,
|
|
142
156
|
"is-active": selectedIndex.value === index,
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { MpRichTextEditor } from './rich-text-editor.mjs';
|
|
2
2
|
export { MpRTEStyleProvider } from './rte-style-provider.mjs';
|
|
3
|
-
export { ActionTypes, ItemOptions, Items, MentionSuggestionItem, RTEStyleProviderApiMachine, RTEStyleProviderClasses, RTEStyleProviderDefinedContext, RTEStyleProviderState, RichTextEditorApiMachine, RichTextEditorClasses, RichTextEditorDefinedContext, RichTextEditorProps, RichTextEditorState, RteStyleProviderProps, ToolbarOption, ToolbarOptionObject, VariableSuggestionItem } from './modules/rich-text-editor.types.mjs';
|
|
3
|
+
export { ActionTypes, ItemOptions, Items, MentionSuggestionItem, MentionSuggestionSource, RTEStyleProviderApiMachine, RTEStyleProviderClasses, RTEStyleProviderDefinedContext, RTEStyleProviderState, RichTextEditorApiMachine, RichTextEditorClasses, RichTextEditorDefinedContext, RichTextEditorProps, RichTextEditorState, RteStyleProviderProps, ToolbarOption, ToolbarOptionObject, VariableSuggestionItem } from './modules/rich-text-editor.types.mjs';
|
|
4
4
|
import 'vue/jsx-runtime';
|
|
5
5
|
import 'vue';
|
|
6
6
|
import '@mekari/pixel3-utils';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { MpRichTextEditor } from './rich-text-editor.js';
|
|
2
2
|
export { MpRTEStyleProvider } from './rte-style-provider.js';
|
|
3
|
-
export { ActionTypes, ItemOptions, Items, MentionSuggestionItem, RTEStyleProviderApiMachine, RTEStyleProviderClasses, RTEStyleProviderDefinedContext, RTEStyleProviderState, RichTextEditorApiMachine, RichTextEditorClasses, RichTextEditorDefinedContext, RichTextEditorProps, RichTextEditorState, RteStyleProviderProps, ToolbarOption, ToolbarOptionObject, VariableSuggestionItem } from './modules/rich-text-editor.types.js';
|
|
3
|
+
export { ActionTypes, ItemOptions, Items, MentionSuggestionItem, MentionSuggestionSource, RTEStyleProviderApiMachine, RTEStyleProviderClasses, RTEStyleProviderDefinedContext, RTEStyleProviderState, RichTextEditorApiMachine, RichTextEditorClasses, RichTextEditorDefinedContext, RichTextEditorProps, RichTextEditorState, RteStyleProviderProps, ToolbarOption, ToolbarOptionObject, VariableSuggestionItem } from './modules/rich-text-editor.types.js';
|
|
4
4
|
import 'vue/jsx-runtime';
|
|
5
5
|
import 'vue';
|
|
6
6
|
import '@mekari/pixel3-utils';
|
package/dist/index.js
CHANGED
|
@@ -72,9 +72,13 @@ var richTextEditorProps = {
|
|
|
72
72
|
default: true
|
|
73
73
|
},
|
|
74
74
|
suggestions: {
|
|
75
|
-
type: Array,
|
|
75
|
+
type: [Array, Function],
|
|
76
76
|
default: () => []
|
|
77
77
|
},
|
|
78
|
+
maxSuggestions: {
|
|
79
|
+
type: Number,
|
|
80
|
+
default: 50
|
|
81
|
+
},
|
|
78
82
|
variables: {
|
|
79
83
|
type: Array,
|
|
80
84
|
default: () => []
|
|
@@ -91,7 +95,7 @@ var RTEStyleProviderProps = {
|
|
|
91
95
|
type: String
|
|
92
96
|
}
|
|
93
97
|
};
|
|
94
|
-
var richTextEditorEmits = (0, import_pixel3_utils.declareEmit)(["change", "blur", "focus", "action", "paste"]);
|
|
98
|
+
var richTextEditorEmits = (0, import_pixel3_utils.declareEmit)(["change", "blur", "focus", "action", "paste", "suggestionsChange"]);
|
|
95
99
|
|
|
96
100
|
// src/modules/rich-text-editor.hooks.ts
|
|
97
101
|
var import_vue = require("vue");
|
|
@@ -1809,6 +1813,7 @@ var import_css7 = require("@mekari/pixel3-styled-system/css");
|
|
|
1809
1813
|
var import_pixel3_avatar = require("@mekari/pixel3-avatar");
|
|
1810
1814
|
var import_pixel3_popover4 = require("@mekari/pixel3-popover");
|
|
1811
1815
|
var import_pixel3_text3 = require("@mekari/pixel3-text");
|
|
1816
|
+
var import_pixel3_spinner = require("@mekari/pixel3-spinner");
|
|
1812
1817
|
var avatarVariantColors = ["violet", "lime", "amber", "sky", "pink", "teal", "rose", "stone"];
|
|
1813
1818
|
var getAvatarVariantColor = /* @__PURE__ */ __name((index) => {
|
|
1814
1819
|
return avatarVariantColors[index % avatarVariantColors.length];
|
|
@@ -1823,6 +1828,10 @@ var MentionList = (0, import_vue21.defineComponent)({
|
|
|
1823
1828
|
command: {
|
|
1824
1829
|
type: Function,
|
|
1825
1830
|
required: true
|
|
1831
|
+
},
|
|
1832
|
+
isLoading: {
|
|
1833
|
+
type: Boolean,
|
|
1834
|
+
default: false
|
|
1826
1835
|
}
|
|
1827
1836
|
},
|
|
1828
1837
|
setup(props, {
|
|
@@ -1907,7 +1916,16 @@ var MentionList = (0, import_vue21.defineComponent)({
|
|
|
1907
1916
|
},
|
|
1908
1917
|
"data-pixel-rte": true
|
|
1909
1918
|
}, {
|
|
1910
|
-
default: () => [
|
|
1919
|
+
default: () => [props.isLoading && (0, import_vue20.createVNode)("div", {
|
|
1920
|
+
"class": (0, import_css7.css)({
|
|
1921
|
+
display: "flex",
|
|
1922
|
+
justifyContent: "center",
|
|
1923
|
+
px: "3",
|
|
1924
|
+
py: "3"
|
|
1925
|
+
})
|
|
1926
|
+
}, [(0, import_vue20.createVNode)(import_pixel3_spinner.MpSpinner, {
|
|
1927
|
+
"size": "sm"
|
|
1928
|
+
}, null)]), !props.isLoading && !props.items.length && (0, import_vue20.createVNode)(import_pixel3_text3.MpText, {
|
|
1911
1929
|
"color": "text.secondary",
|
|
1912
1930
|
"class": (0, import_css7.css)({
|
|
1913
1931
|
px: "3",
|
|
@@ -1915,7 +1933,7 @@ var MentionList = (0, import_vue21.defineComponent)({
|
|
|
1915
1933
|
})
|
|
1916
1934
|
}, {
|
|
1917
1935
|
default: () => [(0, import_vue20.createTextVNode)("No result")]
|
|
1918
|
-
}), props.items.map((item, index) => {
|
|
1936
|
+
}), !props.isLoading && props.items.map((item, index) => {
|
|
1919
1937
|
return (0, import_vue20.createVNode)(import_pixel3_popover4.MpPopoverListItem, {
|
|
1920
1938
|
"key": `${item.id}-${index}`,
|
|
1921
1939
|
"is-active": selectedIndex.value === index,
|
|
@@ -1969,8 +1987,7 @@ var MentionList = (0, import_vue21.defineComponent)({
|
|
|
1969
1987
|
});
|
|
1970
1988
|
|
|
1971
1989
|
// src/rte-suggestion.ts
|
|
1972
|
-
var
|
|
1973
|
-
var getFilteredSuggestionItems = /* @__PURE__ */ __name((items, query) => {
|
|
1990
|
+
var getFilteredSuggestionItems = /* @__PURE__ */ __name((items, query, maxItems) => {
|
|
1974
1991
|
const normalizedQuery = query.trim().toLowerCase();
|
|
1975
1992
|
return items.filter((item) => {
|
|
1976
1993
|
var _a, _b;
|
|
@@ -1981,14 +1998,25 @@ var getFilteredSuggestionItems = /* @__PURE__ */ __name((items, query) => {
|
|
|
1981
1998
|
const label = ((_a = item.name) != null ? _a : "").toLowerCase();
|
|
1982
1999
|
const description = ((_b = item.description) != null ? _b : "").toLowerCase();
|
|
1983
2000
|
return id.includes(normalizedQuery) || label.includes(normalizedQuery) || description.includes(normalizedQuery);
|
|
1984
|
-
}).slice(0,
|
|
2001
|
+
}).slice(0, maxItems);
|
|
1985
2002
|
}, "getFilteredSuggestionItems");
|
|
1986
|
-
var createMentionSuggestion = /* @__PURE__ */ __name((
|
|
2003
|
+
var createMentionSuggestion = /* @__PURE__ */ __name((getSuggestionSource = () => [], options = {}) => {
|
|
2004
|
+
var _a;
|
|
2005
|
+
const maxItems = (_a = options.maxItems) != null ? _a : 50;
|
|
1987
2006
|
return {
|
|
1988
|
-
items: ({
|
|
2007
|
+
items: async ({
|
|
1989
2008
|
query
|
|
1990
2009
|
}) => {
|
|
1991
|
-
|
|
2010
|
+
var _a2, _b, _c;
|
|
2011
|
+
const source = getSuggestionSource();
|
|
2012
|
+
if (typeof source === "function") {
|
|
2013
|
+
const items2 = ((_a2 = await source(query)) != null ? _a2 : []).slice(0, maxItems);
|
|
2014
|
+
(_b = options.onSuggestionsChange) == null ? void 0 : _b.call(options, items2);
|
|
2015
|
+
return items2;
|
|
2016
|
+
}
|
|
2017
|
+
const items = getFilteredSuggestionItems(source != null ? source : [], query, maxItems);
|
|
2018
|
+
(_c = options.onSuggestionsChange) == null ? void 0 : _c.call(options, items);
|
|
2019
|
+
return items;
|
|
1992
2020
|
},
|
|
1993
2021
|
render: () => {
|
|
1994
2022
|
let component = null;
|
|
@@ -2049,8 +2077,8 @@ var createMentionSuggestion = /* @__PURE__ */ __name((getSuggestionItems = () =>
|
|
|
2049
2077
|
}
|
|
2050
2078
|
return {
|
|
2051
2079
|
getBoundingClientRect: () => {
|
|
2052
|
-
var
|
|
2053
|
-
return (
|
|
2080
|
+
var _a2;
|
|
2081
|
+
return (_a2 = clientRectProvider == null ? void 0 : clientRectProvider()) != null ? _a2 : new DOMRect();
|
|
2054
2082
|
}
|
|
2055
2083
|
};
|
|
2056
2084
|
}, "getVirtualElement");
|
|
@@ -2079,14 +2107,18 @@ var createMentionSuggestion = /* @__PURE__ */ __name((getSuggestionItems = () =>
|
|
|
2079
2107
|
popperInstance.update();
|
|
2080
2108
|
}, "updatePopoverPosition");
|
|
2081
2109
|
return {
|
|
2082
|
-
|
|
2110
|
+
// Fires synchronously before `items()` resolves, so the popover can
|
|
2111
|
+
// mount showing a loading state instead of a blank/"No result" flash
|
|
2112
|
+
// while the (possibly async) suggestion source is fetched.
|
|
2113
|
+
onBeforeStart: (props) => {
|
|
2083
2114
|
clientRectProvider = props.clientRect;
|
|
2084
2115
|
editorElement = props.editor.view.dom;
|
|
2085
2116
|
component = new import_vue_3.VueRenderer(MentionList, {
|
|
2086
2117
|
editor: props.editor,
|
|
2087
2118
|
props: {
|
|
2088
|
-
items:
|
|
2089
|
-
command: props.command
|
|
2119
|
+
items: [],
|
|
2120
|
+
command: props.command,
|
|
2121
|
+
isLoading: true
|
|
2090
2122
|
}
|
|
2091
2123
|
});
|
|
2092
2124
|
popoverWrapper = document.createElement("div");
|
|
@@ -2099,21 +2131,39 @@ var createMentionSuggestion = /* @__PURE__ */ __name((getSuggestionItems = () =>
|
|
|
2099
2131
|
setupOutsideListeners();
|
|
2100
2132
|
updatePopoverPosition();
|
|
2101
2133
|
},
|
|
2134
|
+
onStart: (props) => {
|
|
2135
|
+
clientRectProvider = props.clientRect;
|
|
2136
|
+
component == null ? void 0 : component.updateProps({
|
|
2137
|
+
items: props.items,
|
|
2138
|
+
command: props.command,
|
|
2139
|
+
isLoading: false
|
|
2140
|
+
});
|
|
2141
|
+
updatePopoverPosition();
|
|
2142
|
+
},
|
|
2143
|
+
// Fires before every re-fetch triggered by a query change — flips
|
|
2144
|
+
// back to the loading state until the new `items()` call resolves.
|
|
2145
|
+
onBeforeUpdate: (props) => {
|
|
2146
|
+
clientRectProvider = props.clientRect;
|
|
2147
|
+
component == null ? void 0 : component.updateProps({
|
|
2148
|
+
isLoading: true
|
|
2149
|
+
});
|
|
2150
|
+
},
|
|
2102
2151
|
onUpdate: (props) => {
|
|
2103
2152
|
clientRectProvider = props.clientRect;
|
|
2104
2153
|
component == null ? void 0 : component.updateProps({
|
|
2105
2154
|
items: props.items,
|
|
2106
|
-
command: props.command
|
|
2155
|
+
command: props.command,
|
|
2156
|
+
isLoading: false
|
|
2107
2157
|
});
|
|
2108
2158
|
updatePopoverPosition();
|
|
2109
2159
|
},
|
|
2110
2160
|
onKeyDown: (props) => {
|
|
2111
|
-
var
|
|
2161
|
+
var _a2, _b;
|
|
2112
2162
|
if (props.event.key === "Escape") {
|
|
2113
2163
|
destroyMentionPopover();
|
|
2114
2164
|
return true;
|
|
2115
2165
|
}
|
|
2116
|
-
return (_b = (
|
|
2166
|
+
return (_b = (_a2 = component == null ? void 0 : component.ref) == null ? void 0 : _a2.onKeyDown(props)) != null ? _b : false;
|
|
2117
2167
|
},
|
|
2118
2168
|
onExit: () => {
|
|
2119
2169
|
destroyMentionPopover();
|
|
@@ -2129,7 +2179,7 @@ var import_vue_32 = require("@tiptap/vue-3");
|
|
|
2129
2179
|
var import_core4 = require("@popperjs/core");
|
|
2130
2180
|
var import_state = require("@tiptap/pm/state");
|
|
2131
2181
|
var VariablePluginKey = new import_state.PluginKey("variable");
|
|
2132
|
-
var
|
|
2182
|
+
var MAX_SUGGESTION_ITEMS = 50;
|
|
2133
2183
|
var getFilteredSuggestionItems2 = /* @__PURE__ */ __name((items, query) => {
|
|
2134
2184
|
const normalizedQuery = query.trim().toLowerCase();
|
|
2135
2185
|
return items.filter((item) => {
|
|
@@ -2141,7 +2191,7 @@ var getFilteredSuggestionItems2 = /* @__PURE__ */ __name((items, query) => {
|
|
|
2141
2191
|
const name = ((_a = item.name) != null ? _a : "").toLowerCase();
|
|
2142
2192
|
const category = ((_b = item.category) != null ? _b : "").toLowerCase();
|
|
2143
2193
|
return id.includes(normalizedQuery) || name.includes(normalizedQuery) || category.includes(normalizedQuery);
|
|
2144
|
-
}).slice(0,
|
|
2194
|
+
}).slice(0, MAX_SUGGESTION_ITEMS);
|
|
2145
2195
|
}, "getFilteredSuggestionItems");
|
|
2146
2196
|
var createVariableSuggestion = /* @__PURE__ */ __name((getSuggestionItems = () => []) => {
|
|
2147
2197
|
return {
|
|
@@ -2368,8 +2418,15 @@ var MpRichTextEditor = (0, import_vue23.defineComponent)({
|
|
|
2368
2418
|
import_extension_character_count.default.configure({
|
|
2369
2419
|
limit: api.value.maxlength
|
|
2370
2420
|
}),
|
|
2371
|
-
|
|
2372
|
-
|
|
2421
|
+
// Extensions are registered once at mount, so the array-length check
|
|
2422
|
+
// here can't be reactive. A resolver function always registers the
|
|
2423
|
+
// extension — use that form when suggestions are loaded dynamically
|
|
2424
|
+
// (e.g. fetched from an API after mount).
|
|
2425
|
+
...typeof props.suggestions === "function" || props.suggestions && props.suggestions.length > 0 ? [import_extension_mention.default.configure({
|
|
2426
|
+
suggestion: createMentionSuggestion(() => props.suggestions, {
|
|
2427
|
+
maxItems: props.maxSuggestions,
|
|
2428
|
+
onSuggestionsChange: (items) => emit("suggestionsChange", items)
|
|
2429
|
+
})
|
|
2373
2430
|
})] : [],
|
|
2374
2431
|
...props.variables && props.variables.length > 0 ? [Variable.configure({
|
|
2375
2432
|
suggestion: createVariableSuggestion(() => props.variables || [])
|