@kopexa/tiptap 17.7.2 → 17.8.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 (3) hide show
  1. package/dist/index.js +1650 -1217
  2. package/dist/index.mjs +1654 -1214
  3. package/package.json +24 -24
package/dist/index.js CHANGED
@@ -1023,7 +1023,7 @@ var ImageNode = import_extension_image.Image.extend({
1023
1023
  return (0, import_react11.ReactNodeViewRenderer)(ImageNodeView, {
1024
1024
  stopEvent: ({ event }) => {
1025
1025
  const target = event.target;
1026
- if (target.closest("button, [role='button'], input, a")) {
1026
+ if (target instanceof HTMLElement && target.closest("button, [role='button'], input, a")) {
1027
1027
  return true;
1028
1028
  }
1029
1029
  return false;
@@ -1374,7 +1374,7 @@ var ImageUploadNode = import_core2.Node.create({
1374
1374
  return (0, import_react14.ReactNodeViewRenderer)(ImageUploadNodeView, {
1375
1375
  stopEvent: ({ event }) => {
1376
1376
  const target = event.target;
1377
- if (target.closest("button, [role='button'], input, a")) {
1377
+ if (target instanceof HTMLElement && target.closest("button, [role='button'], input, a")) {
1378
1378
  return true;
1379
1379
  }
1380
1380
  return false;
@@ -4267,8 +4267,8 @@ async function handleFileUpload(editor, file, fileHandler, pos) {
4267
4267
  // src/presets/basic/index.tsx
4268
4268
  var import_extension_table2 = require("@kopexa/extension-table");
4269
4269
  var import_theme9 = require("@kopexa/theme");
4270
- var import_react57 = require("@tiptap/react");
4271
- var import_react58 = require("react");
4270
+ var import_react60 = require("@tiptap/react");
4271
+ var import_react61 = require("react");
4272
4272
 
4273
4273
  // src/context/editor-context.ts
4274
4274
  var import_react_utils = require("@kopexa/react-utils");
@@ -5818,12 +5818,12 @@ var List = ({
5818
5818
  };
5819
5819
 
5820
5820
  // src/presets/basic/editor-header.tsx
5821
- var import_editor_utils28 = require("@kopexa/editor-utils");
5822
- var import_icons25 = require("@kopexa/icons");
5821
+ var import_editor_utils31 = require("@kopexa/editor-utils");
5822
+ var import_icons26 = require("@kopexa/icons");
5823
5823
  var import_popover3 = require("@kopexa/popover");
5824
5824
  var import_toolbar10 = require("@kopexa/toolbar");
5825
- var import_use_is_mobile2 = require("@kopexa/use-is-mobile");
5826
- var import_react56 = require("react");
5825
+ var import_use_is_mobile3 = require("@kopexa/use-is-mobile");
5826
+ var import_react59 = require("react");
5827
5827
 
5828
5828
  // src/hooks/use-cursor-visibility.ts
5829
5829
  var React13 = __toESM(require("react"));
@@ -5927,95 +5927,122 @@ function useCursorVisibility({
5927
5927
  return rect;
5928
5928
  }
5929
5929
 
5930
- // src/ui/blockquote-button/blockquote-button.tsx
5930
+ // src/ui/color-highlight-popover/color-highlight-popover.tsx
5931
+ var import_button11 = require("@kopexa/button");
5932
+ var import_editor_utils14 = require("@kopexa/editor-utils");
5933
+ var import_icons15 = require("@kopexa/icons");
5934
+ var import_popover2 = require("@kopexa/popover");
5935
+ var import_toolbar5 = require("@kopexa/toolbar");
5936
+ var import_react43 = require("react");
5937
+
5938
+ // src/ui/color-highlight-button/color-highlight-button.tsx
5931
5939
  var import_editor_utils13 = require("@kopexa/editor-utils");
5940
+ var import_theme8 = require("@kopexa/theme");
5932
5941
  var import_toolbar4 = require("@kopexa/toolbar");
5933
- var React15 = __toESM(require("react"));
5942
+ var import_react42 = require("react");
5934
5943
 
5935
- // src/ui/blockquote-button/use-blockquote.ts
5944
+ // src/ui/color-highlight-button/use-color-highlight.ts
5936
5945
  var import_editor_utils12 = require("@kopexa/editor-utils");
5937
5946
  var import_icons14 = require("@kopexa/icons");
5938
- var import_state7 = require("@tiptap/pm/state");
5947
+ var import_use_is_mobile = require("@kopexa/use-is-mobile");
5939
5948
  var React14 = __toESM(require("react"));
5940
- var BLOCKQUOTE_SHORTCUT_KEY = "mod+shift+b";
5941
- function canToggleBlockquote(editor, turnInto = true) {
5942
- var _a;
5943
- if (!editor || !editor.isEditable) return false;
5944
- if (!(0, import_editor_utils12.isNodeInSchema)("blockquote", editor) || (0, import_editor_utils12.isNodeTypeSelected)(editor, ["image"]))
5945
- return false;
5946
- if (!turnInto) {
5947
- return editor.can().toggleWrap("blockquote");
5948
- }
5949
- try {
5950
- const view = editor.view;
5951
- const state = view.state;
5952
- const selection = state.selection;
5953
- if (selection.empty || selection instanceof import_state7.TextSelection) {
5954
- const pos = (_a = (0, import_editor_utils12.findNodePosition)({
5955
- editor,
5956
- node: state.selection.$anchor.node(1)
5957
- })) == null ? void 0 : _a.pos;
5958
- if (!(0, import_editor_utils12.isValidPosition)(pos)) return false;
5959
- }
5960
- return true;
5961
- } catch {
5962
- return false;
5949
+ var import_react_hotkeys_hook = require("react-hotkeys-hook");
5950
+ var COLOR_HIGHLIGHT_SHORTCUT_KEY = "mod+shift+h";
5951
+ var HIGHLIGHT_COLORS = [
5952
+ {
5953
+ label: "Default background",
5954
+ value: "var(--tt-bg-color)",
5955
+ border: "var(--tt-bg-color-contrast)"
5956
+ },
5957
+ {
5958
+ label: "Gray background",
5959
+ value: "var(--tt-color-highlight-gray)",
5960
+ border: "var(--tt-color-highlight-gray-contrast)"
5961
+ },
5962
+ {
5963
+ label: "Brown background",
5964
+ value: "var(--tt-color-highlight-brown)",
5965
+ border: "var(--tt-color-highlight-brown-contrast)"
5966
+ },
5967
+ {
5968
+ label: "Orange background",
5969
+ value: "var(--tt-color-highlight-orange)",
5970
+ border: "var(--tt-color-highlight-orange-contrast)"
5971
+ },
5972
+ {
5973
+ label: "Yellow background",
5974
+ value: "var(--tt-color-highlight-yellow)",
5975
+ border: "var(--tt-color-highlight-yellow-contrast)"
5976
+ },
5977
+ {
5978
+ label: "Green background",
5979
+ value: "var(--tt-color-highlight-green)",
5980
+ border: "var(--tt-color-highlight-green-contrast)"
5981
+ },
5982
+ {
5983
+ label: "Blue background",
5984
+ value: "var(--tt-color-highlight-blue)",
5985
+ border: "var(--tt-color-highlight-blue-contrast)"
5986
+ },
5987
+ {
5988
+ label: "Purple background",
5989
+ value: "var(--tt-color-highlight-purple)",
5990
+ border: "var(--tt-color-highlight-purple-contrast)"
5991
+ },
5992
+ {
5993
+ label: "Pink background",
5994
+ value: "var(--tt-color-highlight-pink)",
5995
+ border: "var(--tt-color-highlight-pink-contrast)"
5996
+ },
5997
+ {
5998
+ label: "Red background",
5999
+ value: "var(--tt-color-highlight-red)",
6000
+ border: "var(--tt-color-highlight-red-contrast)"
5963
6001
  }
6002
+ ];
6003
+ function pickHighlightColorsByValue(values) {
6004
+ const colorMap = new Map(
6005
+ HIGHLIGHT_COLORS.map((color) => [color.value, color])
6006
+ );
6007
+ return values.map((value) => colorMap.get(value)).filter((color) => !!color);
5964
6008
  }
5965
- function toggleBlockquote(editor) {
5966
- var _a, _b, _c;
6009
+ function canColorHighlight(editor) {
5967
6010
  if (!editor || !editor.isEditable) return false;
5968
- if (!canToggleBlockquote(editor)) return false;
5969
- try {
5970
- const view = editor.view;
5971
- let state = view.state;
5972
- let tr = state.tr;
5973
- if (state.selection.empty || state.selection instanceof import_state7.TextSelection) {
5974
- const pos = (_a = (0, import_editor_utils12.findNodePosition)({
5975
- editor,
5976
- node: state.selection.$anchor.node(1)
5977
- })) == null ? void 0 : _a.pos;
5978
- if (!(0, import_editor_utils12.isValidPosition)(pos)) return false;
5979
- tr = tr.setSelection(import_state7.NodeSelection.create(state.doc, pos));
5980
- view.dispatch(tr);
5981
- state = view.state;
5982
- }
5983
- const selection = state.selection;
5984
- let chain = editor.chain().focus();
5985
- if (selection instanceof import_state7.NodeSelection) {
5986
- const firstChild = (_b = selection.node.firstChild) == null ? void 0 : _b.firstChild;
5987
- const lastChild = (_c = selection.node.lastChild) == null ? void 0 : _c.lastChild;
5988
- const from = firstChild ? selection.from + firstChild.nodeSize : selection.from + 1;
5989
- const to = lastChild ? selection.to - lastChild.nodeSize : selection.to - 1;
5990
- chain = chain.setTextSelection({ from, to }).clearNodes();
5991
- }
5992
- const toggle = editor.isActive("blockquote") ? chain.lift("blockquote") : chain.wrapIn("blockquote");
5993
- toggle.run();
5994
- editor.chain().focus().selectTextblockEnd().run();
5995
- return true;
5996
- } catch {
6011
+ if (!(0, import_editor_utils12.isMarkInSchema)("highlight", editor) || (0, import_editor_utils12.isNodeTypeSelected)(editor, ["image"]))
5997
6012
  return false;
5998
- }
6013
+ return editor.can().setMark("highlight");
6014
+ }
6015
+ function isColorHighlightActive(editor, highlightColor) {
6016
+ if (!editor || !editor.isEditable) return false;
6017
+ return highlightColor ? editor.isActive("highlight", { color: highlightColor }) : editor.isActive("highlight");
6018
+ }
6019
+ function removeHighlight(editor) {
6020
+ if (!editor || !editor.isEditable) return false;
6021
+ if (!canColorHighlight(editor)) return false;
6022
+ return editor.chain().focus().unsetMark("highlight").run();
5999
6023
  }
6000
6024
  function shouldShowButton2(props) {
6001
6025
  const { editor, hideWhenUnavailable } = props;
6002
6026
  if (!editor || !editor.isEditable) return false;
6003
- if (!(0, import_editor_utils12.isNodeInSchema)("blockquote", editor)) return false;
6027
+ if (!(0, import_editor_utils12.isMarkInSchema)("highlight", editor)) return false;
6004
6028
  if (hideWhenUnavailable && !editor.isActive("code")) {
6005
- return canToggleBlockquote(editor);
6029
+ return canColorHighlight(editor);
6006
6030
  }
6007
6031
  return true;
6008
6032
  }
6009
- function useBlockquote(config) {
6033
+ function useColorHighlight(config) {
6010
6034
  const {
6011
6035
  editor: providedEditor,
6036
+ label,
6037
+ highlightColor,
6012
6038
  hideWhenUnavailable = false,
6013
- onToggled
6014
- } = config || {};
6039
+ onApplied
6040
+ } = config;
6015
6041
  const { editor } = (0, import_editor_utils12.useTiptapEditor)(providedEditor);
6042
+ const isMobile = (0, import_use_is_mobile.useIsMobile)();
6016
6043
  const [isVisible, setIsVisible] = React14.useState(true);
6017
- const canToggle3 = canToggleBlockquote(editor);
6018
- const isActive = (editor == null ? void 0 : editor.isActive("blockquote")) || false;
6044
+ const canColorHighlightState = canColorHighlight(editor);
6045
+ const isActive = isColorHighlightActive(editor, highlightColor);
6019
6046
  React14.useEffect(() => {
6020
6047
  if (!editor) return;
6021
6048
  const handleSelectionUpdate = () => {
@@ -6027,375 +6054,885 @@ function useBlockquote(config) {
6027
6054
  editor.off("selectionUpdate", handleSelectionUpdate);
6028
6055
  };
6029
6056
  }, [editor, hideWhenUnavailable]);
6030
- const handleToggle = React14.useCallback(() => {
6031
- if (!editor) return false;
6032
- const success = toggleBlockquote(editor);
6057
+ const handleColorHighlight = React14.useCallback(() => {
6058
+ if (!editor || !canColorHighlightState || !highlightColor || !label)
6059
+ return false;
6060
+ if (editor.state.storedMarks) {
6061
+ const highlightMarkType = editor.schema.marks.highlight;
6062
+ if (highlightMarkType) {
6063
+ editor.view.dispatch(
6064
+ editor.state.tr.removeStoredMark(highlightMarkType)
6065
+ );
6066
+ }
6067
+ }
6068
+ setTimeout(() => {
6069
+ const success = editor.chain().focus().toggleMark("highlight", { color: highlightColor }).run();
6070
+ if (success) {
6071
+ onApplied == null ? void 0 : onApplied({ color: highlightColor, label });
6072
+ }
6073
+ return success;
6074
+ }, 0);
6075
+ }, [canColorHighlightState, highlightColor, editor, label, onApplied]);
6076
+ const handleRemoveHighlight = React14.useCallback(() => {
6077
+ const success = removeHighlight(editor);
6033
6078
  if (success) {
6034
- onToggled == null ? void 0 : onToggled();
6079
+ onApplied == null ? void 0 : onApplied({ color: "", label: "Remove highlight" });
6035
6080
  }
6036
6081
  return success;
6037
- }, [editor, onToggled]);
6082
+ }, [editor, onApplied]);
6083
+ (0, import_react_hotkeys_hook.useHotkeys)(
6084
+ COLOR_HIGHLIGHT_SHORTCUT_KEY,
6085
+ (event) => {
6086
+ event.preventDefault();
6087
+ handleColorHighlight();
6088
+ },
6089
+ {
6090
+ enabled: isVisible && canColorHighlightState,
6091
+ enableOnContentEditable: !isMobile,
6092
+ enableOnFormTags: true
6093
+ }
6094
+ );
6038
6095
  return {
6039
6096
  isVisible,
6040
6097
  isActive,
6041
- handleToggle,
6042
- canToggle: canToggle3,
6043
- label: "Blockquote",
6044
- shortcutKeys: BLOCKQUOTE_SHORTCUT_KEY,
6045
- Icon: import_icons14.BlockquoteIcon
6098
+ handleColorHighlight,
6099
+ handleRemoveHighlight,
6100
+ canColorHighlight: canColorHighlightState,
6101
+ label: label || `Highlight`,
6102
+ shortcutKeys: COLOR_HIGHLIGHT_SHORTCUT_KEY,
6103
+ Icon: import_icons14.HighlighterIcon
6046
6104
  };
6047
6105
  }
6048
6106
 
6049
- // src/ui/blockquote-button/blockquote-button.tsx
6107
+ // src/ui/color-highlight-button/color-highlight-button.tsx
6050
6108
  var import_jsx_runtime21 = require("react/jsx-runtime");
6051
- var BlockquoteButton = ({
6109
+ var ColorHighlightButton = ({
6052
6110
  editor: providedEditor,
6111
+ highlightColor,
6053
6112
  text,
6054
6113
  hideWhenUnavailable = false,
6055
- onToggled,
6114
+ onApplied,
6056
6115
  showShortcut = false,
6057
6116
  onClick,
6058
6117
  children,
6118
+ style,
6119
+ className,
6059
6120
  ...buttonProps
6060
6121
  }) => {
6061
6122
  const { editor } = (0, import_editor_utils13.useTiptapEditor)(providedEditor);
6062
6123
  const {
6063
6124
  isVisible,
6064
- canToggle: canToggle3,
6125
+ canColorHighlight: canColorHighlight2,
6065
6126
  isActive,
6066
- handleToggle,
6127
+ handleColorHighlight,
6067
6128
  label,
6068
- shortcutKeys,
6069
- Icon
6070
- } = useBlockquote({
6129
+ shortcutKeys
6130
+ } = useColorHighlight({
6071
6131
  editor,
6132
+ highlightColor,
6133
+ label: text || `Toggle highlight (${highlightColor})`,
6072
6134
  hideWhenUnavailable,
6073
- onToggled
6135
+ onApplied
6074
6136
  });
6075
- const handleClick = React15.useCallback(
6137
+ const handleClick = (0, import_react42.useCallback)(
6076
6138
  (event) => {
6077
6139
  onClick == null ? void 0 : onClick(event);
6078
6140
  if (event.defaultPrevented) return;
6079
- handleToggle();
6141
+ handleColorHighlight();
6080
6142
  },
6081
- [handleToggle, onClick]
6143
+ [handleColorHighlight, onClick]
6144
+ );
6145
+ const buttonStyle = (0, import_react42.useMemo)(
6146
+ () => ({
6147
+ ...style,
6148
+ "--highlight-color": highlightColor
6149
+ }),
6150
+ [highlightColor, style]
6082
6151
  );
6083
6152
  if (!isVisible) {
6084
6153
  return null;
6085
6154
  }
6086
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6155
+ const styles = (0, import_theme8.colorHighlightButton)();
6156
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
6087
6157
  import_toolbar4.ToolbarButton,
6088
6158
  {
6089
6159
  type: "button",
6160
+ disabled: !canColorHighlight2,
6161
+ "data-disabled": !canColorHighlight2,
6090
6162
  variant: "ghost",
6091
6163
  color: "default",
6092
- disabled: !canToggle3,
6093
- "data-disabled": !canToggle3,
6094
6164
  "data-active-state": isActive ? "on" : "off",
6095
6165
  tabIndex: -1,
6096
- "aria-label": "blockquote",
6097
- "aria-pressed": isActive,
6098
- title: label,
6166
+ "aria-label": label,
6099
6167
  shortcutKeys,
6168
+ "aria-pressed": isActive,
6100
6169
  onClick: handleClick,
6101
- isIconOnly: !text && !children,
6170
+ style: buttonStyle,
6171
+ className: styles.button({ className }),
6172
+ isIconOnly: true,
6102
6173
  ...buttonProps,
6103
- children: children != null ? children : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
6104
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Icon, {}),
6105
- text && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: text })
6106
- ] })
6107
- }
6108
- );
6109
- };
6110
-
6111
- // src/ui/codeblock-button/code-block-button.tsx
6112
- var import_editor_utils15 = require("@kopexa/editor-utils");
6174
+ children: [
6175
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6176
+ "span",
6177
+ {
6178
+ "data-active-state": isActive ? "on" : "off",
6179
+ className: styles.mark()
6180
+ }
6181
+ ),
6182
+ children || /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
6183
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6184
+ "span",
6185
+ {
6186
+ style: { "--highlight-color": highlightColor }
6187
+ }
6188
+ ),
6189
+ text
6190
+ ] })
6191
+ ]
6192
+ }
6193
+ );
6194
+ };
6195
+
6196
+ // src/ui/color-highlight-popover/color-highlight-popover.tsx
6197
+ var import_jsx_runtime22 = require("react/jsx-runtime");
6198
+ var ColorHighlightPopoverButton = ({
6199
+ className,
6200
+ children,
6201
+ ...props
6202
+ }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6203
+ import_button11.IconButton,
6204
+ {
6205
+ type: "button",
6206
+ className,
6207
+ variant: "ghost",
6208
+ color: "default",
6209
+ tabIndex: -1,
6210
+ "aria-label": "Highlight text",
6211
+ tooltip: "Highlight",
6212
+ isIconOnly: !children,
6213
+ ...props,
6214
+ children: children != null ? children : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_icons15.HighlighterIcon, {})
6215
+ }
6216
+ );
6217
+ function ColorHighlightPopoverContent({
6218
+ editor,
6219
+ colors = pickHighlightColorsByValue([
6220
+ "var(--tt-color-highlight-green)",
6221
+ "var(--tt-color-highlight-blue)",
6222
+ "var(--tt-color-highlight-red)",
6223
+ "var(--tt-color-highlight-purple)",
6224
+ "var(--tt-color-highlight-yellow)"
6225
+ ])
6226
+ }) {
6227
+ const { handleRemoveHighlight } = useColorHighlight({ editor });
6228
+ const containerRef = (0, import_react43.useRef)(null);
6229
+ const menuItems = (0, import_react43.useMemo)(
6230
+ () => [...colors, { label: "Remove highlight", value: "none" }],
6231
+ [colors]
6232
+ );
6233
+ const { selectedIndex } = useMenuNavigation({
6234
+ containerRef,
6235
+ items: menuItems,
6236
+ orientation: "both",
6237
+ onSelect: (item) => {
6238
+ if (!containerRef.current) return false;
6239
+ const highlightedElement = containerRef.current.querySelector(
6240
+ '[data-highlighted="true"]'
6241
+ );
6242
+ if (highlightedElement) highlightedElement.click();
6243
+ if (item.value === "none") handleRemoveHighlight();
6244
+ },
6245
+ autoSelectFirstItem: false
6246
+ });
6247
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { ref: containerRef, className: "flex gap-1 items-center", children: [
6248
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6249
+ "div",
6250
+ {
6251
+ className: "flex items-center gap-1 outline-none",
6252
+ "data-orientation": "horizontal",
6253
+ children: colors.map((color, index) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6254
+ ColorHighlightButton,
6255
+ {
6256
+ editor,
6257
+ highlightColor: color.value,
6258
+ "aria-label": `${color.label} highlight color`,
6259
+ tabIndex: index === selectedIndex ? 0 : -1,
6260
+ "data-highlighted": selectedIndex === index
6261
+ },
6262
+ color.value
6263
+ ))
6264
+ }
6265
+ ),
6266
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_toolbar5.ToolbarSeparator, { orientation: "vertical" }),
6267
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "tiptap-button-group", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6268
+ import_button11.IconButton,
6269
+ {
6270
+ onClick: handleRemoveHighlight,
6271
+ "aria-label": "Remove highlight",
6272
+ tabIndex: selectedIndex === colors.length ? 0 : -1,
6273
+ type: "button",
6274
+ role: "menuitem",
6275
+ variant: "ghost",
6276
+ color: "default",
6277
+ "data-highlighted": selectedIndex === colors.length,
6278
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_icons15.BanIcon, {})
6279
+ }
6280
+ ) })
6281
+ ] });
6282
+ }
6283
+ function ColorHighlightPopover({
6284
+ editor: providedEditor,
6285
+ colors = pickHighlightColorsByValue([
6286
+ "var(--tt-color-highlight-green)",
6287
+ "var(--tt-color-highlight-blue)",
6288
+ "var(--tt-color-highlight-red)",
6289
+ "var(--tt-color-highlight-purple)",
6290
+ "var(--tt-color-highlight-yellow)"
6291
+ ]),
6292
+ hideWhenUnavailable = false,
6293
+ onApplied,
6294
+ ...props
6295
+ }) {
6296
+ const { editor } = (0, import_editor_utils14.useTiptapEditor)(providedEditor);
6297
+ const [isOpen, setIsOpen] = (0, import_react43.useState)(false);
6298
+ const { isVisible, canColorHighlight: canColorHighlight2, isActive, label } = useColorHighlight({
6299
+ editor,
6300
+ hideWhenUnavailable,
6301
+ onApplied
6302
+ });
6303
+ if (!isVisible) return null;
6304
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_popover2.Popover.Root, { open: isOpen, onOpenChange: setIsOpen, spacing: "dense", children: [
6305
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6306
+ import_popover2.Popover.Trigger,
6307
+ {
6308
+ render: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6309
+ ColorHighlightPopoverButton,
6310
+ {
6311
+ disabled: !canColorHighlight2,
6312
+ "data-disabled": !canColorHighlight2,
6313
+ "data-active-state": isActive ? "on" : "off",
6314
+ "aria-pressed": isActive,
6315
+ "aria-label": label,
6316
+ title: label,
6317
+ ...props
6318
+ }
6319
+ )
6320
+ }
6321
+ ),
6322
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_popover2.Popover.Content, { "aria-label": "Highlight colors", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ColorHighlightPopoverContent, { editor, colors }) })
6323
+ ] });
6324
+ }
6325
+
6326
+ // src/ui/list-dropdown-menu/index.tsx
6327
+ var import_button13 = require("@kopexa/button");
6328
+ var import_dropdown_menu = require("@kopexa/dropdown-menu");
6329
+ var import_editor_utils16 = require("@kopexa/editor-utils");
6330
+ var import_icons17 = require("@kopexa/icons");
6331
+ var import_react46 = require("@tiptap/react");
6332
+ var import_react47 = require("react");
6333
+
6334
+ // src/ui/list-button/index.tsx
6335
+ var import_button12 = require("@kopexa/button");
6336
+ var import_editor_utils15 = require("@kopexa/editor-utils");
6113
6337
  var import_icons16 = require("@kopexa/icons");
