@godxjp/editor 31.18.0 → 31.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -30,7 +30,9 @@ import { FormField } from "@godxjp/ui/data-entry";
30
30
  `readOnly`, its actions stay focusable but do nothing (`aria-disabled`).
31
31
  - Files: `upload(file) => Promise<{ url, name? }>`. A placeholder marks each upload and is replaced
32
32
  by `![name](url)` (images) or `[name](url)`; a failure removes it and says which file failed.
33
- `uploadBlockedReason` refuses files with the host's message. Without `upload`, files are ignored.
33
+ `uploadBlockedReason` refuses files with the host's message — with or without `upload`: a
34
+ pasted or dropped file shows it, and the attach button names the reason and shows it when
35
+ pressed instead of opening the picker. With neither prop, files are left to the browser.
34
36
  - Strings come from the kit's catalogue in ja / en / vi; `labels` overrides any of them.
35
37
 
36
38
  ## Props
package/dist/index.d.ts CHANGED
@@ -164,7 +164,11 @@ type MarkdownEditorProps = Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement
164
164
  * (an app's own storage today, the media service later). Omit it and files are not accepted.
165
165
  */
166
166
  upload?: (file: File) => Promise<MarkdownEditorUploadResult>;
167
- /** When set, files are refused with this message (a quota, a read-only space). */
167
+ /**
168
+ * When set, files are refused with this message (a quota, a read-only space) — with or without
169
+ * `upload`. Pasted / dropped files show it; the attach button carries it in its name and tooltip
170
+ * and shows it when pressed, instead of opening a file picker whose choice would be refused.
171
+ */
168
172
  uploadBlockedReason?: string | null;
169
173
  /** The preview. Default: `<Prose><Markdown>{value}</Markdown></Prose>` from `@godxjp/markdown`. */
170
174
  renderPreview?: (value: string) => React.ReactNode;
@@ -197,7 +201,11 @@ declare const MarkdownEditor: React.ForwardRefExoticComponent<Omit<React.Textare
197
201
  * (an app's own storage today, the media service later). Omit it and files are not accepted.
198
202
  */
199
203
  upload?: (file: File) => Promise<MarkdownEditorUploadResult>;
200
- /** When set, files are refused with this message (a quota, a read-only space). */
204
+ /**
205
+ * When set, files are refused with this message (a quota, a read-only space) — with or without
206
+ * `upload`. Pasted / dropped files show it; the attach button carries it in its name and tooltip
207
+ * and shows it when pressed, instead of opening a file picker whose choice would be refused.
208
+ */
201
209
  uploadBlockedReason?: string | null;
202
210
  /** The preview. Default: `<Prose><Markdown>{value}</Markdown></Prose>` from `@godxjp/markdown`. */
203
211
  renderPreview?: (value: string) => React.ReactNode;
package/dist/index.js CHANGED
@@ -290,12 +290,14 @@ var MarkdownEditor = React.forwardRef(
290
290
  const [uploadError, setUploadError] = React.useState(null);
291
291
  const uploadSeq = React.useRef(0);
292
292
  const fileInput = React.useRef(null);
293
+ const takesFiles = Boolean(upload) || Boolean(uploadBlockedReason);
293
294
  const acceptFiles = async (files) => {
294
- if (!upload || files.length === 0 || !editable) return;
295
+ if (files.length === 0 || !editable) return;
295
296
  if (uploadBlockedReason) {
296
297
  setUploadError(uploadBlockedReason);
297
298
  return;
298
299
  }
300
+ if (!upload) return;
299
301
  setUploadError(null);
300
302
  for (const file of files) {
301
303
  const placeholder = `![${label("uploading")} ${file.name.replace(/[[\]\\]/g, "")} #${++uploadSeq.current}]()`;
@@ -361,12 +363,14 @@ var MarkdownEditor = React.forwardRef(
361
363
  },
362
364
  { key: "quote", label: label("quote"), icon: /* @__PURE__ */ jsx(Quote, {}), run: () => lines("> ") }
363
365
  ];
364
- if (upload) {
366
+ if (takesFiles) {
365
367
  builtIn.push({
366
368
  key: "attach",
367
- label: label("attach"),
369
+ // A blocked attach says why in its own name and tooltip, BEFORE anyone opens the picker.
370
+ label: uploadBlockedReason ? `${label("attach")} \u2014 ${uploadBlockedReason}` : label("attach"),
368
371
  icon: /* @__PURE__ */ jsx(Paperclip, {}),
369
- run: () => fileInput.current?.click()
372
+ // …and a press repeats the reason instead of opening a picker whose choice would be refused.
373
+ run: () => uploadBlockedReason ? setUploadError(uploadBlockedReason) : fileInput.current?.click()
370
374
  });
371
375
  }
372
376
  const all = [...builtIn, ...actions];
@@ -397,7 +401,7 @@ var MarkdownEditor = React.forwardRef(
397
401
  onPaste: (event) => {
398
402
  onPaste?.(event);
399
403
  const files = Array.from(event.clipboardData?.files ?? []);
400
- if (!event.defaultPrevented && upload && files.length > 0) {
404
+ if (!event.defaultPrevented && takesFiles && files.length > 0) {
401
405
  event.preventDefault();
402
406
  void acceptFiles(files);
403
407
  }
@@ -405,7 +409,7 @@ var MarkdownEditor = React.forwardRef(
405
409
  onDrop: (event) => {
406
410
  onDrop?.(event);
407
411
  const files = Array.from(event.dataTransfer?.files ?? []);
408
- if (!event.defaultPrevented && upload && files.length > 0) {
412
+ if (!event.defaultPrevented && takesFiles && files.length > 0) {
409
413
  event.preventDefault();
410
414
  void acceptFiles(files);
411
415
  }
@@ -450,7 +454,7 @@ var MarkdownEditor = React.forwardRef(
450
454
  /* @__PURE__ */ jsx("div", { hidden: mode === "preview", children: textarea }),
451
455
  mode === "preview" ? preview : null
452
456
  ] }),
453
- upload ? /* @__PURE__ */ jsx(
457
+ upload && !uploadBlockedReason ? /* @__PURE__ */ jsx(
454
458
  "input",
455
459
  {
456
460
  ref: fileInput,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@godxjp/editor",
3
- "version": "31.18.0",
3
+ "version": "31.19.0",
4
4
  "description": "Markdown editor for GoDX apps: formatting toolbar, write / preview / side by side with @godxjp/markdown, paste / drop / attach through a host upload function, IME-safe, ja / en / vi.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -29,8 +29,8 @@
29
29
  },
30
30
  "license": "Apache-2.0",
31
31
  "peerDependencies": {
32
- "@godxjp/markdown": "~31.18.0",
33
- "@godxjp/ui": "~31.18.0",
32
+ "@godxjp/markdown": "~31.19.0",
33
+ "@godxjp/ui": "~31.19.0",
34
34
  "lucide-react": ">=1.0.0",
35
35
  "react": ">=19.0.0"
36
36
  },