document-cli 1.1.0 → 1.2.1
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/README.md +46 -8
- package/dist/cli.js +223 -24
- package/dist/index.cjs +517 -20
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +519 -22
- package/dist/odb-structure-CX_0zL8_.js +382 -0
- package/dist/{tui-Dywpifqx.js → tui-DD4bQp39.js} +464 -68
- package/package.json +3 -3
- package/dist/io-CKOE9Xda.js +0 -84
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { d as inferFormatFromExtension, i as formatOdbReportLines, l as loadProvidedFonts, n as describeOdbReport, o as readInput, r as formatOdbFormLines, t as describeOdbForm, u as formatToExtension } from "./odb-structure-CX_0zL8_.js";
|
|
2
2
|
import { readFile, writeFile } from "node:fs/promises";
|
|
3
|
-
import { createDocx, createOdg, createOdp, createOds, createOdt, createPptx, decodeMarkdownText, docxToPdf, encodeMarkdownText, hsqldbCellDisplayText, markdownToPdf, odgToPdf, odpToPdf, odsToPdf, odtToPdf, openDocx, openOdg, openOdp, openOds, openOdt, openPptx, pptxToPdf, readOdbTables, readOdgContent, readOdsContent, readPdf, rgbHexToColor } from "documents.js";
|
|
3
|
+
import { createDocx, createOdg, createOdp, createOds, createOdt, createPptx, decodeMarkdownText, docxToPdf, encodeMarkdownText, hsqldbCellDisplayText, markdownToPdf, odgToPdf, odpToPdf, odsToPdf, odtToPdf, openDocx, openOdg, openOdp, openOds, openOdt, openPptx, pptxToPdf, readOdbForms, readOdbReports, readOdbTables, readOdgContent, readOdsContent, readPdf, rgbHexToColor, xlsxToPdf } from "documents.js";
|
|
4
4
|
import { basename, dirname, extname, join } from "node:path";
|
|
5
5
|
import { cellReference, columnIndexToLetters, decodePackage } from "odf.js";
|
|
6
6
|
import { readdirSync } from "node:fs";
|
|
@@ -15,9 +15,17 @@ function describeError(error) {
|
|
|
15
15
|
}
|
|
16
16
|
//#endregion
|
|
17
17
|
//#region src/tui/format/export-pdf.ts
|
|
18
|
-
function toPdfOptions(options) {
|
|
18
|
+
function toPdfOptions(options, fonts) {
|
|
19
19
|
return {
|
|
20
20
|
signal: options.signal,
|
|
21
|
+
fonts,
|
|
22
|
+
onFontSubstitution: (substitution) => {
|
|
23
|
+
const requested = `${substitution.requestedFamily}${substitution.requestedBold ? " bold" : ""}${substitution.requestedItalic ? " italic" : ""}`;
|
|
24
|
+
options.onDiagnostic({
|
|
25
|
+
severity: "info",
|
|
26
|
+
message: `No "${requested}" face available; drew it in "${substitution.resolvedFamily}"`
|
|
27
|
+
});
|
|
28
|
+
},
|
|
21
29
|
onSubstitution: (substitution, context) => {
|
|
22
30
|
options.onDiagnostic({
|
|
23
31
|
severity: "info",
|
|
@@ -29,12 +37,17 @@ function toPdfOptions(options) {
|
|
|
29
37
|
}
|
|
30
38
|
async function exportToPdf(openDocument, destinationPath, options) {
|
|
31
39
|
if (openDocument.format === "odb" || openDocument.format === "pdf") throw new Error(`A ${openDocument.format} document is already a read-only source; there is no export-to-PDF path for it`);
|
|
32
|
-
const pdfOptions = toPdfOptions(options);
|
|
40
|
+
const pdfOptions = toPdfOptions(options, await loadProvidedFonts(options.fontFiles ?? [], { signal: options.signal }));
|
|
33
41
|
if (openDocument.format === "markdown") {
|
|
34
42
|
const pdfBytes = markdownToPdf(encodeMarkdownText(openDocument.source), pdfOptions);
|
|
35
43
|
await writeFile(destinationPath, pdfBytes);
|
|
36
44
|
return;
|
|
37
45
|
}
|
|
46
|
+
if (openDocument.format === "xlsx") {
|
|
47
|
+
const pdfBytes = xlsxToPdf(openDocument.bytes, pdfOptions);
|
|
48
|
+
await writeFile(destinationPath, pdfBytes);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
38
51
|
const bytes = openDocument.editor.toBytes();
|
|
39
52
|
const pdfBytes = convert(openDocument.format, bytes, pdfOptions);
|
|
40
53
|
await writeFile(destinationPath, pdfBytes);
|
|
@@ -64,11 +77,16 @@ function detectFormat(path) {
|
|
|
64
77
|
const ODB_EXTENSION = ".odb";
|
|
65
78
|
async function openDocumentAtPath(path) {
|
|
66
79
|
const bytes = new Uint8Array(await readFile(path));
|
|
67
|
-
if (path.toLowerCase().endsWith(ODB_EXTENSION))
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
80
|
+
if (path.toLowerCase().endsWith(ODB_EXTENSION)) {
|
|
81
|
+
const pkg = decodePackage(bytes);
|
|
82
|
+
return {
|
|
83
|
+
format: "odb",
|
|
84
|
+
tables: readOdbTables(pkg),
|
|
85
|
+
forms: readOdbForms(pkg),
|
|
86
|
+
reports: readOdbReports(pkg),
|
|
87
|
+
path
|
|
88
|
+
};
|
|
89
|
+
}
|
|
72
90
|
const format = detectFormat(path);
|
|
73
91
|
if (format === void 0) throw new Error(`Cannot tell what kind of document ${path} is from its extension`);
|
|
74
92
|
switch (format) {
|
|
@@ -112,7 +130,12 @@ async function openDocumentAtPath(path) {
|
|
|
112
130
|
source: decodeMarkdownText(bytes),
|
|
113
131
|
path
|
|
114
132
|
};
|
|
115
|
-
case "xlsx":
|
|
133
|
+
case "xlsx": return {
|
|
134
|
+
format,
|
|
135
|
+
layout: readPdf(xlsxToPdf(bytes)),
|
|
136
|
+
bytes,
|
|
137
|
+
path
|
|
138
|
+
};
|
|
116
139
|
case "odf": throw new Error("A standalone .odf formula document has no editor; convert it to PDF (odfToPdf) instead");
|
|
117
140
|
}
|
|
118
141
|
}
|
|
@@ -151,7 +174,7 @@ function createNewDocument(format) {
|
|
|
151
174
|
}
|
|
152
175
|
}
|
|
153
176
|
async function saveDocumentTo(openDocument, path) {
|
|
154
|
-
if (openDocument.format === "odb" || openDocument.format === "pdf") throw new Error(`A ${openDocument.format} document is opened read-only and cannot be written back`);
|
|
177
|
+
if (openDocument.format === "odb" || openDocument.format === "pdf" || openDocument.format === "xlsx") throw new Error(`A ${openDocument.format} document is opened read-only and cannot be written back`);
|
|
155
178
|
if (openDocument.format === "markdown") {
|
|
156
179
|
await writeFile(path, encodeMarkdownText(openDocument.source));
|
|
157
180
|
return;
|
|
@@ -190,6 +213,8 @@ function selectionKeyFor(screen) {
|
|
|
190
213
|
case "sheetList":
|
|
191
214
|
case "pageList":
|
|
192
215
|
case "odbTableList":
|
|
216
|
+
case "odbFormList":
|
|
217
|
+
case "odbReportList":
|
|
193
218
|
case "pdfPageList":
|
|
194
219
|
case "exportOptions":
|
|
195
220
|
case "saveAsPrompt":
|
|
@@ -211,6 +236,8 @@ function selectionKeyFor(screen) {
|
|
|
211
236
|
case "shapeOrVectorDetail":
|
|
212
237
|
case "pdfItemDetail": return `${screen.kind}:${screen.pageIndex}:${screen.itemIndex}`;
|
|
213
238
|
case "odbTableRows": return `odbTableRows:${screen.tableName}`;
|
|
239
|
+
case "odbFormDetail": return `odbFormDetail:${screen.formName}`;
|
|
240
|
+
case "odbReportDetail": return `odbReportDetail:${screen.reportName}`;
|
|
214
241
|
case "markdownLineEditor": return `markdownLineEditor:${screen.lineIndex}`;
|
|
215
242
|
}
|
|
216
243
|
}
|
|
@@ -224,7 +251,8 @@ function rootScreenForFormat(format) {
|
|
|
224
251
|
case "odg": return { kind: "pageList" };
|
|
225
252
|
case "odb": return { kind: "odbTableList" };
|
|
226
253
|
case "markdown": return { kind: "markdownLineList" };
|
|
227
|
-
case "pdf":
|
|
254
|
+
case "pdf":
|
|
255
|
+
case "xlsx": return { kind: "pdfPageList" };
|
|
228
256
|
}
|
|
229
257
|
}
|
|
230
258
|
function currentScreen(state) {
|
|
@@ -339,6 +367,8 @@ function documentWithPath(doc, path) {
|
|
|
339
367
|
case "odb": return {
|
|
340
368
|
format: "odb",
|
|
341
369
|
tables: doc.tables,
|
|
370
|
+
forms: doc.forms,
|
|
371
|
+
reports: doc.reports,
|
|
342
372
|
path
|
|
343
373
|
};
|
|
344
374
|
case "markdown": return {
|
|
@@ -351,6 +381,12 @@ function documentWithPath(doc, path) {
|
|
|
351
381
|
layout: doc.layout,
|
|
352
382
|
path
|
|
353
383
|
};
|
|
384
|
+
case "xlsx": return {
|
|
385
|
+
format: "xlsx",
|
|
386
|
+
layout: doc.layout,
|
|
387
|
+
bytes: doc.bytes,
|
|
388
|
+
path
|
|
389
|
+
};
|
|
354
390
|
}
|
|
355
391
|
}
|
|
356
392
|
function reopenEditable(doc, bytes) {
|
|
@@ -559,7 +595,7 @@ function appReducer(state, action) {
|
|
|
559
595
|
selection: {},
|
|
560
596
|
errorDetail: void 0,
|
|
561
597
|
stack: [rootScreenForFormat(action.doc.format)]
|
|
562
|
-
}, "info", `Opened ${action.path}`);
|
|
598
|
+
}, "info", action.doc.format === "xlsx" ? `Opened ${action.path} as a read-only PDF preview -- press ':' then 'export pdf' to save it as a real PDF` : `Opened ${action.path}`);
|
|
563
599
|
case "OPEN_FILE_ERROR": return withStatus({
|
|
564
600
|
...state,
|
|
565
601
|
errorDetail: {
|
|
@@ -689,6 +725,21 @@ function appReducer(state, action) {
|
|
|
689
725
|
doc.editor.addSlide();
|
|
690
726
|
});
|
|
691
727
|
}
|
|
728
|
+
case "ADD_SLIDE_TABLE": {
|
|
729
|
+
const doc = presentationDocument(state);
|
|
730
|
+
if (doc === void 0) return wrongDocument(state, "a pptx or odp document");
|
|
731
|
+
const slide = doc.editor.slides()[action.slideIndex];
|
|
732
|
+
if (slide === void 0) return withStatus(state, "warning", `There is no slide at index ${action.slideIndex}`);
|
|
733
|
+
return mutate(state, doc, () => {
|
|
734
|
+
slide.addTable({
|
|
735
|
+
frame: action.frame,
|
|
736
|
+
table: {
|
|
737
|
+
rows: action.rows,
|
|
738
|
+
columns: action.columns
|
|
739
|
+
}
|
|
740
|
+
});
|
|
741
|
+
});
|
|
742
|
+
}
|
|
692
743
|
case "ADD_TEXTBOX": {
|
|
693
744
|
const doc = shapeHostDocument(state);
|
|
694
745
|
if (doc === void 0) return wrongDocument(state, "a pptx, odp or odg document");
|
|
@@ -850,7 +901,7 @@ function appReducer(state, action) {
|
|
|
850
901
|
case "UNDO": {
|
|
851
902
|
const doc = state.openDocument;
|
|
852
903
|
if (doc === void 0) return withStatus(state, "info", "There is nothing to undo");
|
|
853
|
-
if (doc.format === "odb" || doc.format === "pdf") return withStatus(state, "warning", `A ${doc.format} document is read-only, so it has no history to undo`);
|
|
904
|
+
if (doc.format === "odb" || doc.format === "pdf" || doc.format === "xlsx") return withStatus(state, "warning", `A ${doc.format} document is read-only, so it has no history to undo`);
|
|
854
905
|
const snapshot = state.undoStack.at(-1);
|
|
855
906
|
if (snapshot === void 0) return withStatus(state, "info", "There is nothing to undo");
|
|
856
907
|
const restored = doc.format === "markdown" ? {
|
|
@@ -2349,11 +2400,249 @@ function requireOdbDocument(openDocument) {
|
|
|
2349
2400
|
return openDocument;
|
|
2350
2401
|
}
|
|
2351
2402
|
//#endregion
|
|
2403
|
+
//#region src/tui/screens/editors/odb/form-detail.tsx
|
|
2404
|
+
const FORM_DETAIL_RESERVED_ROWS = 5;
|
|
2405
|
+
function requireForm(forms, formName) {
|
|
2406
|
+
const form = forms.find((candidate) => candidate.name === formName);
|
|
2407
|
+
if (form === void 0) throw new Error(`odbFormDetail was pushed for form "${formName}", but the open .odb document has no form by that name.`);
|
|
2408
|
+
return form;
|
|
2409
|
+
}
|
|
2410
|
+
function OdbFormDetailScreen() {
|
|
2411
|
+
const state = useAppState();
|
|
2412
|
+
const dispatch = useAppDispatch();
|
|
2413
|
+
const doc = requireOdbDocument(state.openDocument);
|
|
2414
|
+
const screen = currentScreen(state);
|
|
2415
|
+
if (screen.kind !== "odbFormDetail") throw new Error(`OdbFormDetailScreen rendered while the current screen is "${screen.kind}", not "odbFormDetail".`);
|
|
2416
|
+
const form = requireForm(doc.forms, screen.formName);
|
|
2417
|
+
const allLines = formatOdbFormLines(form);
|
|
2418
|
+
const query = state.searchQuery.trim().toLowerCase();
|
|
2419
|
+
const lines = query === "" ? allLines : allLines.filter((line) => line.toLowerCase().includes(query));
|
|
2420
|
+
const { selectedIndex } = useNavigationInput({
|
|
2421
|
+
itemCount: lines.length,
|
|
2422
|
+
onSelect: () => {},
|
|
2423
|
+
onBack: () => {
|
|
2424
|
+
dispatch({ type: "POP_SCREEN" });
|
|
2425
|
+
},
|
|
2426
|
+
isActive: !anyOverlayOpen(state)
|
|
2427
|
+
});
|
|
2428
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
2429
|
+
flexDirection: "column",
|
|
2430
|
+
children: [
|
|
2431
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
2432
|
+
bold: true,
|
|
2433
|
+
children: [
|
|
2434
|
+
form.name,
|
|
2435
|
+
" (",
|
|
2436
|
+
lines.length,
|
|
2437
|
+
" of ",
|
|
2438
|
+
allLines.length,
|
|
2439
|
+
" lines)"
|
|
2440
|
+
]
|
|
2441
|
+
}),
|
|
2442
|
+
/* @__PURE__ */ jsx(Text, {
|
|
2443
|
+
dimColor: true,
|
|
2444
|
+
children: form.href
|
|
2445
|
+
}),
|
|
2446
|
+
/* @__PURE__ */ jsx(ListView, {
|
|
2447
|
+
items: lines,
|
|
2448
|
+
selectedIndex,
|
|
2449
|
+
reservedRows: FORM_DETAIL_RESERVED_ROWS,
|
|
2450
|
+
emptyMessage: query === "" ? "This form declares no structure." : `No lines match "${state.searchQuery}".`,
|
|
2451
|
+
renderItem: (line, isSelected) => /* @__PURE__ */ jsx(Text, {
|
|
2452
|
+
color: isSelected ? "cyan" : void 0,
|
|
2453
|
+
inverse: isSelected,
|
|
2454
|
+
children: line
|
|
2455
|
+
})
|
|
2456
|
+
}),
|
|
2457
|
+
/* @__PURE__ */ jsx(Text, {
|
|
2458
|
+
dimColor: true,
|
|
2459
|
+
children: "Esc to go back to the form list"
|
|
2460
|
+
})
|
|
2461
|
+
]
|
|
2462
|
+
});
|
|
2463
|
+
}
|
|
2464
|
+
//#endregion
|
|
2465
|
+
//#region src/tui/screens/editors/odb/form-list.tsx
|
|
2466
|
+
function OdbFormListScreen() {
|
|
2467
|
+
const state = useAppState();
|
|
2468
|
+
const dispatch = useAppDispatch();
|
|
2469
|
+
const doc = requireOdbDocument(state.openDocument);
|
|
2470
|
+
const query = state.searchQuery.trim().toLowerCase();
|
|
2471
|
+
const forms = query === "" ? doc.forms : doc.forms.filter((form) => form.name.toLowerCase().includes(query));
|
|
2472
|
+
const { selectedIndex } = useNavigationInput({
|
|
2473
|
+
itemCount: forms.length,
|
|
2474
|
+
onSelect: (index) => {
|
|
2475
|
+
const form = forms[index];
|
|
2476
|
+
if (form === void 0) return;
|
|
2477
|
+
dispatch({
|
|
2478
|
+
type: "PUSH_SCREEN",
|
|
2479
|
+
screen: {
|
|
2480
|
+
kind: "odbFormDetail",
|
|
2481
|
+
formName: form.name
|
|
2482
|
+
}
|
|
2483
|
+
});
|
|
2484
|
+
},
|
|
2485
|
+
onBack: () => {
|
|
2486
|
+
dispatch({ type: "POP_SCREEN" });
|
|
2487
|
+
},
|
|
2488
|
+
isActive: !anyOverlayOpen(state)
|
|
2489
|
+
});
|
|
2490
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
2491
|
+
flexDirection: "column",
|
|
2492
|
+
children: [
|
|
2493
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
2494
|
+
bold: true,
|
|
2495
|
+
children: [
|
|
2496
|
+
"Forms (",
|
|
2497
|
+
forms.length,
|
|
2498
|
+
" of ",
|
|
2499
|
+
doc.forms.length,
|
|
2500
|
+
")"
|
|
2501
|
+
]
|
|
2502
|
+
}),
|
|
2503
|
+
/* @__PURE__ */ jsx(ListView, {
|
|
2504
|
+
items: forms,
|
|
2505
|
+
selectedIndex,
|
|
2506
|
+
emptyMessage: query === "" ? "This database declares no forms." : `No forms match "${state.searchQuery}".`,
|
|
2507
|
+
renderItem: (form, isSelected) => /* @__PURE__ */ jsx(Text, {
|
|
2508
|
+
color: isSelected ? "cyan" : void 0,
|
|
2509
|
+
inverse: isSelected,
|
|
2510
|
+
children: describeOdbForm(form)
|
|
2511
|
+
})
|
|
2512
|
+
}),
|
|
2513
|
+
/* @__PURE__ */ jsx(Text, {
|
|
2514
|
+
dimColor: true,
|
|
2515
|
+
children: "Enter to open a form, Esc to go back to the tables"
|
|
2516
|
+
})
|
|
2517
|
+
]
|
|
2518
|
+
});
|
|
2519
|
+
}
|
|
2520
|
+
//#endregion
|
|
2521
|
+
//#region src/tui/screens/editors/odb/report-detail.tsx
|
|
2522
|
+
const REPORT_DETAIL_RESERVED_ROWS = 5;
|
|
2523
|
+
function requireReport(reports, reportName) {
|
|
2524
|
+
const report = reports.find((candidate) => candidate.name === reportName);
|
|
2525
|
+
if (report === void 0) throw new Error(`odbReportDetail was pushed for report "${reportName}", but the open .odb document has no report by that name.`);
|
|
2526
|
+
return report;
|
|
2527
|
+
}
|
|
2528
|
+
function OdbReportDetailScreen() {
|
|
2529
|
+
const state = useAppState();
|
|
2530
|
+
const dispatch = useAppDispatch();
|
|
2531
|
+
const doc = requireOdbDocument(state.openDocument);
|
|
2532
|
+
const screen = currentScreen(state);
|
|
2533
|
+
if (screen.kind !== "odbReportDetail") throw new Error(`OdbReportDetailScreen rendered while the current screen is "${screen.kind}", not "odbReportDetail".`);
|
|
2534
|
+
const report = requireReport(doc.reports, screen.reportName);
|
|
2535
|
+
const allLines = formatOdbReportLines(report);
|
|
2536
|
+
const query = state.searchQuery.trim().toLowerCase();
|
|
2537
|
+
const lines = query === "" ? allLines : allLines.filter((line) => line.toLowerCase().includes(query));
|
|
2538
|
+
const { selectedIndex } = useNavigationInput({
|
|
2539
|
+
itemCount: lines.length,
|
|
2540
|
+
onSelect: () => {},
|
|
2541
|
+
onBack: () => {
|
|
2542
|
+
dispatch({ type: "POP_SCREEN" });
|
|
2543
|
+
},
|
|
2544
|
+
isActive: !anyOverlayOpen(state)
|
|
2545
|
+
});
|
|
2546
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
2547
|
+
flexDirection: "column",
|
|
2548
|
+
children: [
|
|
2549
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
2550
|
+
bold: true,
|
|
2551
|
+
children: [
|
|
2552
|
+
report.name,
|
|
2553
|
+
" (",
|
|
2554
|
+
lines.length,
|
|
2555
|
+
" of ",
|
|
2556
|
+
allLines.length,
|
|
2557
|
+
" lines)"
|
|
2558
|
+
]
|
|
2559
|
+
}),
|
|
2560
|
+
/* @__PURE__ */ jsx(Text, {
|
|
2561
|
+
dimColor: true,
|
|
2562
|
+
children: report.href
|
|
2563
|
+
}),
|
|
2564
|
+
/* @__PURE__ */ jsx(ListView, {
|
|
2565
|
+
items: lines,
|
|
2566
|
+
selectedIndex,
|
|
2567
|
+
reservedRows: REPORT_DETAIL_RESERVED_ROWS,
|
|
2568
|
+
emptyMessage: query === "" ? "This report declares no structure." : `No lines match "${state.searchQuery}".`,
|
|
2569
|
+
renderItem: (line, isSelected) => /* @__PURE__ */ jsx(Text, {
|
|
2570
|
+
color: isSelected ? "cyan" : void 0,
|
|
2571
|
+
inverse: isSelected,
|
|
2572
|
+
children: line
|
|
2573
|
+
})
|
|
2574
|
+
}),
|
|
2575
|
+
/* @__PURE__ */ jsx(Text, {
|
|
2576
|
+
dimColor: true,
|
|
2577
|
+
children: "Esc to go back to the report list"
|
|
2578
|
+
})
|
|
2579
|
+
]
|
|
2580
|
+
});
|
|
2581
|
+
}
|
|
2582
|
+
//#endregion
|
|
2583
|
+
//#region src/tui/screens/editors/odb/report-list.tsx
|
|
2584
|
+
function OdbReportListScreen() {
|
|
2585
|
+
const state = useAppState();
|
|
2586
|
+
const dispatch = useAppDispatch();
|
|
2587
|
+
const doc = requireOdbDocument(state.openDocument);
|
|
2588
|
+
const query = state.searchQuery.trim().toLowerCase();
|
|
2589
|
+
const reports = query === "" ? doc.reports : doc.reports.filter((report) => report.name.toLowerCase().includes(query));
|
|
2590
|
+
const { selectedIndex } = useNavigationInput({
|
|
2591
|
+
itemCount: reports.length,
|
|
2592
|
+
onSelect: (index) => {
|
|
2593
|
+
const report = reports[index];
|
|
2594
|
+
if (report === void 0) return;
|
|
2595
|
+
dispatch({
|
|
2596
|
+
type: "PUSH_SCREEN",
|
|
2597
|
+
screen: {
|
|
2598
|
+
kind: "odbReportDetail",
|
|
2599
|
+
reportName: report.name
|
|
2600
|
+
}
|
|
2601
|
+
});
|
|
2602
|
+
},
|
|
2603
|
+
onBack: () => {
|
|
2604
|
+
dispatch({ type: "POP_SCREEN" });
|
|
2605
|
+
},
|
|
2606
|
+
isActive: !anyOverlayOpen(state)
|
|
2607
|
+
});
|
|
2608
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
2609
|
+
flexDirection: "column",
|
|
2610
|
+
children: [
|
|
2611
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
2612
|
+
bold: true,
|
|
2613
|
+
children: [
|
|
2614
|
+
"Reports (",
|
|
2615
|
+
reports.length,
|
|
2616
|
+
" of ",
|
|
2617
|
+
doc.reports.length,
|
|
2618
|
+
")"
|
|
2619
|
+
]
|
|
2620
|
+
}),
|
|
2621
|
+
/* @__PURE__ */ jsx(ListView, {
|
|
2622
|
+
items: reports,
|
|
2623
|
+
selectedIndex,
|
|
2624
|
+
emptyMessage: query === "" ? "This database declares no reports." : `No reports match "${state.searchQuery}".`,
|
|
2625
|
+
renderItem: (report, isSelected) => /* @__PURE__ */ jsx(Text, {
|
|
2626
|
+
color: isSelected ? "cyan" : void 0,
|
|
2627
|
+
inverse: isSelected,
|
|
2628
|
+
children: describeOdbReport(report)
|
|
2629
|
+
})
|
|
2630
|
+
}),
|
|
2631
|
+
/* @__PURE__ */ jsx(Text, {
|
|
2632
|
+
dimColor: true,
|
|
2633
|
+
children: "Enter to open a report, Esc to go back to the tables"
|
|
2634
|
+
})
|
|
2635
|
+
]
|
|
2636
|
+
});
|
|
2637
|
+
}
|
|
2638
|
+
//#endregion
|
|
2352
2639
|
//#region src/tui/screens/editors/odb/table-list.tsx
|
|
2640
|
+
const TABLE_LIST_RESERVED_ROWS = 5;
|
|
2353
2641
|
function OdbTableListScreen() {
|
|
2354
2642
|
const state = useAppState();
|
|
2355
2643
|
const dispatch = useAppDispatch();
|
|
2356
2644
|
const doc = requireOdbDocument(state.openDocument);
|
|
2645
|
+
const overlayOpen = anyOverlayOpen(state);
|
|
2357
2646
|
const query = state.searchQuery.trim().toLowerCase();
|
|
2358
2647
|
const tables = query === "" ? doc.tables : doc.tables.filter((table) => table.tableName.toLowerCase().includes(query));
|
|
2359
2648
|
const { selectedIndex } = useNavigationInput({
|
|
@@ -2372,36 +2661,63 @@ function OdbTableListScreen() {
|
|
|
2372
2661
|
onBack: () => {
|
|
2373
2662
|
dispatch({ type: "POP_SCREEN" });
|
|
2374
2663
|
},
|
|
2375
|
-
isActive: !
|
|
2664
|
+
isActive: !overlayOpen
|
|
2376
2665
|
});
|
|
2666
|
+
useInput((input) => {
|
|
2667
|
+
if (input === "f") {
|
|
2668
|
+
dispatch({
|
|
2669
|
+
type: "PUSH_SCREEN",
|
|
2670
|
+
screen: { kind: "odbFormList" }
|
|
2671
|
+
});
|
|
2672
|
+
return;
|
|
2673
|
+
}
|
|
2674
|
+
if (input === "r") dispatch({
|
|
2675
|
+
type: "PUSH_SCREEN",
|
|
2676
|
+
screen: { kind: "odbReportList" }
|
|
2677
|
+
});
|
|
2678
|
+
}, { isActive: !overlayOpen });
|
|
2377
2679
|
return /* @__PURE__ */ jsxs(Box, {
|
|
2378
2680
|
flexDirection: "column",
|
|
2379
|
-
children: [
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
"Tables (",
|
|
2383
|
-
tables.length,
|
|
2384
|
-
" of ",
|
|
2385
|
-
doc.tables.length,
|
|
2386
|
-
")"
|
|
2387
|
-
]
|
|
2388
|
-
}), /* @__PURE__ */ jsx(ListView, {
|
|
2389
|
-
items: tables,
|
|
2390
|
-
selectedIndex,
|
|
2391
|
-
emptyMessage: query === "" ? "This database has no tables." : `No tables match "${state.searchQuery}".`,
|
|
2392
|
-
renderItem: (table, isSelected) => /* @__PURE__ */ jsxs(Text, {
|
|
2393
|
-
color: isSelected ? "cyan" : void 0,
|
|
2394
|
-
inverse: isSelected,
|
|
2681
|
+
children: [
|
|
2682
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
2683
|
+
bold: true,
|
|
2395
2684
|
children: [
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2685
|
+
"Tables (",
|
|
2686
|
+
tables.length,
|
|
2687
|
+
" of ",
|
|
2688
|
+
doc.tables.length,
|
|
2689
|
+
")"
|
|
2690
|
+
]
|
|
2691
|
+
}),
|
|
2692
|
+
/* @__PURE__ */ jsx(ListView, {
|
|
2693
|
+
items: tables,
|
|
2694
|
+
selectedIndex,
|
|
2695
|
+
reservedRows: TABLE_LIST_RESERVED_ROWS,
|
|
2696
|
+
emptyMessage: query === "" ? "This database has no tables." : `No tables match "${state.searchQuery}".`,
|
|
2697
|
+
renderItem: (table, isSelected) => /* @__PURE__ */ jsxs(Text, {
|
|
2698
|
+
color: isSelected ? "cyan" : void 0,
|
|
2699
|
+
inverse: isSelected,
|
|
2700
|
+
children: [
|
|
2701
|
+
table.tableName,
|
|
2702
|
+
" (",
|
|
2703
|
+
table.columns.length,
|
|
2704
|
+
" columns, ",
|
|
2705
|
+
table.rows.length,
|
|
2706
|
+
" rows)"
|
|
2707
|
+
]
|
|
2708
|
+
})
|
|
2709
|
+
}),
|
|
2710
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
2711
|
+
dimColor: true,
|
|
2712
|
+
children: [
|
|
2713
|
+
"Enter to open a table, f for forms (",
|
|
2714
|
+
doc.forms.length,
|
|
2715
|
+
"), r for reports (",
|
|
2716
|
+
doc.reports.length,
|
|
2717
|
+
")"
|
|
2402
2718
|
]
|
|
2403
2719
|
})
|
|
2404
|
-
|
|
2720
|
+
]
|
|
2405
2721
|
});
|
|
2406
2722
|
}
|
|
2407
2723
|
//#endregion
|
|
@@ -3720,6 +4036,12 @@ const IMAGE_EXTENSION_TO_FORMAT = {
|
|
|
3720
4036
|
jpg: "jpeg",
|
|
3721
4037
|
jpeg: "jpeg"
|
|
3722
4038
|
};
|
|
4039
|
+
const DEFAULT_TABLE_ROWS = 2;
|
|
4040
|
+
const DEFAULT_TABLE_COLUMNS = 2;
|
|
4041
|
+
function parsePositiveIntField(raw, fallback) {
|
|
4042
|
+
const parsed = Number.parseInt(raw, 10);
|
|
4043
|
+
return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
|
|
4044
|
+
}
|
|
3723
4045
|
function imageFormatFromPath(path) {
|
|
3724
4046
|
const dotIndex = path.lastIndexOf(".");
|
|
3725
4047
|
if (dotIndex < 0) return;
|
|
@@ -3748,6 +4070,7 @@ function SlideDetailScreen(props) {
|
|
|
3748
4070
|
const [addMode, setAddMode] = useState("closed");
|
|
3749
4071
|
const [draft, setDraft] = useState("");
|
|
3750
4072
|
const [imageError, setImageError] = useState(void 0);
|
|
4073
|
+
const [tableRows, setTableRows] = useState(DEFAULT_TABLE_ROWS);
|
|
3751
4074
|
const formIsOpen = addMode !== "closed";
|
|
3752
4075
|
const { selectedIndex } = useNavigationInput({
|
|
3753
4076
|
itemCount: rows.length,
|
|
@@ -3788,10 +4111,15 @@ function SlideDetailScreen(props) {
|
|
|
3788
4111
|
setDraft("");
|
|
3789
4112
|
setImageError(void 0);
|
|
3790
4113
|
setAddMode("image");
|
|
4114
|
+
return;
|
|
4115
|
+
}
|
|
4116
|
+
if (input === "b") {
|
|
4117
|
+
setDraft(String(DEFAULT_TABLE_ROWS));
|
|
4118
|
+
setAddMode("tableRows");
|
|
3791
4119
|
}
|
|
3792
4120
|
}, { isActive: !overlayOpen && addMode === "chooseKind" });
|
|
3793
4121
|
useInput((input) => {
|
|
3794
|
-
if (input === "n"
|
|
4122
|
+
if (input === "n") dispatch({
|
|
3795
4123
|
type: "PUSH_SCREEN",
|
|
3796
4124
|
screen: {
|
|
3797
4125
|
kind: "notesEditor",
|
|
@@ -3826,6 +4154,22 @@ function SlideDetailScreen(props) {
|
|
|
3826
4154
|
}
|
|
3827
4155
|
})();
|
|
3828
4156
|
};
|
|
4157
|
+
const commitTableRows = (raw) => {
|
|
4158
|
+
setTableRows(parsePositiveIntField(raw, DEFAULT_TABLE_ROWS));
|
|
4159
|
+
setDraft(String(DEFAULT_TABLE_COLUMNS));
|
|
4160
|
+
setAddMode("tableColumns");
|
|
4161
|
+
};
|
|
4162
|
+
const commitTableColumns = (raw) => {
|
|
4163
|
+
const columns = parsePositiveIntField(raw, DEFAULT_TABLE_COLUMNS);
|
|
4164
|
+
dispatch({
|
|
4165
|
+
type: "ADD_SLIDE_TABLE",
|
|
4166
|
+
slideIndex,
|
|
4167
|
+
frame: defaultShapeFrame(doc.editor.slideSize),
|
|
4168
|
+
rows: tableRows,
|
|
4169
|
+
columns
|
|
4170
|
+
});
|
|
4171
|
+
setAddMode("closed");
|
|
4172
|
+
};
|
|
3829
4173
|
return /* @__PURE__ */ jsxs(Box, {
|
|
3830
4174
|
flexDirection: "column",
|
|
3831
4175
|
children: [
|
|
@@ -3862,7 +4206,7 @@ function SlideDetailScreen(props) {
|
|
|
3862
4206
|
}),
|
|
3863
4207
|
addMode === "chooseKind" ? /* @__PURE__ */ jsx(Text, {
|
|
3864
4208
|
color: "cyan",
|
|
3865
|
-
children: "Add shape: t textbox, i image, Esc cancel"
|
|
4209
|
+
children: "Add shape: t textbox, i image, b table, Esc cancel"
|
|
3866
4210
|
}) : void 0,
|
|
3867
4211
|
addMode === "textbox" ? /* @__PURE__ */ jsxs(Box, { children: [/* @__PURE__ */ jsx(Text, {
|
|
3868
4212
|
color: "cyan",
|
|
@@ -3894,13 +4238,33 @@ function SlideDetailScreen(props) {
|
|
|
3894
4238
|
children: imageError
|
|
3895
4239
|
})]
|
|
3896
4240
|
}) : void 0,
|
|
3897
|
-
/* @__PURE__ */ jsxs(Text, {
|
|
4241
|
+
addMode === "tableRows" ? /* @__PURE__ */ jsxs(Box, { children: [/* @__PURE__ */ jsx(Text, {
|
|
4242
|
+
color: "cyan",
|
|
4243
|
+
children: "Rows: "
|
|
4244
|
+
}), /* @__PURE__ */ jsx(TextField, {
|
|
4245
|
+
value: draft,
|
|
4246
|
+
isFocused: true,
|
|
4247
|
+
onChange: setDraft,
|
|
4248
|
+
onSubmit: commitTableRows,
|
|
4249
|
+
onCancel: () => {
|
|
4250
|
+
setAddMode("closed");
|
|
4251
|
+
}
|
|
4252
|
+
})] }) : void 0,
|
|
4253
|
+
addMode === "tableColumns" ? /* @__PURE__ */ jsxs(Box, { children: [/* @__PURE__ */ jsx(Text, {
|
|
4254
|
+
color: "cyan",
|
|
4255
|
+
children: "Columns: "
|
|
4256
|
+
}), /* @__PURE__ */ jsx(TextField, {
|
|
4257
|
+
value: draft,
|
|
4258
|
+
isFocused: true,
|
|
4259
|
+
onChange: setDraft,
|
|
4260
|
+
onSubmit: commitTableColumns,
|
|
4261
|
+
onCancel: () => {
|
|
4262
|
+
setAddMode("closed");
|
|
4263
|
+
}
|
|
4264
|
+
})] }) : void 0,
|
|
4265
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3898
4266
|
dimColor: true,
|
|
3899
|
-
children:
|
|
3900
|
-
"Enter: edit shape a: add shape",
|
|
3901
|
-
doc.format === "odp" ? " n: notes" : "",
|
|
3902
|
-
" Esc: back"
|
|
3903
|
-
]
|
|
4267
|
+
children: "Enter: edit shape a: add shape n: notes Esc: back"
|
|
3904
4268
|
})
|
|
3905
4269
|
]
|
|
3906
4270
|
});
|
|
@@ -3914,15 +4278,11 @@ function PptxSlideListScreen() {
|
|
|
3914
4278
|
}
|
|
3915
4279
|
//#endregion
|
|
3916
4280
|
//#region src/tui/screens/editors/odp/notes-editor.tsx
|
|
3917
|
-
function assertOdpDocument(doc) {
|
|
3918
|
-
if (doc?.format !== "odp") throw new Error("NotesEditorScreen rendered without an open odp document; check the screen router in app.tsx.");
|
|
3919
|
-
return doc;
|
|
3920
|
-
}
|
|
3921
4281
|
function NotesEditorScreen(props) {
|
|
3922
4282
|
const state = useAppState();
|
|
3923
4283
|
const dispatch = useAppDispatch();
|
|
3924
4284
|
const overlayOpen = anyOverlayOpen(state);
|
|
3925
|
-
const doc =
|
|
4285
|
+
const doc = assertPresentationDocument(state.openDocument);
|
|
3926
4286
|
const { slideIndex } = props.screen;
|
|
3927
4287
|
const slide = doc.editor.slides()[slideIndex];
|
|
3928
4288
|
const [draft, setDraft] = useState(() => slide?.notes ?? "");
|
|
@@ -4027,6 +4387,7 @@ const KIND_BADGE = {
|
|
|
4027
4387
|
boolean: "B",
|
|
4028
4388
|
date: "D",
|
|
4029
4389
|
time: "T",
|
|
4390
|
+
dateTime: "@",
|
|
4030
4391
|
error: "E",
|
|
4031
4392
|
empty: "."
|
|
4032
4393
|
};
|
|
@@ -4038,6 +4399,7 @@ const CELL_VALUE_KINDS = [
|
|
|
4038
4399
|
"boolean",
|
|
4039
4400
|
"date",
|
|
4040
4401
|
"time",
|
|
4402
|
+
"dateTime",
|
|
4041
4403
|
"error"
|
|
4042
4404
|
];
|
|
4043
4405
|
function rawEditableText(value) {
|
|
@@ -4046,6 +4408,7 @@ function rawEditableText(value) {
|
|
|
4046
4408
|
case "string":
|
|
4047
4409
|
case "date":
|
|
4048
4410
|
case "time":
|
|
4411
|
+
case "dateTime":
|
|
4049
4412
|
case "error": return value.value;
|
|
4050
4413
|
case "boolean": return value.value ? "TRUE" : "FALSE";
|
|
4051
4414
|
case "number":
|
|
@@ -4116,6 +4479,13 @@ function buildCellValue(kind, text) {
|
|
|
4116
4479
|
value: trimmed
|
|
4117
4480
|
};
|
|
4118
4481
|
}
|
|
4482
|
+
case "dateTime": {
|
|
4483
|
+
const trimmed = text.trim();
|
|
4484
|
+
return trimmed.length === 0 ? void 0 : {
|
|
4485
|
+
kind: "dateTime",
|
|
4486
|
+
value: trimmed
|
|
4487
|
+
};
|
|
4488
|
+
}
|
|
4119
4489
|
case "error": {
|
|
4120
4490
|
const trimmed = text.trim();
|
|
4121
4491
|
return trimmed.length === 0 ? void 0 : {
|
|
@@ -4863,7 +5233,7 @@ function OdtBodyListScreen() {
|
|
|
4863
5233
|
//#endregion
|
|
4864
5234
|
//#region src/tui/screens/editors/pdf/shared.ts
|
|
4865
5235
|
function requirePdfDocument(openDocument) {
|
|
4866
|
-
if (openDocument?.format !== "pdf") throw new Error("A PDF inspection screen rendered without an open PDF document; the app router only reaches this screen group from pdfPageList, which is only ever the root screen of
|
|
5236
|
+
if (openDocument?.format !== "pdf" && openDocument?.format !== "xlsx") throw new Error("A PDF inspection screen rendered without an open PDF or xlsx document; the app router only reaches this screen group from pdfPageList, which is only ever the root screen of one of those two formats.");
|
|
4867
5237
|
return openDocument;
|
|
4868
5238
|
}
|
|
4869
5239
|
function formatSize(widthPt, heightPt) {
|
|
@@ -5162,12 +5532,17 @@ function PdfPageItemsScreen() {
|
|
|
5162
5532
|
function defaultExportDestinationFor(document, cwd) {
|
|
5163
5533
|
return document.path === void 0 ? join(cwd, "untitled.pdf") : defaultPdfPathFor(document.path);
|
|
5164
5534
|
}
|
|
5535
|
+
function parseFontFileField(value) {
|
|
5536
|
+
return value.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
5537
|
+
}
|
|
5165
5538
|
function ExportOptionsScreen() {
|
|
5166
5539
|
const state = useAppState();
|
|
5167
5540
|
const dispatch = useAppDispatch();
|
|
5168
5541
|
const isActive = !anyOverlayOpen(state);
|
|
5169
5542
|
const document = state.openDocument;
|
|
5170
5543
|
const [destination, setDestination] = useState(() => document === void 0 ? "" : defaultExportDestinationFor(document, state.cwd));
|
|
5544
|
+
const [fontFiles, setFontFiles] = useState("");
|
|
5545
|
+
const [field, setField] = useState("destination");
|
|
5171
5546
|
if (document === void 0) return /* @__PURE__ */ jsx(Box, {
|
|
5172
5547
|
flexDirection: "column",
|
|
5173
5548
|
children: /* @__PURE__ */ jsx(Text, {
|
|
@@ -5175,21 +5550,27 @@ function ExportOptionsScreen() {
|
|
|
5175
5550
|
children: "There is no open document to export."
|
|
5176
5551
|
})
|
|
5177
5552
|
});
|
|
5178
|
-
const
|
|
5553
|
+
const cancel = () => {
|
|
5554
|
+
dispatch({ type: "POP_SCREEN" });
|
|
5555
|
+
};
|
|
5556
|
+
const submit = () => {
|
|
5179
5557
|
(async () => {
|
|
5180
5558
|
let diagnosticCount = 0;
|
|
5181
5559
|
try {
|
|
5182
|
-
await exportToPdf(document,
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
|
|
5560
|
+
await exportToPdf(document, destination, {
|
|
5561
|
+
fontFiles: parseFontFileField(fontFiles),
|
|
5562
|
+
onDiagnostic: (diagnostic) => {
|
|
5563
|
+
diagnosticCount += 1;
|
|
5564
|
+
dispatch({
|
|
5565
|
+
type: "APPEND_DIAGNOSTIC",
|
|
5566
|
+
diagnostic
|
|
5567
|
+
});
|
|
5568
|
+
}
|
|
5569
|
+
});
|
|
5189
5570
|
dispatch({
|
|
5190
5571
|
type: "SET_STATUS",
|
|
5191
5572
|
severity: "info",
|
|
5192
|
-
text: `Exported ${
|
|
5573
|
+
text: `Exported ${destination}`
|
|
5193
5574
|
});
|
|
5194
5575
|
if (diagnosticCount > 0) dispatch({
|
|
5195
5576
|
type: "OPEN_OVERLAY",
|
|
@@ -5199,7 +5580,7 @@ function ExportOptionsScreen() {
|
|
|
5199
5580
|
} catch (error) {
|
|
5200
5581
|
dispatch({
|
|
5201
5582
|
type: "OPEN_FILE_ERROR",
|
|
5202
|
-
message: `Could not export to ${
|
|
5583
|
+
message: `Could not export to ${destination}`,
|
|
5203
5584
|
detail: describeError(error)
|
|
5204
5585
|
});
|
|
5205
5586
|
}
|
|
@@ -5217,17 +5598,28 @@ function ExportOptionsScreen() {
|
|
|
5217
5598
|
children: "Path: "
|
|
5218
5599
|
}), /* @__PURE__ */ jsx(TextField, {
|
|
5219
5600
|
value: destination,
|
|
5220
|
-
isFocused: isActive,
|
|
5601
|
+
isFocused: isActive && field === "destination",
|
|
5221
5602
|
placeholder: "destination path",
|
|
5222
5603
|
onChange: setDestination,
|
|
5604
|
+
onSubmit: () => {
|
|
5605
|
+
setField("fonts");
|
|
5606
|
+
},
|
|
5607
|
+
onCancel: cancel
|
|
5608
|
+
})] }),
|
|
5609
|
+
/* @__PURE__ */ jsxs(Box, { children: [/* @__PURE__ */ jsx(Text, {
|
|
5610
|
+
color: "cyan",
|
|
5611
|
+
children: "Fonts: "
|
|
5612
|
+
}), /* @__PURE__ */ jsx(TextField, {
|
|
5613
|
+
value: fontFiles,
|
|
5614
|
+
isFocused: isActive && field === "fonts",
|
|
5615
|
+
placeholder: "optional .ttf/.otf paths, comma-separated",
|
|
5616
|
+
onChange: setFontFiles,
|
|
5223
5617
|
onSubmit: submit,
|
|
5224
|
-
onCancel:
|
|
5225
|
-
dispatch({ type: "POP_SCREEN" });
|
|
5226
|
-
}
|
|
5618
|
+
onCancel: cancel
|
|
5227
5619
|
})] }),
|
|
5228
5620
|
/* @__PURE__ */ jsx(Text, {
|
|
5229
5621
|
dimColor: true,
|
|
5230
|
-
children: "Enter to export, Esc to cancel"
|
|
5622
|
+
children: field === "destination" ? "Enter for fonts, Esc to cancel" : "Enter to export, Esc to cancel. Each font's family is read from the file itself"
|
|
5231
5623
|
})
|
|
5232
5624
|
]
|
|
5233
5625
|
});
|
|
@@ -5479,7 +5871,7 @@ function LauncherScreen() {
|
|
|
5479
5871
|
}),
|
|
5480
5872
|
/* @__PURE__ */ jsx(Text, {
|
|
5481
5873
|
dimColor: true,
|
|
5482
|
-
children: "A terminal editor for docx, pptx, odt, odp, ods, odg, markdown, odb and pdf."
|
|
5874
|
+
children: "A terminal editor for docx, pptx, odt, odp, ods, odg, markdown, odb and pdf -- xlsx opens as a read-only PDF preview."
|
|
5483
5875
|
}),
|
|
5484
5876
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
5485
5877
|
/* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
|
|
@@ -5665,6 +6057,10 @@ function ScreenBody({ screen }) {
|
|
|
5665
6057
|
case "shapeOrVectorDetail": return /* @__PURE__ */ jsx(OdgShapeOrVectorDetailScreen, {});
|
|
5666
6058
|
case "odbTableList": return /* @__PURE__ */ jsx(OdbTableListScreen, {});
|
|
5667
6059
|
case "odbTableRows": return /* @__PURE__ */ jsx(OdbTableRowsScreen, {});
|
|
6060
|
+
case "odbFormList": return /* @__PURE__ */ jsx(OdbFormListScreen, {});
|
|
6061
|
+
case "odbFormDetail": return /* @__PURE__ */ jsx(OdbFormDetailScreen, {});
|
|
6062
|
+
case "odbReportList": return /* @__PURE__ */ jsx(OdbReportListScreen, {});
|
|
6063
|
+
case "odbReportDetail": return /* @__PURE__ */ jsx(OdbReportDetailScreen, {});
|
|
5668
6064
|
case "markdownLineList": return /* @__PURE__ */ jsx(MarkdownLineListScreen, {});
|
|
5669
6065
|
case "markdownLineEditor": return /* @__PURE__ */ jsx(MarkdownLineEditorScreen, {});
|
|
5670
6066
|
case "pdfPageList": return /* @__PURE__ */ jsx(PdfPageListScreen, {});
|