@hachej/boring-workspace 0.1.63 → 0.1.65

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.
Files changed (36) hide show
  1. package/dist/FileTree-B_fRS4Om.js +230 -0
  2. package/dist/MarkdownEditor-C55gVDyW.js +743 -0
  3. package/dist/WorkspaceLoadingState-D3i4X-eH.js +847 -0
  4. package/dist/WorkspaceProvider-Ddx7GByq.js +8770 -0
  5. package/dist/app-front.d.ts +106 -4
  6. package/dist/app-front.js +3110 -2427
  7. package/dist/app-server.d.ts +2 -2
  8. package/dist/app-server.js +6 -4
  9. package/dist/boring-workspace.css +2 -1
  10. package/dist/charts.d.ts +6 -1
  11. package/dist/charts.js +131 -138
  12. package/dist/plugin.d.ts +64 -1
  13. package/dist/plugin.js +32 -0
  14. package/dist/rolldown-runtime-Dqa2HsxW.js +20 -0
  15. package/dist/{runtimeEnv-HolIkcoB.d.ts → runtimeEnv-CU-c4kaV.d.ts} +7 -0
  16. package/dist/server.d.ts +2 -2
  17. package/dist/server.js +4 -3
  18. package/dist/testing-e2e.d.ts +5 -0
  19. package/dist/testing-e2e.js +33 -42
  20. package/dist/testing.d.ts +6 -1
  21. package/dist/testing.js +9474 -10814
  22. package/dist/utils-BRcxFdrz.js +8 -0
  23. package/dist/workspace.css +2790 -301
  24. package/dist/workspace.d.ts +164 -21
  25. package/dist/workspace.js +568 -734
  26. package/docs/plans/archive/CODE_OWNERSHIP_CLEANUP_PLAN.md +1 -1
  27. package/docs/plans/archive/DECLARATIVE_LAYOUT_MIGRATION.md +4 -4
  28. package/docs/plans/archive/GENERIC_EXPLORER_PLUGIN_PLAN.md +10 -10
  29. package/docs/plans/archive/PLUGIN_MODEL.md +37 -37
  30. package/docs/plans/archive/WORKSPACE_V2_PLAN.md +2 -2
  31. package/package.json +50 -50
  32. package/dist/FileTree-CUvn5K86.js +0 -315
  33. package/dist/MarkdownEditor-5f4lhBqc.js +0 -598
  34. package/dist/WorkspaceLoadingState-y087Q6ek.js +0 -866
  35. package/dist/WorkspaceProvider-U4izhS84.js +0 -8660
  36. package/dist/utils-B6yFEsav.js +0 -8
