erl-mathtextx-editor 0.1.6 → 0.1.7

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.
@@ -0,0 +1,217 @@
1
+ import { jsxs as l, Fragment as E, jsx as e } from "react/jsx-runtime";
2
+ import { useId as I, useRef as P, useState as c, useCallback as n } from "react";
3
+ import { u as W } from "./index-Ci20X1Rj.js";
4
+ function O({
5
+ isOpen: f,
6
+ onClose: x,
7
+ onInsert: m,
8
+ onImageUpload: p
9
+ }) {
10
+ const k = I(), N = P(null), [g, y] = c(p ? "upload" : "url"), [t, U] = c(""), [d, w] = c(""), [F, h] = c(!1), [G, b] = c(!1), [v, s] = c(null), [D, i] = c(""), R = P(null), C = n(() => {
11
+ U(""), w(""), s(null), i(""), b(!1), h(!1);
12
+ }, []), r = n(() => {
13
+ C(), x();
14
+ }, [x, C]);
15
+ W({ isOpen: f, dialogRef: N, onClose: r });
16
+ const _ = n(
17
+ async (a) => {
18
+ if (!a.type.startsWith("image/")) {
19
+ i("File harus berupa gambar (jpg, png, gif, webp)");
20
+ return;
21
+ }
22
+ if (a.size > 10 * 1024 * 1024) {
23
+ i("Ukuran file maksimal 10MB");
24
+ return;
25
+ }
26
+ i("");
27
+ const o = URL.createObjectURL(a);
28
+ if (s(o), p) {
29
+ b(!0);
30
+ try {
31
+ const u = await p(a);
32
+ m(u, d || a.name), r();
33
+ } catch {
34
+ i("Upload gagal. Silakan coba lagi."), s(null);
35
+ } finally {
36
+ b(!1);
37
+ }
38
+ } else {
39
+ const u = new FileReader();
40
+ u.onload = () => {
41
+ const T = u.result;
42
+ m(T, d || a.name), r();
43
+ }, u.readAsDataURL(a);
44
+ }
45
+ },
46
+ [p, m, d, r]
47
+ ), M = n(
48
+ (a) => {
49
+ const o = a.target.files?.[0];
50
+ o && _(o);
51
+ },
52
+ [_]
53
+ ), S = n((a) => {
54
+ a.preventDefault(), a.stopPropagation(), h(!0);
55
+ }, []), j = n((a) => {
56
+ a.preventDefault(), a.stopPropagation(), h(!1);
57
+ }, []), A = n(
58
+ (a) => {
59
+ a.preventDefault(), a.stopPropagation(), h(!1);
60
+ const o = a.dataTransfer.files?.[0];
61
+ o && _(o);
62
+ },
63
+ [_]
64
+ ), L = n(() => {
65
+ if (!t.trim()) {
66
+ i("Masukkan URL gambar");
67
+ return;
68
+ }
69
+ try {
70
+ new URL(t);
71
+ } catch {
72
+ i("URL tidak valid");
73
+ return;
74
+ }
75
+ m(t.trim(), d || void 0), r();
76
+ }, [t, d, m, r]), B = n(() => {
77
+ if (t.trim())
78
+ try {
79
+ new URL(t), s(t.trim()), i("");
80
+ } catch {
81
+ i("URL tidak valid");
82
+ }
83
+ }, [t]);
84
+ return f ? /* @__PURE__ */ l(E, { children: [
85
+ /* @__PURE__ */ e("div", { className: "mtx-dialog-overlay", onClick: r }),
86
+ /* @__PURE__ */ l("div", { className: "mtx-image-dialog", ref: N, role: "dialog", "aria-modal": "true", "aria-labelledby": k, tabIndex: -1, children: [
87
+ /* @__PURE__ */ l("div", { className: "mtx-image-dialog__header", children: [
88
+ /* @__PURE__ */ e("h3", { id: k, children: "Sisipkan Gambar" }),
89
+ /* @__PURE__ */ e(
90
+ "button",
91
+ {
92
+ className: "mtx-image-dialog__close",
93
+ onClick: r,
94
+ "aria-label": "Tutup",
95
+ children: "✕"
96
+ }
97
+ )
98
+ ] }),
99
+ /* @__PURE__ */ l("div", { className: "mtx-image-dialog__tabs", children: [
100
+ /* @__PURE__ */ e(
101
+ "button",
102
+ {
103
+ className: `mtx-image-dialog__tab ${g === "upload" ? "is-active" : ""}`,
104
+ onClick: () => {
105
+ y("upload"), i(""), s(null);
106
+ },
107
+ children: "📁 Upload File"
108
+ }
109
+ ),
110
+ /* @__PURE__ */ e(
111
+ "button",
112
+ {
113
+ className: `mtx-image-dialog__tab ${g === "url" ? "is-active" : ""}`,
114
+ onClick: () => {
115
+ y("url"), i(""), s(null);
116
+ },
117
+ children: "🔗 URL"
118
+ }
119
+ )
120
+ ] }),
121
+ /* @__PURE__ */ l("div", { className: "mtx-image-dialog__body", children: [
122
+ g === "upload" && /* @__PURE__ */ l(
123
+ "div",
124
+ {
125
+ className: `mtx-image-dialog__dropzone ${F ? "is-dragging" : ""}`,
126
+ onDragOver: S,
127
+ onDragLeave: j,
128
+ onDrop: A,
129
+ onClick: () => R.current?.click(),
130
+ children: [
131
+ /* @__PURE__ */ e(
132
+ "input",
133
+ {
134
+ ref: R,
135
+ type: "file",
136
+ accept: "image/*",
137
+ onChange: M,
138
+ style: { display: "none" }
139
+ }
140
+ ),
141
+ G ? /* @__PURE__ */ l("div", { className: "mtx-image-dialog__uploading", children: [
142
+ /* @__PURE__ */ e("div", { className: "mtx-spinner" }),
143
+ /* @__PURE__ */ e("p", { children: "Mengupload gambar..." })
144
+ ] }) : v ? /* @__PURE__ */ e("div", { className: "mtx-image-dialog__preview", children: /* @__PURE__ */ e("img", { src: v, alt: "Preview" }) }) : /* @__PURE__ */ l("div", { className: "mtx-image-dialog__placeholder", children: [
145
+ /* @__PURE__ */ l("svg", { width: "48", height: "48", viewBox: "0 0 48 48", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
146
+ /* @__PURE__ */ e("rect", { x: "4", y: "8", width: "40", height: "32", rx: "4" }),
147
+ /* @__PURE__ */ e("circle", { cx: "16", cy: "20", r: "4" }),
148
+ /* @__PURE__ */ e("path", { d: "M4 36l10-10 6 6 8-10 16 14" })
149
+ ] }),
150
+ /* @__PURE__ */ l("p", { children: [
151
+ /* @__PURE__ */ e("strong", { children: "Klik untuk pilih file" }),
152
+ " atau drag & drop ke sini"
153
+ ] }),
154
+ /* @__PURE__ */ e("span", { children: "JPG, PNG, GIF, WebP — Maks 10MB" })
155
+ ] })
156
+ ]
157
+ }
158
+ ),
159
+ g === "url" && /* @__PURE__ */ l("div", { className: "mtx-image-dialog__url-form", children: [
160
+ /* @__PURE__ */ e("label", { children: "URL Gambar" }),
161
+ /* @__PURE__ */ e("div", { className: "mtx-image-dialog__url-row", children: /* @__PURE__ */ e(
162
+ "input",
163
+ {
164
+ type: "url",
165
+ value: t,
166
+ onChange: (a) => U(a.target.value),
167
+ placeholder: "https://example.com/gambar.jpg",
168
+ onKeyDown: (a) => {
169
+ a.key === "Enter" && L();
170
+ },
171
+ onBlur: B,
172
+ autoFocus: !0
173
+ }
174
+ ) }),
175
+ v && /* @__PURE__ */ e("div", { className: "mtx-image-dialog__url-preview", children: /* @__PURE__ */ e(
176
+ "img",
177
+ {
178
+ src: v,
179
+ alt: "Preview",
180
+ onError: () => {
181
+ s(null), i("Gambar tidak dapat dimuat dari URL ini");
182
+ }
183
+ }
184
+ ) })
185
+ ] }),
186
+ /* @__PURE__ */ l("div", { className: "mtx-image-dialog__alt", children: [
187
+ /* @__PURE__ */ e("label", { children: "Teks Alternatif (opsional)" }),
188
+ /* @__PURE__ */ e(
189
+ "input",
190
+ {
191
+ type: "text",
192
+ value: d,
193
+ onChange: (a) => w(a.target.value),
194
+ placeholder: "Deskripsi gambar untuk aksesibilitas"
195
+ }
196
+ )
197
+ ] }),
198
+ D && /* @__PURE__ */ e("div", { className: "mtx-image-dialog__error", children: D })
199
+ ] }),
200
+ /* @__PURE__ */ l("div", { className: "mtx-image-dialog__footer", children: [
201
+ /* @__PURE__ */ e("button", { className: "mtx-image-dialog__btn mtx-image-dialog__btn--cancel", onClick: r, children: "Batal" }),
202
+ g === "url" && /* @__PURE__ */ e(
203
+ "button",
204
+ {
205
+ className: "mtx-image-dialog__btn mtx-image-dialog__btn--insert",
206
+ onClick: L,
207
+ disabled: !t.trim(),
208
+ children: "Sisipkan"
209
+ }
210
+ )
211
+ ] })
212
+ ] })
213
+ ] }) : null;
214
+ }
215
+ export {
216
+ O as ImageInsertDialog
217
+ };
@@ -1,6 +1,6 @@
1
1
  import { jsx as e, jsxs as t } from "react/jsx-runtime";
