@kopexa/tiptap 17.3.0 → 17.5.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.
Files changed (59) hide show
  1. package/dist/{chunk-NSYSECKW.mjs → chunk-2UDCL55K.mjs} +3 -1
  2. package/dist/chunk-4HO7BWDC.mjs +89 -0
  3. package/dist/chunk-552JLRNB.mjs +35 -0
  4. package/dist/chunk-5SMDMQDF.mjs +34 -0
  5. package/dist/{chunk-XKWTI3MA.mjs → chunk-DQK6PA4U.mjs} +11 -2
  6. package/dist/chunk-H7MS2UMO.mjs +168 -0
  7. package/dist/chunk-JVSH5T4B.mjs +72 -0
  8. package/dist/chunk-JZBRWJHC.mjs +170 -0
  9. package/dist/chunk-Q5FK7SFY.mjs +75 -0
  10. package/dist/chunk-QIELBKP3.mjs +104 -0
  11. package/dist/{chunk-XNDXYI2N.mjs → chunk-XGAABDMW.mjs} +2 -1
  12. package/dist/extensions/variable/extract-variables.d.mts +16 -0
  13. package/dist/extensions/variable/extract-variables.d.ts +16 -0
  14. package/dist/extensions/variable/extract-variables.js +58 -0
  15. package/dist/extensions/variable/extract-variables.mjs +7 -0
  16. package/dist/extensions/variable/index.d.mts +38 -0
  17. package/dist/extensions/variable/index.d.ts +38 -0
  18. package/dist/extensions/variable/index.js +190 -0
  19. package/dist/extensions/variable/index.mjs +11 -0
  20. package/dist/extensions/variable/messages.d.mts +69 -0
  21. package/dist/extensions/variable/messages.d.ts +69 -0
  22. package/dist/extensions/variable/messages.js +98 -0
  23. package/dist/extensions/variable/messages.mjs +7 -0
  24. package/dist/extensions/variable/variable-context.d.mts +56 -0
  25. package/dist/extensions/variable/variable-context.d.ts +56 -0
  26. package/dist/extensions/variable/variable-context.js +70 -0
  27. package/dist/extensions/variable/variable-context.mjs +12 -0
  28. package/dist/extensions/variable/variable-filler-dialog.d.mts +43 -0
  29. package/dist/extensions/variable/variable-filler-dialog.d.ts +43 -0
  30. package/dist/extensions/variable/variable-filler-dialog.js +207 -0
  31. package/dist/extensions/variable/variable-filler-dialog.mjs +9 -0
  32. package/dist/extensions/variable/variable-suggestion.d.mts +31 -0
  33. package/dist/extensions/variable/variable-suggestion.d.ts +31 -0
  34. package/dist/extensions/variable/variable-suggestion.js +615 -0
  35. package/dist/extensions/variable/variable-suggestion.mjs +14 -0
  36. package/dist/extensions/variable/variable-view.d.mts +13 -0
  37. package/dist/extensions/variable/variable-view.d.ts +13 -0
  38. package/dist/extensions/variable/variable-view.js +110 -0
  39. package/dist/extensions/variable/variable-view.mjs +11 -0
  40. package/dist/hooks/use-create-editor.d.mts +8 -2
  41. package/dist/hooks/use-create-editor.d.ts +8 -2
  42. package/dist/hooks/use-create-editor.js +163 -7
  43. package/dist/hooks/use-create-editor.mjs +4 -1
  44. package/dist/index.d.mts +5 -0
  45. package/dist/index.d.ts +5 -0
  46. package/dist/index.js +1866 -1260
  47. package/dist/index.mjs +35 -9
  48. package/dist/presets/basic/editor-header.mjs +3 -3
  49. package/dist/presets/basic/index.d.mts +12 -1
  50. package/dist/presets/basic/index.d.ts +12 -1
  51. package/dist/presets/basic/index.js +4245 -3858
  52. package/dist/presets/basic/index.mjs +12 -8
  53. package/dist/ui/bubble-menu/index.js +3 -1
  54. package/dist/ui/bubble-menu/index.mjs +1 -1
  55. package/dist/ui/link-bubble/index.js +2 -1
  56. package/dist/ui/link-bubble/index.mjs +1 -1
  57. package/package.json +24 -24
  58. package/dist/chunk-LWU4F64F.mjs +0 -110
  59. package/dist/{chunk-FDPXD6VC.mjs → chunk-RFWNKE7D.mjs} +3 -3
package/dist/index.js CHANGED
@@ -39,13 +39,20 @@ __export(index_exports, {
39
39
  InlineMath: () => InlineMath,
40
40
  MathBlock: () => MathBlock,
41
41
  TocNode: () => TocNode,
42
+ VariableFillerDialog: () => VariableFillerDialog,
43
+ VariableNode: () => VariableNode,
44
+ VariableProvider: () => VariableProvider,
45
+ VariableSuggestion: () => VariableSuggestion,
42
46
  convertFileToBase64: () => convertFileToBase64,
47
+ extractVariablesFromContent: () => extractVariablesFromContent,
43
48
  getExtensions: () => getExtensions,
44
49
  handleImageUpload: () => handleImageUpload,
45
50
  isAllowedUri: () => isAllowedUri,
46
51
  sanitizeUrl: () => sanitizeUrl,
47
52
  useEditorFile: () => useEditorFile,
48
- useEditorFileRequired: () => useEditorFileRequired
53
+ useEditorFileRequired: () => useEditorFileRequired,
54
+ useVariables: () => useVariables,
55
+ useVariablesWithFallback: () => useVariablesWithFallback
49
56
  });
50
57
  module.exports = __toCommonJS(index_exports);
51
58
 
@@ -2044,186 +2051,1160 @@ var TocNode = import_core5.Node.create({
2044
2051
  }
2045
2052
  });
2046
2053
 
2047
- // src/hooks/use-create-editor.ts
2048
- var import_extension_code = require("@kopexa/extension-code");
2049
- var import_extension_controlref = require("@kopexa/extension-controlref");
2050
- var import_extension_table = require("@kopexa/extension-table");
2051
- var import_extension_file_handler = require("@tiptap/extension-file-handler");
2052
- var import_extension_highlight = require("@tiptap/extension-highlight");
2053
- var import_extension_invisible_characters = __toESM(require("@tiptap/extension-invisible-characters"));
2054
- var import_extension_list = require("@tiptap/extension-list");
2055
- var import_extension_subscript = require("@tiptap/extension-subscript");
2056
- var import_extension_superscript = require("@tiptap/extension-superscript");
2057
- var import_extension_table_of_contents = require("@tiptap/extension-table-of-contents");
2058
- var import_extension_text_align = require("@tiptap/extension-text-align");
2059
- var import_extension_text_style = require("@tiptap/extension-text-style");
2060
- var import_extension_typography = require("@tiptap/extension-typography");
2061
- var import_extension_unique_id = require("@tiptap/extension-unique-id");
2062
- var import_extensions = require("@tiptap/extensions");
2063
- var import_react25 = require("@tiptap/react");
2064
- var import_starter_kit = require("@tiptap/starter-kit");
2065
- var import_react26 = require("react");
2054
+ // src/extensions/variable/index.ts
2055
+ var import_core6 = require("@tiptap/core");
2056
+ var import_react23 = require("@tiptap/react");
2066
2057
 
2067
- // src/extensions/link/index.ts
2068
- var import_extension_link = __toESM(require("@tiptap/extension-link"));
2069
- var import_state = require("@tiptap/pm/state");
2058
+ // src/extensions/variable/variable-view.tsx
2059
+ var import_theme5 = require("@kopexa/theme");
2070
2060
  var import_react22 = require("@tiptap/react");
