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.
package/dist/viewer.js CHANGED
@@ -1,4 +1,4 @@
1
- import { C as r } from "./ContentViewer-CsFSAN_B.js";
1
+ import { C as r } from "./ContentViewer-CWZ30KYR.js";
2
2
  export {
3
3
  r as ContentViewer
4
4
  };
package/package.json CHANGED
@@ -1,133 +1,133 @@
1
- {
2
- "name": "erl-mathtextx-editor",
3
- "version": "0.1.6",
4
- "description": "Visual math editor component for solutest.id — CKEditor replacement with zero-LaTeX approach",
5
- "type": "module",
6
- "main": "./dist/erl-mathtextx-editor.umd.cjs",
7
- "module": "./dist/erl-mathtextx-editor.js",
8
- "types": "./dist/index.d.ts",
9
- "exports": {
10
- ".": {
11
- "import": "./dist/erl-mathtextx-editor.js",
12
- "require": "./dist/erl-mathtextx-editor.umd.cjs",
13
- "types": "./dist/index.d.ts"
14
- },
15
- "./viewer": {
16
- "import": "./dist/viewer.js",
17
- "types": "./dist/viewer.d.ts"
18
- },
19
- "./styles": "./dist/assets/erl-mathtextx-editor.css",
20
- "./viewer/styles": "./dist/viewer-styles.js"
21
- },
22
- "files": [
23
- "dist"
24
- ],
25
- "scripts": {
26
- "dev": "vite",
27
- "build": "tsc && vite build && vite build --config vite.config.umd.ts",
28
- "preview": "vite preview",
29
- "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
30
- "test": "vitest",
31
- "test:run": "vitest run",
32
- "test:coverage": "vitest run --coverage"
33
- },
34
- "peerDependencies": {
35
- "react": "^18.0.0 || ^19.0.0",
36
- "react-dom": "^18.0.0 || ^19.0.0"
37
- },
38
- "dependencies": {
39
- "@tiptap/core": "^2.11.0",
40
- "@tiptap/extension-bold": "^2.11.0",
41
- "@tiptap/extension-bullet-list": "^2.11.0",
42
- "@tiptap/extension-code-block": "^2.11.0",
43
- "@tiptap/extension-color": "^2.27.2",
44
- "@tiptap/extension-document": "^2.11.0",
45
- "@tiptap/extension-dropcursor": "^2.11.0",
46
- "@tiptap/extension-font-family": "^2.27.2",
47
- "@tiptap/extension-gapcursor": "^2.11.0",
48
- "@tiptap/extension-hard-break": "^2.11.0",
49
- "@tiptap/extension-heading": "^2.11.0",
50
- "@tiptap/extension-highlight": "^2.27.2",
51
- "@tiptap/extension-history": "^2.11.0",
52
- "@tiptap/extension-horizontal-rule": "^2.11.0",
53
- "@tiptap/extension-image": "^2.11.0",
54
- "@tiptap/extension-italic": "^2.11.0",
55
- "@tiptap/extension-link": "^2.11.0",
56
- "@tiptap/extension-list-item": "^2.11.0",
57
- "@tiptap/extension-ordered-list": "^2.11.0",
58
- "@tiptap/extension-paragraph": "^2.11.0",
59
- "@tiptap/extension-placeholder": "^2.11.0",
60
- "@tiptap/extension-strike": "^2.11.0",
61
- "@tiptap/extension-subscript": "^2.11.0",
62
- "@tiptap/extension-superscript": "^2.11.0",
63
- "@tiptap/extension-table": "^2.11.0",
64
- "@tiptap/extension-table-cell": "^2.11.0",
65
- "@tiptap/extension-table-header": "^2.11.0",
66
- "@tiptap/extension-table-row": "^2.11.0",
67
- "@tiptap/extension-task-item": "^2.11.0",
68
- "@tiptap/extension-task-list": "^2.11.0",
69
- "@tiptap/extension-text": "^2.11.0",
70
- "@tiptap/extension-text-align": "^2.27.2",
71
- "@tiptap/extension-text-style": "^2.27.2",
72
- "@tiptap/extension-typography": "^2.27.2",
73
- "@tiptap/extension-underline": "^2.11.0",
74
- "@tiptap/pm": "^2.11.0",
75
- "@tiptap/react": "^2.11.0",
76
- "@tiptap/starter-kit": "^2.11.0",
77
- "@weiruo/tiptap-extension-indent": "^2.0.4-1",
78
- "dompurify": "^3.3.1",
79
- "function-plot": "^1.25.3",
80
- "html2canvas": "^1.4.1",
81
- "jspdf": "^4.1.0",
82
- "katex": "^0.16.33",
83
- "mathlive": "^0.101.0"
84
- },
85
- "devDependencies": {
86
- "@eslint/js": "^9.39.2",
87
- "@fullhuman/postcss-purgecss": "^8.0.0",
88
- "@types/dompurify": "^3.0.5",
89
- "@types/react": "^18.2.0",
90
- "@types/react-dom": "^18.2.0",
91
- "@typescript-eslint/eslint-plugin": "^8.56.0",
92
- "@typescript-eslint/parser": "^8.56.0",
93
- "@vitejs/plugin-react": "^4.3.0",
94
- "@vitest/coverage-v8": "^2.1.9",
95
- "eslint": "^9.39.2",
96
- "eslint-plugin-react": "^7.37.5",
97
- "eslint-plugin-react-hooks": "^7.0.1",
98
- "eslint-plugin-react-refresh": "^0.5.0",
99
- "globals": "^17.3.0",
100
- "jsdom": "^24.1.3",
101
- "react": "^18.2.0",
102
- "react-dom": "^18.2.0",
103
- "typescript": "^5.5.0",
104
- "typescript-eslint": "^8.57.0",
105
- "vite": "^5.4.0",
106
- "vite-plugin-css-injected-by-js": "^3.5.0",
107
- "vite-plugin-dts": "^4.0.0",
108
- "vitest": "^2.1.9"
109
- },
110
- "license": "MIT",
111
- "author": "Erlangga Team",
112
- "repository": {
113
- "type": "git",
114
- "url": "git+https://github.com/erlangga/richtext-editor-research.git"
115
- },
116
- "homepage": "https://github.com/erlangga/richtext-editor-research#readme",
117
- "bugs": {
118
- "url": "https://github.com/erlangga/richtext-editor-research/issues"
119
- },
120
- "publishConfig": {
121
- "access": "public",
122
- "registry": "https://registry.npmjs.org/"
123
- },
124
- "keywords": [
125
- "math-editor",
126
- "tiptap",
127
- "mathlive",
128
- "wysiwyg",
129
- "ckeditor-replacement",
130
- "solutest",
131
- "react"
132
- ]
133
- }
1
+ {
2
+ "name": "erl-mathtextx-editor",
3
+ "version": "0.1.7",
4
+ "description": "Visual math editor component for solutest.id — CKEditor replacement with zero-LaTeX approach",
5
+ "type": "module",
6
+ "main": "./dist/erl-mathtextx-editor.umd.cjs",
7
+ "module": "./dist/erl-mathtextx-editor.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/erl-mathtextx-editor.js",
12
+ "require": "./dist/erl-mathtextx-editor.umd.cjs",
13
+ "types": "./dist/index.d.ts"
14
+ },
15
+ "./viewer": {
16
+ "import": "./dist/viewer.js",
17
+ "types": "./dist/viewer.d.ts"
18
+ },
19
+ "./styles": "./dist/assets/erl-mathtextx-editor.css",
20
+ "./viewer/styles": "./dist/viewer-styles.js"
21
+ },
22
+ "files": [
23
+ "dist"
24
+ ],
25
+ "scripts": {
26
+ "dev": "vite",
27
+ "build": "tsc && vite build && vite build --config vite.config.umd.ts",
28
+ "preview": "vite preview",
29
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
30
+ "test": "vitest",
31
+ "test:run": "vitest run",
32
+ "test:coverage": "vitest run --coverage"
33
+ },
34
+ "peerDependencies": {
35
+ "react": "^18.0.0 || ^19.0.0",
36
+ "react-dom": "^18.0.0 || ^19.0.0"
37
+ },
38
+ "dependencies": {
39
+ "@tiptap/core": "^2.11.0",
40
+ "@tiptap/extension-bold": "^2.11.0",
41
+ "@tiptap/extension-bullet-list": "^2.11.0",
42
+ "@tiptap/extension-code-block": "^2.11.0",
43
+ "@tiptap/extension-color": "^2.27.2",
44
+ "@tiptap/extension-document": "^2.11.0",
45
+ "@tiptap/extension-dropcursor": "^2.11.0",
46
+ "@tiptap/extension-font-family": "^2.27.2",
47
+ "@tiptap/extension-gapcursor": "^2.11.0",
48
+ "@tiptap/extension-hard-break": "^2.11.0",
49
+ "@tiptap/extension-heading": "^2.11.0",
50
+ "@tiptap/extension-highlight": "^2.27.2",
51
+ "@tiptap/extension-history": "^2.11.0",
52
+ "@tiptap/extension-horizontal-rule": "^2.11.0",
53
+ "@tiptap/extension-image": "^2.11.0",
54
+ "@tiptap/extension-italic": "^2.11.0",
55
+ "@tiptap/extension-link": "^2.11.0",
56
+ "@tiptap/extension-list-item": "^2.11.0",
57
+ "@tiptap/extension-ordered-list": "^2.11.0",
58
+ "@tiptap/extension-paragraph": "^2.11.0",
59
+ "@tiptap/extension-placeholder": "^2.11.0",
60
+ "@tiptap/extension-strike": "^2.11.0",
61
+ "@tiptap/extension-subscript": "^2.11.0",
62
+ "@tiptap/extension-superscript": "^2.11.0",
63
+ "@tiptap/extension-table": "^2.11.0",
64
+ "@tiptap/extension-table-cell": "^2.11.0",
65
+ "@tiptap/extension-table-header": "^2.11.0",
66
+ "@tiptap/extension-table-row": "^2.11.0",
67
+ "@tiptap/extension-task-item": "^2.11.0",
68
+ "@tiptap/extension-task-list": "^2.11.0",
69
+ "@tiptap/extension-text": "^2.11.0",
70
+ "@tiptap/extension-text-align": "^2.27.2",
71
+ "@tiptap/extension-text-style": "^2.27.2",
72
+ "@tiptap/extension-typography": "^2.27.2",
73
+ "@tiptap/extension-underline": "^2.11.0",
74
+ "@tiptap/pm": "^2.11.0",
75
+ "@tiptap/react": "^2.11.0",
76
+ "@tiptap/starter-kit": "^2.11.0",
77
+ "@weiruo/tiptap-extension-indent": "^2.0.4-1",
78
+ "dompurify": "^3.3.1",
79
+ "function-plot": "^1.25.3",
80
+ "html2canvas": "^1.4.1",
81
+ "jspdf": "^4.1.0",
82
+ "katex": "^0.16.33",
83
+ "mathlive": "^0.101.0"
84
+ },
85
+ "devDependencies": {
86
+ "@eslint/js": "^9.39.2",
87
+ "@fullhuman/postcss-purgecss": "^8.0.0",
88
+ "@types/dompurify": "^3.0.5",
89
+ "@types/react": "^18.2.0",
90
+ "@types/react-dom": "^18.2.0",
91
+ "@typescript-eslint/eslint-plugin": "^8.56.0",
92
+ "@typescript-eslint/parser": "^8.56.0",
93
+ "@vitejs/plugin-react": "^4.3.0",
94
+ "@vitest/coverage-v8": "^2.1.9",
95
+ "eslint": "^9.39.2",
96
+ "eslint-plugin-react": "^7.37.5",
97
+ "eslint-plugin-react-hooks": "^7.0.1",
98
+ "eslint-plugin-react-refresh": "^0.5.0",
99
+ "globals": "^17.3.0",
100
+ "jsdom": "^24.1.3",
101
+ "react": "^18.2.0",
102
+ "react-dom": "^18.2.0",
103
+ "typescript": "^5.5.0",
104
+ "typescript-eslint": "^8.57.0",
105
+ "vite": "^5.4.0",
106
+ "vite-plugin-css-injected-by-js": "^3.5.0",
107
+ "vite-plugin-dts": "^4.0.0",
108
+ "vitest": "^2.1.9"
109
+ },
110
+ "license": "MIT",
111
+ "author": "Erlangga Team",
112
+ "repository": {
113
+ "type": "git",
114
+ "url": "git+https://github.com/erlangga/richtext-editor-research.git"
115
+ },
116
+ "homepage": "https://github.com/erlangga/richtext-editor-research#readme",
117
+ "bugs": {
118
+ "url": "https://github.com/erlangga/richtext-editor-research/issues"
119
+ },
120
+ "publishConfig": {
121
+ "access": "public",
122
+ "registry": "https://registry.npmjs.org/"
123
+ },
124
+ "keywords": [
125
+ "math-editor",
126
+ "tiptap",
127
+ "mathlive",
128
+ "wysiwyg",
129
+ "ckeditor-replacement",
130
+ "solutest",
131
+ "react"
132
+ ]
133
+ }
@@ -1,238 +0,0 @@
1
- import { jsxs as i, Fragment as J, jsx as e } from "react/jsx-runtime";
2
- import { useId as V, useRef as y, useState as d, useCallback as s } from "react";
3
- import { u as q } from "./index-wMMXFiRr.js";
4
- function Z({
5
- isOpen: U,
6
- onClose: N,
7
- onInsert: u,
8
- onImageUpload: v
9
- }) {
10
- const w = V(), R = y(null), [p, L] = d(v ? "upload" : "url"), [r, D] = d(""), [g, C] = d(""), [B, h] = d(!1), [T, k] = d(!1), [f, o] = d(null), [P, l] = d(""), F = y(null), m = y(null), j = s(() => {
11
- m.current && (URL.revokeObjectURL(m.current), m.current = null), D(""), C(""), o(null), l(""), k(!1), h(!1);
12
- }, []), t = s(() => {
13
- j(), N();
14
- }, [N, j]);
15
- q({ isOpen: U, dialogRef: R, onClose: t });
16
- const A = async (a) => {
17
- if (!["image/png", "image/jpeg", "image/jpg", "image/gif", "image/webp"].includes(a.type))
18
- return { valid: !1, error: "File harus berupa gambar (JPG, PNG, GIF, WebP)" };
19
- if (a.size > 10 * 1024 * 1024)
20
- return { valid: !1, error: "Ukuran file maksimal 10MB" };
21
- const _ = {
22
- "image/png": [[137, 80, 78, 71]],
23
- "image/jpeg": [[255, 216, 255]],
24
- "image/jpg": [[255, 216, 255]],
25
- "image/gif": [[71, 73, 70, 56]],
26
- "image/webp": [[82, 73, 70, 70]]
27
- };
28
- try {
29
- const c = await a.slice(0, 8).arrayBuffer(), x = new Uint8Array(c), S = _[a.type];
30
- if (!S)
31
- return { valid: !1, error: "Format gambar tidak dikenali" };
32
- if (!S.some(
33
- (W) => W.every(($, z) => x[z] === $)
34
- ))
35
- return { valid: !1, error: "File signature tidak valid. Kemungkinan file rusak atau mencurigakan." };
36
- } catch {
37
- return { valid: !1, error: "Gagal memvalidasi file" };
38
- }
39
- return { valid: !0 };
40
- }, b = s(
41
- async (a) => {
42
- const n = await A(a);
43
- if (!n.valid) {
44
- l(n.error);
45
- return;
46
- }
47
- l(""), m.current && URL.revokeObjectURL(m.current);
48
- const _ = URL.createObjectURL(a);
49
- if (m.current = _, o(_), v) {
50
- k(!0);
51
- try {
52
- const c = await v(a);
53
- u(c, g || a.name), t();
54
- } catch {
55
- l("Upload gagal. Silakan coba lagi."), o(null);
56
- } finally {
57
- k(!1);
58
- }
59
- } else {
60
- const c = new FileReader();
61
- c.onload = () => {
62
- const x = c.result;
63
- u(x, g || a.name), t();
64
- }, c.readAsDataURL(a);
65
- }
66
- },
67
- [v, u, g, t]
68
- ), M = s(
69
- (a) => {
70
- const n = a.target.files?.[0];
71
- n && b(n);
72
- },
73
- [b]
74
- ), I = s((a) => {
75
- a.preventDefault(), a.stopPropagation(), h(!0);
76
- }, []), O = s((a) => {
77
- a.preventDefault(), a.stopPropagation(), h(!1);
78
- }, []), E = s(
79
- (a) => {
80
- a.preventDefault(), a.stopPropagation(), h(!1);
81
- const n = a.dataTransfer.files?.[0];
82
- n && b(n);
83
- },
84
- [b]
85
- ), G = s(() => {
86
- if (!r.trim()) {
87
- l("Masukkan URL gambar");
88
- return;
89
- }
90
- try {
91
- new URL(r);
92
- } catch {
93
- l("URL tidak valid");
94
- return;
95
- }
96
- u(r.trim(), g || void 0), t();
97
- }, [r, g, u, t]), K = s(() => {
98
- if (r.trim())
99
- try {
100
- new URL(r), o(r.trim()), l("");
101
- } catch {
102
- l("URL tidak valid");
103
- }
104
- }, [r]);
105
- return U ? /* @__PURE__ */ i(J, { children: [
106
- /* @__PURE__ */ e("div", { className: "mtx-dialog-overlay", onClick: t }),
107
- /* @__PURE__ */ i("div", { className: "mtx-image-dialog", ref: R, role: "dialog", "aria-modal": "true", "aria-labelledby": w, tabIndex: -1, children: [
108
- /* @__PURE__ */ i("div", { className: "mtx-image-dialog__header", children: [
109
- /* @__PURE__ */ e("h3", { id: w, children: "Sisipkan Gambar" }),
110
- /* @__PURE__ */ e(
111
- "button",
112
- {
113
- className: "mtx-image-dialog__close",
114
- onClick: t,
115
- "aria-label": "Tutup",
116
- children: "✕"
117
- }
118
- )
119
- ] }),
120
- /* @__PURE__ */ i("div", { className: "mtx-image-dialog__tabs", children: [
121
- /* @__PURE__ */ e(
122
- "button",
123
- {
124
- className: `mtx-image-dialog__tab ${p === "upload" ? "is-active" : ""}`,
125
- onClick: () => {
126
- L("upload"), l(""), o(null);
127
- },
128
- children: "📁 Upload File"
129
- }
130
- ),
131
- /* @__PURE__ */ e(
132
- "button",
133
- {
134
- className: `mtx-image-dialog__tab ${p === "url" ? "is-active" : ""}`,
135
- onClick: () => {
136
- L("url"), l(""), o(null);
137
- },
138
- children: "🔗 URL"
139
- }
140
- )
141
- ] }),
142
- /* @__PURE__ */ i("div", { className: "mtx-image-dialog__body", children: [
143
- p === "upload" && /* @__PURE__ */ i(
144
- "div",
145
- {
146
- className: `mtx-image-dialog__dropzone ${B ? "is-dragging" : ""}`,
147
- onDragOver: I,
148
- onDragLeave: O,
149
- onDrop: E,
150
- onClick: () => F.current?.click(),
151
- children: [
152
- /* @__PURE__ */ e(
153
- "input",
154
- {
155
- ref: F,
156
- type: "file",
157
- accept: "image/*",
158
- onChange: M,
159
- style: { display: "none" }
160
- }
161
- ),
162
- T ? /* @__PURE__ */ i("div", { className: "mtx-image-dialog__uploading", children: [
163
- /* @__PURE__ */ e("div", { className: "mtx-spinner" }),
164
- /* @__PURE__ */ e("p", { children: "Mengupload gambar..." })
165
- ] }) : f ? /* @__PURE__ */ e("div", { className: "mtx-image-dialog__preview", children: /* @__PURE__ */ e("img", { src: f, alt: "Preview" }) }) : /* @__PURE__ */ i("div", { className: "mtx-image-dialog__placeholder", children: [
166
- /* @__PURE__ */ i("svg", { width: "48", height: "48", viewBox: "0 0 48 48", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
167
- /* @__PURE__ */ e("rect", { x: "4", y: "8", width: "40", height: "32", rx: "4" }),
168
- /* @__PURE__ */ e("circle", { cx: "16", cy: "20", r: "4" }),
169
- /* @__PURE__ */ e("path", { d: "M4 36l10-10 6 6 8-10 16 14" })
170
- ] }),
171
- /* @__PURE__ */ i("p", { children: [
172
- /* @__PURE__ */ e("strong", { children: "Klik untuk pilih file" }),
173
- " atau drag & drop ke sini"
174
- ] }),
175
- /* @__PURE__ */ e("span", { children: "JPG, PNG, GIF, WebP — Maks 10MB" })
176
- ] })
177
- ]
178
- }
179
- ),
180
- p === "url" && /* @__PURE__ */ i("div", { className: "mtx-image-dialog__url-form", children: [
181
- /* @__PURE__ */ e("label", { children: "URL Gambar" }),
182
- /* @__PURE__ */ e("div", { className: "mtx-image-dialog__url-row", children: /* @__PURE__ */ e(
183
- "input",
184
- {
185
- type: "url",
186
- value: r,
187
- onChange: (a) => D(a.target.value),
188
- placeholder: "https://example.com/gambar.jpg",
189
- onKeyDown: (a) => {
190
- a.key === "Enter" && G();
191
- },
192
- onBlur: K,
193
- autoFocus: !0
194
- }
195
- ) }),
196
- f && /* @__PURE__ */ e("div", { className: "mtx-image-dialog__url-preview", children: /* @__PURE__ */ e(
197
- "img",
198
- {
199
- src: f,
200
- alt: "Preview",
201
- onError: () => {
202
- o(null), l("Gambar tidak dapat dimuat dari URL ini");
203
- }
204
- }
205
- ) })
206
- ] }),
207
- /* @__PURE__ */ i("div", { className: "mtx-image-dialog__alt", children: [
208
- /* @__PURE__ */ e("label", { children: "Teks Alternatif (opsional)" }),
209
- /* @__PURE__ */ e(
210
- "input",
211
- {
212
- type: "text",
213
- value: g,
214
- onChange: (a) => C(a.target.value),
215
- placeholder: "Deskripsi gambar untuk aksesibilitas"
216
- }
217
- )
218
- ] }),
219
- P && /* @__PURE__ */ e("div", { className: "mtx-image-dialog__error", children: P })
220
- ] }),
221
- /* @__PURE__ */ i("div", { className: "mtx-image-dialog__footer", children: [
222
- /* @__PURE__ */ e("button", { className: "mtx-image-dialog__btn mtx-image-dialog__btn--cancel", onClick: t, children: "Batal" }),
223
- p === "url" && /* @__PURE__ */ e(
224
- "button",
225
- {
226
- className: "mtx-image-dialog__btn mtx-image-dialog__btn--insert",
227
- onClick: G,
228
- disabled: !r.trim(),
229
- children: "Sisipkan"
230
- }
231
- )
232
- ] })
233
- ] })
234
- ] }) : null;
235
- }
236
- export {
237
- Z as ImageInsertDialog
238
- };
@@ -1,5 +0,0 @@
1
- import { NodeViewProps } from '@tiptap/react';
2
- /**
3
- * MathLive field wrapper for use inside TipTap node view.
4
- */
5
- export declare function MathFieldView(props: NodeViewProps): import("react/jsx-runtime").JSX.Element;
@@ -1,46 +0,0 @@
1
- /**
2
- * Logger utility for the editor package.
3
- * Logs only in development modes to avoid information disclosure in production.
4
- * TODO: Add integration with error tracking service (Sentry, etc.) for production
5
- */
6
- declare global {
7
- interface Window {
8
- __DEV__?: boolean;
9
- }
10
- }
11
- /**
12
- * Logger object with methods for different log levels.
13
- * In production, these are no-ops to prevent console noise and info disclosure.
14
- * Note: Uses only console.warn and console.error to comply with ESLint rules.
15
- */
16
- export declare const logger: {
17
- /**
18
- * Log error messages. In production, consider sending to error tracking service.
19
- */
20
- error: (message: string, error?: unknown) => void;
21
- /**
22
- * Log warning messages.
23
- */
24
- warn: (message: string, data?: unknown) => void;
25
- /**
26
- * Log informational messages (uses warn in dev to comply with ESLint rules).
27
- */
28
- info: (message: string, data?: unknown) => void;
29
- /**
30
- * Log debug messages (verbose logging for development, uses warn in dev).
31
- */
32
- debug: (message: string, data?: unknown) => void;
33
- };
34
- /**
35
- * Type-safe error handler that captures both message and error object.
36
- * Use this for async operations where you need to handle errors.
37
- */
38
- export declare function handleError(context: string, error: unknown, options?: {
39
- silent?: boolean;
40
- fallbackMessage?: string;
41
- }): void;
42
- /**
43
- * Wrap a function with error logging.
44
- * Useful for event handlers and callbacks.
45
- */
46
- export declare function withErrorLogging<T extends (...args: unknown[]) => unknown>(fn: T, context: string): (...args: Parameters<T>) => ReturnType<T> | undefined;