@june-ai/june-ui 0.2.5 → 0.2.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/CHANGELOG.md +7 -0
- package/dist/block-automount.js +2 -0
- package/dist/{chunk-CZE533PM.js → chunk-VFZI3SEL.js} +186 -9
- package/dist/{document-engine-IAY2T6B3.js → document-engine-RKD5SLXR.js} +1 -1
- package/dist/index.cjs +1134 -679
- package/dist/index.d.cts +44 -1
- package/dist/index.d.ts +44 -1
- package/dist/index.js +889 -615
- package/dist/june.css +43 -19
- package/package.json +6 -3
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import "./block-automount.js";
|
|
1
2
|
import {
|
|
2
3
|
JuneError,
|
|
3
4
|
createDocumentExtensions,
|
|
@@ -6,24 +7,75 @@ import {
|
|
|
6
7
|
docToHtml,
|
|
7
8
|
docToMarkdown,
|
|
8
9
|
emptyDoc,
|
|
10
|
+
getPageCount,
|
|
9
11
|
getSearchState,
|
|
10
12
|
gotoMatch,
|
|
11
13
|
isJuneError,
|
|
12
14
|
parseDocumentContent,
|
|
15
|
+
remeasurePagination,
|
|
13
16
|
replaceAll,
|
|
14
17
|
replaceCurrent,
|
|
15
18
|
sanitizeHref,
|
|
19
|
+
setPaginationConfig,
|
|
16
20
|
setSearch,
|
|
17
21
|
slugify,
|
|
18
22
|
toJuneError,
|
|
19
23
|
wordCountOf
|
|
20
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-VFZI3SEL.js";
|
|
25
|
+
|
|
26
|
+
// src/openui/disable-devtools.tsx
|
|
27
|
+
import { OpenUIDevtools } from "@openuidev/devtools";
|
|
28
|
+
import { jsx } from "react/jsx-runtime";
|
|
29
|
+
var AUTO_MOUNT_FLAG = /* @__PURE__ */ Symbol.for("openui.devtools.autoMount");
|
|
30
|
+
var BLOCKED_BY_JUNE = /* @__PURE__ */ Symbol.for("openui.devtools.blockedByJune");
|
|
31
|
+
var flags = globalThis;
|
|
32
|
+
var scheduledByOpenUI = flags[AUTO_MOUNT_FLAG] === true && flags[BLOCKED_BY_JUNE] !== true;
|
|
33
|
+
flags[AUTO_MOUNT_FLAG] = true;
|
|
34
|
+
flags[BLOCKED_BY_JUNE] = true;
|
|
35
|
+
var DEVTOOLS_BUNDLE = "https://cdn.jsdelivr.net/npm/@openuidev/devtools@0/dist/devtools.browser.js";
|
|
36
|
+
var ALIAS_CACHE_MS = 5 * 60 * 1e3;
|
|
37
|
+
function claimDisabledDevtools() {
|
|
38
|
+
if (typeof document === "undefined") return () => {
|
|
39
|
+
};
|
|
40
|
+
const url = `${DEVTOOLS_BUNDLE}?t=${Math.floor(Date.now() / ALIAS_CACHE_MS)}`;
|
|
41
|
+
let cancelled = false;
|
|
42
|
+
let unmount = () => {
|
|
43
|
+
cancelled = true;
|
|
44
|
+
};
|
|
45
|
+
void Promise.all([
|
|
46
|
+
import(
|
|
47
|
+
/* @vite-ignore */
|
|
48
|
+
url
|
|
49
|
+
),
|
|
50
|
+
import("react"),
|
|
51
|
+
import("react-dom"),
|
|
52
|
+
import("react-dom/client")
|
|
53
|
+
]).then(([devtools, react, reactDom, reactDomClient]) => {
|
|
54
|
+
if (cancelled) return;
|
|
55
|
+
unmount = devtools.mountOpenUIDevtools({
|
|
56
|
+
React: react,
|
|
57
|
+
ReactDOM: reactDom,
|
|
58
|
+
ReactDOMClient: reactDomClient,
|
|
59
|
+
loadReactLang: () => import("@openuidev/react-lang"),
|
|
60
|
+
props: { enabled: false }
|
|
61
|
+
});
|
|
62
|
+
}).catch(() => {
|
|
63
|
+
});
|
|
64
|
+
return () => unmount();
|
|
65
|
+
}
|
|
66
|
+
if (scheduledByOpenUI && process.env.NODE_ENV === "development" && process.env.VITEST !== "true" && typeof document !== "undefined") {
|
|
67
|
+
claimDisabledDevtools();
|
|
68
|
+
}
|
|
69
|
+
function OpenUIDevtoolsGate() {
|
|
70
|
+
return /* @__PURE__ */ jsx(OpenUIDevtools, { enabled: false });
|
|
71
|
+
}
|
|
21
72
|
|
|
22
73
|
// src/renderer/renderer.tsx
|
|
23
74
|
import { Renderer } from "@openuidev/react-lang";
|
|
24
75
|
import {
|
|
25
76
|
Fragment,
|
|
26
77
|
useCallback,
|
|
78
|
+
useEffect,
|
|
27
79
|
useMemo as useMemo2,
|
|
28
80
|
useRef
|
|
29
81
|
} from "react";
|
|
@@ -101,6 +153,316 @@ function useDocumentValue(store, id, selector) {
|
|
|
101
153
|
return useSyncExternalStore(store.subscribe, read, read);
|
|
102
154
|
}
|
|
103
155
|
|
|
156
|
+
// src/components/document-editor/document-merge.ts
|
|
157
|
+
var MAX_CELLS = 4e6;
|
|
158
|
+
function matchIndices(a, b) {
|
|
159
|
+
const n = a.length;
|
|
160
|
+
const m = b.length;
|
|
161
|
+
if (n * m > MAX_CELLS) return null;
|
|
162
|
+
const dp = Array.from({ length: n + 1 }, () => new Uint32Array(m + 1));
|
|
163
|
+
for (let i2 = n - 1; i2 >= 0; i2--) {
|
|
164
|
+
for (let j2 = m - 1; j2 >= 0; j2--) {
|
|
165
|
+
dp[i2][j2] = a[i2] === b[j2] ? dp[i2 + 1][j2 + 1] + 1 : Math.max(dp[i2 + 1][j2], dp[i2][j2 + 1]);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const matches = /* @__PURE__ */ new Map();
|
|
169
|
+
let i = 0;
|
|
170
|
+
let j = 0;
|
|
171
|
+
while (i < n && j < m) {
|
|
172
|
+
if (a[i] === b[j]) {
|
|
173
|
+
matches.set(i, j);
|
|
174
|
+
i++;
|
|
175
|
+
j++;
|
|
176
|
+
} else if (dp[i + 1][j] >= dp[i][j + 1]) i++;
|
|
177
|
+
else j++;
|
|
178
|
+
}
|
|
179
|
+
return matches;
|
|
180
|
+
}
|
|
181
|
+
var same = (x, y) => x.length === y.length && x.every((v, i) => v === y[i]);
|
|
182
|
+
function mergeBlocks(base, local, incoming) {
|
|
183
|
+
if (same(local, base)) return { blocks: incoming, conflicts: 0 };
|
|
184
|
+
if (same(incoming, base) || same(local, incoming)) return { blocks: local, conflicts: 0 };
|
|
185
|
+
const ml = matchIndices(base, local);
|
|
186
|
+
const mn = matchIndices(base, incoming);
|
|
187
|
+
if (!ml || !mn) return { blocks: null, conflicts: 1 };
|
|
188
|
+
const anchors = [...ml.keys()].filter((i) => mn.has(i)).sort((x, y) => x - y);
|
|
189
|
+
const out = [];
|
|
190
|
+
let conflicts = 0;
|
|
191
|
+
let pb = -1;
|
|
192
|
+
let pl = -1;
|
|
193
|
+
let pn = -1;
|
|
194
|
+
const region = (bEnd, lEnd, nEnd) => {
|
|
195
|
+
const B = base.slice(pb + 1, bEnd);
|
|
196
|
+
const L = local.slice(pl + 1, lEnd);
|
|
197
|
+
const N = incoming.slice(pn + 1, nEnd);
|
|
198
|
+
if (B.length === L.length && L.length === N.length) {
|
|
199
|
+
for (let k = 0; k < B.length; k++) {
|
|
200
|
+
if (L[k] === B[k]) out.push(N[k]);
|
|
201
|
+
else if (N[k] === B[k] || N[k] === L[k]) out.push(L[k]);
|
|
202
|
+
else {
|
|
203
|
+
conflicts++;
|
|
204
|
+
out.push(L[k]);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (same(L, B)) out.push(...N);
|
|
210
|
+
else if (same(N, B) || same(L, N)) out.push(...L);
|
|
211
|
+
else {
|
|
212
|
+
conflicts++;
|
|
213
|
+
out.push(...L);
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
for (const a of anchors) {
|
|
217
|
+
const la = ml.get(a);
|
|
218
|
+
const na = mn.get(a);
|
|
219
|
+
region(a, la, na);
|
|
220
|
+
out.push(local[la]);
|
|
221
|
+
pb = a;
|
|
222
|
+
pl = la;
|
|
223
|
+
pn = na;
|
|
224
|
+
}
|
|
225
|
+
region(base.length, local.length, incoming.length);
|
|
226
|
+
return { blocks: out, conflicts };
|
|
227
|
+
}
|
|
228
|
+
function mergeDocuments(base, local, incoming) {
|
|
229
|
+
const toBlocks = (d) => (d.content ?? []).map((node) => JSON.stringify(node));
|
|
230
|
+
const { blocks: blocks2, conflicts } = mergeBlocks(toBlocks(base), toBlocks(local), toBlocks(incoming));
|
|
231
|
+
if (!blocks2) return { doc: local, conflicts: Math.max(1, conflicts) };
|
|
232
|
+
if (blocks2.length === 0) return { doc: emptyDoc(), conflicts };
|
|
233
|
+
return { doc: { type: "doc", content: blocks2.map((b) => JSON.parse(b)) }, conflicts };
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// src/components/document-editor/document-store.ts
|
|
237
|
+
var incomingKey = (doc) => JSON.stringify([doc.title, docKey(doc.json)]);
|
|
238
|
+
function createDocumentStore() {
|
|
239
|
+
const records = /* @__PURE__ */ new Map();
|
|
240
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
241
|
+
const emit = () => listeners.forEach((listener) => listener());
|
|
242
|
+
const put = (record) => {
|
|
243
|
+
records.set(record.id, record);
|
|
244
|
+
emit();
|
|
245
|
+
};
|
|
246
|
+
const fresh2 = (doc) => ({
|
|
247
|
+
id: doc.id,
|
|
248
|
+
title: doc.title,
|
|
249
|
+
documentType: doc.documentType,
|
|
250
|
+
status: doc.status,
|
|
251
|
+
json: doc.json,
|
|
252
|
+
baseJson: doc.json,
|
|
253
|
+
baseTitle: doc.title,
|
|
254
|
+
lastIncomingKey: incomingKey(doc),
|
|
255
|
+
revision: 0,
|
|
256
|
+
origin: "external",
|
|
257
|
+
pending: null,
|
|
258
|
+
updatedAt: Date.now()
|
|
259
|
+
});
|
|
260
|
+
return {
|
|
261
|
+
get: (id) => records.get(id),
|
|
262
|
+
list: () => [...records.values()],
|
|
263
|
+
subscribe: (listener) => {
|
|
264
|
+
listeners.add(listener);
|
|
265
|
+
return () => {
|
|
266
|
+
listeners.delete(listener);
|
|
267
|
+
};
|
|
268
|
+
},
|
|
269
|
+
receive(incoming) {
|
|
270
|
+
const current = records.get(incoming.id);
|
|
271
|
+
if (!current) {
|
|
272
|
+
put(fresh2(incoming));
|
|
273
|
+
return "created";
|
|
274
|
+
}
|
|
275
|
+
const key = incomingKey(incoming);
|
|
276
|
+
if (current.lastIncomingKey === key) return "unchanged";
|
|
277
|
+
const userEditedBody = docKey(current.json) !== docKey(current.baseJson);
|
|
278
|
+
const userEditedTitle = current.title !== current.baseTitle;
|
|
279
|
+
const title = userEditedTitle ? current.title : incoming.title;
|
|
280
|
+
const meta = {
|
|
281
|
+
documentType: incoming.documentType ?? current.documentType,
|
|
282
|
+
status: incoming.status ?? current.status
|
|
283
|
+
};
|
|
284
|
+
if (!userEditedBody) {
|
|
285
|
+
put({
|
|
286
|
+
...current,
|
|
287
|
+
...meta,
|
|
288
|
+
title,
|
|
289
|
+
baseTitle: incoming.title,
|
|
290
|
+
json: incoming.json,
|
|
291
|
+
baseJson: incoming.json,
|
|
292
|
+
lastIncomingKey: key,
|
|
293
|
+
revision: current.revision + 1,
|
|
294
|
+
origin: "external",
|
|
295
|
+
pending: null,
|
|
296
|
+
updatedAt: Date.now()
|
|
297
|
+
});
|
|
298
|
+
return "applied";
|
|
299
|
+
}
|
|
300
|
+
const { doc, conflicts } = mergeDocuments(current.baseJson, current.json, incoming.json);
|
|
301
|
+
if (conflicts === 0) {
|
|
302
|
+
put({
|
|
303
|
+
...current,
|
|
304
|
+
...meta,
|
|
305
|
+
title,
|
|
306
|
+
baseTitle: incoming.title,
|
|
307
|
+
json: doc,
|
|
308
|
+
baseJson: incoming.json,
|
|
309
|
+
lastIncomingKey: key,
|
|
310
|
+
revision: current.revision + 1,
|
|
311
|
+
origin: "external",
|
|
312
|
+
pending: null,
|
|
313
|
+
updatedAt: Date.now()
|
|
314
|
+
});
|
|
315
|
+
return "merged";
|
|
316
|
+
}
|
|
317
|
+
put({
|
|
318
|
+
...current,
|
|
319
|
+
...meta,
|
|
320
|
+
lastIncomingKey: key,
|
|
321
|
+
pending: { json: incoming.json, title: incoming.title, merged: doc, conflicts }
|
|
322
|
+
});
|
|
323
|
+
return "conflict";
|
|
324
|
+
},
|
|
325
|
+
hydrate(doc) {
|
|
326
|
+
put(fresh2(doc));
|
|
327
|
+
},
|
|
328
|
+
edit(id, json, origin) {
|
|
329
|
+
const current = records.get(id);
|
|
330
|
+
if (!current || docKey(current.json) === docKey(json)) return;
|
|
331
|
+
put({ ...current, json, origin, revision: current.revision + 1, updatedAt: Date.now() });
|
|
332
|
+
},
|
|
333
|
+
setTitle(id, title) {
|
|
334
|
+
const current = records.get(id);
|
|
335
|
+
if (!current || current.title === title) return;
|
|
336
|
+
put({ ...current, title, updatedAt: Date.now() });
|
|
337
|
+
},
|
|
338
|
+
resolve(id, choice) {
|
|
339
|
+
const current = records.get(id);
|
|
340
|
+
const pending = current?.pending;
|
|
341
|
+
if (!current || !pending) return;
|
|
342
|
+
if (choice === "keep") {
|
|
343
|
+
put({ ...current, baseJson: pending.json, baseTitle: pending.title, pending: null });
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
const json = choice === "merge" ? pending.merged : pending.json;
|
|
347
|
+
const title = choice === "merge" ? current.title : pending.title;
|
|
348
|
+
put({
|
|
349
|
+
...current,
|
|
350
|
+
title,
|
|
351
|
+
json,
|
|
352
|
+
baseJson: pending.json,
|
|
353
|
+
baseTitle: pending.title,
|
|
354
|
+
revision: current.revision + 1,
|
|
355
|
+
origin: "external",
|
|
356
|
+
pending: null,
|
|
357
|
+
updatedAt: Date.now()
|
|
358
|
+
});
|
|
359
|
+
},
|
|
360
|
+
remove(id) {
|
|
361
|
+
if (records.delete(id)) emit();
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
var echoes = /* @__PURE__ */ new WeakMap();
|
|
366
|
+
var ECHO_MEMORY = 8;
|
|
367
|
+
function rememberDocumentEcho(store, id, content) {
|
|
368
|
+
let byId = echoes.get(store);
|
|
369
|
+
if (!byId) echoes.set(store, byId = /* @__PURE__ */ new Map());
|
|
370
|
+
const list2 = byId.get(id) ?? [];
|
|
371
|
+
list2.push(content);
|
|
372
|
+
if (list2.length > ECHO_MEMORY) list2.shift();
|
|
373
|
+
byId.set(id, list2);
|
|
374
|
+
}
|
|
375
|
+
function isDocumentEcho(store, id, content) {
|
|
376
|
+
return !!content && !!echoes.get(store)?.get(id)?.includes(content);
|
|
377
|
+
}
|
|
378
|
+
var defaultStore = null;
|
|
379
|
+
function getDefaultDocumentStore() {
|
|
380
|
+
if (!defaultStore) defaultStore = createDocumentStore();
|
|
381
|
+
return defaultStore;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// src/utils/update-document-program.ts
|
|
385
|
+
function readString(src, i) {
|
|
386
|
+
if (src[i] !== '"') return null;
|
|
387
|
+
let j = i + 1;
|
|
388
|
+
let value = "";
|
|
389
|
+
while (j < src.length) {
|
|
390
|
+
const ch = src[j];
|
|
391
|
+
if (ch === '"') return { start: i, end: j + 1, value };
|
|
392
|
+
if (ch === "\\") {
|
|
393
|
+
const next = src[j + 1];
|
|
394
|
+
if (next === void 0) return null;
|
|
395
|
+
if (next === "u" && /^[0-9a-fA-F]{4}$/.test(src.slice(j + 2, j + 6))) {
|
|
396
|
+
value += String.fromCharCode(parseInt(src.slice(j + 2, j + 6), 16));
|
|
397
|
+
j += 6;
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
value += next === "n" ? "\n" : next === "t" ? " " : next === "r" ? "\r" : next === "b" ? "\b" : next === "f" ? "\f" : next;
|
|
401
|
+
j += 2;
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
value += ch;
|
|
405
|
+
j++;
|
|
406
|
+
}
|
|
407
|
+
return null;
|
|
408
|
+
}
|
|
409
|
+
var skipSpace = (src, i) => {
|
|
410
|
+
while (i < src.length && /\s/.test(src[i])) i++;
|
|
411
|
+
return i;
|
|
412
|
+
};
|
|
413
|
+
var toLangString = (value) => JSON.stringify(value);
|
|
414
|
+
function updateDocumentInProgram(program, documentId, update, componentName = "DocumentEditor") {
|
|
415
|
+
const re = new RegExp(`\\b${componentName}\\s*\\(`, "g");
|
|
416
|
+
let match;
|
|
417
|
+
while (match = re.exec(program)) {
|
|
418
|
+
const args = [];
|
|
419
|
+
let i = match.index + match[0].length;
|
|
420
|
+
for (let n = 0; n < 3; n++) {
|
|
421
|
+
i = skipSpace(program, i);
|
|
422
|
+
const tok = readString(program, i);
|
|
423
|
+
if (!tok) break;
|
|
424
|
+
args.push(tok);
|
|
425
|
+
i = skipSpace(program, tok.end);
|
|
426
|
+
if (program[i] === ",") i++;
|
|
427
|
+
else break;
|
|
428
|
+
}
|
|
429
|
+
if (args[0]?.value !== documentId) continue;
|
|
430
|
+
const edits = [];
|
|
431
|
+
if (update.title !== void 0 && args[1] && args[1].value !== update.title) {
|
|
432
|
+
edits.push({ start: args[1].start, end: args[1].end, text: toLangString(update.title) });
|
|
433
|
+
}
|
|
434
|
+
if (update.content !== void 0 && args[2] && args[2].value !== update.content) {
|
|
435
|
+
edits.push({ start: args[2].start, end: args[2].end, text: toLangString(update.content) });
|
|
436
|
+
}
|
|
437
|
+
if (!args[2] && update.content !== void 0) return null;
|
|
438
|
+
let out = program;
|
|
439
|
+
for (const e of edits.sort((a, b) => b.start - a.start)) {
|
|
440
|
+
out = out.slice(0, e.start) + e.text + out.slice(e.end);
|
|
441
|
+
}
|
|
442
|
+
return out;
|
|
443
|
+
}
|
|
444
|
+
return null;
|
|
445
|
+
}
|
|
446
|
+
function readDocumentFromProgram(program, documentId, componentName = "DocumentEditor") {
|
|
447
|
+
const re = new RegExp(`\\b${componentName}\\s*\\(`, "g");
|
|
448
|
+
let match;
|
|
449
|
+
while (match = re.exec(program)) {
|
|
450
|
+
const args = [];
|
|
451
|
+
let i = match.index + match[0].length;
|
|
452
|
+
for (let n = 0; n < 3; n++) {
|
|
453
|
+
i = skipSpace(program, i);
|
|
454
|
+
const tok = readString(program, i);
|
|
455
|
+
if (!tok) break;
|
|
456
|
+
args.push(tok);
|
|
457
|
+
i = skipSpace(program, tok.end);
|
|
458
|
+
if (program[i] === ",") i++;
|
|
459
|
+
else break;
|
|
460
|
+
}
|
|
461
|
+
if (args[0]?.value === documentId && args[1] && args[2]) return { title: args[1].value, content: args[2].value };
|
|
462
|
+
}
|
|
463
|
+
return null;
|
|
464
|
+
}
|
|
465
|
+
|
|
104
466
|
// src/core/context.ts
|
|
105
467
|
import { createContext as createContext2, useContext as useContext2 } from "react";
|
|
106
468
|
var JuneContext = createContext2({
|
|
@@ -140,7 +502,7 @@ var lightTheme = {
|
|
|
140
502
|
};
|
|
141
503
|
|
|
142
504
|
// src/themes/theme-provider.tsx
|
|
143
|
-
import { jsx } from "react/jsx-runtime";
|
|
505
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
144
506
|
var QUERY = "(prefers-color-scheme: dark)";
|
|
145
507
|
function subscribe(onChange) {
|
|
146
508
|
if (typeof window === "undefined" || !window.matchMedia) return () => {
|
|
@@ -183,7 +545,7 @@ function JuneThemeProvider({
|
|
|
183
545
|
() => ({ mode: mode ?? "system", theme: resolved }),
|
|
184
546
|
[mode, resolved]
|
|
185
547
|
);
|
|
186
|
-
return /* @__PURE__ */
|
|
548
|
+
return /* @__PURE__ */ jsx2(JuneContext.Provider, { value: context, children: /* @__PURE__ */ jsx2(
|
|
187
549
|
"div",
|
|
188
550
|
{
|
|
189
551
|
className: className ? `june-ui-root ${className}` : "june-ui-root",
|
|
@@ -605,7 +967,7 @@ function splitResponse(source, options = {}) {
|
|
|
605
967
|
|
|
606
968
|
// src/renderer/error-boundary.tsx
|
|
607
969
|
import { Component } from "react";
|
|
608
|
-
import { jsx as
|
|
970
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
609
971
|
function keysChanged(a = [], b = []) {
|
|
610
972
|
return a.length !== b.length || a.some((v, i) => !Object.is(v, b[i]));
|
|
611
973
|
}
|
|
@@ -634,12 +996,12 @@ var JuneErrorBoundary = class extends Component {
|
|
|
634
996
|
const { fallback } = this.props;
|
|
635
997
|
if (typeof fallback === "function") return fallback({ error, reset: this.reset });
|
|
636
998
|
if (fallback !== void 0) return fallback;
|
|
637
|
-
return /* @__PURE__ */
|
|
999
|
+
return /* @__PURE__ */ jsx3("div", { role: "alert", "data-june-error": "", children: "Something went wrong while rendering this UI." });
|
|
638
1000
|
}
|
|
639
1001
|
};
|
|
640
1002
|
|
|
641
1003
|
// src/renderer/renderer.tsx
|
|
642
|
-
import { jsx as
|
|
1004
|
+
import { jsx as jsx4, jsxs } from "react/jsx-runtime";
|
|
643
1005
|
function JuneRenderer(props) {
|
|
644
1006
|
const {
|
|
645
1007
|
library,
|
|
@@ -659,14 +1021,43 @@ function JuneRenderer(props) {
|
|
|
659
1021
|
onError,
|
|
660
1022
|
onJuneError,
|
|
661
1023
|
documents,
|
|
1024
|
+
onResponseChange,
|
|
1025
|
+
responseChangeDelay = 300,
|
|
662
1026
|
loadingFallback = null,
|
|
663
1027
|
emptyFallback = null,
|
|
664
1028
|
errorFallback,
|
|
665
1029
|
resetKeys,
|
|
666
1030
|
...rendererProps
|
|
667
1031
|
} = props;
|
|
668
|
-
const latest = useRef({ actions, confirmAction, parseActionEvent, onAction, onError, onJuneError });
|
|
669
|
-
latest.current = { actions, confirmAction, parseActionEvent, onAction, onError, onJuneError };
|
|
1032
|
+
const latest = useRef({ actions, confirmAction, parseActionEvent, onAction, onError, onJuneError, onResponseChange, responseChangeDelay, response });
|
|
1033
|
+
latest.current = { actions, confirmAction, parseActionEvent, onAction, onError, onJuneError, onResponseChange, responseChangeDelay, response };
|
|
1034
|
+
const syncTimers = useRef(/* @__PURE__ */ new Map());
|
|
1035
|
+
useEffect(() => {
|
|
1036
|
+
const timers = syncTimers.current;
|
|
1037
|
+
return () => {
|
|
1038
|
+
timers.forEach(clearTimeout);
|
|
1039
|
+
timers.clear();
|
|
1040
|
+
};
|
|
1041
|
+
}, []);
|
|
1042
|
+
const syncProgram = useCallback(async (change, store) => {
|
|
1043
|
+
const l = latest.current;
|
|
1044
|
+
if (!l.onResponseChange || typeof l.response !== "string") return;
|
|
1045
|
+
const record = store.get(change.documentId);
|
|
1046
|
+
const title = record?.title ?? change.title;
|
|
1047
|
+
const json = record?.json ?? change.json;
|
|
1048
|
+
try {
|
|
1049
|
+
const { docToMarkdown: docToMarkdown2 } = await import("./document-engine-RKD5SLXR.js");
|
|
1050
|
+
const markdown = docToMarkdown2(json);
|
|
1051
|
+
const program = latest.current.response;
|
|
1052
|
+
if (typeof program !== "string") return;
|
|
1053
|
+
const next = updateDocumentInProgram(program, change.documentId, { title, content: markdown });
|
|
1054
|
+
if (next === null || next === program) return;
|
|
1055
|
+
rememberDocumentEcho(store, change.documentId, markdown);
|
|
1056
|
+
latest.current.onResponseChange?.(next, { documentId: change.documentId, title, markdown, source: change.source });
|
|
1057
|
+
} catch (error) {
|
|
1058
|
+
latest.current.onJuneError?.(toJuneError(error, "DOCUMENT_ERROR", "Updating the program failed"));
|
|
1059
|
+
}
|
|
1060
|
+
}, []);
|
|
670
1061
|
const handleAction = useCallback((event) => {
|
|
671
1062
|
const l = latest.current;
|
|
672
1063
|
l.onAction?.(event);
|
|
@@ -705,12 +1096,27 @@ function JuneRenderer(props) {
|
|
|
705
1096
|
const documentOptions = useMemo2(
|
|
706
1097
|
() => ({
|
|
707
1098
|
...documents,
|
|
1099
|
+
onDocumentChange: (change) => {
|
|
1100
|
+
documents?.onDocumentChange?.(change);
|
|
1101
|
+
if (!latest.current.onResponseChange || change.source === "ai") return;
|
|
1102
|
+
const store = documents?.store ?? getDefaultDocumentStore();
|
|
1103
|
+
const timers = syncTimers.current;
|
|
1104
|
+
const prev = timers.get(change.documentId);
|
|
1105
|
+
if (prev) clearTimeout(prev);
|
|
1106
|
+
timers.set(
|
|
1107
|
+
change.documentId,
|
|
1108
|
+
setTimeout(() => {
|
|
1109
|
+
timers.delete(change.documentId);
|
|
1110
|
+
void syncProgram(change, store);
|
|
1111
|
+
}, Math.max(0, latest.current.responseChangeDelay))
|
|
1112
|
+
);
|
|
1113
|
+
},
|
|
708
1114
|
onError: (error) => {
|
|
709
1115
|
documents?.onError?.(error);
|
|
710
1116
|
latest.current.onJuneError?.(error);
|
|
711
1117
|
}
|
|
712
1118
|
}),
|
|
713
|
-
[documents]
|
|
1119
|
+
[documents, syncProgram]
|
|
714
1120
|
);
|
|
715
1121
|
const parts = useMemo2(
|
|
716
1122
|
() => mixedContent && response ? splitResponse(response, { streaming: isStreaming }) : null,
|
|
@@ -725,31 +1131,34 @@ function JuneRenderer(props) {
|
|
|
725
1131
|
const before = parts?.before ?? [];
|
|
726
1132
|
const after = parts?.after ?? [];
|
|
727
1133
|
const hasText = before.length + after.length > 0;
|
|
728
|
-
const text = (value, index, key) => /* @__PURE__ */
|
|
729
|
-
return /* @__PURE__ */
|
|
730
|
-
|
|
731
|
-
{
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
1134
|
+
const text = (value, index, key) => /* @__PURE__ */ jsx4(Fragment, { children: renderText ? renderText(value, index) : /* @__PURE__ */ jsx4("p", { className: "june-text", children: value }) }, key);
|
|
1135
|
+
return /* @__PURE__ */ jsxs(JuneThemeProvider, { mode: theme, vars: themeVars, className, style, children: [
|
|
1136
|
+
/* @__PURE__ */ jsx4(OpenUIDevtoolsGate, {}),
|
|
1137
|
+
/* @__PURE__ */ jsx4(JuneRuntimeContext.Provider, { value: runtime, children: /* @__PURE__ */ jsx4(JuneDocumentContext.Provider, { value: documentOptions, children: /* @__PURE__ */ jsxs(
|
|
1138
|
+
JuneErrorBoundary,
|
|
1139
|
+
{
|
|
1140
|
+
fallback: errorFallback,
|
|
1141
|
+
onError: handleBoundaryError,
|
|
1142
|
+
resetKeys: resetKeys ?? [response],
|
|
1143
|
+
children: [
|
|
1144
|
+
before.map((t, i) => text(t, i, `b${i}`)),
|
|
1145
|
+
hasUi && /* @__PURE__ */ jsx4(
|
|
1146
|
+
Renderer,
|
|
1147
|
+
{
|
|
1148
|
+
...rendererProps,
|
|
1149
|
+
library,
|
|
1150
|
+
response: uiText,
|
|
1151
|
+
isStreaming,
|
|
1152
|
+
onAction: handleAction,
|
|
1153
|
+
onError: handleParserErrors
|
|
1154
|
+
}
|
|
1155
|
+
),
|
|
1156
|
+
after.map((t, i) => text(t, before.length + i, `a${i}`)),
|
|
1157
|
+
!hasUi && !hasText && (isStreaming ? loadingFallback : emptyFallback)
|
|
1158
|
+
]
|
|
1159
|
+
}
|
|
1160
|
+
) }) })
|
|
1161
|
+
] });
|
|
753
1162
|
}
|
|
754
1163
|
|
|
755
1164
|
// src/components/library.ts
|
|
@@ -803,7 +1212,7 @@ function defineJuneAction(definition) {
|
|
|
803
1212
|
}
|
|
804
1213
|
|
|
805
1214
|
// src/streaming/use-june-stream.ts
|
|
806
|
-
import { useCallback as useCallback2, useEffect, useMemo as useMemo3, useRef as useRef2, useState } from "react";
|
|
1215
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo3, useRef as useRef2, useState } from "react";
|
|
807
1216
|
|
|
808
1217
|
// src/streaming/stream-handler.ts
|
|
809
1218
|
function isReadableStream(source) {
|
|
@@ -1058,7 +1467,7 @@ function useJuneStream(options = {}) {
|
|
|
1058
1467
|
clearTimer();
|
|
1059
1468
|
setState(INITIAL);
|
|
1060
1469
|
}, [clearTimer]);
|
|
1061
|
-
|
|
1470
|
+
useEffect2(
|
|
1062
1471
|
() => () => {
|
|
1063
1472
|
runIdRef.current++;
|
|
1064
1473
|
controllerRef.current?.abort();
|
|
@@ -1077,25 +1486,25 @@ import { defineComponent as defineComponent2 } from "@openuidev/react-lang";
|
|
|
1077
1486
|
import { z } from "zod/v4";
|
|
1078
1487
|
|
|
1079
1488
|
// src/components/document-editor/document-draft.tsx
|
|
1080
|
-
import { jsx as
|
|
1489
|
+
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1081
1490
|
function DocumentDraft({ title, words, state }) {
|
|
1082
1491
|
if (state === "empty") {
|
|
1083
|
-
return /* @__PURE__ */
|
|
1492
|
+
return /* @__PURE__ */ jsx5("div", { className: "june-doc june-doc--draft", role: "alert", children: /* @__PURE__ */ jsx5("p", { className: "june-doc__draft-text", children: "No document content was received." }) });
|
|
1084
1493
|
}
|
|
1085
1494
|
return /* @__PURE__ */ jsxs2("div", { className: "june-doc june-doc--draft", role: "status", "aria-live": "polite", children: [
|
|
1086
|
-
title ? /* @__PURE__ */
|
|
1087
|
-
/* @__PURE__ */
|
|
1495
|
+
title ? /* @__PURE__ */ jsx5("p", { className: "june-doc__draft-title", children: title }) : null,
|
|
1496
|
+
/* @__PURE__ */ jsx5("p", { className: "june-doc__draft-text", children: state === "drafting" ? `Drafting document\u2026${words ? ` ${words} words so far` : ""}` : "Loading editor\u2026" }),
|
|
1088
1497
|
/* @__PURE__ */ jsxs2("div", { className: "june-doc__pulse", "aria-hidden": "true", children: [
|
|
1089
|
-
/* @__PURE__ */
|
|
1090
|
-
/* @__PURE__ */
|
|
1091
|
-
/* @__PURE__ */
|
|
1498
|
+
/* @__PURE__ */ jsx5("span", {}),
|
|
1499
|
+
/* @__PURE__ */ jsx5("span", {}),
|
|
1500
|
+
/* @__PURE__ */ jsx5("span", {})
|
|
1092
1501
|
] })
|
|
1093
1502
|
] });
|
|
1094
1503
|
}
|
|
1095
1504
|
|
|
1096
1505
|
// src/components/document-editor/document-editor.tsx
|
|
1097
1506
|
import { useEditor } from "@tiptap/react";
|
|
1098
|
-
import { useCallback as useCallback3, useEffect as
|
|
1507
|
+
import { useCallback as useCallback3, useEffect as useEffect6, useId, useMemo as useMemo4, useRef as useRef7, useState as useState6 } from "react";
|
|
1099
1508
|
|
|
1100
1509
|
// src/components/document-editor/document-bubble.tsx
|
|
1101
1510
|
import { useEditorState as useEditorState2 } from "@tiptap/react";
|
|
@@ -1106,208 +1515,208 @@ import { useEditorState } from "@tiptap/react";
|
|
|
1106
1515
|
import { useRef as useRef4, useState as useState3 } from "react";
|
|
1107
1516
|
|
|
1108
1517
|
// src/components/document-editor/document-icons.tsx
|
|
1109
|
-
import { Fragment as Fragment2, jsx as
|
|
1518
|
+
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1110
1519
|
var PATHS = {
|
|
1111
1520
|
undo: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1112
|
-
/* @__PURE__ */
|
|
1113
|
-
/* @__PURE__ */
|
|
1521
|
+
/* @__PURE__ */ jsx6("path", { d: "M9 14 4 9l5-5" }),
|
|
1522
|
+
/* @__PURE__ */ jsx6("path", { d: "M4 9h10.5a5.5 5.5 0 0 1 0 11H11" })
|
|
1114
1523
|
] }),
|
|
1115
1524
|
redo: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1116
|
-
/* @__PURE__ */
|
|
1117
|
-
/* @__PURE__ */
|
|
1525
|
+
/* @__PURE__ */ jsx6("path", { d: "m15 14 5-5-5-5" }),
|
|
1526
|
+
/* @__PURE__ */ jsx6("path", { d: "M20 9H9.5a5.5 5.5 0 0 0 0 11H13" })
|
|
1118
1527
|
] }),
|
|
1119
|
-
bold: /* @__PURE__ */
|
|
1528
|
+
bold: /* @__PURE__ */ jsx6("path", { d: "M6 12h9a4 4 0 0 1 0 8H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h7a4 4 0 0 1 0 8" }),
|
|
1120
1529
|
italic: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1121
|
-
/* @__PURE__ */
|
|
1122
|
-
/* @__PURE__ */
|
|
1123
|
-
/* @__PURE__ */
|
|
1530
|
+
/* @__PURE__ */ jsx6("line", { x1: "19", x2: "10", y1: "4", y2: "4" }),
|
|
1531
|
+
/* @__PURE__ */ jsx6("line", { x1: "14", x2: "5", y1: "20", y2: "20" }),
|
|
1532
|
+
/* @__PURE__ */ jsx6("line", { x1: "15", x2: "9", y1: "4", y2: "20" })
|
|
1124
1533
|
] }),
|
|
1125
1534
|
underline: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1126
|
-
/* @__PURE__ */
|
|
1127
|
-
/* @__PURE__ */
|
|
1535
|
+
/* @__PURE__ */ jsx6("path", { d: "M6 4v6a6 6 0 0 0 12 0V4" }),
|
|
1536
|
+
/* @__PURE__ */ jsx6("line", { x1: "4", x2: "20", y1: "20", y2: "20" })
|
|
1128
1537
|
] }),
|
|
1129
1538
|
strike: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1130
|
-
/* @__PURE__ */
|
|
1131
|
-
/* @__PURE__ */
|
|
1132
|
-
/* @__PURE__ */
|
|
1539
|
+
/* @__PURE__ */ jsx6("path", { d: "M16 4H9a3 3 0 0 0-2.83 4" }),
|
|
1540
|
+
/* @__PURE__ */ jsx6("path", { d: "M14 12a4 4 0 0 1 0 8H6" }),
|
|
1541
|
+
/* @__PURE__ */ jsx6("line", { x1: "4", x2: "20", y1: "12", y2: "12" })
|
|
1133
1542
|
] }),
|
|
1134
1543
|
code: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1135
|
-
/* @__PURE__ */
|
|
1136
|
-
/* @__PURE__ */
|
|
1544
|
+
/* @__PURE__ */ jsx6("path", { d: "m16 18 6-6-6-6" }),
|
|
1545
|
+
/* @__PURE__ */ jsx6("path", { d: "m8 6-6 6 6 6" })
|
|
1137
1546
|
] }),
|
|
1138
1547
|
codeBlock: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1139
|
-
/* @__PURE__ */
|
|
1140
|
-
/* @__PURE__ */
|
|
1141
|
-
/* @__PURE__ */
|
|
1548
|
+
/* @__PURE__ */ jsx6("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
|
|
1549
|
+
/* @__PURE__ */ jsx6("path", { d: "m10 9-3 3 3 3" }),
|
|
1550
|
+
/* @__PURE__ */ jsx6("path", { d: "m14 15 3-3-3-3" })
|
|
1142
1551
|
] }),
|
|
1143
1552
|
superscript: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1144
|
-
/* @__PURE__ */
|
|
1145
|
-
/* @__PURE__ */
|
|
1146
|
-
/* @__PURE__ */
|
|
1553
|
+
/* @__PURE__ */ jsx6("path", { d: "m4 19 8-8" }),
|
|
1554
|
+
/* @__PURE__ */ jsx6("path", { d: "m12 19-8-8" }),
|
|
1555
|
+
/* @__PURE__ */ jsx6("path", { d: "M20 12h-4c0-1.5.44-2 1.5-2.5S20 8.33 20 7c0-.47-.17-.93-.48-1.29a2.11 2.11 0 0 0-2.62-.44c-.42.24-.74.62-.9 1.07" })
|
|
1147
1556
|
] }),
|
|
1148
1557
|
subscript: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1149
|
-
/* @__PURE__ */
|
|
1150
|
-
/* @__PURE__ */
|
|
1151
|
-
/* @__PURE__ */
|
|
1558
|
+
/* @__PURE__ */ jsx6("path", { d: "m4 5 8 8" }),
|
|
1559
|
+
/* @__PURE__ */ jsx6("path", { d: "m12 5-8 8" }),
|
|
1560
|
+
/* @__PURE__ */ jsx6("path", { d: "M20 19h-4c0-1.5.44-2 1.5-2.5S20 15.33 20 14c0-.47-.17-.93-.48-1.29a2.11 2.11 0 0 0-2.62-.44c-.42.24-.74.62-.9 1.07" })
|
|
1152
1561
|
] }),
|
|
1153
1562
|
alignLeft: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1154
|
-
/* @__PURE__ */
|
|
1155
|
-
/* @__PURE__ */
|
|
1156
|
-
/* @__PURE__ */
|
|
1563
|
+
/* @__PURE__ */ jsx6("path", { d: "M15 12H3" }),
|
|
1564
|
+
/* @__PURE__ */ jsx6("path", { d: "M17 18H3" }),
|
|
1565
|
+
/* @__PURE__ */ jsx6("path", { d: "M21 6H3" })
|
|
1157
1566
|
] }),
|
|
1158
1567
|
alignCenter: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1159
|
-
/* @__PURE__ */
|
|
1160
|
-
/* @__PURE__ */
|
|
1161
|
-
/* @__PURE__ */
|
|
1568
|
+
/* @__PURE__ */ jsx6("path", { d: "M17 12H7" }),
|
|
1569
|
+
/* @__PURE__ */ jsx6("path", { d: "M19 18H5" }),
|
|
1570
|
+
/* @__PURE__ */ jsx6("path", { d: "M21 6H3" })
|
|
1162
1571
|
] }),
|
|
1163
1572
|
alignRight: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1164
|
-
/* @__PURE__ */
|
|
1165
|
-
/* @__PURE__ */
|
|
1166
|
-
/* @__PURE__ */
|
|
1573
|
+
/* @__PURE__ */ jsx6("path", { d: "M21 12H9" }),
|
|
1574
|
+
/* @__PURE__ */ jsx6("path", { d: "M21 18H7" }),
|
|
1575
|
+
/* @__PURE__ */ jsx6("path", { d: "M21 6H3" })
|
|
1167
1576
|
] }),
|
|
1168
1577
|
alignJustify: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1169
|
-
/* @__PURE__ */
|
|
1170
|
-
/* @__PURE__ */
|
|
1171
|
-
/* @__PURE__ */
|
|
1578
|
+
/* @__PURE__ */ jsx6("path", { d: "M3 12h18" }),
|
|
1579
|
+
/* @__PURE__ */ jsx6("path", { d: "M3 18h18" }),
|
|
1580
|
+
/* @__PURE__ */ jsx6("path", { d: "M3 6h18" })
|
|
1172
1581
|
] }),
|
|
1173
1582
|
list: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1174
|
-
/* @__PURE__ */
|
|
1175
|
-
/* @__PURE__ */
|
|
1176
|
-
/* @__PURE__ */
|
|
1177
|
-
/* @__PURE__ */
|
|
1178
|
-
/* @__PURE__ */
|
|
1179
|
-
/* @__PURE__ */
|
|
1583
|
+
/* @__PURE__ */ jsx6("path", { d: "M3 12h.01" }),
|
|
1584
|
+
/* @__PURE__ */ jsx6("path", { d: "M3 18h.01" }),
|
|
1585
|
+
/* @__PURE__ */ jsx6("path", { d: "M3 6h.01" }),
|
|
1586
|
+
/* @__PURE__ */ jsx6("path", { d: "M8 12h13" }),
|
|
1587
|
+
/* @__PURE__ */ jsx6("path", { d: "M8 18h13" }),
|
|
1588
|
+
/* @__PURE__ */ jsx6("path", { d: "M8 6h13" })
|
|
1180
1589
|
] }),
|
|
1181
1590
|
listOrdered: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1182
|
-
/* @__PURE__ */
|
|
1183
|
-
/* @__PURE__ */
|
|
1184
|
-
/* @__PURE__ */
|
|
1185
|
-
/* @__PURE__ */
|
|
1186
|
-
/* @__PURE__ */
|
|
1187
|
-
/* @__PURE__ */
|
|
1591
|
+
/* @__PURE__ */ jsx6("path", { d: "M10 12h11" }),
|
|
1592
|
+
/* @__PURE__ */ jsx6("path", { d: "M10 18h11" }),
|
|
1593
|
+
/* @__PURE__ */ jsx6("path", { d: "M10 6h11" }),
|
|
1594
|
+
/* @__PURE__ */ jsx6("path", { d: "M4 10h2" }),
|
|
1595
|
+
/* @__PURE__ */ jsx6("path", { d: "M4 6h1v4" }),
|
|
1596
|
+
/* @__PURE__ */ jsx6("path", { d: "M6 18H4c0-1 2-2 2-3s-1-1.5-2-1" })
|
|
1188
1597
|
] }),
|
|
1189
1598
|
outdent: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1190
|
-
/* @__PURE__ */
|
|
1191
|
-
/* @__PURE__ */
|
|
1192
|
-
/* @__PURE__ */
|
|
1193
|
-
/* @__PURE__ */
|
|
1599
|
+
/* @__PURE__ */ jsx6("path", { d: "M21 12H11" }),
|
|
1600
|
+
/* @__PURE__ */ jsx6("path", { d: "M21 18H11" }),
|
|
1601
|
+
/* @__PURE__ */ jsx6("path", { d: "M21 6H11" }),
|
|
1602
|
+
/* @__PURE__ */ jsx6("path", { d: "m7 8-4 4 4 4" })
|
|
1194
1603
|
] }),
|
|
1195
1604
|
indent: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1196
|
-
/* @__PURE__ */
|
|
1197
|
-
/* @__PURE__ */
|
|
1198
|
-
/* @__PURE__ */
|
|
1199
|
-
/* @__PURE__ */
|
|
1605
|
+
/* @__PURE__ */ jsx6("path", { d: "M21 12H11" }),
|
|
1606
|
+
/* @__PURE__ */ jsx6("path", { d: "M21 18H11" }),
|
|
1607
|
+
/* @__PURE__ */ jsx6("path", { d: "M21 6H11" }),
|
|
1608
|
+
/* @__PURE__ */ jsx6("path", { d: "m3 8 4 4-4 4" })
|
|
1200
1609
|
] }),
|
|
1201
1610
|
quote: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1202
|
-
/* @__PURE__ */
|
|
1203
|
-
/* @__PURE__ */
|
|
1204
|
-
/* @__PURE__ */
|
|
1205
|
-
/* @__PURE__ */
|
|
1611
|
+
/* @__PURE__ */ jsx6("path", { d: "M17 6H3" }),
|
|
1612
|
+
/* @__PURE__ */ jsx6("path", { d: "M21 12H8" }),
|
|
1613
|
+
/* @__PURE__ */ jsx6("path", { d: "M21 18H8" }),
|
|
1614
|
+
/* @__PURE__ */ jsx6("path", { d: "M3 12v6" })
|
|
1206
1615
|
] }),
|
|
1207
1616
|
pilcrow: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1208
|
-
/* @__PURE__ */
|
|
1209
|
-
/* @__PURE__ */
|
|
1210
|
-
/* @__PURE__ */
|
|
1617
|
+
/* @__PURE__ */ jsx6("path", { d: "M13 4v16" }),
|
|
1618
|
+
/* @__PURE__ */ jsx6("path", { d: "M17 4v16" }),
|
|
1619
|
+
/* @__PURE__ */ jsx6("path", { d: "M19 4H9.5a4.5 4.5 0 0 0 0 9H13" })
|
|
1211
1620
|
] }),
|
|
1212
1621
|
pageBreak: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1213
|
-
/* @__PURE__ */
|
|
1214
|
-
/* @__PURE__ */
|
|
1215
|
-
/* @__PURE__ */
|
|
1622
|
+
/* @__PURE__ */ jsx6("line", { x1: "3", x2: "21", y1: "12", y2: "12" }),
|
|
1623
|
+
/* @__PURE__ */ jsx6("polyline", { points: "8 8 12 4 16 8" }),
|
|
1624
|
+
/* @__PURE__ */ jsx6("polyline", { points: "16 16 12 20 8 16" })
|
|
1216
1625
|
] }),
|
|
1217
1626
|
divider: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1218
|
-
/* @__PURE__ */
|
|
1219
|
-
/* @__PURE__ */
|
|
1220
|
-
/* @__PURE__ */
|
|
1627
|
+
/* @__PURE__ */ jsx6("path", { d: "M3 12h18" }),
|
|
1628
|
+
/* @__PURE__ */ jsx6("path", { d: "M8 6h8", opacity: ".45" }),
|
|
1629
|
+
/* @__PURE__ */ jsx6("path", { d: "M8 18h8", opacity: ".45" })
|
|
1221
1630
|
] }),
|
|
1222
1631
|
layout: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1223
|
-
/* @__PURE__ */
|
|
1224
|
-
/* @__PURE__ */
|
|
1225
|
-
/* @__PURE__ */
|
|
1632
|
+
/* @__PURE__ */ jsx6("rect", { width: "18", height: "7", x: "3", y: "3", rx: "1" }),
|
|
1633
|
+
/* @__PURE__ */ jsx6("rect", { width: "9", height: "7", x: "3", y: "14", rx: "1" }),
|
|
1634
|
+
/* @__PURE__ */ jsx6("rect", { width: "5", height: "7", x: "16", y: "14", rx: "1" })
|
|
1226
1635
|
] }),
|
|
1227
1636
|
search: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1228
|
-
/* @__PURE__ */
|
|
1229
|
-
/* @__PURE__ */
|
|
1637
|
+
/* @__PURE__ */ jsx6("circle", { cx: "11", cy: "11", r: "8" }),
|
|
1638
|
+
/* @__PURE__ */ jsx6("path", { d: "m21 21-4.3-4.3" })
|
|
1230
1639
|
] }),
|
|
1231
1640
|
palette: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1232
|
-
/* @__PURE__ */
|
|
1233
|
-
/* @__PURE__ */
|
|
1234
|
-
/* @__PURE__ */
|
|
1235
|
-
/* @__PURE__ */
|
|
1236
|
-
/* @__PURE__ */
|
|
1641
|
+
/* @__PURE__ */ jsx6("circle", { cx: "13.5", cy: "6.5", r: ".5", fill: "currentColor" }),
|
|
1642
|
+
/* @__PURE__ */ jsx6("circle", { cx: "17.5", cy: "10.5", r: ".5", fill: "currentColor" }),
|
|
1643
|
+
/* @__PURE__ */ jsx6("circle", { cx: "8.5", cy: "7.5", r: ".5", fill: "currentColor" }),
|
|
1644
|
+
/* @__PURE__ */ jsx6("circle", { cx: "6.5", cy: "12.5", r: ".5", fill: "currentColor" }),
|
|
1645
|
+
/* @__PURE__ */ jsx6("path", { d: "M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.93 0 1.65-.75 1.65-1.69 0-.44-.18-.84-.44-1.13-.29-.29-.44-.65-.44-1.13a1.64 1.64 0 0 1 1.67-1.67h2c3.05 0 5.55-2.5 5.55-5.55C21.97 6.01 17.46 2 12 2z" })
|
|
1237
1646
|
] }),
|
|
1238
1647
|
highlighter: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1239
|
-
/* @__PURE__ */
|
|
1240
|
-
/* @__PURE__ */
|
|
1648
|
+
/* @__PURE__ */ jsx6("path", { d: "m9 11-6 6v3h9l3-3" }),
|
|
1649
|
+
/* @__PURE__ */ jsx6("path", { d: "m22 12-4.6 4.6a2 2 0 0 1-2.8 0l-5.2-5.2a2 2 0 0 1 0-2.8L14 4" })
|
|
1241
1650
|
] }),
|
|
1242
1651
|
link: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1243
|
-
/* @__PURE__ */
|
|
1244
|
-
/* @__PURE__ */
|
|
1652
|
+
/* @__PURE__ */ jsx6("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
|
|
1653
|
+
/* @__PURE__ */ jsx6("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
|
|
1245
1654
|
] }),
|
|
1246
1655
|
image: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1247
|
-
/* @__PURE__ */
|
|
1248
|
-
/* @__PURE__ */
|
|
1249
|
-
/* @__PURE__ */
|
|
1656
|
+
/* @__PURE__ */ jsx6("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2" }),
|
|
1657
|
+
/* @__PURE__ */ jsx6("circle", { cx: "9", cy: "9", r: "2" }),
|
|
1658
|
+
/* @__PURE__ */ jsx6("path", { d: "m21 15-3.09-3.09a2 2 0 0 0-2.82 0L6 21" })
|
|
1250
1659
|
] }),
|
|
1251
1660
|
table: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1252
|
-
/* @__PURE__ */
|
|
1253
|
-
/* @__PURE__ */
|
|
1254
|
-
/* @__PURE__ */
|
|
1255
|
-
/* @__PURE__ */
|
|
1661
|
+
/* @__PURE__ */ jsx6("path", { d: "M12 3v18" }),
|
|
1662
|
+
/* @__PURE__ */ jsx6("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2" }),
|
|
1663
|
+
/* @__PURE__ */ jsx6("path", { d: "M3 9h18" }),
|
|
1664
|
+
/* @__PURE__ */ jsx6("path", { d: "M3 15h18" })
|
|
1256
1665
|
] }),
|
|
1257
1666
|
eraser: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1258
|
-
/* @__PURE__ */
|
|
1259
|
-
/* @__PURE__ */
|
|
1260
|
-
/* @__PURE__ */
|
|
1667
|
+
/* @__PURE__ */ jsx6("path", { d: "m7 21-4.3-4.3c-1-1-1-2.5 0-3.4l9.6-9.6c1-1 2.5-1 3.4 0l5.6 5.6c1 1 1 2.5 0 3.4L13 21" }),
|
|
1668
|
+
/* @__PURE__ */ jsx6("path", { d: "M22 21H7" }),
|
|
1669
|
+
/* @__PURE__ */ jsx6("path", { d: "m5 11 9 9" })
|
|
1261
1670
|
] }),
|
|
1262
1671
|
save: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1263
|
-
/* @__PURE__ */
|
|
1264
|
-
/* @__PURE__ */
|
|
1265
|
-
/* @__PURE__ */
|
|
1672
|
+
/* @__PURE__ */ jsx6("path", { d: "M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" }),
|
|
1673
|
+
/* @__PURE__ */ jsx6("path", { d: "M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" }),
|
|
1674
|
+
/* @__PURE__ */ jsx6("path", { d: "M7 3v4a1 1 0 0 0 1 1h7" })
|
|
1266
1675
|
] }),
|
|
1267
1676
|
download: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1268
|
-
/* @__PURE__ */
|
|
1269
|
-
/* @__PURE__ */
|
|
1270
|
-
/* @__PURE__ */
|
|
1677
|
+
/* @__PURE__ */ jsx6("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
|
|
1678
|
+
/* @__PURE__ */ jsx6("polyline", { points: "7 10 12 15 17 10" }),
|
|
1679
|
+
/* @__PURE__ */ jsx6("line", { x1: "12", x2: "12", y1: "15", y2: "3" })
|
|
1271
1680
|
] }),
|
|
1272
|
-
chevronDown: /* @__PURE__ */
|
|
1273
|
-
chevronUp: /* @__PURE__ */
|
|
1681
|
+
chevronDown: /* @__PURE__ */ jsx6("path", { d: "m6 9 6 6 6-6" }),
|
|
1682
|
+
chevronUp: /* @__PURE__ */ jsx6("path", { d: "m18 15-6-6-6 6" }),
|
|
1274
1683
|
close: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1275
|
-
/* @__PURE__ */
|
|
1276
|
-
/* @__PURE__ */
|
|
1684
|
+
/* @__PURE__ */ jsx6("path", { d: "M18 6 6 18" }),
|
|
1685
|
+
/* @__PURE__ */ jsx6("path", { d: "m6 6 12 12" })
|
|
1277
1686
|
] }),
|
|
1278
1687
|
maximize: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1279
|
-
/* @__PURE__ */
|
|
1280
|
-
/* @__PURE__ */
|
|
1281
|
-
/* @__PURE__ */
|
|
1282
|
-
/* @__PURE__ */
|
|
1688
|
+
/* @__PURE__ */ jsx6("path", { d: "M8 3H5a2 2 0 0 0-2 2v3" }),
|
|
1689
|
+
/* @__PURE__ */ jsx6("path", { d: "M21 8V5a2 2 0 0 0-2-2h-3" }),
|
|
1690
|
+
/* @__PURE__ */ jsx6("path", { d: "M3 16v3a2 2 0 0 0 2 2h3" }),
|
|
1691
|
+
/* @__PURE__ */ jsx6("path", { d: "M16 21h3a2 2 0 0 0 2-2v-3" })
|
|
1283
1692
|
] }),
|
|
1284
1693
|
copy: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1285
|
-
/* @__PURE__ */
|
|
1286
|
-
/* @__PURE__ */
|
|
1694
|
+
/* @__PURE__ */ jsx6("rect", { width: "14", height: "14", x: "8", y: "8", rx: "2" }),
|
|
1695
|
+
/* @__PURE__ */ jsx6("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" })
|
|
1287
1696
|
] }),
|
|
1288
1697
|
file: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1289
|
-
/* @__PURE__ */
|
|
1290
|
-
/* @__PURE__ */
|
|
1698
|
+
/* @__PURE__ */ jsx6("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
|
|
1699
|
+
/* @__PURE__ */ jsx6("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" })
|
|
1291
1700
|
] }),
|
|
1292
1701
|
plus: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1293
|
-
/* @__PURE__ */
|
|
1294
|
-
/* @__PURE__ */
|
|
1702
|
+
/* @__PURE__ */ jsx6("path", { d: "M5 12h14" }),
|
|
1703
|
+
/* @__PURE__ */ jsx6("path", { d: "M12 5v14" })
|
|
1295
1704
|
] }),
|
|
1296
|
-
minus: /* @__PURE__ */
|
|
1297
|
-
check: /* @__PURE__ */
|
|
1705
|
+
minus: /* @__PURE__ */ jsx6("path", { d: "M5 12h14" }),
|
|
1706
|
+
check: /* @__PURE__ */ jsx6("path", { d: "M20 6 9 17l-5-5" }),
|
|
1298
1707
|
sparkles: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1299
|
-
/* @__PURE__ */
|
|
1300
|
-
/* @__PURE__ */
|
|
1301
|
-
/* @__PURE__ */
|
|
1708
|
+
/* @__PURE__ */ jsx6("path", { d: "M9.94 14.06 8 20l-1.94-5.94L0 12l6.06-1.94L8 4l1.94 6.06L16 12z", transform: "translate(3 -1) scale(.85)" }),
|
|
1709
|
+
/* @__PURE__ */ jsx6("path", { d: "M20 3v4" }),
|
|
1710
|
+
/* @__PURE__ */ jsx6("path", { d: "M22 5h-4" })
|
|
1302
1711
|
] }),
|
|
1303
1712
|
upload: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1304
|
-
/* @__PURE__ */
|
|
1305
|
-
/* @__PURE__ */
|
|
1306
|
-
/* @__PURE__ */
|
|
1713
|
+
/* @__PURE__ */ jsx6("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
|
|
1714
|
+
/* @__PURE__ */ jsx6("polyline", { points: "17 8 12 3 7 8" }),
|
|
1715
|
+
/* @__PURE__ */ jsx6("line", { x1: "12", x2: "12", y1: "3", y2: "15" })
|
|
1307
1716
|
] })
|
|
1308
1717
|
};
|
|
1309
1718
|
function Icon({ name, size = 16 }) {
|
|
1310
|
-
return /* @__PURE__ */
|
|
1719
|
+
return /* @__PURE__ */ jsx6(
|
|
1311
1720
|
"svg",
|
|
1312
1721
|
{
|
|
1313
1722
|
className: "june-doc__icon",
|
|
@@ -1327,12 +1736,12 @@ function Icon({ name, size = 16 }) {
|
|
|
1327
1736
|
}
|
|
1328
1737
|
|
|
1329
1738
|
// src/components/document-editor/document-popover.tsx
|
|
1330
|
-
import { useEffect as
|
|
1331
|
-
import { jsx as
|
|
1739
|
+
import { useEffect as useEffect3, useRef as useRef3, useState as useState2 } from "react";
|
|
1740
|
+
import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1332
1741
|
function Dropdown({ trigger, children, align = "start", className, onOpen }) {
|
|
1333
1742
|
const [open, setOpen] = useState2(false);
|
|
1334
1743
|
const anchor = useRef3(null);
|
|
1335
|
-
|
|
1744
|
+
useEffect3(() => {
|
|
1336
1745
|
if (!open) return;
|
|
1337
1746
|
const onDown = (e) => {
|
|
1338
1747
|
if (anchor.current && !anchor.current.contains(e.target)) setOpen(false);
|
|
@@ -1358,14 +1767,14 @@ function Dropdown({ trigger, children, align = "start", className, onOpen }) {
|
|
|
1358
1767
|
},
|
|
1359
1768
|
children: [
|
|
1360
1769
|
trigger({ open, toggle }),
|
|
1361
|
-
open ? /* @__PURE__ */
|
|
1770
|
+
open ? /* @__PURE__ */ jsx7("div", { className: `june-doc__pop june-doc__pop--${align}${className ? ` ${className}` : ""}`, children: children(close) }) : null
|
|
1362
1771
|
]
|
|
1363
1772
|
}
|
|
1364
1773
|
);
|
|
1365
1774
|
}
|
|
1366
1775
|
|
|
1367
1776
|
// src/components/document-editor/document-toolbar.tsx
|
|
1368
|
-
import { jsx as
|
|
1777
|
+
import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1369
1778
|
var FONT_FAMILIES = [
|
|
1370
1779
|
{ label: "Default", value: "" },
|
|
1371
1780
|
{ label: "Arial", value: "Arial, Helvetica, sans-serif" },
|
|
@@ -1425,26 +1834,26 @@ function Btn({ label, icon, active, disabled, toggle, onClick, children, classNa
|
|
|
1425
1834
|
onMouseDown: (e) => e.preventDefault(),
|
|
1426
1835
|
onClick,
|
|
1427
1836
|
children: [
|
|
1428
|
-
icon ? /* @__PURE__ */
|
|
1429
|
-
children ?? (text ? /* @__PURE__ */
|
|
1837
|
+
icon ? /* @__PURE__ */ jsx8(Icon, { name: icon }) : null,
|
|
1838
|
+
children ?? (text ? /* @__PURE__ */ jsx8("span", { children: label }) : null)
|
|
1430
1839
|
]
|
|
1431
1840
|
}
|
|
1432
1841
|
);
|
|
1433
1842
|
}
|
|
1434
1843
|
function Group({ label, children }) {
|
|
1435
1844
|
return /* @__PURE__ */ jsxs5("div", { className: "june-doc__group", role: "group", "aria-label": label, children: [
|
|
1436
|
-
label ? /* @__PURE__ */
|
|
1845
|
+
label ? /* @__PURE__ */ jsx8("span", { className: "june-doc__group-label", "aria-hidden": "true", children: label }) : null,
|
|
1437
1846
|
children
|
|
1438
1847
|
] });
|
|
1439
1848
|
}
|
|
1440
1849
|
function Field({ label, children }) {
|
|
1441
1850
|
return /* @__PURE__ */ jsxs5("label", { className: "june-doc__field", children: [
|
|
1442
|
-
/* @__PURE__ */
|
|
1851
|
+
/* @__PURE__ */ jsx8("span", { className: "june-doc__field-label", children: label }),
|
|
1443
1852
|
children
|
|
1444
1853
|
] });
|
|
1445
1854
|
}
|
|
1446
1855
|
function ColorPicker({ label, icon, colors, current, disabled, resetLabel, onPick, onReset }) {
|
|
1447
|
-
return /* @__PURE__ */
|
|
1856
|
+
return /* @__PURE__ */ jsx8(
|
|
1448
1857
|
Dropdown,
|
|
1449
1858
|
{
|
|
1450
1859
|
trigger: ({ open, toggle }) => /* @__PURE__ */ jsxs5(
|
|
@@ -1460,14 +1869,14 @@ function ColorPicker({ label, icon, colors, current, disabled, resetLabel, onPic
|
|
|
1460
1869
|
onMouseDown: (e) => e.preventDefault(),
|
|
1461
1870
|
onClick: toggle,
|
|
1462
1871
|
children: [
|
|
1463
|
-
/* @__PURE__ */
|
|
1464
|
-
/* @__PURE__ */
|
|
1872
|
+
/* @__PURE__ */ jsx8(Icon, { name: icon }),
|
|
1873
|
+
/* @__PURE__ */ jsx8("span", { className: "june-doc__color-bar", style: { background: current ?? "transparent" } })
|
|
1465
1874
|
]
|
|
1466
1875
|
}
|
|
1467
1876
|
),
|
|
1468
1877
|
children: (close) => /* @__PURE__ */ jsxs5("div", { className: "june-doc__swatches-wrap", role: "dialog", "aria-label": label, children: [
|
|
1469
|
-
/* @__PURE__ */
|
|
1470
|
-
/* @__PURE__ */
|
|
1878
|
+
/* @__PURE__ */ jsx8("div", { className: "june-doc__pop-title", children: label }),
|
|
1879
|
+
/* @__PURE__ */ jsx8("div", { className: "june-doc__swatches", children: colors.map((c) => /* @__PURE__ */ jsx8(
|
|
1471
1880
|
"button",
|
|
1472
1881
|
{
|
|
1473
1882
|
type: "button",
|
|
@@ -1485,7 +1894,7 @@ function ColorPicker({ label, icon, colors, current, disabled, resetLabel, onPic
|
|
|
1485
1894
|
c
|
|
1486
1895
|
)) }),
|
|
1487
1896
|
/* @__PURE__ */ jsxs5("div", { className: "june-doc__pop-row", children: [
|
|
1488
|
-
/* @__PURE__ */
|
|
1897
|
+
/* @__PURE__ */ jsx8(
|
|
1489
1898
|
"button",
|
|
1490
1899
|
{
|
|
1491
1900
|
type: "button",
|
|
@@ -1499,8 +1908,8 @@ function ColorPicker({ label, icon, colors, current, disabled, resetLabel, onPic
|
|
|
1499
1908
|
}
|
|
1500
1909
|
),
|
|
1501
1910
|
/* @__PURE__ */ jsxs5("label", { className: "june-doc__custom-color", title: "Custom color", children: [
|
|
1502
|
-
/* @__PURE__ */
|
|
1503
|
-
/* @__PURE__ */
|
|
1911
|
+
/* @__PURE__ */ jsx8("span", { children: "Custom" }),
|
|
1912
|
+
/* @__PURE__ */ jsx8(
|
|
1504
1913
|
"input",
|
|
1505
1914
|
{
|
|
1506
1915
|
type: "color",
|
|
@@ -1532,8 +1941,8 @@ function LinkPanel({
|
|
|
1532
1941
|
close();
|
|
1533
1942
|
};
|
|
1534
1943
|
return /* @__PURE__ */ jsxs5("div", { className: "june-doc__form", role: "dialog", "aria-label": "Edit link", children: [
|
|
1535
|
-
/* @__PURE__ */
|
|
1536
|
-
/* @__PURE__ */
|
|
1944
|
+
/* @__PURE__ */ jsx8("div", { className: "june-doc__pop-title", children: "Link" }),
|
|
1945
|
+
/* @__PURE__ */ jsx8(
|
|
1537
1946
|
"input",
|
|
1538
1947
|
{
|
|
1539
1948
|
"aria-label": "Link address",
|
|
@@ -1551,9 +1960,9 @@ function LinkPanel({
|
|
|
1551
1960
|
}
|
|
1552
1961
|
),
|
|
1553
1962
|
/* @__PURE__ */ jsxs5("div", { className: "june-doc__pop-row june-doc__pop-row--end", children: [
|
|
1554
|
-
isLink ? /* @__PURE__ */
|
|
1555
|
-
/* @__PURE__ */
|
|
1556
|
-
/* @__PURE__ */
|
|
1963
|
+
isLink ? /* @__PURE__ */ jsx8("button", { type: "button", className: "june-doc__btn june-doc__btn--ghost", onClick: remove, children: "Remove" }) : null,
|
|
1964
|
+
/* @__PURE__ */ jsx8("button", { type: "button", className: "june-doc__btn", onClick: close, children: "Cancel" }),
|
|
1965
|
+
/* @__PURE__ */ jsx8("button", { type: "button", className: "june-doc__btn june-doc__btn--primary", onClick: apply, children: "Apply" })
|
|
1557
1966
|
] })
|
|
1558
1967
|
] });
|
|
1559
1968
|
}
|
|
@@ -1583,7 +1992,7 @@ function ImagePanel({ editor, close, onNotice }) {
|
|
|
1583
1992
|
reader.readAsDataURL(f);
|
|
1584
1993
|
};
|
|
1585
1994
|
return /* @__PURE__ */ jsxs5("div", { className: "june-doc__form", role: "dialog", "aria-label": "Insert image", children: [
|
|
1586
|
-
/* @__PURE__ */
|
|
1995
|
+
/* @__PURE__ */ jsx8("div", { className: "june-doc__pop-title", children: "Image" }),
|
|
1587
1996
|
/* @__PURE__ */ jsxs5(
|
|
1588
1997
|
"button",
|
|
1589
1998
|
{
|
|
@@ -1596,12 +2005,12 @@ function ImagePanel({ editor, close, onNotice }) {
|
|
|
1596
2005
|
fromFile(e.dataTransfer.files[0]);
|
|
1597
2006
|
},
|
|
1598
2007
|
children: [
|
|
1599
|
-
/* @__PURE__ */
|
|
1600
|
-
/* @__PURE__ */
|
|
2008
|
+
/* @__PURE__ */ jsx8(Icon, { name: "upload", size: 18 }),
|
|
2009
|
+
/* @__PURE__ */ jsx8("span", { children: "Upload or drop an image" })
|
|
1601
2010
|
]
|
|
1602
2011
|
}
|
|
1603
2012
|
),
|
|
1604
|
-
/* @__PURE__ */
|
|
2013
|
+
/* @__PURE__ */ jsx8(
|
|
1605
2014
|
"input",
|
|
1606
2015
|
{
|
|
1607
2016
|
ref: file,
|
|
@@ -1611,8 +2020,8 @@ function ImagePanel({ editor, close, onNotice }) {
|
|
|
1611
2020
|
onChange: (e) => fromFile(e.target.files?.[0])
|
|
1612
2021
|
}
|
|
1613
2022
|
),
|
|
1614
|
-
/* @__PURE__ */
|
|
1615
|
-
/* @__PURE__ */
|
|
2023
|
+
/* @__PURE__ */ jsx8("div", { className: "june-doc__or", children: "or" }),
|
|
2024
|
+
/* @__PURE__ */ jsx8(
|
|
1616
2025
|
"input",
|
|
1617
2026
|
{
|
|
1618
2027
|
"aria-label": "Image address",
|
|
@@ -1623,7 +2032,7 @@ function ImagePanel({ editor, close, onNotice }) {
|
|
|
1623
2032
|
onKeyDown: (e) => e.key === "Enter" && fromUrl()
|
|
1624
2033
|
}
|
|
1625
2034
|
),
|
|
1626
|
-
/* @__PURE__ */
|
|
2035
|
+
/* @__PURE__ */ jsx8(
|
|
1627
2036
|
"input",
|
|
1628
2037
|
{
|
|
1629
2038
|
"aria-label": "Alternative text",
|
|
@@ -1634,8 +2043,8 @@ function ImagePanel({ editor, close, onNotice }) {
|
|
|
1634
2043
|
}
|
|
1635
2044
|
),
|
|
1636
2045
|
/* @__PURE__ */ jsxs5("div", { className: "june-doc__pop-row june-doc__pop-row--end", children: [
|
|
1637
|
-
/* @__PURE__ */
|
|
1638
|
-
/* @__PURE__ */
|
|
2046
|
+
/* @__PURE__ */ jsx8("button", { type: "button", className: "june-doc__btn", onClick: close, children: "Cancel" }),
|
|
2047
|
+
/* @__PURE__ */ jsx8("button", { type: "button", className: "june-doc__btn june-doc__btn--primary", disabled: !url.trim(), onClick: fromUrl, children: "Insert" })
|
|
1639
2048
|
] })
|
|
1640
2049
|
] });
|
|
1641
2050
|
}
|
|
@@ -1647,10 +2056,10 @@ function TablePanel({ editor, close }) {
|
|
|
1647
2056
|
"Table ",
|
|
1648
2057
|
hover[0] ? `${hover[0]} \xD7 ${hover[1]}` : ""
|
|
1649
2058
|
] }),
|
|
1650
|
-
/* @__PURE__ */
|
|
2059
|
+
/* @__PURE__ */ jsx8("div", { className: "june-doc__grid", onMouseLeave: () => setHover([0, 0]), children: Array.from({ length: N * N }, (_, i) => {
|
|
1651
2060
|
const r = Math.floor(i / N) + 1;
|
|
1652
2061
|
const c = i % N + 1;
|
|
1653
|
-
return /* @__PURE__ */
|
|
2062
|
+
return /* @__PURE__ */ jsx8(
|
|
1654
2063
|
"button",
|
|
1655
2064
|
{
|
|
1656
2065
|
type: "button",
|
|
@@ -1735,29 +2144,29 @@ function DocumentToolbar(props) {
|
|
|
1735
2144
|
return /* @__PURE__ */ jsxs5("div", { className: "june-doc__ribbon", role: "toolbar", "aria-label": "Document formatting", children: [
|
|
1736
2145
|
/* @__PURE__ */ jsxs5("div", { className: "june-doc__row", children: [
|
|
1737
2146
|
/* @__PURE__ */ jsxs5(Group, { label: "History", children: [
|
|
1738
|
-
/* @__PURE__ */
|
|
1739
|
-
/* @__PURE__ */
|
|
2147
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Undo", icon: "undo", disabled: off || !s?.canUndo, onClick: () => run()?.undo().run() }),
|
|
2148
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Redo", icon: "redo", disabled: off || !s?.canRedo, onClick: () => run()?.redo().run() })
|
|
1740
2149
|
] }),
|
|
1741
2150
|
/* @__PURE__ */ jsxs5(Group, { label: "Format", children: [
|
|
1742
|
-
/* @__PURE__ */
|
|
1743
|
-
/* @__PURE__ */
|
|
1744
|
-
/* @__PURE__ */
|
|
1745
|
-
/* @__PURE__ */
|
|
1746
|
-
/* @__PURE__ */
|
|
1747
|
-
/* @__PURE__ */
|
|
1748
|
-
/* @__PURE__ */
|
|
2151
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Bold", icon: "bold", toggle: true, active: s?.bold, disabled: off, onClick: () => run()?.toggleBold().run() }),
|
|
2152
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Italic", icon: "italic", toggle: true, active: s?.italic, disabled: off, onClick: () => run()?.toggleItalic().run() }),
|
|
2153
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Underline", icon: "underline", toggle: true, active: s?.underline, disabled: off, onClick: () => run()?.toggleUnderline().run() }),
|
|
2154
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Strikethrough", icon: "strike", toggle: true, active: s?.strike, disabled: off, onClick: () => run()?.toggleStrike().run() }),
|
|
2155
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Inline code", icon: "code", toggle: true, active: s?.code, disabled: off, onClick: () => run()?.toggleCode().run() }),
|
|
2156
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Superscript", icon: "superscript", toggle: true, active: s?.sup, disabled: off, onClick: () => run()?.toggleSuperscript().run() }),
|
|
2157
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Subscript", icon: "subscript", toggle: true, active: s?.sub, disabled: off, onClick: () => run()?.toggleSubscript().run() })
|
|
1749
2158
|
] }),
|
|
1750
2159
|
/* @__PURE__ */ jsxs5(Group, { label: "Align", children: [
|
|
1751
|
-
/* @__PURE__ */
|
|
1752
|
-
/* @__PURE__ */
|
|
1753
|
-
/* @__PURE__ */
|
|
1754
|
-
/* @__PURE__ */
|
|
2160
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Align left", icon: "alignLeft", toggle: true, active: s?.left, disabled: off, onClick: () => run()?.setTextAlign("left").run() }),
|
|
2161
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Align center", icon: "alignCenter", toggle: true, active: s?.center, disabled: off, onClick: () => run()?.setTextAlign("center").run() }),
|
|
2162
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Align right", icon: "alignRight", toggle: true, active: s?.right, disabled: off, onClick: () => run()?.setTextAlign("right").run() }),
|
|
2163
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Justify", icon: "alignJustify", toggle: true, active: s?.justify, disabled: off, onClick: () => run()?.setTextAlign("justify").run() })
|
|
1755
2164
|
] }),
|
|
1756
2165
|
/* @__PURE__ */ jsxs5(Group, { label: "Lists", children: [
|
|
1757
|
-
/* @__PURE__ */
|
|
1758
|
-
/* @__PURE__ */
|
|
1759
|
-
/* @__PURE__ */
|
|
1760
|
-
/* @__PURE__ */
|
|
2166
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Bullet list", icon: "list", toggle: true, active: s?.bullet, disabled: off, onClick: () => run()?.toggleBulletList().run() }),
|
|
2167
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Numbered list", icon: "listOrdered", toggle: true, active: s?.ordered, disabled: off, onClick: () => run()?.toggleOrderedList().run() }),
|
|
2168
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Decrease indent", icon: "outdent", disabled: off || !s?.canLift, onClick: () => run()?.liftListItem("listItem").run() }),
|
|
2169
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Increase indent", icon: "indent", disabled: off || !s?.canSink, onClick: () => run()?.sinkListItem("listItem").run() })
|
|
1761
2170
|
] }),
|
|
1762
2171
|
/* @__PURE__ */ jsxs5(
|
|
1763
2172
|
"button",
|
|
@@ -1770,22 +2179,22 @@ function DocumentToolbar(props) {
|
|
|
1770
2179
|
onClick: onToggleExpanded,
|
|
1771
2180
|
children: [
|
|
1772
2181
|
expanded ? "Less" : "More",
|
|
1773
|
-
/* @__PURE__ */
|
|
2182
|
+
/* @__PURE__ */ jsx8(Icon, { name: expanded ? "chevronUp" : "chevronDown", size: 14 })
|
|
1774
2183
|
]
|
|
1775
2184
|
}
|
|
1776
2185
|
)
|
|
1777
2186
|
] }),
|
|
1778
2187
|
expanded ? /* @__PURE__ */ jsxs5("div", { className: "june-doc__row june-doc__row--secondary", children: [
|
|
1779
2188
|
/* @__PURE__ */ jsxs5(Group, { label: "Style", children: [
|
|
1780
|
-
/* @__PURE__ */
|
|
1781
|
-
/* @__PURE__ */
|
|
1782
|
-
/* @__PURE__ */
|
|
1783
|
-
/* @__PURE__ */
|
|
1784
|
-
/* @__PURE__ */
|
|
1785
|
-
/* @__PURE__ */
|
|
1786
|
-
/* @__PURE__ */
|
|
2189
|
+
/* @__PURE__ */ jsx8(Field, { label: "Style", children: /* @__PURE__ */ jsxs5("select", { className: "june-doc__select", "aria-label": "Text style", disabled: off, value: style, onChange: (e) => setStyle(e.target.value), children: [
|
|
2190
|
+
/* @__PURE__ */ jsx8("option", { value: "p", children: "Paragraph" }),
|
|
2191
|
+
/* @__PURE__ */ jsx8("option", { value: "1", children: "Heading 1" }),
|
|
2192
|
+
/* @__PURE__ */ jsx8("option", { value: "2", children: "Heading 2" }),
|
|
2193
|
+
/* @__PURE__ */ jsx8("option", { value: "3", children: "Heading 3" }),
|
|
2194
|
+
/* @__PURE__ */ jsx8("option", { value: "quote", children: "Quote" }),
|
|
2195
|
+
/* @__PURE__ */ jsx8("option", { value: "code", children: "Code block" })
|
|
1787
2196
|
] }) }),
|
|
1788
|
-
/* @__PURE__ */
|
|
2197
|
+
/* @__PURE__ */ jsx8(Field, { label: "Font", children: /* @__PURE__ */ jsxs5(
|
|
1789
2198
|
"select",
|
|
1790
2199
|
{
|
|
1791
2200
|
className: "june-doc__select june-doc__select--font",
|
|
@@ -1798,12 +2207,12 @@ function DocumentToolbar(props) {
|
|
|
1798
2207
|
else run()?.unsetFontFamily().run();
|
|
1799
2208
|
},
|
|
1800
2209
|
children: [
|
|
1801
|
-
FONT_FAMILIES.map((f) => /* @__PURE__ */
|
|
1802
|
-
!fontKnown && s?.fontFamily ? /* @__PURE__ */
|
|
2210
|
+
FONT_FAMILIES.map((f) => /* @__PURE__ */ jsx8("option", { value: f.value, style: { fontFamily: f.value || void 0 }, children: f.label }, f.label)),
|
|
2211
|
+
!fontKnown && s?.fontFamily ? /* @__PURE__ */ jsx8("option", { value: s.fontFamily, children: s.fontFamily.split(",")[0].replace(/['"]/g, "") }) : null
|
|
1803
2212
|
]
|
|
1804
2213
|
}
|
|
1805
2214
|
) }),
|
|
1806
|
-
/* @__PURE__ */
|
|
2215
|
+
/* @__PURE__ */ jsx8(Field, { label: "Size", children: /* @__PURE__ */ jsxs5(
|
|
1807
2216
|
"select",
|
|
1808
2217
|
{
|
|
1809
2218
|
className: "june-doc__select june-doc__select--size",
|
|
@@ -1816,21 +2225,21 @@ function DocumentToolbar(props) {
|
|
|
1816
2225
|
else run()?.unsetFontSize().run();
|
|
1817
2226
|
},
|
|
1818
2227
|
children: [
|
|
1819
|
-
/* @__PURE__ */
|
|
1820
|
-
sizes.map((n) => /* @__PURE__ */
|
|
2228
|
+
/* @__PURE__ */ jsx8("option", { value: "", children: "Auto" }),
|
|
2229
|
+
sizes.map((n) => /* @__PURE__ */ jsx8("option", { value: String(n), children: n }, n))
|
|
1821
2230
|
]
|
|
1822
2231
|
}
|
|
1823
2232
|
) })
|
|
1824
2233
|
] }),
|
|
1825
|
-
/* @__PURE__ */
|
|
2234
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Show formatting marks", icon: "pilcrow", toggle: true, active: showMarks, onClick: onToggleMarks, text: true, className: "june-doc__btn--marks", children: /* @__PURE__ */ jsx8("span", { children: "Paragraph" }) }),
|
|
1826
2235
|
/* @__PURE__ */ jsxs5(Group, { label: "Document", children: [
|
|
1827
|
-
/* @__PURE__ */
|
|
1828
|
-
/* @__PURE__ */
|
|
1829
|
-
/* @__PURE__ */
|
|
1830
|
-
/* @__PURE__ */
|
|
2236
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Insert page break", icon: "pageBreak", disabled: off, onClick: () => run()?.setPageBreak().run() }),
|
|
2237
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Insert divider", icon: "divider", disabled: off, onClick: () => run()?.setHorizontalRule().run() }),
|
|
2238
|
+
/* @__PURE__ */ jsx8(Btn, { label: layout === "page" ? "Switch to full-width layout" : "Switch to page layout", icon: "layout", toggle: true, active: layout === "fluid", onClick: onToggleLayout }),
|
|
2239
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Find and replace", icon: "search", toggle: true, active: findOpen, onClick: onToggleFind })
|
|
1831
2240
|
] }),
|
|
1832
2241
|
/* @__PURE__ */ jsxs5(Group, { label: "Color", children: [
|
|
1833
|
-
/* @__PURE__ */
|
|
2242
|
+
/* @__PURE__ */ jsx8(
|
|
1834
2243
|
ColorPicker,
|
|
1835
2244
|
{
|
|
1836
2245
|
label: "Text color",
|
|
@@ -1843,7 +2252,7 @@ function DocumentToolbar(props) {
|
|
|
1843
2252
|
onReset: () => run()?.unsetColor().run()
|
|
1844
2253
|
}
|
|
1845
2254
|
),
|
|
1846
|
-
/* @__PURE__ */
|
|
2255
|
+
/* @__PURE__ */ jsx8(
|
|
1847
2256
|
ColorPicker,
|
|
1848
2257
|
{
|
|
1849
2258
|
label: "Highlight",
|
|
@@ -1858,33 +2267,33 @@ function DocumentToolbar(props) {
|
|
|
1858
2267
|
)
|
|
1859
2268
|
] }),
|
|
1860
2269
|
/* @__PURE__ */ jsxs5(Group, { label: "Insert", children: [
|
|
1861
|
-
editor ? /* @__PURE__ */
|
|
2270
|
+
editor ? /* @__PURE__ */ jsx8(
|
|
1862
2271
|
Dropdown,
|
|
1863
2272
|
{
|
|
1864
|
-
trigger: ({ open, toggle }) => /* @__PURE__ */
|
|
1865
|
-
children: (close) => /* @__PURE__ */
|
|
2273
|
+
trigger: ({ open, toggle }) => /* @__PURE__ */ jsx8(Btn, { label: "Link", icon: "link", toggle: true, active: s?.link || open, disabled: off, onClick: toggle }),
|
|
2274
|
+
children: (close) => /* @__PURE__ */ jsx8(LinkPanel, { editor, href: s?.linkHref ?? "", isLink: !!s?.link, close })
|
|
1866
2275
|
}
|
|
1867
2276
|
) : null,
|
|
1868
|
-
editor ? /* @__PURE__ */
|
|
1869
|
-
editor ? /* @__PURE__ */
|
|
2277
|
+
editor ? /* @__PURE__ */ jsx8(Dropdown, { trigger: ({ open, toggle }) => /* @__PURE__ */ jsx8(Btn, { label: "Insert image", icon: "image", active: open, disabled: off, onClick: toggle }), children: (close) => /* @__PURE__ */ jsx8(ImagePanel, { editor, close, onNotice }) }) : null,
|
|
2278
|
+
editor ? /* @__PURE__ */ jsx8(Dropdown, { trigger: ({ open, toggle }) => /* @__PURE__ */ jsx8(Btn, { label: "Insert table", icon: "table", active: open, disabled: off, onClick: toggle }), children: (close) => /* @__PURE__ */ jsx8(TablePanel, { editor, close }) }) : null
|
|
1870
2279
|
] }),
|
|
1871
|
-
/* @__PURE__ */
|
|
2280
|
+
/* @__PURE__ */ jsx8(Group, { label: "Actions", children: /* @__PURE__ */ jsx8(Btn, { label: "Clear formatting", icon: "eraser", disabled: off, onClick: () => run()?.unsetAllMarks().clearNodes().run() }) })
|
|
1872
2281
|
] }) : null,
|
|
1873
|
-
s?.inTable ? /* @__PURE__ */
|
|
1874
|
-
/* @__PURE__ */
|
|
1875
|
-
/* @__PURE__ */
|
|
1876
|
-
/* @__PURE__ */
|
|
1877
|
-
/* @__PURE__ */
|
|
1878
|
-
/* @__PURE__ */
|
|
1879
|
-
/* @__PURE__ */
|
|
1880
|
-
/* @__PURE__ */
|
|
1881
|
-
/* @__PURE__ */
|
|
2282
|
+
s?.inTable ? /* @__PURE__ */ jsx8("div", { className: "june-doc__row june-doc__row--context", children: /* @__PURE__ */ jsxs5(Group, { label: "Table", children: [
|
|
2283
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Add row below", disabled: off, onClick: () => run()?.addRowAfter().run(), children: "+ Row" }),
|
|
2284
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Add column right", disabled: off, onClick: () => run()?.addColumnAfter().run(), children: "+ Column" }),
|
|
2285
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Delete row", disabled: off, onClick: () => run()?.deleteRow().run(), children: "\u2212 Row" }),
|
|
2286
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Delete column", disabled: off, onClick: () => run()?.deleteColumn().run(), children: "\u2212 Column" }),
|
|
2287
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Merge cells", disabled: off || !s?.canMerge, onClick: () => run()?.mergeCells().run(), children: "Merge" }),
|
|
2288
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Split cell", disabled: off || !s?.canSplit, onClick: () => run()?.splitCell().run(), children: "Split" }),
|
|
2289
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Toggle header row", disabled: off, onClick: () => run()?.toggleHeaderRow().run(), children: "Header row" }),
|
|
2290
|
+
/* @__PURE__ */ jsx8(Btn, { label: "Delete table", disabled: off, onClick: () => run()?.deleteTable().run(), className: "june-doc__btn--danger", children: "Delete table" })
|
|
1882
2291
|
] }) }) : null
|
|
1883
2292
|
] });
|
|
1884
2293
|
}
|
|
1885
2294
|
|
|
1886
2295
|
// src/components/document-editor/document-bubble.tsx
|
|
1887
|
-
import { jsx as
|
|
2296
|
+
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1888
2297
|
function DocumentBubbleMenu({ editor }) {
|
|
1889
2298
|
const s = useEditorState2({
|
|
1890
2299
|
editor,
|
|
@@ -1913,13 +2322,13 @@ function DocumentBubbleMenu({ editor }) {
|
|
|
1913
2322
|
return state.doc.textBetween(state.selection.from, state.selection.to).trim().length > 0;
|
|
1914
2323
|
},
|
|
1915
2324
|
children: [
|
|
1916
|
-
/* @__PURE__ */
|
|
1917
|
-
/* @__PURE__ */
|
|
1918
|
-
/* @__PURE__ */
|
|
1919
|
-
/* @__PURE__ */
|
|
1920
|
-
/* @__PURE__ */
|
|
1921
|
-
/* @__PURE__ */
|
|
1922
|
-
/* @__PURE__ */
|
|
2325
|
+
/* @__PURE__ */ jsx9(Btn, { label: "Bold", icon: "bold", toggle: true, active: s.bold, onClick: () => run().toggleBold().run() }),
|
|
2326
|
+
/* @__PURE__ */ jsx9(Btn, { label: "Italic", icon: "italic", toggle: true, active: s.italic, onClick: () => run().toggleItalic().run() }),
|
|
2327
|
+
/* @__PURE__ */ jsx9(Btn, { label: "Underline", icon: "underline", toggle: true, active: s.underline, onClick: () => run().toggleUnderline().run() }),
|
|
2328
|
+
/* @__PURE__ */ jsx9(Btn, { label: "Strikethrough", icon: "strike", toggle: true, active: s.strike, onClick: () => run().toggleStrike().run() }),
|
|
2329
|
+
/* @__PURE__ */ jsx9("span", { className: "june-doc__bubble-sep", "aria-hidden": "true" }),
|
|
2330
|
+
/* @__PURE__ */ jsx9(Dropdown, { trigger: ({ open, toggle }) => /* @__PURE__ */ jsx9(Btn, { label: "Link", icon: "link", toggle: true, active: s.link || open, onClick: toggle }), children: (close) => /* @__PURE__ */ jsx9(LinkPanel, { editor, href: s.linkHref, isLink: s.link, close }) }),
|
|
2331
|
+
/* @__PURE__ */ jsx9(
|
|
1923
2332
|
ColorPicker,
|
|
1924
2333
|
{
|
|
1925
2334
|
label: "Text color",
|
|
@@ -1931,7 +2340,7 @@ function DocumentBubbleMenu({ editor }) {
|
|
|
1931
2340
|
onReset: () => run().unsetColor().run()
|
|
1932
2341
|
}
|
|
1933
2342
|
),
|
|
1934
|
-
/* @__PURE__ */
|
|
2343
|
+
/* @__PURE__ */ jsx9(
|
|
1935
2344
|
ColorPicker,
|
|
1936
2345
|
{
|
|
1937
2346
|
label: "Highlight",
|
|
@@ -1943,8 +2352,8 @@ function DocumentBubbleMenu({ editor }) {
|
|
|
1943
2352
|
onReset: () => run().unsetHighlight().run()
|
|
1944
2353
|
}
|
|
1945
2354
|
),
|
|
1946
|
-
/* @__PURE__ */
|
|
1947
|
-
/* @__PURE__ */
|
|
2355
|
+
/* @__PURE__ */ jsx9("span", { className: "june-doc__bubble-sep", "aria-hidden": "true" }),
|
|
2356
|
+
/* @__PURE__ */ jsx9(Btn, { label: "Clear formatting", icon: "eraser", onClick: () => run().unsetAllMarks().run() })
|
|
1948
2357
|
]
|
|
1949
2358
|
}
|
|
1950
2359
|
);
|
|
@@ -1952,60 +2361,116 @@ function DocumentBubbleMenu({ editor }) {
|
|
|
1952
2361
|
|
|
1953
2362
|
// src/components/document-editor/document-content.tsx
|
|
1954
2363
|
import { EditorContent } from "@tiptap/react";
|
|
1955
|
-
import { useEffect as
|
|
1956
|
-
import { jsx as
|
|
2364
|
+
import { useEffect as useEffect4, useLayoutEffect, useRef as useRef5, useState as useState4 } from "react";
|
|
2365
|
+
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2366
|
+
var PAGE_WIDTH = 794;
|
|
1957
2367
|
var PAGE_HEIGHT = 1123;
|
|
1958
|
-
var
|
|
2368
|
+
var PAGE_GAP = 28;
|
|
2369
|
+
var CANVAS_PAD_X = 24;
|
|
2370
|
+
var useIsoLayoutEffect = typeof window === "undefined" ? useEffect4 : useLayoutEffect;
|
|
2371
|
+
function geometry(width) {
|
|
2372
|
+
const ratio = width / PAGE_WIDTH;
|
|
2373
|
+
const height = Math.round(PAGE_HEIGHT * ratio);
|
|
2374
|
+
const padX = Math.round(Math.min(96, Math.max(20, width * 0.12)));
|
|
2375
|
+
const padY = Math.round(Math.min(96, Math.max(36, 96 * ratio)));
|
|
2376
|
+
return { width, height, padX, padY };
|
|
2377
|
+
}
|
|
1959
2378
|
function DocumentContent({ editor, layout = "page", zoom = 1, showMarks = false, onMetrics }) {
|
|
1960
2379
|
const canvas = useRef5(null);
|
|
1961
2380
|
const sheet = useRef5(null);
|
|
2381
|
+
const [avail, setAvail] = useState4(PAGE_WIDTH);
|
|
2382
|
+
const [sheetH, setSheetH] = useState4(0);
|
|
1962
2383
|
const [pages, setPages] = useState4(1);
|
|
1963
2384
|
const metricsRef = useRef5(onMetrics);
|
|
1964
2385
|
metricsRef.current = onMetrics;
|
|
1965
2386
|
const last = useRef5({ page: 0, pages: 0 });
|
|
1966
|
-
|
|
2387
|
+
const paged = layout === "page";
|
|
2388
|
+
const width = paged ? Math.max(260, Math.min(PAGE_WIDTH, Math.floor(avail / zoom))) : Math.max(260, Math.floor(avail / zoom));
|
|
2389
|
+
const g = geometry(width);
|
|
2390
|
+
const stride = g.height + PAGE_GAP;
|
|
2391
|
+
useIsoLayoutEffect(() => {
|
|
1967
2392
|
const c = canvas.current;
|
|
1968
|
-
|
|
1969
|
-
const
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
const
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
2393
|
+
if (!c) return;
|
|
2394
|
+
const read = () => {
|
|
2395
|
+
const cs = typeof getComputedStyle === "function" ? getComputedStyle(c) : null;
|
|
2396
|
+
const padX = cs ? (parseFloat(cs.paddingLeft) || 0) + (parseFloat(cs.paddingRight) || 0) : CANVAS_PAD_X * 2;
|
|
2397
|
+
const w = c.clientWidth - padX;
|
|
2398
|
+
if (w > 0) setAvail(w);
|
|
2399
|
+
};
|
|
2400
|
+
read();
|
|
2401
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
2402
|
+
const ro = new ResizeObserver(read);
|
|
2403
|
+
ro.observe(c);
|
|
2404
|
+
return () => ro.disconnect();
|
|
2405
|
+
}, []);
|
|
2406
|
+
useEffect4(() => {
|
|
2407
|
+
if (!editor) return;
|
|
2408
|
+
setPaginationConfig(editor, {
|
|
2409
|
+
enabled: paged,
|
|
2410
|
+
pageHeight: g.height,
|
|
2411
|
+
gap: PAGE_GAP,
|
|
2412
|
+
padTop: g.padY,
|
|
2413
|
+
padBottom: g.padY
|
|
2414
|
+
});
|
|
2415
|
+
}, [editor, paged, g.height, g.padY, width]);
|
|
2416
|
+
useEffect4(() => {
|
|
2417
|
+
const c = canvas.current;
|
|
2418
|
+
const s = sheet.current;
|
|
2419
|
+
if (!editor || !c || !s) return;
|
|
2420
|
+
const prose = editor.view.dom;
|
|
2421
|
+
const report = () => {
|
|
2422
|
+
const total = paged ? getPageCount(editor) : 1;
|
|
1978
2423
|
setPages(total);
|
|
2424
|
+
setSheetH(s.offsetHeight);
|
|
2425
|
+
const cRect = c.getBoundingClientRect();
|
|
2426
|
+
const sRect = s.getBoundingClientRect();
|
|
2427
|
+
const y = (cRect.top + c.clientHeight * 0.35 - sRect.top) / zoom;
|
|
2428
|
+
const page = paged ? Math.min(total, Math.max(1, Math.floor(y / stride) + 1)) : 1;
|
|
1979
2429
|
if (last.current.page !== page || last.current.pages !== total) {
|
|
1980
2430
|
last.current = { page, pages: total };
|
|
1981
2431
|
metricsRef.current?.({ page, pages: total });
|
|
1982
2432
|
}
|
|
1983
2433
|
};
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
2434
|
+
report();
|
|
2435
|
+
editor.on("transaction", report);
|
|
2436
|
+
c.addEventListener("scroll", report, { passive: true });
|
|
2437
|
+
const onLoad = () => remeasurePagination(editor);
|
|
2438
|
+
prose.addEventListener("load", onLoad, true);
|
|
2439
|
+
const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(report) : null;
|
|
2440
|
+
ro?.observe(s);
|
|
1990
2441
|
return () => {
|
|
1991
|
-
|
|
2442
|
+
editor.off("transaction", report);
|
|
2443
|
+
c.removeEventListener("scroll", report);
|
|
2444
|
+
prose.removeEventListener("load", onLoad, true);
|
|
1992
2445
|
ro?.disconnect();
|
|
1993
|
-
editor?.off("update", measure);
|
|
1994
2446
|
};
|
|
1995
|
-
}, [editor,
|
|
1996
|
-
const
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2447
|
+
}, [editor, paged, zoom, stride]);
|
|
2448
|
+
const minHeight = paged ? pages * g.height + (pages - 1) * PAGE_GAP : void 0;
|
|
2449
|
+
const sheetStyle = {
|
|
2450
|
+
width,
|
|
2451
|
+
minHeight,
|
|
2452
|
+
transform: zoom === 1 ? void 0 : `scale(${zoom})`,
|
|
2453
|
+
"--jd-pad-x": `${g.padX}px`,
|
|
2454
|
+
"--jd-pad-y": `${g.padY}px`
|
|
2455
|
+
};
|
|
2456
|
+
const zoomerStyle = {
|
|
2457
|
+
width: width * zoom,
|
|
2458
|
+
height: zoom === 1 ? void 0 : Math.max(sheetH, minHeight ?? 0) * zoom
|
|
2459
|
+
};
|
|
2460
|
+
return /* @__PURE__ */ jsx10("div", { ref: canvas, className: "june-doc__content june-doc__canvas", "data-layout": layout, "data-marks": showMarks || void 0, children: /* @__PURE__ */ jsx10("div", { className: "june-doc__zoomer", style: zoomerStyle, children: /* @__PURE__ */ jsxs7("div", { ref: sheet, className: "june-doc__sheet", style: sheetStyle, children: [
|
|
2461
|
+
paged ? /* @__PURE__ */ jsx10("div", { className: "june-doc__pages", "aria-hidden": "true", children: Array.from({ length: pages }, (_, i) => /* @__PURE__ */ jsx10("div", { className: "june-doc__page", style: { top: i * stride, height: g.height }, children: /* @__PURE__ */ jsxs7("span", { className: "june-doc__page-num", children: [
|
|
2462
|
+
i + 1,
|
|
2463
|
+
" / ",
|
|
2464
|
+
pages
|
|
2465
|
+
] }) }, i)) }) : null,
|
|
2466
|
+
/* @__PURE__ */ jsx10(EditorContent, { editor })
|
|
2467
|
+
] }) }) });
|
|
2003
2468
|
}
|
|
2004
2469
|
|
|
2005
2470
|
// src/components/document-editor/document-findbar.tsx
|
|
2006
2471
|
import { useEditorState as useEditorState3 } from "@tiptap/react";
|
|
2007
|
-
import { useEffect as
|
|
2008
|
-
import { Fragment as Fragment3, jsx as
|
|
2472
|
+
import { useEffect as useEffect5, useRef as useRef6, useState as useState5 } from "react";
|
|
2473
|
+
import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2009
2474
|
function DocumentFindBar({ editor, editable, onClose, onNotice }) {
|
|
2010
2475
|
const [term, setTerm] = useState5(() => {
|
|
2011
2476
|
const { from, to, empty } = editor.state.selection;
|
|
@@ -2021,19 +2486,19 @@ function DocumentFindBar({ editor, editable, onClose, onNotice }) {
|
|
|
2021
2486
|
return { count: s?.matches.length ?? 0, current: s?.current ?? -1 };
|
|
2022
2487
|
}
|
|
2023
2488
|
});
|
|
2024
|
-
|
|
2489
|
+
useEffect5(() => {
|
|
2025
2490
|
input.current?.focus();
|
|
2026
2491
|
input.current?.select();
|
|
2027
2492
|
}, []);
|
|
2028
|
-
|
|
2493
|
+
useEffect5(() => {
|
|
2029
2494
|
setSearch(editor, { term, caseSensitive, current: 0 });
|
|
2030
2495
|
}, [editor, term, caseSensitive]);
|
|
2031
|
-
|
|
2496
|
+
useEffect5(() => () => {
|
|
2032
2497
|
if (!editor.isDestroyed) setSearch(editor, { term: "" });
|
|
2033
2498
|
}, [editor]);
|
|
2034
2499
|
const count = info?.count ?? 0;
|
|
2035
2500
|
const current = info?.current ?? -1;
|
|
2036
|
-
return /* @__PURE__ */
|
|
2501
|
+
return /* @__PURE__ */ jsxs8(
|
|
2037
2502
|
"div",
|
|
2038
2503
|
{
|
|
2039
2504
|
className: "june-doc__findbar",
|
|
@@ -2046,9 +2511,9 @@ function DocumentFindBar({ editor, editable, onClose, onNotice }) {
|
|
|
2046
2511
|
}
|
|
2047
2512
|
},
|
|
2048
2513
|
children: [
|
|
2049
|
-
/* @__PURE__ */
|
|
2050
|
-
/* @__PURE__ */
|
|
2051
|
-
/* @__PURE__ */
|
|
2514
|
+
/* @__PURE__ */ jsxs8("div", { className: "june-doc__find-field", children: [
|
|
2515
|
+
/* @__PURE__ */ jsx11(Icon, { name: "search", size: 14 }),
|
|
2516
|
+
/* @__PURE__ */ jsx11(
|
|
2052
2517
|
"input",
|
|
2053
2518
|
{
|
|
2054
2519
|
ref: input,
|
|
@@ -2065,11 +2530,11 @@ function DocumentFindBar({ editor, editable, onClose, onNotice }) {
|
|
|
2065
2530
|
}
|
|
2066
2531
|
}
|
|
2067
2532
|
),
|
|
2068
|
-
/* @__PURE__ */
|
|
2533
|
+
/* @__PURE__ */ jsx11("span", { className: "june-doc__find-count", "aria-live": "polite", children: term ? count ? `${current + 1} of ${count}` : "No results" : "" })
|
|
2069
2534
|
] }),
|
|
2070
|
-
/* @__PURE__ */
|
|
2071
|
-
/* @__PURE__ */
|
|
2072
|
-
/* @__PURE__ */
|
|
2535
|
+
/* @__PURE__ */ jsx11("button", { type: "button", className: "june-doc__btn june-doc__btn--icon", "aria-label": "Previous match", title: "Previous (Shift+Enter)", disabled: !count, onClick: () => gotoMatch(editor, -1), children: /* @__PURE__ */ jsx11(Icon, { name: "chevronUp" }) }),
|
|
2536
|
+
/* @__PURE__ */ jsx11("button", { type: "button", className: "june-doc__btn june-doc__btn--icon", "aria-label": "Next match", title: "Next (Enter)", disabled: !count, onClick: () => gotoMatch(editor, 1), children: /* @__PURE__ */ jsx11(Icon, { name: "chevronDown" }) }),
|
|
2537
|
+
/* @__PURE__ */ jsx11(
|
|
2073
2538
|
"button",
|
|
2074
2539
|
{
|
|
2075
2540
|
type: "button",
|
|
@@ -2082,9 +2547,9 @@ function DocumentFindBar({ editor, editable, onClose, onNotice }) {
|
|
|
2082
2547
|
children: "Aa"
|
|
2083
2548
|
}
|
|
2084
2549
|
),
|
|
2085
|
-
editable ? /* @__PURE__ */
|
|
2086
|
-
/* @__PURE__ */
|
|
2087
|
-
/* @__PURE__ */
|
|
2550
|
+
editable ? /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
2551
|
+
/* @__PURE__ */ jsx11("span", { className: "june-doc__find-sep", "aria-hidden": "true" }),
|
|
2552
|
+
/* @__PURE__ */ jsx11(
|
|
2088
2553
|
"input",
|
|
2089
2554
|
{
|
|
2090
2555
|
className: "june-doc__input june-doc__replace-input",
|
|
@@ -2100,8 +2565,8 @@ function DocumentFindBar({ editor, editable, onClose, onNotice }) {
|
|
|
2100
2565
|
}
|
|
2101
2566
|
}
|
|
2102
2567
|
),
|
|
2103
|
-
/* @__PURE__ */
|
|
2104
|
-
/* @__PURE__ */
|
|
2568
|
+
/* @__PURE__ */ jsx11("button", { type: "button", className: "june-doc__btn", disabled: !count, onClick: () => replaceCurrent(editor, replacement), children: "Replace" }),
|
|
2569
|
+
/* @__PURE__ */ jsx11(
|
|
2105
2570
|
"button",
|
|
2106
2571
|
{
|
|
2107
2572
|
type: "button",
|
|
@@ -2115,16 +2580,16 @@ function DocumentFindBar({ editor, editable, onClose, onNotice }) {
|
|
|
2115
2580
|
}
|
|
2116
2581
|
)
|
|
2117
2582
|
] }) : null,
|
|
2118
|
-
/* @__PURE__ */
|
|
2583
|
+
/* @__PURE__ */ jsx11("button", { type: "button", className: "june-doc__btn june-doc__btn--icon june-doc__btn--ghost june-doc__find-close", "aria-label": "Close find", onClick: onClose, children: /* @__PURE__ */ jsx11(Icon, { name: "close" }) })
|
|
2119
2584
|
]
|
|
2120
2585
|
}
|
|
2121
2586
|
);
|
|
2122
2587
|
}
|
|
2123
2588
|
|
|
2124
2589
|
// src/components/document-editor/document-title.tsx
|
|
2125
|
-
import { jsx as
|
|
2590
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
2126
2591
|
function DocumentTitle({ value, disabled, onChange }) {
|
|
2127
|
-
return /* @__PURE__ */
|
|
2592
|
+
return /* @__PURE__ */ jsx12(
|
|
2128
2593
|
"input",
|
|
2129
2594
|
{
|
|
2130
2595
|
className: "june-doc__title",
|
|
@@ -2138,7 +2603,7 @@ function DocumentTitle({ value, disabled, onChange }) {
|
|
|
2138
2603
|
}
|
|
2139
2604
|
|
|
2140
2605
|
// src/components/document-editor/document-header.tsx
|
|
2141
|
-
import { jsx as
|
|
2606
|
+
import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
2142
2607
|
var FORMATS = {
|
|
2143
2608
|
docx: { label: "Word document", hint: ".docx", icon: "file" },
|
|
2144
2609
|
pdf: { label: "PDF", hint: "Print / Save as PDF", icon: "file" },
|
|
@@ -2147,36 +2612,37 @@ var FORMATS = {
|
|
|
2147
2612
|
txt: { label: "Plain text", hint: ".txt", icon: "file" }
|
|
2148
2613
|
};
|
|
2149
2614
|
function DocumentHeader(props) {
|
|
2150
|
-
const { title, editable, isDraft, fullscreen, onToggleFullscreen, onTitle, exportFormats, canSave, saveState, onExport, onCopy, onSave } = props;
|
|
2151
|
-
return /* @__PURE__ */
|
|
2152
|
-
fullscreen ? /* @__PURE__ */
|
|
2153
|
-
/* @__PURE__ */
|
|
2154
|
-
isDraft ? /* @__PURE__ */
|
|
2155
|
-
/* @__PURE__ */
|
|
2615
|
+
const { title, editable, isDraft, fullscreen, onToggleFullscreen, onTitle, exportFormats, canSave, showSave = canSave, saveState, onExport, onCopy, onSave } = props;
|
|
2616
|
+
return /* @__PURE__ */ jsxs9("div", { className: "june-doc__header", children: [
|
|
2617
|
+
fullscreen ? /* @__PURE__ */ jsx13("button", { type: "button", className: "june-doc__btn june-doc__btn--icon june-doc__btn--ghost", "aria-label": "Close full screen", title: "Close (Esc)", onClick: onToggleFullscreen, children: /* @__PURE__ */ jsx13(Icon, { name: "close", size: 18 }) }) : /* @__PURE__ */ jsx13("span", { className: "june-doc__doc-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx13(Icon, { name: "file", size: 16 }) }),
|
|
2618
|
+
/* @__PURE__ */ jsx13(DocumentTitle, { value: title, disabled: !editable, onChange: onTitle }),
|
|
2619
|
+
isDraft ? /* @__PURE__ */ jsxs9("span", { className: "june-doc__badge", children: [
|
|
2620
|
+
/* @__PURE__ */ jsx13(Icon, { name: "sparkles", size: 12 }),
|
|
2156
2621
|
"AI draft"
|
|
2157
2622
|
] }) : null,
|
|
2158
|
-
/* @__PURE__ */
|
|
2159
|
-
|
|
2623
|
+
/* @__PURE__ */ jsxs9("div", { className: "june-doc__header-actions", children: [
|
|
2624
|
+
showSave ? /* @__PURE__ */ jsxs9(
|
|
2160
2625
|
"button",
|
|
2161
2626
|
{
|
|
2162
2627
|
type: "button",
|
|
2163
|
-
className: "june-doc__btn june-doc__btn--outline",
|
|
2628
|
+
className: "june-doc__btn june-doc__btn--outline june-doc__save",
|
|
2629
|
+
"data-state": saveState,
|
|
2164
2630
|
"aria-label": "Save",
|
|
2165
2631
|
title: "Save (Ctrl+S)",
|
|
2166
2632
|
disabled: saveState === "saving" || saveState === "saved" || saveState === "idle",
|
|
2167
2633
|
onClick: onSave,
|
|
2168
2634
|
children: [
|
|
2169
|
-
/* @__PURE__ */
|
|
2170
|
-
/* @__PURE__ */
|
|
2635
|
+
/* @__PURE__ */ jsx13(Icon, { name: saveState === "saved" ? "check" : "save" }),
|
|
2636
|
+
/* @__PURE__ */ jsx13("span", { children: saveState === "saving" ? "Saving\u2026" : saveState === "saved" ? "Saved" : "Save" })
|
|
2171
2637
|
]
|
|
2172
2638
|
}
|
|
2173
2639
|
) : null,
|
|
2174
|
-
/* @__PURE__ */
|
|
2640
|
+
/* @__PURE__ */ jsx13(
|
|
2175
2641
|
Dropdown,
|
|
2176
2642
|
{
|
|
2177
2643
|
align: "end",
|
|
2178
2644
|
className: "june-doc__menu",
|
|
2179
|
-
trigger: ({ open, toggle }) => /* @__PURE__ */
|
|
2645
|
+
trigger: ({ open, toggle }) => /* @__PURE__ */ jsxs9(
|
|
2180
2646
|
"button",
|
|
2181
2647
|
{
|
|
2182
2648
|
type: "button",
|
|
@@ -2186,15 +2652,15 @@ function DocumentHeader(props) {
|
|
|
2186
2652
|
"aria-expanded": open,
|
|
2187
2653
|
onClick: toggle,
|
|
2188
2654
|
children: [
|
|
2189
|
-
/* @__PURE__ */
|
|
2190
|
-
/* @__PURE__ */
|
|
2655
|
+
/* @__PURE__ */ jsx13("span", { children: "Download" }),
|
|
2656
|
+
/* @__PURE__ */ jsx13(Icon, { name: "chevronDown", size: 14 })
|
|
2191
2657
|
]
|
|
2192
2658
|
}
|
|
2193
2659
|
),
|
|
2194
|
-
children: (close) => /* @__PURE__ */
|
|
2660
|
+
children: (close) => /* @__PURE__ */ jsxs9("div", { role: "menu", "aria-label": "Download options", children: [
|
|
2195
2661
|
exportFormats.map((f) => {
|
|
2196
2662
|
const meta = FORMATS[f] ?? { label: f.toUpperCase(), hint: "", icon: "file" };
|
|
2197
|
-
return /* @__PURE__ */
|
|
2663
|
+
return /* @__PURE__ */ jsxs9(
|
|
2198
2664
|
"button",
|
|
2199
2665
|
{
|
|
2200
2666
|
type: "button",
|
|
@@ -2205,16 +2671,16 @@ function DocumentHeader(props) {
|
|
|
2205
2671
|
onExport(f);
|
|
2206
2672
|
},
|
|
2207
2673
|
children: [
|
|
2208
|
-
/* @__PURE__ */
|
|
2209
|
-
/* @__PURE__ */
|
|
2210
|
-
/* @__PURE__ */
|
|
2674
|
+
/* @__PURE__ */ jsx13(Icon, { name: meta.icon }),
|
|
2675
|
+
/* @__PURE__ */ jsx13("span", { className: "june-doc__menu-label", children: meta.label }),
|
|
2676
|
+
/* @__PURE__ */ jsx13("span", { className: "june-doc__menu-hint", children: meta.hint })
|
|
2211
2677
|
]
|
|
2212
2678
|
},
|
|
2213
2679
|
f
|
|
2214
2680
|
);
|
|
2215
2681
|
}),
|
|
2216
|
-
exportFormats.length ? /* @__PURE__ */
|
|
2217
|
-
/* @__PURE__ */
|
|
2682
|
+
exportFormats.length ? /* @__PURE__ */ jsx13("div", { className: "june-doc__menu-sep", role: "separator" }) : null,
|
|
2683
|
+
/* @__PURE__ */ jsxs9(
|
|
2218
2684
|
"button",
|
|
2219
2685
|
{
|
|
2220
2686
|
type: "button",
|
|
@@ -2226,15 +2692,15 @@ function DocumentHeader(props) {
|
|
|
2226
2692
|
onCopy();
|
|
2227
2693
|
},
|
|
2228
2694
|
children: [
|
|
2229
|
-
/* @__PURE__ */
|
|
2230
|
-
/* @__PURE__ */
|
|
2695
|
+
/* @__PURE__ */ jsx13(Icon, { name: "copy" }),
|
|
2696
|
+
/* @__PURE__ */ jsx13("span", { className: "june-doc__menu-label", children: "Copy to clipboard" })
|
|
2231
2697
|
]
|
|
2232
2698
|
}
|
|
2233
2699
|
)
|
|
2234
2700
|
] })
|
|
2235
2701
|
}
|
|
2236
2702
|
),
|
|
2237
|
-
/* @__PURE__ */
|
|
2703
|
+
/* @__PURE__ */ jsx13(
|
|
2238
2704
|
"button",
|
|
2239
2705
|
{
|
|
2240
2706
|
type: "button",
|
|
@@ -2243,7 +2709,7 @@ function DocumentHeader(props) {
|
|
|
2243
2709
|
title: fullscreen ? "Exit full screen" : "Open full screen",
|
|
2244
2710
|
"aria-pressed": fullscreen,
|
|
2245
2711
|
onClick: onToggleFullscreen,
|
|
2246
|
-
children: /* @__PURE__ */
|
|
2712
|
+
children: /* @__PURE__ */ jsx13(Icon, { name: "maximize" })
|
|
2247
2713
|
}
|
|
2248
2714
|
)
|
|
2249
2715
|
] })
|
|
@@ -2265,7 +2731,7 @@ var textResult = (text, filename, mimeType) => ({
|
|
|
2265
2731
|
blob: new Blob([text], { type: `${mimeType};charset=utf-8` })
|
|
2266
2732
|
});
|
|
2267
2733
|
var exportHtml = async (ctx) => {
|
|
2268
|
-
const { docToHtml: docToHtml2 } = await import("./document-engine-
|
|
2734
|
+
const { docToHtml: docToHtml2 } = await import("./document-engine-RKD5SLXR.js");
|
|
2269
2735
|
return textResult(
|
|
2270
2736
|
buildHtmlDocument(ctx.title, docToHtml2(ctx.json)),
|
|
2271
2737
|
`${ctx.basename}.html`,
|
|
@@ -2273,7 +2739,7 @@ var exportHtml = async (ctx) => {
|
|
|
2273
2739
|
);
|
|
2274
2740
|
};
|
|
2275
2741
|
var exportMarkdown = async (ctx) => {
|
|
2276
|
-
const { docToMarkdown: docToMarkdown2 } = await import("./document-engine-
|
|
2742
|
+
const { docToMarkdown: docToMarkdown2 } = await import("./document-engine-RKD5SLXR.js");
|
|
2277
2743
|
return textResult(
|
|
2278
2744
|
`# ${ctx.title}
|
|
2279
2745
|
|
|
@@ -2284,7 +2750,7 @@ ${docToMarkdown2(ctx.json)}
|
|
|
2284
2750
|
);
|
|
2285
2751
|
};
|
|
2286
2752
|
var exportTxt = async (ctx) => {
|
|
2287
|
-
const { docToText } = await import("./document-engine-
|
|
2753
|
+
const { docToText } = await import("./document-engine-RKD5SLXR.js");
|
|
2288
2754
|
return textResult(`${ctx.title}
|
|
2289
2755
|
|
|
2290
2756
|
${docToText(ctx.json)}
|
|
@@ -2606,7 +3072,7 @@ function printHtml(html) {
|
|
|
2606
3072
|
});
|
|
2607
3073
|
}
|
|
2608
3074
|
var exportPdf = async (ctx) => {
|
|
2609
|
-
const { docToHtml: docToHtml2 } = await import("./document-engine-
|
|
3075
|
+
const { docToHtml: docToHtml2 } = await import("./document-engine-RKD5SLXR.js");
|
|
2610
3076
|
await printHtml(buildHtmlDocument(ctx.title, docToHtml2(ctx.json)));
|
|
2611
3077
|
return { filename: `${ctx.basename}.pdf`, mimeType: "application/pdf", handled: true };
|
|
2612
3078
|
};
|
|
@@ -2644,7 +3110,7 @@ function downloadResult(result) {
|
|
|
2644
3110
|
setTimeout(() => URL.revokeObjectURL(url), 1e3);
|
|
2645
3111
|
}
|
|
2646
3112
|
async function copyDocumentToClipboard(doc) {
|
|
2647
|
-
const { docToHtml: docToHtml2, docToText } = await import("./document-engine-
|
|
3113
|
+
const { docToHtml: docToHtml2, docToText } = await import("./document-engine-RKD5SLXR.js");
|
|
2648
3114
|
const html = docToHtml2(doc.json);
|
|
2649
3115
|
const text = `${doc.title}
|
|
2650
3116
|
|
|
@@ -2666,221 +3132,6 @@ ${docToText(doc.json)}`;
|
|
|
2666
3132
|
}
|
|
2667
3133
|
}
|
|
2668
3134
|
|
|
2669
|
-
// src/components/document-editor/document-merge.ts
|
|
2670
|
-
var MAX_CELLS = 4e6;
|
|
2671
|
-
function matchIndices(a, b) {
|
|
2672
|
-
const n = a.length;
|
|
2673
|
-
const m = b.length;
|
|
2674
|
-
if (n * m > MAX_CELLS) return null;
|
|
2675
|
-
const dp = Array.from({ length: n + 1 }, () => new Uint32Array(m + 1));
|
|
2676
|
-
for (let i2 = n - 1; i2 >= 0; i2--) {
|
|
2677
|
-
for (let j2 = m - 1; j2 >= 0; j2--) {
|
|
2678
|
-
dp[i2][j2] = a[i2] === b[j2] ? dp[i2 + 1][j2 + 1] + 1 : Math.max(dp[i2 + 1][j2], dp[i2][j2 + 1]);
|
|
2679
|
-
}
|
|
2680
|
-
}
|
|
2681
|
-
const matches = /* @__PURE__ */ new Map();
|
|
2682
|
-
let i = 0;
|
|
2683
|
-
let j = 0;
|
|
2684
|
-
while (i < n && j < m) {
|
|
2685
|
-
if (a[i] === b[j]) {
|
|
2686
|
-
matches.set(i, j);
|
|
2687
|
-
i++;
|
|
2688
|
-
j++;
|
|
2689
|
-
} else if (dp[i + 1][j] >= dp[i][j + 1]) i++;
|
|
2690
|
-
else j++;
|
|
2691
|
-
}
|
|
2692
|
-
return matches;
|
|
2693
|
-
}
|
|
2694
|
-
var same = (x, y) => x.length === y.length && x.every((v, i) => v === y[i]);
|
|
2695
|
-
function mergeBlocks(base, local, incoming) {
|
|
2696
|
-
if (same(local, base)) return { blocks: incoming, conflicts: 0 };
|
|
2697
|
-
if (same(incoming, base) || same(local, incoming)) return { blocks: local, conflicts: 0 };
|
|
2698
|
-
const ml = matchIndices(base, local);
|
|
2699
|
-
const mn = matchIndices(base, incoming);
|
|
2700
|
-
if (!ml || !mn) return { blocks: null, conflicts: 1 };
|
|
2701
|
-
const anchors = [...ml.keys()].filter((i) => mn.has(i)).sort((x, y) => x - y);
|
|
2702
|
-
const out = [];
|
|
2703
|
-
let conflicts = 0;
|
|
2704
|
-
let pb = -1;
|
|
2705
|
-
let pl = -1;
|
|
2706
|
-
let pn = -1;
|
|
2707
|
-
const region = (bEnd, lEnd, nEnd) => {
|
|
2708
|
-
const B = base.slice(pb + 1, bEnd);
|
|
2709
|
-
const L = local.slice(pl + 1, lEnd);
|
|
2710
|
-
const N = incoming.slice(pn + 1, nEnd);
|
|
2711
|
-
if (B.length === L.length && L.length === N.length) {
|
|
2712
|
-
for (let k = 0; k < B.length; k++) {
|
|
2713
|
-
if (L[k] === B[k]) out.push(N[k]);
|
|
2714
|
-
else if (N[k] === B[k] || N[k] === L[k]) out.push(L[k]);
|
|
2715
|
-
else {
|
|
2716
|
-
conflicts++;
|
|
2717
|
-
out.push(L[k]);
|
|
2718
|
-
}
|
|
2719
|
-
}
|
|
2720
|
-
return;
|
|
2721
|
-
}
|
|
2722
|
-
if (same(L, B)) out.push(...N);
|
|
2723
|
-
else if (same(N, B) || same(L, N)) out.push(...L);
|
|
2724
|
-
else {
|
|
2725
|
-
conflicts++;
|
|
2726
|
-
out.push(...L);
|
|
2727
|
-
}
|
|
2728
|
-
};
|
|
2729
|
-
for (const a of anchors) {
|
|
2730
|
-
const la = ml.get(a);
|
|
2731
|
-
const na = mn.get(a);
|
|
2732
|
-
region(a, la, na);
|
|
2733
|
-
out.push(local[la]);
|
|
2734
|
-
pb = a;
|
|
2735
|
-
pl = la;
|
|
2736
|
-
pn = na;
|
|
2737
|
-
}
|
|
2738
|
-
region(base.length, local.length, incoming.length);
|
|
2739
|
-
return { blocks: out, conflicts };
|
|
2740
|
-
}
|
|
2741
|
-
function mergeDocuments(base, local, incoming) {
|
|
2742
|
-
const toBlocks = (d) => (d.content ?? []).map((node) => JSON.stringify(node));
|
|
2743
|
-
const { blocks: blocks2, conflicts } = mergeBlocks(toBlocks(base), toBlocks(local), toBlocks(incoming));
|
|
2744
|
-
if (!blocks2) return { doc: local, conflicts: Math.max(1, conflicts) };
|
|
2745
|
-
if (blocks2.length === 0) return { doc: emptyDoc(), conflicts };
|
|
2746
|
-
return { doc: { type: "doc", content: blocks2.map((b) => JSON.parse(b)) }, conflicts };
|
|
2747
|
-
}
|
|
2748
|
-
|
|
2749
|
-
// src/components/document-editor/document-store.ts
|
|
2750
|
-
var incomingKey = (doc) => JSON.stringify([doc.title, docKey(doc.json)]);
|
|
2751
|
-
function createDocumentStore() {
|
|
2752
|
-
const records = /* @__PURE__ */ new Map();
|
|
2753
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
2754
|
-
const emit = () => listeners.forEach((listener) => listener());
|
|
2755
|
-
const put = (record) => {
|
|
2756
|
-
records.set(record.id, record);
|
|
2757
|
-
emit();
|
|
2758
|
-
};
|
|
2759
|
-
const fresh2 = (doc) => ({
|
|
2760
|
-
id: doc.id,
|
|
2761
|
-
title: doc.title,
|
|
2762
|
-
documentType: doc.documentType,
|
|
2763
|
-
status: doc.status,
|
|
2764
|
-
json: doc.json,
|
|
2765
|
-
baseJson: doc.json,
|
|
2766
|
-
baseTitle: doc.title,
|
|
2767
|
-
lastIncomingKey: incomingKey(doc),
|
|
2768
|
-
revision: 0,
|
|
2769
|
-
origin: "external",
|
|
2770
|
-
pending: null,
|
|
2771
|
-
updatedAt: Date.now()
|
|
2772
|
-
});
|
|
2773
|
-
return {
|
|
2774
|
-
get: (id) => records.get(id),
|
|
2775
|
-
list: () => [...records.values()],
|
|
2776
|
-
subscribe: (listener) => {
|
|
2777
|
-
listeners.add(listener);
|
|
2778
|
-
return () => {
|
|
2779
|
-
listeners.delete(listener);
|
|
2780
|
-
};
|
|
2781
|
-
},
|
|
2782
|
-
receive(incoming) {
|
|
2783
|
-
const current = records.get(incoming.id);
|
|
2784
|
-
if (!current) {
|
|
2785
|
-
put(fresh2(incoming));
|
|
2786
|
-
return "created";
|
|
2787
|
-
}
|
|
2788
|
-
const key = incomingKey(incoming);
|
|
2789
|
-
if (current.lastIncomingKey === key) return "unchanged";
|
|
2790
|
-
const userEditedBody = docKey(current.json) !== docKey(current.baseJson);
|
|
2791
|
-
const userEditedTitle = current.title !== current.baseTitle;
|
|
2792
|
-
const title = userEditedTitle ? current.title : incoming.title;
|
|
2793
|
-
const meta = {
|
|
2794
|
-
documentType: incoming.documentType ?? current.documentType,
|
|
2795
|
-
status: incoming.status ?? current.status
|
|
2796
|
-
};
|
|
2797
|
-
if (!userEditedBody) {
|
|
2798
|
-
put({
|
|
2799
|
-
...current,
|
|
2800
|
-
...meta,
|
|
2801
|
-
title,
|
|
2802
|
-
baseTitle: incoming.title,
|
|
2803
|
-
json: incoming.json,
|
|
2804
|
-
baseJson: incoming.json,
|
|
2805
|
-
lastIncomingKey: key,
|
|
2806
|
-
revision: current.revision + 1,
|
|
2807
|
-
origin: "external",
|
|
2808
|
-
pending: null,
|
|
2809
|
-
updatedAt: Date.now()
|
|
2810
|
-
});
|
|
2811
|
-
return "applied";
|
|
2812
|
-
}
|
|
2813
|
-
const { doc, conflicts } = mergeDocuments(current.baseJson, current.json, incoming.json);
|
|
2814
|
-
if (conflicts === 0) {
|
|
2815
|
-
put({
|
|
2816
|
-
...current,
|
|
2817
|
-
...meta,
|
|
2818
|
-
title,
|
|
2819
|
-
baseTitle: incoming.title,
|
|
2820
|
-
json: doc,
|
|
2821
|
-
baseJson: incoming.json,
|
|
2822
|
-
lastIncomingKey: key,
|
|
2823
|
-
revision: current.revision + 1,
|
|
2824
|
-
origin: "external",
|
|
2825
|
-
pending: null,
|
|
2826
|
-
updatedAt: Date.now()
|
|
2827
|
-
});
|
|
2828
|
-
return "merged";
|
|
2829
|
-
}
|
|
2830
|
-
put({
|
|
2831
|
-
...current,
|
|
2832
|
-
...meta,
|
|
2833
|
-
lastIncomingKey: key,
|
|
2834
|
-
pending: { json: incoming.json, title: incoming.title, merged: doc, conflicts }
|
|
2835
|
-
});
|
|
2836
|
-
return "conflict";
|
|
2837
|
-
},
|
|
2838
|
-
hydrate(doc) {
|
|
2839
|
-
put(fresh2(doc));
|
|
2840
|
-
},
|
|
2841
|
-
edit(id, json, origin) {
|
|
2842
|
-
const current = records.get(id);
|
|
2843
|
-
if (!current || docKey(current.json) === docKey(json)) return;
|
|
2844
|
-
put({ ...current, json, origin, revision: current.revision + 1, updatedAt: Date.now() });
|
|
2845
|
-
},
|
|
2846
|
-
setTitle(id, title) {
|
|
2847
|
-
const current = records.get(id);
|
|
2848
|
-
if (!current || current.title === title) return;
|
|
2849
|
-
put({ ...current, title, updatedAt: Date.now() });
|
|
2850
|
-
},
|
|
2851
|
-
resolve(id, choice) {
|
|
2852
|
-
const current = records.get(id);
|
|
2853
|
-
const pending = current?.pending;
|
|
2854
|
-
if (!current || !pending) return;
|
|
2855
|
-
if (choice === "keep") {
|
|
2856
|
-
put({ ...current, baseJson: pending.json, baseTitle: pending.title, pending: null });
|
|
2857
|
-
return;
|
|
2858
|
-
}
|
|
2859
|
-
const json = choice === "merge" ? pending.merged : pending.json;
|
|
2860
|
-
const title = choice === "merge" ? current.title : pending.title;
|
|
2861
|
-
put({
|
|
2862
|
-
...current,
|
|
2863
|
-
title,
|
|
2864
|
-
json,
|
|
2865
|
-
baseJson: pending.json,
|
|
2866
|
-
baseTitle: pending.title,
|
|
2867
|
-
revision: current.revision + 1,
|
|
2868
|
-
origin: "external",
|
|
2869
|
-
pending: null,
|
|
2870
|
-
updatedAt: Date.now()
|
|
2871
|
-
});
|
|
2872
|
-
},
|
|
2873
|
-
remove(id) {
|
|
2874
|
-
if (records.delete(id)) emit();
|
|
2875
|
-
}
|
|
2876
|
-
};
|
|
2877
|
-
}
|
|
2878
|
-
var defaultStore = null;
|
|
2879
|
-
function getDefaultDocumentStore() {
|
|
2880
|
-
if (!defaultStore) defaultStore = createDocumentStore();
|
|
2881
|
-
return defaultStore;
|
|
2882
|
-
}
|
|
2883
|
-
|
|
2884
3135
|
// src/components/document-editor/document-types.ts
|
|
2885
3136
|
var ALL_EXPORT_FORMATS = [
|
|
2886
3137
|
"html",
|
|
@@ -2891,7 +3142,7 @@ var ALL_EXPORT_FORMATS = [
|
|
|
2891
3142
|
];
|
|
2892
3143
|
|
|
2893
3144
|
// src/components/document-editor/document-editor.tsx
|
|
2894
|
-
import { Fragment as Fragment4, jsx as
|
|
3145
|
+
import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2895
3146
|
var snapshotOf = (r) => ({
|
|
2896
3147
|
documentId: r.id,
|
|
2897
3148
|
title: r.title,
|
|
@@ -2937,7 +3188,7 @@ function DocumentEditorImpl(props) {
|
|
|
2937
3188
|
return { json: null, error: toJuneError(e, "DOCUMENT_ERROR") };
|
|
2938
3189
|
}
|
|
2939
3190
|
}, [contentKey]);
|
|
2940
|
-
|
|
3191
|
+
useEffect6(() => {
|
|
2941
3192
|
if (parsed.error) optionsRef.current.onError?.(parsed.error);
|
|
2942
3193
|
}, [parsed.error]);
|
|
2943
3194
|
const title = useDocumentValue(store, documentId, (r) => r?.title ?? titleProp);
|
|
@@ -2953,7 +3204,7 @@ function DocumentEditorImpl(props) {
|
|
|
2953
3204
|
const [findOpen, setFindOpen] = useState6(false);
|
|
2954
3205
|
const [zoom, setZoom] = useState6(1);
|
|
2955
3206
|
const [metrics, setMetrics] = useState6({ page: 1, pages: 1 });
|
|
2956
|
-
|
|
3207
|
+
useEffect6(() => {
|
|
2957
3208
|
if (!fullscreen || typeof document === "undefined") return;
|
|
2958
3209
|
const prev = document.body.style.overflow;
|
|
2959
3210
|
document.body.style.overflow = "hidden";
|
|
@@ -2967,7 +3218,7 @@ function DocumentEditorImpl(props) {
|
|
|
2967
3218
|
const flash = useCallback3((message) => {
|
|
2968
3219
|
setNotice(message);
|
|
2969
3220
|
}, []);
|
|
2970
|
-
|
|
3221
|
+
useEffect6(() => {
|
|
2971
3222
|
if (!notice) return;
|
|
2972
3223
|
const t = setTimeout(() => setNotice(null), 3e3);
|
|
2973
3224
|
return () => clearTimeout(t);
|
|
@@ -2985,12 +3236,17 @@ function DocumentEditorImpl(props) {
|
|
|
2985
3236
|
const delay = options.autosaveDelay ?? 1500;
|
|
2986
3237
|
return delay > 0 ? debounce(() => void saveRef.current(), delay) : null;
|
|
2987
3238
|
}, [options.autosaveDelay]);
|
|
2988
|
-
|
|
3239
|
+
useEffect6(() => () => autosave?.flush(), [autosave]);
|
|
2989
3240
|
saveRef.current = async () => {
|
|
2990
3241
|
const record = store.get(documentId);
|
|
2991
3242
|
const onSave = optionsRef.current.onSave;
|
|
2992
|
-
if (!record
|
|
3243
|
+
if (!record) return;
|
|
2993
3244
|
const key = JSON.stringify([record.title, docKey(record.json)]);
|
|
3245
|
+
if (!onSave) {
|
|
3246
|
+
lastSavedKey.current = key;
|
|
3247
|
+
setSaveState("saved");
|
|
3248
|
+
return;
|
|
3249
|
+
}
|
|
2994
3250
|
if (key === lastSavedKey.current) {
|
|
2995
3251
|
setSaveState("saved");
|
|
2996
3252
|
return;
|
|
@@ -3011,11 +3267,22 @@ function DocumentEditorImpl(props) {
|
|
|
3011
3267
|
optionsRef.current.onError?.(toJuneError(error, "DOCUMENT_ERROR", "Saving the document failed"));
|
|
3012
3268
|
}
|
|
3013
3269
|
};
|
|
3014
|
-
const markDirty = useCallback3(
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3270
|
+
const markDirty = useCallback3(
|
|
3271
|
+
(userEdit = true) => {
|
|
3272
|
+
if (!optionsRef.current.onSave) {
|
|
3273
|
+
if (userEdit) setSaveState("dirty");
|
|
3274
|
+
return;
|
|
3275
|
+
}
|
|
3276
|
+
setSaveState("dirty");
|
|
3277
|
+
autosave?.();
|
|
3278
|
+
},
|
|
3279
|
+
[autosave]
|
|
3280
|
+
);
|
|
3281
|
+
useEffect6(() => {
|
|
3282
|
+
if (saveState !== "saved" || options.onSave) return;
|
|
3283
|
+
const t = setTimeout(() => setSaveState((s) => s === "saved" ? "idle" : s), 2500);
|
|
3284
|
+
return () => clearTimeout(t);
|
|
3285
|
+
}, [saveState, options.onSave]);
|
|
3019
3286
|
const [initialJson] = useState6(() => store.get(documentId)?.json ?? parsed.json ?? emptyDoc());
|
|
3020
3287
|
const extensions = useMemo4(() => createDocumentExtensions(), []);
|
|
3021
3288
|
const onUpdateRef = useRef7(() => {
|
|
@@ -3040,11 +3307,13 @@ function DocumentEditorImpl(props) {
|
|
|
3040
3307
|
},
|
|
3041
3308
|
onUpdate: ({ editor: ed }) => onUpdateRef.current(ed.getJSON())
|
|
3042
3309
|
});
|
|
3043
|
-
|
|
3044
|
-
editor
|
|
3310
|
+
useEffect6(() => {
|
|
3311
|
+
if (!editor || editor.isEditable === editable) return;
|
|
3312
|
+
editor.setEditable(editable);
|
|
3045
3313
|
}, [editor, editable]);
|
|
3046
|
-
|
|
3314
|
+
useEffect6(() => {
|
|
3047
3315
|
if (!parsed.json) return;
|
|
3316
|
+
if (isDocumentEcho(store, documentId, contentKey)) return;
|
|
3048
3317
|
const outcome = store.receive({
|
|
3049
3318
|
id: documentId,
|
|
3050
3319
|
title: titleProp,
|
|
@@ -3054,7 +3323,7 @@ function DocumentEditorImpl(props) {
|
|
|
3054
3323
|
});
|
|
3055
3324
|
if (outcome === "applied" || outcome === "merged") {
|
|
3056
3325
|
emitChange(outcome === "applied" ? "ai" : "merge");
|
|
3057
|
-
markDirty();
|
|
3326
|
+
markDirty(false);
|
|
3058
3327
|
} else if (outcome === "conflict") {
|
|
3059
3328
|
const record = store.get(documentId);
|
|
3060
3329
|
optionsRef.current.onConflict?.({
|
|
@@ -3064,7 +3333,7 @@ function DocumentEditorImpl(props) {
|
|
|
3064
3333
|
});
|
|
3065
3334
|
}
|
|
3066
3335
|
}, [store, documentId, titleProp, parsed.json, documentType, status, emitChange, markDirty]);
|
|
3067
|
-
|
|
3336
|
+
useEffect6(() => {
|
|
3068
3337
|
if (!editor) return;
|
|
3069
3338
|
const apply = () => {
|
|
3070
3339
|
const record = store.get(documentId);
|
|
@@ -3081,7 +3350,7 @@ function DocumentEditorImpl(props) {
|
|
|
3081
3350
|
apply();
|
|
3082
3351
|
return store.subscribe(apply);
|
|
3083
3352
|
}, [editor, store, documentId, instanceId]);
|
|
3084
|
-
|
|
3353
|
+
useEffect6(() => {
|
|
3085
3354
|
if (!editor || readyRef.current) return;
|
|
3086
3355
|
const record = store.get(documentId);
|
|
3087
3356
|
if (!record) return;
|
|
@@ -3125,18 +3394,18 @@ function DocumentEditorImpl(props) {
|
|
|
3125
3394
|
};
|
|
3126
3395
|
const formats = (exportFormats ?? [...ALL_EXPORT_FORMATS]).filter((f) => listDocumentExporters().includes(f));
|
|
3127
3396
|
if (parsed.error && !store.get(documentId)) {
|
|
3128
|
-
return /* @__PURE__ */
|
|
3129
|
-
/* @__PURE__ */
|
|
3130
|
-
/* @__PURE__ */
|
|
3131
|
-
/* @__PURE__ */
|
|
3132
|
-
/* @__PURE__ */
|
|
3397
|
+
return /* @__PURE__ */ jsxs10("div", { className: "june-doc june-doc--error", "data-theme": resolvedTheme, role: "alert", children: [
|
|
3398
|
+
/* @__PURE__ */ jsx14("p", { className: "june-doc__draft-text", children: "This document could not be displayed." }),
|
|
3399
|
+
/* @__PURE__ */ jsxs10("details", { children: [
|
|
3400
|
+
/* @__PURE__ */ jsx14("summary", { children: "Show raw content" }),
|
|
3401
|
+
/* @__PURE__ */ jsx14("pre", { className: "june-doc__raw", children: contentKey })
|
|
3133
3402
|
] })
|
|
3134
3403
|
] });
|
|
3135
3404
|
}
|
|
3136
|
-
if (!editor) return /* @__PURE__ */
|
|
3405
|
+
if (!editor) return /* @__PURE__ */ jsx14(DocumentDraft, { title, state: "loading" });
|
|
3137
3406
|
const isDraft = recordStatus === "draft";
|
|
3138
3407
|
const classes = ["june-doc", fullscreen ? "june-doc--fullscreen" : "", className ?? ""].filter(Boolean).join(" ");
|
|
3139
|
-
return /* @__PURE__ */
|
|
3408
|
+
return /* @__PURE__ */ jsxs10(
|
|
3140
3409
|
"div",
|
|
3141
3410
|
{
|
|
3142
3411
|
className: classes,
|
|
@@ -3158,7 +3427,7 @@ function DocumentEditorImpl(props) {
|
|
|
3158
3427
|
}
|
|
3159
3428
|
},
|
|
3160
3429
|
children: [
|
|
3161
|
-
/* @__PURE__ */
|
|
3430
|
+
/* @__PURE__ */ jsx14(
|
|
3162
3431
|
DocumentHeader,
|
|
3163
3432
|
{
|
|
3164
3433
|
title,
|
|
@@ -3169,27 +3438,28 @@ function DocumentEditorImpl(props) {
|
|
|
3169
3438
|
onTitle: handleTitle,
|
|
3170
3439
|
exportFormats: formats,
|
|
3171
3440
|
canSave: !!options.onSave,
|
|
3441
|
+
showSave: !!options.onSave || editable && saveState !== "idle",
|
|
3172
3442
|
saveState,
|
|
3173
3443
|
onExport: (f) => void handleExport(f),
|
|
3174
3444
|
onCopy: () => void handleCopy(),
|
|
3175
3445
|
onSave: () => void saveRef.current()
|
|
3176
3446
|
}
|
|
3177
3447
|
),
|
|
3178
|
-
pending ? /* @__PURE__ */
|
|
3179
|
-
/* @__PURE__ */
|
|
3448
|
+
pending ? /* @__PURE__ */ jsxs10("div", { className: "june-doc__banner", role: "status", children: [
|
|
3449
|
+
/* @__PURE__ */ jsxs10("span", { children: [
|
|
3180
3450
|
"The assistant suggested changes that overlap your edits (",
|
|
3181
3451
|
pending.conflicts,
|
|
3182
3452
|
" ",
|
|
3183
3453
|
pending.conflicts === 1 ? "section" : "sections",
|
|
3184
3454
|
")."
|
|
3185
3455
|
] }),
|
|
3186
|
-
/* @__PURE__ */
|
|
3187
|
-
/* @__PURE__ */
|
|
3188
|
-
/* @__PURE__ */
|
|
3189
|
-
/* @__PURE__ */
|
|
3456
|
+
/* @__PURE__ */ jsxs10("span", { className: "june-doc__banner-actions", children: [
|
|
3457
|
+
/* @__PURE__ */ jsx14("button", { type: "button", className: "june-doc__btn", onClick: () => resolve("merge"), children: "Merge, keep my edits" }),
|
|
3458
|
+
/* @__PURE__ */ jsx14("button", { type: "button", className: "june-doc__btn", onClick: () => resolve("replace"), children: "Use AI version" }),
|
|
3459
|
+
/* @__PURE__ */ jsx14("button", { type: "button", className: "june-doc__btn", onClick: () => resolve("keep"), children: "Keep mine" })
|
|
3190
3460
|
] })
|
|
3191
3461
|
] }) : null,
|
|
3192
|
-
/* @__PURE__ */
|
|
3462
|
+
/* @__PURE__ */ jsx14(
|
|
3193
3463
|
DocumentToolbar,
|
|
3194
3464
|
{
|
|
3195
3465
|
editor,
|
|
@@ -3205,33 +3475,33 @@ function DocumentEditorImpl(props) {
|
|
|
3205
3475
|
onNotice: flash
|
|
3206
3476
|
}
|
|
3207
3477
|
),
|
|
3208
|
-
findOpen ? /* @__PURE__ */
|
|
3209
|
-
editable ? /* @__PURE__ */
|
|
3210
|
-
/* @__PURE__ */
|
|
3211
|
-
/* @__PURE__ */
|
|
3212
|
-
/* @__PURE__ */
|
|
3213
|
-
layout === "page" ? /* @__PURE__ */
|
|
3214
|
-
/* @__PURE__ */
|
|
3478
|
+
findOpen ? /* @__PURE__ */ jsx14(DocumentFindBar, { editor, editable, onClose: () => setFindOpen(false), onNotice: flash }) : null,
|
|
3479
|
+
editable ? /* @__PURE__ */ jsx14(DocumentBubbleMenu, { editor }) : null,
|
|
3480
|
+
/* @__PURE__ */ jsx14(DocumentContent, { editor, layout, zoom, showMarks, onMetrics: setMetrics }),
|
|
3481
|
+
/* @__PURE__ */ jsxs10("div", { className: "june-doc__footer", children: [
|
|
3482
|
+
/* @__PURE__ */ jsxs10("div", { className: "june-doc__stats", children: [
|
|
3483
|
+
layout === "page" ? /* @__PURE__ */ jsxs10(Fragment4, { children: [
|
|
3484
|
+
/* @__PURE__ */ jsxs10("span", { children: [
|
|
3215
3485
|
"Page ",
|
|
3216
3486
|
metrics.page,
|
|
3217
3487
|
" of ",
|
|
3218
3488
|
metrics.pages
|
|
3219
3489
|
] }),
|
|
3220
|
-
/* @__PURE__ */
|
|
3490
|
+
/* @__PURE__ */ jsx14("span", { className: "june-doc__stats-sep", "aria-hidden": "true" })
|
|
3221
3491
|
] }) : null,
|
|
3222
|
-
/* @__PURE__ */
|
|
3492
|
+
/* @__PURE__ */ jsxs10("span", { children: [
|
|
3223
3493
|
words,
|
|
3224
3494
|
" words"
|
|
3225
3495
|
] })
|
|
3226
3496
|
] }),
|
|
3227
|
-
/* @__PURE__ */
|
|
3228
|
-
/* @__PURE__ */
|
|
3229
|
-
/* @__PURE__ */
|
|
3230
|
-
/* @__PURE__ */
|
|
3497
|
+
/* @__PURE__ */ jsx14("span", { className: "june-doc__status", "aria-live": "polite", "data-state": notice ? "notice" : saveState, children: notice ?? SAVE_LABEL[saveState] }),
|
|
3498
|
+
/* @__PURE__ */ jsxs10("div", { className: "june-doc__zoom", role: "group", "aria-label": "Zoom", children: [
|
|
3499
|
+
/* @__PURE__ */ jsx14("button", { type: "button", className: "june-doc__btn june-doc__btn--icon june-doc__btn--ghost", "aria-label": "Zoom out", disabled: zoom <= ZOOM_STEPS[0], onClick: () => setZoom(stepZoom(zoom, -1)), children: /* @__PURE__ */ jsx14(Icon, { name: "minus", size: 14 }) }),
|
|
3500
|
+
/* @__PURE__ */ jsxs10("button", { type: "button", className: "june-doc__zoom-value", "aria-label": "Reset zoom", title: "Reset zoom", onClick: () => setZoom(1), children: [
|
|
3231
3501
|
Math.round(zoom * 100),
|
|
3232
3502
|
"%"
|
|
3233
3503
|
] }),
|
|
3234
|
-
/* @__PURE__ */
|
|
3504
|
+
/* @__PURE__ */ jsx14("button", { type: "button", className: "june-doc__btn june-doc__btn--icon june-doc__btn--ghost", "aria-label": "Zoom in", disabled: zoom >= ZOOM_STEPS[ZOOM_STEPS.length - 1], onClick: () => setZoom(stepZoom(zoom, 1)), children: /* @__PURE__ */ jsx14(Icon, { name: "plus", size: 14 }) })
|
|
3235
3505
|
] })
|
|
3236
3506
|
] })
|
|
3237
3507
|
]
|
|
@@ -3240,7 +3510,7 @@ function DocumentEditorImpl(props) {
|
|
|
3240
3510
|
}
|
|
3241
3511
|
|
|
3242
3512
|
// src/components/document-editor/document-component.tsx
|
|
3243
|
-
import { jsx as
|
|
3513
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
3244
3514
|
var DOCUMENT_COMPONENT_DESCRIPTION = 'Custom component. An editable document. DocumentEditor(documentId, title, content, documentType?, status?, editable?, exportFormats?). Place it in the root container (Card or Stack). "content" is the full document body as one Markdown string. Reuse documentId when revising the same document. Use it only when the user asks to create or revise a document.';
|
|
3245
3515
|
var documentProps = z.object({
|
|
3246
3516
|
documentId: z.string().describe("Stable id. Reuse it when revising the same document."),
|
|
@@ -3254,12 +3524,12 @@ var documentProps = z.object({
|
|
|
3254
3524
|
function DocumentEditor(props) {
|
|
3255
3525
|
const { isStreaming } = useJuneRuntime();
|
|
3256
3526
|
if (props.generating || isStreaming) {
|
|
3257
|
-
return /* @__PURE__ */
|
|
3527
|
+
return /* @__PURE__ */ jsx15(DocumentDraft, { title: props.title, state: "drafting" });
|
|
3258
3528
|
}
|
|
3259
|
-
return /* @__PURE__ */
|
|
3529
|
+
return /* @__PURE__ */ jsx15(DocumentEditorImpl, { ...props });
|
|
3260
3530
|
}
|
|
3261
3531
|
function OpenUIDocument({ props }) {
|
|
3262
|
-
return /* @__PURE__ */
|
|
3532
|
+
return /* @__PURE__ */ jsx15(
|
|
3263
3533
|
DocumentEditor,
|
|
3264
3534
|
{
|
|
3265
3535
|
documentId: props.documentId,
|
|
@@ -3334,7 +3604,7 @@ function documentPromptOptions(options = {}) {
|
|
|
3334
3604
|
var attr = (value) => value.replace(/"/g, """);
|
|
3335
3605
|
async function serializeDocumentsForAgent(options = {}) {
|
|
3336
3606
|
const store = options.store ?? getDefaultDocumentStore();
|
|
3337
|
-
const { docToMarkdown: docToMarkdown2 } = await import("./document-engine-
|
|
3607
|
+
const { docToMarkdown: docToMarkdown2 } = await import("./document-engine-RKD5SLXR.js");
|
|
3338
3608
|
return store.list().filter((r) => !options.ids || options.ids.includes(r.id)).map(
|
|
3339
3609
|
(r) => `<document id="${attr(r.id)}" title="${attr(r.title)}"${r.documentType ? ` type="${attr(r.documentType)}"` : ""}>
|
|
3340
3610
|
${docToMarkdown2(r.json)}
|
|
@@ -3347,9 +3617,9 @@ import { openuiLibrary } from "@openuidev/react-ui";
|
|
|
3347
3617
|
var juneLibrary = withDocumentEditor(openuiLibrary);
|
|
3348
3618
|
|
|
3349
3619
|
// src/core/JuneUI.tsx
|
|
3350
|
-
import { jsx as
|
|
3620
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
3351
3621
|
function JuneUI({ library = juneLibrary, ...props }) {
|
|
3352
|
-
return /* @__PURE__ */
|
|
3622
|
+
return /* @__PURE__ */ jsx16(JuneRenderer, { library, ...props });
|
|
3353
3623
|
}
|
|
3354
3624
|
export {
|
|
3355
3625
|
ALL_EXPORT_FORMATS,
|
|
@@ -3378,17 +3648,21 @@ export {
|
|
|
3378
3648
|
getDefaultDocumentStore,
|
|
3379
3649
|
getDocumentEditorInstructions,
|
|
3380
3650
|
getDocumentEditorRules,
|
|
3651
|
+
isDocumentEcho,
|
|
3381
3652
|
isJuneError,
|
|
3382
3653
|
jsonFieldExtractor,
|
|
3383
3654
|
juneLibrary,
|
|
3384
3655
|
lightTheme,
|
|
3385
3656
|
listDocumentExporters,
|
|
3386
3657
|
mergeDocuments,
|
|
3658
|
+
readDocumentFromProgram,
|
|
3387
3659
|
registerDocumentExporter,
|
|
3660
|
+
rememberDocumentEcho,
|
|
3388
3661
|
runAction,
|
|
3389
3662
|
serializeDocumentsForAgent,
|
|
3390
3663
|
sseToText,
|
|
3391
3664
|
toJuneError,
|
|
3665
|
+
updateDocumentInProgram,
|
|
3392
3666
|
useDocumentOptions,
|
|
3393
3667
|
useJuneRuntime,
|
|
3394
3668
|
useJuneStream,
|