6114
- var import_toolbar5 = require("@kopexa/toolbar");
6115
- var import_react42 = require("react");
6338
+ var import_react44 = require("@tiptap/react");
6339
+ var import_react45 = require("react");
6340
+ var import_jsx_runtime23 = require("react/jsx-runtime");
6341
+ var listOptions = [
6342
+ {
6343
+ label: "Bullet List",
6344
+ type: "bulletList",
6345
+ icon: import_icons16.ListIcon
6346
+ },
6347
+ {
6348
+ label: "Ordered List",
6349
+ type: "orderedList",
6350
+ icon: import_icons16.ListOrderedIcon
6351
+ },
6352
+ {
6353
+ label: "Task List",
6354
+ type: "taskList",
6355
+ icon: import_icons16.ListTodoIcon
6356
+ }
6357
+ ];
6358
+ var listShortcutKeys = {
6359
+ bulletList: "Ctrl-Shift-8",
6360
+ orderedList: "Ctrl-Shift-7",
6361
+ taskList: "Ctrl-Shift-9"
6362
+ };
6363
+ function canToggleList(editor, type) {
6364
+ if (!editor) {
6365
+ return false;
6366
+ }
6367
+ switch (type) {
6368
+ case "bulletList":
6369
+ return editor.can().toggleBulletList();
6370
+ case "orderedList":
6371
+ return editor.can().toggleOrderedList();
6372
+ case "taskList":
6373
+ return editor.can().toggleList("taskList", "taskItem");
6374
+ default:
6375
+ return false;
6376
+ }
6377
+ }
6378
+ function isListActive(editor, type) {
6379
+ if (!editor) return false;
6380
+ switch (type) {
6381
+ case "bulletList":
6382
+ return editor.isActive("bulletList");
6383
+ case "orderedList":
6384
+ return editor.isActive("orderedList");
6385
+ case "taskList":
6386
+ return editor.isActive("taskList");
6387
+ default:
6388
+ return false;
6389
+ }
6390
+ }
6391
+ function toggleList(editor, type) {
6392
+ if (!editor) return;
6393
+ switch (type) {
6394
+ case "bulletList":
6395
+ editor.chain().focus().toggleBulletList().run();
6396
+ break;
6397
+ case "orderedList":
6398
+ editor.chain().focus().toggleOrderedList().run();
6399
+ break;
6400
+ case "taskList":
6401
+ editor.chain().focus().toggleList("taskList", "taskItem").run();
6402
+ break;
6403
+ }
6404
+ }
6405
+ function getListOption(type) {
6406
+ return listOptions.find((option) => option.type === type);
6407
+ }
6408
+ function shouldShowListButton(params) {
6409
+ const { editor, type, hideWhenUnavailable, listInSchema } = params;
6410
+ if (!listInSchema || !editor) {
6411
+ return false;
6412
+ }
6413
+ if (hideWhenUnavailable) {
6414
+ if ((0, import_react44.isNodeSelection)(editor.state.selection) || !canToggleList(editor, type)) {
6415
+ return false;
6416
+ }
6417
+ }
6418
+ return true;
6419
+ }
6420
+ function useListState(editor, type) {
6421
+ const listInSchema = (0, import_editor_utils15.isNodeInSchema)(type, editor);
6422
+ const listOption = getListOption(type);
6423
+ const isActive = isListActive(editor, type);
6424
+ const shortcutKey = listShortcutKeys[type];
6425
+ return {
6426
+ listInSchema,
6427
+ listOption,
6428
+ isActive,
6429
+ shortcutKey
6430
+ };
6431
+ }
6432
+ var ListButton = ({
6433
+ editor: providedEditor,
6434
+ type,
6435
+ hideWhenUnavailable = false,
6436
+ className = "",
6437
+ onClick,
6438
+ text,
6439
+ children,
6440
+ ref,
6441
+ ...buttonProps
6442
+ }) => {
6443
+ const { editor } = (0, import_editor_utils15.useTiptapEditor)(providedEditor);
6444
+ const { listInSchema, listOption, isActive, shortcutKey } = useListState(
6445
+ editor,
6446
+ type
6447
+ );
6448
+ const Icon = (listOption == null ? void 0 : listOption.icon) || import_icons16.ListIcon;
6449
+ const handleClick = (0, import_react45.useCallback)(
6450
+ (e) => {
6451
+ onClick == null ? void 0 : onClick(e);
6452
+ if (!e.defaultPrevented && editor) {
6453
+ toggleList(editor, type);
6454
+ }
6455
+ },
6456
+ [onClick, editor, type]
6457
+ );
6458
+ const show = (0, import_react45.useMemo)(() => {
6459
+ return shouldShowListButton({
6460
+ editor,
6461
+ type,
6462
+ hideWhenUnavailable,
6463
+ listInSchema
6464
+ });
6465
+ }, [editor, type, hideWhenUnavailable, listInSchema]);
6466
+ if (!show || !editor || !editor.isEditable) {
6467
+ return null;
6468
+ }
6469
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6470
+ import_button12.Button,
6471
+ {
6472
+ type: "button",
6473
+ className: className.trim(),
6474
+ variant: "ghost",
6475
+ color: "default",
6476
+ "data-active-state": isActive ? "on" : "off",
6477
+ tabIndex: -1,
6478
+ "aria-label": (listOption == null ? void 0 : listOption.label) || type,
6479
+ "aria-pressed": isActive,
6480
+ tooltip: (listOption == null ? void 0 : listOption.label) || type,
6481
+ shortcutKeys: shortcutKey,
6482
+ onClick: handleClick,
6483
+ startContent: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Icon, {}),
6484
+ ...buttonProps,
6485
+ ref,
6486
+ children: children || text
6487
+ }
6488
+ );
6489
+ };
6116
6490
 
6117
- // src/ui/codeblock-button/use-code-block.ts
6118
- var import_editor_utils14 = require("@kopexa/editor-utils");
6119
- var import_icons15 = require("@kopexa/icons");
6120
- var import_state8 = require("@tiptap/pm/state");
6121
- var React16 = __toESM(require("react"));
6122
- var CODE_BLOCK_SHORTCUT_KEY = "mod+alt+c";
6123
- function canToggle2(editor, turnInto = true) {
6124
- var _a;
6125
- if (!editor || !editor.isEditable) return false;
6126
- if (!(0, import_editor_utils14.isNodeInSchema)("codeBlock", editor) || (0, import_editor_utils14.isNodeTypeSelected)(editor, ["image"]))
6491
+ // src/ui/list-dropdown-menu/index.tsx
6492
+ var import_jsx_runtime24 = require("react/jsx-runtime");
6493
+ function canToggleAnyList(editor, listTypes) {
6494
+ if (!editor) return false;
6495
+ return listTypes.some((type) => canToggleList(editor, type));
6496
+ }
6497
+ function isAnyListActive(editor, listTypes) {
6498
+ if (!editor) return false;
6499
+ return listTypes.some((type) => isListActive(editor, type));
6500
+ }
6501
+ function getFilteredListOptions(availableTypes) {
6502
+ return listOptions.filter(
6503
+ (option) => !option.type || availableTypes.includes(option.type)
6504
+ );
6505
+ }
6506
+ function shouldShowListDropdown(params) {
6507
+ const { editor, hideWhenUnavailable, listInSchema, canToggleAny } = params;
6508
+ if (!listInSchema || !editor) {
6127
6509
  return false;
6128
- if (!turnInto) {
6129
- return editor.can().toggleNode("codeBlock", "paragraph");
6130
6510
  }
6131
- try {
6132
- const view = editor.view;
6133
- const state = view.state;
6134
- const selection = state.selection;
6135
- if (selection.empty || selection instanceof import_state8.TextSelection) {
6136
- const pos = (_a = (0, import_editor_utils14.findNodePosition)({
6511
+ if (hideWhenUnavailable) {
6512
+ if ((0, import_react46.isNodeSelection)(editor.state.selection) || !canToggleAny) {
6513
+ return false;
6514
+ }
6515
+ }
6516
+ return true;
6517
+ }
6518
+ function useListDropdownState(editor, availableTypes) {
6519
+ const [isOpen, setIsOpen] = (0, import_react47.useState)(false);
6520
+ const listInSchema = availableTypes.some(
6521
+ (type) => (0, import_editor_utils16.isNodeInSchema)(type, editor)
6522
+ );
6523
+ const filteredLists = (0, import_react47.useMemo)(
6524
+ () => getFilteredListOptions(availableTypes),
6525
+ [availableTypes]
6526
+ );
6527
+ const canToggleAny = canToggleAnyList(editor, availableTypes);
6528
+ const isAnyActive = isAnyListActive(editor, availableTypes);
6529
+ const handleOpenChange = (0, import_react47.useCallback)(
6530
+ (open, callback) => {
6531
+ setIsOpen(open);
6532
+ callback == null ? void 0 : callback(open);
6533
+ },
6534
+ []
6535
+ );
6536
+ return {
6537
+ isOpen,
6538
+ setIsOpen,
6539
+ listInSchema,
6540
+ filteredLists,
6541
+ canToggleAny,
6542
+ isAnyActive,
6543
+ handleOpenChange
6544
+ };
6545
+ }
6546
+ function useActiveListIcon(editor, filteredLists) {
6547
+ return (0, import_react47.useCallback)(() => {
6548
+ const activeOption = filteredLists.find(
6549
+ (option) => isListActive(editor, option.type)
6550
+ );
6551
+ return activeOption ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(activeOption.icon, {}) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_icons17.ListIcon, {});
6552
+ }, [editor, filteredLists]);
6553
+ }
6554
+ function ListDropdownMenu({
6555
+ editor: providedEditor,
6556
+ types = ["bulletList", "orderedList", "taskList"],
6557
+ hideWhenUnavailable = false,
6558
+ onOpenChange,
6559
+ ...props
6560
+ }) {
6561
+ const { editor } = (0, import_editor_utils16.useTiptapEditor)(providedEditor);
6562
+ const {
6563
+ isOpen,
6564
+ listInSchema,
6565
+ filteredLists,
6566
+ canToggleAny,
6567
+ isAnyActive,
6568
+ handleOpenChange
6569
+ } = useListDropdownState(editor, types);
6570
+ const getActiveIcon = useActiveListIcon(editor, filteredLists);
6571
+ const show = (0, import_react47.useMemo)(() => {
6572
+ return shouldShowListDropdown({
6573
+ editor,
6574
+ listTypes: types,
6575
+ hideWhenUnavailable,
6576
+ listInSchema,
6577
+ canToggleAny
6578
+ });
6579
+ }, [editor, types, hideWhenUnavailable, listInSchema, canToggleAny]);
6580
+ const handleOnOpenChange = (0, import_react47.useCallback)(
6581
+ (open) => handleOpenChange(open, onOpenChange),
6582
+ [handleOpenChange, onOpenChange]
6583
+ );
6584
+ if (!show || !editor || !editor.isEditable) {
6585
+ return null;
6586
+ }
6587
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_dropdown_menu.DropdownMenu.Root, { open: isOpen, onOpenChange: handleOnOpenChange, children: [
6588
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_dropdown_menu.DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6589
+ import_button13.Button,
6590
+ {
6591
+ type: "button",
6592
+ variant: "ghost",
6593
+ color: "default",
6594
+ "data-active-state": isAnyActive ? "on" : "off",
6595
+ tabIndex: -1,
6596
+ "aria-label": "List options",
6597
+ tooltip: "List",
6598
+ endContent: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_icons17.ChevronDownIcon, {}),
6599
+ ...props,
6600
+ children: getActiveIcon()
6601
+ }
6602
+ ) }),
6603
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_dropdown_menu.DropdownMenu.Content, { children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_dropdown_menu.DropdownMenu.Group, { children: filteredLists.map((option) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_dropdown_menu.DropdownMenu.Item, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6604
+ ListButton,
6605
+ {
6137
6606
  editor,
6138
- node: state.selection.$anchor.node(1)
6139
- })) == null ? void 0 : _a.pos;
6140
- if (!(0, import_editor_utils14.isValidPosition)(pos)) return false;
6607
+ type: option.type,
6608
+ text: option.label,
6609
+ hideWhenUnavailable,
6610
+ tooltip: "",
6611
+ fullWidth: true,
6612
+ spacing: "start"
6613
+ }
6614
+ ) }, option.type)) }) })
6615
+ ] });
6616
+ }
6617
+
6618
+ // src/ui/table-button/index.tsx
6619
+ var import_editor_utils17 = require("@kopexa/editor-utils");
6620
+ var import_toolbar6 = require("@kopexa/toolbar");
6621
+ var import_react48 = require("react");
6622
+ var import_jsx_runtime25 = require("react/jsx-runtime");
6623
+ var TableButton = ({
6624
+ editor: providedEditor,
6625
+ text,
6626
+ hideWhenUnavailable = false,
6627
+ onToggled,
6628
+ onClick,
6629
+ children,
6630
+ ...buttonProps
6631
+ }) => {
6632
+ const { editor } = (0, import_editor_utils17.useTiptapEditor)(providedEditor);
6633
+ const {
6634
+ isVisible,
6635
+ canToggle: canToggle3,
6636
+ isActive,
6637
+ handleToggle,
6638
+ label,
6639
+ // shortcutKeys,
6640
+ Icon
6641
+ } = useTableBlock({
6642
+ editor,
6643
+ hideWhenUnavailable,
6644
+ onToggled
6645
+ });
6646
+ const handleClick = (0, import_react48.useCallback)(
6647
+ (event) => {
6648
+ onClick == null ? void 0 : onClick(event);
6649
+ if (event.defaultPrevented) return;
6650
+ handleToggle();
6651
+ },
6652
+ [handleToggle, onClick]
6653
+ );
6654
+ if (!isVisible) {
6655
+ return null;
6656
+ }
6657
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6658
+ import_toolbar6.ToolbarButton,
6659
+ {
6660
+ type: "button",
6661
+ variant: "ghost",
6662
+ color: "default",
6663
+ "data-active-state": isActive ? "on" : "off",
6664
+ disabled: !canToggle3,
6665
+ "data-disabled": !canToggle3,
6666
+ tabIndex: -1,
6667
+ "aria-label": label,
6668
+ "aria-pressed": isActive,
6669
+ title: label,
6670
+ onClick: handleClick,
6671
+ isIconOnly: !text && !children,
6672
+ ...buttonProps,
6673
+ children: children || /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
6674
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Icon, {}),
6675
+ text && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: text })
6676
+ ] })
6141
6677
  }