2071
- var Link = import_extension_link.default.extend({
2072
- inclusive: false,
2061
+
2062
+ // src/extensions/variable/variable-context.tsx
2063
+ var React = __toESM(require("react"));
2064
+ var import_jsx_runtime10 = require("react/jsx-runtime");
2065
+ var VariableContext = React.createContext(null);
2066
+ function VariableProvider({
2067
+ children,
2068
+ variables,
2069
+ resolveVariable
2070
+ }) {
2071
+ const value = React.useMemo(
2072
+ () => ({
2073
+ variables,
2074
+ resolveVariable
2075
+ }),
2076
+ [variables, resolveVariable]
2077
+ );
2078
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(VariableContext.Provider, { value, children });
2079
+ }
2080
+ function useVariables() {
2081
+ return React.useContext(VariableContext);
2082
+ }
2083
+ function useVariablesWithFallback(fallbackVariables = []) {
2084
+ var _a;
2085
+ const context = React.useContext(VariableContext);
2086
+ return (_a = context == null ? void 0 : context.variables) != null ? _a : fallbackVariables;
2087
+ }
2088
+
2089
+ // src/extensions/variable/variable-view.tsx
2090
+ var import_jsx_runtime11 = require("react/jsx-runtime");
2091
+ function VariableNodeView({ node, editor }) {
2092
+ var _a;
2093
+ const attrs = node.attrs;
2094
+ const { name, fallback, category } = attrs;
2095
+ const context = useVariables();
2096
+ const isEditable = (0, import_react22.useEditorState)({
2097
+ editor,
2098
+ selector: ({ editor: e }) => {
2099
+ var _a2;
2100
+ return (_a2 = e == null ? void 0 : e.isEditable) != null ? _a2 : true;
2101
+ }
2102
+ });
2103
+ const resolvedValue = (_a = context == null ? void 0 : context.resolveVariable) == null ? void 0 : _a.call(context, name);
2104
+ const hasValue = resolvedValue !== void 0 && resolvedValue !== "";
2105
+ const displayValue = resolvedValue || fallback;
2106
+ const styles = (0, import_theme5.variableNode)({ resolved: hasValue });
2107
+ if (!isEditable && hasValue) {
2108
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2109
+ import_react22.NodeViewWrapper,
2110
+ {
2111
+ as: "span",
2112
+ "data-type": "variable",
2113
+ "data-name": name,
2114
+ style: { userSelect: "text" },
2115
+ children: displayValue
2116
+ }
2117
+ );
2118
+ }
2119
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2120
+ import_react22.NodeViewWrapper,
2121
+ {
2122
+ as: "span",
2123
+ className: styles.wrapper(),
2124
+ "data-type": "variable",
2125
+ "data-name": name,
2126
+ "data-category": category,
2127
+ "data-resolved": hasValue ? "true" : "false",
2128
+ children: hasValue ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: styles.chip(), title: `{{${name}}}`, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: styles.value(), children: displayValue }) }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2129
+ "span",
2130
+ {
2131
+ className: styles.chip(),
2132
+ title: fallback ? `Fallback: ${fallback}` : void 0,
2133
+ children: [
2134
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: styles.bracket(), children: "{" }),
2135
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: styles.bracket(), children: "{" }),
2136
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: styles.name(), children: name }),
2137
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: styles.bracket(), children: "}" }),
2138
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: styles.bracket(), children: "}" })
2139
+ ]
2140
+ }
2141
+ )
2142
+ }
2143
+ );
2144
+ }
2145
+
2146
+ // src/extensions/variable/index.ts
2147
+ var VariableNode = import_core6.Node.create({
2148
+ name: "variable",
2149
+ group: "inline",
2150
+ inline: true,
2151
+ atom: true,
2152
+ selectable: true,
2153
+ draggable: true,
2154
+ addOptions() {
2155
+ return {
2156
+ HTMLAttributes: {}
2157
+ };
2158
+ },
2159
+ addAttributes() {
2160
+ return {
2161
+ name: {
2162
+ default: "",
2163
+ parseHTML: (element) => element.getAttribute("data-name"),
2164
+ renderHTML: (attributes) => ({
2165
+ "data-name": attributes.name
2166
+ })
2167
+ },
2168
+ fallback: {
2169
+ default: void 0,
2170
+ parseHTML: (element) => element.getAttribute("data-fallback"),
2171
+ renderHTML: (attributes) => {
2172
+ if (!attributes.fallback) return {};
2173
+ return {
2174
+ "data-fallback": attributes.fallback
2175
+ };
2176
+ }
2177
+ },
2178
+ category: {
2179
+ default: void 0,
2180
+ parseHTML: (element) => element.getAttribute("data-category"),
2181
+ renderHTML: (attributes) => {
2182
+ if (!attributes.category) return {};
2183
+ return {
2184
+ "data-category": attributes.category
2185
+ };
2186
+ }
2187
+ }
2188
+ };
2189
+ },
2073
2190
  parseHTML() {
2074
2191
  return [
2075
2192
  {
2076
- tag: 'a[href]:not([data-type="button"]):not([href *= "javascript:" i])'
2193
+ tag: 'span[data-type="variable"]'
2077
2194
  }
2078
2195
  ];
2079
2196
  },
2080
- addProseMirrorPlugins() {
2081
- var _a;
2082
- const { editor } = this;
2083
- return [
2084
- ...((_a = this.parent) == null ? void 0 : _a.call(this)) || [],
2085
- new import_state.Plugin({
2086
- key: new import_state.PluginKey("linkKeyHandler"),
2087
- props: {
2088
- handleKeyDown: (_, event) => {
2089
- const { selection } = editor.state;
2090
- if (event.key === "Escape" && selection.empty !== true) {
2091
- editor.commands.focus(selection.to, { scrollIntoView: false });
2092
- }
2093
- return false;
2094
- },
2095
- handleClick(view, pos) {
2096
- const { schema, doc, tr } = view.state;
2097
- let range;
2098
- if (schema.marks.link) {
2099
- range = (0, import_react22.getMarkRange)(doc.resolve(pos), schema.marks.link);
2100
- }
2101
- if (!range) {
2102
- return;
2103
- }
2104
- const { from, to } = range;
2105
- const start = Math.min(from, to);
2106
- const end = Math.max(from, to);
2107
- if (pos < start || pos > end) {
2108
- return;
2109
- }
2110
- const $start = doc.resolve(start);
2111
- const $end = doc.resolve(end);
2112
- const transaction = tr.setSelection(
2113
- new import_state.TextSelection($start, $end)
2114
- );
2115
- view.dispatch(transaction);
2116
- }
2117
- }
2118
- })
2119
- ];
2120
- }
2121
- });
2122
-
2123
- // src/extensions/selection/index.ts
2124
- var import_state2 = require("@tiptap/pm/state");
2125
- var import_view = require("@tiptap/pm/view");
2126
- var import_react23 = require("@tiptap/react");
2127
- var Selection = import_react23.Extension.create({
2128
- name: "selection",
2129
- addProseMirrorPlugins() {
2130
- const { editor } = this;
2197
+ renderHTML({ node, HTMLAttributes }) {
2198
+ const attrs = node.attrs;
2131
2199
  return [
2132
- new import_state2.Plugin({
2133
- key: new import_state2.PluginKey("selection"),
2134
- props: {
2135
- decorations(state) {
2136
- if (state.selection.empty) {
2137
- return null;
2138
- }
2139
- if (editor.isFocused === true || !editor.isEditable) {
2140
- return null;
2141
- }
2142
- if ((0, import_react23.isNodeSelection)(state.selection)) {
2143
- return null;
2144
- }
2145
- return import_view.DecorationSet.create(state.doc, [
2146
- import_view.Decoration.inline(state.selection.from, state.selection.to, {
2147
- class: "selection"
2148
- })
2149
- ]);
2150
- }
2151
- }
2152
- })
2200
+ "span",
2201
+ (0, import_core6.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes, {
2202
+ "data-type": "variable",
2203
+ class: "variable-node"
2204
+ }),
2205
+ `{{${attrs.name}}}`
2153
2206
  ];
2207
+ },
2208
+ addNodeView() {
2209
+ return (0, import_react23.ReactNodeViewRenderer)(VariableNodeView);
2210
+ },
2211
+ addCommands() {
2212
+ return {
2213
+ insertVariable: (attrs) => ({ commands }) => {
2214
+ return commands.insertContent({
2215
+ type: this.name,
2216
+ attrs
2217
+ });
2218
+ }
2219
+ };
2154
2220
  }
2155
2221
  });
2156
2222
 
2157
- // src/extensions/trailing-node/index.ts
2158
- var import_state3 = require("@tiptap/pm/state");
2159
- var import_react24 = require("@tiptap/react");
2160
- function nodeEqualsType({
2161
- types,
2162
- node
2163
- }) {
2164
- if (!node) return false;
2165
- if (Array.isArray(types)) {
2166
- return types.includes(node.type);
2223
+ // src/extensions/variable/extract-variables.ts
2224
+ function extractVariablesFromContent(content) {
2225
+ if (!content) return [];
2226
+ const variables = /* @__PURE__ */ new Map();
2227
+ function scan(node) {
2228
+ var _a;
2229
+ if (node.type === "variable" && ((_a = node.attrs) == null ? void 0 : _a.name)) {
2230
+ const name = node.attrs.name;
2231
+ if (!variables.has(name)) {
2232
+ variables.set(name, {
2233
+ name,
2234
+ label: formatVariableName(name),
2235
+ category: node.attrs.category || void 0,
2236
+ fallback: node.attrs.fallback || void 0
2237
+ });
2238
+ }
2239
+ }
2240
+ if (node.content && Array.isArray(node.content)) {
2241
+ for (const child of node.content) {
2242
+ scan(child);
2243
+ }
2244
+ }
2167
2245
  }
2168
- return node.type === types;
2246
+ scan(content);
2247
+ return Array.from(variables.values());
2169
2248
  }
2170
- var TrailingNode = import_react24.Extension.create({
2171
- name: "trailingNode",
2172
- addOptions() {
2173
- return {
2174
- node: "paragraph",
2175
- notAfter: ["paragraph"]
2176
- };
2249
+ function formatVariableName(name) {
2250
+ return name.replace(/([A-Z])/g, " $1").replace(/[_-]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()).replace(/\s+/g, " ").trim();
2251
+ }
2252
+
2253
+ // src/extensions/variable/variable-filler-dialog.tsx
2254
+ var import_button7 = require("@kopexa/button");
2255
+ var import_dialog5 = require("@kopexa/dialog");
2256
+ var import_input2 = require("@kopexa/input");
2257
+ var import_label5 = require("@kopexa/label");
2258
+ var React2 = __toESM(require("react"));
2259
+ var import_react_intl14 = require("react-intl");
2260
+
2261
+ // src/extensions/variable/messages.ts
2262
+ var import_react_intl13 = require("react-intl");
2263
+ var messages6 = (0, import_react_intl13.defineMessages)({
2264
+ title: {
2265
+ id: "editor.variable.title",
2266
+ defaultMessage: "Variables",
2267
+ description: "Title for the variables section"
2177
2268
  },
2178
- addProseMirrorPlugins() {
2179
- const plugin = new import_state3.PluginKey(this.name);
2180
- const disabledNodes = Object.entries(this.editor.schema.nodes).map(([, value]) => value).filter((node) => this.options.notAfter.includes(node.name));
2181
- return [
2182
- new import_state3.Plugin({
2183
- key: plugin,
2184
- appendTransaction: (_, __, state) => {
2185
- const { doc, tr, schema } = state;
2186
- const shouldInsertNodeAtEnd = plugin.getState(state);
2187
- const endPosition = doc.content.size;
2188
- const type = schema.nodes[this.options.node];
2189
- if (!shouldInsertNodeAtEnd) {
2190
- return null;
2191
- }
2192
- if (type) {
2193
- return tr.insert(endPosition, type.create());
2194
- }
2195
- return null;
2196
- },
2197
- state: {
2198
- init: (_, state) => {
2199
- const lastNode = state.tr.doc.lastChild;
2200
- return !nodeEqualsType({ node: lastNode, types: disabledNodes });
2201
- },
2202
- apply: (tr, value) => {
2203
- if (!tr.docChanged) {
2204
- return value;
2205
- }
2206
- const lastNode = tr.doc.lastChild;
2207
- return !nodeEqualsType({ node: lastNode, types: disabledNodes });
2208
- }
2209
- }
2210
- })
2211
- ];
2269
+ insert: {
2270
+ id: "editor.variable.insert",
2271
+ defaultMessage: "Insert variable",
2272
+ description: "Insert variable button label"
2273
+ },
2274
+ empty_state: {
2275
+ id: "editor.variable.empty_state",
2276
+ defaultMessage: "No variables available",
2277
+ description: "Empty state when no variables are defined"
2278
+ },
2279
+ hint: {
2280
+ id: "editor.variable.hint",
2281
+ defaultMessage: "Type {{ to insert a variable",
2282
+ description: "Hint for inserting variables"
2283
+ },
2284
+ save: {
2285
+ id: "editor.variable.save",
2286
+ defaultMessage: "Save",
2287
+ description: "Save button label"
2288
+ },
2289
+ cancel: {
2290
+ id: "editor.variable.cancel",
2291
+ defaultMessage: "Cancel",
2292
+ description: "Cancel button label"
2293
+ },
2294
+ category_company: {
2295
+ id: "editor.variable.category.company",
2296
+ defaultMessage: "Company",
2297
+ description: "Company variables category"
2298
+ },
2299
+ category_user: {
2300
+ id: "editor.variable.category.user",
2301
+ defaultMessage: "User",
2302
+ description: "User variables category"
2303
+ },
2304
+ category_date: {
2305
+ id: "editor.variable.category.date",
2306
+ defaultMessage: "Date",
2307
+ description: "Date variables category"
2308
+ },
2309
+ category_document: {
2310
+ id: "editor.variable.category.document",
2311
+ defaultMessage: "Document",
2312
+ description: "Document variables category"
2313
+ },
2314
+ category_other: {
2315
+ id: "editor.variable.category.other",
2316
+ defaultMessage: "Other",
2317
+ description: "Other variables category"
2318
+ },
2319
+ filler_title: {
2320
+ id: "editor.variable.filler.title",
2321
+ defaultMessage: "Fill in Variables",
2322
+ description: "Title for the variable filler dialog"
2323
+ },
2324
+ filler_filled: {
2325
+ id: "editor.variable.filler.filled",
2326
+ defaultMessage: "filled",
2327
+ description: "Label for filled count"
2212
2328
  }
2213
2329
  });
2214
2330
 
2215
- // src/extensions/ui-state/index.ts
2216
- var import_core6 = require("@tiptap/core");
2217
- var defaultUiState = {
2218
- aiGenerationIsSelection: false,
2219
- aiGenerationIsLoading: false,
2220
- aiGenerationActive: false,
2221
- aiGenerationHasMessage: false,
2222
- commentInputVisible: false,
2331
+ // src/extensions/variable/variable-filler-dialog.tsx
2332
+ var import_jsx_runtime12 = require("react/jsx-runtime");
2333
+ function VariableFillerDialog({
2334
+ open,
2335
+ onOpenChange,
2336
+ variables,
2337
+ values,
2338
+ onSave,
2339
+ title,
2340
+ description
2341
+ }) {
2342
+ const intl = (0, import_react_intl14.useIntl)();
2343
+ const [localValues, setLocalValues] = React2.useState(
2344
+ {}
2345
+ );
2346
+ React2.useEffect(() => {
2347
+ if (open) {
2348
+ setLocalValues({ ...values });
2349
+ }
2350
+ }, [open, values]);
2351
+ const handleChange = React2.useCallback((name, value) => {
2352
+ setLocalValues((prev) => ({
2353
+ ...prev,
2354
+ [name]: value
2355
+ }));
2356
+ }, []);
2357
+ const handleSave = React2.useCallback(() => {
2358
+ onSave(localValues);
2359
+ onOpenChange(false);
2360
+ }, [localValues, onSave, onOpenChange]);
2361
+ const handleCancel = React2.useCallback(() => {
2362
+ setLocalValues({ ...values });
2363
+ onOpenChange(false);
2364
+ }, [values, onOpenChange]);
2365
+ const groupedVariables = React2.useMemo(() => {
2366
+ return variables.reduce(
2367
+ (acc, v) => {
2368
+ const cat = v.category || intl.formatMessage(messages6.category_other);
2369
+ if (!acc[cat]) acc[cat] = [];
2370
+ acc[cat].push(v);
2371
+ return acc;
2372
+ },
2373
+ {}
2374
+ );
2375
+ }, [variables, intl]);
2376
+ const filledCount = React2.useMemo(() => {
2377
+ return variables.filter((v) => {
2378
+ var _a;
2379
+ return (_a = localValues[v.name]) == null ? void 0 : _a.trim();
2380
+ }).length;
2381
+ }, [variables, localValues]);
2382
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_dialog5.Dialog.Root, { open, onOpenChange, size: "md", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_dialog5.Dialog.Content, { children: [
2383
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_dialog5.Dialog.Header, { children: [
2384
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_dialog5.Dialog.Title, { children: title || intl.formatMessage(messages6.filler_title) }),
2385
+ description && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_dialog5.Dialog.Description, { children: description })
2386
+ ] }),
2387
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_dialog5.Dialog.Body, { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "space-y-6", children: Object.entries(groupedVariables).map(([category, vars]) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
2388
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h4", { className: "text-sm font-semibold text-muted-foreground uppercase tracking-wide mb-3", children: category }),
2389
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "space-y-3", children: vars.map((v) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "space-y-1.5", children: [
2390
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_label5.Label, { htmlFor: `var-${v.name}`, className: "text-sm", children: [
2391
+ v.label,
2392
+ v.description && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ml-2 text-xs text-muted-foreground font-normal", children: v.description })
2393
+ ] }),
2394
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2395
+ import_input2.Input,
2396
+ {
2397
+ id: `var-${v.name}`,
2398
+ placeholder: v.fallback || `{{${v.name}}}`,
2399
+ value: localValues[v.name] || "",
2400
+ onChange: (e) => handleChange(v.name, e.target.value)
2401
+ }
2402
+ )
2403
+ ] }, v.name)) })
2404
+ ] }, category)) }) }),
2405
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_dialog5.Dialog.Footer, { className: "flex items-center justify-between", children: [
2406
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "text-sm text-muted-foreground", children: [
2407
+ filledCount,
2408
+ " / ",
2409
+ variables.length,
2410
+ " ",
2411
+ intl.formatMessage(messages6.filler_filled)
2412
+ ] }),
2413
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex gap-2", children: [
2414
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_button7.Button, { variant: "ghost", onClick: handleCancel, children: intl.formatMessage(messages6.cancel) }),
2415
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_button7.Button, { onClick: handleSave, children: intl.formatMessage(messages6.save) })
2416
+ ] })
2417
+ ] })
2418
+ ] }) });
2419
+ }
2420
+
2421
+ // src/extensions/variable/variable-suggestion.tsx
2422
+ var import_editor_utils = require("@kopexa/editor-utils");
2423
+ var import_theme6 = require("@kopexa/theme");
2424
+ var import_state2 = require("@tiptap/pm/state");
2425
+ var React6 = __toESM(require("react"));
2426
+
2427
+ // src/ui/suggestion-menu/suggestion-menu.tsx
2428
+ var import_react27 = require("@floating-ui/react");
2429
+ var import_state = require("@tiptap/pm/state");
2430
+ var import_suggestion = require("@tiptap/suggestion");
2431
+ var React5 = __toESM(require("react"));
2432
+
2433
+ // src/hooks/use-floating-element.ts
2434
+ var import_react24 = require("@floating-ui/react");
2435
+ var React3 = __toESM(require("react"));
2436
+ function useFloatingElement(show, referencePos, zIndex, options) {
2437
+ const { dismissOptions, ...floatingOptions } = options || {};
2438
+ const { refs, update, context, floatingStyles } = (0, import_react24.useFloating)({
2439
+ open: show,
2440
+ ...floatingOptions
2441
+ });
2442
+ const { isMounted, styles } = (0, import_react24.useTransitionStyles)(context);
2443
+ const dismiss = (0, import_react24.useDismiss)(context, dismissOptions);
2444
+ const { getReferenceProps, getFloatingProps } = (0, import_react24.useInteractions)([dismiss]);
2445
+ React3.useEffect(() => {
2446
+ update();
2447
+ }, [referencePos, update]);
2448
+ React3.useEffect(() => {
2449
+ if (referencePos === null) {
2450
+ return;
2451
+ }
2452
+ refs.setReference({
2453
+ getBoundingClientRect: () => referencePos
2454
+ });
2455
+ }, [referencePos, refs]);
2456
+ return React3.useMemo(
2457
+ () => ({
2458
+ isMounted,
2459
+ ref: refs.setFloating,
2460
+ style: {
2461
+ ...styles,
2462
+ ...floatingStyles,
2463
+ zIndex
2464
+ },
2465
+ update,
2466
+ getFloatingProps,
2467
+ getReferenceProps
2468
+ }),
2469
+ [
2470
+ floatingStyles,
2471
+ isMounted,
2472
+ refs.setFloating,
2473
+ styles,
2474
+ update,
2475
+ zIndex,
2476
+ getFloatingProps,
2477
+ getReferenceProps
2478
+ ]
2479
+ );
2480
+ }
2481
+
2482
+ // src/hooks/use-menu-navigation.ts
2483
+ var React4 = __toESM(require("react"));
2484
+ function useMenuNavigation({
2485
+ editor,
2486
+ containerRef,
2487
+ query,
2488
+ items,
2489
+ onSelect,
2490
+ onClose,
2491
+ orientation = "vertical",
2492
+ autoSelectFirstItem = true
2493
+ }) {
2494
+ const [selectedIndex, setSelectedIndex] = React4.useState(
2495
+ autoSelectFirstItem ? 0 : -1
2496
+ );
2497
+ React4.useEffect(() => {
2498
+ const handleKeyboardNavigation = (event) => {
2499
+ if (!items.length) return false;
2500
+ const moveNext = () => setSelectedIndex((currentIndex) => {
2501
+ if (currentIndex === -1) return 0;
2502
+ return (currentIndex + 1) % items.length;
2503
+ });
2504
+ const movePrev = () => setSelectedIndex((currentIndex) => {
2505
+ if (currentIndex === -1) return items.length - 1;
2506
+ return (currentIndex - 1 + items.length) % items.length;
2507
+ });
2508
+ switch (event.key) {
2509
+ case "ArrowUp": {
2510
+ if (orientation === "horizontal") return false;
2511
+ event.preventDefault();
2512
+ movePrev();
2513
+ return true;
2514
+ }
2515
+ case "ArrowDown": {
2516
+ if (orientation === "horizontal") return false;
2517
+ event.preventDefault();
2518
+ moveNext();
2519
+ return true;
2520
+ }
2521
+ case "ArrowLeft": {
2522
+ if (orientation === "vertical") return false;
2523
+ event.preventDefault();
2524
+ movePrev();
2525
+ return true;
2526
+ }
2527
+ case "ArrowRight": {
2528
+ if (orientation === "vertical") return false;
2529
+ event.preventDefault();
2530
+ moveNext();
2531
+ return true;
2532
+ }
2533
+ case "Tab": {
2534
+ event.preventDefault();
2535
+ if (event.shiftKey) {
2536
+ movePrev();
2537
+ } else {
2538
+ moveNext();
2539
+ }
2540
+ return true;
2541
+ }
2542
+ case "Home": {
2543
+ event.preventDefault();
2544
+ setSelectedIndex(0);
2545
+ return true;
2546
+ }
2547
+ case "End": {
2548
+ event.preventDefault();
2549
+ setSelectedIndex(items.length - 1);
2550
+ return true;
2551
+ }
2552
+ case "Enter": {
2553
+ if (event.isComposing) return false;
2554
+ event.preventDefault();
2555
+ if (selectedIndex !== -1 && items[selectedIndex]) {
2556
+ onSelect == null ? void 0 : onSelect(items[selectedIndex]);
2557
+ }
2558
+ return true;
2559
+ }
2560
+ case "Escape": {
2561
+ event.preventDefault();
2562
+ onClose == null ? void 0 : onClose();
2563
+ return true;
2564
+ }
2565
+ default:
2566
+ return false;
2567
+ }
2568
+ };
2569
+ let targetElement = null;
2570
+ if (editor) {
2571
+ targetElement = editor.view.dom;
2572
+ } else if (containerRef == null ? void 0 : containerRef.current) {
2573
+ targetElement = containerRef.current;
2574
+ }
2575
+ if (targetElement) {
2576
+ targetElement.addEventListener("keydown", handleKeyboardNavigation, true);
2577
+ return () => {
2578
+ targetElement == null ? void 0 : targetElement.removeEventListener(
2579
+ "keydown",
2580
+ handleKeyboardNavigation,
2581
+ true
2582
+ );
2583
+ };
2584
+ }
2585
+ return void 0;
2586
+ }, [
2587
+ editor,
2588
+ containerRef,
2589
+ items,
2590
+ selectedIndex,
2591
+ onSelect,
2592
+ onClose,
2593
+ orientation
2594
+ ]);
2595
+ React4.useEffect(() => {
2596
+ if (query) {
2597
+ setSelectedIndex(autoSelectFirstItem ? 0 : -1);
2598
+ }
2599
+ }, [query, autoSelectFirstItem]);
2600
+ return {
2601
+ selectedIndex: items.length ? selectedIndex : void 0,
2602
+ setSelectedIndex
2603
+ };
2604
+ }
2605
+
2606
+ // src/hooks/use-tiptap-editor.ts
2607
+ var import_react25 = require("@tiptap/react");
2608
+ var import_react26 = require("react");
2609
+ function useTiptapEditor(providedEditor) {
2610
+ const { editor: coreEditor } = (0, import_react25.useCurrentEditor)();
2611
+ const mainEditor = (0, import_react26.useMemo)(
2612
+ () => providedEditor || coreEditor,
2613
+ [providedEditor, coreEditor]
2614
+ );
2615
+ const editorState = (0, import_react25.useEditorState)({
2616
+ editor: mainEditor,
2617
+ selector(context) {
2618
+ if (!context.editor) {
2619
+ return {
2620
+ editor: null,
2621
+ editorState: void 0,
2622
+ canCommand: void 0
2623
+ };
2624
+ }
2625
+ return {
2626
+ editor: context.editor,
2627
+ editorState: context.editor.state,
2628
+ canCommand: context.editor.can
2629
+ };
2630
+ }
2631
+ });
2632
+ return editorState || { editor: null };
2633
+ }
2634
+
2635
+ // src/ui/suggestion-menu/suggestion-menu-utils.ts
2636
+ function calculateStartPosition(cursorPosition, previousNode, triggerChar) {
2637
+ if (!(previousNode == null ? void 0 : previousNode.text) || !triggerChar) {
2638
+ return cursorPosition;
2639
+ }
2640
+ const commandText = previousNode.text;
2641
+ const triggerCharIndex = commandText.lastIndexOf(triggerChar);
2642
+ if (triggerCharIndex === -1) {
2643
+ return cursorPosition;
2644
+ }
2645
+ const textLength = commandText.substring(triggerCharIndex).length;
2646
+ return cursorPosition - textLength;
2647
+ }
2648
+ function filterSuggestionItems(items, query) {
2649
+ const normalizedQuery = query.trim().toLowerCase();
2650
+ if (!normalizedQuery) {
2651
+ return items;
2652
+ }
2653
+ return items.filter((item) => {
2654
+ var _a, _b;
2655
+ if (item.title.toLowerCase().includes(normalizedQuery)) {
2656
+ return true;
2657
+ }
2658
+ if ((_a = item.subtext) == null ? void 0 : _a.toLowerCase().includes(normalizedQuery)) {
2659
+ return true;
2660
+ }
2661
+ if ((_b = item.keywords) == null ? void 0 : _b.some(
2662
+ (keyword) => keyword.toLowerCase().includes(normalizedQuery)
2663
+ )) {
2664
+ return true;
2665
+ }
2666
+ return false;
2667
+ }).sort((a, b) => {
2668
+ const aTitle = a.title.toLowerCase();
2669
+ const bTitle = b.title.toLowerCase();
2670
+ if (aTitle === normalizedQuery && bTitle !== normalizedQuery) return -1;
2671
+ if (bTitle === normalizedQuery && aTitle !== normalizedQuery) return 1;
2672
+ if (aTitle.startsWith(normalizedQuery) && !bTitle.startsWith(normalizedQuery))
2673
+ return -1;
2674
+ if (bTitle.startsWith(normalizedQuery) && !aTitle.startsWith(normalizedQuery))
2675
+ return 1;
2676
+ return 0;
2677
+ });
2678
+ }
2679
+
2680
+ // src/ui/suggestion-menu/suggestion-menu.tsx
2681
+ var import_jsx_runtime13 = require("react/jsx-runtime");
2682
+ var SuggestionMenu = ({
2683
+ editor: providedEditor,
2684
+ floatingOptions,
2685
+ selector = "tiptap-suggestion-menu",
2686
+ children,
2687
+ maxHeight = 384,
2688
+ pluginKey = import_suggestion.SuggestionPluginKey,
2689
+ ...internalSuggestionProps
2690
+ }) => {
2691
+ const { editor } = useTiptapEditor(providedEditor);
2692
+ const [show, setShow] = React5.useState(false);
2693
+ const [internalClientRect, setInternalClientRect] = React5.useState(null);
2694
+ const [internalCommand, setInternalCommand] = React5.useState(null);
2695
+ const [internalItems, setInternalItems] = React5.useState(
2696
+ []
2697
+ );
2698
+ const [internalQuery, setInternalQuery] = React5.useState("");
2699
+ const [, setInternalRange] = React5.useState(null);
2700
+ const { ref, style, getFloatingProps, isMounted } = useFloatingElement(
2701
+ show,
2702
+ internalClientRect,
2703
+ 1e3,
2704
+ {
2705
+ placement: "bottom-start",
2706
+ middleware: [
2707
+ (0, import_react27.offset)(10),
2708
+ (0, import_react27.flip)({
2709
+ mainAxis: true,
2710
+ crossAxis: false
2711
+ }),
2712
+ (0, import_react27.shift)(),
2713
+ (0, import_react27.size)({
2714
+ apply({ availableHeight, elements }) {
2715
+ if (elements.floating) {
2716
+ const maxHeightValue = maxHeight ? Math.min(maxHeight, availableHeight) : availableHeight;
2717
+ elements.floating.style.setProperty(
2718
+ "--suggestion-menu-max-height",
2719
+ `${maxHeightValue}px`
2720
+ );
2721
+ }
2722
+ }
2723
+ })
2724
+ ],
2725
+ onOpenChange(open) {
2726
+ if (!open) {
2727
+ setShow(false);
2728
+ }
2729
+ },
2730
+ ...floatingOptions
2731
+ }
2732
+ );
2733
+ const internalSuggestionPropsRef = React5.useRef(internalSuggestionProps);
2734
+ React5.useEffect(() => {
2735
+ internalSuggestionPropsRef.current = internalSuggestionProps;
2736
+ }, [internalSuggestionProps]);
2737
+ const closePopup = React5.useCallback(() => {
2738
+ setShow(false);
2739
+ }, []);
2740
+ React5.useEffect(() => {
2741
+ if (!editor || editor.isDestroyed) {
2742
+ return;
2743
+ }
2744
+ const existingPlugin = editor.state.plugins.find(
2745
+ (plugin) => plugin.spec.key === pluginKey
2746
+ );
2747
+ if (existingPlugin) {
2748
+ editor.unregisterPlugin(pluginKey);
2749
+ }
2750
+ const suggestion = (0, import_suggestion.Suggestion)({
2751
+ pluginKey: pluginKey instanceof import_state.PluginKey ? pluginKey : new import_state.PluginKey(pluginKey),
2752
+ editor,
2753
+ command({ editor: editor2, range, props }) {
2754
+ var _a, _b;
2755
+ if (!range) {
2756
+ return;
2757
+ }
2758
+ const { view, state } = editor2;
2759
+ const { selection } = state;
2760
+ const isMention = editor2.extensionManager.extensions.some(
2761
+ (extension) => {
2762
+ var _a2, _b2;
2763
+ const name = extension.name;
2764
+ return name === "mention" && ((_b2 = (_a2 = extension.options) == null ? void 0 : _a2.suggestion) == null ? void 0 : _b2.char) === internalSuggestionPropsRef.current.char;
2765
+ }
2766
+ );
2767
+ if (!isMention) {
2768
+ const cursorPosition = selection.$from.pos;
2769
+ const previousNode = (_a = selection.$head) == null ? void 0 : _a.nodeBefore;
2770
+ const startPosition = previousNode ? calculateStartPosition(
2771
+ cursorPosition,
2772
+ previousNode,
2773
+ internalSuggestionPropsRef.current.char
2774
+ ) : selection.$from.start();
2775
+ const transaction = state.tr.deleteRange(
2776
+ startPosition,
2777
+ cursorPosition
2778
+ );
2779
+ view.dispatch(transaction);
2780
+ }
2781
+ const nodeAfter = view.state.selection.$to.nodeAfter;
2782
+ const overrideSpace = (_b = nodeAfter == null ? void 0 : nodeAfter.text) == null ? void 0 : _b.startsWith(" ");
2783
+ const rangeToUse = { ...range };
2784
+ if (overrideSpace) {
2785
+ rangeToUse.to += 1;
2786
+ }
2787
+ props.onSelect({ editor: editor2, range: rangeToUse, context: props.context });
2788
+ },
2789
+ render: () => {
2790
+ return {
2791
+ onStart: (props) => {
2792
+ var _a, _b;
2793
+ setInternalCommand(() => props.command);
2794
+ setInternalItems(props.items);
2795
+ setInternalQuery(props.query);
2796
+ setInternalRange(props.range);
2797
+ setInternalClientRect((_b = (_a = props.clientRect) == null ? void 0 : _a.call(props)) != null ? _b : null);
2798
+ setShow(true);
2799
+ },
2800
+ onUpdate: (props) => {
2801
+ var _a, _b;
2802
+ setInternalCommand(() => props.command);
2803
+ setInternalItems(props.items);
2804
+ setInternalQuery(props.query);
2805
+ setInternalRange(props.range);
2806
+ setInternalClientRect((_b = (_a = props.clientRect) == null ? void 0 : _a.call(props)) != null ? _b : null);
2807
+ },
2808
+ onKeyDown: (props) => {
2809
+ if (props.event.key === "Escape") {
2810
+ closePopup();
2811
+ return true;
2812
+ }
2813
+ return false;
2814
+ },
2815
+ onExit: () => {
2816
+ setInternalCommand(null);
2817
+ setInternalItems([]);
2818
+ setInternalQuery("");
2819
+ setInternalRange(null);
2820
+ setInternalClientRect(null);
2821
+ setShow(false);
2822
+ }
2823
+ };
2824
+ },
2825
+ ...internalSuggestionPropsRef.current
2826
+ });
2827
+ editor.registerPlugin(suggestion);
2828
+ return () => {
2829
+ if (!editor.isDestroyed) {
2830
+ editor.unregisterPlugin(pluginKey);
2831
+ }
2832
+ };
2833
+ }, [editor, pluginKey, closePopup]);
2834
+ const onSelect = React5.useCallback(
2835
+ (item) => {
2836
+ closePopup();
2837
+ if (internalCommand) {
2838
+ internalCommand(item);
2839
+ }
2840
+ },
2841
+ [closePopup, internalCommand]
2842
+ );
2843
+ const { selectedIndex } = useMenuNavigation({
2844
+ editor,
2845
+ query: internalQuery,
2846
+ items: internalItems,
2847
+ onSelect
2848
+ });
2849
+ if (!isMounted || !show || !editor) {
2850
+ return null;
2851
+ }
2852
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react27.FloatingPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2853
+ "div",
2854
+ {
2855
+ ref,
2856
+ style,
2857
+ ...getFloatingProps(),
2858
+ "data-selector": selector,
2859
+ className: "tiptap-suggestion-menu",
2860
+ role: "listbox",
2861
+ "aria-label": "Suggestions",
2862
+ onPointerDown: (e) => e.preventDefault(),
2863
+ children: children({
2864
+ items: internalItems,
2865
+ selectedIndex,
2866
+ onSelect
2867
+ })
2868
+ }
2869
+ ) });
2870
+ };
2871
+
2872
+ // src/extensions/variable/variable-suggestion.tsx
2873
+ var import_jsx_runtime14 = require("react/jsx-runtime");
2874
+ var VariableSuggestionPluginKey = new import_state2.PluginKey("variableSuggestion");
2875
+ function VariableSuggestion({
2876
+ editor,
2877
+ variables
2878
+ }) {
2879
+ const getItems = React6.useCallback(
2880
+ ({ query }) => {
2881
+ const normalizedQuery = query.toLowerCase().trim();
2882
+ const items = [];
2883
+ const matchingVariables = variables.filter((variable) => {
2884
+ var _a, _b;
2885
+ if (!normalizedQuery) return true;
2886
+ 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));
2887
+ });
2888
+ for (const variable of matchingVariables) {
2889
+ items.push({
2890
+ title: variable.label,
2891
+ subtext: variable.name,
2892
+ group: variable.category,
2893
+ keywords: [variable.name, variable.label, variable.category].filter(
2894
+ Boolean
2895
+ ),
2896
+ onSelect: ({ editor: editor2 }) => {
2897
+ const attrs = {
2898
+ name: variable.name,
2899
+ fallback: variable.fallback,
2900
+ category: variable.category
2901
+ };
2902
+ editor2.chain().focus().insertVariable(attrs).run();
2903
+ }
2904
+ });
2905
+ }
2906
+ if (normalizedQuery && !variables.some((v) => v.name.toLowerCase() === normalizedQuery)) {
2907
+ items.push({
2908
+ title: `Neue Variable "${query}"`,
2909
+ subtext: query,
2910
+ group: "Neu",
2911
+ onSelect: ({ editor: editor2 }) => {
2912
+ const attrs = {
2913
+ name: query
2914
+ };
2915
+ editor2.chain().focus().insertVariable(attrs).run();
2916
+ }
2917
+ });
2918
+ }
2919
+ return items;
2920
+ },
2921
+ [variables]
2922
+ );
2923
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2924
+ SuggestionMenu,
2925
+ {
2926
+ editor,
2927
+ pluginKey: VariableSuggestionPluginKey,
2928
+ char: "{{",
2929
+ items: getItems,
2930
+ allowSpaces: false,
2931
+ selector: "tiptap-variable-suggestion-menu",
2932
+ children: (props) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(VariableList, { ...props })
2933
+ }
2934
+ );
2935
+ }
2936
+ var VariableItem = ({
2937
+ item,
2938
+ isSelected,
2939
+ onSelect
2940
+ }) => {
2941
+ const itemRef = React6.useRef(null);
2942
+ React6.useEffect(() => {
2943
+ const selector = document.querySelector(
2944
+ '[data-selector="tiptap-variable-suggestion-menu"]'
2945
+ );
2946
+ if (!itemRef.current || !isSelected || !selector) return;
2947
+ const overflow = (0, import_editor_utils.getElementOverflowPosition)(itemRef.current, selector);
2948
+ if (overflow === "top") {
2949
+ itemRef.current.scrollIntoView(true);
2950
+ } else if (overflow === "bottom") {
2951
+ itemRef.current.scrollIntoView(false);
2952
+ }
2953
+ }, [isSelected]);
2954
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2955
+ "button",
2956
+ {
2957
+ ref: itemRef,
2958
+ type: "button",
2959
+ "data-active-state": isSelected ? "on" : "off",
2960
+ onClick: onSelect,
2961
+ 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",
2962
+ children: [
2963
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "font-medium truncate", children: item.title }),
2964
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("code", { className: "text-xs text-muted-foreground font-mono shrink-0", children: item.subtext })
2965
+ ]
2966
+ }
2967
+ );
2968
+ };
2969
+ var VariableList = ({
2970
+ items,
2971
+ selectedIndex,
2972
+ onSelect
2973
+ }) => {
2974
+ const styles = (0, import_theme6.slashDropdownMenu)();
2975
+ const renderedItems = React6.useMemo(() => {
2976
+ const rendered = [];
2977
+ const groups = {};
2978
+ items.forEach((item, index) => {
2979
+ const groupLabel = item.group || "";
2980
+ if (!groups[groupLabel]) {
2981
+ groups[groupLabel] = { items: [], indices: [] };
2982
+ }
2983
+ groups[groupLabel].items.push(item);
2984
+ groups[groupLabel].indices.push(index);
2985
+ });
2986
+ Object.entries(groups).forEach(([groupLabel, groupData], groupIndex) => {
2987
+ const groupItems = groupData.items.map((item, itemIndex) => {
2988
+ const originalIndex = groupData.indices[itemIndex];
2989
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2990
+ VariableItem,
2991
+ {
2992
+ item,
2993
+ isSelected: originalIndex === selectedIndex,
2994
+ onSelect: () => onSelect(item)
2995
+ },
2996
+ `item-${originalIndex}-${item.title}`
2997
+ );
2998
+ });
2999
+ if (groupLabel) {
3000
+ rendered.push(
3001
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "py-1", children: [
3002
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "px-2 py-1 text-xs font-semibold text-muted-foreground uppercase tracking-wide", children: groupLabel }),
3003
+ groupItems
3004
+ ] }, `group-${groupIndex}-${groupLabel}`)
3005
+ );
3006
+ } else {
3007
+ rendered.push(...groupItems);
3008
+ }
3009
+ });
3010
+ return rendered;
3011
+ }, [items, selectedIndex, onSelect]);
3012
+ if (!renderedItems.length) {
3013
+ return null;
3014
+ }
3015
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3016
+ "div",
3017
+ {
3018
+ className: styles.card(),
3019
+ style: {
3020
+ maxHeight: "var(--suggestion-menu-max-height)",
3021
+ minWidth: "240px"
3022
+ },
3023
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: styles.body(), children: renderedItems })
3024
+ }
3025
+ );
3026
+ };
3027
+
3028
+ // src/hooks/use-create-editor.ts
3029
+ var import_extension_code = require("@kopexa/extension-code");
3030
+ var import_extension_controlref = require("@kopexa/extension-controlref");
3031
+ var import_extension_table = require("@kopexa/extension-table");
3032
+ var import_extension_file_handler = require("@tiptap/extension-file-handler");
3033
+ var import_extension_highlight = require("@tiptap/extension-highlight");
3034
+ var import_extension_invisible_characters = __toESM(require("@tiptap/extension-invisible-characters"));
3035
+ var import_extension_list = require("@tiptap/extension-list");
3036
+ var import_extension_subscript = require("@tiptap/extension-subscript");
3037
+ var import_extension_superscript = require("@tiptap/extension-superscript");
3038
+ var import_extension_table_of_contents = require("@tiptap/extension-table-of-contents");
3039
+ var import_extension_text_align = require("@tiptap/extension-text-align");
3040
+ var import_extension_text_style = require("@tiptap/extension-text-style");
3041
+ var import_extension_typography = require("@tiptap/extension-typography");
3042
+ var import_extension_unique_id = require("@tiptap/extension-unique-id");
3043
+ var import_extensions = require("@tiptap/extensions");
3044
+ var import_react31 = require("@tiptap/react");
3045
+ var import_starter_kit = require("@tiptap/starter-kit");
3046
+ var import_react32 = require("react");
3047
+
3048
+ // src/extensions/link/index.ts
3049
+ var import_extension_link = __toESM(require("@tiptap/extension-link"));
3050
+ var import_state3 = require("@tiptap/pm/state");
3051
+ var import_react28 = require("@tiptap/react");
3052
+ var Link = import_extension_link.default.extend({
3053
+ inclusive: false,
3054
+ parseHTML() {
3055
+ return [
3056
+ {
3057
+ tag: 'a[href]:not([data-type="button"]):not([href *= "javascript:" i])'
3058
+ }
3059
+ ];
3060
+ },
3061
+ addProseMirrorPlugins() {
3062
+ var _a;
3063
+ const { editor } = this;
3064
+ return [
3065
+ ...((_a = this.parent) == null ? void 0 : _a.call(this)) || [],
3066
+ new import_state3.Plugin({
3067
+ key: new import_state3.PluginKey("linkKeyHandler"),
3068
+ props: {
3069
+ handleKeyDown: (_, event) => {
3070
+ const { selection } = editor.state;
3071
+ if (event.key === "Escape" && selection.empty !== true) {
3072
+ editor.commands.focus(selection.to, { scrollIntoView: false });
3073
+ }
3074
+ return false;
3075
+ },
3076
+ handleClick(view, pos) {
3077
+ const { schema, doc, tr } = view.state;
3078
+ let range;
3079
+ if (schema.marks.link) {
3080
+ range = (0, import_react28.getMarkRange)(doc.resolve(pos), schema.marks.link);
3081
+ }
3082
+ if (!range) {
3083
+ return;
3084
+ }
3085
+ const { from, to } = range;
3086
+ const start = Math.min(from, to);
3087
+ const end = Math.max(from, to);
3088
+ if (pos < start || pos > end) {
3089
+ return;
3090
+ }
3091
+ const $start = doc.resolve(start);
3092
+ const $end = doc.resolve(end);
3093
+ const transaction = tr.setSelection(
3094
+ new import_state3.TextSelection($start, $end)
3095
+ );
3096
+ view.dispatch(transaction);
3097
+ }
3098
+ }
3099
+ })
3100
+ ];
3101
+ }
3102
+ });
3103
+
3104
+ // src/extensions/selection/index.ts
3105
+ var import_state4 = require("@tiptap/pm/state");
3106
+ var import_view = require("@tiptap/pm/view");
3107
+ var import_react29 = require("@tiptap/react");
3108
+ var Selection = import_react29.Extension.create({
3109
+ name: "selection",
3110
+ addProseMirrorPlugins() {
3111
+ const { editor } = this;
3112
+ return [
3113
+ new import_state4.Plugin({
3114
+ key: new import_state4.PluginKey("selection"),
3115
+ props: {
3116
+ decorations(state) {
3117
+ if (state.selection.empty) {
3118
+ return null;
3119
+ }
3120
+ if (editor.isFocused === true || !editor.isEditable) {
3121
+ return null;
3122
+ }
3123
+ if ((0, import_react29.isNodeSelection)(state.selection)) {
3124
+ return null;
3125
+ }
3126
+ return import_view.DecorationSet.create(state.doc, [
3127
+ import_view.Decoration.inline(state.selection.from, state.selection.to, {
3128
+ class: "selection"
3129
+ })
3130
+ ]);
3131
+ }
3132
+ }
3133
+ })
3134
+ ];
3135
+ }
3136
+ });
3137
+
3138
+ // src/extensions/trailing-node/index.ts
3139
+ var import_state5 = require("@tiptap/pm/state");
3140
+ var import_react30 = require("@tiptap/react");
3141
+ function nodeEqualsType({
3142
+ types,
3143
+ node
3144
+ }) {
3145
+ if (!node) return false;
3146
+ if (Array.isArray(types)) {
3147
+ return types.includes(node.type);
3148
+ }
3149
+ return node.type === types;
3150
+ }
3151
+ var TrailingNode = import_react30.Extension.create({
3152
+ name: "trailingNode",
3153
+ addOptions() {
3154
+ return {
3155
+ node: "paragraph",
3156
+ notAfter: ["paragraph"]
3157
+ };
3158
+ },
3159
+ addProseMirrorPlugins() {
3160
+ const plugin = new import_state5.PluginKey(this.name);
3161
+ const disabledNodes = Object.entries(this.editor.schema.nodes).map(([, value]) => value).filter((node) => this.options.notAfter.includes(node.name));
3162
+ return [
3163
+ new import_state5.Plugin({
3164
+ key: plugin,
3165
+ appendTransaction: (_, __, state) => {
3166
+ const { doc, tr, schema } = state;
3167
+ const shouldInsertNodeAtEnd = plugin.getState(state);
3168
+ const endPosition = doc.content.size;
3169
+ const type = schema.nodes[this.options.node];
3170
+ if (!shouldInsertNodeAtEnd) {
3171
+ return null;
3172
+ }
3173
+ if (type) {
3174
+ return tr.insert(endPosition, type.create());
3175
+ }
3176
+ return null;
3177
+ },
3178
+ state: {
3179
+ init: (_, state) => {
3180
+ const lastNode = state.tr.doc.lastChild;
3181
+ return !nodeEqualsType({ node: lastNode, types: disabledNodes });
3182
+ },
3183
+ apply: (tr, value) => {
3184
+ if (!tr.docChanged) {
3185
+ return value;
3186
+ }
3187
+ const lastNode = tr.doc.lastChild;
3188
+ return !nodeEqualsType({ node: lastNode, types: disabledNodes });
3189
+ }
3190
+ }
3191
+ })
3192
+ ];
3193
+ }
3194
+ });
3195
+
3196
+ // src/extensions/ui-state/index.ts
3197
+ var import_core7 = require("@tiptap/core");
3198
+ var defaultUiState = {
3199
+ aiGenerationIsSelection: false,
3200
+ aiGenerationIsLoading: false,
3201
+ aiGenerationActive: false,
3202
+ aiGenerationHasMessage: false,
3203
+ commentInputVisible: false,
2223
3204
  lockDragHandle: false,
2224
3205
  isDragging: false
2225
3206
  };
