@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.
- package/dist/{CommandPalette-aM61U-b0.js → CommandPalette-DzIDQUfk.js} +1534 -1433
- package/dist/{FileTree-DRq_bfue.js → FileTree-CspphShP.js} +1 -1
- package/dist/MarkdownEditor-wDDxxED5.js +474 -0
- package/dist/{WorkspaceLoadingState-By0dZoPD.js → WorkspaceLoadingState-Cd8nkNHp.js} +1 -1
- package/dist/app-front.js +2 -2
- package/dist/testing.js +1 -1
- package/dist/workspace.css +28 -0
- package/dist/workspace.d.ts +3 -1
- package/dist/workspace.js +5 -5
- package/docs/PLUGIN_STRUCTURE.md +1 -1
- package/package.json +4 -4
- package/dist/MarkdownEditor-DjiHxnRv.js +0 -349
|
@@ -2,7 +2,7 @@ import { jsx as i, jsxs as C } from "react/jsx-runtime";
|
|
|
2
2
|
import { useRef as w, useEffect as R, useMemo as P, useCallback as x, createContext as H, useContext as L } from "react";
|
|
3
3
|
import { Tree as q } from "react-arborist";
|
|
4
4
|
import { FolderOpenIcon as z, FolderIcon as B, ChevronRightIcon as K, Loader2Icon as E } from "lucide-react";
|
|
5
|
-
import { K as Y } from "./CommandPalette-
|
|
5
|
+
import { K as Y } from "./CommandPalette-DzIDQUfk.js";
|
|
6
6
|
import { Input as G } from "@hachej/boring-ui-kit";
|
|
7
7
|
import { c as v } from "./utils-B6yFEsav.js";
|
|
8
8
|
const T = /* @__PURE__ */ new Set(), A = H({
|
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
import { jsxs as C, jsx as e } from "react/jsx-runtime";
|
|
2
|
+
import { useState as x, useCallback as U, useRef as A, useEffect as N } from "react";
|
|
3
|
+
import { ReactNodeViewRenderer as $, NodeViewWrapper as E, useEditor as P, EditorContent as F, useEditorState as D } from "@tiptap/react";
|
|
4
|
+
import z from "@tiptap/starter-kit";
|
|
5
|
+
import W from "@tiptap/extension-underline";
|
|
6
|
+
import q from "@tiptap/extension-link";
|
|
7
|
+
import S from "@tiptap/extension-placeholder";
|
|
8
|
+
import j from "@tiptap/extension-task-list";
|
|
9
|
+
import _ from "@tiptap/extension-task-item";
|
|
10
|
+
import V from "@tiptap/extension-text-align";
|
|
11
|
+
import X from "@tiptap/extension-highlight";
|
|
12
|
+
import { Table as K } from "@tiptap/extension-table";
|
|
13
|
+
import { TableRow as Q } from "@tiptap/extension-table-row";
|
|
14
|
+
import { TableHeader as O } from "@tiptap/extension-table-header";
|
|
15
|
+
import { TableCell as Z } from "@tiptap/extension-table-cell";
|
|
16
|
+
import G from "@tiptap/extension-image";
|
|
17
|
+
import { c as L } from "./utils-B6yFEsav.js";
|
|
18
|
+
import { uploadFile as J } from "@hachej/boring-agent/front";
|
|
19
|
+
import { an as Y, ao as tt } from "./CommandPalette-DzIDQUfk.js";
|
|
20
|
+
import et from "@tiptap/extension-code-block-lowlight";
|
|
21
|
+
import { createLowlight as it, common as rt } from "lowlight";
|
|
22
|
+
import { Markdown as nt } from "@tiptap/markdown";
|
|
23
|
+
import { BoldIcon as at, ItalicIcon as ot, UnderlineIcon as lt, StrikethroughIcon as st, Heading1Icon as ct, Heading2Icon as ut, Heading3Icon as gt, ListIcon as ft, ListOrderedIcon as dt, ListChecksIcon as mt, QuoteIcon as ht, CodeIcon as pt, LinkIcon as wt, ImageIcon as kt, HighlighterIcon as bt, AlignLeftIcon as vt, AlignCenterIcon as At, AlignRightIcon as It, MinusIcon as Lt } from "lucide-react";
|
|
24
|
+
import { Toolbar as yt, Input as Nt, ToolbarButton as Ct, ToolbarSeparator as xt } from "@hachej/boring-ui-kit";
|
|
25
|
+
function Tt(t) {
|
|
26
|
+
const r = Y(), n = tt(), [a, s] = x(0);
|
|
27
|
+
return { upload: U(
|
|
28
|
+
async (o, h) => {
|
|
29
|
+
s((b) => b + 1);
|
|
30
|
+
try {
|
|
31
|
+
return await J(o, {
|
|
32
|
+
apiBaseUrl: r,
|
|
33
|
+
workspaceRequestId: n,
|
|
34
|
+
directory: (h == null ? void 0 : h.directory) ?? (t == null ? void 0 : t.directory),
|
|
35
|
+
sourcePath: h == null ? void 0 : h.sourcePath
|
|
36
|
+
});
|
|
37
|
+
} finally {
|
|
38
|
+
s((b) => b - 1);
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
[r, n, t == null ? void 0 : t.directory]
|
|
42
|
+
), uploading: a > 0 };
|
|
43
|
+
}
|
|
44
|
+
const T = 64, R = 2e3;
|
|
45
|
+
function Rt(t) {
|
|
46
|
+
return t.replace(/\\/g, "\\\\").replace(/]/g, "\\]");
|
|
47
|
+
}
|
|
48
|
+
function y(t) {
|
|
49
|
+
return t.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
50
|
+
}
|
|
51
|
+
function H(t) {
|
|
52
|
+
if (typeof t == "number" && Number.isFinite(t) && t > 0) return t;
|
|
53
|
+
if (typeof t == "string" && t.trim()) {
|
|
54
|
+
const r = Number(t);
|
|
55
|
+
if (Number.isFinite(r) && r > 0) return r;
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const Ht = G.extend({
|
|
60
|
+
name: "image",
|
|
61
|
+
draggable: !0,
|
|
62
|
+
parseMarkdown: (t, r) => r.createNode("image", {
|
|
63
|
+
src: t.href,
|
|
64
|
+
title: t.title,
|
|
65
|
+
alt: t.text
|
|
66
|
+
}),
|
|
67
|
+
renderMarkdown: (t) => {
|
|
68
|
+
var p, k, i, d, m, w, c;
|
|
69
|
+
const r = typeof ((p = t.attrs) == null ? void 0 : p.src) == "string" ? t.attrs.src : "", n = typeof ((k = t.attrs) == null ? void 0 : k.alt) == "string" ? t.attrs.alt : "", a = typeof ((i = t.attrs) == null ? void 0 : i.title) == "string" ? t.attrs.title : "", s = H((d = t.attrs) == null ? void 0 : d.width), g = H((m = t.attrs) == null ? void 0 : m.height), o = ((w = t.attrs) == null ? void 0 : w.align) === "center" || ((c = t.attrs) == null ? void 0 : c.align) === "right" ? t.attrs.align : "left";
|
|
70
|
+
if (!s && !g && o === "left") {
|
|
71
|
+
const l = Rt(n);
|
|
72
|
+
return a ? `}")` : ``;
|
|
73
|
+
}
|
|
74
|
+
const b = `<img ${[
|
|
75
|
+
`src="${y(r)}"`,
|
|
76
|
+
n ? `alt="${y(n)}"` : null,
|
|
77
|
+
a ? `title="${y(a)}"` : null,
|
|
78
|
+
s ? `width="${s}"` : null,
|
|
79
|
+
g ? `height="${g}"` : null
|
|
80
|
+
].filter(Boolean).join(" ")} />`;
|
|
81
|
+
return o === "center" || o === "right" ? `<p align="${o}">${b}</p>` : b;
|
|
82
|
+
},
|
|
83
|
+
addAttributes() {
|
|
84
|
+
var r;
|
|
85
|
+
return {
|
|
86
|
+
...((r = this.parent) == null ? void 0 : r.call(this)) ?? {},
|
|
87
|
+
width: {
|
|
88
|
+
default: null,
|
|
89
|
+
parseHTML: (n) => {
|
|
90
|
+
const a = n.getAttribute("width");
|
|
91
|
+
if (a) {
|
|
92
|
+
const g = parseInt(a, 10);
|
|
93
|
+
return Number.isFinite(g) ? g : null;
|
|
94
|
+
}
|
|
95
|
+
const s = n.style.width;
|
|
96
|
+
if (s && s.endsWith("px")) {
|
|
97
|
+
const g = parseInt(s, 10);
|
|
98
|
+
return Number.isFinite(g) ? g : null;
|
|
99
|
+
}
|
|
100
|
+
return null;
|
|
101
|
+
},
|
|
102
|
+
renderHTML: (n) => n.width ? { width: String(n.width) } : {}
|
|
103
|
+
},
|
|
104
|
+
align: {
|
|
105
|
+
default: "left",
|
|
106
|
+
parseHTML: (n) => {
|
|
107
|
+
const a = n.getAttribute("data-align");
|
|
108
|
+
return a === "left" || a === "center" || a === "right" ? a : n.style.marginLeft === "auto" && n.style.marginRight === "auto" ? "center" : n.style.marginLeft === "auto" ? "right" : "left";
|
|
109
|
+
},
|
|
110
|
+
renderHTML: (n) => ({ "data-align": n.align ?? "left" })
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
},
|
|
114
|
+
addNodeView() {
|
|
115
|
+
return $(Mt);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
function Mt({ node: t, updateAttributes: r, selected: n }) {
|
|
119
|
+
const a = A(null), s = A(null), [g, o] = x(!1), h = t.attrs.src ?? "", b = t.attrs.alt ?? "", p = t.attrs.title ?? void 0, k = t.attrs.width, i = t.attrs.align ?? "left";
|
|
120
|
+
N(() => {
|
|
121
|
+
if (!g) return;
|
|
122
|
+
const m = (c) => {
|
|
123
|
+
const l = s.current;
|
|
124
|
+
if (!l) return;
|
|
125
|
+
const f = c.clientX - l.x, v = Math.max(T, Math.min(R, l.width + f));
|
|
126
|
+
r({ width: Math.round(v) });
|
|
127
|
+
}, w = () => {
|
|
128
|
+
s.current = null, o(!1);
|
|
129
|
+
};
|
|
130
|
+
return window.addEventListener("pointermove", m), window.addEventListener("pointerup", w), window.addEventListener("pointercancel", w), () => {
|
|
131
|
+
window.removeEventListener("pointermove", m), window.removeEventListener("pointerup", w), window.removeEventListener("pointercancel", w);
|
|
132
|
+
};
|
|
133
|
+
}, [g, r]);
|
|
134
|
+
const d = (m) => {
|
|
135
|
+
var l;
|
|
136
|
+
m.preventDefault(), m.stopPropagation();
|
|
137
|
+
const w = (l = a.current) == null ? void 0 : l.querySelector("img"), c = k ?? (w == null ? void 0 : w.getBoundingClientRect().width) ?? 320;
|
|
138
|
+
s.current = { x: m.clientX, width: c }, o(!0);
|
|
139
|
+
};
|
|
140
|
+
return /* @__PURE__ */ C(
|
|
141
|
+
E,
|
|
142
|
+
{
|
|
143
|
+
ref: a,
|
|
144
|
+
"data-resizable-image": "",
|
|
145
|
+
"data-selected": n ? "true" : void 0,
|
|
146
|
+
className: L(
|
|
147
|
+
"relative block max-w-full align-baseline",
|
|
148
|
+
"[&>img]:block [&>img]:max-w-full [&>img]:h-auto [&>img]:rounded-md",
|
|
149
|
+
i === "left" && "mr-auto",
|
|
150
|
+
i === "center" && "mx-auto",
|
|
151
|
+
i === "right" && "ml-auto",
|
|
152
|
+
n && "ring-2 ring-[color:var(--accent)] ring-offset-1 ring-offset-background"
|
|
153
|
+
),
|
|
154
|
+
style: { width: k ? `${k}px` : void 0 },
|
|
155
|
+
children: [
|
|
156
|
+
/* @__PURE__ */ e("img", { src: h, alt: b, title: p, draggable: !1 }),
|
|
157
|
+
/* @__PURE__ */ e(
|
|
158
|
+
"span",
|
|
159
|
+
{
|
|
160
|
+
role: "slider",
|
|
161
|
+
"aria-label": "Resize image",
|
|
162
|
+
"aria-valuenow": k ?? 0,
|
|
163
|
+
"aria-valuemin": T,
|
|
164
|
+
"aria-valuemax": R,
|
|
165
|
+
"data-testid": "resize-handle",
|
|
166
|
+
onPointerDown: d,
|
|
167
|
+
className: L(
|
|
168
|
+
"absolute right-0 bottom-0 h-3 w-3 translate-x-1/2 translate-y-1/2 cursor-nwse-resize",
|
|
169
|
+
"rounded-full border border-background bg-[color:var(--accent)] shadow",
|
|
170
|
+
"opacity-0 transition-opacity duration-150 ease-out",
|
|
171
|
+
(n || g) && "opacity-100"
|
|
172
|
+
)
|
|
173
|
+
}
|
|
174
|
+
)
|
|
175
|
+
]
|
|
176
|
+
}
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
const Bt = it(rt), St = [
|
|
180
|
+
/<script[\s>][\s\S]*?<\/script>/gi,
|
|
181
|
+
/<iframe[\s>][\s\S]*?<\/iframe>/gi,
|
|
182
|
+
/\s+on\w+\s*=\s*["'][^"']*["']/gi,
|
|
183
|
+
/\s+on\w+\s*=\s*\S+/gi,
|
|
184
|
+
/href\s*=\s*["']?\s*javascript:[^"'\s>]*/gi,
|
|
185
|
+
/src\s*=\s*["']?\s*javascript:[^"'\s>]*/gi
|
|
186
|
+
];
|
|
187
|
+
function Ut(t) {
|
|
188
|
+
let r = t;
|
|
189
|
+
for (const n of St)
|
|
190
|
+
r = r.replace(n, "");
|
|
191
|
+
return r;
|
|
192
|
+
}
|
|
193
|
+
const M = [
|
|
194
|
+
z.configure({
|
|
195
|
+
codeBlock: !1,
|
|
196
|
+
link: !1,
|
|
197
|
+
underline: !1
|
|
198
|
+
}),
|
|
199
|
+
W,
|
|
200
|
+
q.configure({
|
|
201
|
+
openOnClick: !0,
|
|
202
|
+
autolink: !0,
|
|
203
|
+
linkOnPaste: !0,
|
|
204
|
+
defaultProtocol: "https",
|
|
205
|
+
HTMLAttributes: { rel: "noopener noreferrer nofollow", target: "_blank" }
|
|
206
|
+
}),
|
|
207
|
+
S.configure({
|
|
208
|
+
placeholder: "Start writing..."
|
|
209
|
+
}),
|
|
210
|
+
j,
|
|
211
|
+
_.configure({ nested: !0 }),
|
|
212
|
+
V.configure({
|
|
213
|
+
types: ["heading", "paragraph"]
|
|
214
|
+
}),
|
|
215
|
+
X,
|
|
216
|
+
K.configure({
|
|
217
|
+
resizable: !0
|
|
218
|
+
}),
|
|
219
|
+
Q,
|
|
220
|
+
O,
|
|
221
|
+
Z,
|
|
222
|
+
Ht.configure({
|
|
223
|
+
inline: !1,
|
|
224
|
+
allowBase64: !0
|
|
225
|
+
}),
|
|
226
|
+
et.configure({ lowlight: Bt }),
|
|
227
|
+
nt.configure({
|
|
228
|
+
markedOptions: {
|
|
229
|
+
gfm: !0,
|
|
230
|
+
breaks: !1,
|
|
231
|
+
pedantic: !1
|
|
232
|
+
}
|
|
233
|
+
})
|
|
234
|
+
];
|
|
235
|
+
function u({ onClick: t, active: r, disabled: n, title: a, children: s }) {
|
|
236
|
+
return /* @__PURE__ */ e(
|
|
237
|
+
Ct,
|
|
238
|
+
{
|
|
239
|
+
type: "button",
|
|
240
|
+
size: "icon-xs",
|
|
241
|
+
onClick: t,
|
|
242
|
+
disabled: n,
|
|
243
|
+
title: a,
|
|
244
|
+
"aria-pressed": r,
|
|
245
|
+
className: L(
|
|
246
|
+
"text-muted-foreground/70",
|
|
247
|
+
r && "bg-[color:var(--accent-soft)] text-[color:var(--accent)]"
|
|
248
|
+
),
|
|
249
|
+
children: s
|
|
250
|
+
}
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
function I() {
|
|
254
|
+
return /* @__PURE__ */ e(xt, { className: "mx-2 h-3.5" });
|
|
255
|
+
}
|
|
256
|
+
function B(t) {
|
|
257
|
+
const r = t.trim().toLowerCase();
|
|
258
|
+
return !r.startsWith("javascript:") && !r.startsWith("data:text/html");
|
|
259
|
+
}
|
|
260
|
+
function $t(t) {
|
|
261
|
+
return new Promise((r, n) => {
|
|
262
|
+
const a = new FileReader();
|
|
263
|
+
a.onload = () => r(a.result), a.onerror = () => n(a.error ?? new Error("Read failed")), a.readAsDataURL(t);
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
function Et(t) {
|
|
267
|
+
if (!t) return null;
|
|
268
|
+
for (const r of Array.from(t.files ?? []))
|
|
269
|
+
if (r.type.startsWith("image/")) return r;
|
|
270
|
+
for (const r of Array.from(t.items ?? [])) {
|
|
271
|
+
if (r.kind !== "file" || !r.type.startsWith("image/")) continue;
|
|
272
|
+
const n = r.getAsFile();
|
|
273
|
+
if (n) return n;
|
|
274
|
+
}
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
function Pt({
|
|
278
|
+
editor: t,
|
|
279
|
+
onInsertImage: r,
|
|
280
|
+
rawMode: n,
|
|
281
|
+
onToggleRawMode: a
|
|
282
|
+
}) {
|
|
283
|
+
const s = (i) => {
|
|
284
|
+
if (t) {
|
|
285
|
+
if (t.isActive("image")) {
|
|
286
|
+
t.chain().focus().updateAttributes("image", { align: i }).run();
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
t.chain().focus().setTextAlign(i).run();
|
|
290
|
+
}
|
|
291
|
+
}, g = A(null), o = D({
|
|
292
|
+
editor: t,
|
|
293
|
+
selector: ({ editor: i }) => i ? {
|
|
294
|
+
bold: i.isActive("bold"),
|
|
295
|
+
italic: i.isActive("italic"),
|
|
296
|
+
underline: i.isActive("underline"),
|
|
297
|
+
strike: i.isActive("strike"),
|
|
298
|
+
h1: i.isActive("heading", { level: 1 }),
|
|
299
|
+
h2: i.isActive("heading", { level: 2 }),
|
|
300
|
+
h3: i.isActive("heading", { level: 3 }),
|
|
301
|
+
bulletList: i.isActive("bulletList"),
|
|
302
|
+
orderedList: i.isActive("orderedList"),
|
|
303
|
+
taskList: i.isActive("taskList"),
|
|
304
|
+
blockquote: i.isActive("blockquote"),
|
|
305
|
+
codeBlock: i.isActive("codeBlock"),
|
|
306
|
+
link: i.isActive("link"),
|
|
307
|
+
highlight: i.isActive("highlight"),
|
|
308
|
+
alignLeft: i.isActive("image") ? (i.getAttributes("image").align ?? "left") === "left" : i.isActive({ textAlign: "left" }),
|
|
309
|
+
alignCenter: i.isActive("image") ? i.getAttributes("image").align === "center" : i.isActive({ textAlign: "center" }),
|
|
310
|
+
alignRight: i.isActive("image") ? i.getAttributes("image").align === "right" : i.isActive({ textAlign: "right" })
|
|
311
|
+
} : null
|
|
312
|
+
});
|
|
313
|
+
if (!t || !o) return null;
|
|
314
|
+
const h = () => {
|
|
315
|
+
const i = window.prompt("URL:");
|
|
316
|
+
i && B(i) && t.chain().focus().extendMarkRange("link").setLink({ href: i }).run();
|
|
317
|
+
}, b = () => {
|
|
318
|
+
const i = window.prompt("Image URL:");
|
|
319
|
+
i && B(i) && t.chain().focus().setImage({ src: i }).run();
|
|
320
|
+
}, p = (i) => {
|
|
321
|
+
var d;
|
|
322
|
+
if (i != null && i.shiftKey) {
|
|
323
|
+
b();
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
(d = g.current) == null || d.click();
|
|
327
|
+
}, k = async (i) => {
|
|
328
|
+
var m;
|
|
329
|
+
const d = (m = i.target.files) == null ? void 0 : m[0];
|
|
330
|
+
i.target.value = "", !(!d || !d.type.startsWith("image/")) && await r(d);
|
|
331
|
+
};
|
|
332
|
+
return /* @__PURE__ */ C(yt, { className: "border-b border-border/60 bg-background px-3 py-1.5", "aria-label": "Formatting toolbar", children: [
|
|
333
|
+
/* @__PURE__ */ e(u, { onClick: () => t.chain().focus().toggleBold().run(), active: o.bold, title: "Bold", children: /* @__PURE__ */ e(at, { className: "h-4 w-4" }) }),
|
|
334
|
+
/* @__PURE__ */ e(u, { onClick: () => t.chain().focus().toggleItalic().run(), active: o.italic, title: "Italic", children: /* @__PURE__ */ e(ot, { className: "h-4 w-4" }) }),
|
|
335
|
+
/* @__PURE__ */ e(u, { onClick: () => t.chain().focus().toggleUnderline().run(), active: o.underline, title: "Underline", children: /* @__PURE__ */ e(lt, { className: "h-4 w-4" }) }),
|
|
336
|
+
/* @__PURE__ */ e(u, { onClick: () => t.chain().focus().toggleStrike().run(), active: o.strike, title: "Strikethrough", children: /* @__PURE__ */ e(st, { className: "h-4 w-4" }) }),
|
|
337
|
+
/* @__PURE__ */ e(I, {}),
|
|
338
|
+
/* @__PURE__ */ e(u, { onClick: () => t.chain().focus().toggleHeading({ level: 1 }).run(), active: o.h1, title: "Heading 1", children: /* @__PURE__ */ e(ct, { className: "h-4 w-4" }) }),
|
|
339
|
+
/* @__PURE__ */ e(u, { onClick: () => t.chain().focus().toggleHeading({ level: 2 }).run(), active: o.h2, title: "Heading 2", children: /* @__PURE__ */ e(ut, { className: "h-4 w-4" }) }),
|
|
340
|
+
/* @__PURE__ */ e(u, { onClick: () => t.chain().focus().toggleHeading({ level: 3 }).run(), active: o.h3, title: "Heading 3", children: /* @__PURE__ */ e(gt, { className: "h-4 w-4" }) }),
|
|
341
|
+
/* @__PURE__ */ e(I, {}),
|
|
342
|
+
/* @__PURE__ */ e(u, { onClick: () => t.chain().focus().toggleBulletList().run(), active: o.bulletList, title: "Bullet list", children: /* @__PURE__ */ e(ft, { className: "h-4 w-4" }) }),
|
|
343
|
+
/* @__PURE__ */ e(u, { onClick: () => t.chain().focus().toggleOrderedList().run(), active: o.orderedList, title: "Ordered list", children: /* @__PURE__ */ e(dt, { className: "h-4 w-4" }) }),
|
|
344
|
+
/* @__PURE__ */ e(u, { onClick: () => t.chain().focus().toggleTaskList().run(), active: o.taskList, title: "Task list", children: /* @__PURE__ */ e(mt, { className: "h-4 w-4" }) }),
|
|
345
|
+
/* @__PURE__ */ e(I, {}),
|
|
346
|
+
/* @__PURE__ */ e(u, { onClick: () => t.chain().focus().toggleBlockquote().run(), active: o.blockquote, title: "Quote", children: /* @__PURE__ */ e(ht, { className: "h-4 w-4" }) }),
|
|
347
|
+
/* @__PURE__ */ e(u, { onClick: () => t.chain().focus().toggleCodeBlock().run(), active: o.codeBlock, title: "Code block", children: /* @__PURE__ */ e(pt, { className: "h-4 w-4" }) }),
|
|
348
|
+
/* @__PURE__ */ e(u, { onClick: h, active: o.link, title: "Link", children: /* @__PURE__ */ e(wt, { className: "h-4 w-4" }) }),
|
|
349
|
+
/* @__PURE__ */ e(
|
|
350
|
+
u,
|
|
351
|
+
{
|
|
352
|
+
onClick: p,
|
|
353
|
+
title: "Image (click to upload, Shift+click for URL)",
|
|
354
|
+
children: /* @__PURE__ */ e(kt, { className: "h-4 w-4" })
|
|
355
|
+
}
|
|
356
|
+
),
|
|
357
|
+
/* @__PURE__ */ e(
|
|
358
|
+
Nt,
|
|
359
|
+
{
|
|
360
|
+
ref: g,
|
|
361
|
+
"data-testid": "image-file-input",
|
|
362
|
+
type: "file",
|
|
363
|
+
accept: "image/*",
|
|
364
|
+
className: "hidden",
|
|
365
|
+
onChange: k
|
|
366
|
+
}
|
|
367
|
+
),
|
|
368
|
+
/* @__PURE__ */ e(u, { onClick: () => t.chain().focus().toggleHighlight().run(), active: o.highlight, title: "Highlight", children: /* @__PURE__ */ e(bt, { className: "h-4 w-4" }) }),
|
|
369
|
+
/* @__PURE__ */ e(I, {}),
|
|
370
|
+
/* @__PURE__ */ e(u, { onClick: () => s("left"), active: o.alignLeft, title: "Align left", children: /* @__PURE__ */ e(vt, { className: "h-4 w-4" }) }),
|
|
371
|
+
/* @__PURE__ */ e(u, { onClick: () => s("center"), active: o.alignCenter, title: "Center align", children: /* @__PURE__ */ e(At, { className: "h-4 w-4" }) }),
|
|
372
|
+
/* @__PURE__ */ e(u, { onClick: () => s("right"), active: o.alignRight, title: "Align right", children: /* @__PURE__ */ e(It, { className: "h-4 w-4" }) }),
|
|
373
|
+
/* @__PURE__ */ e(I, {}),
|
|
374
|
+
/* @__PURE__ */ e(u, { onClick: () => t.chain().focus().setHorizontalRule().run(), title: "Horizontal rule", children: /* @__PURE__ */ e(Lt, { className: "h-4 w-4" }) }),
|
|
375
|
+
/* @__PURE__ */ e(I, {}),
|
|
376
|
+
/* @__PURE__ */ e(
|
|
377
|
+
u,
|
|
378
|
+
{
|
|
379
|
+
onClick: a,
|
|
380
|
+
active: n,
|
|
381
|
+
title: n ? "Rich text" : "Raw markdown",
|
|
382
|
+
children: /* @__PURE__ */ e("span", { className: "font-mono text-[10px] font-semibold leading-none tracking-[-0.02em]", children: "MD" })
|
|
383
|
+
}
|
|
384
|
+
)
|
|
385
|
+
] });
|
|
386
|
+
}
|
|
387
|
+
function se({
|
|
388
|
+
content: t,
|
|
389
|
+
onChange: r,
|
|
390
|
+
readOnly: n = !1,
|
|
391
|
+
placeholder: a,
|
|
392
|
+
className: s,
|
|
393
|
+
documentPath: g
|
|
394
|
+
}) {
|
|
395
|
+
const { upload: o } = Tt(), [h, b] = x(!1), p = A(r);
|
|
396
|
+
p.current = r;
|
|
397
|
+
const k = A(!1), i = A(null), d = A(async () => {
|
|
398
|
+
});
|
|
399
|
+
d.current = async (l) => {
|
|
400
|
+
const f = i.current;
|
|
401
|
+
if (f)
|
|
402
|
+
try {
|
|
403
|
+
const { url: v } = await o(l, { sourcePath: g });
|
|
404
|
+
f.chain().focus().setImage({ src: v, alt: l.name }).run();
|
|
405
|
+
} catch {
|
|
406
|
+
try {
|
|
407
|
+
const v = await $t(l);
|
|
408
|
+
f.chain().focus().setImage({ src: v, alt: l.name }).run();
|
|
409
|
+
} catch {
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
const m = t || { type: "doc", content: [{ type: "paragraph" }] }, w = t ? "markdown" : "json", c = P({
|
|
414
|
+
extensions: a ? [
|
|
415
|
+
...M.filter((l) => l.name !== "placeholder"),
|
|
416
|
+
S.configure({ placeholder: a })
|
|
417
|
+
] : M,
|
|
418
|
+
content: m,
|
|
419
|
+
contentType: w,
|
|
420
|
+
editable: !n,
|
|
421
|
+
editorProps: {
|
|
422
|
+
attributes: {
|
|
423
|
+
class: "tiptap-prose max-w-[68ch] px-8 py-6 focus:outline-none min-h-[200px]"
|
|
424
|
+
},
|
|
425
|
+
transformPastedHTML: Ut,
|
|
426
|
+
handlePaste: (l, f) => {
|
|
427
|
+
if (n) return !1;
|
|
428
|
+
const v = Et(f.clipboardData);
|
|
429
|
+
return v ? (f.preventDefault(), d.current(v), !0) : !1;
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
onUpdate: ({ editor: l }) => {
|
|
433
|
+
var f, v;
|
|
434
|
+
k.current || (v = p.current) == null || v.call(p, ((f = l.getMarkdown) == null ? void 0 : f.call(l)) ?? l.getHTML());
|
|
435
|
+
}
|
|
436
|
+
});
|
|
437
|
+
return i.current = c, N(() => {
|
|
438
|
+
!c || c.isDestroyed || c.setEditable(!n);
|
|
439
|
+
}, [c, n]), N(() => {
|
|
440
|
+
var f;
|
|
441
|
+
!c || c.isDestroyed || (((f = c.getMarkdown) == null ? void 0 : f.call(c)) ?? c.getHTML()) === t || (k.current = !0, c.commands.setContent(m, { contentType: w }), k.current = !1);
|
|
442
|
+
}, [c, t]), /* @__PURE__ */ C("div", { className: L("flex h-full flex-col overflow-hidden", s), children: [
|
|
443
|
+
!n && /* @__PURE__ */ e(
|
|
444
|
+
Pt,
|
|
445
|
+
{
|
|
446
|
+
editor: c,
|
|
447
|
+
onInsertImage: (l) => d.current(l),
|
|
448
|
+
rawMode: h,
|
|
449
|
+
onToggleRawMode: () => b((l) => !l)
|
|
450
|
+
}
|
|
451
|
+
),
|
|
452
|
+
/* @__PURE__ */ e("div", { className: "flex-1 overflow-auto", children: h && !n ? /* @__PURE__ */ e(
|
|
453
|
+
"textarea",
|
|
454
|
+
{
|
|
455
|
+
"aria-label": "Raw markdown",
|
|
456
|
+
"data-testid": "markdown-raw-editor",
|
|
457
|
+
className: "h-full min-h-[200px] w-full resize-none bg-background px-8 py-6 font-mono text-[13px] leading-6 text-foreground outline-none placeholder:text-muted-foreground/70",
|
|
458
|
+
value: t,
|
|
459
|
+
placeholder: a,
|
|
460
|
+
spellCheck: !1,
|
|
461
|
+
onChange: (l) => {
|
|
462
|
+
var f;
|
|
463
|
+
return (f = p.current) == null ? void 0 : f.call(p, l.target.value);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
) : /* @__PURE__ */ e(F, { editor: c }) })
|
|
467
|
+
] });
|
|
468
|
+
}
|
|
469
|
+
export {
|
|
470
|
+
se as MarkdownEditor,
|
|
471
|
+
B as isSafeUrl,
|
|
472
|
+
$t as readFileAsDataUrl,
|
|
473
|
+
Ut as sanitizeHtml
|
|
474
|
+
};
|
|
@@ -2,7 +2,7 @@ import { jsxs as d, jsx as o, Fragment as H } from "react/jsx-runtime";
|
|
|
2
2
|
import { useCallback as b, useMemo as A, useEffect as S, useState as V, Suspense as X, useRef as q } from "react";
|
|
3
3
|
import { LoadingState as Z, ResizeHandle as G, IconButton as $, Button as J, Kbd as Q } from "@hachej/boring-ui-kit";
|
|
4
4
|
import { c as g } from "./utils-B6yFEsav.js";
|
|
5
|
-
import { $ as Y, a6 as ee, E as te, am as ne, ak as re, u as oe } from "./CommandPalette-
|
|
5
|
+
import { $ as Y, a6 as ee, E as te, am as ne, ak as re, u as oe } from "./CommandPalette-DzIDQUfk.js";
|
|
6
6
|
import { Search as ae, Plus as ie } from "lucide-react";
|
|
7
7
|
function be(e, t, r = !0) {
|
|
8
8
|
if (!r || typeof window > "u") return t;
|
package/dist/app-front.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as d, jsxs as Te, Fragment as x } from "react/jsx-runtime";
|
|
2
2
|
import { useSyncExternalStore as ze, useMemo as v, useRef as K, useState as X, useEffect as y, useCallback as P } from "react";
|
|
3
3
|
import { ChatPanel as Fe, useSessions as Ge } from "@hachej/boring-agent/front";
|
|
4
|
-
import { aj as ke, q as Ye, ak as Qe, u as Xe, al as Ze } from "./CommandPalette-
|
|
5
|
-
import { T as He, C as qe, r as Ee, w as et, W as $e } from "./WorkspaceLoadingState-
|
|
4
|
+
import { aj as ke, q as Ye, ak as Qe, u as Xe, al as Ze } from "./CommandPalette-DzIDQUfk.js";
|
|
5
|
+
import { T as He, C as qe, r as Ee, w as et, W as $e } from "./WorkspaceLoadingState-Cd8nkNHp.js";
|
|
6
6
|
function tt() {
|
|
7
7
|
const e = `s${Date.now()}`;
|
|
8
8
|
return {
|
package/dist/testing.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as ka } from "react/jsx-runtime";
|
|
2
2
|
import * as Pa from "react";
|
|
3
3
|
import { createElement as ds, useMemo as Tn, useLayoutEffect as fs, isValidElement as ps, cloneElement as ms, useSyncExternalStore as Ji } from "react";
|
|
4
|
-
import { i as vs, q as bs, ai as hs } from "./CommandPalette-
|
|
4
|
+
import { i as vs, q as bs, ai as hs } from "./CommandPalette-DzIDQUfk.js";
|
|
5
5
|
import { d as ys } from "./panel-DnvDNQac.js";
|
|
6
6
|
import * as Rs from "react-dom/test-utils";
|
|
7
7
|
import Ba from "react-dom";
|
package/dist/workspace.css
CHANGED
|
@@ -1807,6 +1807,9 @@
|
|
|
1807
1807
|
.max-h-\[440px\] {
|
|
1808
1808
|
max-height: 440px;
|
|
1809
1809
|
}
|
|
1810
|
+
.max-h-full {
|
|
1811
|
+
max-height: 100%;
|
|
1812
|
+
}
|
|
1810
1813
|
.min-h-0 {
|
|
1811
1814
|
min-height: calc(var(--spacing) * 0);
|
|
1812
1815
|
}
|
|
@@ -1831,6 +1834,9 @@
|
|
|
1831
1834
|
.min-h-\[240px\] {
|
|
1832
1835
|
min-height: 240px;
|
|
1833
1836
|
}
|
|
1837
|
+
.min-h-\[480px\] {
|
|
1838
|
+
min-height: 480px;
|
|
1839
|
+
}
|
|
1834
1840
|
.min-h-screen {
|
|
1835
1841
|
min-height: 100vh;
|
|
1836
1842
|
}
|
|
@@ -2563,6 +2569,9 @@
|
|
|
2563
2569
|
.fill-foreground {
|
|
2564
2570
|
fill: var(--boring-foreground);
|
|
2565
2571
|
}
|
|
2572
|
+
.object-contain {
|
|
2573
|
+
object-fit: contain;
|
|
2574
|
+
}
|
|
2566
2575
|
.p-0 {
|
|
2567
2576
|
padding: calc(var(--spacing) * 0);
|
|
2568
2577
|
}
|
|
@@ -2827,6 +2836,10 @@
|
|
|
2827
2836
|
--tw-tracking: -0.01em;
|
|
2828
2837
|
letter-spacing: -0.01em;
|
|
2829
2838
|
}
|
|
2839
|
+
.tracking-\[-0\.02em\] {
|
|
2840
|
+
--tw-tracking: -0.02em;
|
|
2841
|
+
letter-spacing: -0.02em;
|
|
2842
|
+
}
|
|
2830
2843
|
.tracking-\[0\.05em\] {
|
|
2831
2844
|
--tw-tracking: 0.05em;
|
|
2832
2845
|
letter-spacing: 0.05em;
|
|
@@ -3340,6 +3353,14 @@
|
|
|
3340
3353
|
color: var(--boring-muted-foreground);
|
|
3341
3354
|
}
|
|
3342
3355
|
}
|
|
3356
|
+
.placeholder\:text-muted-foreground\/70 {
|
|
3357
|
+
&::placeholder {
|
|
3358
|
+
color: var(--boring-muted-foreground);
|
|
3359
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
3360
|
+
color: color-mix(in oklab, var(--boring-muted-foreground) 70%, transparent);
|
|
3361
|
+
}
|
|
3362
|
+
}
|
|
3363
|
+
}
|
|
3343
3364
|
.after\:absolute {
|
|
3344
3365
|
&::after {
|
|
3345
3366
|
content: var(--tw-content);
|
|
@@ -3499,6 +3520,13 @@
|
|
|
3499
3520
|
}
|
|
3500
3521
|
}
|
|
3501
3522
|
}
|
|
3523
|
+
.hover\:bg-muted {
|
|
3524
|
+
&:hover {
|
|
3525
|
+
@media (hover: hover) {
|
|
3526
|
+
background-color: var(--boring-muted);
|
|
3527
|
+
}
|
|
3528
|
+
}
|
|
3529
|
+
}
|
|
3502
3530
|
.hover\:bg-muted\/40 {
|
|
3503
3531
|
&:hover {
|
|
3504
3532
|
@media (hover: hover) {
|
package/dist/workspace.d.ts
CHANGED
|
@@ -1018,7 +1018,7 @@ export declare interface LeftTabParams {
|
|
|
1018
1018
|
chromeless?: boolean;
|
|
1019
1019
|
}
|
|
1020
1020
|
|
|
1021
|
-
export declare function MarkdownEditor({ content, onChange, readOnly, placeholder, className, }: MarkdownEditorProps): JSX.Element;
|
|
1021
|
+
export declare function MarkdownEditor({ content, onChange, readOnly, placeholder, className, documentPath, }: MarkdownEditorProps): JSX.Element;
|
|
1022
1022
|
|
|
1023
1023
|
export declare function MarkdownEditorPane({ params, api, className }: MarkdownEditorPaneProps): JSX.Element;
|
|
1024
1024
|
|
|
@@ -1032,6 +1032,8 @@ export declare interface MarkdownEditorProps {
|
|
|
1032
1032
|
readOnly?: boolean;
|
|
1033
1033
|
placeholder?: string;
|
|
1034
1034
|
className?: string;
|
|
1035
|
+
/** Workspace-relative markdown file path, used to make uploaded image links relative. */
|
|
1036
|
+
documentPath?: string;
|
|
1035
1037
|
}
|
|
1036
1038
|
|
|
1037
1039
|
export declare const MAX_PANELS = 50;
|
package/dist/workspace.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
var qe = Object.defineProperty;
|
|
2
2
|
var _e = (e, t, r) => t in e ? qe(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r;
|
|
3
3
|
var ne = (e, t, r) => _e(e, typeof t != "symbol" ? t + "" : t, r);
|
|
4
|
-
import { d as ae, u as Ne, p as Be, P as Ae, a as $e, b as Ke, D as Ve } from "./CommandPalette-
|
|
5
|
-
import { A as xr, C as yr, c as br, e as vr, f as Sr, F as Nr, g as Cr, M as Tr, h as Pr, i as kr, j as Er, k as wr, l as Mr, R as Dr, S as Ir, m as Rr, n as Or, T as Fr, W as Lr, o as zr, q as qr, r as _r, s as Br, t as Ar, v as $r, w as Kr, x as Vr, y as Qr, z as jr, B as Gr, E as Hr, G as Wr, H as Ur, I as Xr, J as Jr, K as Yr, L as Zr, N as ea, O as ta, Q as ra, U as aa, V as na, X as la, Y as oa, Z as sa, _ as ca, $ as ia, a0 as ua, a1 as da, a2 as pa, a3 as fa, a4 as ma, a5 as ga, a6 as ha, a7 as xa, a8 as ya, a9 as ba, aa as va, ab as Sa, ac as Na, ad as Ca, ae as Ta, af as Pa, ag as ka, ah as Ea } from "./CommandPalette-
|
|
4
|
+
import { d as ae, u as Ne, p as Be, P as Ae, a as $e, b as Ke, D as Ve } from "./CommandPalette-DzIDQUfk.js";
|
|
5
|
+
import { A as xr, C as yr, c as br, e as vr, f as Sr, F as Nr, g as Cr, M as Tr, h as Pr, i as kr, j as Er, k as wr, l as Mr, R as Dr, S as Ir, m as Rr, n as Or, T as Fr, W as Lr, o as zr, q as qr, r as _r, s as Br, t as Ar, v as $r, w as Kr, x as Vr, y as Qr, z as jr, B as Gr, E as Hr, G as Wr, H as Ur, I as Xr, J as Jr, K as Yr, L as Zr, N as ea, O as ta, Q as ra, U as aa, V as na, X as la, Y as oa, Z as sa, _ as ca, $ as ia, a0 as ua, a1 as da, a2 as pa, a3 as fa, a4 as ma, a5 as ga, a6 as ha, a7 as xa, a8 as ya, a9 as ba, aa as va, ab as Sa, ac as Na, ad as Ca, ae as Ta, af as Pa, ag as ka, ah as Ea } from "./CommandPalette-DzIDQUfk.js";
|
|
6
6
|
import { jsxs as h, jsx as a, Fragment as Qe } from "react/jsx-runtime";
|
|
7
7
|
import { useSyncExternalStore as je, useState as V, useEffect as U, useRef as w, useCallback as S, useReducer as Ge, useMemo as Z, Suspense as He, Component as We } from "react";
|
|
8
8
|
import { FilterIcon as Ue, XIcon as Xe, ChevronDownIcon as Ce, ChevronRightIcon as Te, Database as Je, BarChart3 as pe, MenuIcon as Ye, PanelLeftOpenIcon as Ze, PanelLeftCloseIcon as et, PinIcon as tt } from "lucide-react";
|
|
@@ -10,10 +10,10 @@ import { EmptyState as Pe, Toolbar as rt, Input as ke, Popover as at, PopoverTri
|
|
|
10
10
|
import { Toaster as Ma, dismissToast as Da, toast as Ia } from "@hachej/boring-ui-kit";
|
|
11
11
|
import { c as H } from "./utils-B6yFEsav.js";
|
|
12
12
|
import { d as we } from "./panel-DnvDNQac.js";
|
|
13
|
-
import { C as Oa, T as Fa, W as La, b as za } from "./WorkspaceLoadingState-
|
|
13
|
+
import { C as Oa, T as Fa, W as La, b as za } from "./WorkspaceLoadingState-Cd8nkNHp.js";
|
|
14
14
|
import { C as _a, c as Ba } from "./CodeEditor-DQqOn4xz.js";
|
|
15
|
-
import { FileTree as $a } from "./FileTree-
|
|
16
|
-
import { MarkdownEditor as Va } from "./MarkdownEditor-
|
|
15
|
+
import { FileTree as $a } from "./FileTree-CspphShP.js";
|
|
16
|
+
import { MarkdownEditor as Va } from "./MarkdownEditor-wDDxxED5.js";
|
|
17
17
|
function re(e, t) {
|
|
18
18
|
const { pluginId: r, ...n } = e;
|
|
19
19
|
return t ? { ...n, pluginId: t } : n;
|
package/docs/PLUGIN_STRUCTURE.md
CHANGED
|
@@ -134,8 +134,8 @@ slash commands.
|
|
|
134
134
|
|
|
135
135
|
- `packages/workspace/src/plugins/filesystemPlugin`
|
|
136
136
|
- `packages/workspace/src/plugins/dataCatalogPlugin`
|
|
137
|
-
- `apps/boring-macro-v2/src/plugins/macro`
|
|
138
137
|
- `apps/workspace-playground/src/plugins/playgroundDataCatalog`
|
|
138
|
+
- Macro plugin example: `hachej/boring-macro` (`src/plugins/macro`)
|
|
139
139
|
|
|
140
140
|
## Invariants
|
|
141
141
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hachej/boring-workspace",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Workspace UI, plugin, and bridge package for composing chat, files, catalogs, editors, and app-specific panes.",
|
|
@@ -108,6 +108,7 @@
|
|
|
108
108
|
"@tiptap/extension-task-list": "^3.22.4",
|
|
109
109
|
"@tiptap/extension-text-align": "^3.22.4",
|
|
110
110
|
"@tiptap/extension-underline": "^3.22.4",
|
|
111
|
+
"@tiptap/markdown": "^3.22.4",
|
|
111
112
|
"@tiptap/pm": "^3.22.4",
|
|
112
113
|
"@tiptap/react": "^3.22.4",
|
|
113
114
|
"@tiptap/starter-kit": "^3.22.4",
|
|
@@ -122,11 +123,10 @@
|
|
|
122
123
|
"radix-ui": "^1.4.3",
|
|
123
124
|
"react-arborist": "^3.4.0",
|
|
124
125
|
"tailwind-merge": "^2.0.0",
|
|
125
|
-
"tiptap-markdown": "^0.9.0",
|
|
126
126
|
"zod": "^3.23.0",
|
|
127
127
|
"zustand": "^5.0.0",
|
|
128
|
-
"@hachej/boring-
|
|
129
|
-
"@hachej/boring-
|
|
128
|
+
"@hachej/boring-ui-kit": "0.1.7",
|
|
129
|
+
"@hachej/boring-agent": "0.1.7"
|
|
130
130
|
},
|
|
131
131
|
"devDependencies": {
|
|
132
132
|
"@tailwindcss/postcss": "^4.0.0",
|