6142
- return true;
6143
- } catch {
6678
+ );
6679
+ };
6680
+
6681
+ // src/ui/text-align-button/text-align-button.tsx
6682
+ var import_button14 = require("@kopexa/button");
6683
+ var import_editor_utils19 = require("@kopexa/editor-utils");
6684
+ var import_react50 = require("react");
6685
+
6686
+ // src/ui/text-align-button/use-text-align.ts
6687
+ var import_editor_utils18 = require("@kopexa/editor-utils");
6688
+ var import_icons18 = require("@kopexa/icons");
6689
+ var import_react49 = require("react");
6690
+ var TEXT_ALIGN_SHORTCUT_KEYS = {
6691
+ left: "mod+shift+l",
6692
+ center: "mod+shift+e",
6693
+ right: "mod+shift+r",
6694
+ justify: "mod+shift+j"
6695
+ };
6696
+ var textAlignIcons = {
6697
+ left: import_icons18.AlignLeftIcon,
6698
+ center: import_icons18.AlignCenterIcon,
6699
+ right: import_icons18.AlignRightIcon,
6700
+ justify: import_icons18.AlignJustifyIcon
6701
+ };
6702
+ var textAlignLabels = {
6703
+ left: "Align left",
6704
+ center: "Align center",
6705
+ right: "Align right",
6706
+ justify: "Align justify"
6707
+ };
6708
+ function canSetTextAlign(editor, align) {
6709
+ if (!editor || !editor.isEditable) return false;
6710
+ if (!(0, import_editor_utils18.isExtensionAvailable)(editor, "textAlign") || (0, import_editor_utils18.isNodeTypeSelected)(editor, ["image"]))
6144
6711
  return false;
6145
- }
6712
+ return editor.can().setTextAlign(align);
6146
6713
  }
6147
- function toggleCodeBlock(editor) {
6148
- var _a, _b, _c;
6714
+ function hasSetTextAlign(commands) {
6715
+ return "setTextAlign" in commands;
6716
+ }
6717
+ function isTextAlignActive(editor, align) {
6149
6718
  if (!editor || !editor.isEditable) return false;
6150
- if (!canToggle2(editor)) return false;
6151
- try {
6152
- const view = editor.view;
6153
- let state = view.state;
6154
- let tr = state.tr;
6155
- if (state.selection.empty || state.selection instanceof import_state8.TextSelection) {
6156
- const pos = (_a = (0, import_editor_utils14.findNodePosition)({
6157
- editor,
6158
- node: state.selection.$anchor.node(1)
6159
- })) == null ? void 0 : _a.pos;
6160
- if (!(0, import_editor_utils14.isValidPosition)(pos)) return false;
6161
- tr = tr.setSelection(import_state8.NodeSelection.create(state.doc, pos));
6162
- view.dispatch(tr);
6163
- state = view.state;
6164
- }
6165
- const selection = state.selection;
6166
- let chain = editor.chain().focus();
6167
- if (selection instanceof import_state8.NodeSelection) {
6168
- const firstChild = (_b = selection.node.firstChild) == null ? void 0 : _b.firstChild;
6169
- const lastChild = (_c = selection.node.lastChild) == null ? void 0 : _c.lastChild;
6170
- const from = firstChild ? selection.from + firstChild.nodeSize : selection.from + 1;
6171
- const to = lastChild ? selection.to - lastChild.nodeSize : selection.to - 1;
6172
- chain = chain.setTextSelection({ from, to }).clearNodes();
6173
- }
6174
- const toggle = editor.isActive("codeBlock") ? chain.setNode("paragraph") : chain.toggleNode("codeBlock", "paragraph");
6175
- toggle.run();
6176
- editor.chain().focus().selectTextblockEnd().run();
6177
- return true;
6178
- } catch {
6179
- return false;
6719
+ return editor.isActive({ textAlign: align });
6720
+ }
6721
+ function setTextAlign(editor, align) {
6722
+ if (!editor || !editor.isEditable) return false;
6723
+ if (!canSetTextAlign(editor, align)) return false;
6724
+ const chain = editor.chain().focus();
6725
+ if (hasSetTextAlign(chain)) {
6726
+ return chain.setTextAlign(align).run();
6180
6727
  }
6728
+ return false;
6181
6729
  }
6182
6730
  function shouldShowButton3(props) {
6183
- const { editor, hideWhenUnavailable } = props;
6731
+ const { editor, hideWhenUnavailable, align } = props;
6184
6732
  if (!editor || !editor.isEditable) return false;
6185
- if (!(0, import_editor_utils14.isNodeInSchema)("codeBlock", editor)) return false;
6733
+ if (!(0, import_editor_utils18.isExtensionAvailable)(editor, "textAlign")) return false;
6186
6734
  if (hideWhenUnavailable && !editor.isActive("code")) {
6187
- return canToggle2(editor);
6735
+ return canSetTextAlign(editor, align);
6188
6736
  }
6189
6737
  return true;
6190
6738
  }
6191
- function useCodeBlock(config) {
6739
+ function useTextAlign(config) {
6192
6740
  const {
6193
6741
  editor: providedEditor,
6742
+ align,
6194
6743
  hideWhenUnavailable = false,
6195
- onToggled
6196
- } = config || {};
6197
- const { editor } = (0, import_editor_utils14.useTiptapEditor)(providedEditor);
6198
- const [isVisible, setIsVisible] = React16.useState(true);
6199
- const canToggleState = canToggle2(editor);
6200
- const isActive = (editor == null ? void 0 : editor.isActive("codeBlock")) || false;
6201
- React16.useEffect(() => {
6744
+ onAligned
6745
+ } = config;
6746
+ const { editor } = (0, import_editor_utils18.useTiptapEditor)(providedEditor);
6747
+ const [isVisible, setIsVisible] = (0, import_react49.useState)(true);
6748
+ const canAlign = canSetTextAlign(editor, align);
6749
+ const isActive = isTextAlignActive(editor, align);
6750
+ (0, import_react49.useEffect)(() => {
6202
6751
  if (!editor) return;
6203
6752
  const handleSelectionUpdate = () => {
6204
- setIsVisible(shouldShowButton3({ editor, hideWhenUnavailable }));
6753
+ setIsVisible(shouldShowButton3({ editor, align, hideWhenUnavailable }));
6205
6754
  };
6206
6755
  handleSelectionUpdate();
6207
6756
  editor.on("selectionUpdate", handleSelectionUpdate);
6208
6757
  return () => {
6209
6758
  editor.off("selectionUpdate", handleSelectionUpdate);
6210
6759
  };
6211
- }, [editor, hideWhenUnavailable]);
6212
- const handleToggle = React16.useCallback(() => {
6760
+ }, [editor, hideWhenUnavailable, align]);
6761
+ const handleTextAlign = (0, import_react49.useCallback)(() => {
6213
6762
  if (!editor) return false;
6214
- const success = toggleCodeBlock(editor);
6763
+ const success = setTextAlign(editor, align);
6215
6764
  if (success) {
6216
- onToggled == null ? void 0 : onToggled();
6765
+ onAligned == null ? void 0 : onAligned();
6217
6766
  }
6218
6767
  return success;
6219
- }, [editor, onToggled]);
6768
+ }, [editor, align, onAligned]);
6220
6769
  return {
6221
6770
  isVisible,
6222
6771
  isActive,
6223
- handleToggle,
6224
- canToggle: canToggleState,
6225
- label: "Code Block",
6226
- shortcutKeys: CODE_BLOCK_SHORTCUT_KEY,
6227
- Icon: import_icons15.CodeblockIcon
6772
+ handleTextAlign,
6773
+ canAlign,
6774
+ label: textAlignLabels[align],
6775
+ shortcutKeys: TEXT_ALIGN_SHORTCUT_KEYS[align],
6776
+ Icon: textAlignIcons[align]
6228
6777
  };
6229
6778
  }
6230
6779
 
6231
- // src/ui/codeblock-button/code-block-button.tsx
6232
- var import_jsx_runtime22 = require("react/jsx-runtime");
6233
- var CodeBlockButton = ({
6780
+ // src/ui/text-align-button/text-align-button.tsx
6781
+ var import_jsx_runtime26 = require("react/jsx-runtime");
6782
+ var TextAlignButton = ({
6234
6783
  editor: providedEditor,
6784
+ align,
6235
6785
  text,
6236
6786
  hideWhenUnavailable = false,
6237
- onToggled,
6787
+ onAligned,
6238
6788
  showShortcut = false,
6239
6789
  onClick,
6240
6790
  children,
6241
6791
  ...buttonProps
6242
6792
  }) => {
6243
- const { editor } = (0, import_editor_utils15.useTiptapEditor)(providedEditor);
6244
- const { isVisible, canToggle: canToggle3, isActive, handleToggle, label, shortcutKeys } = useCodeBlock({
6793
+ const { editor } = (0, import_editor_utils19.useTiptapEditor)(providedEditor);
6794
+ const {
6795
+ isVisible,
6796
+ handleTextAlign,
6797
+ label,
6798
+ canAlign,
6799
+ isActive,
6800
+ Icon,
6801
+ shortcutKeys
6802
+ } = useTextAlign({
6245
6803
  editor,
6804
+ align,
6246
6805
  hideWhenUnavailable,
6247
- onToggled
6806
+ onAligned
6248
6807
  });
6249
- const handleClick = (0, import_react42.useCallback)(
6250
- (event) => {
6251
- onClick == null ? void 0 : onClick(event);
6252
- if (event.defaultPrevented) return;
6253
- handleToggle();
6808
+ const handleClick = (0, import_react50.useCallback)(
6809
+ (e) => {
6810
+ onClick == null ? void 0 : onClick(e);
6811
+ if (e.defaultPrevented) return;
6812
+ handleTextAlign();
6254
6813
  },
6255
- [handleToggle, onClick]
6814
+ [handleTextAlign, onClick]
6256
6815
  );
6257
6816
  if (!isVisible) {
6258
6817
  return null;
6259
6818
  }
6260
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6261
- import_toolbar5.ToolbarButton,
6819
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6820
+ import_button14.IconButton,
6262
6821
  {
6263
6822
  type: "button",
6823
+ disabled: canAlign,
6264
6824
  variant: "ghost",
6265
6825
  color: "default",
6266
- disabled: !canToggle3,
6267
- "data-disabled": !canToggle3,
6268
6826
  "data-active-state": isActive ? "on" : "off",
6827
+ "data-disabled": canAlign,
6269
6828
  tabIndex: -1,
6270
- "aria-label": "codeBlock",
6829
+ "aria-label": label,
6271
6830
  "aria-pressed": isActive,
6272
- title: label,
6831
+ tooltip: label,
6273
6832
  shortcutKeys,
6274
6833
  onClick: handleClick,
6275
- isIconOnly: true,
6276
6834
  ...buttonProps,
6277
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_icons16.CodeblockIcon, {})
6835
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Icon, {})
6278
6836
  }
6279
6837
  );
6280
6838
  };
6281
6839
 
6282
- // src/ui/color-highlight-popover/color-highlight-popover.tsx
6283
- var import_button11 = require("@kopexa/button");
6284
- var import_editor_utils18 = require("@kopexa/editor-utils");
6285
- var import_icons18 = require("@kopexa/icons");
6286
- var import_popover2 = require("@kopexa/popover");
6287
- var import_toolbar7 = require("@kopexa/toolbar");
6288
- var import_react44 = require("react");
6840
+ // src/ui/turn-into-dropdown/turn-into-dropdown.tsx
6841
+ var import_button17 = require("@kopexa/button");
6842
+ var import_dropdown_menu2 = require("@kopexa/dropdown-menu");
6843
+ var import_editor_utils28 = require("@kopexa/editor-utils");
6844
+ var import_react56 = require("react");
6289
6845
 
6290
- // src/ui/color-highlight-button/color-highlight-button.tsx
6291
- var import_editor_utils17 = require("@kopexa/editor-utils");
6292
- var import_theme8 = require("@kopexa/theme");
6293
- var import_toolbar6 = require("@kopexa/toolbar");
6294
- var import_react43 = require("react");
6846
+ // src/ui/blockquote-button/blockquote-button.tsx
6847
+ var import_editor_utils21 = require("@kopexa/editor-utils");
6848
+ var import_toolbar7 = require("@kopexa/toolbar");
6849
+ var React16 = __toESM(require("react"));
6295
6850
 
6296
- // src/ui/color-highlight-button/use-color-highlight.ts
6297
- var import_editor_utils16 = require("@kopexa/editor-utils");
6298
- var import_icons17 = require("@kopexa/icons");
6299
- var import_use_is_mobile = require("@kopexa/use-is-mobile");
6300
- var React17 = __toESM(require("react"));
6301
- var import_react_hotkeys_hook = require("react-hotkeys-hook");
6302
- var COLOR_HIGHLIGHT_SHORTCUT_KEY = "mod+shift+h";
6303
- var HIGHLIGHT_COLORS = [
6304
- {
6305
- label: "Default background",
6306
- value: "var(--tt-bg-color)",
6307
- border: "var(--tt-bg-color-contrast)"
6308
- },
6309
- {
6310
- label: "Gray background",
6311
- value: "var(--tt-color-highlight-gray)",
6312
- border: "var(--tt-color-highlight-gray-contrast)"
6313
- },
6314
- {
6315
- label: "Brown background",
6316
- value: "var(--tt-color-highlight-brown)",
6317
- border: "var(--tt-color-highlight-brown-contrast)"
6318
- },
6319
- {
6320
- label: "Orange background",
6321
- value: "var(--tt-color-highlight-orange)",
6322
- border: "var(--tt-color-highlight-orange-contrast)"
6323
- },
6324
- {
6325
- label: "Yellow background",
6326
- value: "var(--tt-color-highlight-yellow)",
6327
- border: "var(--tt-color-highlight-yellow-contrast)"
6328
- },
6329
- {
6330
- label: "Green background",
6331
- value: "var(--tt-color-highlight-green)",
6332
- border: "var(--tt-color-highlight-green-contrast)"
6333
- },
6334
- {
6335
- label: "Blue background",
6336
- value: "var(--tt-color-highlight-blue)",
6337
- border: "var(--tt-color-highlight-blue-contrast)"
6338
- },
6339
- {
6340
- label: "Purple background",
6341
- value: "var(--tt-color-highlight-purple)",
6342
- border: "var(--tt-color-highlight-purple-contrast)"
6343
- },
6344
- {
6345
- label: "Pink background",
6346
- value: "var(--tt-color-highlight-pink)",
6347
- border: "var(--tt-color-highlight-pink-contrast)"
6348
- },
6349
- {
6350
- label: "Red background",
6351
- value: "var(--tt-color-highlight-red)",
6352
- border: "var(--tt-color-highlight-red-contrast)"
6353
- }
6354
- ];
6355
- function pickHighlightColorsByValue(values) {
6356
- const colorMap = new Map(
6357
- HIGHLIGHT_COLORS.map((color) => [color.value, color])
6358
- );
6359
- return values.map((value) => colorMap.get(value)).filter((color) => !!color);
6360
- }
6361
- function canColorHighlight(editor) {
6851
+ // src/ui/blockquote-button/use-blockquote.ts
6852
+ var import_editor_utils20 = require("@kopexa/editor-utils");
6853
+ var import_icons19 = require("@kopexa/icons");
6854
+ var import_state7 = require("@tiptap/pm/state");
6855
+ var React15 = __toESM(require("react"));
6856
+ var BLOCKQUOTE_SHORTCUT_KEY = "mod+shift+b";
6857
+ function canToggleBlockquote(editor, turnInto = true) {
6858
+ var _a;
6362
6859
  if (!editor || !editor.isEditable) return false;
6363
- if (!(0, import_editor_utils16.isMarkInSchema)("highlight", editor) || (0, import_editor_utils16.isNodeTypeSelected)(editor, ["image"]))
6860
+ if (!(0, import_editor_utils20.isNodeInSchema)("blockquote", editor) || (0, import_editor_utils20.isNodeTypeSelected)(editor, ["image"]))
6364
6861
  return false;
6365
- return editor.can().setMark("highlight");
6366
- }
6367
- function isColorHighlightActive(editor, highlightColor) {
6368
- if (!editor || !editor.isEditable) return false;
6369
- return highlightColor ? editor.isActive("highlight", { color: highlightColor }) : editor.isActive("highlight");
6862
+ if (!turnInto) {
6863
+ return editor.can().toggleWrap("blockquote");
6864
+ }
6865
+ try {
6866
+ const view = editor.view;
6867
+ const state = view.state;
6868
+ const selection = state.selection;
6869
+ if (selection.empty || selection instanceof import_state7.TextSelection) {
6870
+ const pos = (_a = (0, import_editor_utils20.findNodePosition)({
6871
+ editor,
6872
+ node: state.selection.$anchor.node(1)
6873
+ })) == null ? void 0 : _a.pos;
6874
+ if (!(0, import_editor_utils20.isValidPosition)(pos)) return false;
6875
+ }
6876
+ return true;
6877
+ } catch {
6878
+ return false;
6879
+ }
6370
6880
  }
6371
- function removeHighlight(editor) {
6881
+ function toggleBlockquote(editor) {
6882
+ var _a, _b, _c;
6372
6883
  if (!editor || !editor.isEditable) return false;
6373
- if (!canColorHighlight(editor)) return false;
6374
- return editor.chain().focus().unsetMark("highlight").run();
6884
+ if (!canToggleBlockquote(editor)) return false;
6885
+ try {
6886
+ const view = editor.view;
6887
+ let state = view.state;
6888
+ let tr = state.tr;
6889
+ if (state.selection.empty || state.selection instanceof import_state7.TextSelection) {
6890
+ const pos = (_a = (0, import_editor_utils20.findNodePosition)({
6891
+ editor,
6892
+ node: state.selection.$anchor.node(1)
6893
+ })) == null ? void 0 : _a.pos;
6894
+ if (!(0, import_editor_utils20.isValidPosition)(pos)) return false;
6895
+ tr = tr.setSelection(import_state7.NodeSelection.create(state.doc, pos));
6896
+ view.dispatch(tr);
6897
+ state = view.state;
6898
+ }
6899
+ const selection = state.selection;
6900
+ let chain = editor.chain().focus();
6901
+ if (selection instanceof import_state7.NodeSelection) {
6902
+ const firstChild = (_b = selection.node.firstChild) == null ? void 0 : _b.firstChild;
6903
+ const lastChild = (_c = selection.node.lastChild) == null ? void 0 : _c.lastChild;
6904
+ const from = firstChild ? selection.from + firstChild.nodeSize : selection.from + 1;
6905
+ const to = lastChild ? selection.to - lastChild.nodeSize : selection.to - 1;
6906
+ chain = chain.setTextSelection({ from, to }).clearNodes();
6907
+ }
6908
+ const toggle = editor.isActive("blockquote") ? chain.lift("blockquote") : chain.wrapIn("blockquote");
6909
+ toggle.run();
6910
+ editor.chain().focus().selectTextblockEnd().run();
6911
+ return true;
6912
+ } catch {
6913
+ return false;
6914
+ }
6375
6915
  }
6376
6916
  function shouldShowButton4(props) {
6377
6917
  const { editor, hideWhenUnavailable } = props;
6378
6918
  if (!editor || !editor.isEditable) return false;
6379
- if (!(0, import_editor_utils16.isMarkInSchema)("highlight", editor)) return false;
6919
+ if (!(0, import_editor_utils20.isNodeInSchema)("blockquote", editor)) return false;
6380
6920
  if (hideWhenUnavailable && !editor.isActive("code")) {
6381
- return canColorHighlight(editor);
6921
+ return canToggleBlockquote(editor);
6382
6922
  }
6383
6923
  return true;
6384
6924
  }
6385
- function useColorHighlight(config) {
6925
+ function useBlockquote(config) {
6386
6926
  const {
6387
6927
  editor: providedEditor,
6388
- label,
6389
- highlightColor,
6390
6928
  hideWhenUnavailable = false,
6391
- onApplied
6392
- } = config;
6393
- const { editor } = (0, import_editor_utils16.useTiptapEditor)(providedEditor);
6394
- const isMobile = (0, import_use_is_mobile.useIsMobile)();
6395
- const [isVisible, setIsVisible] = React17.useState(true);
6396
- const canColorHighlightState = canColorHighlight(editor);
6397
- const isActive = isColorHighlightActive(editor, highlightColor);
6398
- React17.useEffect(() => {
6929
+ onToggled
6930
+ } = config || {};
6931
+ const { editor } = (0, import_editor_utils20.useTiptapEditor)(providedEditor);
6932
+ const [isVisible, setIsVisible] = React15.useState(true);
6933
+ const canToggle3 = canToggleBlockquote(editor);
6934
+ const isActive = (editor == null ? void 0 : editor.isActive("blockquote")) || false;
6935
+ React15.useEffect(() => {
6399
6936
  if (!editor) return;
6400
6937
  const handleSelectionUpdate = () => {
6401
6938
  setIsVisible(shouldShowButton4({ editor, hideWhenUnavailable }));
@@ -6406,674 +6943,403 @@ function useColorHighlight(config) {
6406
6943
  editor.off("selectionUpdate", handleSelectionUpdate);
6407
6944
  };
6408
6945
  }, [editor, hideWhenUnavailable]);
6409
- const handleColorHighlight = React17.useCallback(() => {
6410
- if (!editor || !canColorHighlightState || !highlightColor || !label)
6411
- return false;
6412
- if (editor.state.storedMarks) {
6413
- const highlightMarkType = editor.schema.marks.highlight;
6414
- if (highlightMarkType) {
6415
- editor.view.dispatch(
6416
- editor.state.tr.removeStoredMark(highlightMarkType)
6417
- );
6418
- }
6419
- }
6420
- setTimeout(() => {
6421
- const success = editor.chain().focus().toggleMark("highlight", { color: highlightColor }).run();
6422
- if (success) {
6423
- onApplied == null ? void 0 : onApplied({ color: highlightColor, label });
6424
- }
6425
- return success;
6426
- }, 0);
6427
- }, [canColorHighlightState, highlightColor, editor, label, onApplied]);
6428
- const handleRemoveHighlight = React17.useCallback(() => {
6429
- const success = removeHighlight(editor);
6946
+ const handleToggle = React15.useCallback(() => {
6947
+ if (!editor) return false;
6948
+ const success = toggleBlockquote(editor);
6430
6949
  if (success) {
6431
- onApplied == null ? void 0 : onApplied({ color: "", label: "Remove highlight" });
6950
+ onToggled == null ? void 0 : onToggled();
6432
6951
  }
6433
6952
  return success;
6434
- }, [editor, onApplied]);
6435
- (0, import_react_hotkeys_hook.useHotkeys)(
6436
- COLOR_HIGHLIGHT_SHORTCUT_KEY,
6437
- (event) => {
6438
- event.preventDefault();
6439
- handleColorHighlight();
6440
- },
6441
- {
6442
- enabled: isVisible && canColorHighlightState,
6443
- enableOnContentEditable: !isMobile,
6444
- enableOnFormTags: true
6445
- }
6446
- );
6953
+ }, [editor, onToggled]);
6447
6954
  return {
6448
6955
  isVisible,
6449
6956
  isActive,
6450
- handleColorHighlight,
6451
- handleRemoveHighlight,
6452
- canColorHighlight: canColorHighlightState,
6453
- label: label || `Highlight`,
6454
- shortcutKeys: COLOR_HIGHLIGHT_SHORTCUT_KEY,
6455
- Icon: import_icons17.HighlighterIcon
6957
+ handleToggle,
6958
+ canToggle: canToggle3,
6959
+ label: "Blockquote",
6960
+ shortcutKeys: BLOCKQUOTE_SHORTCUT_KEY,
6961
+ Icon: import_icons19.BlockquoteIcon
6456
6962
  };
6457
6963
  }
6458
6964
 
6459
- // src/ui/color-highlight-button/color-highlight-button.tsx
6460
- var import_jsx_runtime23 = require("react/jsx-runtime");
6461
- var ColorHighlightButton = ({
6965
+ // src/ui/blockquote-button/blockquote-button.tsx
6966
+ var import_jsx_runtime27 = require("react/jsx-runtime");
6967
+ var BlockquoteButton = ({
6462
6968
  editor: providedEditor,
6463
- highlightColor,
6464
6969
  text,
6465
6970
  hideWhenUnavailable = false,
6466
- onApplied,
6971
+ onToggled,
6467
6972
  showShortcut = false,
6468
6973
  onClick,
6469
6974
  children,
6470
- style,
6471
- className,
6472
6975
  ...buttonProps
6473
6976
  }) => {
6474
- const { editor } = (0, import_editor_utils17.useTiptapEditor)(providedEditor);
6977
+ const { editor } = (0, import_editor_utils21.useTiptapEditor)(providedEditor);
6475
6978
  const {
6476
6979
  isVisible,
6477
- canColorHighlight: canColorHighlight2,
6980
+ canToggle: canToggle3,
6478
6981
  isActive,
6479
- handleColorHighlight,
6982
+ handleToggle,
6480
6983
  label,
6481
- shortcutKeys
6482
- } = useColorHighlight({
6984
+ shortcutKeys,
6985
+ Icon
6986
+ } = useBlockquote({
6483
6987
  editor,
6484
- highlightColor,
6485
- label: text || `Toggle highlight (${highlightColor})`,
6486
6988
  hideWhenUnavailable,
6487
- onApplied
6989
+ onToggled
6488
6990
  });
6489
- const handleClick = (0, import_react43.useCallback)(
6991
+ const handleClick = React16.useCallback(
6490
6992
  (event) => {
6491
6993
  onClick == null ? void 0 : onClick(event);
6492
6994
  if (event.defaultPrevented) return;
6493
- handleColorHighlight();
6995
+ handleToggle();
6494
6996
  },
6495
- [handleColorHighlight, onClick]
6496
- );
6497
- const buttonStyle = (0, import_react43.useMemo)(
6498
- () => ({
6499
- ...style,
6500
- "--highlight-color": highlightColor
6501
- }),
6502
- [highlightColor, style]
6997
+ [handleToggle, onClick]
6503
6998
  );
6504
6999
  if (!isVisible) {
6505
7000
  return null;
6506
7001
  }
6507
- const styles = (0, import_theme8.colorHighlightButton)();
6508
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
6509
- import_toolbar6.ToolbarButton,
7002
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
7003
+ import_toolbar7.ToolbarButton,
6510
7004
  {
6511
7005
  type: "button",
6512
- disabled: !canColorHighlight2,
6513
- "data-disabled": !canColorHighlight2,
6514
7006
  variant: "ghost",
6515
7007
  color: "default",
7008
+ disabled: !canToggle3,
7009
+ "data-disabled": !canToggle3,
6516
7010
  "data-active-state": isActive ? "on" : "off",
6517
7011
  tabIndex: -1,
6518
- "aria-label": label,
6519
- shortcutKeys,
7012
+ "aria-label": "blockquote",
6520
7013
  "aria-pressed": isActive,
7014
+ title: label,
7015
+ shortcutKeys,
6521
7016
  onClick: handleClick,
6522
- style: buttonStyle,
6523
- className: styles.button({ className }),
6524
- isIconOnly: true,
7017
+ isIconOnly: !text && !children,
6525
7018
  ...buttonProps,
6526
- children: [
6527
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6528
- "span",
6529
- {
6530
- "data-active-state": isActive ? "on" : "off",
6531
- className: styles.mark()
6532
- }
6533
- ),
6534
- children || /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
6535
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6536
- "span",
6537
- {
6538
- style: { "--highlight-color": highlightColor }
6539
- }
6540
- ),
6541
- text
6542
- ] })
6543
- ]
7019
+ children: children != null ? children : /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
7020
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Icon, {}),
7021
+ text && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: text })
7022
+ ] })
6544
7023
  }
6545
7024
  );
6546
7025
  };
6547
7026
 
6548
- // src/ui/color-highlight-popover/color-highlight-popover.tsx
6549
- var import_jsx_runtime24 = require("react/jsx-runtime");
6550
- var ColorHighlightPopoverButton = ({
6551
- className,
6552
- children,
6553
- ...props
6554
- }) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6555
- import_button11.IconButton,
6556
- {
6557
- type: "button",
6558
- className,
6559
- variant: "ghost",
6560
- color: "default",
6561
- tabIndex: -1,
6562
- "aria-label": "Highlight text",
6563
- tooltip: "Highlight",
6564
- isIconOnly: !children,
6565
- ...props,
6566
- children: children != null ? children : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_icons18.HighlighterIcon, {})
6567
- }
6568
- );
6569
- function ColorHighlightPopoverContent({
6570
- editor,
6571
- colors = pickHighlightColorsByValue([
6572
- "var(--tt-color-highlight-green)",
6573
- "var(--tt-color-highlight-blue)",
6574
- "var(--tt-color-highlight-red)",
6575
- "var(--tt-color-highlight-purple)",
6576
- "var(--tt-color-highlight-yellow)"
6577
- ])
6578
- }) {
6579
- const { handleRemoveHighlight } = useColorHighlight({ editor });
6580
- const containerRef = (0, import_react44.useRef)(null);
6581
- const menuItems = (0, import_react44.useMemo)(
6582
- () => [...colors, { label: "Remove highlight", value: "none" }],
6583
- [colors]
6584
- );
6585
- const { selectedIndex } = useMenuNavigation({
6586
- containerRef,
6587
- items: menuItems,
6588
- orientation: "both",
6589
- onSelect: (item) => {
6590
- if (!containerRef.current) return false;
6591
- const highlightedElement = containerRef.current.querySelector(
6592
- '[data-highlighted="true"]'
6593
- );
6594
- if (highlightedElement) highlightedElement.click();
6595
- if (item.value === "none") handleRemoveHighlight();
6596
- },
6597
- autoSelectFirstItem: false
6598
- });
6599
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { ref: containerRef, className: "flex gap-1 items-center", children: [
6600
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6601
- "div",
6602
- {
6603
- className: "flex items-center gap-1 outline-none",
6604
- "data-orientation": "horizontal",
6605
- children: colors.map((color, index) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6606
- ColorHighlightButton,
6607
- {
6608
- editor,
6609
- highlightColor: color.value,
6610
- "aria-label": `${color.label} highlight color`,
6611
- tabIndex: index === selectedIndex ? 0 : -1,
6612
- "data-highlighted": selectedIndex === index
6613
- },
6614
- color.value
6615
- ))
6616
- }
6617
- ),
6618
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_toolbar7.ToolbarSeparator, { orientation: "vertical" }),
6619
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "tiptap-button-group", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6620
- import_button11.IconButton,
6621
- {
6622
- onClick: handleRemoveHighlight,
6623
- "aria-label": "Remove highlight",
6624
- tabIndex: selectedIndex === colors.length ? 0 : -1,
6625
- type: "button",
6626
- role: "menuitem",
6627
- variant: "ghost",
6628
- color: "default",
6629
- "data-highlighted": selectedIndex === colors.length,
6630
- children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_icons18.BanIcon, {})
6631
- }
6632
- ) })
6633
- ] });
6634
- }
6635
- function ColorHighlightPopover({
6636
- editor: providedEditor,
6637
- colors = pickHighlightColorsByValue([
6638
- "var(--tt-color-highlight-green)",
6639
- "var(--tt-color-highlight-blue)",
6640
- "var(--tt-color-highlight-red)",
6641
- "var(--tt-color-highlight-purple)",
6642
- "var(--tt-color-highlight-yellow)"
6643
- ]),
6644
- hideWhenUnavailable = false,
6645
- onApplied,
6646
- ...props
6647
- }) {
6648
- const { editor } = (0, import_editor_utils18.useTiptapEditor)(providedEditor);
6649
- const [isOpen, setIsOpen] = (0, import_react44.useState)(false);
6650
- const { isVisible, canColorHighlight: canColorHighlight2, isActive, label } = useColorHighlight({
6651
- editor,
6652
- hideWhenUnavailable,
6653
- onApplied
6654
- });
6655
- if (!isVisible) return null;
6656
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_popover2.Popover.Root, { open: isOpen, onOpenChange: setIsOpen, spacing: "dense", children: [
6657
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6658
- import_popover2.Popover.Trigger,
6659
- {
6660
- render: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6661
- ColorHighlightPopoverButton,
6662
- {
6663
- disabled: !canColorHighlight2,
6664
- "data-disabled": !canColorHighlight2,
6665
- "data-active-state": isActive ? "on" : "off",
6666
- "aria-pressed": isActive,
6667
- "aria-label": label,
6668
- title: label,
6669
- ...props
6670
- }
6671
- )
6672
- }
6673
- ),
6674
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_popover2.Popover.Content, { "aria-label": "Highlight colors", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ColorHighlightPopoverContent, { editor, colors }) })
6675
- ] });
6676
- }
7027
+ // src/ui/codeblock-button/code-block-button.tsx
7028
+ var import_editor_utils23 = require("@kopexa/editor-utils");
7029
+ var import_icons21 = require("@kopexa/icons");
7030
+ var import_toolbar8 = require("@kopexa/toolbar");
7031
+ var import_react51 = require("react");
6677
7032
 
