UNPKG

@nestledjs/forms

Version:

A flexible React form library supporting both declarative and imperative usage patterns with TypeScript support

333 lines (332 loc) 11.3 kB
import { jsxs as d, Fragment as b, jsx as n } from "react/jsx-runtime"; import W, { Suspense as I, lazy as K, useEffect as G, useCallback as J } from "react"; import { u as Q, c as x, C as Y } from "./index-_yiSpXfV.js"; const f = (o) => async (e) => { if (o === "base64") return new Promise((t, r) => { const i = new FileReader(); i.onload = () => t(i.result), i.onerror = r, i.readAsDataURL(e); }); throw new Error("Custom image upload handler required for non-base64 mode"); }, ee = async ({ file: o, maxImageSize: e, allowedImageTypes: t, imageUploadHandler: r }) => { if (o.size > e) throw new Error(`Image size must be less than ${Math.round(e / 1024 / 1024)}MB`); if (!t.includes(o.type)) throw new Error(`Image type must be one of: ${t.join(", ")}`); return await r(o); }, oe = async (o) => { if (o.length > 102400 && (console.warn("Markdown input too large, truncating to prevent DoS"), o = o.substring(0, 102400)), typeof window < "u") try { return o.replace(/^### ([^\r\n]{0,200})$/gim, "<h3>$1</h3>").replace(/^## ([^\r\n]{0,200})$/gim, "<h2>$1</h2>").replace(/^# ([^\r\n]{0,200})$/gim, "<h1>$1</h1>").replace(/\*\*([^*\r\n]{1,500}?)\*\*/gim, "<strong>$1</strong>").replace(/\*([^*\r\n]{1,500}?)\*/gim, "<em>$1</em>").replace(/!\[([^\]]{0,200})\]\(([^)\s]{1,500})\)/gim, '<img alt="$1" src="$2" />').replace(/\[([^\]]{0,200})\]\(([^)\s]{1,500})\)/gim, '<a href="$2">$1</a>').replace(/\n$/gim, "<br />"); } catch (t) { return console.warn("Failed to convert markdown to HTML:", t), o; } return o; }, te = ({ enableImageUpload: o, UndoRedo: e, Separator: t, BoldItalicUnderlineToggles: r, CodeToggle: i, ListsToggle: a, CreateLink: m, InsertImage: p }) => /* @__PURE__ */ d(b, { children: [ /* @__PURE__ */ n(e, {}), /* @__PURE__ */ n(t, {}), /* @__PURE__ */ n(r, {}), /* @__PURE__ */ n(i, {}), /* @__PURE__ */ n(t, {}), /* @__PURE__ */ n(a, {}), /* @__PURE__ */ n(t, {}), /* @__PURE__ */ n(m, {}), o && /* @__PURE__ */ d(b, { children: [ /* @__PURE__ */ n(t, {}), /* @__PURE__ */ n(p, {}) ] }) ] }), C = ({ height: o = 300 }) => /* @__PURE__ */ n( "div", { className: "border border-gray-300 rounded-md p-4 flex items-center justify-center text-gray-500", style: { minHeight: `${o}px` }, children: "Loading editor..." } ); let y = 0; const ne = (o) => (G(() => { if (!o || typeof window > "u") return; const e = "mdx-editor-popup-z-index"; let t = document.getElementById(e); return y++, t || (t = document.createElement("style"), t.id = e, document.head.appendChild(t)), t.textContent = ` .mdxeditor-popup-container { z-index: ${o} !important; } .mdxeditor .mdxeditor-popup-container * { z-index: ${o} !important; } `, () => { if (y--, y <= 0) { const r = document.getElementById(e); r && document.head.removeChild(r), y = 0; } }; }, [o]), o ? { "--mdx-popup-z-index": o.toString() } : void 0), ae = (o, e, t, r) => { const { headingsPlugin: i, listsPlugin: a, quotePlugin: m, linkPlugin: p, linkDialogPlugin: g, imagePlugin: l, markdownShortcutPlugin: u, toolbarPlugin: c } = r, h = [ i(), a(), m(), p(), g(), u() ], s = o ? [l({ imageUploadHandler: e })] : [], w = t ? [] : [ c({ toolbarContents: () => te({ enableImageUpload: o, ...r.toolbarComponents }) }) ]; return [...h, ...s, ...w]; }, re = (o, e = "base64", t = 5 * 1024 * 1024, r = ["image/png", "image/jpeg", "image/gif", "image/webp"]) => { const i = o || f(e); return async (a) => ee({ file: a, maxImageSize: t, allowedImageTypes: r, imageUploadHandler: i }); }, ie = (o, e, t) => J( async (r) => { if (o(r), (e === "html" || e === "both") && t) try { const i = await oe(r); t(i); } catch (i) { console.warn("Failed to convert markdown to HTML:", i); } }, [o, t, e] ), se = (o) => { const { MDXEditor: e, toolbarPlugin: t, listsPlugin: r, quotePlugin: i, headingsPlugin: a, linkPlugin: m, linkDialogPlugin: p, imagePlugin: g, markdownShortcutPlugin: l, UndoRedo: u, BoldItalicUnderlineToggles: c, CodeToggle: h, CreateLink: s, InsertImage: w, ListsToggle: v, Separator: P } = o, U = { headingsPlugin: a, listsPlugin: r, quotePlugin: i, linkPlugin: m, linkDialogPlugin: p, imagePlugin: g, markdownShortcutPlugin: l, toolbarPlugin: t, toolbarComponents: { UndoRedo: u, Separator: P, BoldItalicUnderlineToggles: c, CodeToggle: h, ListsToggle: v, CreateLink: s, InsertImage: w } }; return W.forwardRef((T, _) => { const { value: $, onChange: N, onBlur: M, placeholder: H, readOnly: E = !1, className: S, enableImageUpload: L = !1, imageUploadHandler: z, maxImageSize: F = 5 * 1024 * 1024, allowedImageTypes: D = ["image/png", "image/jpeg", "image/gif", "image/webp"], imageUploadMode: O = "base64", outputFormat: j = "markdown", onHtmlChange: R, overlayContainer: X, popupZIndex: q } = T, B = ne(q), Z = ie(N, j, R), A = re( z, O, F, D ), V = ae(L, A, E, U); return /* @__PURE__ */ n("div", { style: B, children: /* @__PURE__ */ n( e, { ref: _, markdown: $ || "", onChange: Z, onBlur: M, plugins: V, readOnly: E, placeholder: H, className: S, overlayContainer: X } ) }); }); }, k = K( () => import("@mdxeditor/editor").then((o) => { const e = se(o); return e.displayName = "SimpleEditor", { default: e }; }) ); function ce({ form: o, field: e, hasError: t, formReadOnly: r = !1, formReadOnlyStyle: i = "value" }) { const a = Q(), m = `${e.key}_html`, p = e.options.readOnly ?? r, g = e.options.readOnlyStyle ?? i; if (p) { const l = o.getValues(e.key) ?? ""; return g === "disabled" ? /* @__PURE__ */ d(b, { children: [ /* @__PURE__ */ d( "div", { className: x( a.markdownEditor.editor, a.markdownEditor.disabled, t && a.markdownEditor.error ), children: [ /* @__PURE__ */ n("div", { className: a.markdownEditor.toolbar, children: /* @__PURE__ */ n("span", { className: "text-sm text-gray-500", children: "Markdown Editor (Disabled)" }) }), /* @__PURE__ */ n( "div", { className: x( a.markdownEditor.preview, "opacity-50 min-h-[200px] p-4 font-mono text-sm whitespace-pre-wrap" ), children: l ?? "—" } ) ] } ), e.options.helpText && /* @__PURE__ */ n("div", { className: a.markdownEditor.helpText, children: e.options.helpText }) ] }) : /* @__PURE__ */ d(b, { children: [ /* @__PURE__ */ n("div", { className: x(a.markdownEditor.readOnlyValue), children: /* @__PURE__ */ n(I, { fallback: /* @__PURE__ */ n(C, { height: 200 }), children: /* @__PURE__ */ n( k, { value: l, onChange: () => { }, readOnly: !0, className: "border-none bg-transparent prose prose-sm max-w-none [&_.mdxeditor-root-contenteditable]:list-decimal [&_.mdxeditor-root-contenteditable]:list-inside [&_.mdxeditor-root-contenteditable_ul]:list-disc [&_.mdxeditor-root-contenteditable_ol]:list-decimal", enableImageUpload: e.options.enableImageUpload, imageUploadHandler: e.options.imageUploadHandler, maxImageSize: e.options.maxImageSize, allowedImageTypes: e.options.allowedImageTypes, imageUploadMode: e.options.imageUploadMode, outputFormat: e.options.outputFormat, onHtmlChange: e.options.onHtmlChange, overlayContainer: e.options.overlayContainer, popupZIndex: e.options.popupZIndex } ) }) }), e.options.helpText && /* @__PURE__ */ n("div", { className: a.markdownEditor.helpText, children: e.options.helpText }) ] }); } return /* @__PURE__ */ n( Y, { control: o.control, name: e.key, defaultValue: e.options.defaultValue ?? "", rules: { required: e.options.required, maxLength: e.options.maxLength ? { value: e.options.maxLength, message: `Content must be less than ${e.options.maxLength} characters` } : void 0 }, render: ({ field: { onChange: l, onBlur: u, value: c, ref: h } }) => /* @__PURE__ */ d("div", { className: a.markdownEditor.wrapper, children: [ /* @__PURE__ */ n(I, { fallback: /* @__PURE__ */ n(C, { height: e.options.height ?? 300 }), children: /* @__PURE__ */ d( "div", { className: x( a.markdownEditor.editor, t && a.markdownEditor.error, e.options.disabled && a.markdownEditor.disabled ), style: { minHeight: `${e.options.height ?? 300}px` }, children: [ /* @__PURE__ */ n( k, { ref: h, value: c ?? "", onChange: (s) => { e.options.maxLength && s.length > e.options.maxLength || l(s); }, onBlur: u, placeholder: e.options.placeholder, readOnly: e.options.disabled, className: "w-full prose prose-sm max-w-none [&_.mdxeditor-root-contenteditable]:list-decimal [&_.mdxeditor-root-contenteditable]:list-inside [&_.mdxeditor-root-contenteditable_ul]:list-disc [&_.mdxeditor-root-contenteditable_ol]:list-decimal", enableImageUpload: e.options.enableImageUpload, imageUploadHandler: e.options.imageUploadHandler, maxImageSize: e.options.maxImageSize, allowedImageTypes: e.options.allowedImageTypes, imageUploadMode: e.options.imageUploadMode, outputFormat: e.options.outputFormat, overlayContainer: e.options.overlayContainer, popupZIndex: e.options.popupZIndex, onHtmlChange: (s) => { e.options.outputFormat === "both" && o.setValue(m, s), e.options.onHtmlChange && e.options.onHtmlChange(s); } } ), e.options.maxLength && /* @__PURE__ */ d("div", { className: "text-sm text-gray-500 mt-1 text-right", children: [ c?.length ?? 0, "/", e.options.maxLength ] }) ] } ) }), e.options.helpText && /* @__PURE__ */ n("div", { className: a.markdownEditor.helpText, children: e.options.helpText }) ] }) } ); } export { ce as MarkdownEditor, f as defaultImageUploadHandler, ee as handleImageUpload, oe as markdownToHtml, te as toolbarContents };