@kopexa/tiptap 17.3.0 → 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-LWU4F64F.mjs → chunk-GDDWW2IQ.mjs} +37 -12
- 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-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 +1829 -1260
- package/dist/index.mjs +35 -9
- 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 +4209 -3859
- package/dist/presets/basic/index.mjs +12 -8
- package/dist/ui/bubble-menu/index.js +1 -0
- package/dist/ui/bubble-menu/index.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({
|
|
@@ -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
|
+
};
|
|
@@ -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
|
+
};
|