6678
- // src/ui/heading-dropdown-menu/index.tsx
6679
- var import_button13 = require("@kopexa/button");
6680
- var import_dropdown_menu = require("@kopexa/dropdown-menu");
6681
- var import_editor_utils20 = require("@kopexa/editor-utils");
7033
+ // src/ui/codeblock-button/use-code-block.ts
7034
+ var import_editor_utils22 = require("@kopexa/editor-utils");
6682
7035
  var import_icons20 = require("@kopexa/icons");
6683
- var import_react46 = require("@tiptap/react");
6684
- var React19 = __toESM(require("react"));
6685
-
6686
- // src/ui/heading-button/index.tsx
6687
- var import_button12 = require("@kopexa/button");
6688
- var import_editor_utils19 = require("@kopexa/editor-utils");
6689
- var import_icons19 = require("@kopexa/icons");
6690
- var React18 = __toESM(require("react"));
6691
-
6692
- // src/ui/heading-button/utils.ts
6693
- var import_react45 = require("@tiptap/react");
6694
- var headingShortcutKeys = {
6695
- 1: "Ctrl-Alt-1",
6696
- 2: "Ctrl-Alt-2",
6697
- 3: "Ctrl-Alt-3",
6698
- 4: "Ctrl-Alt-4",
6699
- 5: "Ctrl-Alt-5",
6700
- 6: "Ctrl-Alt-6"
6701
- };
6702
- function canToggleHeading(editor, level) {
6703
- if (!editor) return false;
7036
+ var import_state8 = require("@tiptap/pm/state");
7037
+ var React17 = __toESM(require("react"));
7038
+ var CODE_BLOCK_SHORTCUT_KEY = "mod+alt+c";
7039
+ function canToggle2(editor, turnInto = true) {
7040
+ var _a;
7041
+ if (!editor || !editor.isEditable) return false;
7042
+ if (!(0, import_editor_utils22.isNodeInSchema)("codeBlock", editor) || (0, import_editor_utils22.isNodeTypeSelected)(editor, ["image"]))
7043
+ return false;
7044
+ if (!turnInto) {
7045
+ return editor.can().toggleNode("codeBlock", "paragraph");
7046
+ }
6704
7047
  try {
6705
- return editor.can().toggleNode("heading", "paragraph", { level });
7048
+ const view = editor.view;
7049
+ const state = view.state;
7050
+ const selection = state.selection;
7051
+ if (selection.empty || selection instanceof import_state8.TextSelection) {
7052
+ const pos = (_a = (0, import_editor_utils22.findNodePosition)({
7053
+ editor,
7054
+ node: state.selection.$anchor.node(1)
7055
+ })) == null ? void 0 : _a.pos;
7056
+ if (!(0, import_editor_utils22.isValidPosition)(pos)) return false;
7057
+ }
7058
+ return true;
6706
7059
  } catch {
6707
7060
  return false;
6708
7061
  }
6709
7062
  }
6710
- function isHeadingActive(editor, level) {
6711
- if (!editor) return false;
6712
- return editor.isActive("heading", { level });
6713
- }
6714
- function toggleHeading(editor, level) {
6715
- if (!editor) return;
6716
- if (editor.isActive("heading", { level })) {
6717
- editor.chain().focus().setNode("paragraph").run();
6718
- } else {
6719
- editor.chain().focus().toggleNode("heading", "paragraph", { level }).run();
6720
- }
6721
- }
6722
- function isHeadingButtonDisabled(editor, level, userDisabled = false) {
6723
- if (!editor) return true;
6724
- if (userDisabled) return true;
6725
- if (!canToggleHeading(editor, level)) return true;
6726
- return false;
6727
- }
6728
- function shouldShowHeadingButton(params) {
6729
- const { editor, hideWhenUnavailable, headingInSchema } = params;
6730
- if (!headingInSchema || !editor) {
7063
+ function toggleCodeBlock(editor) {
7064
+ var _a, _b, _c;
7065
+ if (!editor || !editor.isEditable) return false;
7066
+ if (!canToggle2(editor)) return false;
7067
+ try {
7068
+ const view = editor.view;
7069
+ let state = view.state;
7070
+ let tr = state.tr;
7071
+ if (state.selection.empty || state.selection instanceof import_state8.TextSelection) {
7072
+ const pos = (_a = (0, import_editor_utils22.findNodePosition)({
7073
+ editor,
7074
+ node: state.selection.$anchor.node(1)
7075
+ })) == null ? void 0 : _a.pos;
7076
+ if (!(0, import_editor_utils22.isValidPosition)(pos)) return false;
7077
+ tr = tr.setSelection(import_state8.NodeSelection.create(state.doc, pos));
7078
+ view.dispatch(tr);
7079
+ state = view.state;
7080
+ }
7081
+ const selection = state.selection;
7082
+ let chain = editor.chain().focus();
7083
+ if (selection instanceof import_state8.NodeSelection) {
7084
+ const firstChild = (_b = selection.node.firstChild) == null ? void 0 : _b.firstChild;
7085
+ const lastChild = (_c = selection.node.lastChild) == null ? void 0 : _c.lastChild;
7086
+ const from = firstChild ? selection.from + firstChild.nodeSize : selection.from + 1;
7087
+ const to = lastChild ? selection.to - lastChild.nodeSize : selection.to - 1;
7088
+ chain = chain.setTextSelection({ from, to }).clearNodes();
7089
+ }
7090
+ const toggle = editor.isActive("codeBlock") ? chain.setNode("paragraph") : chain.toggleNode("codeBlock", "paragraph");
7091
+ toggle.run();
7092
+ editor.chain().focus().selectTextblockEnd().run();
7093
+ return true;
7094
+ } catch {
6731
7095
  return false;
6732
7096
  }
6733
- if (hideWhenUnavailable) {
6734
- if ((0, import_react45.isNodeSelection)(editor.state.selection)) {
6735
- return false;
6736
- }
7097
+ }
7098
+ function shouldShowButton5(props) {
7099
+ const { editor, hideWhenUnavailable } = props;
7100
+ if (!editor || !editor.isEditable) return false;
7101
+ if (!(0, import_editor_utils22.isNodeInSchema)("codeBlock", editor)) return false;
7102
+ if (hideWhenUnavailable && !editor.isActive("code")) {
7103
+ return canToggle2(editor);
6737
7104
  }
6738
7105
  return true;
6739
7106
  }
6740
- function getFormattedHeadingName(level) {
6741
- return `Heading ${level}`;
6742
- }
6743
-
6744
- // src/ui/heading-button/index.tsx
6745
- var import_jsx_runtime25 = require("react/jsx-runtime");
6746
- var headingIcons = {
6747
- 1: import_icons19.HeadingOneIcon,
6748
- 2: import_icons19.HeadingTwoIcon,
6749
- 3: import_icons19.HeadingThreeIcon,
6750
- 4: import_icons19.HeadingFourIcon,
6751
- 5: import_icons19.HeadingFiveIcon,
6752
- 6: import_icons19.HeadingSixIcon
6753
- };
6754
- function useHeadingState(editor, level, disabled = false) {
6755
- const headingInSchema = (0, import_editor_utils19.isNodeInSchema)("heading", editor);
6756
- const isDisabled = isHeadingButtonDisabled(editor, level, disabled);
6757
- const isActive = isHeadingActive(editor, level);
6758
- const Icon = headingIcons[level];
6759
- const shortcutKey = headingShortcutKeys[level];
6760
- const formattedName = getFormattedHeadingName(level);
7107
+ function useCodeBlock(config) {
7108
+ const {
7109
+ editor: providedEditor,
7110
+ hideWhenUnavailable = false,
7111
+ onToggled
7112
+ } = config || {};
7113
+ const { editor } = (0, import_editor_utils22.useTiptapEditor)(providedEditor);
7114
+ const [isVisible, setIsVisible] = React17.useState(true);
7115
+ const canToggleState = canToggle2(editor);
7116
+ const isActive = (editor == null ? void 0 : editor.isActive("codeBlock")) || false;
7117
+ React17.useEffect(() => {
7118
+ if (!editor) return;
7119
+ const handleSelectionUpdate = () => {
7120
+ setIsVisible(shouldShowButton5({ editor, hideWhenUnavailable }));
7121
+ };
7122
+ handleSelectionUpdate();
7123
+ editor.on("selectionUpdate", handleSelectionUpdate);
7124
+ return () => {
7125
+ editor.off("selectionUpdate", handleSelectionUpdate);
7126
+ };
7127
+ }, [editor, hideWhenUnavailable]);
7128
+ const handleToggle = React17.useCallback(() => {
7129
+ if (!editor) return false;
7130
+ const success = toggleCodeBlock(editor);
7131
+ if (success) {
7132
+ onToggled == null ? void 0 : onToggled();
7133
+ }
7134
+ return success;
7135
+ }, [editor, onToggled]);
6761
7136
  return {
6762
- headingInSchema,
6763
- isDisabled,
7137
+ isVisible,
6764
7138
  isActive,
6765
- Icon,
6766
- shortcutKey,
6767
- formattedName
7139
+ handleToggle,
7140
+ canToggle: canToggleState,
7141
+ label: "Code Block",
7142
+ shortcutKeys: CODE_BLOCK_SHORTCUT_KEY,
7143
+ Icon: import_icons20.CodeblockIcon
6768
7144
  };
6769
7145
  }
6770
- var HeadingButton = ({
7146
+
7147
+ // src/ui/codeblock-button/code-block-button.tsx
7148
+ var import_jsx_runtime28 = require("react/jsx-runtime");
7149
+ var CodeBlockButton = ({
6771
7150
  editor: providedEditor,
6772
- level,
6773
7151
  text,
6774
7152
  hideWhenUnavailable = false,
6775
- className = "",
6776
- disabled,
7153
+ onToggled,
7154
+ showShortcut = false,
6777
7155
  onClick,
6778
7156
  children,
6779
- ref,
6780
7157
  ...buttonProps
6781
7158
  }) => {
6782
- const { editor } = (0, import_editor_utils19.useTiptapEditor)(providedEditor);
6783
- const {
6784
- headingInSchema,
6785
- isDisabled,
6786
- isActive,
6787
- Icon,
6788
- shortcutKey,
6789
- formattedName
6790
- } = useHeadingState(editor, level, disabled);
6791
- const handleClick = React18.useCallback(
6792
- (e) => {
6793
- onClick == null ? void 0 : onClick(e);
6794
- if (!e.defaultPrevented && !isDisabled && editor) {
6795
- toggleHeading(editor, level);
6796
- }
7159
+ const { editor } = (0, import_editor_utils23.useTiptapEditor)(providedEditor);
7160
+ const { isVisible, canToggle: canToggle3, isActive, handleToggle, label, shortcutKeys } = useCodeBlock({
7161
+ editor,
7162
+ hideWhenUnavailable,
7163
+ onToggled
7164
+ });
7165
+ const handleClick = (0, import_react51.useCallback)(
7166
+ (event) => {
7167
+ onClick == null ? void 0 : onClick(event);
7168
+ if (event.defaultPrevented) return;
7169
+ handleToggle();
6797
7170
  },
6798
- [onClick, isDisabled, editor, level]
7171
+ [handleToggle, onClick]
6799
7172
  );
6800
- const show = React18.useMemo(() => {
6801
- return shouldShowHeadingButton({
6802
- editor,
6803
- level,
6804
- hideWhenUnavailable,
6805
- headingInSchema
6806
- });
6807
- }, [editor, level, hideWhenUnavailable, headingInSchema]);
6808
- if (!show || !editor || !editor.isEditable) {
7173
+ if (!isVisible) {
6809
7174
  return null;
6810
7175
  }
6811
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6812
- import_button12.Button,
7176
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7177
+ import_toolbar8.ToolbarButton,
6813
7178
  {
6814
7179
  type: "button",
6815
- className: className.trim(),
6816
- disabled: isDisabled,
6817
7180
  variant: "ghost",
6818
7181
  color: "default",
7182
+ disabled: !canToggle3,
7183
+ "data-disabled": !canToggle3,
6819
7184
  "data-active-state": isActive ? "on" : "off",
6820
- "data-disabled": isDisabled,
6821
7185
  tabIndex: -1,
6822
- "aria-label": formattedName,
7186
+ "aria-label": "codeBlock",
6823
7187
  "aria-pressed": isActive,
6824
- tooltip: formattedName,
6825
- shortcutKeys: shortcutKey,
7188
+ title: label,
7189
+ shortcutKeys,
6826
7190
  onClick: handleClick,
6827
- startContent: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Icon, {}),
7191
+ isIconOnly: !text && !children,
6828
7192
  ...buttonProps,
6829
- ref,
6830
- children: children || text
7193
+ children: children != null ? children : /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
7194
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_icons21.CodeblockIcon, {}),
7195
+ text && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { children: text })
7196
+ ] })
6831
7197
  }
6832
7198
  );
6833
7199
  };
6834
7200
 
6835
- // src/ui/heading-dropdown-menu/index.tsx
6836
- var import_jsx_runtime26 = require("react/jsx-runtime");
6837
- function HeadingDropdownMenu({
6838
- editor: providedEditor,
6839
- levels = [1, 2, 3, 4, 5, 6],
6840
- hideWhenUnavailable = false,
6841
- onOpenChange,
6842
- ...props
6843
- }) {
6844
- var _a;
6845
- const [isOpen, setIsOpen] = React19.useState(false);
6846
- const { editor } = (0, import_editor_utils20.useTiptapEditor)(providedEditor);
6847
- const headingInSchema = (0, import_editor_utils20.isNodeInSchema)("heading", editor);
6848
- const handleOnOpenChange = React19.useCallback(
6849
- (open) => {
6850
- setIsOpen(open);
6851
- onOpenChange == null ? void 0 : onOpenChange(open);
6852
- },
6853
- [onOpenChange]
6854
- );
6855
- const getActiveIcon = React19.useCallback(() => {
6856
- if (!editor) return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_icons20.HeadingIcon, {});
6857
- const activeLevel = levels.find(
6858
- (level) => editor.isActive("heading", { level })
6859
- );
6860
- if (!activeLevel) return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_icons20.HeadingIcon, {});
6861
- const ActiveIcon = headingIcons[activeLevel];
6862
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ActiveIcon, {});
6863
- }, [editor, levels]);
6864
- const canToggleAnyHeading = React19.useCallback(() => {
6865
- if (!editor) return false;
6866
- return levels.some(
6867
- (level) => editor.can().toggleNode("heading", "paragraph", { level })
6868
- );
6869
- }, [editor, levels]);
6870
- const isDisabled = !canToggleAnyHeading();
6871
- const isAnyHeadingActive = (_a = editor == null ? void 0 : editor.isActive("heading")) != null ? _a : false;
6872
- const show = React19.useMemo(() => {
6873
- if (!headingInSchema || !editor) {
6874
- return false;
6875
- }
6876
- if (hideWhenUnavailable) {
6877
- if ((0, import_react46.isNodeSelection)(editor.state.selection) || !canToggleAnyHeading()) {
6878
- return false;
6879
- }
6880
- }
6881
- return true;
6882
- }, [headingInSchema, editor, hideWhenUnavailable, canToggleAnyHeading]);
6883
- if (!show || !editor || !editor.isEditable) {
6884
- return null;
6885
- }
6886
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_dropdown_menu.DropdownMenu.Root, { open: isOpen, onOpenChange: handleOnOpenChange, children: [
6887
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_dropdown_menu.DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6888
- import_button13.Button,
6889
- {
6890
- type: "button",
6891
- disabled: isDisabled,
6892
- variant: "ghost",
6893
- color: "default",
6894
- "data-active-state": isAnyHeadingActive ? "on" : "off",
6895
- "data-disabled": isDisabled,
6896
- tabIndex: -1,
6897
- "aria-label": "Format text as heading",
6898
- "aria-pressed": isAnyHeadingActive,
6899
- tooltip: "Heading",
6900
- endContent: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_icons20.ChevronDownIcon, {}),
6901
- ...props,
6902
- children: getActiveIcon()
6903
- }
6904
- ) }),
6905
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_dropdown_menu.DropdownMenu.Content, { children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_dropdown_menu.DropdownMenu.Group, { children: levels.map((level) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_dropdown_menu.DropdownMenu.Item, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6906
- HeadingButton,
6907
- {
6908
- editor,
6909
- level,
6910
- text: getFormattedHeadingName(level),
6911
- tooltip: "",
6912
- fullWidth: true,
6913
- spacing: "start"
6914
- }
6915
- ) }, `heading-${level}`)) }) })
6916
- ] });
6917
- }
6918
-
6919
- // src/ui/list-dropdown-menu/index.tsx
7201
+ // src/ui/heading-button/index.tsx
6920
7202
  var import_button15 = require("@kopexa/button");
