@dialpad/dialtone 9.34.4 → 9.34.6

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.
Files changed (77) hide show
  1. package/README.md +28 -117
  2. package/dist/css/dialtone.css +2 -2
  3. package/dist/tokens/css/variables-dark.css +1 -1
  4. package/dist/tokens/css/variables-expressive-dark.css +1 -1
  5. package/dist/tokens/css/variables-expressive-light.css +1 -1
  6. package/dist/tokens/css/variables-expressive-sm-dark.css +1 -1
  7. package/dist/tokens/css/variables-expressive-sm-light.css +1 -1
  8. package/dist/tokens/css/variables-light.css +1 -1
  9. package/dist/tokens/css/variables-tmo-dark.css +1 -1
  10. package/dist/tokens/css/variables-tmo-light.css +1 -1
  11. package/dist/tokens/less/variables-dark.less +1 -1
  12. package/dist/tokens/less/variables-expressive-dark.less +1 -1
  13. package/dist/tokens/less/variables-expressive-light.less +1 -1
  14. package/dist/tokens/less/variables-expressive-sm-dark.less +1 -1
  15. package/dist/tokens/less/variables-expressive-sm-light.less +1 -1
  16. package/dist/tokens/less/variables-light.less +1 -1
  17. package/dist/tokens/less/variables-tmo-dark.less +1 -1
  18. package/dist/tokens/less/variables-tmo-light.less +1 -1
  19. package/dist/vue2/common/emoji.cjs +4 -1
  20. package/dist/vue2/common/emoji.cjs.map +1 -1
  21. package/dist/vue2/common/emoji.js +4 -1
  22. package/dist/vue2/common/emoji.js.map +1 -1
  23. package/dist/vue2/dialtone-vue.cjs +1 -0
  24. package/dist/vue2/dialtone-vue.cjs.map +1 -1
  25. package/dist/vue2/dialtone-vue.js +2 -1
  26. package/dist/vue2/lib/datepicker.cjs +4 -4
  27. package/dist/vue2/lib/datepicker.cjs.map +1 -1
  28. package/dist/vue2/lib/datepicker.js +4 -4
  29. package/dist/vue2/lib/datepicker.js.map +1 -1
  30. package/dist/vue2/lib/rich-text-editor.cjs +22 -9
  31. package/dist/vue2/lib/rich-text-editor.cjs.map +1 -1
  32. package/dist/vue2/lib/rich-text-editor.js +22 -9
  33. package/dist/vue2/lib/rich-text-editor.js.map +1 -1
  34. package/dist/vue2/types/common/emoji/index.d.ts +11 -2
  35. package/dist/vue2/types/common/emoji/index.d.ts.map +1 -1
  36. package/dist/vue2/types/components/rich_text_editor/extensions/emoji/emoji.d.ts +0 -1
  37. package/dist/vue2/types/components/rich_text_editor/extensions/emoji/emoji.d.ts.map +1 -1
  38. package/dist/vue2/types/components/rich_text_editor/rich_text_editor.vue.d.ts +1 -1
  39. package/dist/vue2/types/components/rich_text_editor/rich_text_editor.vue.d.ts.map +1 -1
  40. package/dist/vue3/common/emoji.cjs +4 -1
  41. package/dist/vue3/common/emoji.cjs.map +1 -1
  42. package/dist/vue3/common/emoji.js +4 -1
  43. package/dist/vue3/common/emoji.js.map +1 -1
  44. package/dist/vue3/dialtone-vue.cjs +1 -0
  45. package/dist/vue3/dialtone-vue.cjs.map +1 -1
  46. package/dist/vue3/dialtone-vue.js +2 -1
  47. package/dist/vue3/lib/datepicker.cjs +8 -4
  48. package/dist/vue3/lib/datepicker.cjs.map +1 -1
  49. package/dist/vue3/lib/datepicker.js +8 -4
  50. package/dist/vue3/lib/datepicker.js.map +1 -1
  51. package/dist/vue3/lib/message-input.cjs +32 -3
  52. package/dist/vue3/lib/message-input.cjs.map +1 -1
  53. package/dist/vue3/lib/message-input.js +32 -3
  54. package/dist/vue3/lib/message-input.js.map +1 -1
  55. package/dist/vue3/lib/rich-text-editor.cjs +271 -35
  56. package/dist/vue3/lib/rich-text-editor.cjs.map +1 -1
  57. package/dist/vue3/lib/rich-text-editor.js +272 -36
  58. package/dist/vue3/lib/rich-text-editor.js.map +1 -1
  59. package/dist/vue3/types/common/emoji/index.d.ts +1 -0
  60. package/dist/vue3/types/common/emoji/index.d.ts.map +1 -1
  61. package/dist/vue3/types/components/rich_text_editor/extensions/emoji/emoji.d.ts +0 -1
  62. package/dist/vue3/types/components/rich_text_editor/extensions/emoji/emoji.d.ts.map +1 -1
  63. package/dist/vue3/types/components/rich_text_editor/extensions/slash_command/SlashCommandComponent.vue.d.ts +73 -0
  64. package/dist/vue3/types/components/rich_text_editor/extensions/slash_command/SlashCommandComponent.vue.d.ts.map +1 -0
  65. package/dist/vue3/types/components/rich_text_editor/extensions/slash_command/SlashCommandSuggestion.vue.d.ts +17 -0
  66. package/dist/vue3/types/components/rich_text_editor/extensions/slash_command/SlashCommandSuggestion.vue.d.ts.map +1 -0
  67. package/dist/vue3/types/components/rich_text_editor/extensions/slash_command/slash_command.d.ts +2 -0
  68. package/dist/vue3/types/components/rich_text_editor/extensions/slash_command/slash_command.d.ts.map +1 -0
  69. package/dist/vue3/types/components/rich_text_editor/extensions/slash_command/suggestion.d.ts +12 -0
  70. package/dist/vue3/types/components/rich_text_editor/extensions/slash_command/suggestion.d.ts.map +1 -0
  71. package/dist/vue3/types/components/rich_text_editor/rich_text_editor.vue.d.ts +38 -1
  72. package/dist/vue3/types/components/rich_text_editor/rich_text_editor.vue.d.ts.map +1 -1
  73. package/dist/vue3/types/components/rich_text_editor/slash_command_suggestion.d.ts +15 -0
  74. package/dist/vue3/types/components/rich_text_editor/slash_command_suggestion.d.ts.map +1 -0
  75. package/dist/vue3/types/recipes/conversation_view/message_input/message_input.vue.d.ts +38 -1
  76. package/dist/vue3/types/recipes/conversation_view/message_input/message_input.vue.d.ts.map +1 -1
  77. package/package.json +3 -3
