@hachej/boring-workspace 0.1.5 → 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.
@@ -1,349 +0,0 @@
1
- import { jsxs as A, jsx as t } from "react/jsx-runtime";
2
- import { useRef as k, useState as y, useEffect as L } from "react";
3
- import { ReactNodeViewRenderer as S, NodeViewWrapper as B, useEditor as E, EditorContent as U, useEditorState as P } from "@tiptap/react";
4
- import z from "@tiptap/starter-kit";
5
- import D from "@tiptap/extension-underline";
6
- import W from "@tiptap/extension-link";
7
- import T from "@tiptap/extension-placeholder";
8
- import F from "@tiptap/extension-task-list";
9
- import j from "@tiptap/extension-task-item";
10
- import q from "@tiptap/extension-text-align";
11
- import V from "@tiptap/extension-highlight";
12
- import { Table as _ } from "@tiptap/extension-table";
13
- import { TableRow as $ } from "@tiptap/extension-table-row";
14
- import { TableHeader as X } from "@tiptap/extension-table-header";
15
- import { TableCell as K } from "@tiptap/extension-table-cell";
16
- import O from "@tiptap/extension-image";
17
- import { c as v } from "./utils-B6yFEsav.js";
18
- import Q from "@tiptap/extension-code-block-lowlight";
19
- import { createLowlight as Z, common as G } from "lowlight";
20
- import { Markdown as J } from "tiptap-markdown";
21
- import { BoldIcon as Y, ItalicIcon as tt, UnderlineIcon as et, StrikethroughIcon as it, Heading1Icon as rt, Heading2Icon as nt, Heading3Icon as at, ListIcon as ot, ListOrderedIcon as lt, ListChecksIcon as st, QuoteIcon as ct, CodeIcon as ut, LinkIcon as gt, ImageIcon as dt, HighlighterIcon as mt, AlignLeftIcon as ft, AlignCenterIcon as ht, AlignRightIcon as pt, MinusIcon as wt } from "lucide-react";
22
- import { Toolbar as kt, Input as vt, ToolbarButton as bt, ToolbarSeparator as Lt } from "@hachej/boring-ui-kit";
23
- const I = 64, x = 2e3, At = O.extend({
24
- name: "image",
25
- draggable: !0,
26
- addAttributes() {
27
- var a;
28
- return {
29
- ...((a = this.parent) == null ? void 0 : a.call(this)) ?? {},
30
- width: {
31
- default: null,
32
- parseHTML: (n) => {
33
- const r = n.getAttribute("width");
34
- if (r) {
35
- const s = parseInt(r, 10);
36
- return Number.isFinite(s) ? s : null;
37
- }
38
- const u = n.style.width;
39
- if (u && u.endsWith("px")) {
40
- const s = parseInt(u, 10);
41
- return Number.isFinite(s) ? s : null;
42
- }
43
- return null;
44
- },
45
- renderHTML: (n) => n.width ? { width: String(n.width) } : {}
46
- },
47
- align: {
48
- default: "left",
49
- parseHTML: (n) => {
50
- const r = n.getAttribute("data-align");
51
- return r === "left" || r === "center" || r === "right" ? r : n.style.marginLeft === "auto" && n.style.marginRight === "auto" ? "center" : n.style.marginLeft === "auto" ? "right" : "left";
52
- },
53
- renderHTML: (n) => ({ "data-align": n.align ?? "left" })
54
- }
55
- };
56
- },
57
- addNodeView() {
58
- return S(It);
59
- }
60
- });
61
- function It({ node: i, updateAttributes: a, selected: n }) {
62
- const r = k(null), u = k(null), [s, d] = y(!1), c = i.attrs.src ?? "", e = i.attrs.alt ?? "", o = i.attrs.title ?? void 0, g = i.attrs.width, m = i.attrs.align ?? "left";
63
- L(() => {
64
- if (!s) return;
65
- const h = (b) => {
66
- const p = u.current;
67
- if (!p) return;
68
- const R = b.clientX - p.x, M = Math.max(I, Math.min(x, p.width + R));
69
- a({ width: Math.round(M) });
70
- }, f = () => {
71
- u.current = null, d(!1);
72
- };
73
- return window.addEventListener("pointermove", h), window.addEventListener("pointerup", f), window.addEventListener("pointercancel", f), () => {
74
- window.removeEventListener("pointermove", h), window.removeEventListener("pointerup", f), window.removeEventListener("pointercancel", f);
75
- };
76
- }, [s, a]);
77
- const H = (h) => {
78
- var p;
79
- h.preventDefault(), h.stopPropagation();
80
- const f = (p = r.current) == null ? void 0 : p.querySelector("img"), b = g ?? (f == null ? void 0 : f.getBoundingClientRect().width) ?? 320;
81
- u.current = { x: h.clientX, width: b }, d(!0);
82
- };
83
- return /* @__PURE__ */ A(
84
- B,
85
- {
86
- ref: r,
87
- "data-resizable-image": "",
88
- "data-selected": n ? "true" : void 0,
89
- className: v(
90
- "relative block max-w-full align-baseline",
91
- "[&>img]:block [&>img]:max-w-full [&>img]:h-auto [&>img]:rounded-md",
92
- m === "left" && "mr-auto",
93
- m === "center" && "mx-auto",
94
- m === "right" && "ml-auto",
95
- n && "ring-2 ring-[color:var(--accent)] ring-offset-1 ring-offset-background"
96
- ),
97
- style: { width: g ? `${g}px` : void 0 },
98
- children: [
99
- /* @__PURE__ */ t("img", { src: c, alt: e, title: o, draggable: !1 }),
100
- /* @__PURE__ */ t(
101
- "span",
102
- {
103
- role: "slider",
104
- "aria-label": "Resize image",
105
- "aria-valuenow": g ?? 0,
106
- "aria-valuemin": I,
107
- "aria-valuemax": x,
108
- "data-testid": "resize-handle",
109
- onPointerDown: H,
110
- className: v(
111
- "absolute right-0 bottom-0 h-3 w-3 translate-x-1/2 translate-y-1/2 cursor-nwse-resize",
112
- "rounded-full border border-background bg-[color:var(--accent)] shadow",
113
- "opacity-0 transition-opacity duration-150 ease-out",
114
- (n || s) && "opacity-100"
115
- )
116
- }
117
- )
118
- ]
119
- }
120
- );
121
- }
122
- const xt = Z(G), Ct = [
123
- /<script[\s>][\s\S]*?<\/script>/gi,
124
- /<iframe[\s>][\s\S]*?<\/iframe>/gi,
125
- /\s+on\w+\s*=\s*["'][^"']*["']/gi,
126
- /\s+on\w+\s*=\s*\S+/gi,
127
- /href\s*=\s*["']?\s*javascript:[^"'\s>]*/gi,
128
- /src\s*=\s*["']?\s*javascript:[^"'\s>]*/gi
129
- ];
130
- function Nt(i) {
131
- let a = i;
132
- for (const n of Ct)
133
- a = a.replace(n, "");
134
- return a;
135
- }
136
- const C = [
137
- z.configure({
138
- codeBlock: !1,
139
- link: !1,
140
- underline: !1
141
- }),
142
- D,
143
- W.configure({
144
- openOnClick: !0,
145
- autolink: !0,
146
- linkOnPaste: !0,
147
- defaultProtocol: "https",
148
- HTMLAttributes: { rel: "noopener noreferrer nofollow", target: "_blank" }
149
- }),
150
- T.configure({
151
- placeholder: "Start writing..."
152
- }),
153
- F,
154
- j.configure({ nested: !0 }),
155
- q.configure({
156
- types: ["heading", "paragraph"]
157
- }),
158
- V,
159
- _.configure({
160
- resizable: !0
161
- }),
162
- $,
163
- X,
164
- K,
165
- At.configure({
166
- inline: !1,
167
- allowBase64: !0
168
- }),
169
- Q.configure({ lowlight: xt }),
170
- J.configure({
171
- html: !0,
172
- transformPastedText: !0,
173
- transformCopiedText: !0
174
- })
175
- ];
176
- function l({ onClick: i, active: a, disabled: n, title: r, children: u }) {
177
- return /* @__PURE__ */ t(
178
- bt,
179
- {
180
- type: "button",
181
- size: "icon-xs",
182
- onClick: i,
183
- disabled: n,
184
- title: r,
185
- "aria-pressed": a,
186
- className: v(
187
- "text-muted-foreground/70",
188
- a && "bg-[color:var(--accent-soft)] text-[color:var(--accent)]"
189
- ),
190
- children: u
191
- }
192
- );
193
- }
194
- function w() {
195
- return /* @__PURE__ */ t(Lt, { className: "mx-2 h-3.5" });
196
- }
197
- function N(i) {
198
- const a = i.trim().toLowerCase();
199
- return !a.startsWith("javascript:") && !a.startsWith("data:text/html");
200
- }
201
- function Tt(i) {
202
- return new Promise((a, n) => {
203
- const r = new FileReader();
204
- r.onload = () => a(r.result), r.onerror = () => n(r.error ?? new Error("Read failed")), r.readAsDataURL(i);
205
- });
206
- }
207
- function Ht({ editor: i }) {
208
- const a = (e) => {
209
- if (i) {
210
- if (i.isActive("image")) {
211
- i.chain().focus().updateAttributes("image", { align: e }).run();
212
- return;
213
- }
214
- i.chain().focus().setTextAlign(e).run();
215
- }
216
- }, n = k(null), r = P({
217
- editor: i,
218
- selector: ({ editor: e }) => e ? {
219
- bold: e.isActive("bold"),
220
- italic: e.isActive("italic"),
221
- underline: e.isActive("underline"),
222
- strike: e.isActive("strike"),
223
- h1: e.isActive("heading", { level: 1 }),
224
- h2: e.isActive("heading", { level: 2 }),
225
- h3: e.isActive("heading", { level: 3 }),
226
- bulletList: e.isActive("bulletList"),
227
- orderedList: e.isActive("orderedList"),
228
- taskList: e.isActive("taskList"),
229
- blockquote: e.isActive("blockquote"),
230
- codeBlock: e.isActive("codeBlock"),
231
- link: e.isActive("link"),
232
- highlight: e.isActive("highlight"),
233
- alignLeft: e.isActive("image") ? (e.getAttributes("image").align ?? "left") === "left" : e.isActive({ textAlign: "left" }),
234
- alignCenter: e.isActive("image") ? e.getAttributes("image").align === "center" : e.isActive({ textAlign: "center" }),
235
- alignRight: e.isActive("image") ? e.getAttributes("image").align === "right" : e.isActive({ textAlign: "right" })
236
- } : null
237
- });
238
- if (!i || !r) return null;
239
- const u = () => {
240
- const e = window.prompt("URL:");
241
- e && N(e) && i.chain().focus().extendMarkRange("link").setLink({ href: e }).run();
242
- }, s = () => {
243
- const e = window.prompt("Image URL:");
244
- e && N(e) && i.chain().focus().setImage({ src: e }).run();
245
- }, d = (e) => {
246
- var o;
247
- if (e != null && e.shiftKey) {
248
- s();
249
- return;
250
- }
251
- (o = n.current) == null || o.click();
252
- }, c = async (e) => {
253
- var g;
254
- const o = (g = e.target.files) == null ? void 0 : g[0];
255
- if (e.target.value = "", !(!o || !o.type.startsWith("image/")))
256
- try {
257
- const m = await Tt(o);
258
- i.chain().focus().setImage({ src: m, alt: o.name }).run();
259
- } catch {
260
- }
261
- };
262
- return /* @__PURE__ */ A(kt, { className: "border-b border-border/60 bg-background px-3 py-1.5", "aria-label": "Formatting toolbar", children: [
263
- /* @__PURE__ */ t(l, { onClick: () => i.chain().focus().toggleBold().run(), active: r.bold, title: "Bold", children: /* @__PURE__ */ t(Y, { className: "h-4 w-4" }) }),
264
- /* @__PURE__ */ t(l, { onClick: () => i.chain().focus().toggleItalic().run(), active: r.italic, title: "Italic", children: /* @__PURE__ */ t(tt, { className: "h-4 w-4" }) }),
265
- /* @__PURE__ */ t(l, { onClick: () => i.chain().focus().toggleUnderline().run(), active: r.underline, title: "Underline", children: /* @__PURE__ */ t(et, { className: "h-4 w-4" }) }),
266
- /* @__PURE__ */ t(l, { onClick: () => i.chain().focus().toggleStrike().run(), active: r.strike, title: "Strikethrough", children: /* @__PURE__ */ t(it, { className: "h-4 w-4" }) }),
267
- /* @__PURE__ */ t(w, {}),
268
- /* @__PURE__ */ t(l, { onClick: () => i.chain().focus().toggleHeading({ level: 1 }).run(), active: r.h1, title: "Heading 1", children: /* @__PURE__ */ t(rt, { className: "h-4 w-4" }) }),
269
- /* @__PURE__ */ t(l, { onClick: () => i.chain().focus().toggleHeading({ level: 2 }).run(), active: r.h2, title: "Heading 2", children: /* @__PURE__ */ t(nt, { className: "h-4 w-4" }) }),
270
- /* @__PURE__ */ t(l, { onClick: () => i.chain().focus().toggleHeading({ level: 3 }).run(), active: r.h3, title: "Heading 3", children: /* @__PURE__ */ t(at, { className: "h-4 w-4" }) }),
271
- /* @__PURE__ */ t(w, {}),
272
- /* @__PURE__ */ t(l, { onClick: () => i.chain().focus().toggleBulletList().run(), active: r.bulletList, title: "Bullet list", children: /* @__PURE__ */ t(ot, { className: "h-4 w-4" }) }),
273
- /* @__PURE__ */ t(l, { onClick: () => i.chain().focus().toggleOrderedList().run(), active: r.orderedList, title: "Ordered list", children: /* @__PURE__ */ t(lt, { className: "h-4 w-4" }) }),
274
- /* @__PURE__ */ t(l, { onClick: () => i.chain().focus().toggleTaskList().run(), active: r.taskList, title: "Task list", children: /* @__PURE__ */ t(st, { className: "h-4 w-4" }) }),
275
- /* @__PURE__ */ t(w, {}),
276
- /* @__PURE__ */ t(l, { onClick: () => i.chain().focus().toggleBlockquote().run(), active: r.blockquote, title: "Quote", children: /* @__PURE__ */ t(ct, { className: "h-4 w-4" }) }),
277
- /* @__PURE__ */ t(l, { onClick: () => i.chain().focus().toggleCodeBlock().run(), active: r.codeBlock, title: "Code block", children: /* @__PURE__ */ t(ut, { className: "h-4 w-4" }) }),
278
- /* @__PURE__ */ t(l, { onClick: u, active: r.link, title: "Link", children: /* @__PURE__ */ t(gt, { className: "h-4 w-4" }) }),
279
- /* @__PURE__ */ t(
280
- l,
281
- {
282
- onClick: d,
283
- title: "Image (click to upload, Shift+click for URL)",
284
- children: /* @__PURE__ */ t(dt, { className: "h-4 w-4" })
285
- }
286
- ),
287
- /* @__PURE__ */ t(
288
- vt,
289
- {
290
- ref: n,
291
- "data-testid": "image-file-input",
292
- type: "file",
293
- accept: "image/*",
294
- className: "hidden",
295
- onChange: c
296
- }
297
- ),
298
- /* @__PURE__ */ t(l, { onClick: () => i.chain().focus().toggleHighlight().run(), active: r.highlight, title: "Highlight", children: /* @__PURE__ */ t(mt, { className: "h-4 w-4" }) }),
299
- /* @__PURE__ */ t(w, {}),
300
- /* @__PURE__ */ t(l, { onClick: () => a("left"), active: r.alignLeft, title: "Align left", children: /* @__PURE__ */ t(ft, { className: "h-4 w-4" }) }),
301
- /* @__PURE__ */ t(l, { onClick: () => a("center"), active: r.alignCenter, title: "Center align", children: /* @__PURE__ */ t(ht, { className: "h-4 w-4" }) }),
302
- /* @__PURE__ */ t(l, { onClick: () => a("right"), active: r.alignRight, title: "Align right", children: /* @__PURE__ */ t(pt, { className: "h-4 w-4" }) }),
303
- /* @__PURE__ */ t(w, {}),
304
- /* @__PURE__ */ t(l, { onClick: () => i.chain().focus().setHorizontalRule().run(), title: "Horizontal rule", children: /* @__PURE__ */ t(wt, { className: "h-4 w-4" }) })
305
- ] });
306
- }
307
- function Gt({
308
- content: i,
309
- onChange: a,
310
- readOnly: n = !1,
311
- placeholder: r,
312
- className: u
313
- }) {
314
- const s = k(a);
315
- s.current = a;
316
- const d = k(!1), c = E({
317
- extensions: r ? [
318
- ...C.filter((e) => e.name !== "placeholder"),
319
- T.configure({ placeholder: r })
320
- ] : C,
321
- content: i,
322
- editable: !n,
323
- editorProps: {
324
- attributes: {
325
- class: "tiptap-prose max-w-[68ch] px-8 py-6 focus:outline-none min-h-[200px]"
326
- },
327
- transformPastedHTML: Nt
328
- },
329
- onUpdate: ({ editor: e }) => {
330
- var o, g, m;
331
- d.current || (m = s.current) == null || m.call(s, ((g = (o = e.storage.markdown) == null ? void 0 : o.getMarkdown) == null ? void 0 : g.call(o)) ?? e.getHTML());
332
- }
333
- });
334
- return L(() => {
335
- !c || c.isDestroyed || c.setEditable(!n);
336
- }, [c, n]), L(() => {
337
- var o, g;
338
- !c || c.isDestroyed || (((g = (o = c.storage.markdown) == null ? void 0 : o.getMarkdown) == null ? void 0 : g.call(o)) ?? c.getHTML()) === i || (d.current = !0, c.commands.setContent(i), d.current = !1);
339
- }, [c, i]), /* @__PURE__ */ A("div", { className: v("flex h-full flex-col overflow-hidden", u), children: [
340
- !n && /* @__PURE__ */ t(Ht, { editor: c }),
341
- /* @__PURE__ */ t("div", { className: "flex-1 overflow-auto", children: /* @__PURE__ */ t(U, { editor: c }) })
342
- ] });
343
- }
344
- export {
345
- Gt as MarkdownEditor,
346
- N as isSafeUrl,
347
- Tt as readFileAsDataUrl,
348
- Nt as sanitizeHtml
349
- };