6921
- var import_dropdown_menu2 = require("@kopexa/dropdown-menu");
6922
- var import_editor_utils22 = require("@kopexa/editor-utils");
7203
+ var import_editor_utils24 = require("@kopexa/editor-utils");
6923
7204
  var import_icons22 = require("@kopexa/icons");
6924
- var import_react49 = require("@tiptap/react");
6925
- var import_react50 = require("react");
7205
+ var React18 = __toESM(require("react"));
6926
7206
 
6927
- // src/ui/list-button/index.tsx
6928
- var import_button14 = require("@kopexa/button");
6929
- var import_editor_utils21 = require("@kopexa/editor-utils");
6930
- var import_icons21 = require("@kopexa/icons");
6931
- var import_react47 = require("@tiptap/react");
6932
- var import_react48 = require("react");
6933
- var import_jsx_runtime27 = require("react/jsx-runtime");
6934
- var listOptions = [
6935
- {
6936
- label: "Bullet List",
6937
- type: "bulletList",
6938
- icon: import_icons21.ListIcon
6939
- },
6940
- {
6941
- label: "Ordered List",
6942
- type: "orderedList",
6943
- icon: import_icons21.ListOrderedIcon
6944
- },
6945
- {
6946
- label: "Task List",
6947
- type: "taskList",
6948
- icon: import_icons21.ListTodoIcon
6949
- }
6950
- ];
6951
- var listShortcutKeys = {
6952
- bulletList: "Ctrl-Shift-8",
6953
- orderedList: "Ctrl-Shift-7",
6954
- taskList: "Ctrl-Shift-9"
7207
+ // src/ui/heading-button/utils.ts
7208
+ var import_react52 = require("@tiptap/react");
7209
+ var headingShortcutKeys = {
7210
+ 1: "Ctrl-Alt-1",
7211
+ 2: "Ctrl-Alt-2",
7212
+ 3: "Ctrl-Alt-3",
7213
+ 4: "Ctrl-Alt-4",
7214
+ 5: "Ctrl-Alt-5",
7215
+ 6: "Ctrl-Alt-6"
6955
7216
  };
6956
- function canToggleList(editor, type) {
6957
- if (!editor) {
7217
+ function canToggleHeading(editor, level) {
7218
+ if (!editor) return false;
7219
+ try {
7220
+ return editor.can().toggleNode("heading", "paragraph", { level });
7221
+ } catch {
6958
7222
  return false;
6959
7223
  }
6960
- switch (type) {
6961
- case "bulletList":
6962
- return editor.can().toggleBulletList();
6963
- case "orderedList":
6964
- return editor.can().toggleOrderedList();
6965
- case "taskList":
6966
- return editor.can().toggleList("taskList", "taskItem");
6967
- default:
6968
- return false;
6969
- }
6970
7224
  }
6971
- function isListActive(editor, type) {
7225
+ function isHeadingActive(editor, level) {
6972
7226
  if (!editor) return false;
6973
- switch (type) {
6974
- case "bulletList":
6975
- return editor.isActive("bulletList");
6976
- case "orderedList":
6977
- return editor.isActive("orderedList");
6978
- case "taskList":
6979
- return editor.isActive("taskList");
6980
- default:
6981
- return false;
6982
- }
7227
+ return editor.isActive("heading", { level });
6983
7228
  }
6984
- function toggleList(editor, type) {
7229
+ function toggleHeading(editor, level) {
6985
7230
  if (!editor) return;
6986
- switch (type) {
6987
- case "bulletList":
6988
- editor.chain().focus().toggleBulletList().run();
6989
- break;
6990
- case "orderedList":
6991
- editor.chain().focus().toggleOrderedList().run();
6992
- break;
6993
- case "taskList":
6994
- editor.chain().focus().toggleList("taskList", "taskItem").run();
6995
- break;
7231
+ if (editor.isActive("heading", { level })) {
7232
+ editor.chain().focus().setNode("paragraph").run();
7233
+ } else {
7234
+ editor.chain().focus().toggleNode("heading", "paragraph", { level }).run();
6996
7235
  }
6997
7236
  }
6998
- function getListOption(type) {
6999
- return listOptions.find((option) => option.type === type);
7237
+ function isHeadingButtonDisabled(editor, level, userDisabled = false) {
7238
+ if (!editor) return true;
7239
+ if (userDisabled) return true;
7240
+ if (!canToggleHeading(editor, level)) return true;
7241
+ return false;
7000
7242
  }
7001
- function shouldShowListButton(params) {
7002
- const { editor, type, hideWhenUnavailable, listInSchema } = params;
7003
- if (!listInSchema || !editor) {
7243
+ function shouldShowHeadingButton(params) {
7244
+ const { editor, hideWhenUnavailable, headingInSchema } = params;
7245
+ if (!headingInSchema || !editor) {
7004
7246
  return false;
7005
7247
  }
7006
7248
  if (hideWhenUnavailable) {
7007
- if ((0, import_react47.isNodeSelection)(editor.state.selection) || !canToggleList(editor, type)) {
7249
+ if ((0, import_react52.isNodeSelection)(editor.state.selection)) {
7008
7250
  return false;
7009
7251
  }
7010
7252
  }
7011
7253
  return true;
7012
7254
  }
7013
- function useListState(editor, type) {
7014
- const listInSchema = (0, import_editor_utils21.isNodeInSchema)(type, editor);
7015
- const listOption = getListOption(type);
7016
- const isActive = isListActive(editor, type);
7017
- const shortcutKey = listShortcutKeys[type];
7255
+ function getFormattedHeadingName(level) {
7256
+ return `Heading ${level}`;
7257
+ }
7258
+
7259
+ // src/ui/heading-button/index.tsx
7260
+ var import_jsx_runtime29 = require("react/jsx-runtime");
7261
+ var headingIcons = {
7262
+ 1: import_icons22.HeadingOneIcon,
7263
+ 2: import_icons22.HeadingTwoIcon,
7264
+ 3: import_icons22.HeadingThreeIcon,
7265
+ 4: import_icons22.HeadingFourIcon,
7266
+ 5: import_icons22.HeadingFiveIcon,
7267
+ 6: import_icons22.HeadingSixIcon
7268
+ };
7269
+ function useHeadingState(editor, level, disabled = false) {
7270
+ const headingInSchema = (0, import_editor_utils24.isNodeInSchema)("heading", editor);
7271
+ const isDisabled = isHeadingButtonDisabled(editor, level, disabled);
7272
+ const isActive = isHeadingActive(editor, level);
7273
+ const Icon = headingIcons[level];
7274
+ const shortcutKey = headingShortcutKeys[level];
7275
+ const formattedName = getFormattedHeadingName(level);
7018
7276
  return {
7019
- listInSchema,
7020
- listOption,
7277
+ headingInSchema,
7278
+ isDisabled,
7021
7279
  isActive,
7022
- shortcutKey
7280
+ Icon,
7281
+ shortcutKey,
7282
+ formattedName
7023
7283
  };
7024
7284
  }
7025
- var ListButton = ({
7285
+ var HeadingButton = ({
7026
7286
  editor: providedEditor,
7027
- type,
7287
+ level,
7288
+ text,
7028
7289
  hideWhenUnavailable = false,
7029
7290
  className = "",
7291
+ disabled,
7030
7292
  onClick,
7031
- text,
7032
7293
  children,
7033
7294
  ref,
7034
7295
  ...buttonProps
7035
7296
  }) => {
7036
- const { editor } = (0, import_editor_utils21.useTiptapEditor)(providedEditor);
7037
- const { listInSchema, listOption, isActive, shortcutKey } = useListState(
7038
- editor,
7039
- type
7040
- );
7041
- const Icon = (listOption == null ? void 0 : listOption.icon) || import_icons21.ListIcon;
7042
- const handleClick = (0, import_react48.useCallback)(
7297
+ const { editor } = (0, import_editor_utils24.useTiptapEditor)(providedEditor);
7298
+ const {
7299
+ headingInSchema,
7300
+ isDisabled,
7301
+ isActive,
7302
+ Icon,
7303
+ shortcutKey,
7304
+ formattedName
7305
+ } = useHeadingState(editor, level, disabled);
7306
+ const handleClick = React18.useCallback(
7043
7307
  (e) => {
7044
7308
  onClick == null ? void 0 : onClick(e);
7045
- if (!e.defaultPrevented && editor) {
7046
- toggleList(editor, type);
7309
+ if (!e.defaultPrevented && !isDisabled && editor) {
7310
+ toggleHeading(editor, level);
7047
7311
  }
7048
7312
  },
7049
- [onClick, editor, type]
7313
+ [onClick, isDisabled, editor, level]
7050
7314
  );
7051
- const show = (0, import_react48.useMemo)(() => {
7052
- return shouldShowListButton({
7315
+ const show = React18.useMemo(() => {
7316
+ return shouldShowHeadingButton({
7053
7317
  editor,
7054
- type,
7318
+ level,
7055
7319
  hideWhenUnavailable,
7056
- listInSchema
7320
+ headingInSchema
7057
7321
  });
7058
- }, [editor, type, hideWhenUnavailable, listInSchema]);
7322
+ }, [editor, level, hideWhenUnavailable, headingInSchema]);
7059
7323
  if (!show || !editor || !editor.isEditable) {
7060
7324
  return null;
7061
7325
  }
7062
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
7063
- import_button14.Button,
7326
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7327
+ import_button15.Button,
7064
7328
  {
7065
7329
  type: "button",
7066
7330
  className: className.trim(),
7331
+ disabled: isDisabled,
7067
7332
  variant: "ghost",
7068
7333
  color: "default",
7069
7334
  "data-active-state": isActive ? "on" : "off",
7335
+ "data-disabled": isDisabled,
7070
7336
  tabIndex: -1,
7071
- "aria-label": (listOption == null ? void 0 : listOption.label) || type,
7337
+ "aria-label": formattedName,
7072
7338
  "aria-pressed": isActive,
7073
- tooltip: (listOption == null ? void 0 : listOption.label) || type,
7339
+ tooltip: formattedName,
7074
7340
  shortcutKeys: shortcutKey,
7075
7341
  onClick: handleClick,
7076
- startContent: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Icon, {}),
7342
+ startContent: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Icon, {}),
7077
7343
  ...buttonProps,
7078
7344
  ref,
7079
7345
  children: children || text
@@ -7081,162 +7347,189 @@ var ListButton = ({
7081
7347
  );
7082
7348
  };
7083
7349
 
7084
- // src/ui/list-dropdown-menu/index.tsx
7085
- var import_jsx_runtime28 = require("react/jsx-runtime");
7086
- function canToggleAnyList(editor, listTypes) {
7350
+ // src/ui/text-button/text-button.tsx
7351
+ var import_button16 = require("@kopexa/button");
7352
+ var import_chip = require("@kopexa/chip");
7353
+ var import_editor_utils26 = require("@kopexa/editor-utils");
7354
+ var import_shared_utils = require("@kopexa/shared-utils");
7355
+ var import_react54 = require("react");
7356
+
7357
+ // src/ui/text-button/use-text.ts
7358
+ var import_editor_utils25 = require("@kopexa/editor-utils");
7359
+ var import_icons23 = require("@kopexa/icons");
7360
+ var import_use_is_mobile2 = require("@kopexa/use-is-mobile");
7361
+ var import_state9 = require("@tiptap/pm/state");
7362
+ var import_react53 = require("react");
7363
+ var import_react_hotkeys_hook2 = require("react-hotkeys-hook");
7364
+ var TEXT_SHORTCUT_KEY = "mod+alt+0";
7365
+ function canToggleText(editor, turnInto = true) {
7087
7366
  if (!editor) return false;
7088
- return listTypes.some((type) => canToggleList(editor, type));
7367
+ if (!editor.schema.nodes.paragraph) return false;
7368
+ if (!turnInto) {
7369
+ return editor.can().setNode("paragraph");
7370
+ }
7371
+ if (!(0, import_editor_utils25.selectionWithinConvertibleTypes)(editor, [
7372
+ "paragraph",
7373
+ "heading",
7374
+ "bulletList",
7375
+ "orderedList",
7376
+ "taskList",
7377
+ "blockquote",
7378
+ "codeBlock"
7379
+ ]))
7380
+ return false;
7381
+ return editor.can().setNode("paragraph") || editor.can().clearNodes();
7089
7382
  }
7090
- function isAnyListActive(editor, listTypes) {
7383
+ function isParagraphActive(editor) {
7091
7384
  if (!editor) return false;
7092
- return listTypes.some((type) => isListActive(editor, type));
7093
- }
7094
- function getFilteredListOptions(availableTypes) {
7095
- return listOptions.filter(
7096
- (option) => !option.type || availableTypes.includes(option.type)
7097
- );
7385
+ return editor.isActive("paragraph");
7098
7386
  }
7099
- function shouldShowListDropdown(params) {
7100
- const { editor, hideWhenUnavailable, listInSchema, canToggleAny } = params;
7101
- if (!listInSchema || !editor) {
7387
+ function toggleParagraph(editor) {
7388
+ var _a, _b, _c;
7389
+ if (!editor || !editor.isEditable) return false;
7390
+ if (!canToggleText(editor)) return false;
7391
+ try {
7392
+ const view = editor.view;
7393
+ let state = view.state;
7394
+ let tr = state.tr;
7395
+ const blocks = (0, import_editor_utils25.getSelectedBlockNodes)(editor);
7396
+ const isPossibleToTurnInto = (0, import_editor_utils25.selectionWithinConvertibleTypes)(editor, [
7397
+ "paragraph",
7398
+ "heading",
7399
+ "bulletList",
7400
+ "orderedList",
7401
+ "taskList",
7402
+ "blockquote",
7403
+ "codeBlock"
7404
+ ]) && blocks.length === 1;
7405
+ if ((state.selection.empty || state.selection instanceof import_state9.TextSelection) && isPossibleToTurnInto) {
7406
+ const pos = (_a = (0, import_editor_utils25.findNodePosition)({
7407
+ editor,
7408
+ node: state.selection.$anchor.node(1)
7409
+ })) == null ? void 0 : _a.pos;
7410
+ if (!(0, import_editor_utils25.isValidPosition)(pos)) return false;
7411
+ tr = tr.setSelection(import_state9.NodeSelection.create(state.doc, pos));
7412
+ view.dispatch(tr);
7413
+ state = view.state;
7414
+ }
7415
+ const selection = state.selection;
7416
+ let chain = editor.chain().focus();
7417
+ if (selection instanceof import_state9.NodeSelection) {
7418
+ const firstChild = (_b = selection.node.firstChild) == null ? void 0 : _b.firstChild;
7419
+ const lastChild = (_c = selection.node.lastChild) == null ? void 0 : _c.lastChild;
7420
+ const from = firstChild ? selection.from + firstChild.nodeSize : selection.from + 1;
7421
+ const to = lastChild ? selection.to - lastChild.nodeSize : selection.to - 1;
7422
+ const resolvedFrom = state.doc.resolve(from);
7423
+ const resolvedTo = state.doc.resolve(to);
7424
+ chain = chain.setTextSelection(import_state9.TextSelection.between(resolvedFrom, resolvedTo)).clearNodes();
7425
+ }
7426
+ if (!editor.isActive("paragraph")) {
7427
+ chain.setNode("paragraph").run();
7428
+ }
7429
+ editor.chain().focus().selectTextblockEnd().run();
7430
+ return true;
7431
+ } catch {
7102
7432
  return false;
7103
7433
  }
7104
- if (hideWhenUnavailable) {
7105
- if ((0, import_react49.isNodeSelection)(editor.state.selection) || !canToggleAny) {
7106
- return false;
7107
- }
7434
+ }
7435
+ function shouldShowButton6(props) {
7436
+ const { editor, hideWhenUnavailable } = props;
7437
+ if (!editor || !editor.isEditable) return false;
7438
+ if (!hideWhenUnavailable) {
7439
+ return true;
7440
+ }
7441
+ if (!(0, import_editor_utils25.isNodeInSchema)("paragraph", editor)) return false;
7442
+ if (!editor.isActive("code")) {
7443
+ return canToggleText(editor);
7108
7444
  }
7109
7445
  return true;
7110
7446
  }
7111
- function useListDropdownState(editor, availableTypes) {
7112
- const [isOpen, setIsOpen] = (0, import_react50.useState)(false);
7113
- const listInSchema = availableTypes.some(
7114
- (type) => (0, import_editor_utils22.isNodeInSchema)(type, editor)
7115
- );
7116
- const filteredLists = (0, import_react50.useMemo)(
7117
- () => getFilteredListOptions(availableTypes),
7118
- [availableTypes]
7119
- );
7120
- const canToggleAny = canToggleAnyList(editor, availableTypes);
7121
- const isAnyActive = isAnyListActive(editor, availableTypes);
7122
- const handleOpenChange = (0, import_react50.useCallback)(
7123
- (open, callback) => {
7124
- setIsOpen(open);
7125
- callback == null ? void 0 : callback(open);
7126
- },
7127
- []
7128
- );
7129
- return {
7130
- isOpen,
7131
- setIsOpen,
7132
- listInSchema,
7133
- filteredLists,
7134
- canToggleAny,
7135
- isAnyActive,
7136
- handleOpenChange
7137
- };
7138
- }
7139
- function useActiveListIcon(editor, filteredLists) {
7140
- return (0, import_react50.useCallback)(() => {
7141
- const activeOption = filteredLists.find(
7142
- (option) => isListActive(editor, option.type)
7143
- );
7144
- return activeOption ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(activeOption.icon, {}) : /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_icons22.ListIcon, {});
7145
- }, [editor, filteredLists]);
7146
- }
7147
- function ListDropdownMenu({
7148
- editor: providedEditor,
7149
- types = ["bulletList", "orderedList", "taskList"],
7150
- hideWhenUnavailable = false,
7151
- onOpenChange,
7152
- ...props
7153
- }) {
7154
- const { editor } = (0, import_editor_utils22.useTiptapEditor)(providedEditor);
7447
+ function useText(config) {
7155
7448
  const {
7156
- isOpen,
7157
- listInSchema,
7158
- filteredLists,
7159
- canToggleAny,
7160
- isAnyActive,
7161
- handleOpenChange
7162
- } = useListDropdownState(editor, types);
7163
- const getActiveIcon = useActiveListIcon(editor, filteredLists);
7164
- const show = (0, import_react50.useMemo)(() => {
7165
- return shouldShowListDropdown({
7166
- editor,
7167
- listTypes: types,
7168
- hideWhenUnavailable,
7169
- listInSchema,
7170
- canToggleAny
7171
- });
7172
- }, [editor, types, hideWhenUnavailable, listInSchema, canToggleAny]);
7173
- const handleOnOpenChange = (0, import_react50.useCallback)(
7174
- (open) => handleOpenChange(open, onOpenChange),
7175
- [handleOpenChange, onOpenChange]
7176
- );
7177
- if (!show || !editor || !editor.isEditable) {
7178
- return null;
7179
- }
7180
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_dropdown_menu2.DropdownMenu.Root, { open: isOpen, onOpenChange: handleOnOpenChange, children: [
7181
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_dropdown_menu2.DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7182
- import_button15.Button,
7183
- {
7184
- type: "button",
7185
- variant: "ghost",
7186
- color: "default",
7187
- "data-active-state": isAnyActive ? "on" : "off",
7188
- tabIndex: -1,
7189
- "aria-label": "List options",
7190
- tooltip: "List",
7191
- endContent: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_icons22.ChevronDownIcon, {}),
7192
- ...props,
7193
- children: getActiveIcon()
7194
- }
7195
- ) }),
7196
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_dropdown_menu2.DropdownMenu.Content, { children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_dropdown_menu2.DropdownMenu.Group, { children: filteredLists.map((option) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_dropdown_menu2.DropdownMenu.Item, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7197
- ListButton,
7198
- {
7199
- editor,
7200
- type: option.type,
7201
- text: option.label,
7202
- hideWhenUnavailable,
7203
- tooltip: "",
7204
- fullWidth: true,
7205
- spacing: "start"
7206
- }
7207
- ) }, option.type)) }) })
7208
- ] });
7449
+ editor: providedEditor,
7450
+ hideWhenUnavailable = false,
7451
+ onToggled
7452
+ } = config || {};
7453
+ const { editor } = (0, import_editor_utils25.useTiptapEditor)(providedEditor);
7454
+ const isMobile = (0, import_use_is_mobile2.useIsMobile)();
7455
+ const [isVisible, setIsVisible] = (0, import_react53.useState)(true);
7456
+ const canToggle3 = canToggleText(editor);
7457
+ const isActive = isParagraphActive(editor);
7458
+ (0, import_react53.useEffect)(() => {
7459
+ if (!editor) return;
7460
+ const handleSelectionUpdate = () => {
7461
+ setIsVisible(shouldShowButton6({ editor, hideWhenUnavailable }));
7462
+ };
7463
+ handleSelectionUpdate();
7464
+ editor.on("selectionUpdate", handleSelectionUpdate);
7465
+ return () => {
7466
+ editor.off("selectionUpdate", handleSelectionUpdate);
7467
+ };
7468
+ }, [editor, hideWhenUnavailable]);
7469
+ const handleToggle = (0, import_react53.useCallback)(() => {
7470
+ if (!editor) return false;
7471
+ const success = toggleParagraph(editor);
7472
+ if (success) {
7473
+ onToggled == null ? void 0 : onToggled();
7474
+ }
7475
+ return success;
7476
+ }, [editor, onToggled]);
7477
+ (0, import_react_hotkeys_hook2.useHotkeys)(
7478
+ TEXT_SHORTCUT_KEY,
7479
+ (event) => {
7480
+ event.preventDefault();
7481
+ handleToggle();
7482
+ },
7483
+ {
7484
+ enabled: isVisible && canToggle3,
7485
+ enableOnContentEditable: !isMobile,
7486
+ enableOnFormTags: true
7487
+ }
7488
+ );
7489
+ return {
7490
+ isVisible,
7491
+ isActive,
7492
+ handleToggle,
7493
+ canToggle: canToggle3,
7494
+ label: "Text",
7495
+ shortcutKeys: TEXT_SHORTCUT_KEY,
7496
+ Icon: import_icons23.TypeIcon
7497
+ };
7209
7498
  }
7210
7499
 
7211
- // src/ui/table-button/index.tsx
7212
- var import_editor_utils23 = require("@kopexa/editor-utils");
7213
- var import_toolbar8 = require("@kopexa/toolbar");
7214
- var import_react51 = require("react");
7215
- var import_jsx_runtime29 = require("react/jsx-runtime");
7216
- var TableButton = ({
7500
+ // src/ui/text-button/text-button.tsx
7501
+ var import_jsx_runtime30 = require("react/jsx-runtime");
7502
+ function TextShortcutBadge({
7503
+ shortcutKeys = TEXT_SHORTCUT_KEY
7504
+ }) {
7505
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_chip.Chip, { children: (0, import_shared_utils.parseShortcutKeys)({ shortcutKeys }) });
7506
+ }
7507
+ var TextButton = ({
7217
7508
  editor: providedEditor,
7218
7509
  text,
7219
7510
  hideWhenUnavailable = false,
7220
7511
  onToggled,
7512
+ showShortcut = false,
7221
7513
  onClick,
7222
7514
  children,
7515
+ ref,
7223
7516
  ...buttonProps
7224
7517
  }) => {
7225
- const { editor } = (0, import_editor_utils23.useTiptapEditor)(providedEditor);
7518
+ const { editor } = (0, import_editor_utils26.useTiptapEditor)(providedEditor);
7226
7519
  const {
7227
7520
  isVisible,
7228
7521
  canToggle: canToggle3,
7229
7522
  isActive,
7230
7523
  handleToggle,
7231
7524
  label,
7232
- // shortcutKeys,
7525
+ shortcutKeys,
7233
7526
  Icon
7234
- } = useTableBlock({
7527
+ } = useText({
7235
7528
  editor,
7236
7529
  hideWhenUnavailable,
7237
7530
  onToggled
7238
7531
  });
7239
- const handleClick = (0, import_react51.useCallback)(
7532
+ const handleClick = (0, import_react54.useCallback)(
7240
7533
  (event) => {
7241
7534
  onClick == null ? void 0 : onClick(event);
7242
7535
  if (event.defaultPrevented) return;
@@ -7247,198 +7540,343 @@ var TableButton = ({
7247
7540
  if (!isVisible) {
7248
7541
  return null;
7249
7542
  }
7250
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7251
- import_toolbar8.ToolbarButton,
7543
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7544
+ import_button16.Button,
7252
7545
  {
7253
7546
  type: "button",
7254
7547
  variant: "ghost",
7255
7548
  color: "default",
7256
7549
  "data-active-state": isActive ? "on" : "off",
7550
+ tabIndex: -1,
7257
7551
  disabled: !canToggle3,
7258
7552
  "data-disabled": !canToggle3,
7259
- tabIndex: -1,
7260
7553
  "aria-label": label,
7261
7554
  "aria-pressed": isActive,
7262
- title: label,
7555
+ tooltip: "Text",
7556
+ shortcutKeys,
7263
7557
  onClick: handleClick,
7264
- isIconOnly: !text && !children,
7558
+ startContent: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Icon, {}),
7265
7559
  ...buttonProps,
7266
- children: children || /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_jsx_runtime29.Fragment, { children: [
7267
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Icon, {}),
7268
- text && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: text })
7560
+ ref,
7561
+ children: children != null ? children : /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
7562
+ text,
7563
+ showShortcut && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TextShortcutBadge, { shortcutKeys })
7269
7564
  ] })
7270
7565
  }
7271
7566
  );
7272
7567
  };
7273
7568
 
7274
- // src/ui/text-align-button/text-align-button.tsx
7275
- var import_button16 = require("@kopexa/button");
7276
- var import_editor_utils25 = require("@kopexa/editor-utils");
7277
- var import_react53 = require("react");
7278
-
7279
- // src/ui/text-align-button/use-text-align.ts
7280
- var import_editor_utils24 = require("@kopexa/editor-utils");
7281
- var import_icons23 = require("@kopexa/icons");
7282
- var import_react52 = require("react");
7283
- var TEXT_ALIGN_SHORTCUT_KEYS = {
7284
- left: "mod+shift+l",
7285
- center: "mod+shift+e",
7286
- right: "mod+shift+r",
7287
- justify: "mod+shift+j"
7288
- };
7289
- var textAlignIcons = {
7290
- left: import_icons23.AlignLeftIcon,
7291
- center: import_icons23.AlignCenterIcon,
7292
- right: import_icons23.AlignRightIcon,
7293
- justify: import_icons23.AlignJustifyIcon
7294
- };
7295
- var textAlignLabels = {
7296
- left: "Align left",
7297
- center: "Align center",
7298
- right: "Align right",
7299
- justify: "Align justify"
7300
- };
7301
- function canSetTextAlign(editor, align) {
7569
+ // src/ui/turn-into-dropdown/use-turn-into-dropdown.ts
7570
+ var import_editor_utils27 = require("@kopexa/editor-utils");
7571
+ var import_icons24 = require("@kopexa/icons");
7572
+ var import_state10 = require("@tiptap/pm/state");
7573
+ var import_react55 = require("react");
7574
+ var TURN_INTO_BLOCKS = [
7575
+ "paragraph",
7576
+ "heading",
7577
+ "bulletList",
7578
+ "orderedList",
7579
+ "taskList",
7580
+ "blockquote",
7581
+ "codeBlock"
7582
+ ];
7583
+ var blockTypeOptions = [
7584
+ {
7585
+ type: "paragraph",
7586
+ label: "Text",
7587
+ isActive: (editor) => editor.isActive("paragraph") && !editor.isActive("heading") && !editor.isActive("bulletList") && !editor.isActive("orderedList") && !editor.isActive("taskList") && !editor.isActive("blockquote") && !editor.isActive("codeBlock")
7588
+ },
7589
+ {
7590
+ type: "heading",
7591
+ label: "Heading 1",
7592
+ level: 1,
7593
+ isActive: (editor) => editor.isActive("heading", { level: 1 })
7594
+ },
7595
+ {
7596
+ type: "heading",
7597
+ label: "Heading 2",
7598
+ level: 2,
7599
+ isActive: (editor) => editor.isActive("heading", { level: 2 })
7600
+ },
7601
+ {
7602
+ type: "heading",
7603
+ label: "Heading 3",
7604
+ level: 3,
7605
+ isActive: (editor) => editor.isActive("heading", { level: 3 })
7606
+ },
7607
+ {
7608
+ type: "heading",
7609
+ label: "Heading 4",
7610
+ level: 4,
7611
+ isActive: (editor) => editor.isActive("heading", { level: 4 })
7612
+ },
7613
+ {
7614
+ type: "bulletList",
7615
+ label: "Bulleted list",
7616
+ isActive: (editor) => editor.isActive("bulletList")
7617
+ },
7618
+ {
7619
+ type: "orderedList",
7620
+ label: "Numbered list",
7621
+ isActive: (editor) => editor.isActive("orderedList")
7622
+ },
7623
+ {
7624
+ type: "taskList",
7625
+ label: "To-do list",
7626
+ isActive: (editor) => editor.isActive("taskList")
7627
+ },
7628
+ {
7629
+ type: "blockquote",
7630
+ label: "Blockquote",
7631
+ isActive: (editor) => editor.isActive("blockquote")
7632
+ },
7633
+ {
7634
+ type: "codeBlock",
7635
+ label: "Code block",
7636
+ isActive: (editor) => editor.isActive("codeBlock")
7637
+ }
7638
+ ];
7639
+ function canTurnInto(editor, allowedBlockTypes) {
7302
7640
  if (!editor || !editor.isEditable) return false;
7303
- if (!(0, import_editor_utils24.isExtensionAvailable)(editor, "textAlign") || (0, import_editor_utils24.isNodeTypeSelected)(editor, ["image"]))
7304
- return false;
7305
- return editor.can().setTextAlign(align);
7306
- }
7307
- function hasSetTextAlign(commands) {
7308
- return "setTextAlign" in commands;
7641
+ const blockTypes = allowedBlockTypes || TURN_INTO_BLOCKS;
7642
+ const { selection } = editor.state;
7643
+ if (selection instanceof import_state10.NodeSelection) {
7644
+ const nodeType2 = selection.node.type.name;
7645
+ return blockTypes.includes(nodeType2);
7646
+ }
7647
+ const { $anchor } = selection;
7648
+ const nodeType = $anchor.parent.type.name;
7649
+ return blockTypes.includes(nodeType);
7309
7650
  }
7310
- function isTextAlignActive(editor, align) {
7311
- if (!editor || !editor.isEditable) return false;
7312
- return editor.isActive({ textAlign: align });
7651
+ function getFilteredBlockTypeOptions(blockTypes) {
7652
+ if (!blockTypes) return blockTypeOptions;
7653
+ return blockTypeOptions.filter((option) => {
7654
+ return blockTypes.includes(option.type);
7655
+ });
7313
7656
  }
7314
- function setTextAlign(editor, align) {
7315
- if (!editor || !editor.isEditable) return false;
7316
- if (!canSetTextAlign(editor, align)) return false;
7317
- const chain = editor.chain().focus();
7318
- if (hasSetTextAlign(chain)) {
7319
- return chain.setTextAlign(align).run();
7320
- }
7321
- return false;
7657
+ function getActiveBlockType(editor, blockTypes) {
7658
+ if (!editor) return getFilteredBlockTypeOptions(blockTypes)[0];
7659
+ const filteredOptions = getFilteredBlockTypeOptions(blockTypes);
7660
+ const activeOption = filteredOptions.find(
7661
+ (option) => option.isActive(editor)
7662
+ );
7663
+ return activeOption || filteredOptions[0];
7322
7664
  }
7323
- function shouldShowButton5(props) {
7324
- const { editor, hideWhenUnavailable, align } = props;
7665
+ function shouldShowTurnInto(params) {
7666
+ const { editor, hideWhenUnavailable, blockTypes } = params;
7325
7667
  if (!editor || !editor.isEditable) return false;
7326
- if (!(0, import_editor_utils24.isExtensionAvailable)(editor, "textAlign")) return false;
7327
7668
  if (hideWhenUnavailable && !editor.isActive("code")) {
7328
- return canSetTextAlign(editor, align);
7669
+ return canTurnInto(editor, blockTypes);
7329
7670
  }
7330
7671
  return true;
7331
7672
  }
7332
- function useTextAlign(config) {
7673
+ function useTurnIntoDropdown(config) {
7333
7674
  const {
7334
7675
  editor: providedEditor,
7335
- align,
7336
7676
  hideWhenUnavailable = false,
7337
- onAligned
7338
- } = config;
7339
- const { editor } = (0, import_editor_utils24.useTiptapEditor)(providedEditor);
7340
- const [isVisible, setIsVisible] = (0, import_react52.useState)(true);
7341
- const canAlign = canSetTextAlign(editor, align);
7342
- const isActive = isTextAlignActive(editor, align);
7343
- (0, import_react52.useEffect)(() => {
7677
+ blockTypes,
7678
+ onOpenChange
7679
+ } = config || {};
7680
+ const { editor } = (0, import_editor_utils27.useTiptapEditor)(providedEditor);
7681
+ const [isOpen, setIsOpen] = (0, import_react55.useState)(false);
7682
+ const [isVisible, setIsVisible] = (0, import_react55.useState)(true);
7683
+ const canToggle3 = canTurnInto(editor, blockTypes);
7684
+ const activeBlockType = getActiveBlockType(editor, blockTypes);
7685
+ const handleOpenChange = (0, import_react55.useCallback)(
7686
+ (open) => {
7687
+ if (!editor || !canToggle3) return;
7688
+ setIsOpen(open);
7689
+ onOpenChange == null ? void 0 : onOpenChange(open);
7690
+ },
7691
+ [canToggle3, editor, onOpenChange]
7692
+ );
7693
+ (0, import_react55.useEffect)(() => {
7344
7694
  if (!editor) return;
7345
7695
  const handleSelectionUpdate = () => {
7346
- setIsVisible(shouldShowButton5({ editor, align, hideWhenUnavailable }));
7696
+ setIsVisible(
7697
+ shouldShowTurnInto({
7698
+ editor,
7699
+ hideWhenUnavailable,
7700
+ blockTypes
7701
+ })
7702
+ );
7347
7703
  };
7348
7704
  handleSelectionUpdate();
7349
7705
  editor.on("selectionUpdate", handleSelectionUpdate);
7350
7706
  return () => {
7351
7707
  editor.off("selectionUpdate", handleSelectionUpdate);
7352
7708
  };
7353
- }, [editor, hideWhenUnavailable, align]);
7354
- const handleTextAlign = (0, import_react52.useCallback)(() => {
7355
- if (!editor) return false;
7356
- const success = setTextAlign(editor, align);
7357
- if (success) {
7358
- onAligned == null ? void 0 : onAligned();
7359
- }
7360
- return success;
7361
- }, [editor, align, onAligned]);
7709
+ }, [editor, hideWhenUnavailable, blockTypes]);
7362
7710
  return {
7363
7711
  isVisible,
7364
- isActive,
7365
- handleTextAlign,
7366
- canAlign,
7367
- label: textAlignLabels[align],
7368
- shortcutKeys: TEXT_ALIGN_SHORTCUT_KEYS[align],
7369
- Icon: textAlignIcons[align]
7712
+ canToggle: canToggle3,
7713
+ isOpen,
7714
+ setIsOpen,
7715
+ activeBlockType,
7716
+ handleOpenChange,
7717
+ filteredOptions: getFilteredBlockTypeOptions(blockTypes),
7718
+ label: `Turn into (current: ${(activeBlockType == null ? void 0 : activeBlockType.label) || "Text"})`,
7719
+ Icon: import_icons24.ChevronDownIcon
7370
7720
  };
7371
7721
  }
7372
7722
 
7373
- // src/ui/text-align-button/text-align-button.tsx
7374
- var import_jsx_runtime30 = require("react/jsx-runtime");
7375
- var TextAlignButton = ({
7376
- editor: providedEditor,
7377
- align,
7378
- text,
7379
- hideWhenUnavailable = false,
7380
- onAligned,
7381
- showShortcut = false,
7382
- onClick,
7383
- children,
7384
- ...buttonProps
7385
- }) => {
7386
- const { editor } = (0, import_editor_utils25.useTiptapEditor)(providedEditor);
7387
- const {
7388
- isVisible,
7389
- handleTextAlign,
7390
- label,
7391
- canAlign,
7392
- isActive,
7393
- Icon,
7394
- shortcutKeys
7395
- } = useTextAlign({
7396
- editor,
7397
- align,
7398
- hideWhenUnavailable,
7399
- onAligned
7400
- });
7401
- const handleClick = (0, import_react53.useCallback)(
7402
- (e) => {
7403
- onClick == null ? void 0 : onClick(e);
7404
- if (e.defaultPrevented) return;
7405
- handleTextAlign();
7406
- },
7407
- [handleTextAlign, onClick]
7408
- );
7409
- if (!isVisible) {
7410
- return null;
7411
- }
7412
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7413
- import_button16.IconButton,
7414
- {
7415
- type: "button",
7416
- disabled: canAlign,
7417
- variant: "ghost",
7418
- color: "default",
7419
- "data-active-state": isActive ? "on" : "off",
7420
- "data-disabled": canAlign,
7421
- tabIndex: -1,
7422
- "aria-label": label,
7423
- "aria-pressed": isActive,
7424
- tooltip: label,
7425
- shortcutKeys,
7426
- onClick: handleClick,
7427
- ...buttonProps,
7428
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Icon, {})
7723
+ // src/ui/turn-into-dropdown/turn-into-dropdown.tsx
7724
+ var import_jsx_runtime31 = require("react/jsx-runtime");
7725
+ var TurnIntoDropdownContent = ({ blockTypes }) => {
7726
+ const filteredOptions = getFilteredBlockTypeOptions(blockTypes);
7727
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_dropdown_menu2.DropdownMenu.Group, { children: filteredOptions.map(
7728
+ (option, index) => {
7729
+ var _a;
7730
+ return renderBlockTypeButton(
7731
+ option,
7732
+ `${option.type}-${(_a = option.level) != null ? _a : index}`
7733
+ );
7429
7734
  }
7430
- );
7735
+ ) });
7431
7736
  };
7737
+ function renderBlockTypeButton(option, key) {
7738
+ switch (option.type) {
7739
+ case "paragraph":
7740
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_dropdown_menu2.DropdownMenu.Item, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7741
+ TextButton,
7742
+ {
7743
+ fullWidth: true,
7744
+ spacing: "start",
7745
+ tooltip: "",
7746
+ text: option.label
7747
+ }
7748
+ ) }, key);
7749
+ case "heading":
7750
+ if (!option.level) {
7751
+ return null;
7752
+ }
7753
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_dropdown_menu2.DropdownMenu.Item, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7754
+ HeadingButton,
7755
+ {
7756
+ level: option.level || 1,
7757
+ fullWidth: true,
7758
+ spacing: "start",
7759
+ tooltip: "",
7760
+ text: option.label
7761
+ }
7762
+ ) }, key);
7763
+ case "bulletList":
7764
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_dropdown_menu2.DropdownMenu.Item, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7765
+ ListButton,
7766
+ {
7767
+ type: "bulletList",
7768
+ fullWidth: true,
7769
+ spacing: "start",
7770
+ tooltip: "",
7771
+ text: option.label
7772
+ }
7773
+ ) }, key);
7774
+ case "orderedList":
7775
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_dropdown_menu2.DropdownMenu.Item, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7776
+ ListButton,
7777
+ {
7778
+ type: "orderedList",
7779
+ fullWidth: true,
7780
+ spacing: "start",
7781
+ tooltip: "",
7782
+ text: option.label
7783
+ }
7784
+ ) }, key);
7785
+ case "taskList":
7786
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_dropdown_menu2.DropdownMenu.Item, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7787
+ ListButton,
7788
+ {
7789
+ type: "taskList",
7790
+ fullWidth: true,
7791
+ spacing: "start",
7792
+ tooltip: "",
7793
+ text: option.label
7794
+ }
7795
+ ) }, key);
7796
+ case "blockquote":
7797
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_dropdown_menu2.DropdownMenu.Item, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7798
+ BlockquoteButton,
7799
+ {
7800
+ className: "w-full justify-start",
7801
+ title: "",
7802
+ tooltip: "",
7803
+ text: option.label
7804
+ }
7805
+ ) }, key);
7806
+ case "codeBlock":
7807
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_dropdown_menu2.DropdownMenu.Item, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7808
+ CodeBlockButton,
7809
+ {
7810
+ className: "w-full justify-start",
7811
+ title: "",
7812
+ tooltip: "",
7813
+ text: option.label
7814
+ }
7815
+ ) }, key);
7816
+ default:
7817
+ return null;
7818
+ }
7819
+ }
7820
+ var TurnIntoDropdown = (0, import_react56.forwardRef)(
7821
+ ({
7822
+ editor: providedEditor,
7823
+ hideWhenUnavailable = false,
7824
+ blockTypes,
7825
+ onOpenChange,
7826
+ children,
7827
+ ...buttonProps
7828
+ }, ref) => {
7829
+ const { editor } = (0, import_editor_utils28.useTiptapEditor)(providedEditor);
7830
+ const {
7831
+ isVisible,
7832
+ canToggle: canToggle3,
7833
+ isOpen,
7834
+ activeBlockType,
7835
+ handleOpenChange,
7836
+ label,
7837
+ Icon
7838
+ } = useTurnIntoDropdown({
7839
+ editor,
7840
+ hideWhenUnavailable,
7841
+ blockTypes,
7842
+ onOpenChange
7843
+ });
7844
+ if (!isVisible) {
7845
+ return null;
7846
+ }
7847
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_dropdown_menu2.DropdownMenu.Root, { open: isOpen, onOpenChange: handleOpenChange, children: [
7848
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_dropdown_menu2.DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7849
+ import_button17.Button,
7850
+ {
7851
+ type: "button",
7852
+ variant: "ghost",
7853
+ color: "default",
7854
+ disabled: !canToggle3,
7855
+ "data-disabled": !canToggle3,
7856
+ tabIndex: -1,
7857
+ "aria-label": label,
7858
+ tooltip: "Turn into",
7859
+ endContent: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Icon, {}),
7860
+ ...buttonProps,
7861
+ ref,
7862
+ children: children != null ? children : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { children: (activeBlockType == null ? void 0 : activeBlockType.label) || "Text" })
7863
+ }
7864
+ ) }),
7865
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_dropdown_menu2.DropdownMenu.Content, { align: "start", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(TurnIntoDropdownContent, { blockTypes }) })
7866
+ ] });
7867
+ }
7868
+ );
7869
+ TurnIntoDropdown.displayName = "TurnIntoDropdown";
7432
7870
 