2
2
  import N, { useId as v, useRef as f, useState as c, useEffect as g, useCallback as w } from "react";
3
- import { u as y } from "./index-wMMXFiRr.js";
3
+ import { u as y } from "./index-Ci20X1Rj.js";
4
4
  const k = N.memo(({ isOpen: i, onInsert: d, onClose: m }) => {
5
5
  const b = v(), u = f(null), [l, n] = c(3), [a, s] = c(3), [o, h] = c(!0);
6
6
  g(() => {
@@ -1,102 +1,87 @@
1
- import { jsx as e, jsxs as a } from "react/jsx-runtime";
2
- import D, { useId as _, useRef as j, useState as n, useEffect as F, useCallback as d } from "react";
3
- import { u as E } from "./index-wMMXFiRr.js";
4
- const S = D.memo(({
5
- isOpen: s,
6
- currentUrl: o = "",
7
- currentText: m = "",
1
+ import { jsx as t, jsxs as a } from "react/jsx-runtime";
2
+ import w, { useId as F, useRef as U, useState as r, useEffect as j, useCallback as d } from "react";
3
+ import { u as E } from "./index-Ci20X1Rj.js";
4
+ const P = w.memo(({
5
+ isOpen: m,
6
+ currentUrl: i = "",
7
+ currentText: s = "",
8
8
  currentTitle: h = "",
9
9
  currentTarget: u = "_blank",
10
10
  onInsert: g,
11
11
  onRemove: p,
12
- onClose: r
12
+ onClose: o
13
13
  }) => {
14
- const N = _(), v = j(null), [x, y] = n(o), [k, C] = n(m), [f, L] = n(h), [b, R] = n(u), [c, i] = n("");
15
- F(() => {
16
- s && (y(o), C(m), L(h), R(u || "_blank"), i(""));
17
- }, [s, o, m, h, u]), E({ isOpen: s, dialogRef: v, onClose: r });
18
- const U = d((t) => {
19
- if (!t.trim())
20
- return i("URL tidak boleh kosong"), !1;
21
- if (t.startsWith("#"))
22
- return i(""), !0;
23
- try {
24
- const l = new URL(t);
25
- if (l.protocol !== "http:" && l.protocol !== "https:")
26
- return i("URL harus dimulai dengan http:// atau https://"), !1;
27
- if (t.includes("javascript:") || t.includes("data:") || t.includes("vbscript:"))
28
- return i("URL tidak valid"), !1;
29
- } catch {
30
- return i("URL tidak valid. Pastikan format benar (contoh: https://example.com)"), !1;
31
- }
32
- return i(""), !0;
33
- }, []), I = d((t) => {
34
- const l = t.trim();
14
+ const N = F(), v = U(null), [x, y] = r(i), [k, C] = r(s), [f, L] = r(h), [b, R] = r(u), [c, n] = r("");
15
+ j(() => {
16
+ m && (y(i), C(s), L(h), R(u || "_blank"), n(""));
17
+ }, [m, i, s, h, u]), E({ isOpen: m, dialogRef: v, onClose: o });
18
+ const I = d((e) => e.trim() ? /^(https?:\/\/|mailto:|#)[^\s]+$/i.test(e) ? (n(""), !0) : (n("URL harus dimulai dengan http://, https://, mailto:, atau #"), !1) : (n("URL tidak boleh kosong"), !1), []), D = d((e) => {
19
+ const l = e.trim();
35
20
  return l.startsWith("http://") || l.startsWith("https://") || l.startsWith("mailto:") || l.startsWith("#") ? l : `https://${l}`;
36
- }, []), W = d((t) => {
37
- t.preventDefault();
38
- const l = I(x);
39
- U(l) && g({
21
+ }, []), W = d((e) => {
22
+ e.preventDefault();
23
+ const l = D(x);
24
+ I(l) && g({
40
25
  url: l,
41
26
  text: k.trim() || void 0,
42
27
  title: f.trim() || void 0,
43
28
  target: b || void 0
44
29
  });
45
- }, [x, k, f, b, U, I, g]), w = d(() => {
46
- p?.(), r();
47
- }, [p, r]);
48
- return s ? /* @__PURE__ */ e("div", { className: "mtx-modal-overlay", onClick: r, children: /* @__PURE__ */ a(
30
+ }, [x, k, f, b, I, D, g]), _ = d(() => {
31
+ p?.(), o();
32
+ }, [p, o]);
33
+ return m ? /* @__PURE__ */ t("div", { className: "mtx-modal-overlay", onClick: o, children: /* @__PURE__ */ a(
49
34
  "div",
50
35
  {
51
36
  ref: v,
52
37
  className: "mtx-modal-dialog mtx-link-dialog",
53
- onClick: (t) => t.stopPropagation(),
38
+ onClick: (e) => e.stopPropagation(),
54
39
  role: "dialog",
55
40
  "aria-modal": "true",
56
41
  "aria-labelledby": N,
57
42
  tabIndex: -1,
58
43
  children: [
59
44
  /* @__PURE__ */ a("div", { className: "mtx-modal-header", children: [
60
- /* @__PURE__ */ e("h3", { className: "mtx-modal-title", id: N, children: o ? "Edit Link" : "Insert Link" }),
61
- /* @__PURE__ */ e("button", { className: "mtx-modal-close", onClick: r, title: "Close", "aria-label": "Close dialog", children: /* @__PURE__ */ e("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ e("path", { d: "M4 4l8 8m0-8l-8 8", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) }) })
45
+ /* @__PURE__ */ t("h3", { className: "mtx-modal-title", id: N, children: i ? "Edit Link" : "Insert Link" }),
46
+ /* @__PURE__ */ t("button", { className: "mtx-modal-close", onClick: o, title: "Close", "aria-label": "Close dialog", children: /* @__PURE__ */ t("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ t("path", { d: "M4 4l8 8m0-8l-8 8", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) }) })
62
47
  ] }),
63
48
  /* @__PURE__ */ a("form", { onSubmit: W, children: [
64
49
  /* @__PURE__ */ a("div", { className: "mtx-modal-body", children: [
65
50
  /* @__PURE__ */ a("div", { className: "mtx-form-group", children: [
66
51
  /* @__PURE__ */ a("label", { className: "mtx-form-label", htmlFor: "link-url", children: [
67
52
  "URL ",
68
- /* @__PURE__ */ e("span", { className: "mtx-required", children: "*" })
53
+ /* @__PURE__ */ t("span", { className: "mtx-required", children: "*" })
69
54
  ] }),
70
- /* @__PURE__ */ e(
55
+ /* @__PURE__ */ t(
71
56
  "input",
72
57
  {
73
58
  id: "link-url",
74
59
  type: "text",
75
60
  className: `mtx-form-input ${c ? "mtx-input-error" : ""}`,
76
61
  value: x,
77
- onChange: (t) => {
78
- y(t.target.value), c && i("");
62
+ onChange: (e) => {
63
+ y(e.target.value), c && n("");
79
64
  },
80
65
  placeholder: "https://example.com",
81
66
  autoFocus: !0,
82
67
  autoComplete: "url"
83
68
  }
84
69
  ),
85
- c && /* @__PURE__ */ e("div", { className: "mtx-form-error", children: c })
70
+ c && /* @__PURE__ */ t("div", { className: "mtx-form-error", children: c })
86
71
  ] }),
87
72
  /* @__PURE__ */ a("div", { className: "mtx-form-group", children: [
88
73
  /* @__PURE__ */ a("label", { className: "mtx-form-label", htmlFor: "link-text", children: [
89
74
  "Display Text",
90
- /* @__PURE__ */ e("span", { className: "mtx-form-hint", children: m ? "(kosongkan untuk tetap menggunakan text saat ini)" : "(opsional, akan menggunakan URL jika kosong)" })
75
+ /* @__PURE__ */ t("span", { className: "mtx-form-hint", children: s ? "(kosongkan untuk tetap menggunakan text saat ini)" : "(opsional, akan menggunakan URL jika kosong)" })
91
76
  ] }),
92
- /* @__PURE__ */ e(
77
+ /* @__PURE__ */ t(
93
78
  "input",
94
79
  {
95
80
  id: "link-text",
96
81
  type: "text",
97
82
  className: "mtx-form-input",
98
83
  value: k,
99
- onChange: (t) => C(t.target.value),
84
+ onChange: (e) => C(e.target.value),
100
85
  placeholder: "Click here",
101
86
  autoComplete: "off"
102
87
  }
@@ -105,38 +90,38 @@ const S = D.memo(({
105
90
  /* @__PURE__ */ a("div", { className: "mtx-form-group", children: [
106
91
  /* @__PURE__ */ a("label", { className: "mtx-form-label", htmlFor: "link-title", children: [
107
92
  "Title (Tooltip)",
108
- /* @__PURE__ */ e("span", { className: "mtx-form-hint", children: "Teks yang muncul saat hover" })
93
+ /* @__PURE__ */ t("span", { className: "mtx-form-hint", children: "Teks yang muncul saat hover" })
109
94
  ] }),
110
- /* @__PURE__ */ e(
95
+ /* @__PURE__ */ t(
111
96
  "input",
112
97
  {
113
98
  id: "link-title",
114
99
  type: "text",
115
100
  className: "mtx-form-input",
116
101
  value: f,
117
- onChange: (t) => L(t.target.value),
102
+ onChange: (e) => L(e.target.value),
118
103
  placeholder: "Visit our website",
119
104
  autoComplete: "off"
120
105
  }
121
106
  )
122
107
  ] }),
123
- /* @__PURE__ */ e("div", { className: "mtx-form-group mtx-form-checkbox", children: /* @__PURE__ */ a("label", { className: "mtx-checkbox-label", children: [
124
- /* @__PURE__ */ e(
108
+ /* @__PURE__ */ t("div", { className: "mtx-form-group mtx-form-checkbox", children: /* @__PURE__ */ a("label", { className: "mtx-checkbox-label", children: [
109
+ /* @__PURE__ */ t(
125
110
  "input",
126
111
  {
127
112
  type: "checkbox",
128
113
  checked: b === "_blank",
129
- onChange: (t) => R(t.target.checked ? "_blank" : "_self")
114
+ onChange: (e) => R(e.target.checked ? "_blank" : "_self")
130
115
  }
131
116
  ),
132
- /* @__PURE__ */ e("span", { children: "Open in new tab" })
117
+ /* @__PURE__ */ t("span", { children: "Open in new tab" })
133
118
  ] }) })
134
119
  ] }),
135
120
  /* @__PURE__ */ a("div", { className: "mtx-modal-footer", children: [
136
- /* @__PURE__ */ e("button", { type: "button", className: "mtx-btn mtx-btn-secondary", onClick: r, children: "Cancel" }),
137
- o && p && /* @__PURE__ */ e("button", { type: "button", className: "mtx-btn mtx-btn-danger", onClick: w, children: "Remove Link" }),
121
+ /* @__PURE__ */ t("button", { type: "button", className: "mtx-btn mtx-btn-secondary", onClick: o, children: "Cancel" }),
122
+ i && p && /* @__PURE__ */ t("button", { type: "button", className: "mtx-btn mtx-btn-danger", onClick: _, children: "Remove Link" }),
138
123
  /* @__PURE__ */ a("button", { type: "submit", className: "mtx-btn mtx-btn-primary", children: [
139
- o ? "Update" : "Insert",
124
+ i ? "Update" : "Insert",
140
125
  " Link"
141
126
  ] })
142
127
  ] })
@@ -145,7 +130,7 @@ const S = D.memo(({
145
130
  }
146
131
  ) }) : null;
147
132
  });
148
- S.displayName = "LinkDialogImpl";
133
+ P.displayName = "LinkDialogImpl";
149
134
  export {
150
- S as LinkDialogImpl
135
+ P as LinkDialogImpl
151
136
  };
@@ -1,6 +1,6 @@
1
1
  import { jsx as e, jsxs as t } from "react/jsx-runtime";
2
2
  import o, { useId as c, useRef as n, useCallback as p } from "react";
3
- import { u as h } from "./index-wMMXFiRr.js";
3
+ import { u as h } from "./index-Ci20X1Rj.js";
4
4
  const x = [
5
5
  { id: "plain", name: "Plain", description: "Simple table without styling", headerStyle: "none", borderStyle: "all", stripeRows: !1 },
6
6
  { id: "light", name: "Light", description: "Light gray header", headerStyle: "light", borderStyle: "all", stripeRows: !1 },