2226
- var UiState = import_core6.Extension.create({
3207
+ var UiState = import_core7.Extension.create({
2227
3208
  name: "uiState",
2228
3209
  addStorage() {
2229
3210
  return {
@@ -2439,20 +3420,22 @@ var useCreateEditor = ({
2439
3420
  enableControls = false,
2440
3421
  controlResolver,
2441
3422
  fileHandler: fileHandlerProp,
3423
+ enableVariables = false,
2442
3424
  ...options
2443
3425
  }) => {
2444
3426
  const fileHandlerFromContext = useEditorFile();
2445
3427
  const fileHandler = fileHandlerProp != null ? fileHandlerProp : fileHandlerFromContext;
2446
- const [extensions] = (0, import_react26.useState)(
3428
+ const [extensions] = (0, import_react32.useState)(
2447
3429
  () => getExtensions({
2448
3430
  editable,
2449
3431
  placeholder,
2450
3432
  enableControls,
2451
3433
  controlResolver,
2452
- fileHandler
3434
+ fileHandler,
3435
+ enableVariables
2453
3436
  })
2454
3437
  );
2455
- const editor = (0, import_react25.useEditor)({
3438
+ const editor = (0, import_react31.useEditor)({
2456
3439
  editorProps: {
2457
3440
  attributes: {
2458
3441
  autocomplete: "off",
@@ -2471,7 +3454,7 @@ var useCreateEditor = ({
2471
3454
  content: safeParseContent(content),
2472
3455
  ...options
2473
3456
  });
2474
- (0, import_react26.useEffect)(() => {
3457
+ (0, import_react32.useEffect)(() => {
2475
3458
  if (editor && editor.isEditable !== editable) {
2476
3459
  editor.setEditable(editable);
2477
3460
  }
@@ -2483,7 +3466,8 @@ function getExtensions({
2483
3466
  placeholder,
2484
3467
  enableControls = false,
2485
3468
  controlResolver,
2486
- fileHandler
3469
+ fileHandler,
3470
+ enableVariables = false
2487
3471
  }) {
2488
3472
  const extensions = [
2489
3473
  import_starter_kit.StarterKit.configure({
@@ -2549,6 +3533,9 @@ function getExtensions({
2549
3533
  if (enableControls) {
2550
3534
  extensions.push(import_extension_controlref.ControlKit.configure({ resolver: controlResolver }));
2551
3535
  }
3536
+ if (enableVariables) {
3537
+ extensions.push(VariableNode);
3538
+ }
2552
3539
  if (fileHandler) {
2553
3540
  extensions.push(
2554
3541
  import_extension_file_handler.FileHandler.configure({
@@ -2633,19 +3620,19 @@ async function handleFileUpload(editor, file, fileHandler, pos) {
2633
3620
  }
2634
3621
 
2635
3622
  // src/presets/basic/index.tsx
2636
- var import_theme7 = require("@kopexa/theme");
2637
- var import_react54 = require("@tiptap/react");
2638
- var import_react55 = require("react");
3623
+ var import_theme9 = require("@kopexa/theme");
3624
+ var import_react56 = require("@tiptap/react");
3625
+ var import_react57 = require("react");
2639
3626
 
2640
3627
  // src/context/editor-context.ts
2641
3628
  var import_react_utils = require("@kopexa/react-utils");
2642
3629
  var [EditorUIProvider, useEditorUIContext] = (0, import_react_utils.createContext)();
2643
3630
 
2644
3631
  // src/hooks/use-ui-editor-state.ts
2645
- var import_react27 = require("@tiptap/react");
3632
+ var import_react33 = require("@tiptap/react");
2646
3633
  function useUiEditorState(editor) {
2647
3634
  var _a;
2648
- return (_a = (0, import_react27.useEditorState)({
3635
+ return (_a = (0, import_react33.useEditorState)({
2649
3636
  editor,
2650
3637
  selector: ({ editor: editor2 }) => {
2651
3638
  if (!editor2) return defaultUiState;
@@ -2665,47 +3652,18 @@ function useUiEditorState(editor) {
2665
3652
  var import_toolbar3 = require("@kopexa/toolbar");
2666
3653
  var import_menus = require("@tiptap/react/menus");
2667
3654
 
2668
- // src/ui/link-popover/link-popover.tsx
2669
- var import_button7 = require("@kopexa/button");
2670
- var import_icons9 = require("@kopexa/icons");
2671
- var import_input2 = require("@kopexa/input");
2672
- var import_popover = require("@kopexa/popover");
2673
- var import_toolbar = require("@kopexa/toolbar");
2674
- var import_react30 = require("react");
2675
-
2676
- // src/hooks/use-tiptap-editor.ts
2677
- var import_react28 = require("@tiptap/react");
2678
- var import_react29 = require("react");
2679
- function useTiptapEditor(providedEditor) {
2680
- const { editor: coreEditor } = (0, import_react28.useCurrentEditor)();
2681
- const mainEditor = (0, import_react29.useMemo)(
2682
- () => providedEditor || coreEditor,
2683
- [providedEditor, coreEditor]
2684
- );
2685
- const editorState = (0, import_react28.useEditorState)({
2686
- editor: mainEditor,
2687
- selector(context) {
2688
- if (!context.editor) {
2689
- return {
2690
- editor: null,
2691
- editorState: void 0,
2692
- canCommand: void 0
2693
- };
2694
- }
2695
- return {
2696
- editor: context.editor,
2697
- editorState: context.editor.state,
2698
- canCommand: context.editor.can
2699
- };
2700
- }
2701
- });
2702
- return editorState || { editor: null };
2703
- }
3655
+ // src/ui/link-popover/link-popover.tsx
3656
+ var import_button8 = require("@kopexa/button");
3657
+ var import_icons9 = require("@kopexa/icons");
3658
+ var import_input3 = require("@kopexa/input");
3659
+ var import_popover = require("@kopexa/popover");
3660
+ var import_toolbar = require("@kopexa/toolbar");
3661
+ var import_react34 = require("react");
2704
3662
 
2705
3663
  // src/ui/link-popover/use-link-popover.ts
2706
- var import_editor_utils = require("@kopexa/editor-utils");
3664
+ var import_editor_utils2 = require("@kopexa/editor-utils");
2707
3665
  var import_icons8 = require("@kopexa/icons");
2708
- var React = __toESM(require("react"));
3666
+ var React7 = __toESM(require("react"));
2709
3667
 
2710
3668
  // src/utils/index.ts
2711
3669
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
@@ -2810,7 +3768,7 @@ function isLinkActive(editor) {
2810
3768
  }
2811
3769
  function shouldShowLinkButton(props) {
2812
3770
  const { editor, hideWhenUnavailable } = props;
2813
- const linkInSchema = (0, import_editor_utils.isMarkInSchema)("link", editor);
3771
+ const linkInSchema = (0, import_editor_utils2.isMarkInSchema)("link", editor);
2814
3772
  if (!linkInSchema || !editor) {
2815
3773
  return false;
2816
3774
  }
@@ -2821,15 +3779,15 @@ function shouldShowLinkButton(props) {
2821
3779
  }
2822
3780
  function useLinkHandler(props) {
2823
3781
  const { editor, onSetLink } = props;
2824
- const [url, setUrl] = React.useState(null);
2825
- React.useEffect(() => {
3782
+ const [url, setUrl] = React7.useState(null);
3783
+ React7.useEffect(() => {
2826
3784
  if (!editor) return;
2827
3785
  const { href } = editor.getAttributes("link");
2828
3786
  if (isLinkActive(editor) && url === null) {
2829
3787
  setUrl(href || "");
2830
3788
  }
2831
3789
  }, [editor, url]);
2832
- React.useEffect(() => {
3790
+ React7.useEffect(() => {
2833
3791
  if (!editor) return;
2834
3792
  const updateLinkState = () => {
2835
3793
  const { href } = editor.getAttributes("link");
@@ -2840,7 +3798,7 @@ function useLinkHandler(props) {
2840
3798
  editor.off("selectionUpdate", updateLinkState);
2841
3799
  };
2842
3800
  }, [editor]);
2843
- const setLink = React.useCallback(() => {
3801
+ const setLink = React7.useCallback(() => {
2844
3802
  if (!url || !editor) return;
2845
3803
  const { selection } = editor.state;
2846
3804
  const isEmpty = selection.empty;
@@ -2853,12 +3811,12 @@ function useLinkHandler(props) {
2853
3811
  setUrl(null);
2854
3812
  onSetLink == null ? void 0 : onSetLink();
2855
3813
  }, [editor, onSetLink, url]);
2856
- const removeLink = React.useCallback(() => {
3814
+ const removeLink = React7.useCallback(() => {
2857
3815
  if (!editor) return;
2858
3816
  editor.chain().focus().extendMarkRange("link").unsetLink().setMeta("preventAutolink", true).run();
2859
3817
  setUrl("");
2860
3818
  }, [editor]);
2861
- const openLink = React.useCallback(
3819
+ const openLink = React7.useCallback(
2862
3820
  (target = "_blank", features = "noopener,noreferrer") => {
2863
3821
  if (!url) return;
2864
3822
  const safeUrl = sanitizeUrl(url, window.location.href);
@@ -2880,8 +3838,8 @@ function useLinkState(props) {
2880
3838
  const { editor, hideWhenUnavailable = false } = props;
2881
3839
  const canSet = canSetLink(editor);
2882
3840
  const isActive = isLinkActive(editor);
2883
- const [isVisible, setIsVisible] = React.useState(false);
2884
- React.useEffect(() => {
3841
+ const [isVisible, setIsVisible] = React7.useState(false);
3842
+ React7.useEffect(() => {
2885
3843
  if (!editor) return;
2886
3844
  const handleSelectionUpdate = () => {
2887
3845
  setIsVisible(
@@ -2929,9 +3887,9 @@ function useLinkPopover(config) {
2929
3887
  }
2930
3888
 
2931
3889
  // src/ui/link-popover/link-popover.tsx
2932
- var import_jsx_runtime10 = require("react/jsx-runtime");
3890
+ var import_jsx_runtime15 = require("react/jsx-runtime");
2933
3891
  var LinkButton = ({ className, children, ...props }) => {
2934
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3892
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2935
3893
  import_toolbar.ToolbarButton,
2936
3894
  {
2937
3895
  type: "button",
@@ -2943,7 +3901,7 @@ var LinkButton = ({ className, children, ...props }) => {
2943
3901
  title: "Link",
2944
3902
  isIconOnly: !children,
2945
3903
  ...props,
2946
- children: children || /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_icons9.LinkIcon, {})
3904
+ children: children || /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_icons9.LinkIcon, {})
2947
3905
  }
2948
3906
  );
2949
3907
  };
@@ -2956,8 +3914,8 @@ var LinkMain = ({
2956
3914
  isActive,
2957
3915
  onSave
2958
3916
  }) => {
2959
- const [isEditing, setIsEditing] = (0, import_react30.useState)(!isActive || !url);
2960
- (0, import_react30.useEffect)(() => {
3917
+ const [isEditing, setIsEditing] = (0, import_react34.useState)(!isActive || !url);
3918
+ (0, import_react34.useEffect)(() => {
2961
3919
  setIsEditing(!isActive || !url);
2962
3920
  }, [isActive, url]);
2963
3921
  const handleKeyDown = (event) => {
@@ -2980,9 +3938,9 @@ var LinkMain = ({
2980
3938
  setIsEditing(true);
2981
3939
  };
2982
3940
  if (isEditing) {
2983
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-1 min-w-[280px]", children: [
2984
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2985
- import_input2.Input,
3941
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center gap-1 min-w-[280px]", children: [
3942
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3943
+ import_input3.Input,
2986
3944
  {
2987
3945
  type: "url",
2988
3946
  placeholder: "Enter URL...",
@@ -2996,8 +3954,8 @@ var LinkMain = ({
2996
3954
  autoFocus: true
2997
3955
  }
2998
3956
  ),
2999
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3000
- import_button7.IconButton,
3957
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3958
+ import_button8.IconButton,
3001
3959
  {
3002
3960
  type: "button",
3003
3961
  size: "sm",
@@ -3005,13 +3963,13 @@ var LinkMain = ({
3005
3963
  onClick: handleSave,
3006
3964
  "aria-label": "Save link",
3007
3965
  disabled: !url,
3008
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_icons9.CheckIcon, { className: "size-4" })
3966
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_icons9.CheckIcon, { className: "size-4" })
3009
3967
  }
3010
3968
  )
3011
3969
  ] });
3012
3970
  }
3013
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-1 min-w-[280px]", children: [
3014
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3971
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center gap-1 min-w-[280px]", children: [
3972
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3015
3973
  "a",
3016
3974
  {
3017
3975
  href: url,
@@ -3025,38 +3983,38 @@ var LinkMain = ({
3025
3983
  children: url
3026
3984
  }
3027
3985
  ),
3028
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-0.5 border-l pl-1 ml-1", children: [
3029
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3030
- import_button7.IconButton,
3986
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center gap-0.5 border-l pl-1 ml-1", children: [
3987
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3988
+ import_button8.IconButton,
3031
3989
  {
3032
3990
  type: "button",
3033
3991
  size: "sm",
3034
3992
  variant: "ghost",
3035
3993
  onClick: openLink,
3036
3994
  "aria-label": "Open link in new tab",
3037
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_icons9.ExternalLinkIcon, { className: "size-4" })
3995
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_icons9.ExternalLinkIcon, { className: "size-4" })
3038
3996
  }
3039
3997
  ),
3040
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3041
- import_button7.IconButton,
3998
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3999
+ import_button8.IconButton,
3042
4000
  {
3043
4001
  type: "button",
3044
4002
  size: "sm",
3045
4003
  variant: "ghost",
3046
4004
  onClick: handleEdit,
3047
4005
  "aria-label": "Edit link",
3048
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_icons9.EditIcon, { className: "size-4" })
4006
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_icons9.EditIcon, { className: "size-4" })
3049
4007
  }
3050
4008
  ),
3051
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3052
- import_button7.IconButton,
4009
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4010
+ import_button8.IconButton,
3053
4011
  {
3054
4012
  type: "button",
3055
4013
  size: "sm",
3056
4014
  variant: "ghost",
3057
4015
  onClick: removeLink,
3058
4016
  "aria-label": "Remove link",
3059
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_icons9.TrashIcon, { className: "size-4" })
4017
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_icons9.TrashIcon, { className: "size-4" })
3060
4018
  }
3061
4019
  )
3062
4020
  ] })
@@ -3073,7 +4031,7 @@ function LinkPopover({
3073
4031
  ...buttonProps
3074
4032
  }) {
3075
4033
  const { editor } = useTiptapEditor(providedEditor);
3076
- const [isOpen, setIsOpen] = (0, import_react30.useState)(false);
4034
+ const [isOpen, setIsOpen] = (0, import_react34.useState)(false);
3077
4035
  const {
3078
4036
  isVisible,
3079
4037
  canSet,
@@ -3089,18 +4047,18 @@ function LinkPopover({
3089
4047
  hideWhenUnavailable,
3090
4048
  onSetLink
3091
4049
  });
3092
- const handleOnOpenChange = (0, import_react30.useCallback)(
4050
+ const handleOnOpenChange = (0, import_react34.useCallback)(
3093
4051
  (nextIsOpen) => {
3094
4052
  setIsOpen(nextIsOpen);
3095
4053
  onOpenChange == null ? void 0 : onOpenChange(nextIsOpen);
3096
4054
  },
3097
4055
  [onOpenChange]
3098
4056
  );
3099
- const handleSetLink = (0, import_react30.useCallback)(() => {
4057
+ const handleSetLink = (0, import_react34.useCallback)(() => {
3100
4058
  setLink();
3101
4059
  setIsOpen(false);
3102
4060
  }, [setLink]);
3103
- const handleClick = (0, import_react30.useCallback)(
4061
+ const handleClick = (0, import_react34.useCallback)(
3104
4062
  (event) => {
3105
4063
  onClick == null ? void 0 : onClick(event);
3106
4064
  if (event.defaultPrevented) return;
@@ -3108,7 +4066,7 @@ function LinkPopover({
3108
4066
  },
3109
4067
  [onClick, isOpen]
3110
4068
  );
3111
- (0, import_react30.useEffect)(() => {
4069
+ (0, import_react34.useEffect)(() => {
3112
4070
  if (autoOpenOnLinkActive && isActive) {
3113
4071
  setIsOpen(true);
3114
4072
  }
@@ -3116,17 +4074,17 @@ function LinkPopover({
3116
4074
  if (!isVisible) {
3117
4075
  return null;
3118
4076
  }
3119
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
4077
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
3120
4078
  import_popover.Popover.Root,
3121
4079
  {
3122
4080
  open: isOpen,
3123
4081
  onOpenChange: handleOnOpenChange,
3124
4082
  spacing: "dense",
3125
4083
  children: [
3126
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4084
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3127
4085
  import_popover.Popover.Trigger,
3128
4086
  {
3129
- render: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4087
+ render: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3130
4088
  LinkButton,
3131
4089
  {
3132
4090
  "data-disabled": !canSet,
@@ -3140,7 +4098,7 @@ function LinkPopover({
3140
4098
  )
3141
4099
  }
3142
4100
  ),
3143
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_popover.Popover.Content, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4101
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_popover.Popover.Content, { children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3144
4102
  LinkMain,
3145
4103
  {
3146
4104
  url,
@@ -3159,12 +4117,12 @@ function LinkPopover({
3159
4117
  LinkButton.displayName = "LinkButton";
3160
4118
 
3161
4119
  // src/ui/mark-button/index.tsx
3162
- var import_editor_utils2 = require("@kopexa/editor-utils");
4120
+ var import_editor_utils3 = require("@kopexa/editor-utils");
3163
4121
  var import_icons10 = require("@kopexa/icons");
3164
4122
  var import_toolbar2 = require("@kopexa/toolbar");
3165
- var import_react31 = require("@tiptap/react");
3166
- var import_react32 = require("react");
3167
- var import_jsx_runtime11 = require("react/jsx-runtime");
4123
+ var import_react35 = require("@tiptap/react");
4124
+ var import_react36 = require("react");
4125
+ var import_jsx_runtime16 = require("react/jsx-runtime");
3168
4126
  var markIcons = {
3169
4127
  bold: import_icons10.BoldIcon,
3170
4128
  italic: import_icons10.ItalicIcon,
@@ -3185,7 +4143,7 @@ var markShortcutKeys = {
3185
4143
  };
3186
4144
  function canToggleMark(editor, type) {
3187
4145
  if (!editor || !editor.isEditable) return false;
3188
- if (!(0, import_editor_utils2.isMarkInSchema)(type, editor) || (0, import_editor_utils2.isNodeTypeSelected)(editor, ["image"]))
4146
+ if (!(0, import_editor_utils3.isMarkInSchema)(type, editor) || (0, import_editor_utils3.isNodeTypeSelected)(editor, ["image"]))
3189
4147
  return false;
3190
4148
  return editor.can().toggleMark(type);
3191
4149
  }
@@ -3210,7 +4168,7 @@ function shouldShowMarkButton(params) {
3210
4168
  return false;
3211
4169
  }
3212
4170
  if (hideWhenUnavailable) {
3213
- if ((0, import_react31.isNodeSelection)(editor.state.selection) || !canToggleMark(editor, type)) {
4171
+ if ((0, import_react35.isNodeSelection)(editor.state.selection) || !canToggleMark(editor, type)) {
3214
4172
  return false;
3215
4173
  }
3216
4174
  }
@@ -3220,7 +4178,7 @@ function getFormattedMarkName(type) {
3220
4178
  return type.charAt(0).toUpperCase() + type.slice(1);
3221
4179
  }
3222
4180
  function useMarkState(editor, type, disabled = false) {
3223
- const markInSchema = (0, import_editor_utils2.isMarkInSchema)(type, editor);
4181
+ const markInSchema = (0, import_editor_utils3.isMarkInSchema)(type, editor);
3224
4182
  const isDisabled = isMarkButtonDisabled(editor, type, disabled);
3225
4183
  const isActive = isMarkActive(editor, type);
3226
4184
  const Icon = markIcons[type];
@@ -3255,7 +4213,7 @@ var MarkButton = ({
3255
4213
  shortcutKey,
3256
4214
  formattedName
3257
4215
  } = useMarkState(editor, type, disabled);
3258
- const handleClick = (0, import_react32.useCallback)(
4216
+ const handleClick = (0, import_react36.useCallback)(
3259
4217
  (e) => {
3260
4218
  onClick == null ? void 0 : onClick(e);
3261
4219
  if (!e.defaultPrevented && !isDisabled && editor) {
@@ -3264,7 +4222,7 @@ var MarkButton = ({
3264
4222
  },
3265
4223
  [onClick, isDisabled, editor, type]
3266
4224
  );
3267
- const show = (0, import_react32.useMemo)(() => {
4225
+ const show = (0, import_react36.useMemo)(() => {
3268
4226
  return shouldShowMarkButton({
3269
4227
  editor,
3270
4228
  type,
@@ -3275,7 +4233,7 @@ var MarkButton = ({
3275
4233
  if (!show || !editor || !editor.isEditable) {
3276
4234
  return null;
3277
4235
  }
3278
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4236
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3279
4237
  import_toolbar2.ToolbarButton,
3280
4238
  {
3281
4239
  type: "button",
@@ -3293,739 +4251,326 @@ var MarkButton = ({
3293
4251
  onClick: handleClick,
3294
4252
  isIconOnly: true,
3295
4253
  ...buttonProps,
3296
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Icon, {})
4254
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Icon, {})
3297
4255
  }
3298
4256
  );
3299
4257
  };
3300
4258
 
3301
4259
  // src/ui/bubble-menu/index.tsx
3302
- var import_jsx_runtime12 = require("react/jsx-runtime");
4260
+ var import_jsx_runtime17 = require("react/jsx-runtime");
3303
4261
  function BubbleMenu({ editor }) {
3304
4262
  if (!editor) {
3305
4263
  return null;
3306
4264
  }
3307
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4265
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3308
4266
  import_menus.BubbleMenu,
3309
4267
  {
3310
4268
  editor,
3311
- shouldShow: ({ editor: e, state }) => {
4269
+ shouldShow: ({ editor: e, state, view }) => {
3312
4270
  const { selection } = state;
3313
4271
  const { empty } = selection;
4272
+ if (!view.hasFocus()) return false;
3314
4273
  if (empty) return false;
3315
4274
  if (e.isActive("codeBlock")) return false;
3316
4275
  if (e.isActive("link")) return false;
4276
+ if (e.isActive("variable")) return false;
3317
4277
  if (!e.isEditable) return false;
3318
4278
  return true;
3319
4279
  },
3320
- options: {
3321
- placement: "top",
3322
- offset: 8
3323
- },
3324
- className: "rounded-lg border bg-background shadow-md",
3325
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_toolbar3.Toolbar, { radius: "md", border: "none", className: "p-1", children: [
3326
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_toolbar3.ToolbarGroup, { children: [
3327
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(MarkButton, { type: "bold" }),
3328
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(MarkButton, { type: "italic" }),
3329
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(MarkButton, { type: "strike" }),
3330
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(MarkButton, { type: "code" })
3331
- ] }),
3332
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_toolbar3.ToolbarSeparator, {}),
3333
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_toolbar3.ToolbarGroup, { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(LinkPopover, { autoOpenOnLinkActive: false }) })
3334
- ] })
3335
- }
3336
- );
3337
- }
3338
-
3339
- // src/ui/copy-anchor-link-button/use-scroll-to-hash.ts
3340
- var import_editor_utils3 = require("@kopexa/editor-utils");
3341
- var React3 = __toESM(require("react"));
3342
-
3343
- // src/hooks/use-floating-toolbar-visibility.ts
3344
- var import_state4 = require("@tiptap/pm/state");
3345
- var import_react33 = require("@tiptap/react");
3346
- var React2 = __toESM(require("react"));
3347
- var HIDE_FLOATING_META = "hideFloatingToolbar";
3348
- var selectNodeAndHideFloating = (editor, pos) => {
3349
- if (!editor) return;
3350
- const { state, view } = editor;
3351
- view.dispatch(
3352
- state.tr.setSelection(import_state4.NodeSelection.create(state.doc, pos)).setMeta(HIDE_FLOATING_META, true)
3353
- );
3354
- };
3355
-
3356
- // src/ui/copy-anchor-link-button/use-scroll-to-hash.ts
3357
- function useScrollToHash(config = {}) {
3358
- const {
3359
- editor: providedEditor,
3360
- onTargetFound = () => {
3361
- },
3362
- onTargetNotFound = () => {
3363
- }
3364
- } = config;
3365
- const { editor } = useTiptapEditor(providedEditor);
3366
- const scrollToNode = React3.useCallback(
3367
- (id) => {
3368
- var _a, _b, _c;
3369
- if (!editor) return false;
3370
- const attributeName = (_c = (_b = (_a = (0, import_editor_utils3.getEditorExtension)(editor, "uniqueID")) == null ? void 0 : _a.options) == null ? void 0 : _b.attributeName) != null ? _c : "data-id";
3371
- let position = null;
3372
- editor.state.doc.descendants((node, pos) => {
3373
- var _a2;
3374
- if (((_a2 = node.attrs) == null ? void 0 : _a2[attributeName]) === id) {
3375
- position = pos;
3376
- return false;
3377
- }
3378
- return true;
3379
- });
3380
- if (position === null) return false;
3381
- selectNodeAndHideFloating(editor, position);
3382
- setTimeout(() => {
3383
- let dom = null;
3384
- if (typeof position === "number") {
3385
- dom = editor.view.nodeDOM(position);
3386
- }
3387
- if (dom) {
3388
- dom.scrollIntoView({ behavior: "smooth", block: "center" });
3389
- }
3390
- }, 0);
3391
- return true;
3392
- },
3393
- [editor]
3394
- );
3395
- const handleScroll = React3.useCallback(
3396
- (delay = 0) => {
3397
- var _a;
3398
- const hash = (_a = window.location.hash) == null ? void 0 : _a.substring(1);
3399
- if (!hash) return;
3400
- setTimeout(() => {
3401
- if (scrollToNode(hash)) {
3402
- onTargetFound(hash);
3403
- } else {
3404
- onTargetNotFound(hash);
3405
- }
3406
- }, delay);
3407
- },
3408
- [scrollToNode, onTargetFound, onTargetNotFound]
3409
- );
3410
- React3.useEffect(() => {
3411
- var _a, _b;
3412
- if (!editor) return;
3413
- const provider = (_b = (_a = editor.extensionManager.extensions.find(
3414
- (ext) => ext.name === "collaborationCaret"
3415
- )) == null ? void 0 : _a.options) == null ? void 0 : _b.provider;
3416
- if (provider == null ? void 0 : provider.on) {
3417
- const syncHandler = () => handleScroll(500);
3418
- provider.on("synced", syncHandler);
3419
- return () => {
3420
- var _a2;
3421
- (_a2 = provider.off) == null ? void 0 : _a2.call(provider, "synced", syncHandler);
3422
- };
3423
- } else {
3424
- handleScroll(500);
3425
- }
3426
- }, [editor, handleScroll]);
3427
- React3.useEffect(() => {
3428
- const immediateScroll = () => handleScroll();
3429
- const delayedScroll = () => handleScroll(500);
3430
- window.addEventListener("hashchange", immediateScroll);
3431
- window.addEventListener("pageshow", delayedScroll);
3432
- window.addEventListener("popstate", immediateScroll);
3433
- return () => {
3434
- window.removeEventListener("hashchange", immediateScroll);
3435
- window.removeEventListener("pageshow", delayedScroll);
3436
- window.removeEventListener("popstate", immediateScroll);
3437
- };
3438
- }, [handleScroll]);
3439
- return { scrollToHash: scrollToNode };
3440
- }
3441
-
3442
- // src/ui/link-bubble/index.tsx
3443
- var import_button8 = require("@kopexa/button");
3444
- var import_icons11 = require("@kopexa/icons");
3445
- var import_input3 = require("@kopexa/input");
3446
- var import_menus2 = require("@tiptap/react/menus");
3447
- var import_react34 = require("react");
3448
- var import_jsx_runtime13 = require("react/jsx-runtime");
3449
- function LinkBubble({ editor }) {
3450
- const [isEditing, setIsEditing] = (0, import_react34.useState)(false);
3451
- const [url, setUrl] = (0, import_react34.useState)("");
3452
- const getCurrentUrl = (0, import_react34.useCallback)(() => {
3453
- if (!editor) return "";
3454
- const attrs = editor.getAttributes("link");
3455
- return attrs.href || "";
3456
- }, [editor]);
3457
- (0, import_react34.useEffect)(() => {
3458
- const isLinkActive2 = editor == null ? void 0 : editor.isActive("link");
3459
- if (isLinkActive2) {
3460
- setUrl(getCurrentUrl());
3461
- setIsEditing(false);
3462
- }
3463
- }, [editor, getCurrentUrl]);
3464
- const handleOpenLink = (0, import_react34.useCallback)(() => {
3465
- const href = getCurrentUrl();
3466
- if (href) {
3467
- window.open(href, "_blank", "noopener,noreferrer");
3468
- }
3469
- }, [getCurrentUrl]);
3470
- const handleRemoveLink = (0, import_react34.useCallback)(() => {
3471
- editor == null ? void 0 : editor.chain().focus().unsetLink().run();
3472
- }, [editor]);
3473
- const handleEdit = (0, import_react34.useCallback)(() => {
3474
- setUrl(getCurrentUrl());
3475
- setIsEditing(true);
3476
- }, [getCurrentUrl]);
3477
- const handleSave = (0, import_react34.useCallback)(() => {
3478
- if (url) {
3479
- editor == null ? void 0 : editor.chain().focus().extendMarkRange("link").setLink({ href: url }).run();
3480
- } else {
3481
- editor == null ? void 0 : editor.chain().focus().unsetLink().run();
3482
- }
3483
- setIsEditing(false);
3484
- }, [editor, url]);
3485
- const handleKeyDown = (0, import_react34.useCallback)(
3486
- (e) => {
3487
- if (e.key === "Enter") {
3488
- e.preventDefault();
3489
- handleSave();
3490
- } else if (e.key === "Escape") {
3491
- e.preventDefault();
3492
- setIsEditing(false);
3493
- setUrl(getCurrentUrl());
3494
- }
3495
- },
3496
- [handleSave, getCurrentUrl]
3497
- );
3498
- if (!editor) {
3499
- return null;
3500
- }
3501
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3502
- import_menus2.BubbleMenu,
3503
- {
3504
- editor,
3505
- pluginKey: "linkBubbleMenu",
3506
- shouldShow: ({ editor: e }) => {
3507
- return e.isActive("link") && e.isEditable;
3508
- },
3509
- options: {
3510
- placement: "bottom-start",
3511
- offset: 8
3512
- },
3513
- className: "rounded-lg border bg-background shadow-md",
3514
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "flex items-center gap-1 p-1.5 min-w-[280px]", children: isEditing ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
3515
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3516
- import_input3.Input,
3517
- {
3518
- type: "url",
3519
- value: url,
3520
- onChange: (e) => setUrl(e.target.value),
3521
- onKeyDown: handleKeyDown,
3522
- placeholder: "Enter URL...",
3523
- className: "flex-1 h-8 text-sm",
3524
- autoFocus: true
3525
- }
3526
- ),
3527
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3528
- import_button8.IconButton,
3529
- {
3530
- type: "button",
3531
- size: "sm",
3532
- variant: "ghost",
3533
- onClick: handleSave,
3534
- "aria-label": "Save link",
3535
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons11.EditIcon, { className: "size-4" })
3536
- }
3537
- )
3538
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
3539
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3540
- "a",
3541
- {
3542
- href: getCurrentUrl(),
3543
- target: "_blank",
3544
- rel: "noopener noreferrer",
3545
- className: "flex-1 text-sm text-primary truncate max-w-[200px] hover:underline px-2",
3546
- onClick: (e) => {
3547
- e.preventDefault();
3548
- handleOpenLink();
3549
- },
3550
- children: getCurrentUrl()
3551
- }
3552
- ),
3553
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-0.5 border-l pl-1 ml-1", children: [
3554
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3555
- import_button8.IconButton,
3556
- {
3557
- type: "button",
3558
- size: "sm",
3559
- variant: "ghost",
3560
- onClick: handleOpenLink,
3561
- "aria-label": "Open link in new tab",
3562
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons11.ExternalLinkIcon, { className: "size-4" })
3563
- }
3564
- ),
3565
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3566
- import_button8.IconButton,
3567
- {
3568
- type: "button",
3569
- size: "sm",
3570
- variant: "ghost",
3571
- onClick: handleEdit,
3572
- "aria-label": "Edit link",
3573
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons11.EditIcon, { className: "size-4" })
3574
- }
3575
- ),
3576
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3577
- import_button8.IconButton,
3578
- {
3579
- type: "button",
3580
- size: "sm",
3581
- variant: "ghost",
3582
- onClick: handleRemoveLink,
3583
- "aria-label": "Remove link",
3584
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons11.TrashIcon, { className: "size-4" })
3585
- }
3586
- )
3587
- ] })
3588
- ] }) })
4280
+ options: {
4281
+ placement: "top",
4282
+ offset: 8
4283
+ },
4284
+ className: "rounded-lg border bg-background shadow-md",
4285
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_toolbar3.Toolbar, { radius: "md", border: "none", className: "p-1", children: [
4286
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_toolbar3.ToolbarGroup, { children: [
4287
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(MarkButton, { type: "bold" }),
4288
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(MarkButton, { type: "italic" }),
4289
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(MarkButton, { type: "strike" }),
4290
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(MarkButton, { type: "code" })
4291
+ ] }),
4292
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_toolbar3.ToolbarSeparator, {}),
4293
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_toolbar3.ToolbarGroup, { children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(LinkPopover, { autoOpenOnLinkActive: false }) })
4294
+ ] })
3589
4295
  }
3590
4296
  );
3591
4297
  }
3592
4298
 
3593
- // src/ui/slash-dropdown-menu/slash-dropdown-menu.tsx
3594
- var import_button9 = require("@kopexa/button");
3595
- var import_editor_utils6 = require("@kopexa/editor-utils");
3596
- var import_separator = require("@kopexa/separator");
3597
- var import_theme5 = require("@kopexa/theme");
3598
- var React8 = __toESM(require("react"));
3599
-
3600
- // src/ui/suggestion-menu/suggestion-menu.tsx
3601
- var import_react36 = require("@floating-ui/react");
3602
- var import_state5 = require("@tiptap/pm/state");
3603
- var import_suggestion = require("@tiptap/suggestion");
3604
- var React6 = __toESM(require("react"));
4299
+ // src/ui/copy-anchor-link-button/use-scroll-to-hash.ts
4300
+ var import_editor_utils4 = require("@kopexa/editor-utils");
4301
+ var React9 = __toESM(require("react"));
3605
4302
 
3606
- // src/hooks/use-floating-element.ts
3607
- var import_react35 = require("@floating-ui/react");
3608
- var React4 = __toESM(require("react"));
3609
- function useFloatingElement(show, referencePos, zIndex, options) {
3610
- const { dismissOptions, ...floatingOptions } = options || {};
3611
- const { refs, update, context, floatingStyles } = (0, import_react35.useFloating)({
3612
- open: show,
3613
- ...floatingOptions
3614
- });
3615
- const { isMounted, styles } = (0, import_react35.useTransitionStyles)(context);
3616
- const dismiss = (0, import_react35.useDismiss)(context, dismissOptions);
3617
- const { getReferenceProps, getFloatingProps } = (0, import_react35.useInteractions)([dismiss]);
3618
- React4.useEffect(() => {
3619
- update();
3620
- }, [referencePos, update]);
3621
- React4.useEffect(() => {
3622
- if (referencePos === null) {
3623
- return;
3624
- }
3625
- refs.setReference({
3626
- getBoundingClientRect: () => referencePos
3627
- });
3628
- }, [referencePos, refs]);
3629
- return React4.useMemo(
3630
- () => ({
3631
- isMounted,
3632
- ref: refs.setFloating,
3633
- style: {
3634
- ...styles,
3635
- ...floatingStyles,
3636
- zIndex
3637
- },
3638
- update,
3639
- getFloatingProps,
3640
- getReferenceProps
3641
- }),
3642
- [
3643
- floatingStyles,
3644
- isMounted,
3645
- refs.setFloating,
3646
- styles,
3647
- update,
3648
- zIndex,
3649
- getFloatingProps,
3650
- getReferenceProps
3651
- ]
4303
+ // src/hooks/use-floating-toolbar-visibility.ts
4304
+ var import_state6 = require("@tiptap/pm/state");
4305
+ var import_react37 = require("@tiptap/react");
4306
+ var React8 = __toESM(require("react"));
4307
+ var HIDE_FLOATING_META = "hideFloatingToolbar";
4308
+ var selectNodeAndHideFloating = (editor, pos) => {
4309
+ if (!editor) return;
4310
+ const { state, view } = editor;
4311
+ view.dispatch(
4312
+ state.tr.setSelection(import_state6.NodeSelection.create(state.doc, pos)).setMeta(HIDE_FLOATING_META, true)
3652
4313
  );
3653
- }
4314
+ };
3654
4315
 
3655
- // src/hooks/use-menu-navigation.ts
3656
- var React5 = __toESM(require("react"));
3657
- function useMenuNavigation({
3658
- editor,
3659
- containerRef,
3660
- query,
3661
- items,
3662
- onSelect,
3663
- onClose,
3664
- orientation = "vertical",
3665
- autoSelectFirstItem = true
3666
- }) {
3667
- const [selectedIndex, setSelectedIndex] = React5.useState(
3668
- autoSelectFirstItem ? 0 : -1
3669
- );
3670
- React5.useEffect(() => {
3671
- const handleKeyboardNavigation = (event) => {
3672
- if (!items.length) return false;
3673
- const moveNext = () => setSelectedIndex((currentIndex) => {
3674
- if (currentIndex === -1) return 0;
3675
- return (currentIndex + 1) % items.length;
3676
- });
3677
- const movePrev = () => setSelectedIndex((currentIndex) => {
3678
- if (currentIndex === -1) return items.length - 1;
3679
- return (currentIndex - 1 + items.length) % items.length;
3680
- });
3681
- switch (event.key) {
3682
- case "ArrowUp": {
3683
- if (orientation === "horizontal") return false;
3684
- event.preventDefault();
3685
- movePrev();
3686
- return true;
3687
- }
3688
- case "ArrowDown": {
3689
- if (orientation === "horizontal") return false;
3690
- event.preventDefault();
3691
- moveNext();
3692
- return true;
3693
- }
3694
- case "ArrowLeft": {
3695
- if (orientation === "vertical") return false;
3696
- event.preventDefault();
3697
- movePrev();
3698
- return true;
3699
- }
3700
- case "ArrowRight": {
3701
- if (orientation === "vertical") return false;
3702
- event.preventDefault();
3703
- moveNext();
3704
- return true;
3705
- }
3706
- case "Tab": {
3707
- event.preventDefault();
3708
- if (event.shiftKey) {
3709
- movePrev();
3710
- } else {
3711
- moveNext();
3712
- }
3713
- return true;
3714
- }
3715
- case "Home": {
3716
- event.preventDefault();
3717
- setSelectedIndex(0);
3718
- return true;
4316
+ // src/ui/copy-anchor-link-button/use-scroll-to-hash.ts
4317
+ function useScrollToHash(config = {}) {
4318
+ const {
4319
+ editor: providedEditor,
4320
+ onTargetFound = () => {
4321
+ },
4322
+ onTargetNotFound = () => {
4323
+ }
4324
+ } = config;
4325
+ const { editor } = useTiptapEditor(providedEditor);
4326
+ const scrollToNode = React9.useCallback(
4327
+ (id) => {
4328
+ var _a, _b, _c;
4329
+ if (!editor) return false;
4330
+ const attributeName = (_c = (_b = (_a = (0, import_editor_utils4.getEditorExtension)(editor, "uniqueID")) == null ? void 0 : _a.options) == null ? void 0 : _b.attributeName) != null ? _c : "data-id";
4331
+ let position = null;
4332
+ editor.state.doc.descendants((node, pos) => {
4333
+ var _a2;
4334
+ if (((_a2 = node.attrs) == null ? void 0 : _a2[attributeName]) === id) {
4335
+ position = pos;
4336
+ return false;
3719
4337
  }
3720
- case "End": {
3721
- event.preventDefault();
3722
- setSelectedIndex(items.length - 1);
3723
- return true;
4338
+ return true;
4339
+ });
4340
+ if (position === null) return false;
4341
+ selectNodeAndHideFloating(editor, position);
4342
+ setTimeout(() => {
4343
+ let dom = null;
4344
+ if (typeof position === "number") {
4345
+ dom = editor.view.nodeDOM(position);
3724
4346
  }
3725
- case "Enter": {
3726
- if (event.isComposing) return false;
3727
- event.preventDefault();
3728
- if (selectedIndex !== -1 && items[selectedIndex]) {
3729
- onSelect == null ? void 0 : onSelect(items[selectedIndex]);
3730
- }
3731
- return true;
4347
+ if (dom) {
4348
+ dom.scrollIntoView({ behavior: "smooth", block: "center" });
3732
4349
  }
3733
- case "Escape": {
3734
- event.preventDefault();
3735
- onClose == null ? void 0 : onClose();
3736
- return true;
4350
+ }, 0);
4351
+ return true;
4352
+ },
4353
+ [editor]
4354
+ );
4355
+ const handleScroll = React9.useCallback(
4356
+ (delay = 0) => {
4357
+ var _a;
4358
+ const hash = (_a = window.location.hash) == null ? void 0 : _a.substring(1);
4359
+ if (!hash) return;
4360
+ setTimeout(() => {
4361
+ if (scrollToNode(hash)) {
4362
+ onTargetFound(hash);
4363
+ } else {
4364
+ onTargetNotFound(hash);
3737
4365
  }
3738
- default:
3739
- return false;
3740
- }
3741
- };
3742
- let targetElement = null;
3743
- if (editor) {
3744
- targetElement = editor.view.dom;
3745
- } else if (containerRef == null ? void 0 : containerRef.current) {
3746
- targetElement = containerRef.current;
3747
- }
3748
- if (targetElement) {
3749
- targetElement.addEventListener("keydown", handleKeyboardNavigation, true);
3750
- return () => {
3751
- targetElement == null ? void 0 : targetElement.removeEventListener(
3752
- "keydown",
3753
- handleKeyboardNavigation,
3754
- true
3755
- );
3756
- };
3757
- }
3758
- return void 0;
3759
- }, [
3760
- editor,
3761
- containerRef,
3762
- items,
3763
- selectedIndex,
3764
- onSelect,
3765
- onClose,
3766
- orientation
3767
- ]);
3768
- React5.useEffect(() => {
3769
- if (query) {
3770
- setSelectedIndex(autoSelectFirstItem ? 0 : -1);
3771
- }
3772
- }, [query, autoSelectFirstItem]);
3773
- return {
3774
- selectedIndex: items.length ? selectedIndex : void 0,
3775
- setSelectedIndex
3776
- };
3777
- }
3778
-
3779
- // src/ui/suggestion-menu/suggestion-menu-utils.ts
3780
- function calculateStartPosition(cursorPosition, previousNode, triggerChar) {
3781
- if (!(previousNode == null ? void 0 : previousNode.text) || !triggerChar) {
3782
- return cursorPosition;
3783
- }
3784
- const commandText = previousNode.text;
3785
- const triggerCharIndex = commandText.lastIndexOf(triggerChar);
3786
- if (triggerCharIndex === -1) {
3787
- return cursorPosition;
3788
- }
3789
- const textLength = commandText.substring(triggerCharIndex).length;
3790
- return cursorPosition - textLength;
3791
- }
3792
- function filterSuggestionItems(items, query) {
3793
- const normalizedQuery = query.trim().toLowerCase();
3794
- if (!normalizedQuery) {
3795
- return items;
3796
- }
3797
- return items.filter((item) => {
4366
+ }, delay);
4367
+ },
4368
+ [scrollToNode, onTargetFound, onTargetNotFound]
4369
+ );
4370
+ React9.useEffect(() => {
3798
4371
  var _a, _b;
3799
- if (item.title.toLowerCase().includes(normalizedQuery)) {
3800
- return true;
3801
- }
3802
- if ((_a = item.subtext) == null ? void 0 : _a.toLowerCase().includes(normalizedQuery)) {
3803
- return true;
3804
- }
3805
- if ((_b = item.keywords) == null ? void 0 : _b.some(
3806
- (keyword) => keyword.toLowerCase().includes(normalizedQuery)
3807
- )) {
3808
- return true;
4372
+ if (!editor) return;
4373
+ const provider = (_b = (_a = editor.extensionManager.extensions.find(
4374
+ (ext) => ext.name === "collaborationCaret"
4375
+ )) == null ? void 0 : _a.options) == null ? void 0 : _b.provider;
4376
+ if (provider == null ? void 0 : provider.on) {
4377
+ const syncHandler = () => handleScroll(500);
4378
+ provider.on("synced", syncHandler);
4379
+ return () => {
4380
+ var _a2;
4381
+ (_a2 = provider.off) == null ? void 0 : _a2.call(provider, "synced", syncHandler);
4382
+ };
4383
+ } else {
4384
+ handleScroll(500);
3809
4385
  }
3810
- return false;
3811
- }).sort((a, b) => {
3812
- const aTitle = a.title.toLowerCase();
3813
- const bTitle = b.title.toLowerCase();
3814
- if (aTitle === normalizedQuery && bTitle !== normalizedQuery) return -1;
3815
- if (bTitle === normalizedQuery && aTitle !== normalizedQuery) return 1;
3816
- if (aTitle.startsWith(normalizedQuery) && !bTitle.startsWith(normalizedQuery))
3817
- return -1;
3818
- if (bTitle.startsWith(normalizedQuery) && !aTitle.startsWith(normalizedQuery))
3819
- return 1;
3820
- return 0;
3821
- });
4386
+ }, [editor, handleScroll]);
4387
+ React9.useEffect(() => {
4388
+ const immediateScroll = () => handleScroll();
4389
+ const delayedScroll = () => handleScroll(500);
4390
+ window.addEventListener("hashchange", immediateScroll);
4391
+ window.addEventListener("pageshow", delayedScroll);
4392
+ window.addEventListener("popstate", immediateScroll);
4393
+ return () => {
4394
+ window.removeEventListener("hashchange", immediateScroll);
4395
+ window.removeEventListener("pageshow", delayedScroll);
4396
+ window.removeEventListener("popstate", immediateScroll);
4397
+ };
4398
+ }, [handleScroll]);
4399
+ return { scrollToHash: scrollToNode };
3822
4400
  }
3823
4401
 
3824
- // src/ui/suggestion-menu/suggestion-menu.tsx
3825
- var import_jsx_runtime14 = require("react/jsx-runtime");
3826
- var SuggestionMenu = ({
3827
- editor: providedEditor,
3828
- floatingOptions,
3829
- selector = "tiptap-suggestion-menu",
3830
- children,
3831
- maxHeight = 384,
3832
- pluginKey = import_suggestion.SuggestionPluginKey,
3833
- ...internalSuggestionProps
3834
- }) => {
3835
- const { editor } = useTiptapEditor(providedEditor);
3836
- const [show, setShow] = React6.useState(false);
3837
- const [internalClientRect, setInternalClientRect] = React6.useState(null);
3838
- const [internalCommand, setInternalCommand] = React6.useState(null);
3839
- const [internalItems, setInternalItems] = React6.useState(
3840
- []
3841
- );
3842
- const [internalQuery, setInternalQuery] = React6.useState("");
3843
- const [, setInternalRange] = React6.useState(null);
3844
- const { ref, style, getFloatingProps, isMounted } = useFloatingElement(
3845
- show,
3846
- internalClientRect,
3847
- 1e3,
3848
- {
3849
- placement: "bottom-start",
3850
- middleware: [
3851
- (0, import_react36.offset)(10),
3852
- (0, import_react36.flip)({
3853
- mainAxis: true,
3854
- crossAxis: false
3855
- }),
3856
- (0, import_react36.shift)(),
3857
- (0, import_react36.size)({
3858
- apply({ availableHeight, elements }) {
3859
- if (elements.floating) {
3860
- const maxHeightValue = maxHeight ? Math.min(maxHeight, availableHeight) : availableHeight;
3861
- elements.floating.style.setProperty(
3862
- "--suggestion-menu-max-height",
3863
- `${maxHeightValue}px`
3864
- );
3865
- }
3866
- }
3867
- })
3868
- ],
3869
- onOpenChange(open) {
3870
- if (!open) {
3871
- setShow(false);
3872
- }
3873
- },
3874
- ...floatingOptions
4402
+ // src/ui/link-bubble/index.tsx
4403
+ var import_button9 = require("@kopexa/button");
4404
+ var import_icons11 = require("@kopexa/icons");
4405
+ var import_input4 = require("@kopexa/input");
4406
+ var import_menus2 = require("@tiptap/react/menus");
4407
+ var import_react38 = require("react");
4408
+ var import_jsx_runtime18 = require("react/jsx-runtime");
4409
+ function LinkBubble({ editor }) {
4410
+ const [isEditing, setIsEditing] = (0, import_react38.useState)(false);
4411
+ const [url, setUrl] = (0, import_react38.useState)("");
4412
+ const getCurrentUrl = (0, import_react38.useCallback)(() => {
4413
+ if (!editor) return "";
4414
+ const attrs = editor.getAttributes("link");
4415
+ return attrs.href || "";
4416
+ }, [editor]);
4417
+ (0, import_react38.useEffect)(() => {
4418
+ const isLinkActive2 = editor == null ? void 0 : editor.isActive("link");
4419
+ if (isLinkActive2) {
4420
+ setUrl(getCurrentUrl());
4421
+ setIsEditing(false);
3875
4422
  }
3876
- );
3877
- const internalSuggestionPropsRef = React6.useRef(internalSuggestionProps);
3878
- React6.useEffect(() => {
3879
- internalSuggestionPropsRef.current = internalSuggestionProps;
3880
- }, [internalSuggestionProps]);
3881
- const closePopup = React6.useCallback(() => {
3882
- setShow(false);
3883
- }, []);
3884
- React6.useEffect(() => {
3885
- if (!editor || editor.isDestroyed) {
3886
- return;
4423
+ }, [editor, getCurrentUrl]);
4424
+ const handleOpenLink = (0, import_react38.useCallback)(() => {
4425
+ const href = getCurrentUrl();
4426
+ if (href) {
4427
+ window.open(href, "_blank", "noopener,noreferrer");
3887
4428
  }
3888
- const existingPlugin = editor.state.plugins.find(
3889
- (plugin) => plugin.spec.key === pluginKey
3890
- );
3891
- if (existingPlugin) {
3892
- editor.unregisterPlugin(pluginKey);
4429
+ }, [getCurrentUrl]);
4430
+ const handleRemoveLink = (0, import_react38.useCallback)(() => {
4431
+ editor == null ? void 0 : editor.chain().focus().unsetLink().run();
4432
+ }, [editor]);
4433
+ const handleEdit = (0, import_react38.useCallback)(() => {
4434
+ setUrl(getCurrentUrl());
4435
+ setIsEditing(true);
4436
+ }, [getCurrentUrl]);
4437
+ const handleSave = (0, import_react38.useCallback)(() => {
4438
+ if (url) {
4439
+ editor == null ? void 0 : editor.chain().focus().extendMarkRange("link").setLink({ href: url }).run();
4440
+ } else {
4441
+ editor == null ? void 0 : editor.chain().focus().unsetLink().run();
3893
4442
  }
3894
- const suggestion = (0, import_suggestion.Suggestion)({
3895
- pluginKey: pluginKey instanceof import_state5.PluginKey ? pluginKey : new import_state5.PluginKey(pluginKey),
4443
+ setIsEditing(false);
4444
+ }, [editor, url]);
4445
+ const handleKeyDown = (0, import_react38.useCallback)(
4446
+ (e) => {
4447
+ if (e.key === "Enter") {
4448
+ e.preventDefault();
4449
+ handleSave();
4450
+ } else if (e.key === "Escape") {
4451
+ e.preventDefault();
4452
+ setIsEditing(false);
4453
+ setUrl(getCurrentUrl());
4454
+ }
4455
+ },
4456
+ [handleSave, getCurrentUrl]
4457
+ );
4458
+ if (!editor) {
4459
+ return null;
4460
+ }
4461
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4462
+ import_menus2.BubbleMenu,
4463
+ {
3896
4464
  editor,
3897
- command({ editor: editor2, range, props }) {
3898
- var _a, _b;
3899
- if (!range) {
3900
- return;
3901
- }
3902
- const { view, state } = editor2;
3903
- const { selection } = state;
3904
- const isMention = editor2.extensionManager.extensions.some(
3905
- (extension) => {
3906
- var _a2, _b2;
3907
- const name = extension.name;
3908
- return name === "mention" && ((_b2 = (_a2 = extension.options) == null ? void 0 : _a2.suggestion) == null ? void 0 : _b2.char) === internalSuggestionPropsRef.current.char;
3909
- }
3910
- );
3911
- if (!isMention) {
3912
- const cursorPosition = selection.$from.pos;
3913
- const previousNode = (_a = selection.$head) == null ? void 0 : _a.nodeBefore;
3914
- const startPosition = previousNode ? calculateStartPosition(
3915
- cursorPosition,
3916
- previousNode,
3917
- internalSuggestionPropsRef.current.char
3918
- ) : selection.$from.start();
3919
- const transaction = state.tr.deleteRange(
3920
- startPosition,
3921
- cursorPosition
3922
- );
3923
- view.dispatch(transaction);
3924
- }
3925
- const nodeAfter = view.state.selection.$to.nodeAfter;
3926
- const overrideSpace = (_b = nodeAfter == null ? void 0 : nodeAfter.text) == null ? void 0 : _b.startsWith(" ");
3927
- const rangeToUse = { ...range };
3928
- if (overrideSpace) {
3929
- rangeToUse.to += 1;
3930
- }
3931
- props.onSelect({ editor: editor2, range: rangeToUse, context: props.context });
4465
+ pluginKey: "linkBubbleMenu",
4466
+ shouldShow: ({ editor: e, view }) => {
4467
+ if (!view.hasFocus()) return false;
4468
+ return e.isActive("link") && e.isEditable;
3932
4469
  },
3933
- render: () => {
3934
- return {
3935
- onStart: (props) => {
3936
- var _a, _b;
3937
- setInternalCommand(() => props.command);
3938
- setInternalItems(props.items);
3939
- setInternalQuery(props.query);
3940
- setInternalRange(props.range);
3941
- setInternalClientRect((_b = (_a = props.clientRect) == null ? void 0 : _a.call(props)) != null ? _b : null);
3942
- setShow(true);
3943
- },
3944
- onUpdate: (props) => {
3945
- var _a, _b;
3946
- setInternalCommand(() => props.command);
3947
- setInternalItems(props.items);
3948
- setInternalQuery(props.query);
3949
- setInternalRange(props.range);
3950
- setInternalClientRect((_b = (_a = props.clientRect) == null ? void 0 : _a.call(props)) != null ? _b : null);
3951
- },
3952
- onKeyDown: (props) => {
3953
- if (props.event.key === "Escape") {
3954
- closePopup();
3955
- return true;
3956
- }
3957
- return false;
3958
- },
3959
- onExit: () => {
3960
- setInternalCommand(null);
3961
- setInternalItems([]);
3962
- setInternalQuery("");
3963
- setInternalRange(null);
3964
- setInternalClientRect(null);
3965
- setShow(false);
4470
+ options: {
4471
+ placement: "bottom-start",
4472
+ offset: 8
4473
+ },
4474
+ className: "rounded-lg border bg-background shadow-md",
4475
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex items-center gap-1 p-1.5 min-w-[280px]", children: isEditing ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
4476
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4477
+ import_input4.Input,
4478
+ {
4479
+ type: "url",
4480
+ value: url,
4481
+ onChange: (e) => setUrl(e.target.value),
4482
+ onKeyDown: handleKeyDown,
4483
+ placeholder: "Enter URL...",
4484
+ className: "flex-1 h-8 text-sm",
4485
+ autoFocus: true
4486
+ }
4487
+ ),
4488
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4489
+ import_button9.IconButton,
4490
+ {
4491
+ type: "button",
4492
+ size: "sm",
4493
+ variant: "ghost",
4494
+ onClick: handleSave,
4495
+ "aria-label": "Save link",
4496
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_icons11.EditIcon, { className: "size-4" })
4497
+ }
4498
+ )
4499
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
4500
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4501
+ "a",
4502
+ {
4503
+ href: getCurrentUrl(),
4504
+ target: "_blank",
4505
+ rel: "noopener noreferrer",
4506
+ className: "flex-1 text-sm text-primary truncate max-w-[200px] hover:underline px-2",
4507
+ onClick: (e) => {
4508
+ e.preventDefault();
4509
+ handleOpenLink();
4510
+ },
4511
+ children: getCurrentUrl()
3966
4512
  }
3967
- };
3968
- },
3969
- ...internalSuggestionPropsRef.current
3970
- });
3971
- editor.registerPlugin(suggestion);
3972
- return () => {
3973
- if (!editor.isDestroyed) {
3974
- editor.unregisterPlugin(pluginKey);
3975
- }
3976
- };
3977
- }, [editor, pluginKey, closePopup]);
3978
- const onSelect = React6.useCallback(
3979
- (item) => {
3980
- closePopup();
3981
- if (internalCommand) {
3982
- internalCommand(item);
3983
- }
3984
- },
3985
- [closePopup, internalCommand]
3986
- );
3987
- const { selectedIndex } = useMenuNavigation({
3988
- editor,
3989
- query: internalQuery,
3990
- items: internalItems,
3991
- onSelect
3992
- });
3993
- if (!isMounted || !show || !editor) {
3994
- return null;
3995
- }
3996
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react36.FloatingPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3997
- "div",
3998
- {
3999
- ref,
4000
- style,
4001
- ...getFloatingProps(),
4002
- "data-selector": selector,
4003
- className: "tiptap-suggestion-menu",
4004
- role: "listbox",
4005
- "aria-label": "Suggestions",
4006
- onPointerDown: (e) => e.preventDefault(),
4007
- children: children({
4008
- items: internalItems,
4009
- selectedIndex,
4010
- onSelect
4011
- })
4513
+ ),
4514
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-0.5 border-l pl-1 ml-1", children: [
4515
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4516
+ import_button9.IconButton,
4517
+ {
4518
+ type: "button",
4519
+ size: "sm",
4520
+ variant: "ghost",
4521
+ onClick: handleOpenLink,
4522
+ "aria-label": "Open link in new tab",
4523
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_icons11.ExternalLinkIcon, { className: "size-4" })
4524
+ }
4525
+ ),
4526
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4527
+ import_button9.IconButton,
4528
+ {
4529
+ type: "button",
4530
+ size: "sm",
4531
+ variant: "ghost",
4532
+ onClick: handleEdit,
4533
+ "aria-label": "Edit link",
4534
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_icons11.EditIcon, { className: "size-4" })
4535
+ }
4536
+ ),
4537
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4538
+ import_button9.IconButton,
4539
+ {
4540
+ type: "button",
4541
+ size: "sm",
4542
+ variant: "ghost",
4543
+ onClick: handleRemoveLink,
4544
+ "aria-label": "Remove link",
4545
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_icons11.TrashIcon, { className: "size-4" })
4546
+ }
4547
+ )
4548
+ ] })
4549
+ ] }) })
4012
4550
  }
4013
- ) });
4014
- };
4551
+ );
4552
+ }
4553
+
4554
+ // src/ui/slash-dropdown-menu/slash-dropdown-menu.tsx
4555
+ var import_button10 = require("@kopexa/button");
4556
+ var import_editor_utils7 = require("@kopexa/editor-utils");
4557
+ var import_separator = require("@kopexa/separator");
4558
+ var import_theme7 = require("@kopexa/theme");
4559
+ var React11 = __toESM(require("react"));
4015
4560
 
4016
4561
  // src/ui/slash-dropdown-menu/use-slash-dropdown-menu.ts
4017
- var import_editor_utils5 = require("@kopexa/editor-utils");
4562
+ var import_editor_utils6 = require("@kopexa/editor-utils");
4018
4563
  var import_icons13 = require("@kopexa/icons");
4019
- var React7 = __toESM(require("react"));
4564
+ var React10 = __toESM(require("react"));
4020
4565
 
4021
4566
  // src/ui/table-button/use-table.ts
4022
- var import_editor_utils4 = require("@kopexa/editor-utils");
4567
+ var import_editor_utils5 = require("@kopexa/editor-utils");
4023
4568
  var import_icons12 = require("@kopexa/icons");
4024
- var import_react37 = require("@tiptap/react");
4025
- var import_react38 = require("react");
4569
+ var import_react39 = require("@tiptap/react");
4570
+ var import_react40 = require("react");
4026
4571
  function canToggle(editor) {
4027
4572
  if (!editor || !editor.isEditable) return false;
4028
- if (!(0, import_editor_utils4.isNodeInSchema)("table", editor) || (0, import_editor_utils4.isNodeTypeSelected)(editor, ["image"])) {
4573
+ if (!(0, import_editor_utils5.isNodeInSchema)("table", editor) || (0, import_editor_utils5.isNodeTypeSelected)(editor, ["image"])) {
4029
4574
  return false;
4030
4575
  }
4031
4576
  try {
@@ -4051,9 +4596,9 @@ function toggleTable(editor, config) {
4051
4596
  function shouldShowButton(props) {
4052
4597
  const { editor, hideWhenUnavailable } = props;
4053
4598
  if (!editor || !editor.isEditable) return false;
4054
- if (!(0, import_editor_utils4.isNodeInSchema)("table", editor)) return false;
4599
+ if (!(0, import_editor_utils5.isNodeInSchema)("table", editor)) return false;
4055
4600
  if (hideWhenUnavailable) {
4056
- if ((0, import_react37.isNodeSelection)(editor.state.selection) || !canToggle) {
4601
+ if ((0, import_react39.isNodeSelection)(editor.state.selection) || !canToggle) {
4057
4602
  return false;
4058
4603
  }
4059
4604
  }
@@ -4066,10 +4611,10 @@ function useTableBlock(config) {
4066
4611
  onToggled
4067
4612
  } = config || {};
4068
4613
  const { editor } = useTiptapEditor(providedEditor);
4069
- const [isVisible, setIsVisible] = (0, import_react38.useState)(true);
4614
+ const [isVisible, setIsVisible] = (0, import_react40.useState)(true);
4070
4615
  const canToggleState = canToggle(editor);
4071
4616
  const isActive = (editor == null ? void 0 : editor.isActive("table")) || false;
4072
- (0, import_react38.useEffect)(() => {
4617
+ (0, import_react40.useEffect)(() => {
4073
4618
  if (!editor) return;
4074
4619
  const handleSelectionUpdate = () => {
4075
4620
  setIsVisible(shouldShowButton({ editor, hideWhenUnavailable }));
@@ -4080,7 +4625,7 @@ function useTableBlock(config) {
4080
4625
  editor.off("selectionUpdate", handleSelectionUpdate);
4081
4626
  };
4082
4627
  }, [editor, hideWhenUnavailable]);
4083
- const handleToggle = (0, import_react38.useCallback)(() => {
4628
+ const handleToggle = (0, import_react40.useCallback)(() => {
4084
4629
  if (!editor) return false;
4085
4630
  const success = toggleTable(editor);
4086
4631
  if (success) {
@@ -4266,8 +4811,8 @@ var getItemImplementations = () => {
4266
4811
  // AI
4267
4812
  continue_writing: {
4268
4813
  check: (editor) => {
4269
- const { hasContent } = (0, import_editor_utils5.hasContentAbove)(editor);
4270
- const extensionsReady = (0, import_editor_utils5.isExtensionAvailable)(editor, [
4814
+ const { hasContent } = (0, import_editor_utils6.hasContentAbove)(editor);
4815
+ const extensionsReady = (0, import_editor_utils6.isExtensionAvailable)(editor, [
4271
4816
  "ai",
4272
4817
  "aiAdvanced"
4273
4818
  ]);
@@ -4275,14 +4820,14 @@ var getItemImplementations = () => {
4275
4820
  },
4276
4821
  action: ({ editor }) => {
4277
4822
  const editorChain = editor.chain().focus();
4278
- const nodeSelectionPosition = (0, import_editor_utils5.findSelectionPosition)({ editor });
4823
+ const nodeSelectionPosition = (0, import_editor_utils6.findSelectionPosition)({ editor });
4279
4824
  if (nodeSelectionPosition !== null) {
4280
4825
  editorChain.setNodeSelection(nodeSelectionPosition);
4281
4826
  }
4282
4827
  editorChain.run();
4283
4828
  editor.chain().focus().aiGenerationShow().run();
4284
4829
  requestAnimationFrame(() => {
4285
- const { hasContent, content } = (0, import_editor_utils5.hasContentAbove)(editor);
4830
+ const { hasContent, content } = (0, import_editor_utils6.hasContentAbove)(editor);
4286
4831
  const snippet = content.length > 500 ? `...${content.slice(-500)}` : content;
4287
4832
  const prompt = hasContent ? `Context: ${snippet}
4288
4833
 
@@ -4296,10 +4841,10 @@ Continue writing from where the text above ends. Write ONLY ONE SENTENCE. DONT R
4296
4841
  }
4297
4842
  },
4298
4843
  ai_ask_button: {
4299
- check: (editor) => (0, import_editor_utils5.isExtensionAvailable)(editor, ["ai", "aiAdvanced"]),
4844
+ check: (editor) => (0, import_editor_utils6.isExtensionAvailable)(editor, ["ai", "aiAdvanced"]),
4300
4845
  action: ({ editor }) => {
4301
4846
  const editorChain = editor.chain().focus();
4302
- const nodeSelectionPosition = (0, import_editor_utils5.findSelectionPosition)({ editor });
4847
+ const nodeSelectionPosition = (0, import_editor_utils6.findSelectionPosition)({ editor });
4303
4848
  if (nodeSelectionPosition !== null) {
4304
4849
  editorChain.setNodeSelection(nodeSelectionPosition);
4305
4850
  }
@@ -4309,55 +4854,55 @@ Continue writing from where the text above ends. Write ONLY ONE SENTENCE. DONT R
4309
4854
  },
4310
4855
  // Style
4311
4856
  text: {
4312
- check: (editor) => (0, import_editor_utils5.isNodeInSchema)("paragraph", editor),
4857
+ check: (editor) => (0, import_editor_utils6.isNodeInSchema)("paragraph", editor),
4313
4858
  action: ({ editor }) => {
4314
4859
  editor.chain().focus().setParagraph().run();
4315
4860
  }
4316
4861
  },
4317
4862
  heading_1: {
4318
- check: (editor) => (0, import_editor_utils5.isNodeInSchema)("heading", editor),
4863
+ check: (editor) => (0, import_editor_utils6.isNodeInSchema)("heading", editor),
4319
4864
  action: ({ editor }) => {
4320
4865
  editor.chain().focus().toggleHeading({ level: 1 }).run();
4321
4866
  }
4322
4867
  },
4323
4868
  heading_2: {
4324
- check: (editor) => (0, import_editor_utils5.isNodeInSchema)("heading", editor),
4869
+ check: (editor) => (0, import_editor_utils6.isNodeInSchema)("heading", editor),
4325
4870
  action: ({ editor }) => {
4326
4871
  editor.chain().focus().toggleHeading({ level: 2 }).run();
4327
4872
  }
4328
4873
  },
4329
4874
  heading_3: {
4330
- check: (editor) => (0, import_editor_utils5.isNodeInSchema)("heading", editor),
4875
+ check: (editor) => (0, import_editor_utils6.isNodeInSchema)("heading", editor),
4331
4876
  action: ({ editor }) => {
4332
4877
  editor.chain().focus().toggleHeading({ level: 3 }).run();
4333
4878
  }
4334
4879
  },
4335
4880
  bullet_list: {
4336
- check: (editor) => (0, import_editor_utils5.isNodeInSchema)("bulletList", editor),
4881
+ check: (editor) => (0, import_editor_utils6.isNodeInSchema)("bulletList", editor),
4337
4882
  action: ({ editor }) => {
4338
4883
  editor.chain().focus().toggleBulletList().run();
4339
4884
  }
4340
4885
  },
4341
4886
  ordered_list: {
4342
- check: (editor) => (0, import_editor_utils5.isNodeInSchema)("orderedList", editor),
4887
+ check: (editor) => (0, import_editor_utils6.isNodeInSchema)("orderedList", editor),
4343
4888
  action: ({ editor }) => {
4344
4889
  editor.chain().focus().toggleOrderedList().run();
4345
4890
  }
4346
4891
  },
4347
4892
  task_list: {
4348
- check: (editor) => (0, import_editor_utils5.isNodeInSchema)("taskList", editor),
4893
+ check: (editor) => (0, import_editor_utils6.isNodeInSchema)("taskList", editor),
4349
4894
  action: ({ editor }) => {
4350
4895
  editor.chain().focus().toggleTaskList().run();
4351
4896
  }
4352
4897
  },
4353
4898
  quote: {
4354
- check: (editor) => (0, import_editor_utils5.isNodeInSchema)("blockquote", editor),
4899
+ check: (editor) => (0, import_editor_utils6.isNodeInSchema)("blockquote", editor),
4355
4900
  action: ({ editor }) => {
4356
4901
  editor.chain().focus().toggleBlockquote().run();
4357
4902
  }
4358
4903
  },
4359
4904
  code_block: {
4360
- check: (editor) => (0, import_editor_utils5.isNodeInSchema)("codeBlock", editor),
4905
+ check: (editor) => (0, import_editor_utils6.isNodeInSchema)("codeBlock", editor),
4361
4906
  action: ({ editor }) => {
4362
4907
  editor.chain().focus().toggleNode("codeBlock", "paragraph").run();
4363
4908
  }
@@ -4374,17 +4919,17 @@ Continue writing from where the text above ends. Write ONLY ONE SENTENCE. DONT R
4374
4919
  // action: ({ editor }: { editor: Editor }) => addEmojiTrigger(editor),
4375
4920
  // },
4376
4921
  divider: {
4377
- check: (editor) => (0, import_editor_utils5.isNodeInSchema)("horizontalRule", editor),
4922
+ check: (editor) => (0, import_editor_utils6.isNodeInSchema)("horizontalRule", editor),
4378
4923
  action: ({ editor }) => {
4379
4924
  editor.chain().focus().setHorizontalRule().run();
4380
4925
  }
4381
4926
  },
4382
4927
  table: {
4383
- check: (editor) => (0, import_editor_utils5.isNodeInSchema)("table", editor),
4928
+ check: (editor) => (0, import_editor_utils6.isNodeInSchema)("table", editor),
4384
4929
  action: ({ editor }) => toggleTable(editor, { rows: 3, cols: 3, withHeaderRow: true })
4385
4930
  },
4386
4931
  control: {
4387
- check: (editor) => (0, import_editor_utils5.isNodeInSchema)("controlBlock", editor),
4932
+ check: (editor) => (0, import_editor_utils6.isNodeInSchema)("controlBlock", editor),
4388
4933
  action: ({ editor }) => {
4389
4934
  try {
4390
4935
  return editor.chain().focus().insertControlBlock().run();
@@ -4394,32 +4939,32 @@ Continue writing from where the text above ends. Write ONLY ONE SENTENCE. DONT R
4394
4939
  }
4395
4940
  },
4396
4941
  table_of_contents: {
4397
- check: (editor) => (0, import_editor_utils5.isNodeInSchema)("tableOfContentsNode", editor),
4942
+ check: (editor) => (0, import_editor_utils6.isNodeInSchema)("tableOfContentsNode", editor),
4398
4943
  action: ({ editor }) => {
4399
4944
  editor.chain().focus().insertTableOfContents().run();
4400
4945
  }
4401
4946
  },
4402
4947
  callout: {
4403
- check: (editor) => (0, import_editor_utils5.isNodeInSchema)("calloutNode", editor),
4948
+ check: (editor) => (0, import_editor_utils6.isNodeInSchema)("calloutNode", editor),
4404
4949
  action: ({ editor }) => {
4405
4950
  editor.chain().focus().insertCallout("info").run();
4406
4951
  }
4407
4952
  },
4408
4953
  callout_warning: {
4409
- check: (editor) => (0, import_editor_utils5.isNodeInSchema)("calloutNode", editor),
4954
+ check: (editor) => (0, import_editor_utils6.isNodeInSchema)("calloutNode", editor),
4410
4955
  action: ({ editor }) => {
4411
4956
  editor.chain().focus().insertCallout("warning").run();
4412
4957
  }
4413
4958
  },
4414
4959
  math: {
4415
- check: (editor) => (0, import_editor_utils5.isNodeInSchema)("mathBlock", editor),
4960
+ check: (editor) => (0, import_editor_utils6.isNodeInSchema)("mathBlock", editor),
4416
4961
  action: ({ editor }) => {
4417
4962
  editor.chain().focus().insertMathBlock().run();
4418
4963
  }
4419
4964
  },
4420
4965
  // Upload
4421
4966
  image: {
4422
- check: (editor) => (0, import_editor_utils5.isNodeInSchema)("imageUpload", editor),
4967
+ check: (editor) => (0, import_editor_utils6.isNodeInSchema)("imageUpload", editor),
4423
4968
  action: ({ editor }) => {
4424
4969
  editor.chain().focus().setImageUpload().run();
4425
4970
  }
@@ -4445,7 +4990,7 @@ function organizeItemsByGroups(items, showGroups) {
4445
4990
  return organizedItems;
4446
4991
  }
4447
4992
  function useSlashDropdownMenu(config) {
4448
- const getSlashMenuItems = React7.useCallback(
4993
+ const getSlashMenuItems = React10.useCallback(
4449
4994
  (editor) => {
4450
4995
  const items = [];
4451
4996
  const enabledItems = (config == null ? void 0 : config.enabledItems) || Object.keys(texts);
@@ -4482,11 +5027,11 @@ function useSlashDropdownMenu(config) {
4482
5027
  }
4483
5028
 
4484
5029
  // src/ui/slash-dropdown-menu/slash-dropdown-menu.tsx
4485
- var import_jsx_runtime15 = require("react/jsx-runtime");
5030
+ var import_jsx_runtime19 = require("react/jsx-runtime");
4486
5031
  var SlashDropdownMenu = (props) => {
4487
5032
  const { config, ...restProps } = props;
4488
5033
  const { getSlashMenuItems } = useSlashDropdownMenu(config);
4489
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5034
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
4490
5035
  SuggestionMenu,
4491
5036
  {
4492
5037
  char: "/",
@@ -4496,19 +5041,19 @@ var SlashDropdownMenu = (props) => {
4496
5041
  selector: "tiptap-slash-dropdown-menu",
4497
5042
  items: ({ query, editor }) => filterSuggestionItems(getSlashMenuItems(editor), query),
4498
5043
  ...restProps,
4499
- children: (props2) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(List, { ...props2, config })
5044
+ children: (props2) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(List, { ...props2, config })
4500
5045
  }
4501
5046
  );
4502
5047
  };
4503
5048
  var Item = (props) => {
4504
5049
  const { item, isSelected, onSelect } = props;
4505
- const itemRef = React8.useRef(null);
4506
- React8.useEffect(() => {
5050
+ const itemRef = React11.useRef(null);
5051
+ React11.useEffect(() => {
4507
5052
  const selector = document.querySelector(
4508
5053
  '[data-selector="tiptap-slash-dropdown-menu"]'
4509
5054
  );
4510
5055
  if (!itemRef.current || !isSelected || !selector) return;
4511
- const overflow = (0, import_editor_utils6.getElementOverflowPosition)(itemRef.current, selector);
5056
+ const overflow = (0, import_editor_utils7.getElementOverflowPosition)(itemRef.current, selector);
4512
5057
  if (overflow === "top") {
4513
5058
  itemRef.current.scrollIntoView(true);
4514
5059
  } else if (overflow === "bottom") {
@@ -4516,13 +5061,13 @@ var Item = (props) => {
4516
5061
  }
4517
5062
  }, [isSelected]);
4518
5063
  const BadgeIcon = item.badge;
4519
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4520
- import_button9.Button,
5064
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5065
+ import_button10.Button,
4521
5066
  {
4522
5067
  ref: itemRef,
4523
5068
  variant: "ghost",
4524
5069
  color: "default",
4525
- startContent: BadgeIcon && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(BadgeIcon, {}),
5070
+ startContent: BadgeIcon && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(BadgeIcon, {}),
4526
5071
  "data-active-state": isSelected ? "on" : "off",
4527
5072
  onClick: onSelect,
4528
5073
  fullWidth: true,
@@ -4537,14 +5082,14 @@ var List = ({
4537
5082
  onSelect,
4538
5083
  config
4539
5084
  }) => {
4540
- const styles = (0, import_theme5.slashDropdownMenu)();
4541
- const renderedItems = React8.useMemo(() => {
5085
+ const styles = (0, import_theme7.slashDropdownMenu)();
5086
+ const renderedItems = React11.useMemo(() => {
4542
5087
  const rendered = [];
4543
5088
  const showGroups = (config == null ? void 0 : config.showGroups) !== false;
4544
5089
  if (!showGroups) {
4545
5090
  items.forEach((item, index) => {
4546
5091
  rendered.push(
4547
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5092
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
4548
5093
  Item,
4549
5094
  {
4550
5095
  item,
@@ -4569,7 +5114,7 @@ var List = ({
4569
5114
  Object.entries(groups).forEach(([groupLabel, groupData], groupIndex) => {
4570
5115
  if (groupIndex > 0) {
4571
5116
  rendered.push(
4572
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5117
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
4573
5118
  import_separator.Separator,
4574
5119
  {
4575
5120
  orientation: "horizontal"
@@ -4580,7 +5125,7 @@ var List = ({
4580
5125
  }
4581
5126
  const groupItems = groupData.items.map((item, itemIndex) => {
4582
5127
  const originalIndex = groupData.indices[itemIndex];
4583
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5128
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
4584
5129
  Item,
4585
5130
  {
4586
5131
  item,
@@ -4592,13 +5137,13 @@ var List = ({
4592
5137
  });
4593
5138
  if (groupLabel) {
4594
5139
  rendered.push(
4595
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5140
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
4596
5141
  "div",
4597
5142
  {
4598
5143
  className: styles.cardItemGroup(),
4599
5144
  children: [
4600
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: styles.cardGroupLabel(), children: groupLabel }),
4601
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: styles.cardGroup(), children: groupItems })
5145
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: styles.cardGroupLabel(), children: groupLabel }),
5146
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: styles.cardGroup(), children: groupItems })
4602
5147
  ]
4603
5148
  },
4604
5149
  `group-${groupIndex}-${groupLabel}`
@@ -4613,14 +5158,14 @@ var List = ({
4613
5158
  if (!renderedItems.length) {
4614
5159
  return null;
4615
5160
  }
4616
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5161
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
4617
5162
  "div",
4618
5163
  {
4619
5164
  className: styles.card(),
4620
5165
  style: {
4621
5166
  maxHeight: "var(--suggestion-menu-max-height)"
4622
5167
  },
4623
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: styles.body(), children: renderedItems })
5168
+ children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: styles.body(), children: renderedItems })
4624
5169
  }
4625
5170
  );
4626
5171
  };
@@ -4630,20 +5175,20 @@ var import_icons25 = require("@kopexa/icons");
4630
5175
  var import_popover3 = require("@kopexa/popover");
4631
5176
  var import_toolbar10 = require("@kopexa/toolbar");
4632
5177
  var import_use_is_mobile2 = require("@kopexa/use-is-mobile");
4633
- var import_react53 = require("react");
5178
+ var import_react55 = require("react");
4634
5179
 
4635
5180
  // src/hooks/use-cursor-visibility.ts
4636
- var React10 = __toESM(require("react"));
5181
+ var React13 = __toESM(require("react"));
4637
5182
 
4638
5183
  // src/hooks/use-window-size.ts
4639
- var React9 = __toESM(require("react"));
5184
+ var React12 = __toESM(require("react"));
4640
5185
  function useWindowSize() {
4641
- const [windowSize, setWindowSize] = React9.useState({
5186
+ const [windowSize, setWindowSize] = React12.useState({
4642
5187
  width: 0,
4643
5188
  height: 0,
4644
5189
  offsetTop: 0
4645
5190
  });
4646
- React9.useEffect(() => {
5191
+ React12.useEffect(() => {
4647
5192
  handleResize();
4648
5193
  function handleResize() {
4649
5194
  if (typeof window === "undefined") return;
@@ -4679,19 +5224,19 @@ function useCursorVisibility({
4679
5224
  elementRef = null
4680
5225
  }) {
4681
5226
  const { height: windowHeight } = useWindowSize();
4682
- const [rect, setRect] = React10.useState({
5227
+ const [rect, setRect] = React13.useState({
4683
5228
  x: 0,
4684
5229
  y: 0,
4685
5230
  width: 0,
4686
5231
  height: 0
4687
5232
  });
4688
- const updateRect = React10.useCallback(() => {
5233
+ const updateRect = React13.useCallback(() => {
4689
5234
  var _a;
4690
5235
  const element = (_a = elementRef == null ? void 0 : elementRef.current) != null ? _a : document.body;
4691
5236
  const { x, y, width, height } = element.getBoundingClientRect();
4692
5237
  setRect({ x, y, width, height });
4693
5238
  }, [elementRef]);
4694
- React10.useEffect(() => {
5239
+ React13.useEffect(() => {
4695
5240
  var _a;
4696
5241
  const element = (_a = elementRef == null ? void 0 : elementRef.current) != null ? _a : document.body;
4697
5242
  updateRect();
@@ -4705,7 +5250,7 @@ function useCursorVisibility({
4705
5250
  window.removeEventListener("scroll", updateRect);
4706
5251
  };
4707
5252
  }, [elementRef, updateRect]);
4708
- React10.useEffect(() => {
5253
+ React13.useEffect(() => {
4709
5254
  const ensureCursorVisibility = () => {
4710
5255
  if (!editor) return;
4711
5256
  const { state, view } = editor;
@@ -4736,18 +5281,18 @@ function useCursorVisibility({
4736
5281
 
4737
5282
  // src/ui/blockquote-button/blockquote-button.tsx
4738
5283
  var import_toolbar4 = require("@kopexa/toolbar");
4739
- var React12 = __toESM(require("react"));
5284
+ var React15 = __toESM(require("react"));
4740
5285
 
4741
5286
  // src/ui/blockquote-button/use-blockquote.ts
4742
- var import_editor_utils7 = require("@kopexa/editor-utils");
5287
+ var import_editor_utils8 = require("@kopexa/editor-utils");
4743
5288
  var import_icons14 = require("@kopexa/icons");
4744
- var import_state6 = require("@tiptap/pm/state");
4745
- var React11 = __toESM(require("react"));
5289
+ var import_state7 = require("@tiptap/pm/state");
5290
+ var React14 = __toESM(require("react"));
4746
5291
  var BLOCKQUOTE_SHORTCUT_KEY = "mod+shift+b";
4747
5292
  function canToggleBlockquote(editor, turnInto = true) {
4748
5293
  var _a;
4749
5294
  if (!editor || !editor.isEditable) return false;
4750
- if (!(0, import_editor_utils7.isNodeInSchema)("blockquote", editor) || (0, import_editor_utils7.isNodeTypeSelected)(editor, ["image"]))
5295
+ if (!(0, import_editor_utils8.isNodeInSchema)("blockquote", editor) || (0, import_editor_utils8.isNodeTypeSelected)(editor, ["image"]))
4751
5296
  return false;
4752
5297
  if (!turnInto) {
4753
5298
  return editor.can().toggleWrap("blockquote");
@@ -4756,12 +5301,12 @@ function canToggleBlockquote(editor, turnInto = true) {
4756
5301
  const view = editor.view;
4757
5302
  const state = view.state;
4758
5303
  const selection = state.selection;
4759
- if (selection.empty || selection instanceof import_state6.TextSelection) {
4760
- const pos = (_a = (0, import_editor_utils7.findNodePosition)({
5304
+ if (selection.empty || selection instanceof import_state7.TextSelection) {
5305
+ const pos = (_a = (0, import_editor_utils8.findNodePosition)({
4761
5306
  editor,
4762
5307
  node: state.selection.$anchor.node(1)
4763
5308
  })) == null ? void 0 : _a.pos;
4764
- if (!(0, import_editor_utils7.isValidPosition)(pos)) return false;
5309
+ if (!(0, import_editor_utils8.isValidPosition)(pos)) return false;
4765
5310
  }
4766
5311
  return true;
4767
5312
  } catch {
@@ -4776,19 +5321,19 @@ function toggleBlockquote(editor) {
4776
5321
  const view = editor.view;
4777
5322
  let state = view.state;
4778
5323
  let tr = state.tr;
4779
- if (state.selection.empty || state.selection instanceof import_state6.TextSelection) {
4780
- const pos = (_a = (0, import_editor_utils7.findNodePosition)({
5324
+ if (state.selection.empty || state.selection instanceof import_state7.TextSelection) {
5325
+ const pos = (_a = (0, import_editor_utils8.findNodePosition)({
4781
5326
  editor,
4782
5327
  node: state.selection.$anchor.node(1)
4783
5328
  })) == null ? void 0 : _a.pos;
4784
- if (!(0, import_editor_utils7.isValidPosition)(pos)) return false;
4785
- tr = tr.setSelection(import_state6.NodeSelection.create(state.doc, pos));
5329
+ if (!(0, import_editor_utils8.isValidPosition)(pos)) return false;
5330
+ tr = tr.setSelection(import_state7.NodeSelection.create(state.doc, pos));
4786
5331
  view.dispatch(tr);
4787
5332
  state = view.state;
4788
5333
  }
4789
5334
  const selection = state.selection;
4790
5335
  let chain = editor.chain().focus();
4791
- if (selection instanceof import_state6.NodeSelection) {
5336
+ if (selection instanceof import_state7.NodeSelection) {
4792
5337
  const firstChild = (_b = selection.node.firstChild) == null ? void 0 : _b.firstChild;
4793
5338
  const lastChild = (_c = selection.node.lastChild) == null ? void 0 : _c.lastChild;
4794
5339
  const from = firstChild ? selection.from + firstChild.nodeSize : selection.from + 1;
@@ -4806,7 +5351,7 @@ function toggleBlockquote(editor) {
4806
5351
  function shouldShowButton2(props) {
4807
5352
  const { editor, hideWhenUnavailable } = props;
4808
5353
  if (!editor || !editor.isEditable) return false;
4809
- if (!(0, import_editor_utils7.isNodeInSchema)("blockquote", editor)) return false;
5354
+ if (!(0, import_editor_utils8.isNodeInSchema)("blockquote", editor)) return false;
4810
5355
  if (hideWhenUnavailable && !editor.isActive("code")) {
4811
5356
  return canToggleBlockquote(editor);
4812
5357
  }
@@ -4819,10 +5364,10 @@ function useBlockquote(config) {
4819
5364
  onToggled
4820
5365
  } = config || {};
4821
5366
  const { editor } = useTiptapEditor(providedEditor);
4822
- const [isVisible, setIsVisible] = React11.useState(true);
5367
+ const [isVisible, setIsVisible] = React14.useState(true);
4823
5368
  const canToggle3 = canToggleBlockquote(editor);
4824
5369
  const isActive = (editor == null ? void 0 : editor.isActive("blockquote")) || false;
4825
- React11.useEffect(() => {
5370
+ React14.useEffect(() => {
4826
5371
  if (!editor) return;
4827
5372
  const handleSelectionUpdate = () => {
4828
5373
  setIsVisible(shouldShowButton2({ editor, hideWhenUnavailable }));
@@ -4833,7 +5378,7 @@ function useBlockquote(config) {
4833
5378
  editor.off("selectionUpdate", handleSelectionUpdate);
4834
5379
  };
4835
5380
  }, [editor, hideWhenUnavailable]);
4836
- const handleToggle = React11.useCallback(() => {
5381
+ const handleToggle = React14.useCallback(() => {
4837
5382
  if (!editor) return false;
4838
5383
  const success = toggleBlockquote(editor);
4839
5384
  if (success) {
@@ -4853,7 +5398,7 @@ function useBlockquote(config) {
4853
5398
  }
4854
5399
 
4855
5400
  // src/ui/blockquote-button/blockquote-button.tsx
4856
- var import_jsx_runtime16 = require("react/jsx-runtime");
5401
+ var import_jsx_runtime20 = require("react/jsx-runtime");
4857
5402
  var BlockquoteButton = ({
4858
5403
  editor: providedEditor,
4859
5404
  text,
@@ -4878,7 +5423,7 @@ var BlockquoteButton = ({
4878
5423
  hideWhenUnavailable,
4879
5424
  onToggled
4880
5425
  });
4881
- const handleClick = React12.useCallback(
5426
+ const handleClick = React15.useCallback(
4882
5427
  (event) => {
4883
5428
  onClick == null ? void 0 : onClick(event);
4884
5429
  if (event.defaultPrevented) return;
@@ -4889,7 +5434,7 @@ var BlockquoteButton = ({
4889
5434
  if (!isVisible) {
4890
5435
  return null;
4891
5436
  }
4892
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5437
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4893
5438
  import_toolbar4.ToolbarButton,
4894
5439
  {
4895
5440
  type: "button",
@@ -4906,9 +5451,9 @@ var BlockquoteButton = ({
4906
5451
  onClick: handleClick,
4907
5452
  isIconOnly: !text && !children,
4908
5453
  ...buttonProps,
4909
- children: children != null ? children : /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
4910
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Icon, {}),
4911
- text && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: text })
5454
+ children: children != null ? children : /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
5455
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Icon, {}),
5456
+ text && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { children: text })
4912
5457
  ] })
4913
5458
  }
4914
5459
  );
@@ -4917,18 +5462,18 @@ var BlockquoteButton = ({
4917
5462
  // src/ui/codeblock-button/code-block-button.tsx
4918
5463
  var import_icons16 = require("@kopexa/icons");
4919
5464
  var import_toolbar5 = require("@kopexa/toolbar");
4920
- var import_react39 = require("react");
5465
+ var import_react41 = require("react");
4921
5466
 
4922
5467
  // src/ui/codeblock-button/use-code-block.ts
4923
- var import_editor_utils8 = require("@kopexa/editor-utils");
5468
+ var import_editor_utils9 = require("@kopexa/editor-utils");
4924
5469
  var import_icons15 = require("@kopexa/icons");
4925
- var import_state7 = require("@tiptap/pm/state");
4926
- var React13 = __toESM(require("react"));
5470
+ var import_state8 = require("@tiptap/pm/state");
5471
+ var React16 = __toESM(require("react"));
4927
5472
  var CODE_BLOCK_SHORTCUT_KEY = "mod+alt+c";
4928
5473
  function canToggle2(editor, turnInto = true) {
4929
5474
  var _a;
4930
5475
  if (!editor || !editor.isEditable) return false;
4931
- if (!(0, import_editor_utils8.isNodeInSchema)("codeBlock", editor) || (0, import_editor_utils8.isNodeTypeSelected)(editor, ["image"]))
5476
+ if (!(0, import_editor_utils9.isNodeInSchema)("codeBlock", editor) || (0, import_editor_utils9.isNodeTypeSelected)(editor, ["image"]))
4932
5477
  return false;
4933
5478
  if (!turnInto) {
4934
5479
  return editor.can().toggleNode("codeBlock", "paragraph");
@@ -4937,12 +5482,12 @@ function canToggle2(editor, turnInto = true) {
4937
5482
  const view = editor.view;
4938
5483
  const state = view.state;
4939
5484
  const selection = state.selection;
4940
- if (selection.empty || selection instanceof import_state7.TextSelection) {
4941
- const pos = (_a = (0, import_editor_utils8.findNodePosition)({
5485
+ if (selection.empty || selection instanceof import_state8.TextSelection) {
5486
+ const pos = (_a = (0, import_editor_utils9.findNodePosition)({
4942
5487
  editor,
4943
5488
  node: state.selection.$anchor.node(1)
4944
5489
  })) == null ? void 0 : _a.pos;
4945
- if (!(0, import_editor_utils8.isValidPosition)(pos)) return false;
5490
+ if (!(0, import_editor_utils9.isValidPosition)(pos)) return false;
4946
5491
  }
4947
5492
  return true;
4948
5493
  } catch {
@@ -4957,19 +5502,19 @@ function toggleCodeBlock(editor) {
4957
5502
  const view = editor.view;
4958
5503
  let state = view.state;
4959
5504
  let tr = state.tr;
4960
- if (state.selection.empty || state.selection instanceof import_state7.TextSelection) {
4961
- const pos = (_a = (0, import_editor_utils8.findNodePosition)({
5505
+ if (state.selection.empty || state.selection instanceof import_state8.TextSelection) {
5506
+ const pos = (_a = (0, import_editor_utils9.findNodePosition)({
4962
5507
  editor,
4963
5508
  node: state.selection.$anchor.node(1)
4964
5509
  })) == null ? void 0 : _a.pos;
4965
- if (!(0, import_editor_utils8.isValidPosition)(pos)) return false;
4966
- tr = tr.setSelection(import_state7.NodeSelection.create(state.doc, pos));
5510
+ if (!(0, import_editor_utils9.isValidPosition)(pos)) return false;
5511
+ tr = tr.setSelection(import_state8.NodeSelection.create(state.doc, pos));
4967
5512
  view.dispatch(tr);
4968
5513
  state = view.state;
4969
5514
  }
4970
5515
  const selection = state.selection;
4971
5516
  let chain = editor.chain().focus();
4972
- if (selection instanceof import_state7.NodeSelection) {
5517
+ if (selection instanceof import_state8.NodeSelection) {
4973
5518
  const firstChild = (_b = selection.node.firstChild) == null ? void 0 : _b.firstChild;
4974
5519
  const lastChild = (_c = selection.node.lastChild) == null ? void 0 : _c.lastChild;
4975
5520
  const from = firstChild ? selection.from + firstChild.nodeSize : selection.from + 1;
@@ -4987,7 +5532,7 @@ function toggleCodeBlock(editor) {
4987
5532
  function shouldShowButton3(props) {
4988
5533
  const { editor, hideWhenUnavailable } = props;
4989
5534
  if (!editor || !editor.isEditable) return false;
4990
- if (!(0, import_editor_utils8.isNodeInSchema)("codeBlock", editor)) return false;
5535
+ if (!(0, import_editor_utils9.isNodeInSchema)("codeBlock", editor)) return false;
4991
5536
  if (hideWhenUnavailable && !editor.isActive("code")) {
4992
5537
  return canToggle2(editor);
4993
5538
  }
@@ -5000,10 +5545,10 @@ function useCodeBlock(config) {
5000
5545
  onToggled
5001
5546
  } = config || {};
5002
5547
  const { editor } = useTiptapEditor(providedEditor);
5003
- const [isVisible, setIsVisible] = React13.useState(true);
5548
+ const [isVisible, setIsVisible] = React16.useState(true);
5004
5549
  const canToggleState = canToggle2(editor);
5005
5550
  const isActive = (editor == null ? void 0 : editor.isActive("codeBlock")) || false;
5006
- React13.useEffect(() => {
5551
+ React16.useEffect(() => {
5007
5552
  if (!editor) return;
5008
5553
  const handleSelectionUpdate = () => {
5009
5554
  setIsVisible(shouldShowButton3({ editor, hideWhenUnavailable }));
@@ -5014,7 +5559,7 @@ function useCodeBlock(config) {
5014
5559
  editor.off("selectionUpdate", handleSelectionUpdate);
5015
5560
  };
5016
5561
  }, [editor, hideWhenUnavailable]);
5017
- const handleToggle = React13.useCallback(() => {
5562
+ const handleToggle = React16.useCallback(() => {
5018
5563
  if (!editor) return false;
5019
5564
  const success = toggleCodeBlock(editor);
5020
5565
  if (success) {
@@ -5034,7 +5579,7 @@ function useCodeBlock(config) {
5034
5579
  }
5035
5580
 
5036
5581
  // src/ui/codeblock-button/code-block-button.tsx
5037
- var import_jsx_runtime17 = require("react/jsx-runtime");
5582
+ var import_jsx_runtime21 = require("react/jsx-runtime");
5038
5583
  var CodeBlockButton = ({
5039
5584
  editor: providedEditor,
5040
5585
  text,
@@ -5051,7 +5596,7 @@ var CodeBlockButton = ({
5051
5596
  hideWhenUnavailable,
5052
5597
  onToggled
5053
5598
  });
5054
- const handleClick = (0, import_react39.useCallback)(
5599
+ const handleClick = (0, import_react41.useCallback)(
5055
5600
  (event) => {
5056
5601
  onClick == null ? void 0 : onClick(event);
5057
5602
  if (event.defaultPrevented) return;
@@ -5062,7 +5607,7 @@ var CodeBlockButton = ({
5062
5607
  if (!isVisible) {
5063
5608
  return null;
5064
5609
  }
5065
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5610
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
5066
5611
  import_toolbar5.ToolbarButton,
5067
5612
  {
5068
5613
  type: "button",
@@ -5079,28 +5624,28 @@ var CodeBlockButton = ({
5079
5624
  onClick: handleClick,
5080
5625
  isIconOnly: true,
5081
5626
  ...buttonProps,
5082
- children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_icons16.CodeblockIcon, {})
5627
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_icons16.CodeblockIcon, {})
5083
5628
  }
5084
5629
  );
5085
5630
  };
5086
5631
 
5087
5632
  // src/ui/color-highlight-popover/color-highlight-popover.tsx
5088
- var import_button10 = require("@kopexa/button");
5633
+ var import_button11 = require("@kopexa/button");
5089
5634
  var import_icons18 = require("@kopexa/icons");
5090
5635
  var import_popover2 = require("@kopexa/popover");
5091
5636
  var import_toolbar7 = require("@kopexa/toolbar");
5092
- var import_react41 = require("react");
5637
+ var import_react43 = require("react");
5093
5638
 
5094
5639
  // src/ui/color-highlight-button/color-highlight-button.tsx
5095
- var import_theme6 = require("@kopexa/theme");
5640
+ var import_theme8 = require("@kopexa/theme");
5096
5641
  var import_toolbar6 = require("@kopexa/toolbar");
5097
- var import_react40 = require("react");
5642
+ var import_react42 = require("react");
5098
5643
 
5099
5644
  // src/ui/color-highlight-button/use-color-highlight.ts
5100
- var import_editor_utils9 = require("@kopexa/editor-utils");
5645
+ var import_editor_utils10 = require("@kopexa/editor-utils");
5101
5646
  var import_icons17 = require("@kopexa/icons");
5102
5647
  var import_use_is_mobile = require("@kopexa/use-is-mobile");
5103
- var React14 = __toESM(require("react"));
5648
+ var React17 = __toESM(require("react"));
5104
5649
  var import_react_hotkeys_hook = require("react-hotkeys-hook");
5105
5650
  var COLOR_HIGHLIGHT_SHORTCUT_KEY = "mod+shift+h";
5106
5651
  var HIGHLIGHT_COLORS = [
@@ -5163,7 +5708,7 @@ function pickHighlightColorsByValue(values) {
5163
5708
  }
5164
5709
  function canColorHighlight(editor) {
5165
5710
  if (!editor || !editor.isEditable) return false;
5166
- if (!(0, import_editor_utils9.isMarkInSchema)("highlight", editor) || (0, import_editor_utils9.isNodeTypeSelected)(editor, ["image"]))
5711
+ if (!(0, import_editor_utils10.isMarkInSchema)("highlight", editor) || (0, import_editor_utils10.isNodeTypeSelected)(editor, ["image"]))
5167
5712
  return false;
5168
5713
  return editor.can().setMark("highlight");
5169
5714
  }
@@ -5179,7 +5724,7 @@ function removeHighlight(editor) {
5179
5724
  function shouldShowButton4(props) {
5180
5725
  const { editor, hideWhenUnavailable } = props;
5181
5726
  if (!editor || !editor.isEditable) return false;
5182
- if (!(0, import_editor_utils9.isMarkInSchema)("highlight", editor)) return false;
5727
+ if (!(0, import_editor_utils10.isMarkInSchema)("highlight", editor)) return false;
5183
5728
  if (hideWhenUnavailable && !editor.isActive("code")) {
5184
5729
  return canColorHighlight(editor);
5185
5730
  }
@@ -5195,10 +5740,10 @@ function useColorHighlight(config) {
5195
5740
  } = config;
5196
5741
  const { editor } = useTiptapEditor(providedEditor);
5197
5742
  const isMobile = (0, import_use_is_mobile.useIsMobile)();
5198
- const [isVisible, setIsVisible] = React14.useState(true);
5743
+ const [isVisible, setIsVisible] = React17.useState(true);
5199
5744
  const canColorHighlightState = canColorHighlight(editor);
5200
5745
  const isActive = isColorHighlightActive(editor, highlightColor);
5201
- React14.useEffect(() => {
5746
+ React17.useEffect(() => {
5202
5747
  if (!editor) return;
5203
5748
  const handleSelectionUpdate = () => {
5204
5749
  setIsVisible(shouldShowButton4({ editor, hideWhenUnavailable }));
@@ -5209,7 +5754,7 @@ function useColorHighlight(config) {
5209
5754
  editor.off("selectionUpdate", handleSelectionUpdate);
5210
5755
  };
5211
5756
  }, [editor, hideWhenUnavailable]);
5212
- const handleColorHighlight = React14.useCallback(() => {
5757
+ const handleColorHighlight = React17.useCallback(() => {
5213
5758
  if (!editor || !canColorHighlightState || !highlightColor || !label)
5214
5759
  return false;
5215
5760
  if (editor.state.storedMarks) {
@@ -5228,7 +5773,7 @@ function useColorHighlight(config) {
5228
5773
  return success;
5229
5774
  }, 0);
5230
5775
  }, [canColorHighlightState, highlightColor, editor, label, onApplied]);
5231
- const handleRemoveHighlight = React14.useCallback(() => {
5776
+ const handleRemoveHighlight = React17.useCallback(() => {
5232
5777
  const success = removeHighlight(editor);
5233
5778
  if (success) {
5234
5779
  onApplied == null ? void 0 : onApplied({ color: "", label: "Remove highlight" });
@@ -5260,7 +5805,7 @@ function useColorHighlight(config) {
5260
5805
  }
5261
5806
 
5262
5807
  // src/ui/color-highlight-button/color-highlight-button.tsx
5263
- var import_jsx_runtime18 = require("react/jsx-runtime");
5808
+ var import_jsx_runtime22 = require("react/jsx-runtime");
5264
5809
  var ColorHighlightButton = ({
5265
5810
  editor: providedEditor,
5266
5811
  highlightColor,
@@ -5289,7 +5834,7 @@ var ColorHighlightButton = ({
5289
5834
  hideWhenUnavailable,
5290
5835
  onApplied
5291
5836
  });
5292
- const handleClick = (0, import_react40.useCallback)(
5837
+ const handleClick = (0, import_react42.useCallback)(
5293
5838
  (event) => {
5294
5839
  onClick == null ? void 0 : onClick(event);
5295
5840
  if (event.defaultPrevented) return;
@@ -5297,7 +5842,7 @@ var ColorHighlightButton = ({
5297
5842
  },
5298
5843
  [handleColorHighlight, onClick]
5299
5844
  );
5300
- const buttonStyle = (0, import_react40.useMemo)(
5845
+ const buttonStyle = (0, import_react42.useMemo)(
5301
5846
  () => ({
5302
5847
  ...style,
5303
5848
  "--highlight-color": highlightColor
@@ -5307,8 +5852,8 @@ var ColorHighlightButton = ({
5307
5852
  if (!isVisible) {
5308
5853
  return null;
5309
5854
  }
5310
- const styles = (0, import_theme6.colorHighlightButton)();
5311
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
5855
+ const styles = (0, import_theme8.colorHighlightButton)();
5856
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
5312
5857
  import_toolbar6.ToolbarButton,
5313
5858
  {
5314
5859
  type: "button",
@@ -5327,15 +5872,15 @@ var ColorHighlightButton = ({
5327
5872
  isIconOnly: true,
5328
5873
  ...buttonProps,
5329
5874
  children: [
5330
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5875
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5331
5876
  "span",
5332
5877
  {
5333
5878
  "data-active-state": isActive ? "on" : "off",
5334
5879
  className: styles.mark()
5335
5880
  }
5336
5881
  ),
5337
- children || /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
5338
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5882
+ children || /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
5883
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5339
5884
  "span",
5340
5885
  {
5341
5886
  style: { "--highlight-color": highlightColor }
@@ -5349,13 +5894,13 @@ var ColorHighlightButton = ({
5349
5894
  };
5350
5895
 
5351
5896
  // src/ui/color-highlight-popover/color-highlight-popover.tsx
5352
- var import_jsx_runtime19 = require("react/jsx-runtime");
5897
+ var import_jsx_runtime23 = require("react/jsx-runtime");
5353
5898
  var ColorHighlightPopoverButton = ({
5354
5899
  className,
5355
5900
  children,
5356
5901
  ...props
5357
- }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5358
- import_button10.IconButton,
5902
+ }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5903
+ import_button11.IconButton,
5359
5904
  {
5360
5905
  type: "button",
5361
5906
  className,
@@ -5366,7 +5911,7 @@ var ColorHighlightPopoverButton = ({
5366
5911
  tooltip: "Highlight",
5367
5912
  isIconOnly: !children,
5368
5913
  ...props,
5369
- children: children != null ? children : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_icons18.HighlighterIcon, {})
5914
+ children: children != null ? children : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_icons18.HighlighterIcon, {})
5370
5915
  }
5371
5916
  );
5372
5917
  function ColorHighlightPopoverContent({
@@ -5380,8 +5925,8 @@ function ColorHighlightPopoverContent({
5380
5925
  ])
5381
5926
  }) {
5382
5927
  const { handleRemoveHighlight } = useColorHighlight({ editor });
5383
- const containerRef = (0, import_react41.useRef)(null);
5384
- const menuItems = (0, import_react41.useMemo)(
5928
+ const containerRef = (0, import_react43.useRef)(null);
5929
+ const menuItems = (0, import_react43.useMemo)(
5385
5930
  () => [...colors, { label: "Remove highlight", value: "none" }],
5386
5931
  [colors]
5387
5932
  );
@@ -5399,13 +5944,13 @@ function ColorHighlightPopoverContent({
5399
5944
  },
5400
5945
  autoSelectFirstItem: false
5401
5946
  });
5402
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { ref: containerRef, className: "flex gap-1 items-center", children: [
5403
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5947
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { ref: containerRef, className: "flex gap-1 items-center", children: [
5948
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5404
5949
  "div",
5405
5950
  {
5406
5951
  className: "flex items-center gap-1 outline-none",
5407
5952
  "data-orientation": "horizontal",
5408
- children: colors.map((color, index) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5953
+ children: colors.map((color, index) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5409
5954
  ColorHighlightButton,
5410
5955
  {
5411
5956
  editor,
@@ -5418,9 +5963,9 @@ function ColorHighlightPopoverContent({
5418
5963
  ))
5419
5964
  }
5420
5965
  ),
5421
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_toolbar7.ToolbarSeparator, { orientation: "vertical" }),
5422
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "tiptap-button-group", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5423
- import_button10.IconButton,
5966
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_toolbar7.ToolbarSeparator, { orientation: "vertical" }),
5967
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "tiptap-button-group", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5968
+ import_button11.IconButton,
5424
5969
  {
5425
5970
  onClick: handleRemoveHighlight,
5426
5971
  "aria-label": "Remove highlight",
@@ -5430,7 +5975,7 @@ function ColorHighlightPopoverContent({
5430
5975
  variant: "ghost",
5431
5976
  color: "default",
5432
5977
  "data-highlighted": selectedIndex === colors.length,
5433
- children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_icons18.BanIcon, {})
5978
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_icons18.BanIcon, {})
5434
5979
  }
5435
5980
  ) })
5436
5981
  ] });
@@ -5449,18 +5994,18 @@ function ColorHighlightPopover({
5449
5994
  ...props
5450
5995
  }) {
5451
5996
  const { editor } = useTiptapEditor(providedEditor);
5452
- const [isOpen, setIsOpen] = (0, import_react41.useState)(false);
5997
+ const [isOpen, setIsOpen] = (0, import_react43.useState)(false);
5453
5998
  const { isVisible, canColorHighlight: canColorHighlight2, isActive, label } = useColorHighlight({
5454
5999
  editor,
5455
6000
  hideWhenUnavailable,
5456
6001
  onApplied
5457
6002
  });
5458
6003
  if (!isVisible) return null;
5459
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_popover2.Popover.Root, { open: isOpen, onOpenChange: setIsOpen, spacing: "dense", children: [
5460
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6004
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_popover2.Popover.Root, { open: isOpen, onOpenChange: setIsOpen, spacing: "dense", children: [
6005
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5461
6006
  import_popover2.Popover.Trigger,
5462
6007
  {
5463
- render: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6008
+ render: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5464
6009
  ColorHighlightPopoverButton,
5465
6010
  {
5466
6011
  disabled: !canColorHighlight2,
@@ -5474,26 +6019,26 @@ function ColorHighlightPopover({
5474
6019
  )
5475
6020
  }
5476
6021
  ),
5477
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_popover2.Popover.Content, { "aria-label": "Highlight colors", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ColorHighlightPopoverContent, { editor, colors }) })
6022
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_popover2.Popover.Content, { "aria-label": "Highlight colors", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ColorHighlightPopoverContent, { editor, colors }) })
5478
6023
  ] });
5479
6024
  }
5480
6025
 
5481
6026
  // src/ui/heading-dropdown-menu/index.tsx
5482
- var import_button12 = require("@kopexa/button");
6027
+ var import_button13 = require("@kopexa/button");
5483
6028
  var import_dropdown_menu = require("@kopexa/dropdown-menu");
5484
- var import_editor_utils11 = require("@kopexa/editor-utils");
6029
+ var import_editor_utils12 = require("@kopexa/editor-utils");
5485
6030
  var import_icons20 = require("@kopexa/icons");
5486
- var import_react43 = require("@tiptap/react");
5487
- var React16 = __toESM(require("react"));
6031
+ var import_react45 = require("@tiptap/react");
6032
+ var React19 = __toESM(require("react"));
5488
6033
 
5489
6034
  // src/ui/heading-button/index.tsx
5490
- var import_button11 = require("@kopexa/button");
5491
- var import_editor_utils10 = require("@kopexa/editor-utils");
6035
+ var import_button12 = require("@kopexa/button");
6036
+ var import_editor_utils11 = require("@kopexa/editor-utils");
5492
6037
  var import_icons19 = require("@kopexa/icons");
5493
- var React15 = __toESM(require("react"));
6038
+ var React18 = __toESM(require("react"));
5494
6039
 
5495
6040
  // src/ui/heading-button/utils.ts
5496
- var import_react42 = require("@tiptap/react");
6041
+ var import_react44 = require("@tiptap/react");
5497
6042
  var headingShortcutKeys = {
5498
6043
  1: "Ctrl-Alt-1",
5499
6044
  2: "Ctrl-Alt-2",
@@ -5534,7 +6079,7 @@ function shouldShowHeadingButton(params) {
5534
6079
  return false;
5535
6080
  }
5536
6081
  if (hideWhenUnavailable) {
5537
- if ((0, import_react42.isNodeSelection)(editor.state.selection)) {
6082
+ if ((0, import_react44.isNodeSelection)(editor.state.selection)) {
5538
6083
  return false;
5539
6084
  }
5540
6085
  }
@@ -5545,7 +6090,7 @@ function getFormattedHeadingName(level) {
5545
6090
  }
5546
6091
 
5547
6092
  // src/ui/heading-button/index.tsx
5548
- var import_jsx_runtime20 = require("react/jsx-runtime");
6093
+ var import_jsx_runtime24 = require("react/jsx-runtime");
5549
6094
  var headingIcons = {
5550
6095
  1: import_icons19.HeadingOneIcon,
5551
6096
  2: import_icons19.HeadingTwoIcon,
@@ -5555,7 +6100,7 @@ var headingIcons = {
5555
6100
  6: import_icons19.HeadingSixIcon
5556
6101
  };
5557
6102
  function useHeadingState(editor, level, disabled = false) {
5558
- const headingInSchema = (0, import_editor_utils10.isNodeInSchema)("heading", editor);
6103
+ const headingInSchema = (0, import_editor_utils11.isNodeInSchema)("heading", editor);
5559
6104
  const isDisabled = isHeadingButtonDisabled(editor, level, disabled);
5560
6105
  const isActive = isHeadingActive(editor, level);
5561
6106
  const Icon = headingIcons[level];
@@ -5591,7 +6136,7 @@ var HeadingButton = ({
5591
6136
  shortcutKey,
5592
6137
  formattedName
5593
6138
  } = useHeadingState(editor, level, disabled);
5594
- const handleClick = React15.useCallback(
6139
+ const handleClick = React18.useCallback(
5595
6140
  (e) => {
5596
6141
  onClick == null ? void 0 : onClick(e);
5597
6142
  if (!e.defaultPrevented && !isDisabled && editor) {
@@ -5600,7 +6145,7 @@ var HeadingButton = ({
5600
6145
  },
5601
6146
  [onClick, isDisabled, editor, level]
5602
6147
  );
5603
- const show = React15.useMemo(() => {
6148
+ const show = React18.useMemo(() => {
5604
6149
  return shouldShowHeadingButton({
5605
6150
  editor,
5606
6151
  level,
@@ -5611,8 +6156,8 @@ var HeadingButton = ({
5611
6156
  if (!show || !editor || !editor.isEditable) {
5612
6157
  return null;
5613
6158
  }
5614
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5615
- import_button11.Button,
6159
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6160
+ import_button12.Button,
5616
6161
  {
5617
6162
  type: "button",
5618
6163
  className: className.trim(),
@@ -5627,7 +6172,7 @@ var HeadingButton = ({
5627
6172
  tooltip: formattedName,
5628
6173
  shortcutKeys: shortcutKey,
5629
6174
  onClick: handleClick,
5630
- startContent: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Icon, {}),
6175
+ startContent: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Icon, {}),
5631
6176
  ...buttonProps,
5632
6177
  ref,
5633
6178
  children: children || text
@@ -5636,7 +6181,7 @@ var HeadingButton = ({
5636
6181
  };
5637
6182
 
5638
6183
  // src/ui/heading-dropdown-menu/index.tsx
5639
- var import_jsx_runtime21 = require("react/jsx-runtime");
6184
+ var import_jsx_runtime25 = require("react/jsx-runtime");
5640
6185
  function HeadingDropdownMenu({
5641
6186
  editor: providedEditor,
5642
6187
  levels = [1, 2, 3, 4, 5, 6],
@@ -5645,26 +6190,26 @@ function HeadingDropdownMenu({
5645
6190
  ...props
5646
6191
  }) {
5647
6192
  var _a;
5648
- const [isOpen, setIsOpen] = React16.useState(false);
6193
+ const [isOpen, setIsOpen] = React19.useState(false);
5649
6194
  const { editor } = useTiptapEditor(providedEditor);
5650
- const headingInSchema = (0, import_editor_utils11.isNodeInSchema)("heading", editor);
5651
- const handleOnOpenChange = React16.useCallback(
6195
+ const headingInSchema = (0, import_editor_utils12.isNodeInSchema)("heading", editor);
6196
+ const handleOnOpenChange = React19.useCallback(
5652
6197
  (open) => {
5653
6198
  setIsOpen(open);
5654
6199
  onOpenChange == null ? void 0 : onOpenChange(open);
5655
6200
  },
5656
6201
  [onOpenChange]
5657
6202
  );
5658
- const getActiveIcon = React16.useCallback(() => {
5659
- if (!editor) return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_icons20.HeadingIcon, {});
6203
+ const getActiveIcon = React19.useCallback(() => {
6204
+ if (!editor) return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_icons20.HeadingIcon, {});
5660
6205
  const activeLevel = levels.find(
5661
6206
  (level) => editor.isActive("heading", { level })
5662
6207
  );
5663
- if (!activeLevel) return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_icons20.HeadingIcon, {});
6208
+ if (!activeLevel) return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_icons20.HeadingIcon, {});
5664
6209
  const ActiveIcon = headingIcons[activeLevel];
5665
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ActiveIcon, {});
6210
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ActiveIcon, {});
5666
6211
  }, [editor, levels]);
5667
- const canToggleAnyHeading = React16.useCallback(() => {
6212
+ const canToggleAnyHeading = React19.useCallback(() => {
5668
6213
  if (!editor) return false;
5669
6214
  return levels.some(
5670
6215
  (level) => editor.can().toggleNode("heading", "paragraph", { level })
@@ -5672,12 +6217,12 @@ function HeadingDropdownMenu({
5672
6217
  }, [editor, levels]);
5673
6218
  const isDisabled = !canToggleAnyHeading();
5674
6219
  const isAnyHeadingActive = (_a = editor == null ? void 0 : editor.isActive("heading")) != null ? _a : false;
5675
- const show = React16.useMemo(() => {
6220
+ const show = React19.useMemo(() => {
5676
6221
  if (!headingInSchema || !editor) {
5677
6222
  return false;
5678
6223
  }
5679
6224
  if (hideWhenUnavailable) {
5680
- if ((0, import_react43.isNodeSelection)(editor.state.selection) || !canToggleAnyHeading()) {
6225
+ if ((0, import_react45.isNodeSelection)(editor.state.selection) || !canToggleAnyHeading()) {
5681
6226
  return false;
5682
6227
  }
5683
6228
  }
@@ -5686,9 +6231,9 @@ function HeadingDropdownMenu({
5686
6231
  if (!show || !editor || !editor.isEditable) {
5687
6232
  return null;
5688
6233
  }
5689
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_dropdown_menu.DropdownMenu.Root, { open: isOpen, onOpenChange: handleOnOpenChange, children: [
5690
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_dropdown_menu.DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
5691
- import_button12.Button,
6234
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_dropdown_menu.DropdownMenu.Root, { open: isOpen, onOpenChange: handleOnOpenChange, children: [
6235
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_dropdown_menu.DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6236
+ import_button13.Button,
5692
6237
  {
5693
6238
  type: "button",
5694
6239
  disabled: isDisabled,
@@ -5700,12 +6245,12 @@ function HeadingDropdownMenu({
5700
6245
  "aria-label": "Format text as heading",
5701
6246
  "aria-pressed": isAnyHeadingActive,
5702
6247
  tooltip: "Heading",
5703
- endContent: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_icons20.ChevronDownIcon, {}),
6248
+ endContent: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_icons20.ChevronDownIcon, {}),
5704
6249
  ...props,
5705
6250
  children: getActiveIcon()
5706
6251
  }
5707
6252
  ) }),
5708
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_dropdown_menu.DropdownMenu.Content, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_dropdown_menu.DropdownMenu.Group, { children: levels.map((level) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_dropdown_menu.DropdownMenu.Item, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6253
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_dropdown_menu.DropdownMenu.Content, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_dropdown_menu.DropdownMenu.Group, { children: levels.map((level) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_dropdown_menu.DropdownMenu.Item, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5709
6254
  HeadingButton,
5710
6255
  {
5711
6256
  editor,
@@ -5720,20 +6265,20 @@ function HeadingDropdownMenu({
5720
6265
  }
5721
6266
 
5722
6267
  // src/ui/list-dropdown-menu/index.tsx
5723
- var import_button14 = require("@kopexa/button");
6268
+ var import_button15 = require("@kopexa/button");
5724
6269
  var import_dropdown_menu2 = require("@kopexa/dropdown-menu");
5725
- var import_editor_utils13 = require("@kopexa/editor-utils");
6270
+ var import_editor_utils14 = require("@kopexa/editor-utils");
5726
6271
  var import_icons22 = require("@kopexa/icons");
5727
- var import_react46 = require("@tiptap/react");
5728
- var import_react47 = require("react");
6272
+ var import_react48 = require("@tiptap/react");
6273
+ var import_react49 = require("react");
5729
6274
 
5730
6275
  // src/ui/list-button/index.tsx
5731
- var import_button13 = require("@kopexa/button");
5732
- var import_editor_utils12 = require("@kopexa/editor-utils");
6276
+ var import_button14 = require("@kopexa/button");
6277
+ var import_editor_utils13 = require("@kopexa/editor-utils");
5733
6278
  var import_icons21 = require("@kopexa/icons");
5734
- var import_react44 = require("@tiptap/react");
5735
- var import_react45 = require("react");
5736
- var import_jsx_runtime22 = require("react/jsx-runtime");
6279
+ var import_react46 = require("@tiptap/react");
6280
+ var import_react47 = require("react");
6281
+ var import_jsx_runtime26 = require("react/jsx-runtime");
5737
6282
  var listOptions = [
5738
6283
  {
5739
6284
  label: "Bullet List",
@@ -5807,14 +6352,14 @@ function shouldShowListButton(params) {
5807
6352
  return false;
5808
6353
  }
5809
6354
  if (hideWhenUnavailable) {
5810
- if ((0, import_react44.isNodeSelection)(editor.state.selection) || !canToggleList(editor, type)) {
6355
+ if ((0, import_react46.isNodeSelection)(editor.state.selection) || !canToggleList(editor, type)) {
5811
6356
  return false;
5812
6357
  }
5813
6358
  }
5814
6359
  return true;
5815
6360
  }
5816
6361
  function useListState(editor, type) {
5817
- const listInSchema = (0, import_editor_utils12.isNodeInSchema)(type, editor);
6362
+ const listInSchema = (0, import_editor_utils13.isNodeInSchema)(type, editor);
5818
6363
  const listOption = getListOption(type);
5819
6364
  const isActive = isListActive(editor, type);
5820
6365
  const shortcutKey = listShortcutKeys[type];
@@ -5842,7 +6387,7 @@ var ListButton = ({
5842
6387
  type
5843
6388
  );
5844
6389
  const Icon = (listOption == null ? void 0 : listOption.icon) || import_icons21.ListIcon;
5845
- const handleClick = (0, import_react45.useCallback)(
6390
+ const handleClick = (0, import_react47.useCallback)(
5846
6391
  (e) => {
5847
6392
  onClick == null ? void 0 : onClick(e);
5848
6393
  if (!e.defaultPrevented && editor) {
@@ -5851,7 +6396,7 @@ var ListButton = ({
5851
6396
  },
5852
6397
  [onClick, editor, type]
5853
6398
  );
5854
- const show = (0, import_react45.useMemo)(() => {
6399
+ const show = (0, import_react47.useMemo)(() => {
5855
6400
  return shouldShowListButton({
5856
6401
  editor,
5857
6402
  type,
@@ -5862,8 +6407,8 @@ var ListButton = ({
5862
6407
  if (!show || !editor || !editor.isEditable) {
5863
6408
  return null;
5864
6409
  }
5865
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5866
- import_button13.Button,
6410
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6411
+ import_button14.Button,
5867
6412
  {
5868
6413
  type: "button",
5869
6414
  className: className.trim(),
@@ -5876,7 +6421,7 @@ var ListButton = ({
5876
6421
  tooltip: (listOption == null ? void 0 : listOption.label) || type,
5877
6422
  shortcutKeys: shortcutKey,
5878
6423
  onClick: handleClick,
5879
- startContent: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Icon, {}),
6424
+ startContent: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Icon, {}),
5880
6425
  ...buttonProps,
5881
6426
  ref,
5882
6427
  children: children || text
@@ -5885,7 +6430,7 @@ var ListButton = ({
5885
6430
  };
5886
6431
 
5887
6432
  // src/ui/list-dropdown-menu/index.tsx
5888
- var import_jsx_runtime23 = require("react/jsx-runtime");
6433
+ var import_jsx_runtime27 = require("react/jsx-runtime");
5889
6434
  function canToggleAnyList(editor, listTypes) {
5890
6435
  if (!editor) return false;
5891
6436
  return listTypes.some((type) => canToggleList(editor, type));
@@ -5905,24 +6450,24 @@ function shouldShowListDropdown(params) {
5905
6450
  return false;
5906
6451
  }
5907
6452
  if (hideWhenUnavailable) {
5908
- if ((0, import_react46.isNodeSelection)(editor.state.selection) || !canToggleAny) {
6453
+ if ((0, import_react48.isNodeSelection)(editor.state.selection) || !canToggleAny) {
5909
6454
  return false;
5910
6455
  }
5911
6456
  }
5912
6457
  return true;
5913
6458
  }
5914
6459
  function useListDropdownState(editor, availableTypes) {
5915
- const [isOpen, setIsOpen] = (0, import_react47.useState)(false);
6460
+ const [isOpen, setIsOpen] = (0, import_react49.useState)(false);
5916
6461
  const listInSchema = availableTypes.some(
5917
- (type) => (0, import_editor_utils13.isNodeInSchema)(type, editor)
6462
+ (type) => (0, import_editor_utils14.isNodeInSchema)(type, editor)
5918
6463
  );
5919
- const filteredLists = (0, import_react47.useMemo)(
6464
+ const filteredLists = (0, import_react49.useMemo)(
5920
6465
  () => getFilteredListOptions(availableTypes),
5921
6466
  [availableTypes]
5922
6467
  );
5923
6468
  const canToggleAny = canToggleAnyList(editor, availableTypes);
5924
6469
  const isAnyActive = isAnyListActive(editor, availableTypes);
5925
- const handleOpenChange = (0, import_react47.useCallback)(
6470
+ const handleOpenChange = (0, import_react49.useCallback)(
5926
6471
  (open, callback) => {
5927
6472
  setIsOpen(open);
5928
6473
  callback == null ? void 0 : callback(open);
@@ -5940,11 +6485,11 @@ function useListDropdownState(editor, availableTypes) {
5940
6485
  };
5941
6486
  }
5942
6487
  function useActiveListIcon(editor, filteredLists) {
5943
- return (0, import_react47.useCallback)(() => {
6488
+ return (0, import_react49.useCallback)(() => {
5944
6489
  const activeOption = filteredLists.find(
5945
6490
  (option) => isListActive(editor, option.type)
5946
6491
  );
5947
- return activeOption ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(activeOption.icon, {}) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_icons22.ListIcon, {});
6492
+ return activeOption ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(activeOption.icon, {}) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_icons22.ListIcon, {});
5948
6493
  }, [editor, filteredLists]);
5949
6494
  }
5950
6495
  function ListDropdownMenu({
@@ -5964,7 +6509,7 @@ function ListDropdownMenu({
5964
6509
  handleOpenChange
5965
6510
  } = useListDropdownState(editor, types);
5966
6511
  const getActiveIcon = useActiveListIcon(editor, filteredLists);
5967
- const show = (0, import_react47.useMemo)(() => {
6512
+ const show = (0, import_react49.useMemo)(() => {
5968
6513
  return shouldShowListDropdown({
5969
6514
  editor,
5970
6515
  listTypes: types,
@@ -5973,16 +6518,16 @@ function ListDropdownMenu({
5973
6518
  canToggleAny
5974
6519
  });
5975
6520
  }, [editor, types, hideWhenUnavailable, listInSchema, canToggleAny]);
5976
- const handleOnOpenChange = (0, import_react47.useCallback)(
6521
+ const handleOnOpenChange = (0, import_react49.useCallback)(
5977
6522
  (open) => handleOpenChange(open, onOpenChange),
5978
6523
  [handleOpenChange, onOpenChange]
5979
6524
  );
5980
6525
  if (!show || !editor || !editor.isEditable) {
5981
6526
  return null;
5982
6527
  }
5983
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_dropdown_menu2.DropdownMenu.Root, { open: isOpen, onOpenChange: handleOnOpenChange, children: [
5984
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_dropdown_menu2.DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5985
- import_button14.Button,
6528
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_dropdown_menu2.DropdownMenu.Root, { open: isOpen, onOpenChange: handleOnOpenChange, children: [
6529
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_dropdown_menu2.DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6530
+ import_button15.Button,
5986
6531
  {
5987
6532
  type: "button",
5988
6533
  variant: "ghost",
@@ -5991,12 +6536,12 @@ function ListDropdownMenu({
5991
6536
  tabIndex: -1,
5992
6537
  "aria-label": "List options",
5993
6538
  tooltip: "List",
5994
- endContent: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_icons22.ChevronDownIcon, {}),
6539
+ endContent: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_icons22.ChevronDownIcon, {}),
5995
6540
  ...props,
5996
6541
  children: getActiveIcon()
5997
6542
  }
5998
6543
  ) }),
5999
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_dropdown_menu2.DropdownMenu.Content, { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_dropdown_menu2.DropdownMenu.Group, { children: filteredLists.map((option) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_dropdown_menu2.DropdownMenu.Item, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6544
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_dropdown_menu2.DropdownMenu.Content, { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_dropdown_menu2.DropdownMenu.Group, { children: filteredLists.map((option) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_dropdown_menu2.DropdownMenu.Item, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6000
6545
  ListButton,
6001
6546
  {
6002
6547
  editor,
@@ -6013,8 +6558,8 @@ function ListDropdownMenu({
6013
6558
 
6014
6559
  // src/ui/table-button/index.tsx
6015
6560
  var import_toolbar8 = require("@kopexa/toolbar");
6016
- var import_react48 = require("react");
6017
- var import_jsx_runtime24 = require("react/jsx-runtime");
6561
+ var import_react50 = require("react");
6562
+ var import_jsx_runtime28 = require("react/jsx-runtime");
6018
6563
  var TableButton = ({
6019
6564
  editor: providedEditor,
6020
6565
  text,
@@ -6038,7 +6583,7 @@ var TableButton = ({
6038
6583
  hideWhenUnavailable,
6039
6584
  onToggled
6040
6585
  });
6041
- const handleClick = (0, import_react48.useCallback)(
6586
+ const handleClick = (0, import_react50.useCallback)(
6042
6587
  (event) => {
6043
6588
  onClick == null ? void 0 : onClick(event);
6044
6589
  if (event.defaultPrevented) return;
@@ -6049,7 +6594,7 @@ var TableButton = ({
6049
6594
  if (!isVisible) {
6050
6595
  return null;
6051
6596
  }
6052
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6597
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
6053
6598
  import_toolbar8.ToolbarButton,
6054
6599
  {
6055
6600
  type: "button",
@@ -6065,22 +6610,22 @@ var TableButton = ({
6065
6610
  onClick: handleClick,
6066
6611
  isIconOnly: !text && !children,
6067
6612
  ...buttonProps,
6068
- children: children || /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
6069
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Icon, {}),
6070
- text && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: text })
6613
+ children: children || /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
6614
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Icon, {}),
6615
+ text && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { children: text })
6071
6616
  ] })
6072
6617
  }
6073
6618
  );
6074
6619
  };
6075
6620
 
6076
6621
  // src/ui/text-align-button/text-align-button.tsx
6077
- var import_button15 = require("@kopexa/button");
6078
- var import_react50 = require("react");
6622
+ var import_button16 = require("@kopexa/button");
6623
+ var import_react52 = require("react");
6079
6624
 
6080
6625
  // src/ui/text-align-button/use-text-align.ts
6081
- var import_editor_utils14 = require("@kopexa/editor-utils");
6626
+ var import_editor_utils15 = require("@kopexa/editor-utils");
6082
6627
  var import_icons23 = require("@kopexa/icons");
6083
- var import_react49 = require("react");
6628
+ var import_react51 = require("react");
6084
6629
  var TEXT_ALIGN_SHORTCUT_KEYS = {
6085
6630
  left: "mod+shift+l",
6086
6631
  center: "mod+shift+e",
@@ -6101,7 +6646,7 @@ var textAlignLabels = {
6101
6646
  };
6102
6647
  function canSetTextAlign(editor, align) {
6103
6648
  if (!editor || !editor.isEditable) return false;
6104
- if (!(0, import_editor_utils14.isExtensionAvailable)(editor, "textAlign") || (0, import_editor_utils14.isNodeTypeSelected)(editor, ["image"]))
6649
+ if (!(0, import_editor_utils15.isExtensionAvailable)(editor, "textAlign") || (0, import_editor_utils15.isNodeTypeSelected)(editor, ["image"]))
6105
6650
  return false;
6106
6651
  return editor.can().setTextAlign(align);
6107
6652
  }
@@ -6124,7 +6669,7 @@ function setTextAlign(editor, align) {
6124
6669
  function shouldShowButton5(props) {
6125
6670
  const { editor, hideWhenUnavailable, align } = props;
6126
6671
  if (!editor || !editor.isEditable) return false;
6127
- if (!(0, import_editor_utils14.isExtensionAvailable)(editor, "textAlign")) return false;
6672
+ if (!(0, import_editor_utils15.isExtensionAvailable)(editor, "textAlign")) return false;
6128
6673
  if (hideWhenUnavailable && !editor.isActive("code")) {
6129
6674
  return canSetTextAlign(editor, align);
6130
6675
  }
@@ -6138,10 +6683,10 @@ function useTextAlign(config) {
6138
6683
  onAligned
6139
6684
  } = config;
6140
6685
  const { editor } = useTiptapEditor(providedEditor);
6141
- const [isVisible, setIsVisible] = (0, import_react49.useState)(true);
6686
+ const [isVisible, setIsVisible] = (0, import_react51.useState)(true);
6142
6687
  const canAlign = canSetTextAlign(editor, align);
6143
6688
  const isActive = isTextAlignActive(editor, align);
6144
- (0, import_react49.useEffect)(() => {
6689
+ (0, import_react51.useEffect)(() => {
6145
6690
  if (!editor) return;
6146
6691
  const handleSelectionUpdate = () => {
6147
6692
  setIsVisible(shouldShowButton5({ editor, align, hideWhenUnavailable }));
@@ -6152,7 +6697,7 @@ function useTextAlign(config) {
6152
6697
  editor.off("selectionUpdate", handleSelectionUpdate);
6153
6698
  };
6154
6699
  }, [editor, hideWhenUnavailable, align]);
6155
- const handleTextAlign = (0, import_react49.useCallback)(() => {
6700
+ const handleTextAlign = (0, import_react51.useCallback)(() => {
6156
6701
  if (!editor) return false;
6157
6702
  const success = setTextAlign(editor, align);
6158
6703
  if (success) {
@@ -6172,7 +6717,7 @@ function useTextAlign(config) {
6172
6717
  }
6173
6718
 
6174
6719
  // src/ui/text-align-button/text-align-button.tsx
6175
- var import_jsx_runtime25 = require("react/jsx-runtime");
6720
+ var import_jsx_runtime29 = require("react/jsx-runtime");
6176
6721
  var TextAlignButton = ({
6177
6722
  editor: providedEditor,
6178
6723
  align,
@@ -6199,7 +6744,7 @@ var TextAlignButton = ({
6199
6744
  hideWhenUnavailable,
6200
6745
  onAligned
6201
6746
  });
6202
- const handleClick = (0, import_react50.useCallback)(
6747
+ const handleClick = (0, import_react52.useCallback)(
6203
6748
  (e) => {
6204
6749
  onClick == null ? void 0 : onClick(e);
6205
6750
  if (e.defaultPrevented) return;
@@ -6210,8 +6755,8 @@ var TextAlignButton = ({
6210
6755
  if (!isVisible) {
6211
6756
  return null;
6212
6757
  }
6213
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6214
- import_button15.IconButton,
6758
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6759
+ import_button16.IconButton,
6215
6760
  {
6216
6761
  type: "button",
6217
6762
  disabled: canAlign,
@@ -6226,19 +6771,19 @@ var TextAlignButton = ({
6226
6771
  shortcutKeys,
6227
6772
  onClick: handleClick,
6228
6773
  ...buttonProps,
6229
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Icon, {})
6774
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Icon, {})
6230
6775
  }
6231
6776
  );
6232
6777
  };
6233
6778
 
6234
6779
  // src/ui/undo-redo-button/undo-redo-button.tsx
6235
6780
  var import_toolbar9 = require("@kopexa/toolbar");
6236
- var import_react52 = require("react");
6781
+ var import_react54 = require("react");
6237
6782
 
6238
6783
  // src/ui/undo-redo-button/use-undo-redo.ts
6239
- var import_editor_utils15 = require("@kopexa/editor-utils");
6784
+ var import_editor_utils16 = require("@kopexa/editor-utils");
6240
6785
  var import_icons24 = require("@kopexa/icons");
6241
- var import_react51 = require("react");
6786
+ var import_react53 = require("react");
6242
6787
  var UNDO_REDO_SHORTCUT_KEYS = {
6243
6788
  undo: "mod+z",
6244
6789
  redo: "mod+shift+z"
@@ -6253,7 +6798,7 @@ var historyIcons = {
6253
6798
  };
6254
6799
  function canExecuteUndoRedoAction(editor, action) {
6255
6800
  if (!editor || !editor.isEditable) return false;
6256
- if ((0, import_editor_utils15.isNodeTypeSelected)(editor, ["image"])) return false;
6801
+ if ((0, import_editor_utils16.isNodeTypeSelected)(editor, ["image"])) return false;
6257
6802
  return action === "undo" ? editor.can().undo() : editor.can().redo();
6258
6803
  }
6259
6804
  function executeUndoRedoAction(editor, action) {
@@ -6278,9 +6823,9 @@ function useUndoRedo(config) {
6278
6823
  onExecuted
6279
6824
  } = config;
6280
6825
  const { editor } = useTiptapEditor(providedEditor);
6281
- const [isVisible, setIsVisible] = (0, import_react51.useState)(true);
6826
+ const [isVisible, setIsVisible] = (0, import_react53.useState)(true);
6282
6827
  const canExecute = canExecuteUndoRedoAction(editor, action);
6283
- (0, import_react51.useEffect)(() => {
6828
+ (0, import_react53.useEffect)(() => {
6284
6829
  if (!editor) return;
6285
6830
  const handleUpdate = () => {
6286
6831
  setIsVisible(shouldShowButton6({ editor, hideWhenUnavailable, action }));
@@ -6291,7 +6836,7 @@ function useUndoRedo(config) {
6291
6836
  editor.off("transaction", handleUpdate);
6292
6837
  };
6293
6838
  }, [editor, hideWhenUnavailable, action]);
6294
- const handleAction = (0, import_react51.useCallback)(() => {
6839
+ const handleAction = (0, import_react53.useCallback)(() => {
6295
6840
  if (!editor) return false;
6296
6841
  const success = executeUndoRedoAction(editor, action);
6297
6842
  if (success) {
@@ -6310,7 +6855,7 @@ function useUndoRedo(config) {
6310
6855
  }
6311
6856
 
6312
6857
  // src/ui/undo-redo-button/undo-redo-button.tsx
6313
- var import_jsx_runtime26 = require("react/jsx-runtime");
6858
+ var import_jsx_runtime30 = require("react/jsx-runtime");
6314
6859
  var UndoRedoButton = ({
6315
6860
  editor: providedEditor,
6316
6861
  action,
@@ -6329,7 +6874,7 @@ var UndoRedoButton = ({
6329
6874
  hideWhenUnavailable,
6330
6875
  onExecuted
6331
6876
  });
6332
- const handleClick = (0, import_react52.useCallback)(
6877
+ const handleClick = (0, import_react54.useCallback)(
6333
6878
  (event) => {
6334
6879
  onClick == null ? void 0 : onClick(event);
6335
6880
  if (event.defaultPrevented) return;
@@ -6340,7 +6885,7 @@ var UndoRedoButton = ({
6340
6885
  if (!isVisible) {
6341
6886
  return null;
6342
6887
  }
6343
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6888
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6344
6889
  import_toolbar9.ToolbarButton,
6345
6890
  {
6346
6891
  type: "button",
@@ -6355,13 +6900,13 @@ var UndoRedoButton = ({
6355
6900
  onClick: handleClick,
6356
6901
  isIconOnly: true,
6357
6902
  ...buttonProps,
6358
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Icon, {})
6903
+ children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Icon, {})
6359
6904
  }
6360
6905
  );
6361
6906
  };
6362
6907
 
6363
6908
  // src/presets/basic/editor-header.tsx
6364
- var import_jsx_runtime27 = require("react/jsx-runtime");
6909
+ var import_jsx_runtime31 = require("react/jsx-runtime");
6365
6910
  var EditorHeader = ({
6366
6911
  editor: providedEditor,
6367
6912
  variant
@@ -6371,7 +6916,7 @@ var EditorHeader = ({
6371
6916
  const isMobile = (0, import_use_is_mobile2.useIsMobile)();
6372
6917
  const windowSize = useWindowSize();
6373
6918
  const { styles } = useEditorUIContext();
6374
- const toolbarRef = (0, import_react53.useRef)(null);
6919
+ const toolbarRef = (0, import_react55.useRef)(null);
6375
6920
  const bodyRect = useCursorVisibility({
6376
6921
  editor,
6377
6922
  overlayHeight: (_b = (_a = toolbarRef.current) == null ? void 0 : _a.getBoundingClientRect().height) != null ? _b : 0
@@ -6380,7 +6925,7 @@ var EditorHeader = ({
6380
6925
  return null;
6381
6926
  }
6382
6927
  const ToolbarContent = variant === "comment" ? CommentToolbarContent : variant === "field" ? FieldToolbarContent : MainToolbarContent;
6383
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: styles.toolbarContainer(), "data-slot": "editor-toolbar", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6928
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: styles.toolbarContainer(), "data-slot": "editor-toolbar", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6384
6929
  import_toolbar10.Toolbar,
6385
6930
  {
6386
6931
  sticky: true,
@@ -6390,54 +6935,54 @@ var EditorHeader = ({
6390
6935
  bottom: `calc(100% - ${windowSize.height - bodyRect.y}px)`
6391
6936
  } : {},
6392
6937
  className: styles.toolbar(),
6393
- children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ToolbarContent, {})
6938
+ children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(ToolbarContent, {})
6394
6939
  }
6395
6940
  ) });
6396
6941
  };
6397
- var MainToolbarContent = () => /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
6398
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_toolbar10.ToolbarGroup, { children: [
6399
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(UndoRedoButton, { action: "undo" }),
6400
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(UndoRedoButton, { action: "redo" })
6942
+ var MainToolbarContent = () => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_jsx_runtime31.Fragment, { children: [
6943
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_toolbar10.ToolbarGroup, { children: [
6944
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(UndoRedoButton, { action: "undo" }),
6945
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(UndoRedoButton, { action: "redo" })
6401
6946
  ] }),
6402
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_toolbar10.ToolbarSeparator, {}),
6403
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_toolbar10.ToolbarGroup, { children: [
6404
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(HeadingDropdownMenu, { levels: [1, 2, 3, 4] }),
6405
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ListDropdownMenu, { types: ["bulletList", "orderedList", "taskList"] }),
6406
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(BlockquoteButton, {}),
6407
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(CodeBlockButton, {})
6947
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_toolbar10.ToolbarSeparator, {}),
6948
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_toolbar10.ToolbarGroup, { children: [
6949
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(HeadingDropdownMenu, { levels: [1, 2, 3, 4] }),
6950
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(ListDropdownMenu, { types: ["bulletList", "orderedList", "taskList"] }),
6951
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(BlockquoteButton, {}),
6952
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(CodeBlockButton, {})
6408
6953
  ] }),
6409
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_toolbar10.ToolbarSeparator, {}),
6410
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_toolbar10.ToolbarGroup, { children: [
6411
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MarkButton, { type: "bold" }),
6412
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MarkButton, { type: "italic" }),
6413
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MarkButton, { type: "strike" }),
6414
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MarkButton, { type: "code" }),
6415
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MarkButton, { type: "underline" }),
6416
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ColorHighlightPopover, {}),
6417
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(LinkPopover, {})
6954
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_toolbar10.ToolbarSeparator, {}),
6955
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_toolbar10.ToolbarGroup, { children: [
6956
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(MarkButton, { type: "bold" }),
6957
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(MarkButton, { type: "italic" }),
6958
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(MarkButton, { type: "strike" }),
6959
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(MarkButton, { type: "code" }),
6960
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(MarkButton, { type: "underline" }),
6961
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(ColorHighlightPopover, {}),
6962
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(LinkPopover, {})
6418
6963
  ] }),
6419
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_toolbar10.ToolbarSeparator, {}),
6420
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_toolbar10.ToolbarGroup, { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TableButton, {}) }),
6421
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MoreOptions, { hideWhenUnavailable: true })
6964
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_toolbar10.ToolbarSeparator, {}),
6965
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_toolbar10.ToolbarGroup, { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(TableButton, {}) }),
6966
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(MoreOptions, { hideWhenUnavailable: true })
6422
6967
  ] });
6423
- var CommentToolbarContent = () => /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
6424
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_toolbar10.ToolbarGroup, { children: [
6425
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MarkButton, { type: "bold" }),
6426
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MarkButton, { type: "italic" }),
6427
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MarkButton, { type: "strike" }),
6428
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MarkButton, { type: "code" })
6968
+ var CommentToolbarContent = () => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_jsx_runtime31.Fragment, { children: [
6969
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_toolbar10.ToolbarGroup, { children: [
6970
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(MarkButton, { type: "bold" }),
6971
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(MarkButton, { type: "italic" }),
6972
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(MarkButton, { type: "strike" }),
6973
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(MarkButton, { type: "code" })
6429
6974
  ] }),
6430
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_toolbar10.ToolbarSeparator, {}),
6431
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_toolbar10.ToolbarGroup, { children: [
6432
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(LinkPopover, {}),
6433
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ListDropdownMenu, { types: ["bulletList", "orderedList"] })
6975
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_toolbar10.ToolbarSeparator, {}),
6976
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_toolbar10.ToolbarGroup, { children: [
6977
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(LinkPopover, {}),
6978
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(ListDropdownMenu, { types: ["bulletList", "orderedList"] })
6434
6979
  ] })
6435
6980
  ] });
6436
- var FieldToolbarContent = () => /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_toolbar10.ToolbarGroup, { children: [
6437
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MarkButton, { type: "bold" }),
6438
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MarkButton, { type: "italic" }),
6439
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MarkButton, { type: "strike" }),
6440
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(LinkPopover, {})
6981
+ var FieldToolbarContent = () => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_toolbar10.ToolbarGroup, { children: [
6982
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(MarkButton, { type: "bold" }),
6983
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(MarkButton, { type: "italic" }),
6984
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(MarkButton, { type: "strike" }),
6985
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(LinkPopover, {})
6441
6986
  ] });
6442
6987
  function MoreOptions({
6443
6988
  editor: providedEditor,
@@ -6445,8 +6990,8 @@ function MoreOptions({
6445
6990
  ...props
6446
6991
  }) {
6447
6992
  const { editor } = useTiptapEditor(providedEditor);
6448
- const [show, setShow] = (0, import_react53.useState)(false);
6449
- (0, import_react53.useEffect)(() => {
6993
+ const [show, setShow] = (0, import_react55.useState)(false);
6994
+ (0, import_react55.useEffect)(() => {
6450
6995
  if (!editor) return;
6451
6996
  const handleSelectionUpdate = () => {
6452
6997
  setShow(
@@ -6465,13 +7010,13 @@ function MoreOptions({
6465
7010
  if (!show || !editor || !editor.isEditable) {
6466
7011
  return null;
6467
7012
  }
6468
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
6469
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_toolbar10.ToolbarSeparator, {}),
6470
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_toolbar10.ToolbarGroup, { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_popover3.Popover.Root, { spacing: "dense", width: "auto", children: [
6471
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
7013
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_jsx_runtime31.Fragment, { children: [
7014
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_toolbar10.ToolbarSeparator, {}),
7015
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_toolbar10.ToolbarGroup, { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_popover3.Popover.Root, { spacing: "dense", width: "auto", children: [
7016
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6472
7017
  import_popover3.Popover.Trigger,
6473
7018
  {
6474
- render: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
7019
+ render: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6475
7020
  import_toolbar10.ToolbarButton,
6476
7021
  {
6477
7022
  type: "button",
@@ -6483,29 +7028,29 @@ function MoreOptions({
6483
7028
  title: "More options",
6484
7029
  isIconOnly: true,
6485
7030
  ...props,
6486
- children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_icons25.MoreVerticalIcon, {})
7031
+ children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_icons25.MoreVerticalIcon, {})
6487
7032
  }
6488
7033
  )
6489
7034
  }
6490
7035
  ),
6491
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
7036
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6492
7037
  import_popover3.Popover.Content,
6493
7038
  {
6494
7039
  side: "top",
6495
7040
  align: "end",
6496
7041
  alignOffset: 4,
6497
7042
  sideOffset: 4,
6498
- children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_toolbar10.Toolbar, { children: [
6499
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_toolbar10.ToolbarGroup, { children: [
6500
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MarkButton, { type: "superscript" }),
6501
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MarkButton, { type: "subscript" })
7043
+ children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_toolbar10.Toolbar, { children: [
7044
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_toolbar10.ToolbarGroup, { children: [
7045
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(MarkButton, { type: "superscript" }),
7046
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(MarkButton, { type: "subscript" })
6502
7047
  ] }),
6503
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_toolbar10.ToolbarSeparator, {}),
6504
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_toolbar10.ToolbarGroup, { children: [
6505
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TextAlignButton, { align: "left" }),
6506
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TextAlignButton, { align: "center" }),
6507
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TextAlignButton, { align: "right" }),
6508
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TextAlignButton, { align: "justify" })
7048
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_toolbar10.ToolbarSeparator, {}),
7049
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_toolbar10.ToolbarGroup, { children: [
7050
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(TextAlignButton, { align: "left" }),
7051
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(TextAlignButton, { align: "center" }),
7052
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(TextAlignButton, { align: "right" }),
7053
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(TextAlignButton, { align: "justify" })
6509
7054
  ] })
6510
7055
  ] })
6511
7056
  }
@@ -6537,36 +7082,87 @@ function shouldShowMoreOptions(params) {
6537
7082
  }
6538
7083
 
6539
7084
  // src/presets/basic/index.tsx
6540
- var import_jsx_runtime28 = require("react/jsx-runtime");
7085
+ var import_jsx_runtime32 = require("react/jsx-runtime");
6541
7086
  var BasicEditor = ({
6542
7087
  variant,
6543
7088
  bordered,
6544
7089
  content,
7090
+ variables,
7091
+ variableValues,
6545
7092
  ...options
6546
7093
  }) => {
6547
- const editor = useCreateEditor({ content, ...options });
6548
- const styles = (0, import_theme7.editorBasic)({ variant, bordered });
7094
+ const editor = useCreateEditor({
7095
+ content,
7096
+ enableVariables: !!(variables == null ? void 0 : variables.length),
7097
+ ...options
7098
+ });
7099
+ const styles = (0, import_theme9.editorBasic)({ variant, bordered });
7100
+ const resolveVariable = (0, import_react57.useCallback)(
7101
+ (name) => variableValues == null ? void 0 : variableValues[name],
7102
+ [variableValues]
7103
+ );
6549
7104
  if (!editor) {
6550
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(LoadingSpinner, {});
7105
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(LoadingSpinner, {});
6551
7106
  }
6552
7107
  const isBottomToolbar = variant === "field";
6553
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(EditorUIProvider, { value: { styles }, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: styles.root(), "data-slot": "editor", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_react54.EditorContext.Provider, { value: { editor }, children: [
6554
- !isBottomToolbar && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(EditorHeader, { editor, variant }),
6555
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(EditorContentArea, { variant }),
6556
- isBottomToolbar && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(EditorHeader, { editor, variant })
7108
+ const hasVariables = variables && variables.length > 0;
7109
+ const editorContent = /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(EditorUIProvider, { value: { styles }, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: styles.root(), "data-slot": "editor", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_react56.EditorContext.Provider, { value: { editor }, children: [
7110
+ !isBottomToolbar && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(EditorHeader, { editor, variant }),
7111
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(EditorContentArea, { variant, variables }),
7112
+ isBottomToolbar && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(EditorHeader, { editor, variant })
6557
7113
  ] }) }) });
7114
+ if (hasVariables) {
7115
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VariableProvider, { variables, resolveVariable, children: editorContent });
7116
+ }
7117
+ return editorContent;
6558
7118
  };
6559
- var EditorContentArea = ({ variant }) => {
6560
- const styles = (0, import_theme7.editorBasic)({ variant });
6561
- const { editor } = (0, import_react55.useContext)(import_react54.EditorContext);
7119
+ var EditorContentArea = ({ variant, variables }) => {
7120
+ const styles = (0, import_theme9.editorBasic)({ variant });
7121
+ const { editor } = (0, import_react57.useContext)(import_react56.EditorContext);
6562
7122
  const { isDragging } = useUiEditorState(editor);
6563
7123
  useScrollToHash();
7124
+ const handleKeyDown = (0, import_react57.useCallback)(
7125
+ (e) => {
7126
+ if (!(editor == null ? void 0 : editor.isFocused)) return;
7127
+ const isMod = e.metaKey || e.ctrlKey;
7128
+ const key = e.key.toLowerCase();
7129
+ const editorShortcuts = [
7130
+ isMod && key === "b",
7131
+ // Bold
7132
+ isMod && key === "i",
7133
+ // Italic
7134
+ isMod && key === "u",
7135
+ // Underline
7136
+ isMod && e.shiftKey && key === "x",
7137
+ // Strikethrough
7138
+ isMod && key === "k",
7139
+ // Link
7140
+ isMod && key === "z",
7141
+ // Undo
7142
+ isMod && e.shiftKey && key === "z",
7143
+ // Redo
7144
+ isMod && key === "y",
7145
+ // Redo (alternative)
7146
+ isMod && key === "a",
7147
+ // Select all
7148
+ isMod && key === "e",
7149
+ // Code
7150
+ isMod && e.shiftKey && key === "e"
7151
+ // Code block
7152
+ ];
7153
+ if (editorShortcuts.some(Boolean)) {
7154
+ e.stopPropagation();
7155
+ }
7156
+ },
7157
+ [editor]
7158
+ );
6564
7159
  if (!editor) {
6565
7160
  return null;
6566
7161
  }
6567
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: styles.wrapper(), children: [
6568
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
6569
- import_react54.EditorContent,
7162
+ const isEditable = editor.isEditable;
7163
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: styles.wrapper(), onKeyDown: handleKeyDown, children: [
7164
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
7165
+ import_react56.EditorContent,
6570
7166
  {
6571
7167
  editor,
6572
7168
  role: "presentation",
@@ -6574,17 +7170,20 @@ var EditorContentArea = ({ variant }) => {
6574
7170
  style: {
6575
7171
  cursor: isDragging ? "grabbing" : "auto"
6576
7172
  },
6577
- children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(SlashDropdownMenu, {})
7173
+ children: [
7174
+ isEditable && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(SlashDropdownMenu, {}),
7175
+ isEditable && variables && variables.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VariableSuggestion, { editor, variables })
7176
+ ]
6578
7177
  }
6579
7178
  ),
6580
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(BubbleMenu, { editor }),
6581
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(LinkBubble, { editor })
7179
+ isEditable && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(BubbleMenu, { editor }),
7180
+ isEditable && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(LinkBubble, { editor })
6582
7181
  ] });
6583
7182
  };
6584
7183
  function LoadingSpinner({ text = "Connecting..." }) {
6585
- const styles = (0, import_theme7.editorSpinner)();
6586
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: styles.root(), children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: styles.content(), children: [
6587
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
7184
+ const styles = (0, import_theme9.editorSpinner)();
7185
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: styles.root(), children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: styles.content(), children: [
7186
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
6588
7187
  "svg",
6589
7188
  {
6590
7189
  className: styles.svg(),
@@ -6592,9 +7191,9 @@ function LoadingSpinner({ text = "Connecting..." }) {
6592
7191
  fill: "none",
6593
7192
  viewBox: "0 0 24 24",
6594
7193
  children: [
6595
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("title", { children: "Loading Spinner" }),
6596
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("circle", { className: styles.circle(), cx: "12", cy: "12", r: "10" }),
6597
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7194
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("title", { children: "Loading Spinner" }),
7195
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("circle", { className: styles.circle(), cx: "12", cy: "12", r: "10" }),
7196
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6598
7197
  "path",
6599
7198
  {
6600
7199
  className: styles.path(),
@@ -6604,7 +7203,7 @@ function LoadingSpinner({ text = "Connecting..." }) {
6604
7203
  ]
6605
7204
  }
6606
7205
  ),
6607
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: styles.text(), children: text })
7206
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: styles.text(), children: text })
6608
7207
  ] }) });
6609
7208
  }
6610
7209
  // Annotate the CommonJS export names for ESM import in node:
@@ -6617,11 +7216,18 @@ function LoadingSpinner({ text = "Connecting..." }) {
6617
7216
  InlineMath,
6618
7217
  MathBlock,
6619
7218
  TocNode,
7219
+ VariableFillerDialog,
7220
+ VariableNode,
7221
+ VariableProvider,
7222
+ VariableSuggestion,
6620
7223
  convertFileToBase64,
7224
+ extractVariablesFromContent,
6621
7225
  getExtensions,
6622
7226
  handleImageUpload,
6623
7227
  isAllowedUri,
6624
7228
  sanitizeUrl,
6625
7229
  useEditorFile,
6626
- useEditorFileRequired
7230
+ useEditorFileRequired,
7231
+ useVariables,
7232
+ useVariablesWithFallback
6627
7233
  });