7433
7871
  // src/ui/undo-redo-button/undo-redo-button.tsx
7434
- var import_editor_utils27 = require("@kopexa/editor-utils");
7872
+ var import_editor_utils30 = require("@kopexa/editor-utils");
7435
7873
  var import_toolbar9 = require("@kopexa/toolbar");
7436
- var import_react55 = require("react");
7874
+ var import_react58 = require("react");
7437
7875
 
7438
7876
  // src/ui/undo-redo-button/use-undo-redo.ts
7439
- var import_editor_utils26 = require("@kopexa/editor-utils");
7440
- var import_icons24 = require("@kopexa/icons");
7441
- var import_react54 = require("react");
7877
+ var import_editor_utils29 = require("@kopexa/editor-utils");
7878
+ var import_icons25 = require("@kopexa/icons");
7879
+ var import_react57 = require("react");
7442
7880
  var UNDO_REDO_SHORTCUT_KEYS = {
7443
7881
  undo: "mod+z",
7444
7882
  redo: "mod+shift+z"
@@ -7448,12 +7886,12 @@ var historyActionLabels = {
7448
7886
  redo: "Redo"
7449
7887
  };
7450
7888
  var historyIcons = {
7451
- undo: import_icons24.UndoIcon,
7452
- redo: import_icons24.RedoIcon
7889
+ undo: import_icons25.UndoIcon,
7890
+ redo: import_icons25.RedoIcon
7453
7891
  };
7454
7892
  function canExecuteUndoRedoAction(editor, action) {
7455
7893
  if (!editor || !editor.isEditable) return false;
7456
- if ((0, import_editor_utils26.isNodeTypeSelected)(editor, ["image"])) return false;
7894
+ if ((0, import_editor_utils29.isNodeTypeSelected)(editor, ["image"])) return false;
7457
7895
  return action === "undo" ? editor.can().undo() : editor.can().redo();
7458
7896
  }
7459
7897
  function executeUndoRedoAction(editor, action) {
@@ -7462,7 +7900,7 @@ function executeUndoRedoAction(editor, action) {
7462
7900
  const chain = editor.chain().focus();
7463
7901
  return action === "undo" ? chain.undo().run() : chain.redo().run();
7464
7902
  }
7465
- function shouldShowButton6(props) {
7903
+ function shouldShowButton7(props) {
7466
7904
  const { editor, hideWhenUnavailable, action } = props;
7467
7905
  if (!editor || !editor.isEditable) return false;
7468
7906
  if (hideWhenUnavailable && !editor.isActive("code")) {
@@ -7477,13 +7915,13 @@ function useUndoRedo(config) {
7477
7915
  hideWhenUnavailable = false,
7478
7916
  onExecuted
7479
7917
  } = config;
7480
- const { editor } = (0, import_editor_utils26.useTiptapEditor)(providedEditor);
7481
- const [isVisible, setIsVisible] = (0, import_react54.useState)(true);
7918
+ const { editor } = (0, import_editor_utils29.useTiptapEditor)(providedEditor);
7919
+ const [isVisible, setIsVisible] = (0, import_react57.useState)(true);
7482
7920
  const canExecute = canExecuteUndoRedoAction(editor, action);
7483
- (0, import_react54.useEffect)(() => {
7921
+ (0, import_react57.useEffect)(() => {
7484
7922
  if (!editor) return;
7485
7923
  const handleUpdate = () => {
7486
- setIsVisible(shouldShowButton6({ editor, hideWhenUnavailable, action }));
7924
+ setIsVisible(shouldShowButton7({ editor, hideWhenUnavailable, action }));
7487
7925
  };
7488
7926
  handleUpdate();
7489
7927
  editor.on("transaction", handleUpdate);
@@ -7491,7 +7929,7 @@ function useUndoRedo(config) {
7491
7929
  editor.off("transaction", handleUpdate);
7492
7930
  };
7493
7931
  }, [editor, hideWhenUnavailable, action]);
7494
- const handleAction = (0, import_react54.useCallback)(() => {
7932
+ const handleAction = (0, import_react57.useCallback)(() => {
7495
7933
  if (!editor) return false;
7496
7934
  const success = executeUndoRedoAction(editor, action);
7497
7935
  if (success) {
@@ -7510,7 +7948,7 @@ function useUndoRedo(config) {
7510
7948
  }
7511
7949
 
7512
7950
  // src/ui/undo-redo-button/undo-redo-button.tsx
7513
- var import_jsx_runtime31 = require("react/jsx-runtime");
7951
+ var import_jsx_runtime32 = require("react/jsx-runtime");
7514
7952
  var UndoRedoButton = ({
7515
7953
  editor: providedEditor,
7516
7954
  action,
@@ -7522,14 +7960,14 @@ var UndoRedoButton = ({
7522
7960
  children,
7523
7961
  ...buttonProps
7524
7962
  }) => {
7525
- const { editor } = (0, import_editor_utils27.useTiptapEditor)(providedEditor);
7963
+ const { editor } = (0, import_editor_utils30.useTiptapEditor)(providedEditor);
7526
7964
  const { isVisible, handleAction, label, canExecute, Icon, shortcutKeys } = useUndoRedo({
7527
7965
  editor,
7528
7966
  action,
7529
7967
  hideWhenUnavailable,
7530
7968
  onExecuted
7531
7969
  });
7532
- const handleClick = (0, import_react55.useCallback)(
7970
+ const handleClick = (0, import_react58.useCallback)(
7533
7971
  (event) => {
7534
7972
  onClick == null ? void 0 : onClick(event);
7535
7973
  if (event.defaultPrevented) return;
@@ -7540,7 +7978,7 @@ var UndoRedoButton = ({
7540
7978
  if (!isVisible) {
7541
7979
  return null;
7542
7980
  }
7543
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7981
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7544
7982
  import_toolbar9.ToolbarButton,
7545
7983
  {
7546
7984
  type: "button",
@@ -7555,23 +7993,23 @@ var UndoRedoButton = ({
7555
7993
  onClick: handleClick,
7556
7994
  isIconOnly: true,
7557
7995
  ...buttonProps,
7558
- children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Icon, {})
7996
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Icon, {})
7559
7997
  }
7560
7998
  );
7561
7999
  };
7562
8000
 
7563
8001
  // src/presets/basic/editor-header.tsx
7564
- var import_jsx_runtime32 = require("react/jsx-runtime");
8002
+ var import_jsx_runtime33 = require("react/jsx-runtime");
7565
8003
  var EditorHeader = ({
7566
8004
  editor: providedEditor,
7567
8005
  variant
7568
8006
  }) => {
7569
8007
  var _a, _b;
7570
- const { editor } = (0, import_editor_utils28.useTiptapEditor)(providedEditor);
7571
- const isMobile = (0, import_use_is_mobile2.useIsMobile)();
8008
+ const { editor } = (0, import_editor_utils31.useTiptapEditor)(providedEditor);
8009
+ const isMobile = (0, import_use_is_mobile3.useIsMobile)();
7572
8010
  const windowSize = useWindowSize();
7573
8011
  const { styles } = useEditorUIContext();
7574
- const toolbarRef = (0, import_react56.useRef)(null);
8012
+ const toolbarRef = (0, import_react59.useRef)(null);
7575
8013
  const bodyRect = useCursorVisibility({
7576
8014
  editor,
7577
8015
  overlayHeight: (_b = (_a = toolbarRef.current) == null ? void 0 : _a.getBoundingClientRect().height) != null ? _b : 0
@@ -7580,7 +8018,7 @@ var EditorHeader = ({
7580
8018
  return null;
7581
8019
  }
7582
8020
  const ToolbarContent = variant === "comment" ? CommentToolbarContent : variant === "field" ? FieldToolbarContent : MainToolbarContent;
7583
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: styles.toolbarContainer(), "data-slot": "editor-toolbar", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
8021
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: styles.toolbarContainer(), "data-slot": "editor-toolbar", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7584
8022
  import_toolbar10.Toolbar,
7585
8023
  {
7586
8024
  sticky: true,
@@ -7590,63 +8028,58 @@ var EditorHeader = ({
7590
8028
  bottom: `calc(100% - ${windowSize.height - bodyRect.y}px)`
7591
8029
  } : {},
7592
8030
  className: styles.toolbar(),
7593
- children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ToolbarContent, {})
8031
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ToolbarContent, {})
7594
8032
  }
7595
8033
  ) });
7596
8034
  };
7597
- var MainToolbarContent = () => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
7598
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_toolbar10.ToolbarGroup, { children: [
7599
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(UndoRedoButton, { action: "undo" }),
7600
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(UndoRedoButton, { action: "redo" })
8035
+ var MainToolbarContent = () => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
8036
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_toolbar10.ToolbarGroup, { children: [
8037
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(UndoRedoButton, { action: "undo" }),
8038
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(UndoRedoButton, { action: "redo" })
7601
8039
  ] }),
7602
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_toolbar10.ToolbarSeparator, {}),
7603
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_toolbar10.ToolbarGroup, { children: [
7604
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(HeadingDropdownMenu, { levels: [1, 2, 3, 4] }),
7605
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ListDropdownMenu, { types: ["bulletList", "orderedList", "taskList"] }),
7606
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(BlockquoteButton, {}),
7607
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(CodeBlockButton, {})
8040
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_toolbar10.ToolbarSeparator, {}),
8041
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_toolbar10.ToolbarGroup, { children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TurnIntoDropdown, {}) }),
8042
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_toolbar10.ToolbarSeparator, {}),
8043
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_toolbar10.ToolbarGroup, { children: [
8044
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(MarkButton, { type: "bold" }),
8045
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(MarkButton, { type: "italic" }),
8046
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(MarkButton, { type: "strike" }),
8047
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(MarkButton, { type: "code" }),
8048
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(MarkButton, { type: "underline" }),
8049
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ColorHighlightPopover, {}),
8050
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(LinkPopover, {})
7608
8051
  ] }),
7609
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_toolbar10.ToolbarSeparator, {}),
7610
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_toolbar10.ToolbarGroup, { children: [
7611
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(MarkButton, { type: "bold" }),
7612
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(MarkButton, { type: "italic" }),
7613
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(MarkButton, { type: "strike" }),
7614
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(MarkButton, { type: "code" }),
7615
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(MarkButton, { type: "underline" }),
7616
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ColorHighlightPopover, {}),
7617
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(LinkPopover, {})
7618
- ] }),
7619
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_toolbar10.ToolbarSeparator, {}),
7620
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_toolbar10.ToolbarGroup, { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(TableButton, {}) }),
7621
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(MoreOptions, { hideWhenUnavailable: true })
8052
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_toolbar10.ToolbarSeparator, {}),
8053
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_toolbar10.ToolbarGroup, { children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TableButton, {}) }),
8054
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(MoreOptions, { hideWhenUnavailable: true })
7622
8055
  ] });
7623
- var CommentToolbarContent = () => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
7624
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_toolbar10.ToolbarGroup, { children: [
7625
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(MarkButton, { type: "bold" }),
7626
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(MarkButton, { type: "italic" }),
7627
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(MarkButton, { type: "strike" }),
7628
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(MarkButton, { type: "code" })
8056
+ var CommentToolbarContent = () => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
8057
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_toolbar10.ToolbarGroup, { children: [
8058
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(MarkButton, { type: "bold" }),
8059
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(MarkButton, { type: "italic" }),
8060
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(MarkButton, { type: "strike" }),
8061
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(MarkButton, { type: "code" })
7629
8062
  ] }),
7630
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_toolbar10.ToolbarSeparator, {}),
7631
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_toolbar10.ToolbarGroup, { children: [
7632
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(LinkPopover, {}),
7633
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ListDropdownMenu, { types: ["bulletList", "orderedList"] })
8063
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_toolbar10.ToolbarSeparator, {}),
8064
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_toolbar10.ToolbarGroup, { children: [
8065
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(LinkPopover, {}),
8066
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ListDropdownMenu, { types: ["bulletList", "orderedList"] })
7634
8067
  ] })