@@ -0,0 +1,230 @@
1
+ import { n as e } from "./rolldown-runtime-Dqa2HsxW.js";
2
+ import { kt as t } from "./WorkspaceProvider-Ddx7GByq.js";
3
+ import { t as n } from "./utils-BRcxFdrz.js";
4
+ import { createContext as r, useCallback as i, useContext as a, useEffect as o, useMemo as s, useRef as c } from "react";
5
+ import { jsx as l, jsxs as u } from "react/jsx-runtime";
6
+ import { ChevronRightIcon as d, FolderIcon as f, FolderOpenIcon as p, Loader2Icon as m } from "lucide-react";
7
+ import { EmptyState as h, Input as g } from "@hachej/boring-ui-kit";
8
+ import { Tree as _ } from "react-arborist";
9
+ import { createDragDropManager as v } from "dnd-core";
10
+ import { HTML5Backend as y } from "react-dnd-html5-backend";
11
+ //#region src/plugins/filesystemPlugin/front/file-tree/dndManager.ts
12
+ var b = Symbol.for("@hachej/boring-workspace/file-tree-dnd-manager");
13
+ function x() {
14
+ let e = globalThis;
15
+ return e[b] ??= v(y, typeof window > "u" ? void 0 : window), e[b];
16
+ }
17
+ //#endregion
18
+ //#region src/plugins/filesystemPlugin/front/file-tree/FileTree.tsx
19
+ var S = /* @__PURE__ */ e({
20
+ FileTree: () => k,
21
+ sanitizeFileTree: () => E
22
+ }), C = /* @__PURE__ */ new Set(), w = r({
23
+ onContextMenu: void 0,
24
+ editing: null,
25
+ pendingPaths: C,
26
+ onSubmitEdit: void 0,
27
+ onCancelEdit: void 0
28
+ });
29
+ function T({ initialValue: e, onSubmit: t, onCancel: n, isDraft: r }) {
30
+ let i = c(null), a = c(!1);
31
+ o(() => {
32
+ let t = i.current;
33
+ if (t) if (t.focus(), !r && e.includes(".")) {
34
+ let n = e.lastIndexOf(".");
35
+ t.setSelectionRange(0, n);
36
+ } else t.select();
37
+ }, [e, r]);
38
+ let s = () => {
39
+ if (a.current) return;
40
+ a.current = !0;
41
+ let r = i.current?.value.trim() ?? "";
42
+ !r || r === e ? n() : t(r);
43
+ };
44
+ return /* @__PURE__ */ l(g, {
45
+ ref: i,
46
+ type: "text",
47
+ defaultValue: e,
48
+ "data-testid": "file-tree-edit-input",
49
+ "aria-label": r ? "Name" : "Rename",
50
+ onPointerDown: (e) => e.stopPropagation(),
51
+ onClick: (e) => e.stopPropagation(),
52
+ onKeyDown: (e) => {
53
+ e.stopPropagation(), e.key === "Enter" ? (e.preventDefault(), s()) : e.key === "Escape" && (e.preventDefault(), a.current = !0, n());
54
+ },
55
+ onBlur: s,
56
+ className: "h-5 min-w-0 flex-1 rounded-sm border-[color:var(--accent)]/60 px-1 text-[13px] leading-[1.2] focus-visible:ring-[color:var(--accent)]"
57
+ });
58
+ }
59
+ function E(e) {
60
+ let t = /* @__PURE__ */ new Set(), n = 0, r = (e) => {
61
+ let i = [];
62
+ for (let a of e) {
63
+ if (typeof a?.path != "string" || a.path.length === 0 || t.has(a.path)) {
64
+ n++;
65
+ continue;
66
+ }
67
+ t.add(a.path), i.push(a.children && a.children.length > 0 ? {
68
+ ...a,
69
+ children: r(a.children)
70
+ } : a);
71
+ }
72
+ return i;
73
+ };
74
+ return {
75
+ nodes: r(e),
76
+ dropped: n
77
+ };
78
+ }
79
+ function D(e, t) {
80
+ if (!t?.trim()) return e.length;
81
+ let n = t.trim().toLowerCase(), r = (e) => {
82
+ let t = 0;
83
+ for (let i of e) {
84
+ let e = i.name.toLowerCase().includes(n), a = i.children?.length ? r(i.children) : 0;
85
+ (e || a > 0) && (t += 1);
86
+ }
87
+ return t;
88
+ };
89
+ return r(e);
90
+ }
91
+ function O({ node: e, style: r, dragHandle: i }) {
92
+ let { onContextMenu: o, editing: s, pendingPaths: c, onSubmitEdit: h, onCancelEdit: g } = a(w), _ = e.data, v = _.kind === "dir", y = s?.path === _.path, b = c.has(_.path), x = v ? e.isOpen ? p : f : t(_.name || "untitled");
93
+ return /* @__PURE__ */ u("div", {
94
+ ref: i,
95
+ style: r,
96
+ className: n("group relative mx-1 flex items-center gap-1.5 rounded-md px-2 py-0.5 text-[13px] leading-[1.4] cursor-pointer select-none text-foreground", "transition-colors duration-150 ease-[cubic-bezier(0.22,1,0.36,1)]", !y && "hover:bg-foreground/[0.04]", e.isSelected && !y && "bg-[oklch(from_var(--accent)_l_c_h/0.10)] text-foreground font-medium", e.willReceiveDrop && "bg-foreground/5 outline outline-1 outline-border"),
97
+ onClick: (t) => {
98
+ y || (t.stopPropagation(), v ? e.toggle() : (e.select(), e.activate()));
99
+ },
100
+ onContextMenu: (e) => {
101
+ y || _.isDraft || (e.preventDefault(), e.stopPropagation(), o?.(e, _));
102
+ },
103
+ children: [
104
+ v ? /* @__PURE__ */ l(d, {
105
+ className: n("h-3 w-3 shrink-0 text-muted-foreground/70 transition-transform duration-150 ease-[cubic-bezier(0.22,1,0.36,1)]", e.isOpen && "rotate-90"),
106
+ strokeWidth: 2
107
+ }) : /* @__PURE__ */ l("span", { className: "w-3 shrink-0" }),
108
+ /* @__PURE__ */ l(x, {
109
+ className: n("h-4 w-4 shrink-0", e.isSelected ? "text-[color:var(--accent)]" : "text-muted-foreground/80"),
110
+ strokeWidth: 1.5
111
+ }),
112
+ y ? /* @__PURE__ */ l(T, {
113
+ initialValue: s?.initialValue ?? _.name ?? "",
114
+ isDraft: !!s?.isDraft,
115
+ onSubmit: (e) => h?.(_.path, e),
116
+ onCancel: () => g?.()
117
+ }) : /* @__PURE__ */ l("span", {
118
+ className: n("truncate", b && "text-muted-foreground italic"),
119
+ children: _.name
120
+ }),
121
+ b && !y && /* @__PURE__ */ l(m, {
122
+ "data-testid": "file-tree-pending-spinner",
123
+ "aria-label": "Pending",
124
+ className: "ml-auto h-3 w-3 shrink-0 animate-spin text-muted-foreground/70",
125
+ strokeWidth: 2
126
+ })
127
+ ]
128
+ });
129
+ }
130
+ function k({ files: e, selectedPath: t, searchQuery: r, height: a = 400, editing: u, revealPath: d, pendingPaths: f, onSelect: p, onExpand: m, onCollapse: g, onContextMenu: v, onSubmitEdit: y, onCancelEdit: b, onRevealHandled: S, onDragDrop: T, className: k }) {
131
+ let A = c(null), { nodes: j, dropped: M } = s(() => E(e), [e]), N = c(0);
132
+ o(() => {
133
+ M > 0 && M !== N.current && console.warn(`[filesystem] dropped ${M} file-tree node(s) with a missing or duplicate path`), N.current = M;
134
+ }, [M]), o(() => {
135
+ if (!u?.isDraft) return;
136
+ let e = requestAnimationFrame(() => {
137
+ A.current?.scrollTo(u.path);
138
+ });
139
+ return () => cancelAnimationFrame(e);
140
+ }, [u?.isDraft, u?.path]), o(() => {
141
+ if (!d) return;
142
+ let e = 0, t = requestAnimationFrame(() => {
143
+ let t = A.current;
144
+ if (!t) return;
145
+ t.openParents(d);
146
+ let n = t.get(d);
147
+ n && (n.isInternal && n.open(), e = requestAnimationFrame(() => {
148
+ A.current?.scrollTo(d), S?.(d);
149
+ }));
150
+ });
151
+ return () => {
152
+ cancelAnimationFrame(t), cancelAnimationFrame(e);
153
+ };
154
+ }, [
155
+ e,
156
+ S,
157
+ d
158
+ ]);
159
+ let P = s(() => t || void 0, [t]), F = i((e) => {
160
+ e.data.kind === "file" && p?.(e.data.path);
161
+ }, [p]), I = i((e) => {
162
+ let t = A.current?.get(e);
163
+ t && (t.isOpen ? m?.(t.data.path) : g?.(t.data.path));
164
+ }, [m, g]), L = i((e) => {
165
+ if (!T) return;
166
+ let t = !e.parentNode || e.parentNode.isRoot, n = t ? "." : e.parentNode.data.path;
167
+ if (!(!t && e.parentNode.data.kind !== "dir")) for (let t of e.dragNodes) {
168
+ let e = t.data.path;
169
+ if (n === e || n !== "." && n.startsWith(e + "/")) return;
170
+ T(e, n);
171
+ }
172
+ }, [T]), R = i((e) => {
173
+ if (!e.parentNode || e.parentNode.isRoot) return !1;
174
+ if (e.parentNode.data.kind !== "dir") return !0;
175
+ for (let t of e.dragNodes) if (e.parentNode.data.path === t.data.path || e.parentNode.data.path.startsWith(t.data.path + "/")) return !0;
176
+ return !1;
177
+ }, []), z = i((e, t) => e.data.name.toLowerCase().includes(t.toLowerCase()), []), B = s(() => ({
178
+ onContextMenu: v,
179
+ editing: u ?? null,
180
+ pendingPaths: f ?? C,
181
+ onSubmitEdit: y,
182
+ onCancelEdit: b
183
+ }), [
184
+ v,
185
+ u,
186
+ f,
187
+ y,
188
+ b
189
+ ]), V = s(() => D(j, r), [j, r]);
190
+ return j.length === 0 ? /* @__PURE__ */ l("div", {
191
+ className: n("flex h-full items-center justify-center text-sm text-muted-foreground", k),
192
+ children: "No files"
193
+ }) : V === 0 ? /* @__PURE__ */ l("div", {
194
+ className: n("flex h-full items-center justify-center p-6", k),
195
+ children: /* @__PURE__ */ l(h, {
196
+ className: "min-h-0 border-0",
197
+ title: "No matching files",
198
+ description: r?.trim() ? `No files match “${r.trim()}”.` : "No files match the current filter."
199
+ })
200
+ }) : /* @__PURE__ */ l(w.Provider, {
201
+ value: B,
202
+ children: /* @__PURE__ */ l("div", {
203
+ "data-boring-workspace-part": "file-tree",
204
+ className: n("file-tree", k),
205
+ children: /* @__PURE__ */ l(_, {
206
+ ref: A,
207
+ data: j,
208
+ idAccessor: "path",
209
+ childrenAccessor: "children",
210
+ openByDefault: !1,
211
+ width: "100%",
212
+ height: a,
213
+ rowHeight: 26,
214
+ indent: 14,
215
+ selection: P,
216
+ searchTerm: r ?? "",
217
+ searchMatch: z,
218
+ onActivate: F,
219
+ onToggle: I,
220
+ onMove: L,
221
+ disableDrop: R,
222
+ disableEdit: !0,
223
+ dndManager: x(),
224
+ children: O
225
+ })
226
+ })
227
+ });
228
+ }
229
+ //#endregion
230
+ export { S as n, k as t };