@kopexa/tiptap 17.2.4 → 17.4.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-4HO7BWDC.mjs +89 -0
- package/dist/chunk-552JLRNB.mjs +35 -0
- package/dist/chunk-5SMDMQDF.mjs +34 -0
- package/dist/{chunk-XKWTI3MA.mjs → chunk-DQK6PA4U.mjs} +11 -2
- package/dist/{chunk-3ZPLSXTZ.mjs → chunk-ERPGWXFK.mjs} +1 -1
- package/dist/{chunk-NJZK5DRT.mjs → chunk-GDDWW2IQ.mjs} +38 -13
- package/dist/{chunk-NSYSECKW.mjs → chunk-GL3RTIER.mjs} +1 -0
- package/dist/chunk-H7MS2UMO.mjs +168 -0
- package/dist/chunk-JVSH5T4B.mjs +72 -0
- package/dist/{chunk-ZYFCSR3E.mjs → chunk-L5RDMV3H.mjs} +3 -3
- package/dist/chunk-Q5FK7SFY.mjs +75 -0
- package/dist/chunk-QIELBKP3.mjs +104 -0
- package/dist/extensions/variable/extract-variables.d.mts +16 -0
- package/dist/extensions/variable/extract-variables.d.ts +16 -0
- package/dist/extensions/variable/extract-variables.js +58 -0
- package/dist/extensions/variable/extract-variables.mjs +7 -0
- package/dist/extensions/variable/index.d.mts +38 -0
- package/dist/extensions/variable/index.d.ts +38 -0
- package/dist/extensions/variable/index.js +190 -0
- package/dist/extensions/variable/index.mjs +11 -0
- package/dist/extensions/variable/messages.d.mts +69 -0
- package/dist/extensions/variable/messages.d.ts +69 -0
- package/dist/extensions/variable/messages.js +98 -0
- package/dist/extensions/variable/messages.mjs +7 -0
- package/dist/extensions/variable/variable-context.d.mts +56 -0
- package/dist/extensions/variable/variable-context.d.ts +56 -0
- package/dist/extensions/variable/variable-context.js +70 -0
- package/dist/extensions/variable/variable-context.mjs +12 -0
- package/dist/extensions/variable/variable-filler-dialog.d.mts +43 -0
- package/dist/extensions/variable/variable-filler-dialog.d.ts +43 -0
- package/dist/extensions/variable/variable-filler-dialog.js +207 -0
- package/dist/extensions/variable/variable-filler-dialog.mjs +9 -0
- package/dist/extensions/variable/variable-suggestion.d.mts +31 -0
- package/dist/extensions/variable/variable-suggestion.d.ts +31 -0
- package/dist/extensions/variable/variable-suggestion.js +615 -0
- package/dist/extensions/variable/variable-suggestion.mjs +14 -0
- package/dist/extensions/variable/variable-view.d.mts +13 -0
- package/dist/extensions/variable/variable-view.d.ts +13 -0
- package/dist/extensions/variable/variable-view.js +110 -0
- package/dist/extensions/variable/variable-view.mjs +11 -0
- package/dist/hooks/use-create-editor.d.mts +8 -2
- package/dist/hooks/use-create-editor.d.ts +8 -2
- package/dist/hooks/use-create-editor.js +163 -7
- package/dist/hooks/use-create-editor.mjs +4 -1
- package/dist/index.d.mts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +2733 -2164
- package/dist/index.mjs +37 -11
- package/dist/presets/basic/editor-header.mjs +3 -3
- package/dist/presets/basic/index.d.mts +12 -1
- package/dist/presets/basic/index.d.ts +12 -1
- package/dist/presets/basic/index.js +4203 -3853
- package/dist/presets/basic/index.mjs +14 -10
- package/dist/ui/bubble-menu/index.js +1 -0
- package/dist/ui/bubble-menu/index.mjs +1 -1
- package/dist/ui/slash-dropdown-menu/index.js +2 -2
- package/dist/ui/slash-dropdown-menu/index.mjs +2 -2
- package/dist/ui/slash-dropdown-menu/slash-dropdown-menu.js +2 -2
- package/dist/ui/slash-dropdown-menu/slash-dropdown-menu.mjs +2 -2
- package/dist/ui/suggestion-menu/index.js +2 -2
- package/dist/ui/suggestion-menu/index.mjs +1 -1
- package/dist/ui/suggestion-menu/suggestion-menu.js +2 -2
- package/dist/ui/suggestion-menu/suggestion-menu.mjs +1 -1
- package/package.json +24 -24
- package/dist/{chunk-FDPXD6VC.mjs → chunk-RFWNKE7D.mjs} +3 -3
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
VariableNodeView
|
|
4
|
+
} from "./chunk-JVSH5T4B.mjs";
|
|
5
|
+
|
|
6
|
+
// src/extensions/variable/index.ts
|
|
7
|
+
import { mergeAttributes, Node } from "@tiptap/core";
|
|
8
|
+
import { ReactNodeViewRenderer } from "@tiptap/react";
|
|
9
|
+
var VariableNode = Node.create({
|
|
10
|
+
name: "variable",
|
|
11
|
+
group: "inline",
|
|
12
|
+
inline: true,
|
|
13
|
+
atom: true,
|
|
14
|
+
selectable: true,
|
|
15
|
+
draggable: true,
|
|
16
|
+
addOptions() {
|
|
17
|
+
return {
|
|
18
|
+
HTMLAttributes: {}
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
addAttributes() {
|
|
22
|
+
return {
|
|
23
|
+
name: {
|
|
24
|
+
default: "",
|
|
25
|
+
parseHTML: (element) => element.getAttribute("data-name"),
|
|
26
|
+
renderHTML: (attributes) => ({
|
|
27
|
+
"data-name": attributes.name
|
|
28
|
+
})
|
|
29
|
+
},
|
|
30
|
+
fallback: {
|
|
31
|
+
default: void 0,
|
|
32
|
+
parseHTML: (element) => element.getAttribute("data-fallback"),
|
|
33
|
+
renderHTML: (attributes) => {
|
|
34
|
+
if (!attributes.fallback) return {};
|
|
35
|
+
return {
|
|
36
|
+
"data-fallback": attributes.fallback
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
category: {
|
|
41
|
+
default: void 0,
|
|
42
|
+
parseHTML: (element) => element.getAttribute("data-category"),
|
|
43
|
+
renderHTML: (attributes) => {
|
|
44
|
+
if (!attributes.category) return {};
|
|
45
|
+
return {
|
|
46
|
+
"data-category": attributes.category
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
},
|
|
52
|
+
parseHTML() {
|
|
53
|
+
return [
|
|
54
|
+
{
|
|
55
|
+
tag: 'span[data-type="variable"]'
|
|
56
|
+
}
|
|
57
|
+
];
|
|
58
|
+
},
|
|
59
|
+
renderHTML({ node, HTMLAttributes }) {
|
|
60
|
+
const attrs = node.attrs;
|
|
61
|
+
return [
|
|
62
|
+
"span",
|
|
63
|
+
mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {
|
|
64
|
+
"data-type": "variable",
|
|
65
|
+
class: "variable-node"
|
|
66
|
+
}),
|
|
67
|
+
`{{${attrs.name}}}`
|
|
68
|
+
];
|
|
69
|
+
},
|
|
70
|
+
addNodeView() {
|
|
71
|
+
return ReactNodeViewRenderer(VariableNodeView);
|
|
72
|
+
},
|
|
73
|
+
addCommands() {
|
|
74
|
+
return {
|
|
75
|
+
insertVariable: (attrs) => ({ commands }) => {
|
|
76
|
+
return commands.insertContent({
|
|
77
|
+
type: this.name,
|
|
78
|
+
attrs
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
var variable_default = VariableNode;
|
|
85
|
+
|
|
86
|
+
export {
|
|
87
|
+
VariableNode,
|
|
88
|
+
variable_default
|
|
89
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/extensions/variable/extract-variables.ts
|
|
4
|
+
function extractVariablesFromContent(content) {
|
|
5
|
+
if (!content) return [];
|
|
6
|
+
const variables = /* @__PURE__ */ new Map();
|
|
7
|
+
function scan(node) {
|
|
8
|
+
var _a;
|
|
9
|
+
if (node.type === "variable" && ((_a = node.attrs) == null ? void 0 : _a.name)) {
|
|
10
|
+
const name = node.attrs.name;
|
|
11
|
+
if (!variables.has(name)) {
|
|
12
|
+
variables.set(name, {
|
|
13
|
+
name,
|
|
14
|
+
label: formatVariableName(name),
|
|
15
|
+
category: node.attrs.category || void 0,
|
|
16
|
+
fallback: node.attrs.fallback || void 0
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (node.content && Array.isArray(node.content)) {
|
|
21
|
+
for (const child of node.content) {
|
|
22
|
+
scan(child);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
scan(content);
|
|
27
|
+
return Array.from(variables.values());
|
|
28
|
+
}
|
|
29
|
+
function formatVariableName(name) {
|
|
30
|
+
return name.replace(/([A-Z])/g, " $1").replace(/[_-]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()).replace(/\s+/g, " ").trim();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export {
|
|
34
|
+
extractVariablesFromContent
|
|
35
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/extensions/variable/variable-context.tsx
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
var VariableContext = React.createContext(null);
|
|
7
|
+
function VariableProvider({
|
|
8
|
+
children,
|
|
9
|
+
variables,
|
|
10
|
+
resolveVariable
|
|
11
|
+
}) {
|
|
12
|
+
const value = React.useMemo(
|
|
13
|
+
() => ({
|
|
14
|
+
variables,
|
|
15
|
+
resolveVariable
|
|
16
|
+
}),
|
|
17
|
+
[variables, resolveVariable]
|
|
18
|
+
);
|
|
19
|
+
return /* @__PURE__ */ jsx(VariableContext.Provider, { value, children });
|
|
20
|
+
}
|
|
21
|
+
function useVariables() {
|
|
22
|
+
return React.useContext(VariableContext);
|
|
23
|
+
}
|
|
24
|
+
function useVariablesWithFallback(fallbackVariables = []) {
|
|
25
|
+
var _a;
|
|
26
|
+
const context = React.useContext(VariableContext);
|
|
27
|
+
return (_a = context == null ? void 0 : context.variables) != null ? _a : fallbackVariables;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export {
|
|
31
|
+
VariableProvider,
|
|
32
|
+
useVariables,
|
|
33
|
+
useVariablesWithFallback
|
|
34
|
+
};
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
TrailingNode
|
|
4
4
|
} from "./chunk-H6LC4LDQ.mjs";
|
|
5
|
+
import {
|
|
6
|
+
VariableNode
|
|
7
|
+
} from "./chunk-4HO7BWDC.mjs";
|
|
5
8
|
import {
|
|
6
9
|
MathBlock
|
|
7
10
|
} from "./chunk-2U5CQUZH.mjs";
|
|
@@ -68,6 +71,7 @@ var useCreateEditor = ({
|
|
|
68
71
|
enableControls = false,
|
|
69
72
|
controlResolver,
|
|
70
73
|
fileHandler: fileHandlerProp,
|
|
74
|
+
enableVariables = false,
|
|
71
75
|
...options
|
|
72
76
|
}) => {
|
|
73
77
|
const fileHandlerFromContext = useEditorFile();
|
|
@@ -78,7 +82,8 @@ var useCreateEditor = ({
|
|
|
78
82
|
placeholder,
|
|
79
83
|
enableControls,
|
|
80
84
|
controlResolver,
|
|
81
|
-
fileHandler
|
|
85
|
+
fileHandler,
|
|
86
|
+
enableVariables
|
|
82
87
|
})
|
|
83
88
|
);
|
|
84
89
|
const editor = useEditor({
|
|
@@ -112,7 +117,8 @@ function getExtensions({
|
|
|
112
117
|
placeholder,
|
|
113
118
|
enableControls = false,
|
|
114
119
|
controlResolver,
|
|
115
|
-
fileHandler
|
|
120
|
+
fileHandler,
|
|
121
|
+
enableVariables = false
|
|
116
122
|
}) {
|
|
117
123
|
const extensions = [
|
|
118
124
|
StarterKit.configure({
|
|
@@ -178,6 +184,9 @@ function getExtensions({
|
|
|
178
184
|
if (enableControls) {
|
|
179
185
|
extensions.push(ControlKit.configure({ resolver: controlResolver }));
|
|
180
186
|
}
|
|
187
|
+
if (enableVariables) {
|
|
188
|
+
extensions.push(VariableNode);
|
|
189
|
+
}
|
|
181
190
|
if (fileHandler) {
|
|
182
191
|
extensions.push(
|
|
183
192
|
FileHandler.configure({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
3
|
SlashDropdownMenu
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ERPGWXFK.mjs";
|
|
5
5
|
import {
|
|
6
6
|
useScrollToHash
|
|
7
7
|
} from "./chunk-DZLGLP7R.mjs";
|
|
@@ -10,10 +10,13 @@ import {
|
|
|
10
10
|
} from "./chunk-XNDXYI2N.mjs";
|
|
11
11
|
import {
|
|
12
12
|
BubbleMenu
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-GL3RTIER.mjs";
|
|
14
|
+
import {
|
|
15
|
+
VariableSuggestion
|
|
16
|
+
} from "./chunk-H7MS2UMO.mjs";
|
|
14
17
|
import {
|
|
15
18
|
EditorHeader
|
|
16
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-RFWNKE7D.mjs";
|
|
17
20
|
import {
|
|
18
21
|
useUiEditorState
|
|
19
22
|
} from "./chunk-BXJYNSWQ.mjs";
|
|
@@ -22,7 +25,10 @@ import {
|
|
|
22
25
|
} from "./chunk-REJEJXOZ.mjs";
|
|
23
26
|
import {
|
|
24
27
|
useCreateEditor
|
|
25
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-DQK6PA4U.mjs";
|
|
29
|
+
import {
|
|
30
|
+
VariableProvider
|
|
31
|
+
} from "./chunk-5SMDMQDF.mjs";
|
|
26
32
|
|
|
27
33
|
// src/presets/basic/index.tsx
|
|
28
34
|
import {
|
|
@@ -33,27 +39,42 @@ import {
|
|
|
33
39
|
EditorContent,
|
|
34
40
|
EditorContext
|
|
35
41
|
} from "@tiptap/react";
|
|
36
|
-
import { useContext } from "react";
|
|
42
|
+
import { useCallback, useContext } from "react";
|
|
37
43
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
38
44
|
var BasicEditor = ({
|
|
39
45
|
variant,
|
|
40
46
|
bordered,
|
|
41
47
|
content,
|
|
48
|
+
variables,
|
|
49
|
+
variableValues,
|
|
42
50
|
...options
|
|
43
51
|
}) => {
|
|
44
|
-
const editor = useCreateEditor({
|
|
52
|
+
const editor = useCreateEditor({
|
|
53
|
+
content,
|
|
54
|
+
enableVariables: !!(variables == null ? void 0 : variables.length),
|
|
55
|
+
...options
|
|
56
|
+
});
|
|
45
57
|
const styles = editorBasic({ variant, bordered });
|
|
58
|
+
const resolveVariable = useCallback(
|
|
59
|
+
(name) => variableValues == null ? void 0 : variableValues[name],
|
|
60
|
+
[variableValues]
|
|
61
|
+
);
|
|
46
62
|
if (!editor) {
|
|
47
63
|
return /* @__PURE__ */ jsx(LoadingSpinner, {});
|
|
48
64
|
}
|
|
49
65
|
const isBottomToolbar = variant === "field";
|
|
50
|
-
|
|
66
|
+
const hasVariables = variables && variables.length > 0;
|
|
67
|
+
const editorContent = /* @__PURE__ */ jsx(EditorUIProvider, { value: { styles }, children: /* @__PURE__ */ jsx("div", { className: styles.root(), "data-slot": "editor", children: /* @__PURE__ */ jsxs(EditorContext.Provider, { value: { editor }, children: [
|
|
51
68
|
!isBottomToolbar && /* @__PURE__ */ jsx(EditorHeader, { editor, variant }),
|
|
52
|
-
/* @__PURE__ */ jsx(EditorContentArea, { variant }),
|
|
69
|
+
/* @__PURE__ */ jsx(EditorContentArea, { variant, variables }),
|
|
53
70
|
isBottomToolbar && /* @__PURE__ */ jsx(EditorHeader, { editor, variant })
|
|
54
71
|
] }) }) });
|
|
72
|
+
if (hasVariables) {
|
|
73
|
+
return /* @__PURE__ */ jsx(VariableProvider, { variables, resolveVariable, children: editorContent });
|
|
74
|
+
}
|
|
75
|
+
return editorContent;
|
|
55
76
|
};
|
|
56
|
-
var EditorContentArea = ({ variant }) => {
|
|
77
|
+
var EditorContentArea = ({ variant, variables }) => {
|
|
57
78
|
const styles = editorBasic({ variant });
|
|
58
79
|
const { editor } = useContext(EditorContext);
|
|
59
80
|
const { isDragging } = useUiEditorState(editor);
|
|
@@ -61,8 +82,9 @@ var EditorContentArea = ({ variant }) => {
|
|
|
61
82
|
if (!editor) {
|
|
62
83
|
return null;
|
|
63
84
|
}
|
|
85
|
+
const isEditable = editor.isEditable;
|
|
64
86
|
return /* @__PURE__ */ jsxs("div", { className: styles.wrapper(), children: [
|
|
65
|
-
/* @__PURE__ */
|
|
87
|
+
/* @__PURE__ */ jsxs(
|
|
66
88
|
EditorContent,
|
|
67
89
|
{
|
|
68
90
|
editor,
|
|
@@ -71,11 +93,14 @@ var EditorContentArea = ({ variant }) => {
|
|
|
71
93
|
style: {
|
|
72
94
|
cursor: isDragging ? "grabbing" : "auto"
|
|
73
95
|
},
|
|
74
|
-
children:
|
|
96
|
+
children: [
|
|
97
|
+
isEditable && /* @__PURE__ */ jsx(SlashDropdownMenu, {}),
|
|
98
|
+
isEditable && variables && variables.length > 0 && /* @__PURE__ */ jsx(VariableSuggestion, { editor, variables })
|
|
99
|
+
]
|
|
75
100
|
}
|
|
76
101
|
),
|
|
77
|
-
/* @__PURE__ */ jsx(BubbleMenu, { editor }),
|
|
78
|
-
/* @__PURE__ */ jsx(LinkBubble, { editor })
|
|
102
|
+
isEditable && /* @__PURE__ */ jsx(BubbleMenu, { editor }),
|
|
103
|
+
isEditable && /* @__PURE__ */ jsx(LinkBubble, { editor })
|
|
79
104
|
] });
|
|
80
105
|
};
|
|
81
106
|
function LoadingSpinner({ text = "Connecting..." }) {
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
SuggestionMenu
|
|
4
|
+
} from "./chunk-L5RDMV3H.mjs";
|
|
5
|
+
|
|
6
|
+
// src/extensions/variable/variable-suggestion.tsx
|
|
7
|
+
import { getElementOverflowPosition } from "@kopexa/editor-utils";
|
|
8
|
+
import { slashDropdownMenu } from "@kopexa/theme";
|
|
9
|
+
import { PluginKey } from "@tiptap/pm/state";
|
|
10
|
+
import * as React from "react";
|
|
11
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
var VariableSuggestionPluginKey = new PluginKey("variableSuggestion");
|
|
13
|
+
function VariableSuggestion({
|
|
14
|
+
editor,
|
|
15
|
+
variables
|
|
16
|
+
}) {
|
|
17
|
+
const getItems = React.useCallback(
|
|
18
|
+
({ query }) => {
|
|
19
|
+
const normalizedQuery = query.toLowerCase().trim();
|
|
20
|
+
const items = [];
|
|
21
|
+
const matchingVariables = variables.filter((variable) => {
|
|
22
|
+
var _a, _b;
|
|
23
|
+
if (!normalizedQuery) return true;
|
|
24
|
+
return variable.name.toLowerCase().includes(normalizedQuery) || variable.label.toLowerCase().includes(normalizedQuery) || ((_a = variable.category) == null ? void 0 : _a.toLowerCase().includes(normalizedQuery)) || ((_b = variable.description) == null ? void 0 : _b.toLowerCase().includes(normalizedQuery));
|
|
25
|
+
});
|
|
26
|
+
for (const variable of matchingVariables) {
|
|
27
|
+
items.push({
|
|
28
|
+
title: variable.label,
|
|
29
|
+
subtext: variable.name,
|
|
30
|
+
group: variable.category,
|
|
31
|
+
keywords: [variable.name, variable.label, variable.category].filter(
|
|
32
|
+
Boolean
|
|
33
|
+
),
|
|
34
|
+
onSelect: ({ editor: editor2 }) => {
|
|
35
|
+
const attrs = {
|
|
36
|
+
name: variable.name,
|
|
37
|
+
fallback: variable.fallback,
|
|
38
|
+
category: variable.category
|
|
39
|
+
};
|
|
40
|
+
editor2.chain().focus().insertVariable(attrs).run();
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
if (normalizedQuery && !variables.some((v) => v.name.toLowerCase() === normalizedQuery)) {
|
|
45
|
+
items.push({
|
|
46
|
+
title: `Neue Variable "${query}"`,
|
|
47
|
+
subtext: query,
|
|
48
|
+
group: "Neu",
|
|
49
|
+
onSelect: ({ editor: editor2 }) => {
|
|
50
|
+
const attrs = {
|
|
51
|
+
name: query
|
|
52
|
+
};
|
|
53
|
+
editor2.chain().focus().insertVariable(attrs).run();
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return items;
|
|
58
|
+
},
|
|
59
|
+
[variables]
|
|
60
|
+
);
|
|
61
|
+
return /* @__PURE__ */ jsx(
|
|
62
|
+
SuggestionMenu,
|
|
63
|
+
{
|
|
64
|
+
editor,
|
|
65
|
+
pluginKey: VariableSuggestionPluginKey,
|
|
66
|
+
char: "{{",
|
|
67
|
+
items: getItems,
|
|
68
|
+
allowSpaces: false,
|
|
69
|
+
selector: "tiptap-variable-suggestion-menu",
|
|
70
|
+
children: (props) => /* @__PURE__ */ jsx(VariableList, { ...props })
|
|
71
|
+
}
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
var VariableItem = ({
|
|
75
|
+
item,
|
|
76
|
+
isSelected,
|
|
77
|
+
onSelect
|
|
78
|
+
}) => {
|
|
79
|
+
const itemRef = React.useRef(null);
|
|
80
|
+
React.useEffect(() => {
|
|
81
|
+
const selector = document.querySelector(
|
|
82
|
+
'[data-selector="tiptap-variable-suggestion-menu"]'
|
|
83
|
+
);
|
|
84
|
+
if (!itemRef.current || !isSelected || !selector) return;
|
|
85
|
+
const overflow = getElementOverflowPosition(itemRef.current, selector);
|
|
86
|
+
if (overflow === "top") {
|
|
87
|
+
itemRef.current.scrollIntoView(true);
|
|
88
|
+
} else if (overflow === "bottom") {
|
|
89
|
+
itemRef.current.scrollIntoView(false);
|
|
90
|
+
}
|
|
91
|
+
}, [isSelected]);
|
|
92
|
+
return /* @__PURE__ */ jsxs(
|
|
93
|
+
"button",
|
|
94
|
+
{
|
|
95
|
+
ref: itemRef,
|
|
96
|
+
type: "button",
|
|
97
|
+
"data-active-state": isSelected ? "on" : "off",
|
|
98
|
+
onClick: onSelect,
|
|
99
|
+
className: "w-full flex items-center justify-between gap-3 px-2 py-1.5 text-sm rounded-sm outline-none hover:bg-muted data-[active-state=on]:bg-muted",
|
|
100
|
+
children: [
|
|
101
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium truncate", children: item.title }),
|
|
102
|
+
/* @__PURE__ */ jsx("code", { className: "text-xs text-muted-foreground font-mono shrink-0", children: item.subtext })
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
};
|
|
107
|
+
var VariableList = ({
|
|
108
|
+
items,
|
|
109
|
+
selectedIndex,
|
|
110
|
+
onSelect
|
|
111
|
+
}) => {
|
|
112
|
+
const styles = slashDropdownMenu();
|
|
113
|
+
const renderedItems = React.useMemo(() => {
|
|
114
|
+
const rendered = [];
|
|
115
|
+
const groups = {};
|
|
116
|
+
items.forEach((item, index) => {
|
|
117
|
+
const groupLabel = item.group || "";
|
|
118
|
+
if (!groups[groupLabel]) {
|
|
119
|
+
groups[groupLabel] = { items: [], indices: [] };
|
|
120
|
+
}
|
|
121
|
+
groups[groupLabel].items.push(item);
|
|
122
|
+
groups[groupLabel].indices.push(index);
|
|
123
|
+
});
|
|
124
|
+
Object.entries(groups).forEach(([groupLabel, groupData], groupIndex) => {
|
|
125
|
+
const groupItems = groupData.items.map((item, itemIndex) => {
|
|
126
|
+
const originalIndex = groupData.indices[itemIndex];
|
|
127
|
+
return /* @__PURE__ */ jsx(
|
|
128
|
+
VariableItem,
|
|
129
|
+
{
|
|
130
|
+
item,
|
|
131
|
+
isSelected: originalIndex === selectedIndex,
|
|
132
|
+
onSelect: () => onSelect(item)
|
|
133
|
+
},
|
|
134
|
+
`item-${originalIndex}-${item.title}`
|
|
135
|
+
);
|
|
136
|
+
});
|
|
137
|
+
if (groupLabel) {
|
|
138
|
+
rendered.push(
|
|
139
|
+
/* @__PURE__ */ jsxs("div", { className: "py-1", children: [
|
|
140
|
+
/* @__PURE__ */ jsx("div", { className: "px-2 py-1 text-xs font-semibold text-muted-foreground uppercase tracking-wide", children: groupLabel }),
|
|
141
|
+
groupItems
|
|
142
|
+
] }, `group-${groupIndex}-${groupLabel}`)
|
|
143
|
+
);
|
|
144
|
+
} else {
|
|
145
|
+
rendered.push(...groupItems);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
return rendered;
|
|
149
|
+
}, [items, selectedIndex, onSelect]);
|
|
150
|
+
if (!renderedItems.length) {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
return /* @__PURE__ */ jsx(
|
|
154
|
+
"div",
|
|
155
|
+
{
|
|
156
|
+
className: styles.card(),
|
|
157
|
+
style: {
|
|
158
|
+
maxHeight: "var(--suggestion-menu-max-height)",
|
|
159
|
+
minWidth: "240px"
|
|
160
|
+
},
|
|
161
|
+
children: /* @__PURE__ */ jsx("div", { className: styles.body(), children: renderedItems })
|
|
162
|
+
}
|
|
163
|
+
);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
export {
|
|
167
|
+
VariableSuggestion
|
|
168
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
useVariables
|
|
4
|
+
} from "./chunk-5SMDMQDF.mjs";
|
|
5
|
+
|
|
6
|
+
// src/extensions/variable/variable-view.tsx
|
|
7
|
+
import { variableNode } from "@kopexa/theme";
|
|
8
|
+
import {
|
|
9
|
+
NodeViewWrapper,
|
|
10
|
+
useEditorState
|
|
11
|
+
} from "@tiptap/react";
|
|
12
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
13
|
+
function VariableNodeView({ node, editor }) {
|
|
14
|
+
var _a;
|
|
15
|
+
const attrs = node.attrs;
|
|
16
|
+
const { name, fallback, category } = attrs;
|
|
17
|
+
const context = useVariables();
|
|
18
|
+
const isEditable = useEditorState({
|
|
19
|
+
editor,
|
|
20
|
+
selector: ({ editor: e }) => {
|
|
21
|
+
var _a2;
|
|
22
|
+
return (_a2 = e == null ? void 0 : e.isEditable) != null ? _a2 : true;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
const resolvedValue = (_a = context == null ? void 0 : context.resolveVariable) == null ? void 0 : _a.call(context, name);
|
|
26
|
+
const hasValue = resolvedValue !== void 0 && resolvedValue !== "";
|
|
27
|
+
const displayValue = resolvedValue || fallback;
|
|
28
|
+
const styles = variableNode({ resolved: hasValue });
|
|
29
|
+
if (!isEditable && hasValue) {
|
|
30
|
+
return /* @__PURE__ */ jsx(
|
|
31
|
+
NodeViewWrapper,
|
|
32
|
+
{
|
|
33
|
+
as: "span",
|
|
34
|
+
"data-type": "variable",
|
|
35
|
+
"data-name": name,
|
|
36
|
+
style: { userSelect: "text" },
|
|
37
|
+
children: displayValue
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
return /* @__PURE__ */ jsx(
|
|
42
|
+
NodeViewWrapper,
|
|
43
|
+
{
|
|
44
|
+
as: "span",
|
|
45
|
+
className: styles.wrapper(),
|
|
46
|
+
"data-type": "variable",
|
|
47
|
+
"data-name": name,
|
|
48
|
+
"data-category": category,
|
|
49
|
+
"data-resolved": hasValue ? "true" : "false",
|
|
50
|
+
children: hasValue ? /* @__PURE__ */ jsx("span", { className: styles.chip(), title: `{{${name}}}`, children: /* @__PURE__ */ jsx("span", { className: styles.value(), children: displayValue }) }) : /* @__PURE__ */ jsxs(
|
|
51
|
+
"span",
|
|
52
|
+
{
|
|
53
|
+
className: styles.chip(),
|
|
54
|
+
title: fallback ? `Fallback: ${fallback}` : void 0,
|
|
55
|
+
children: [
|
|
56
|
+
/* @__PURE__ */ jsx("span", { className: styles.bracket(), children: "{" }),
|
|
57
|
+
/* @__PURE__ */ jsx("span", { className: styles.bracket(), children: "{" }),
|
|
58
|
+
/* @__PURE__ */ jsx("span", { className: styles.name(), children: name }),
|
|
59
|
+
/* @__PURE__ */ jsx("span", { className: styles.bracket(), children: "}" }),
|
|
60
|
+
/* @__PURE__ */ jsx("span", { className: styles.bracket(), children: "}" })
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
var variable_view_default = VariableNodeView;
|
|
68
|
+
|
|
69
|
+
export {
|
|
70
|
+
VariableNodeView,
|
|
71
|
+
variable_view_default
|
|
72
|
+
};
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
} from "./chunk-42HKGCOO.mjs";
|
|
14
14
|
|
|
15
15
|
// src/ui/suggestion-menu/suggestion-menu.tsx
|
|
16
|
-
import { flip, offset, shift, size } from "@floating-ui/react";
|
|
16
|
+
import { FloatingPortal, flip, offset, shift, size } from "@floating-ui/react";
|
|
17
17
|
import { PluginKey } from "@tiptap/pm/state";
|
|
18
18
|
import {
|
|
19
19
|
Suggestion,
|
|
@@ -191,7 +191,7 @@ var SuggestionMenu = ({
|
|
|
191
191
|
if (!isMounted || !show || !editor) {
|
|
192
192
|
return null;
|
|
193
193
|
}
|
|
194
|
-
return /* @__PURE__ */ jsx(
|
|
194
|
+
return /* @__PURE__ */ jsx(FloatingPortal, { children: /* @__PURE__ */ jsx(
|
|
195
195
|
"div",
|
|
196
196
|
{
|
|
197
197
|
ref,
|
|
@@ -208,7 +208,7 @@ var SuggestionMenu = ({
|
|
|
208
208
|
onSelect
|
|
209
209
|
})
|
|
210
210
|
}
|
|
211
|
-
);
|
|
211
|
+
) });
|
|
212
212
|
};
|
|
213
213
|
|
|
214
214
|
export {
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/extensions/variable/messages.ts
|
|
4
|
+
import { defineMessages } from "react-intl";
|
|
5
|
+
var messages = defineMessages({
|
|
6
|
+
title: {
|
|
7
|
+
id: "editor.variable.title",
|
|
8
|
+
defaultMessage: "Variables",
|
|
9
|
+
description: "Title for the variables section"
|
|
10
|
+
},
|
|
11
|
+
insert: {
|
|
12
|
+
id: "editor.variable.insert",
|
|
13
|
+
defaultMessage: "Insert variable",
|
|
14
|
+
description: "Insert variable button label"
|
|
15
|
+
},
|
|
16
|
+
empty_state: {
|
|
17
|
+
id: "editor.variable.empty_state",
|
|
18
|
+
defaultMessage: "No variables available",
|
|
19
|
+
description: "Empty state when no variables are defined"
|
|
20
|
+
},
|
|
21
|
+
hint: {
|
|
22
|
+
id: "editor.variable.hint",
|
|
23
|
+
defaultMessage: "Type {{ to insert a variable",
|
|
24
|
+
description: "Hint for inserting variables"
|
|
25
|
+
},
|
|
26
|
+
save: {
|
|
27
|
+
id: "editor.variable.save",
|
|
28
|
+
defaultMessage: "Save",
|
|
29
|
+
description: "Save button label"
|
|
30
|
+
},
|
|
31
|
+
cancel: {
|
|
32
|
+
id: "editor.variable.cancel",
|
|
33
|
+
defaultMessage: "Cancel",
|
|
34
|
+
description: "Cancel button label"
|
|
35
|
+
},
|
|
36
|
+
category_company: {
|
|
37
|
+
id: "editor.variable.category.company",
|
|
38
|
+
defaultMessage: "Company",
|
|
39
|
+
description: "Company variables category"
|
|
40
|
+
},
|
|
41
|
+
category_user: {
|
|
42
|
+
id: "editor.variable.category.user",
|
|
43
|
+
defaultMessage: "User",
|
|
44
|
+
description: "User variables category"
|
|
45
|
+
},
|
|
46
|
+
category_date: {
|
|
47
|
+
id: "editor.variable.category.date",
|
|
48
|
+
defaultMessage: "Date",
|
|
49
|
+
description: "Date variables category"
|
|
50
|
+
},
|
|
51
|
+
category_document: {
|
|
52
|
+
id: "editor.variable.category.document",
|
|
53
|
+
defaultMessage: "Document",
|
|
54
|
+
description: "Document variables category"
|
|
55
|
+
},
|
|
56
|
+
category_other: {
|
|
57
|
+
id: "editor.variable.category.other",
|
|
58
|
+
defaultMessage: "Other",
|
|
59
|
+
description: "Other variables category"
|
|
60
|
+
},
|
|
61
|
+
filler_title: {
|
|
62
|
+
id: "editor.variable.filler.title",
|
|
63
|
+
defaultMessage: "Fill in Variables",
|
|
64
|
+
description: "Title for the variable filler dialog"
|
|
65
|
+
},
|
|
66
|
+
filler_filled: {
|
|
67
|
+
id: "editor.variable.filler.filled",
|
|
68
|
+
defaultMessage: "filled",
|
|
69
|
+
description: "Label for filled count"
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
export {
|
|
74
|
+
messages
|
|
75
|
+
};
|