7635
8068
  ] });
7636
- var FieldToolbarContent = () => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_toolbar10.ToolbarGroup, { children: [
7637
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(MarkButton, { type: "bold" }),
7638
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(MarkButton, { type: "italic" }),
7639
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(MarkButton, { type: "strike" }),
7640
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(LinkPopover, {})
8069
+ var FieldToolbarContent = () => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_toolbar10.ToolbarGroup, { children: [
8070
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(MarkButton, { type: "bold" }),
8071
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(MarkButton, { type: "italic" }),
8072
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(MarkButton, { type: "strike" }),
8073
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(LinkPopover, {})
7641
8074
  ] });
7642
8075
  function MoreOptions({
7643
8076
  editor: providedEditor,
7644
8077
  hideWhenUnavailable = false,
7645
8078
  ...props
7646
8079
  }) {
7647
- const { editor } = (0, import_editor_utils28.useTiptapEditor)(providedEditor);
7648
- const [show, setShow] = (0, import_react56.useState)(false);
7649
- (0, import_react56.useEffect)(() => {
8080
+ const { editor } = (0, import_editor_utils31.useTiptapEditor)(providedEditor);
8081
+ const [show, setShow] = (0, import_react59.useState)(false);
8082
+ (0, import_react59.useEffect)(() => {
7650
8083
  if (!editor) return;
7651
8084
  const handleSelectionUpdate = () => {
7652
8085
  setShow(
@@ -7665,13 +8098,13 @@ function MoreOptions({
7665
8098
  if (!show || !editor || !editor.isEditable) {
7666
8099
  return null;
7667
8100
  }
7668
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
7669
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_toolbar10.ToolbarSeparator, {}),
7670
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_toolbar10.ToolbarGroup, { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_popover3.Popover.Root, { spacing: "dense", width: "auto", children: [
7671
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
8101
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
8102
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_toolbar10.ToolbarSeparator, {}),
8103
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_toolbar10.ToolbarGroup, { children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_popover3.Popover.Root, { spacing: "dense", width: "auto", children: [
8104
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7672
8105
  import_popover3.Popover.Trigger,
7673
8106
  {
7674
- render: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
8107
+ render: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7675
8108
  import_toolbar10.ToolbarButton,
7676
8109
  {
7677
8110
  type: "button",
@@ -7683,29 +8116,29 @@ function MoreOptions({
7683
8116
  title: "More options",
7684
8117
  isIconOnly: true,
7685
8118
  ...props,
7686
- children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_icons25.MoreVerticalIcon, {})
8119
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_icons26.MoreVerticalIcon, {})
7687
8120
  }
7688
8121
  )
7689
8122
  }
7690
8123
  ),
7691
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
8124
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7692
8125
  import_popover3.Popover.Content,
7693
8126
  {
7694
8127
  side: "top",
7695
8128
  align: "end",
7696
8129
  alignOffset: 4,
7697
8130
  sideOffset: 4,
7698
- children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_toolbar10.Toolbar, { children: [
7699
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_toolbar10.ToolbarGroup, { children: [
7700
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(MarkButton, { type: "superscript" }),
7701
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(MarkButton, { type: "subscript" })
8131
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_toolbar10.Toolbar, { children: [
8132
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_toolbar10.ToolbarGroup, { children: [
8133
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(MarkButton, { type: "superscript" }),
8134
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(MarkButton, { type: "subscript" })
7702
8135
  ] }),
7703
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_toolbar10.ToolbarSeparator, {}),
7704
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_toolbar10.ToolbarGroup, { children: [
7705
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(TextAlignButton, { align: "left" }),
7706
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(TextAlignButton, { align: "center" }),
7707
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(TextAlignButton, { align: "right" }),
7708
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(TextAlignButton, { align: "justify" })
8136
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_toolbar10.ToolbarSeparator, {}),
8137
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_toolbar10.ToolbarGroup, { children: [
8138
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TextAlignButton, { align: "left" }),
8139
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TextAlignButton, { align: "center" }),
8140
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TextAlignButton, { align: "right" }),
8141
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TextAlignButton, { align: "justify" })
7709
8142
  ] })
7710
8143
  ] })
7711
8144
  }
@@ -7737,7 +8170,7 @@ function shouldShowMoreOptions(params) {
7737
8170
  }
7738
8171
 
7739
8172
  // src/presets/basic/index.tsx
7740
- var import_jsx_runtime33 = require("react/jsx-runtime");
8173
+ var import_jsx_runtime34 = require("react/jsx-runtime");
7741
8174
  var BasicEditor = ({
7742
8175
  variant,
7743
8176
  bordered,
@@ -7755,19 +8188,19 @@ var BasicEditor = ({
7755
8188
  ...options
7756
8189
  });
7757
8190
  const styles = (0, import_theme9.editorBasic)({ variant, bordered });
7758
- const resolveVariable = (0, import_react58.useCallback)(
8191
+ const resolveVariable = (0, import_react61.useCallback)(
7759
8192
  (name) => variableValues == null ? void 0 : variableValues[name],
7760
8193
  [variableValues]
7761
8194
  );
7762
8195
  if (!editor) {
7763
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(LoadingSpinner, {});
8196
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(LoadingSpinner, {});
7764
8197
  }
7765
8198
  const isBottomToolbar = variant === "field";
7766
8199
  const hasVariables = variables && variables.length > 0;
7767
8200
  const hasPagination = !!pagesOptions;
7768
- const editorContent = /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(EditorUIProvider, { value: { styles }, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: styles.root(), "data-slot": "editor", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_react57.EditorContext.Provider, { value: { editor }, children: [
7769
- showToolbar && !isBottomToolbar && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(EditorHeader, { editor, variant }),
7770
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
8201
+ const editorContent = /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(EditorUIProvider, { value: { styles }, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: styles.root(), "data-slot": "editor", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_react60.EditorContext.Provider, { value: { editor }, children: [
8202
+ showToolbar && !isBottomToolbar && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(EditorHeader, { editor, variant }),
8203
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7771
8204
  EditorContentArea,
7772
8205
  {
7773
8206
  variant,
@@ -7775,10 +8208,10 @@ var BasicEditor = ({
7775
8208
  hasPagination
7776
8209
  }
7777
8210
  ),
7778
- showToolbar && isBottomToolbar && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(EditorHeader, { editor, variant })
8211
+ showToolbar && isBottomToolbar && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(EditorHeader, { editor, variant })
7779
8212
  ] }) }) });
7780
8213
  if (hasVariables) {
7781
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VariableProvider, { variables, resolveVariable, children: editorContent });
8214
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(VariableProvider, { variables, resolveVariable, children: editorContent });
7782
8215
  }
7783
8216
  return editorContent;
7784
8217
  };
@@ -7788,10 +8221,10 @@ var EditorContentArea = ({
7788
8221
  hasPagination
7789
8222
  }) => {
7790
8223
  const styles = (0, import_theme9.editorBasic)({ variant });
7791
- const { editor } = (0, import_react58.useContext)(import_react57.EditorContext);
8224
+ const { editor } = (0, import_react61.useContext)(import_react60.EditorContext);
7792
8225
  const { isDragging } = useUiEditorState(editor);
7793
8226
  useScrollToHash();
7794
- const handleKeyDown = (0, import_react58.useCallback)(
8227
+ const handleKeyDown = (0, import_react61.useCallback)(
7795
8228
  (e) => {
7796
8229
  if (!(editor == null ? void 0 : editor.isFocused)) return;
7797
8230
  const isMod = e.metaKey || e.ctrlKey;
@@ -7833,9 +8266,9 @@ var EditorContentArea = ({
7833
8266
  const contentClassName = hasPagination ? "w-full min-w-0 h-auto min-h-0" : styles.content();
7834
8267
  return (
7835
8268
  // biome-ignore lint/a11y/noStaticElementInteractions: Wrapper intercepts keyboard shortcuts to prevent propagation
7836
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: styles.wrapper(), onKeyDown: handleKeyDown, children: [
7837
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
7838
- import_react57.EditorContent,
8269
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: styles.wrapper(), onKeyDown: handleKeyDown, children: [
8270
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
8271
+ import_react60.EditorContent,
7839
8272
  {
7840
8273
  editor,
7841
8274
  role: "presentation",
@@ -7844,20 +8277,20 @@ var EditorContentArea = ({
7844
8277
  cursor: isDragging ? "grabbing" : "auto"
7845
8278
  },
7846
8279
  children: [
7847
- isEditable && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(SlashDropdownMenu, {}),
7848
- isEditable && variables && variables.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VariableSuggestion, { editor, variables })
8280
+ isEditable && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(SlashDropdownMenu, {}),
8281
+ isEditable && variables && variables.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(VariableSuggestion, { editor, variables })
7849
8282
  ]
7850
8283
  }
7851
8284
  ),
7852
- isEditable && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(BubbleMenu, { editor }),
7853
- isEditable && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(LinkBubble, { editor }),
7854
- isEditable && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
7855
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_extension_table2.TableHandle, { editor }),
7856
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
8285
+ isEditable && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(BubbleMenu, { editor }),
8286
+ isEditable && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(LinkBubble, { editor }),
8287
+ isEditable && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
8288
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_extension_table2.TableHandle, { editor }),
8289
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7857
8290
  import_extension_table2.TableSelectionOverlay,
7858
8291
  {
7859
8292
  showResizeHandles: true,
7860
- cellMenu: (props) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
8293
+ cellMenu: (props) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7861
8294
  import_extension_table2.TableCellHandleMenu,
7862
8295
  {
7863
8296
  editor: props.editor,
@@ -7872,8 +8305,8 @@ var EditorContentArea = ({
7872
8305
  };
7873
8306
  function LoadingSpinner({ text = "Connecting..." }) {
7874
8307
  const styles = (0, import_theme9.editorSpinner)();
7875
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: styles.root(), children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: styles.content(), children: [
7876
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
8308
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: styles.root(), children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: styles.content(), children: [
8309
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
7877
8310
  "svg",
7878
8311
  {
7879
8312
  className: styles.svg(),
@@ -7881,9 +8314,9 @@ function LoadingSpinner({ text = "Connecting..." }) {
7881
8314
  fill: "none",
7882
8315
  viewBox: "0 0 24 24",
7883
8316
  children: [
7884
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("title", { children: "Loading Spinner" }),
7885
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("circle", { className: styles.circle(), cx: "12", cy: "12", r: "10" }),
7886
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
8317
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("title", { children: "Loading Spinner" }),
8318
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("circle", { className: styles.circle(), cx: "12", cy: "12", r: "10" }),
8319
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7887
8320
  "path",
7888
8321
  {
7889
8322
  className: styles.path(),
@@ -7893,7 +8326,7 @@ function LoadingSpinner({ text = "Connecting..." }) {
7893
8326
  ]
7894
8327
  }
7895
8328
  ),
7896
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: styles.text(), children: text })
8329
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: styles.text(), children: text })
7897
8330
  ] }) });
7898
8331
  }
7899
8332
  // Annotate the CommonJS export names for ESM import in node: