@meowdown/react 0.39.0 → 0.40.1

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 (2) hide show
  1. package/dist/index.js +52 -6
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { clsx } from "clsx/lite";
2
2
  import { Fragment, cloneElement, createElement, useCallback, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from "react";
3
- import { codeBlockLanguages, defaultResolveImageUrl, defineBulletAfterHeading, defineCodeBlockPreviewPlugin, defineEditorExtension, defineEmbedPaste, defineExitBoundaryHandler, defineFileClickHandler, defineFilePaste, defineFileView, defineFollowLinkHandler, defineHTMLPaste, defineImage, defineImageClickHandler, defineLinkClickHandler, defineLinkEditKeymap, defineLinkHoverHandler, defineLinkPaste, defineMarkdownCopy, definePendingReplacementHandler, definePlaceholder, defineReadonly, defineSpellCheckPlugin, defineTagClickHandler, defineWikilinkClickHandler, defineWikilinkTrigger, docToMarkdown, getCodeTokens, getMarkBuilders, getPendingReplacement, getSelectedText, getTableColumnAlign, getVirtualElementFromRange, inlineTextToMarkChunks, isCodeBlockPreviewHiddenDecoration, isSelectionInTableCell, listenForTweetHeight, loadKaTeX, markdownToDoc, matchEmbed, renderMathInto } from "@meowdown/core";
3
+ import { buildFileMarkdown, codeBlockLanguages, defaultResolveImageUrl, defineBulletAfterHeading, defineCodeBlockPreviewPlugin, defineEditorExtension, defineEmbedPaste, defineExitBoundaryHandler, defineFileClickHandler, defineFilePaste, defineFileView, defineFollowLinkHandler, defineHTMLPaste, defineImage, defineImageClickHandler, defineLinkClickHandler, defineLinkEditKeymap, defineLinkHoverHandler, defineLinkPaste, defineMarkdownCopy, definePendingReplacementHandler, definePlaceholder, defineReadonly, defineSpellCheckPlugin, defineTagClickHandler, defineWikilinkClickHandler, defineWikilinkTrigger, docToMarkdown, getCodeTokens, getMarkBuilders, getPendingReplacement, getSelectedText, getTableColumnAlign, getVirtualElementFromRange, inlineTextToMarkChunks, isCodeBlockPreviewHiddenDecoration, isSelectionInTableCell, listenForTweetHeight, loadKaTeX, markdownToDoc, matchEmbed, renderMathInto } from "@meowdown/core";
4
4
  import { clamp } from "@ocavue/utils";
5
5
  import { canUseRegexLookbehind, createEditor, defineDocChangeHandler, defineUpdateHandler, isTextSelection, union } from "@prosekit/core";
6
6
  import { Selection, TextSelection } from "@prosekit/pm/state";
@@ -999,6 +999,9 @@ var autocomplete_menu_module_default = {
999
999
  //#endregion
1000
1000
  //#region src/components/slash-menu.tsx
1001
1001
  const regex$2 = canUseRegexLookbehind() ? /(?<!\S)\/(\S.*)?$/u : /\/(\S.*)?$/u;
1002
+ const defaultOnFileSaveError = (error) => {
1003
+ console.error("[meowdown] failed to save attached file:", error);
1004
+ };
1002
1005
  function SlashMenuItem({ label, keywords, detail, kbd, onSelect }) {
1003
1006
  return /* @__PURE__ */ jsxs(AutocompleteItem, {
1004
1007
  value: [label, ...keywords ?? []].join(" "),
@@ -1020,8 +1023,9 @@ function SlashMenuItem({ label, keywords, detail, kbd, onSelect }) {
1020
1023
  function selectionInTableCell(editor) {
1021
1024
  return isSelectionInTableCell(editor.state);
1022
1025
  }
1023
- function SlashMenu({ timeFormat = "12", onSlashMenuSearch }) {
1026
+ function SlashMenu({ timeFormat = "12", onSlashMenuSearch, onFilePaste, onFileSaveError }) {
1024
1027
  const editor = useEditor$1();
1028
+ const fileInputRef = useRef(null);
1025
1029
  const inTableCell = useEditorDerivedValue(selectionInTableCell);
1026
1030
  const [open, setOpen] = useState(false);
1027
1031
  const [query, setQuery] = useState("");
@@ -1046,11 +1050,42 @@ function SlashMenu({ timeFormat = "12", onSlashMenuSearch }) {
1046
1050
  query,
1047
1051
  fetchHostItems
1048
1052
  ]);
1049
- return /* @__PURE__ */ jsx(AutocompleteRoot, {
1053
+ const openFilePicker = useCallback(() => {
1054
+ fileInputRef.current?.click();
1055
+ }, []);
1056
+ const handleFileInputChange = useCallback(async (event) => {
1057
+ const input = event.currentTarget;
1058
+ const files = Array.from(input.files ?? []);
1059
+ input.value = "";
1060
+ if (!onFilePaste || files.length === 0) return;
1061
+ const onSaveError = onFileSaveError ?? defaultOnFileSaveError;
1062
+ const markdown = [];
1063
+ for (const file of files) try {
1064
+ const destination = await onFilePaste(file);
1065
+ if (destination) markdown.push(buildFileMarkdown(file, destination));
1066
+ } catch (error) {
1067
+ onSaveError(error, file);
1068
+ }
1069
+ if (markdown.length === 0) return;
1070
+ editor.focus();
1071
+ editor.commands.insertText({ text: markdown.join("\n") });
1072
+ }, [
1073
+ editor,
1074
+ onFilePaste,
1075
+ onFileSaveError
1076
+ ]);
1077
+ return /* @__PURE__ */ jsxs(AutocompleteRoot, {
1050
1078
  regex: regex$2,
1051
1079
  onOpenChange: (event) => setOpen(event.detail),
1052
1080
  onQueryChange: (event) => setQuery(event.detail),
1053
- children: /* @__PURE__ */ jsx(AutocompletePositioner, {
1081
+ children: [onFilePaste ? /* @__PURE__ */ jsx("input", {
1082
+ ref: fileInputRef,
1083
+ "data-testid": "slash-menu-file-input",
1084
+ type: "file",
1085
+ multiple: true,
1086
+ hidden: true,
1087
+ onChange: handleFileInputChange
1088
+ }) : null, /* @__PURE__ */ jsx(AutocompletePositioner, {
1054
1089
  className: autocomplete_menu_module_default.Positioner,
1055
1090
  children: /* @__PURE__ */ jsxs(AutocompletePopup, {
1056
1091
  className: autocomplete_menu_module_default.Popup,
@@ -1126,6 +1161,15 @@ function SlashMenu({ timeFormat = "12", onSlashMenuSearch }) {
1126
1161
  label: "Now",
1127
1162
  onSelect: () => editor.commands.insertText({ text: formatNowTime(timeFormat) })
1128
1163
  }),
1164
+ onFilePaste ? /* @__PURE__ */ jsx(SlashMenuItem, {
1165
+ label: "Attach file",
1166
+ keywords: [
1167
+ "attachment",
1168
+ "file",
1169
+ "upload"
1170
+ ],
1171
+ onSelect: openFilePicker
1172
+ }) : null,
1129
1173
  hostItems.map((item) => /* @__PURE__ */ jsx(SlashMenuItem, {
1130
1174
  label: item.label,
1131
1175
  keywords: item.keywords,
@@ -1138,7 +1182,7 @@ function SlashMenu({ timeFormat = "12", onSlashMenuSearch }) {
1138
1182
  })
1139
1183
  ]
1140
1184
  })
1141
- })
1185
+ })]
1142
1186
  });
1143
1187
  }
1144
1188
 
@@ -1644,7 +1688,9 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onSl
1644
1688
  blockHandle && !readOnly && /* @__PURE__ */ jsx(DropIndicator$1, {}),
1645
1689
  /* @__PURE__ */ jsx(SlashMenu, {
1646
1690
  timeFormat,
1647
- onSlashMenuSearch
1691
+ onSlashMenuSearch,
1692
+ onFilePaste,
1693
+ onFileSaveError
1648
1694
  }),
1649
1695
  !readOnly && /* @__PURE__ */ jsx(LinkMenu, {
1650
1696
  onLinkClick,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meowdown/react",
3
3
  "type": "module",
4
- "version": "0.39.0",
4
+ "version": "0.40.1",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -26,7 +26,7 @@
26
26
  "clsx": "^2.1.1",
27
27
  "lucide-react": "^1.21.0",
28
28
  "react-property": "^2.0.2",
29
- "@meowdown/core": "0.39.0"
29
+ "@meowdown/core": "0.40.1"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "react": "^19.0.0",