@@ -16,10 +16,10 @@ import Underline from "@tiptap/extension-underline";
16
16
  import Text from "@tiptap/extension-text";
17
17
  import TextAlign from "@tiptap/extension-text-align";
18
18
  import { Node, mergeAttributes, nodeInputRule, nodePasteRule, getMarksBetween, combineTransactionSteps, getChangedRanges, findChildrenInRange, Mark } from "@tiptap/core";
19
- import { resolveComponent, openBlock, createBlock, withCtx, createVNode, createElementBlock, withDirectives, createElementVNode, Fragment, renderList, normalizeClass, withModifiers, resolveDynamicComponent, vShow, createTextVNode, toDisplayString, markRaw } from "vue";
19
+ import { resolveComponent, openBlock, createBlock, withCtx, createVNode, createElementBlock, withDirectives, createElementVNode, Fragment, renderList, normalizeClass, withModifiers, resolveDynamicComponent, vShow, createTextVNode, toDisplayString, markRaw, createCommentVNode } from "vue";
20
20
  import { _export_sfc } from "../chunks/_plugin-vue_export-helper-caHeSgYY.js";
21
21
  import { DtEmoji } from "./emoji.js";
22
- import { codeToEmojiData } from "../common/emoji.js";
22
+ import { codeToEmojiData, emojiShortCodeRegex } from "../common/emoji.js";
23
23
  import { PluginKey, Plugin } from "@tiptap/pm/state";
24
24
  import Suggestion from "@tiptap/suggestion";
25
25
  import { emojisIndexed } from "@dialpad/dialtone-emojis";
@@ -44,7 +44,7 @@ import "../chunks/stack_constants-HraCekPm.js";
44
44
  import "../common/constants.js";
45
45
  import "../chunks/link_constants-nWVlXQBs.js";
46
46
  import "./presence.js";
47
- const _sfc_main$7 = {
47
+ const _sfc_main$9 = {
48
48
  name: "EmojiComponent",
49
49
  components: {
50
50
  NodeViewWrapper,
@@ -52,7 +52,7 @@ const _sfc_main$7 = {
52
52
  },
53
53
  props: nodeViewProps
54
54
  };
55
- function _sfc_render$7(_ctx, _cache, $props, $setup, $data, $options) {
55
+ function _sfc_render$9(_ctx, _cache, $props, $setup, $data, $options) {
56
56
  const _component_dt_emoji = resolveComponent("dt-emoji");
57
57
  const _component_node_view_wrapper = resolveComponent("node-view-wrapper");
58
58
  return openBlock(), createBlock(_component_node_view_wrapper, { class: "d-d-inline-block d-va-bottom d-lh0" }, {
@@ -65,8 +65,8 @@ function _sfc_render$7(_ctx, _cache, $props, $setup, $data, $options) {
65
65
  _: 1
66
66
  });
67
67
  }
68
- const EmojiComponent = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["render", _sfc_render$7]]);
69
- const _sfc_main$6 = {
68
+ const EmojiComponent = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["render", _sfc_render$9]]);
69
+ const _sfc_main$8 = {
70
70
  name: "SuggestionList",
71
71
  components: {
72
72
  DtListItem
@@ -149,19 +149,22 @@ const _sfc_main$6 = {
149
149
  case "channel":
150
150
  this.command({ name: item.name, id: item.id });
151
151
  break;
152
+ case "slash-command":
153
+ this.command({ command: item.command });
154
+ break;
152
155
  }
153
156
  }
154
157
  }
155
158
  };
156
- const _hoisted_1 = { class: "d-popover__dialog" };
157
- const _hoisted_2 = {
159
+ const _hoisted_1$1 = { class: "d-popover__dialog" };
160
+ const _hoisted_2$1 = {
158
161
  ref: "suggestionList",
159
162
  class: "dt-suggestion-list"
160
163
  };
161
- function _sfc_render$6(_ctx, _cache, $props, $setup, $data, $options) {
164
+ function _sfc_render$8(_ctx, _cache, $props, $setup, $data, $options) {
162
165
  const _component_dt_list_item = resolveComponent("dt-list-item");
163
- return openBlock(), createElementBlock("div", _hoisted_1, [
164
- withDirectives(createElementVNode("ul", _hoisted_2, [
166
+ return openBlock(), createElementBlock("div", _hoisted_1$1, [
167
+ withDirectives(createElementVNode("ul", _hoisted_2$1, [
165
168
  (openBlock(true), createElementBlock(Fragment, null, renderList($props.items, (item, index) => {
166
169
  return openBlock(), createBlock(_component_dt_list_item, {
167
170
  key: item.id,
@@ -184,8 +187,8 @@ function _sfc_render$6(_ctx, _cache, $props, $setup, $data, $options) {
184
187
  ])
185
188
  ]);
186
189
  }
187
- const SuggestionList = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["render", _sfc_render$6]]);
188
- const _sfc_main$5 = {
190
+ const SuggestionList = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["render", _sfc_render$8]]);
191
+ const _sfc_main$7 = {
189
192
  name: "EmojiSuggestion",
190
193
  components: {
191
194
  DtEmoji,
@@ -198,7 +201,7 @@ const _sfc_main$5 = {
198
201
  }
199
202
  }
200
203
  };
201
- function _sfc_render$5(_ctx, _cache, $props, $setup, $data, $options) {
204
+ function _sfc_render$7(_ctx, _cache, $props, $setup, $data, $options) {
202
205
  const _component_dt_emoji = resolveComponent("dt-emoji");
203
206
  const _component_dt_stack = resolveComponent("dt-stack");
204
207
  return openBlock(), createBlock(_component_dt_stack, {
@@ -215,7 +218,7 @@ function _sfc_render$5(_ctx, _cache, $props, $setup, $data, $options) {
215
218
  _: 1
216
219
  });
217
220
  }
218
- const EmojiSuggestion = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["render", _sfc_render$5]]);
221
+ const EmojiSuggestion = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["render", _sfc_render$7]]);
219
222
  const suggestionOptions = {
220
223
  items: ({ query }) => {
221
224
  if (query.length < 2) {
@@ -304,15 +307,15 @@ const suggestionOptions = {
304
307
  }
305
308
  };
306
309
  const EmojiPluginKey = new PluginKey("emoji");
307
- const inputShortCodeRegex = /:\w+:$/;
308
- const emojiShortCodeRegex = /:\w+:/g;
310
+ const inputShortCodeRegex = new RegExp("(^| |(?<=:))(:\\w+:)$");
309
311
  const inputUnicodeRegex = /(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])$/;
310
312
  const pasteUnicodeRegex = /(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])/g;
311
313
  const inputRuleMatch = (match) => {
312
314
  if (match && codeToEmojiData(match[0])) {
315
+ const text = match[2] || match[0];
313
316
  return {
314
317
  index: match.index,
315
- text: match[0],
318
+ text,
316
319
  match
317
320
  };
318
321
  }
@@ -371,6 +374,8 @@ const Emoji = Node.create({
371
374
  nodeInputRule({
372
375
  find: (text) => {
373
376
  const match = text.match(inputShortCodeRegex);
377
+ if (!match)
378
+ return;
374
379
  return inputRuleMatch(match);
375
380
  },
376
381
  type: this.type,
@@ -383,6 +388,8 @@ const Emoji = Node.create({
383
388
  nodeInputRule({
384
389
  find: (text) => {
385
390
  const match = text.match(inputUnicodeRegex);
391
+ if (!match)
392
+ return;
386
393
  return inputRuleMatch(match);
387
394
  },
388
395
  type: this.type,
@@ -590,7 +597,7 @@ const Link = Mark.create({
590
597
  ];
591
598
  }
592
599
  });
593
- const _sfc_main$4 = {
600
+ const _sfc_main$6 = {
594
601
  name: "MentionComponent",
595
602
  components: {
596
603
  NodeViewWrapper,
@@ -603,7 +610,7 @@ const _sfc_main$4 = {
603
610
  }
604
611
  }
605
612
  };
606
- function _sfc_render$4(_ctx, _cache, $props, $setup, $data, $options) {
613
+ function _sfc_render$6(_ctx, _cache, $props, $setup, $data, $options) {
607
614
  const _component_dt_link = resolveComponent("dt-link");
608
615
  const _component_node_view_wrapper = resolveComponent("node-view-wrapper");
609
616
  return openBlock(), createBlock(_component_node_view_wrapper, { class: "d-d-inline-block" }, {
@@ -618,7 +625,7 @@ function _sfc_render$4(_ctx, _cache, $props, $setup, $data, $options) {
618
625
  _: 1
619
626
  });
620
627
  }
621
- const MentionComponent = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["render", _sfc_render$4]]);
628
+ const MentionComponent = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["render", _sfc_render$6]]);
622
629
  const mentionRegex = /@([\w.-]+)[^\w.-]?/g;
623
630
  const mentionPasteMatch = (text, suggestions) => {
624
631
  const matches = [...text.matchAll(mentionRegex)];
@@ -705,7 +712,7 @@ const MentionPlugin = Mention.extend({
705
712
  pluginKey: new PluginKey("mentionSuggestion")
706
713
  }
707
714
  });
708
- const _sfc_main$3 = {
715
+ const _sfc_main$5 = {
709
716
  name: "ChannelComponent",
710
717
  components: {
711
718
  NodeViewWrapper,
@@ -718,7 +725,7 @@ const _sfc_main$3 = {
718
725
  }
719
726
  }
720
727
  };
721
- function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) {
728
+ function _sfc_render$5(_ctx, _cache, $props, $setup, $data, $options) {
722
729
  const _component_dt_link = resolveComponent("dt-link");
723
730
  const _component_node_view_wrapper = resolveComponent("node-view-wrapper");
724
731
  return openBlock(), createBlock(_component_node_view_wrapper, { class: "d-d-inline-block" }, {
@@ -733,7 +740,7 @@ function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) {
733
740
  _: 1
734
741
  });
735
742
  }
736
- const ChannelComponent = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", _sfc_render$3]]);
743
+ const ChannelComponent = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["render", _sfc_render$5]]);
737
744
  const channelRegex = /#([\w-]+)[^\w-]?/g;
738
745
  const channelPasteMatch = (text, suggestions) => {
739
746
  const matches = [...text.matchAll(channelRegex)];
@@ -823,6 +830,112 @@ const ChannelPlugin = Mention.extend({
823
830
  pluginKey: new PluginKey("channelSuggestion")
824
831
  }
825
832
  });
833
+ const _sfc_main$4 = {
834
+ name: "SlashCommandsComponent",
835
+ components: {
836
+ NodeViewWrapper
837
+ },
838
+ props: nodeViewProps,
839
+ emits: ["selected-command"],
840
+ computed: {
841
+ text() {
842
+ return "/" + this.$props.node.attrs.command;
843
+ }
844
+ },
845
+ created() {
846
+ this.$parent.$emit("selected-command", this.$props.node.attrs.command);
847
+ }
848
+ };
849
+ function _sfc_render$4(_ctx, _cache, $props, $setup, $data, $options) {
850
+ const _component_node_view_wrapper = resolveComponent("node-view-wrapper");
851
+ return openBlock(), createBlock(_component_node_view_wrapper, { class: "d-d-inline-block" }, {
852
+ default: withCtx(() => [
853
+ createTextVNode(toDisplayString($options.text), 1)
854
+ ]),
855
+ _: 1
856
+ });
857
+ }
858
+ const SlashCommandComponent = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["render", _sfc_render$4]]);
859
+ const slashCommandPasteMatch = (text, slashCommandRegex) => {
860
+ const matches = [...text.matchAll(slashCommandRegex)];
861
+ return matches.map((match) => {
862
+ let slashCommand = match[2];
863
+ if (!slashCommand.endsWith(" "))
864
+ slashCommand += " ";
865
+ return {
866
+ index: match.index,
867
+ text: slashCommand,
868
+ match
869
+ };
870
+ });
871
+ };
872
+ const SlashCommandPlugin = Mention.extend({
873
+ name: "slash-commands",
874
+ group: "inline",
875
+ inline: true,
876
+ addNodeView() {
877
+ return VueNodeViewRenderer(SlashCommandComponent);
878
+ },
879
+ parseHTML() {
880
+ return [
881
+ {
882
+ tag: "command-component"
883
+ }
884
+ ];
885
+ },
886
+ addAttributes() {
887
+ return {
888
+ command: {
889
+ default: ""
890
+ },
891
+ parametersExample: {
892
+ default: ""
893
+ },
894
+ description: {
895
+ default: ""
896
+ }
897
+ };
898
+ },
899
+ renderText({ node }) {
900
+ return `/${node.attrs.command}`;
901
+ },
902
+ renderHTML({ HTMLAttributes }) {
903
+ return ["command-component", mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)];
904
+ },
905
+ addInputRules() {
906
+ var _a;
907
+ const suggestions = (_a = this.options.suggestion) == null ? void 0 : _a.items({ query: "" }).map((suggestion) => suggestion.command);
908
+ const slashCommandRegex = new RegExp(`^((?:\\/)(${suggestions.join("|")})) $`);
909
+ return [
910
+ nodeInputRule({
911
+ find: slashCommandRegex,
912
+ type: this.type,
913
+ getAttributes(attrs) {
914
+ return { command: attrs[2] };
915
+ }
916
+ })
917
+ ];
918
+ },
919
+ addPasteRules() {
920
+ var _a;
921
+ const suggestions = (_a = this.options.suggestion) == null ? void 0 : _a.items({ query: "" }).map((suggestion) => suggestion.command);
922
+ const slashCommandRegex = new RegExp(`^((?:\\/)(${suggestions.join("|")})) ?$`, "g");
923
+ return [
924
+ nodePasteRule({
925
+ find: (text) => slashCommandPasteMatch(text, slashCommandRegex),
926
+ type: this.type,
927
+ getAttributes(attrs) {
928
+ return { command: attrs[0].trim() };
929
+ }
930
+ })
931
+ ];
932
+ }
933
+ }).configure({
934
+ suggestion: {
935
+ char: "/",
936
+ pluginKey: new PluginKey("slashCommandSuggestion")
937
+ }
938
+ });
826
939
  const RICH_TEXT_EDITOR_OUTPUT_FORMATS = [
827
940
  "text",
828
941
  "json",
@@ -841,7 +954,7 @@ const RICH_TEXT_EDITOR_SUPPORTED_LINK_PROTOCOLS = [
841
954
  "sftp",
842
955
  "mailto"
843
956
  ];
844
- const _sfc_main$2 = {
957
+ const _sfc_main$3 = {
845
958
  name: "MentionSuggestion",
846
959
  components: {
847
960
  DtAvatar,
@@ -862,7 +975,7 @@ const _sfc_main$2 = {
862
975
  }
863
976
  }
864
977
  };
865
- function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
978
+ function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) {
866
979
  const _component_dt_avatar = resolveComponent("dt-avatar");
867
980
  const _component_dt_stack = resolveComponent("dt-stack");
868
981
  return openBlock(), createBlock(_component_dt_stack, {
@@ -881,7 +994,7 @@ function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
881
994
  _: 1
882
995
  });
883
996
  }
884
- const MentionSuggestion = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$2]]);
997
+ const MentionSuggestion = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", _sfc_render$3]]);
885
998
  const mentionSuggestion = {
886
999
  // This function comes from the user and passed to the editor directly.
887
1000
  // This will also activate the mention plugin on the editor
@@ -936,7 +1049,7 @@ const mentionSuggestion = {
936
1049
  };
937
1050
  }
938
1051
  };
939
- const _sfc_main$1 = {
1052
+ const _sfc_main$2 = {
940
1053
  name: "ChannelSuggestion",
941
1054
  components: {
942
1055
  DtStack,
@@ -955,7 +1068,7 @@ const _sfc_main$1 = {
955
1068
  }
956
1069
  }
957
1070
  };
958
- function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
1071
+ function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
959
1072
  const _component_dt_icon_hash = resolveComponent("dt-icon-hash");
960
1073
  const _component_dt_icon_lock = resolveComponent("dt-icon-lock");
961
1074
  const _component_dt_stack = resolveComponent("dt-stack");
@@ -976,7 +1089,7 @@ function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
976
1089
  _: 1
977
1090
  });
978
1091
  }
979
- const ChannelSuggestion = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render$1]]);
1092
+ const ChannelSuggestion = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$2]]);
980
1093
  const channelSuggestion = {
981
1094
  // This function comes from the user and passed to the editor directly.
982
1095
  // This will also activate the mention plugin on the editor
@@ -1031,6 +1144,95 @@ const channelSuggestion = {
1031
1144
  };
1032
1145
  }
1033
1146
  };
1147
+ const _sfc_main$1 = {
1148
+ name: "SlashCommandSuggestion",
1149
+ props: {
1150
+ item: {
1151
+ type: Object,
1152
+ required: true
1153
+ }
1154
+ },
1155
+ computed: {
1156
+ command() {
1157
+ return this.item.command;
1158
+ },
1159
+ description() {
1160
+ return this.item.description;
1161
+ },
1162
+ parametersExample() {
1163
+ return this.item.parametersExample;
1164
+ }
1165
+ }
1166
+ };
1167
+ const _hoisted_1 = { class: "d-body--md-compact" };
1168
+ const _hoisted_2 = { key: 0 };
1169
+ const _hoisted_3 = { class: "d-body--sm" };
1170
+ function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
1171
+ return openBlock(), createElementBlock("div", null, [
1172
+ createElementVNode("div", _hoisted_1, [
1173
+ createElementVNode("span", null, "/" + toDisplayString($options.command), 1),
1174
+ $options.parametersExample ? (openBlock(), createElementBlock("span", _hoisted_2, toDisplayString($options.parametersExample), 1)) : createCommentVNode("", true)
1175
+ ]),
1176
+ createElementVNode("div", _hoisted_3, toDisplayString($options.description), 1)
1177
+ ]);
1178
+ }
1179
+ const SlashCommandSuggestion = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render$1]]);
1180
+ const slashCommandSuggestion = {
1181
+ // This function comes from the user and passed to the editor directly.
1182
+ // This will also activate the mention plugin on the editor
1183
+ // items: ({ query }) => { return [] },
1184
+ allowSpaces: true,
1185
+ startOfLine: true,
1186
+ render: () => {
1187
+ let component;
1188
+ let popup;
1189
+ return {
1190
+ onStart: (props) => {
1191
+ component = new VueRenderer(SuggestionList, {
1192
+ parent: void 0,
1193
+ props: {
1194
+ itemComponent: markRaw(SlashCommandSuggestion),
1195
+ itemType: "slash-command",
1196
+ ...props
1197
+ },
1198
+ editor: props.editor
1199
+ });
1200
+ if (!props.clientRect) {
1201
+ return;
1202
+ }
1203
+ popup = tippy("body", {
1204
+ getReferenceClientRect: props.clientRect,
1205
+ appendTo: () => document.body,
1206
+ content: component.element,
1207
+ showOnCreate: true,
1208
+ interactive: true,
1209
+ trigger: "manual",
1210
+ placement: "top-start"
1211
+ });
1212
+ },
1213
+ onUpdate(props) {
1214
+ component.updateProps(props);
1215
+ if (!props.clientRect) {
1216
+ return;
1217
+ }
1218
+ popup[0].setProps({
1219
+ getReferenceClientRect: props.clientRect
1220
+ });
1221
+ },
1222
+ onKeyDown(props) {
1223
+ if (props.event.key === "Escape") {
1224
+ popup[0].hide();
1225
+ return true;
1226
+ }
1227
+ return component == null ? void 0 : component.ref.onKeyDown(props);
1228
+ },
1229
+ onExit() {
1230
+ popup[0].destroy();
1231
+ component.destroy();
1232
+ }
1233
+ };
1234
+ }
1235
+ };
1034
1236
  const _sfc_main = {
1035
1237
  name: "DtRichTextEditor",
1036
1238
  components: {
@@ -1153,6 +1355,23 @@ const _sfc_main = {
1153
1355
  type: Object,
1154
1356
  default: null
1155
1357
  },
1358
+ /**
1359
+ * suggestion object containing the items query function.
1360
+ * The valid keys passed into this object can be found here: https://tiptap.dev/api/utilities/suggestion
1361
+ *
1362
+ * The only required key is the items function which is used to query the slash commands for suggestion.
1363
+ * items({ query }) => { return [SlashCommandObject]; }
1364
+ * SlashCommandObject format:
1365
+ * { command: string, description: string, parametersExample?: string }
1366
+ * The "parametersExample" parameter is optional, and describes an example
1367
+ * of the parameters that command can take.
1368
+ *
1369
+ * When null, it does not add the plugin.
1370
+ */
1371
+ slashCommandSuggestion: {
1372
+ type: Object,
1373
+ default: null
1374
+ },
1156
1375
  /**
1157
1376
  * Whether the input allows for block quote.
1158
1377
  */
@@ -1220,7 +1439,14 @@ const _sfc_main = {
1220
1439
  * @event focus
1221
1440
  * @type {FocusEvent}
1222
1441
  */
1223
- "focus"
1442
+ "focus",
1443
+ /**
1444
+ * Fires when a slash command is selected
1445
+ *
1446
+ * @event selected-command
1447
+ * @type {String}
1448
+ */
1449
+ "selected-command"
1224
1450
  ],
1225
1451
  data() {
1226
1452
  return {
@@ -1290,6 +1516,10 @@ const _sfc_main = {
1290
1516
  const suggestionObject = { ...this.channelSuggestion, ...channelSuggestion };
1291
1517
  extensions.push(ChannelPlugin.configure({ suggestion: suggestionObject }));
1292
1518
  }
1519
+ if (this.slashCommandSuggestion) {
1520
+ const suggestionObject = { ...this.slashCommandSuggestion, ...slashCommandSuggestion };
1521
+ extensions.push(SlashCommandPlugin.configure({ suggestion: suggestionObject }));
1522
+ }
1293
1523
  extensions.push(Emoji);
1294
1524
  extensions.push(TextAlign.configure({
1295
1525
  types: ["paragraph"],
@@ -1354,6 +1584,9 @@ const _sfc_main = {
1354
1584
  this.destroyEditor();
1355
1585
  },
1356
1586
  methods: {
1587
+ onSelectedCommand(command) {
1588
+ this.$emit("selected-command", command);
1589
+ },
1357
1590
  createEditor() {
1358
1591
  this.editor = new Editor({
1359
1592
  autofocus: this.autoFocus,
@@ -1382,14 +1615,16 @@ const _sfc_main = {
1382
1615
  this.editor.commands.setContent(this.internalValue, true);
1383
1616
  },
1384
1617
  parseEmojis() {
1385
- const matches = [...this.modelValue.matchAll(emojiRegex()), ...this.modelValue.matchAll(emojiShortCodeRegex)];
1618
+ const matches = new Set(
1619
+ [...this.modelValue.matchAll(emojiRegex()), ...this.modelValue.matchAll(emojiShortCodeRegex)].map((match) => match[0].trim())
1620
+ );
1386
1621
  if (!matches)
1387
1622
  return;
1388
1623
  matches.forEach((match) => {
1389
- const emoji = codeToEmojiData(match[0]);
1624
+ const emoji = codeToEmojiData(match);
1390
1625
  if (!emoji)
1391
1626
  return;
1392
- this.internalValue = this.internalValue.replace(new RegExp(` ${match[0]}`), ` <emoji-component code="${emoji.shortname}"></emoji-component>`);
1627
+ this.internalValue = this.internalValue.replace(new RegExp(`${match}`, "g"), `<emoji-component code="${emoji.shortname}"></emoji-component>`);
1393
1628
  });
1394
1629
  },
1395
1630
  parseChannels() {
@@ -1473,8 +1708,9 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
1473
1708
  return openBlock(), createBlock(_component_editor_content, {
1474
1709
  editor: $data.editor,
1475
1710
  "data-qa": "dt-rich-text-editor",
1476
- class: "dt-rich-text-editor"
1477
- }, null, 8, ["editor"]);
1711
+ class: "dt-rich-text-editor",
1712
+ onSelectedCommand: $options.onSelectedCommand
1713
+ }, null, 8, ["editor", "onSelectedCommand"]);
1478
1714
  }
1479
1715
  const DtRichTextEditor = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]);
1480
1716
  export {