@react-email/editor 0.0.0-experimental.14 → 0.0.0-experimental.15
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/index.cjs +485 -0
- package/dist/index.d.cts +123 -46
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +120 -43
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +465 -3
- package/dist/index.mjs.map +1 -1
- package/dist/ui/bubble-menu/bubble-menu.css +32 -17
- package/dist/ui/slash-command/slash-command.css +44 -0
- package/dist/ui/themes/default.css +241 -31
- package/package.json +6 -1
package/dist/index.mjs
CHANGED
|
@@ -9,11 +9,14 @@ import { Decoration, DecorationSet } from "@tiptap/pm/view";
|
|
|
9
9
|
import { fromHtml } from "hast-util-from-html";
|
|
10
10
|
import Prism from "prismjs";
|
|
11
11
|
import TipTapPlaceholder from "@tiptap/extension-placeholder";
|
|
12
|
-
import { useCurrentEditor, useEditorState } from "@tiptap/react";
|
|
13
|
-
import { AlignCenterIcon, AlignLeftIcon, AlignRightIcon, BoldIcon, CaseUpperIcon, Check, ChevronDown, Code, CodeIcon, ExternalLinkIcon, Heading1, Heading2, Heading3, ItalicIcon, LinkIcon, List, ListOrdered, PencilIcon, StrikethroughIcon, TextIcon, TextQuote, UnderlineIcon, UnlinkIcon } from "lucide-react";
|
|
12
|
+
import { ReactRenderer, useCurrentEditor, useEditorState } from "@tiptap/react";
|
|
13
|
+
import { AlignCenterIcon, AlignLeftIcon, AlignRightIcon, BoldIcon, CaseUpperIcon, Check, ChevronDown, Code, CodeIcon, Columns2, Columns3, Columns4, ExternalLinkIcon, Heading1, Heading2, Heading3, ItalicIcon, LinkIcon, List, ListOrdered, MousePointer, PencilIcon, Rows2, SplitSquareVertical, SquareCode, StrikethroughIcon, Text, TextIcon, TextQuote, UnderlineIcon, UnlinkIcon } from "lucide-react";
|
|
14
14
|
import * as React from "react";
|
|
15
|
+
import { useCallback, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState } from "react";
|
|
15
16
|
import * as Popover from "@radix-ui/react-popover";
|
|
16
17
|
import { BubbleMenu as BubbleMenu$1 } from "@tiptap/react/menus";
|
|
18
|
+
import Suggestion from "@tiptap/suggestion";
|
|
19
|
+
import tippy from "tippy.js";
|
|
17
20
|
|
|
18
21
|
//#region src/core/email-node.ts
|
|
19
22
|
var EmailNode = class EmailNode extends Node {
|
|
@@ -2881,5 +2884,464 @@ const LinkBubbleMenu = {
|
|
|
2881
2884
|
};
|
|
2882
2885
|
|
|
2883
2886
|
//#endregion
|
|
2884
|
-
|
|
2887
|
+
//#region src/ui/slash-command/utils.ts
|
|
2888
|
+
function isInsideNode(editor, type) {
|
|
2889
|
+
const { $from } = editor.state.selection;
|
|
2890
|
+
for (let d = $from.depth; d > 0; d--) if ($from.node(d).type.name === type) return true;
|
|
2891
|
+
return false;
|
|
2892
|
+
}
|
|
2893
|
+
function isAtMaxColumnsDepth(editor) {
|
|
2894
|
+
const { from } = editor.state.selection;
|
|
2895
|
+
return getColumnsDepth(editor.state.doc, from) >= MAX_COLUMNS_DEPTH;
|
|
2896
|
+
}
|
|
2897
|
+
function updateScrollView(container, item) {
|
|
2898
|
+
const containerRect = container.getBoundingClientRect();
|
|
2899
|
+
const itemRect = item.getBoundingClientRect();
|
|
2900
|
+
if (itemRect.top < containerRect.top) container.scrollTop -= containerRect.top - itemRect.top;
|
|
2901
|
+
else if (itemRect.bottom > containerRect.bottom) container.scrollTop += itemRect.bottom - containerRect.bottom;
|
|
2902
|
+
}
|
|
2903
|
+
|
|
2904
|
+
//#endregion
|
|
2905
|
+
//#region src/ui/slash-command/command-list.tsx
|
|
2906
|
+
const CATEGORY_ORDER = [
|
|
2907
|
+
"Text",
|
|
2908
|
+
"Media",
|
|
2909
|
+
"Layout",
|
|
2910
|
+
"Utility"
|
|
2911
|
+
];
|
|
2912
|
+
function groupByCategory(items) {
|
|
2913
|
+
const seen = /* @__PURE__ */ new Map();
|
|
2914
|
+
for (const item of items) {
|
|
2915
|
+
const existing = seen.get(item.category);
|
|
2916
|
+
if (existing) existing.push(item);
|
|
2917
|
+
else seen.set(item.category, [item]);
|
|
2918
|
+
}
|
|
2919
|
+
const ordered = [];
|
|
2920
|
+
for (const cat of CATEGORY_ORDER) {
|
|
2921
|
+
const group = seen.get(cat);
|
|
2922
|
+
if (group) {
|
|
2923
|
+
ordered.push({
|
|
2924
|
+
category: cat,
|
|
2925
|
+
items: group
|
|
2926
|
+
});
|
|
2927
|
+
seen.delete(cat);
|
|
2928
|
+
}
|
|
2929
|
+
}
|
|
2930
|
+
for (const [category, group] of seen) ordered.push({
|
|
2931
|
+
category,
|
|
2932
|
+
items: group
|
|
2933
|
+
});
|
|
2934
|
+
return ordered;
|
|
2935
|
+
}
|
|
2936
|
+
function CommandItem({ item, selected, onSelect }) {
|
|
2937
|
+
const Icon = item.icon;
|
|
2938
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
2939
|
+
"data-re-slash-command-item": "",
|
|
2940
|
+
"data-selected": selected || void 0,
|
|
2941
|
+
onClick: onSelect,
|
|
2942
|
+
type: "button",
|
|
2943
|
+
children: [/* @__PURE__ */ jsx(Icon, { size: 20 }), /* @__PURE__ */ jsx("span", { children: item.title })]
|
|
2944
|
+
});
|
|
2945
|
+
}
|
|
2946
|
+
function CommandList({ items, command, query, ref }) {
|
|
2947
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
2948
|
+
const containerRef = useRef(null);
|
|
2949
|
+
useEffect(() => {
|
|
2950
|
+
setSelectedIndex(0);
|
|
2951
|
+
}, [items]);
|
|
2952
|
+
useLayoutEffect(() => {
|
|
2953
|
+
const container = containerRef.current;
|
|
2954
|
+
if (!container) return;
|
|
2955
|
+
const selected = container.querySelector("[data-selected]");
|
|
2956
|
+
if (selected) updateScrollView(container, selected);
|
|
2957
|
+
}, [selectedIndex]);
|
|
2958
|
+
const selectItem = useCallback((index) => {
|
|
2959
|
+
const item = items[index];
|
|
2960
|
+
if (item) command(item);
|
|
2961
|
+
}, [items, command]);
|
|
2962
|
+
useImperativeHandle(ref, () => ({ onKeyDown: ({ event }) => {
|
|
2963
|
+
if (items.length === 0) return false;
|
|
2964
|
+
if (event.key === "ArrowUp") {
|
|
2965
|
+
setSelectedIndex((i) => (i + items.length - 1) % items.length);
|
|
2966
|
+
return true;
|
|
2967
|
+
}
|
|
2968
|
+
if (event.key === "ArrowDown") {
|
|
2969
|
+
setSelectedIndex((i) => (i + 1) % items.length);
|
|
2970
|
+
return true;
|
|
2971
|
+
}
|
|
2972
|
+
if (event.key === "Enter") {
|
|
2973
|
+
selectItem(selectedIndex);
|
|
2974
|
+
return true;
|
|
2975
|
+
}
|
|
2976
|
+
return false;
|
|
2977
|
+
} }), [
|
|
2978
|
+
items.length,
|
|
2979
|
+
selectItem,
|
|
2980
|
+
selectedIndex
|
|
2981
|
+
]);
|
|
2982
|
+
if (items.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
2983
|
+
"data-re-slash-command": "",
|
|
2984
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
2985
|
+
"data-re-slash-command-empty": "",
|
|
2986
|
+
children: "No results"
|
|
2987
|
+
})
|
|
2988
|
+
});
|
|
2989
|
+
if (query.trim().length > 0) return /* @__PURE__ */ jsx("div", {
|
|
2990
|
+
"data-re-slash-command": "",
|
|
2991
|
+
ref: containerRef,
|
|
2992
|
+
children: items.map((item, index) => /* @__PURE__ */ jsx(CommandItem, {
|
|
2993
|
+
item,
|
|
2994
|
+
onSelect: () => selectItem(index),
|
|
2995
|
+
selected: index === selectedIndex
|
|
2996
|
+
}, item.title))
|
|
2997
|
+
});
|
|
2998
|
+
const groups = groupByCategory(items);
|
|
2999
|
+
let flatIndex = 0;
|
|
3000
|
+
return /* @__PURE__ */ jsx("div", {
|
|
3001
|
+
"data-re-slash-command": "",
|
|
3002
|
+
ref: containerRef,
|
|
3003
|
+
children: groups.map((group) => /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
|
|
3004
|
+
"data-re-slash-command-category": "",
|
|
3005
|
+
children: group.category
|
|
3006
|
+
}), group.items.map((item) => {
|
|
3007
|
+
const currentIndex = flatIndex++;
|
|
3008
|
+
return /* @__PURE__ */ jsx(CommandItem, {
|
|
3009
|
+
item,
|
|
3010
|
+
onSelect: () => selectItem(currentIndex),
|
|
3011
|
+
selected: currentIndex === selectedIndex
|
|
3012
|
+
}, item.title);
|
|
3013
|
+
})] }, group.category))
|
|
3014
|
+
});
|
|
3015
|
+
}
|
|
3016
|
+
|
|
3017
|
+
//#endregion
|
|
3018
|
+
//#region src/ui/slash-command/commands.ts
|
|
3019
|
+
const TEXT = {
|
|
3020
|
+
title: "Text",
|
|
3021
|
+
description: "Plain text block",
|
|
3022
|
+
icon: Text,
|
|
3023
|
+
category: "Text",
|
|
3024
|
+
searchTerms: ["p", "paragraph"],
|
|
3025
|
+
command: ({ editor, range }) => {
|
|
3026
|
+
editor.chain().focus().deleteRange(range).toggleNode("paragraph", "paragraph").run();
|
|
3027
|
+
}
|
|
3028
|
+
};
|
|
3029
|
+
const H1 = {
|
|
3030
|
+
title: "Title",
|
|
3031
|
+
description: "Large heading",
|
|
3032
|
+
icon: Heading1,
|
|
3033
|
+
category: "Text",
|
|
3034
|
+
searchTerms: [
|
|
3035
|
+
"title",
|
|
3036
|
+
"big",
|
|
3037
|
+
"large",
|
|
3038
|
+
"h1"
|
|
3039
|
+
],
|
|
3040
|
+
command: ({ editor, range }) => {
|
|
3041
|
+
editor.chain().focus().deleteRange(range).setNode("heading", { level: 1 }).run();
|
|
3042
|
+
}
|
|
3043
|
+
};
|
|
3044
|
+
const H2 = {
|
|
3045
|
+
title: "Subtitle",
|
|
3046
|
+
description: "Medium heading",
|
|
3047
|
+
icon: Heading2,
|
|
3048
|
+
category: "Text",
|
|
3049
|
+
searchTerms: [
|
|
3050
|
+
"subtitle",
|
|
3051
|
+
"medium",
|
|
3052
|
+
"h2"
|
|
3053
|
+
],
|
|
3054
|
+
command: ({ editor, range }) => {
|
|
3055
|
+
editor.chain().focus().deleteRange(range).setNode("heading", { level: 2 }).run();
|
|
3056
|
+
}
|
|
3057
|
+
};
|
|
3058
|
+
const H3 = {
|
|
3059
|
+
title: "Heading",
|
|
3060
|
+
description: "Small heading",
|
|
3061
|
+
icon: Heading3,
|
|
3062
|
+
category: "Text",
|
|
3063
|
+
searchTerms: [
|
|
3064
|
+
"subtitle",
|
|
3065
|
+
"small",
|
|
3066
|
+
"h3"
|
|
3067
|
+
],
|
|
3068
|
+
command: ({ editor, range }) => {
|
|
3069
|
+
editor.chain().focus().deleteRange(range).setNode("heading", { level: 3 }).run();
|
|
3070
|
+
}
|
|
3071
|
+
};
|
|
3072
|
+
const BULLET_LIST = {
|
|
3073
|
+
title: "Bullet list",
|
|
3074
|
+
description: "Unordered list",
|
|
3075
|
+
icon: List,
|
|
3076
|
+
category: "Text",
|
|
3077
|
+
searchTerms: ["unordered", "point"],
|
|
3078
|
+
command: ({ editor, range }) => {
|
|
3079
|
+
editor.chain().focus().deleteRange(range).toggleBulletList().run();
|
|
3080
|
+
}
|
|
3081
|
+
};
|
|
3082
|
+
const NUMBERED_LIST = {
|
|
3083
|
+
title: "Numbered list",
|
|
3084
|
+
description: "Ordered list",
|
|
3085
|
+
icon: ListOrdered,
|
|
3086
|
+
category: "Text",
|
|
3087
|
+
searchTerms: ["ordered"],
|
|
3088
|
+
command: ({ editor, range }) => {
|
|
3089
|
+
editor.chain().focus().deleteRange(range).toggleOrderedList().run();
|
|
3090
|
+
}
|
|
3091
|
+
};
|
|
3092
|
+
const QUOTE = {
|
|
3093
|
+
title: "Quote",
|
|
3094
|
+
description: "Block quote",
|
|
3095
|
+
icon: TextQuote,
|
|
3096
|
+
category: "Text",
|
|
3097
|
+
searchTerms: ["blockquote"],
|
|
3098
|
+
command: ({ editor, range }) => {
|
|
3099
|
+
editor.chain().focus().deleteRange(range).toggleNode("paragraph", "paragraph").toggleBlockquote().run();
|
|
3100
|
+
}
|
|
3101
|
+
};
|
|
3102
|
+
const CODE = {
|
|
3103
|
+
title: "Code block",
|
|
3104
|
+
description: "Code snippet",
|
|
3105
|
+
icon: SquareCode,
|
|
3106
|
+
category: "Text",
|
|
3107
|
+
searchTerms: ["codeblock"],
|
|
3108
|
+
command: ({ editor, range }) => {
|
|
3109
|
+
editor.chain().focus().deleteRange(range).toggleCodeBlock().run();
|
|
3110
|
+
}
|
|
3111
|
+
};
|
|
3112
|
+
const BUTTON = {
|
|
3113
|
+
title: "Button",
|
|
3114
|
+
description: "Clickable button",
|
|
3115
|
+
icon: MousePointer,
|
|
3116
|
+
category: "Layout",
|
|
3117
|
+
searchTerms: ["button"],
|
|
3118
|
+
command: ({ editor, range }) => {
|
|
3119
|
+
editor.chain().focus().deleteRange(range).setButton().run();
|
|
3120
|
+
}
|
|
3121
|
+
};
|
|
3122
|
+
const DIVIDER = {
|
|
3123
|
+
title: "Divider",
|
|
3124
|
+
description: "Horizontal separator",
|
|
3125
|
+
icon: SplitSquareVertical,
|
|
3126
|
+
category: "Layout",
|
|
3127
|
+
searchTerms: [
|
|
3128
|
+
"hr",
|
|
3129
|
+
"divider",
|
|
3130
|
+
"separator"
|
|
3131
|
+
],
|
|
3132
|
+
command: ({ editor, range }) => {
|
|
3133
|
+
editor.chain().focus().deleteRange(range).setHorizontalRule().run();
|
|
3134
|
+
}
|
|
3135
|
+
};
|
|
3136
|
+
const SECTION = {
|
|
3137
|
+
title: "Section",
|
|
3138
|
+
description: "Content section",
|
|
3139
|
+
icon: Rows2,
|
|
3140
|
+
category: "Layout",
|
|
3141
|
+
searchTerms: [
|
|
3142
|
+
"section",
|
|
3143
|
+
"row",
|
|
3144
|
+
"container"
|
|
3145
|
+
],
|
|
3146
|
+
command: ({ editor, range }) => {
|
|
3147
|
+
editor.chain().focus().deleteRange(range).insertSection().run();
|
|
3148
|
+
}
|
|
3149
|
+
};
|
|
3150
|
+
const TWO_COLUMNS = {
|
|
3151
|
+
title: "2 columns",
|
|
3152
|
+
description: "Two column layout",
|
|
3153
|
+
icon: Columns2,
|
|
3154
|
+
category: "Layout",
|
|
3155
|
+
searchTerms: [
|
|
3156
|
+
"columns",
|
|
3157
|
+
"column",
|
|
3158
|
+
"layout",
|
|
3159
|
+
"grid",
|
|
3160
|
+
"split",
|
|
3161
|
+
"side-by-side",
|
|
3162
|
+
"multi-column",
|
|
3163
|
+
"row",
|
|
3164
|
+
"two",
|
|
3165
|
+
"2"
|
|
3166
|
+
],
|
|
3167
|
+
command: ({ editor, range }) => {
|
|
3168
|
+
editor.chain().focus().deleteRange(range).insertColumns(2).run();
|
|
3169
|
+
}
|
|
3170
|
+
};
|
|
3171
|
+
const THREE_COLUMNS = {
|
|
3172
|
+
title: "3 columns",
|
|
3173
|
+
description: "Three column layout",
|
|
3174
|
+
icon: Columns3,
|
|
3175
|
+
category: "Layout",
|
|
3176
|
+
searchTerms: [
|
|
3177
|
+
"columns",
|
|
3178
|
+
"column",
|
|
3179
|
+
"layout",
|
|
3180
|
+
"grid",
|
|
3181
|
+
"split",
|
|
3182
|
+
"multi-column",
|
|
3183
|
+
"row",
|
|
3184
|
+
"three",
|
|
3185
|
+
"3"
|
|
3186
|
+
],
|
|
3187
|
+
command: ({ editor, range }) => {
|
|
3188
|
+
editor.chain().focus().deleteRange(range).insertColumns(3).run();
|
|
3189
|
+
}
|
|
3190
|
+
};
|
|
3191
|
+
const FOUR_COLUMNS = {
|
|
3192
|
+
title: "4 columns",
|
|
3193
|
+
description: "Four column layout",
|
|
3194
|
+
icon: Columns4,
|
|
3195
|
+
category: "Layout",
|
|
3196
|
+
searchTerms: [
|
|
3197
|
+
"columns",
|
|
3198
|
+
"column",
|
|
3199
|
+
"layout",
|
|
3200
|
+
"grid",
|
|
3201
|
+
"split",
|
|
3202
|
+
"multi-column",
|
|
3203
|
+
"row",
|
|
3204
|
+
"four",
|
|
3205
|
+
"4"
|
|
3206
|
+
],
|
|
3207
|
+
command: ({ editor, range }) => {
|
|
3208
|
+
editor.chain().focus().deleteRange(range).insertColumns(4).run();
|
|
3209
|
+
}
|
|
3210
|
+
};
|
|
3211
|
+
const defaultSlashCommands = [
|
|
3212
|
+
TEXT,
|
|
3213
|
+
H1,
|
|
3214
|
+
H2,
|
|
3215
|
+
H3,
|
|
3216
|
+
BULLET_LIST,
|
|
3217
|
+
NUMBERED_LIST,
|
|
3218
|
+
QUOTE,
|
|
3219
|
+
CODE,
|
|
3220
|
+
BUTTON,
|
|
3221
|
+
DIVIDER,
|
|
3222
|
+
SECTION,
|
|
3223
|
+
TWO_COLUMNS,
|
|
3224
|
+
THREE_COLUMNS,
|
|
3225
|
+
FOUR_COLUMNS
|
|
3226
|
+
];
|
|
3227
|
+
|
|
3228
|
+
//#endregion
|
|
3229
|
+
//#region src/ui/slash-command/extension.ts
|
|
3230
|
+
const SlashCommandExtension = Extension.create({
|
|
3231
|
+
name: "slash-command",
|
|
3232
|
+
addOptions() {
|
|
3233
|
+
return { suggestion: {
|
|
3234
|
+
char: "/",
|
|
3235
|
+
allow: ({ editor }) => !editor.isActive("codeBlock"),
|
|
3236
|
+
command: ({ editor, range, props }) => {
|
|
3237
|
+
props.command({
|
|
3238
|
+
editor,
|
|
3239
|
+
range
|
|
3240
|
+
});
|
|
3241
|
+
}
|
|
3242
|
+
} };
|
|
3243
|
+
},
|
|
3244
|
+
addProseMirrorPlugins() {
|
|
3245
|
+
return [Suggestion({
|
|
3246
|
+
pluginKey: new PluginKey("slash-command"),
|
|
3247
|
+
editor: this.editor,
|
|
3248
|
+
...this.options.suggestion
|
|
3249
|
+
})];
|
|
3250
|
+
}
|
|
3251
|
+
});
|
|
3252
|
+
|
|
3253
|
+
//#endregion
|
|
3254
|
+
//#region src/ui/slash-command/render.tsx
|
|
3255
|
+
function createRenderItems(component = CommandList) {
|
|
3256
|
+
return () => {
|
|
3257
|
+
let renderer = null;
|
|
3258
|
+
let popup = null;
|
|
3259
|
+
return {
|
|
3260
|
+
onStart: (props) => {
|
|
3261
|
+
renderer = new ReactRenderer(component, {
|
|
3262
|
+
props,
|
|
3263
|
+
editor: props.editor
|
|
3264
|
+
});
|
|
3265
|
+
if (!props.clientRect) return;
|
|
3266
|
+
popup = tippy("body", {
|
|
3267
|
+
getReferenceClientRect: props.clientRect,
|
|
3268
|
+
appendTo: () => document.body,
|
|
3269
|
+
content: renderer.element,
|
|
3270
|
+
showOnCreate: true,
|
|
3271
|
+
interactive: true,
|
|
3272
|
+
trigger: "manual",
|
|
3273
|
+
placement: "bottom-start"
|
|
3274
|
+
});
|
|
3275
|
+
},
|
|
3276
|
+
onUpdate: (props) => {
|
|
3277
|
+
if (!renderer) return;
|
|
3278
|
+
renderer.updateProps(props);
|
|
3279
|
+
if (popup?.[0] && props.clientRect) popup[0].setProps({ getReferenceClientRect: props.clientRect });
|
|
3280
|
+
},
|
|
3281
|
+
onKeyDown: (props) => {
|
|
3282
|
+
if (props.event.key === "Escape") {
|
|
3283
|
+
popup?.[0]?.hide();
|
|
3284
|
+
return true;
|
|
3285
|
+
}
|
|
3286
|
+
return renderer?.ref?.onKeyDown(props) ?? false;
|
|
3287
|
+
},
|
|
3288
|
+
onExit: () => {
|
|
3289
|
+
popup?.[0]?.destroy();
|
|
3290
|
+
renderer?.destroy();
|
|
3291
|
+
popup = null;
|
|
3292
|
+
renderer = null;
|
|
3293
|
+
}
|
|
3294
|
+
};
|
|
3295
|
+
};
|
|
3296
|
+
}
|
|
3297
|
+
|
|
3298
|
+
//#endregion
|
|
3299
|
+
//#region src/ui/slash-command/search.ts
|
|
3300
|
+
function scoreItem(item, query) {
|
|
3301
|
+
if (!query) return 100;
|
|
3302
|
+
const q = query.toLowerCase();
|
|
3303
|
+
const title = item.title.toLowerCase();
|
|
3304
|
+
const description = item.description.toLowerCase();
|
|
3305
|
+
const terms = item.searchTerms?.map((t) => t.toLowerCase()) ?? [];
|
|
3306
|
+
if (title === q) return 100;
|
|
3307
|
+
if (title.startsWith(q)) return 90;
|
|
3308
|
+
if (title.split(/\s+/).some((w) => w.startsWith(q))) return 80;
|
|
3309
|
+
if (terms.some((t) => t === q)) return 70;
|
|
3310
|
+
if (terms.some((t) => t.startsWith(q))) return 60;
|
|
3311
|
+
if (title.includes(q)) return 40;
|
|
3312
|
+
if (terms.some((t) => t.includes(q))) return 30;
|
|
3313
|
+
if (description.includes(q)) return 20;
|
|
3314
|
+
return 0;
|
|
3315
|
+
}
|
|
3316
|
+
function filterAndRankItems(items, query) {
|
|
3317
|
+
const trimmed = query.trim();
|
|
3318
|
+
if (!trimmed) return items;
|
|
3319
|
+
const scored = items.map((item) => ({
|
|
3320
|
+
item,
|
|
3321
|
+
score: scoreItem(item, trimmed)
|
|
3322
|
+
})).filter(({ score }) => score > 0);
|
|
3323
|
+
scored.sort((a, b) => b.score - a.score);
|
|
3324
|
+
return scored.map(({ item }) => item);
|
|
3325
|
+
}
|
|
3326
|
+
|
|
3327
|
+
//#endregion
|
|
3328
|
+
//#region src/ui/slash-command/create-slash-command.ts
|
|
3329
|
+
function defaultFilterItems(items, query, editor) {
|
|
3330
|
+
return filterAndRankItems(isAtMaxColumnsDepth(editor) ? items.filter((item) => item.category !== "Layout" || !item.title.includes("column")) : items, query);
|
|
3331
|
+
}
|
|
3332
|
+
function createSlashCommand(options) {
|
|
3333
|
+
const items = options?.items ?? defaultSlashCommands;
|
|
3334
|
+
const filterFn = options?.filterItems ?? defaultFilterItems;
|
|
3335
|
+
return SlashCommandExtension.configure({ suggestion: {
|
|
3336
|
+
items: ({ query, editor }) => filterFn(items, query, editor),
|
|
3337
|
+
render: createRenderItems(options?.component)
|
|
3338
|
+
} });
|
|
3339
|
+
}
|
|
3340
|
+
|
|
3341
|
+
//#endregion
|
|
3342
|
+
//#region src/ui/slash-command/index.ts
|
|
3343
|
+
const SlashCommand = createSlashCommand();
|
|
3344
|
+
|
|
3345
|
+
//#endregion
|
|
3346
|
+
export { AlignmentAttribute, BULLET_LIST, BUTTON, Body, Bold, BubbleMenu, BubbleMenuAlignCenter, BubbleMenuAlignLeft, BubbleMenuAlignRight, BubbleMenuBold, BubbleMenuCode, BubbleMenuDefault, BubbleMenuItalic, BubbleMenuItem, BubbleMenuItemGroup, BubbleMenuLinkSelector, BubbleMenuNodeSelector, BubbleMenuRoot, BubbleMenuSeparator, BubbleMenuStrike, BubbleMenuUnderline, BubbleMenuUppercase, Button, ButtonBubbleMenu, ButtonBubbleMenuDefault, ButtonBubbleMenuEditLink, ButtonBubbleMenuRoot, ButtonBubbleMenuToolbar, CODE, COLUMN_PARENT_TYPES, ClassAttribute, CodeBlockPrism, ColumnsColumn, CommandList, DIVIDER, Div, EmailNode, FOUR_COLUMNS, FourColumns, H1, H2, H3, ImageBubbleMenu, ImageBubbleMenuDefault, ImageBubbleMenuEditLink, ImageBubbleMenuRoot, ImageBubbleMenuToolbar, LinkBubbleMenu, LinkBubbleMenuDefault, LinkBubbleMenuEditLink, LinkBubbleMenuForm, LinkBubbleMenuOpenLink, LinkBubbleMenuRoot, LinkBubbleMenuToolbar, LinkBubbleMenuUnlink, MAX_COLUMNS_DEPTH, MaxNesting, NUMBERED_LIST, NodeSelectorContent, NodeSelectorRoot, NodeSelectorTrigger, Placeholder, PreservedStyle, PreviewText, QUOTE, SECTION, Section, SlashCommand, StyleAttribute, Sup, TEXT, THREE_COLUMNS, TWO_COLUMNS, Table, TableCell, TableHeader, TableRow, ThreeColumns, TwoColumns, Uppercase, coreExtensions, createSlashCommand, defaultSlashCommands, editorEventBus, filterAndRankItems, getColumnsDepth, isAtMaxColumnsDepth, isInsideNode, processStylesForUnlink, scoreItem, setTextAlignment, useButtonBubbleMenuContext, useImageBubbleMenuContext, useLinkBubbleMenuContext };
|
|
2885
3347
|
//# sourceMappingURL=index.mjs.map
|