@geomak/ui 7.8.0 → 7.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +296 -109
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +296 -109
- package/dist/index.js.map +1 -1
- package/dist/styles.css +16 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5937,6 +5937,15 @@ async function sourceToBytes(source, remote) {
|
|
|
5937
5937
|
}
|
|
5938
5938
|
throw new Error("Unsupported source type");
|
|
5939
5939
|
}
|
|
5940
|
+
function downloadBlob(blob, name) {
|
|
5941
|
+
if (typeof document === "undefined") return;
|
|
5942
|
+
const url = URL.createObjectURL(blob);
|
|
5943
|
+
const a = document.createElement("a");
|
|
5944
|
+
a.href = url;
|
|
5945
|
+
a.download = name;
|
|
5946
|
+
a.click();
|
|
5947
|
+
setTimeout(() => URL.revokeObjectURL(url), 1e3);
|
|
5948
|
+
}
|
|
5940
5949
|
function sourceName(source) {
|
|
5941
5950
|
if (typeof File !== "undefined" && source instanceof File) return source.name;
|
|
5942
5951
|
if (isUrlSource(source)) {
|
|
@@ -5947,17 +5956,45 @@ function sourceName(source) {
|
|
|
5947
5956
|
return void 0;
|
|
5948
5957
|
}
|
|
5949
5958
|
var pdfjsPromise = null;
|
|
5950
|
-
function loadPdfjs() {
|
|
5959
|
+
function loadPdfjs(workerSrc) {
|
|
5951
5960
|
if (pdfjsPromise) return pdfjsPromise;
|
|
5952
5961
|
pdfjsPromise = import('pdfjs-dist').then((pdfjs) => {
|
|
5953
5962
|
if (!pdfjs.GlobalWorkerOptions.workerSrc) {
|
|
5954
|
-
pdfjs.GlobalWorkerOptions.workerSrc = `https://cdn.jsdelivr.net/npm/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;
|
|
5963
|
+
pdfjs.GlobalWorkerOptions.workerSrc = workerSrc ?? `https://cdn.jsdelivr.net/npm/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;
|
|
5955
5964
|
}
|
|
5956
5965
|
return pdfjs;
|
|
5957
5966
|
});
|
|
5958
5967
|
return pdfjsPromise;
|
|
5959
5968
|
}
|
|
5960
5969
|
var GAP = 12;
|
|
5970
|
+
var SEARCH_DEBOUNCE = 220;
|
|
5971
|
+
var TEXT_LAYER_STYLE_ID = "oxygen-pdf-textlayer";
|
|
5972
|
+
var TEXT_LAYER_CSS = `
|
|
5973
|
+
.oxy-textLayer{position:absolute;inset:0;overflow:clip;line-height:1;text-size-adjust:none;forced-color-adjust:none;transform-origin:0 0}
|
|
5974
|
+
.oxy-textLayer span,.oxy-textLayer br{color:transparent;position:absolute;white-space:pre;cursor:text;transform-origin:0 0}
|
|
5975
|
+
.oxy-textLayer span.markedContent{top:0;height:0}
|
|
5976
|
+
.oxy-textLayer ::selection{background:color-mix(in srgb, var(--color-accent) 35%, transparent)}
|
|
5977
|
+
`;
|
|
5978
|
+
function ensureTextLayerStyles() {
|
|
5979
|
+
if (typeof document === "undefined" || document.getElementById(TEXT_LAYER_STYLE_ID)) return;
|
|
5980
|
+
const el = document.createElement("style");
|
|
5981
|
+
el.id = TEXT_LAYER_STYLE_ID;
|
|
5982
|
+
el.textContent = TEXT_LAYER_CSS;
|
|
5983
|
+
document.head.appendChild(el);
|
|
5984
|
+
}
|
|
5985
|
+
function pageIndexAt(offsets, y) {
|
|
5986
|
+
let lo = 0;
|
|
5987
|
+
let hi = offsets.length - 1;
|
|
5988
|
+
let ans = 0;
|
|
5989
|
+
while (lo <= hi) {
|
|
5990
|
+
const mid = lo + hi >> 1;
|
|
5991
|
+
if (offsets[mid] <= y) {
|
|
5992
|
+
ans = mid;
|
|
5993
|
+
lo = mid + 1;
|
|
5994
|
+
} else hi = mid - 1;
|
|
5995
|
+
}
|
|
5996
|
+
return ans;
|
|
5997
|
+
}
|
|
5961
5998
|
function PdfViewer({
|
|
5962
5999
|
source,
|
|
5963
6000
|
remote,
|
|
@@ -5966,6 +6003,7 @@ function PdfViewer({
|
|
|
5966
6003
|
toolbar = true,
|
|
5967
6004
|
thumbnails = false,
|
|
5968
6005
|
textLayer = true,
|
|
6006
|
+
workerSrc,
|
|
5969
6007
|
onLoad,
|
|
5970
6008
|
onError,
|
|
5971
6009
|
onPageChange,
|
|
@@ -5976,6 +6014,7 @@ function PdfViewer({
|
|
|
5976
6014
|
const [doc, setDoc] = useState(null);
|
|
5977
6015
|
const [numPages, setNumPages] = useState(0);
|
|
5978
6016
|
const [baseSize, setBaseSize] = useState(null);
|
|
6017
|
+
const [sizes, setSizes] = useState([]);
|
|
5979
6018
|
const [status, setStatus] = useState("loading");
|
|
5980
6019
|
const [error, setError] = useState(null);
|
|
5981
6020
|
const [reloadKey, setReloadKey] = useState(0);
|
|
@@ -5988,6 +6027,13 @@ function PdfViewer({
|
|
|
5988
6027
|
const [query, setQuery] = useState("");
|
|
5989
6028
|
const [matchPages, setMatchPages] = useState(null);
|
|
5990
6029
|
const [matchIdx, setMatchIdx] = useState(0);
|
|
6030
|
+
const [searching, setSearching] = useState(false);
|
|
6031
|
+
const [pageDraft, setPageDraft] = useState("");
|
|
6032
|
+
const pageEditing = useRef(false);
|
|
6033
|
+
const pageText = useRef(/* @__PURE__ */ new Map());
|
|
6034
|
+
const searchSeq = useRef(0);
|
|
6035
|
+
const searchTimer = useRef(null);
|
|
6036
|
+
const measured = useRef(/* @__PURE__ */ new Set());
|
|
5991
6037
|
const tb = toolbar === true ? { zoom: true, pager: true, download: true, print: true, search: true } : toolbar || {};
|
|
5992
6038
|
useEffect(() => {
|
|
5993
6039
|
let cancelled = false;
|
|
@@ -5996,7 +6042,12 @@ function PdfViewer({
|
|
|
5996
6042
|
setError(null);
|
|
5997
6043
|
setDoc(null);
|
|
5998
6044
|
setBaseSize(null);
|
|
5999
|
-
|
|
6045
|
+
setSizes([]);
|
|
6046
|
+
pageText.current.clear();
|
|
6047
|
+
measured.current = /* @__PURE__ */ new Set();
|
|
6048
|
+
setMatchPages(null);
|
|
6049
|
+
setMatchIdx(0);
|
|
6050
|
+
loadPdfjs(workerSrc).then(async (pdfjs2) => {
|
|
6000
6051
|
if (cancelled) return;
|
|
6001
6052
|
setPdfjs(pdfjs2);
|
|
6002
6053
|
const params = isUrlSource(source) ? { url: urlHref(source), httpHeaders: remote?.httpHeaders, withCredentials: remote?.withCredentials } : { data: source instanceof Uint8Array || source instanceof ArrayBuffer ? source : new Uint8Array(await source.arrayBuffer()) };
|
|
@@ -6009,9 +6060,12 @@ function PdfViewer({
|
|
|
6009
6060
|
const first = await pdf.getPage(1);
|
|
6010
6061
|
const vp = first.getViewport({ scale: 1 });
|
|
6011
6062
|
if (cancelled) return;
|
|
6063
|
+
const base = { width: vp.width, height: vp.height };
|
|
6012
6064
|
setDoc(pdf);
|
|
6013
6065
|
setNumPages(pdf.numPages);
|
|
6014
|
-
setBaseSize(
|
|
6066
|
+
setBaseSize(base);
|
|
6067
|
+
setSizes(Array.from({ length: pdf.numPages }, () => base));
|
|
6068
|
+
measured.current.add(1);
|
|
6015
6069
|
setStatus("ready");
|
|
6016
6070
|
onLoad?.({ numPages: pdf.numPages });
|
|
6017
6071
|
}).catch((err) => {
|
|
@@ -6024,7 +6078,7 @@ function PdfViewer({
|
|
|
6024
6078
|
cancelled = true;
|
|
6025
6079
|
task?.destroy?.();
|
|
6026
6080
|
};
|
|
6027
|
-
}, [source, remote, reloadKey]);
|
|
6081
|
+
}, [source, remote, reloadKey, workerSrc]);
|
|
6028
6082
|
useEffect(() => () => {
|
|
6029
6083
|
doc?.destroy?.();
|
|
6030
6084
|
}, [doc]);
|
|
@@ -6037,59 +6091,101 @@ function PdfViewer({
|
|
|
6037
6091
|
ro.observe(el);
|
|
6038
6092
|
return () => ro.disconnect();
|
|
6039
6093
|
}, [status]);
|
|
6094
|
+
const handleMeasure = useCallback((p, size) => {
|
|
6095
|
+
setSizes((prev) => {
|
|
6096
|
+
const cur = prev[p - 1];
|
|
6097
|
+
if (cur && Math.abs(cur.width - size.width) < 0.5 && Math.abs(cur.height - size.height) < 0.5) return prev;
|
|
6098
|
+
const next = prev.slice();
|
|
6099
|
+
next[p - 1] = size;
|
|
6100
|
+
return next;
|
|
6101
|
+
});
|
|
6102
|
+
}, []);
|
|
6040
6103
|
const scale = useMemo(() => {
|
|
6041
6104
|
if (!baseSize) return 1;
|
|
6042
6105
|
if (typeof zoomMode === "number") return zoomMode;
|
|
6043
|
-
const avail = Math.max(
|
|
6106
|
+
const avail = Math.max(1, (viewport.w || baseSize.width) - 32);
|
|
6044
6107
|
if (zoomMode === "page-width" || zoomMode === "auto") return avail / baseSize.width;
|
|
6045
6108
|
if (zoomMode === "page-fit") {
|
|
6046
|
-
const availH = Math.max(
|
|
6109
|
+
const availH = Math.max(1, (viewport.h || baseSize.height) - 32);
|
|
6047
6110
|
return Math.min(avail / baseSize.width, availH / baseSize.height);
|
|
6048
6111
|
}
|
|
6049
6112
|
return 1;
|
|
6050
6113
|
}, [zoomMode, baseSize, viewport]);
|
|
6051
|
-
const
|
|
6052
|
-
|
|
6053
|
-
|
|
6114
|
+
const { offsets, total } = useMemo(() => {
|
|
6115
|
+
const offs = new Array(sizes.length);
|
|
6116
|
+
let acc = 0;
|
|
6117
|
+
for (let i = 0; i < sizes.length; i++) {
|
|
6118
|
+
offs[i] = acc;
|
|
6119
|
+
acc += sizes[i].height * scale + GAP;
|
|
6120
|
+
}
|
|
6121
|
+
return { offsets: offs, total: acc };
|
|
6122
|
+
}, [sizes, scale]);
|
|
6054
6123
|
const overscan = 1;
|
|
6055
|
-
const
|
|
6056
|
-
const
|
|
6124
|
+
const hasLayout = offsets.length > 0 && total > 0;
|
|
6125
|
+
const startIdx = hasLayout ? Math.max(0, pageIndexAt(offsets, scrollTop) - overscan) : 0;
|
|
6126
|
+
const endIdx = hasLayout ? Math.min(numPages, pageIndexAt(offsets, scrollTop + viewport.h) + 1 + overscan) : 0;
|
|
6057
6127
|
const visiblePages = Array.from({ length: Math.max(0, endIdx - startIdx) }, (_, i) => startIdx + i + 1);
|
|
6128
|
+
const scrollToPage = useCallback((p) => {
|
|
6129
|
+
const el = scrollRef.current;
|
|
6130
|
+
if (!el || !offsets.length) return;
|
|
6131
|
+
const clamped = Math.min(offsets.length, Math.max(1, p));
|
|
6132
|
+
el.scrollTo({ top: offsets[clamped - 1] ?? 0, behavior: "smooth" });
|
|
6133
|
+
}, [offsets]);
|
|
6058
6134
|
useEffect(() => {
|
|
6059
|
-
if (!
|
|
6060
|
-
const cur =
|
|
6135
|
+
if (!hasLayout) return;
|
|
6136
|
+
const cur = pageIndexAt(offsets, scrollTop + viewport.h / 2) + 1;
|
|
6061
6137
|
if (cur !== page) {
|
|
6062
6138
|
setPage(cur);
|
|
6063
6139
|
onPageChange?.(cur);
|
|
6064
6140
|
}
|
|
6065
|
-
}, [scrollTop,
|
|
6066
|
-
const scrollToPage = useCallback((p) => {
|
|
6067
|
-
const el = scrollRef.current;
|
|
6068
|
-
if (!el || !pageH) return;
|
|
6069
|
-
el.scrollTo({ top: (p - 1) * pageH, behavior: "smooth" });
|
|
6070
|
-
}, [pageH]);
|
|
6141
|
+
}, [scrollTop, offsets, viewport.h, numPages]);
|
|
6071
6142
|
useEffect(() => {
|
|
6072
6143
|
if (status === "ready" && initialPage > 1) scrollToPage(initialPage);
|
|
6073
|
-
}, [status]);
|
|
6144
|
+
}, [status, initialPage]);
|
|
6074
6145
|
const runSearch = useCallback(async (q) => {
|
|
6075
|
-
|
|
6076
|
-
if (!doc || !
|
|
6146
|
+
const needle = q.trim().toLowerCase();
|
|
6147
|
+
if (!doc || !needle) {
|
|
6077
6148
|
setMatchPages(null);
|
|
6078
6149
|
setMatchIdx(0);
|
|
6150
|
+
setSearching(false);
|
|
6079
6151
|
return;
|
|
6080
6152
|
}
|
|
6081
|
-
const
|
|
6153
|
+
const seq = ++searchSeq.current;
|
|
6154
|
+
setSearching(true);
|
|
6082
6155
|
const hits = [];
|
|
6083
6156
|
for (let p = 1; p <= numPages; p++) {
|
|
6084
|
-
|
|
6085
|
-
|
|
6086
|
-
|
|
6157
|
+
let text = pageText.current.get(p);
|
|
6158
|
+
if (text === void 0) {
|
|
6159
|
+
const pg = await doc.getPage(p);
|
|
6160
|
+
const tc = await pg.getTextContent();
|
|
6161
|
+
const built = tc.items.map((it) => "str" in it ? it.str : "").join(" ").toLowerCase();
|
|
6162
|
+
pageText.current.set(p, built);
|
|
6163
|
+
text = built;
|
|
6164
|
+
}
|
|
6165
|
+
if (seq !== searchSeq.current) return;
|
|
6087
6166
|
if (text.includes(needle)) hits.push(p);
|
|
6088
6167
|
}
|
|
6168
|
+
if (seq !== searchSeq.current) return;
|
|
6089
6169
|
setMatchPages(hits);
|
|
6090
6170
|
setMatchIdx(0);
|
|
6171
|
+
setSearching(false);
|
|
6091
6172
|
if (hits.length) scrollToPage(hits[0]);
|
|
6092
6173
|
}, [doc, numPages, scrollToPage]);
|
|
6174
|
+
const onQueryChange = useCallback((v) => {
|
|
6175
|
+
setQuery(v);
|
|
6176
|
+
if (searchTimer.current) clearTimeout(searchTimer.current);
|
|
6177
|
+
if (!v.trim()) {
|
|
6178
|
+
searchSeq.current++;
|
|
6179
|
+
setMatchPages(null);
|
|
6180
|
+
setMatchIdx(0);
|
|
6181
|
+
setSearching(false);
|
|
6182
|
+
return;
|
|
6183
|
+
}
|
|
6184
|
+
searchTimer.current = setTimeout(() => runSearch(v), SEARCH_DEBOUNCE);
|
|
6185
|
+
}, [runSearch]);
|
|
6186
|
+
useEffect(() => () => {
|
|
6187
|
+
if (searchTimer.current) clearTimeout(searchTimer.current);
|
|
6188
|
+
}, []);
|
|
6093
6189
|
const gotoMatch = (dir) => {
|
|
6094
6190
|
if (!matchPages?.length) return;
|
|
6095
6191
|
const next = (matchIdx + dir + matchPages.length) % matchPages.length;
|
|
@@ -6103,15 +6199,9 @@ function PdfViewer({
|
|
|
6103
6199
|
if (typeof Blob !== "undefined" && source instanceof Blob) return new Uint8Array(await source.arrayBuffer());
|
|
6104
6200
|
throw new Error("No bytes available");
|
|
6105
6201
|
}, [doc, source]);
|
|
6106
|
-
const
|
|
6202
|
+
const download = useCallback(async () => {
|
|
6107
6203
|
const bytes = await getBytes();
|
|
6108
|
-
|
|
6109
|
-
const url = URL.createObjectURL(blob);
|
|
6110
|
-
const a = document.createElement("a");
|
|
6111
|
-
a.href = url;
|
|
6112
|
-
a.download = sourceName(source) || "document.pdf";
|
|
6113
|
-
a.click();
|
|
6114
|
-
setTimeout(() => URL.revokeObjectURL(url), 1e3);
|
|
6204
|
+
downloadBlob(new Blob([bytes], { type: "application/pdf" }), sourceName(source) || "document.pdf");
|
|
6115
6205
|
}, [getBytes, source]);
|
|
6116
6206
|
const print = useCallback(async () => {
|
|
6117
6207
|
const bytes = await getBytes();
|
|
@@ -6137,6 +6227,12 @@ function PdfViewer({
|
|
|
6137
6227
|
const cur = typeof zoomMode === "number" ? zoomMode : scale;
|
|
6138
6228
|
setZoomMode(Math.min(5, Math.max(0.25, +(cur * factor).toFixed(2))));
|
|
6139
6229
|
};
|
|
6230
|
+
const zoomPct = Math.round(scale * 100);
|
|
6231
|
+
const commitPageDraft = () => {
|
|
6232
|
+
pageEditing.current = false;
|
|
6233
|
+
const n = parseInt(pageDraft, 10);
|
|
6234
|
+
if (Number.isFinite(n)) scrollToPage(n);
|
|
6235
|
+
};
|
|
6140
6236
|
if (status === "error") {
|
|
6141
6237
|
return /* @__PURE__ */ jsxs("div", { className: cx("flex flex-col items-center justify-center gap-3 rounded-lg border border-border bg-surface p-8 text-center", className), style, children: [
|
|
6142
6238
|
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-status-error", children: "Couldn\u2019t load the PDF" }),
|
|
@@ -6144,80 +6240,127 @@ function PdfViewer({
|
|
|
6144
6240
|
/* @__PURE__ */ jsx(Button_default, { content: "Retry", size: "sm", variant: "outline", onClick: () => setReloadKey((k) => k + 1) })
|
|
6145
6241
|
] });
|
|
6146
6242
|
}
|
|
6243
|
+
const ready = status === "ready";
|
|
6147
6244
|
return /* @__PURE__ */ jsxs("div", { className: cx("flex flex-col overflow-hidden rounded-lg border border-border bg-surface-raised", className), style: { height: 600, ...style }, children: [
|
|
6148
|
-
toolbar !== false && /* @__PURE__ */ jsxs("div", { className: "flex flex-shrink-0 flex-
|
|
6149
|
-
|
|
6150
|
-
/* @__PURE__ */
|
|
6151
|
-
|
|
6152
|
-
|
|
6153
|
-
|
|
6154
|
-
|
|
6245
|
+
toolbar !== false && /* @__PURE__ */ jsxs("div", { className: "flex flex-shrink-0 flex-col border-b border-border bg-surface", children: [
|
|
6246
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 px-2 py-1.5", children: [
|
|
6247
|
+
tb.pager && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
6248
|
+
/* @__PURE__ */ jsx(IconButton_default, { type: "ghost", size: "sm", title: "Previous page", onClick: () => scrollToPage(page - 1), icon: /* @__PURE__ */ jsx(Chevron5, { dir: "up" }), disabled: !ready || page <= 1 }),
|
|
6249
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-xs text-foreground-secondary select-none", children: [
|
|
6250
|
+
/* @__PURE__ */ jsx(
|
|
6251
|
+
"input",
|
|
6252
|
+
{
|
|
6253
|
+
value: pageEditing.current ? pageDraft : ready ? String(page) : "\u2013",
|
|
6254
|
+
onFocus: () => {
|
|
6255
|
+
pageEditing.current = true;
|
|
6256
|
+
setPageDraft(String(page));
|
|
6257
|
+
},
|
|
6258
|
+
onChange: (e) => setPageDraft(e.target.value.replace(/[^\d]/g, "")),
|
|
6259
|
+
onBlur: commitPageDraft,
|
|
6260
|
+
onKeyDown: (e) => {
|
|
6261
|
+
if (e.key === "Enter") e.target.blur();
|
|
6262
|
+
},
|
|
6263
|
+
disabled: !ready,
|
|
6264
|
+
"aria-label": "Page number",
|
|
6265
|
+
className: "h-6 w-9 rounded border border-border bg-surface-raised text-center tabular-nums text-foreground outline-none focus:border-accent disabled:opacity-50"
|
|
6266
|
+
}
|
|
6267
|
+
),
|
|
6268
|
+
/* @__PURE__ */ jsxs("span", { className: "tabular-nums", children: [
|
|
6269
|
+
"/ ",
|
|
6270
|
+
numPages || "\u2013"
|
|
6271
|
+
] })
|
|
6272
|
+
] }),
|
|
6273
|
+
/* @__PURE__ */ jsx(IconButton_default, { type: "ghost", size: "sm", title: "Next page", onClick: () => scrollToPage(page + 1), icon: /* @__PURE__ */ jsx(Chevron5, { dir: "down" }), disabled: !ready || page >= numPages })
|
|
6155
6274
|
] }),
|
|
6156
|
-
/* @__PURE__ */ jsx(
|
|
6157
|
-
|
|
6158
|
-
|
|
6159
|
-
|
|
6160
|
-
|
|
6161
|
-
|
|
6162
|
-
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6275
|
+
tb.pager && tb.zoom && /* @__PURE__ */ jsx("span", { className: "mx-1 h-5 w-px bg-border", "aria-hidden": "true" }),
|
|
6276
|
+
tb.zoom && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
6277
|
+
/* @__PURE__ */ jsx(IconButton_default, { type: "ghost", size: "sm", title: "Zoom out", onClick: () => setZoomNum(1 / 1.2), icon: /* @__PURE__ */ jsx(MinusIcon, {}), disabled: !ready }),
|
|
6278
|
+
/* @__PURE__ */ jsx("span", { className: "w-10 text-center text-xs tabular-nums text-foreground-secondary select-none", children: ready ? `${zoomPct}%` : "\u2013" }),
|
|
6279
|
+
/* @__PURE__ */ jsx(IconButton_default, { type: "ghost", size: "sm", title: "Zoom in", onClick: () => setZoomNum(1.2), icon: /* @__PURE__ */ jsx(PlusIcon, {}), disabled: !ready }),
|
|
6280
|
+
/* @__PURE__ */ jsx(IconButton_default, { type: "ghost", size: "sm", title: "Fit width", onClick: () => setZoomMode("page-width"), icon: /* @__PURE__ */ jsx(FitWidthIcon, {}), disabled: !ready }),
|
|
6281
|
+
/* @__PURE__ */ jsx(IconButton_default, { type: "ghost", size: "sm", title: "Fit page", onClick: () => setZoomMode("page-fit"), icon: /* @__PURE__ */ jsx(FitPageIcon, {}), disabled: !ready })
|
|
6282
|
+
] }),
|
|
6283
|
+
/* @__PURE__ */ jsxs("div", { className: "ml-auto flex items-center gap-1", children: [
|
|
6284
|
+
tb.search && /* @__PURE__ */ jsx(IconButton_default, { type: showSearch ? "bordered" : "ghost", size: "sm", title: "Search", onClick: () => setShowSearch((s) => !s), icon: /* @__PURE__ */ jsx(SearchIcon2, {}), disabled: !ready }),
|
|
6285
|
+
tb.search && (tb.download || tb.print) && /* @__PURE__ */ jsx("span", { className: "mx-1 h-5 w-px bg-border", "aria-hidden": "true" }),
|
|
6286
|
+
tb.download && /* @__PURE__ */ jsx(IconButton_default, { type: "ghost", size: "sm", title: "Download", onClick: download, icon: /* @__PURE__ */ jsx(DownloadIcon, {}), disabled: !ready }),
|
|
6287
|
+
tb.print && /* @__PURE__ */ jsx(IconButton_default, { type: "ghost", size: "sm", title: "Print", onClick: print, icon: /* @__PURE__ */ jsx(PrintIcon, {}), disabled: !ready })
|
|
6288
|
+
] })
|
|
6168
6289
|
] }),
|
|
6169
|
-
tb.search && showSearch && /* @__PURE__ */ jsxs("div", { className: "flex
|
|
6290
|
+
tb.search && showSearch && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 border-t border-border px-2 py-1.5", children: [
|
|
6291
|
+
/* @__PURE__ */ jsx(SearchIcon2, {}),
|
|
6170
6292
|
/* @__PURE__ */ jsx(
|
|
6171
6293
|
"input",
|
|
6172
6294
|
{
|
|
6173
6295
|
autoFocus: true,
|
|
6174
6296
|
value: query,
|
|
6175
|
-
onChange: (e) =>
|
|
6297
|
+
onChange: (e) => onQueryChange(e.target.value),
|
|
6298
|
+
onKeyDown: (e) => {
|
|
6299
|
+
if (e.key === "Enter") gotoMatch(e.shiftKey ? -1 : 1);
|
|
6300
|
+
},
|
|
6176
6301
|
placeholder: "Find in document\u2026",
|
|
6177
|
-
className: "h-7 flex-1
|
|
6302
|
+
className: "h-7 flex-1 bg-transparent text-sm text-foreground outline-none placeholder:text-foreground-muted"
|
|
6178
6303
|
}
|
|
6179
6304
|
),
|
|
6180
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs tabular-nums text-foreground-muted", children: matchPages == null ? "" : matchPages.length ? `${matchIdx + 1}
|
|
6305
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs tabular-nums text-foreground-muted", children: searching ? "Searching\u2026" : matchPages == null ? "" : matchPages.length ? `${matchIdx + 1} of ${matchPages.length}` : "No matches" }),
|
|
6181
6306
|
/* @__PURE__ */ jsx(IconButton_default, { type: "ghost", size: "sm", title: "Previous match", onClick: () => gotoMatch(-1), icon: /* @__PURE__ */ jsx(Chevron5, { dir: "up" }), disabled: !matchPages?.length }),
|
|
6182
|
-
/* @__PURE__ */ jsx(IconButton_default, { type: "ghost", size: "sm", title: "Next match", onClick: () => gotoMatch(1), icon: /* @__PURE__ */ jsx(Chevron5, { dir: "down" }), disabled: !matchPages?.length })
|
|
6307
|
+
/* @__PURE__ */ jsx(IconButton_default, { type: "ghost", size: "sm", title: "Next match", onClick: () => gotoMatch(1), icon: /* @__PURE__ */ jsx(Chevron5, { dir: "down" }), disabled: !matchPages?.length }),
|
|
6308
|
+
/* @__PURE__ */ jsx(IconButton_default, { type: "ghost", size: "sm", title: "Close search", onClick: () => {
|
|
6309
|
+
setShowSearch(false);
|
|
6310
|
+
onQueryChange("");
|
|
6311
|
+
}, icon: /* @__PURE__ */ jsx(CloseIcon, {}) })
|
|
6183
6312
|
] })
|
|
6184
6313
|
] }),
|
|
6185
6314
|
/* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1", children: [
|
|
6186
|
-
thumbnails &&
|
|
6187
|
-
|
|
6188
|
-
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
|
|
6200
|
-
|
|
6315
|
+
thumbnails && ready && doc && baseSize && /* @__PURE__ */ jsx("div", { className: "w-32 flex-shrink-0 overflow-y-auto border-r border-border bg-surface p-2", children: Array.from({ length: numPages }, (_, i) => i + 1).map((p) => {
|
|
6316
|
+
const s = sizes[p - 1] ?? baseSize;
|
|
6317
|
+
return /* @__PURE__ */ jsx(
|
|
6318
|
+
"button",
|
|
6319
|
+
{
|
|
6320
|
+
type: "button",
|
|
6321
|
+
onClick: () => scrollToPage(p),
|
|
6322
|
+
className: cx(
|
|
6323
|
+
"mb-2 block w-full overflow-hidden rounded border bg-surface-raised transition-colors",
|
|
6324
|
+
p === page ? "border-accent ring-1 ring-accent" : "border-border hover:border-border-strong"
|
|
6325
|
+
),
|
|
6326
|
+
style: { aspectRatio: `${s.width} / ${s.height}` },
|
|
6327
|
+
"aria-label": `Page ${p}`,
|
|
6328
|
+
"aria-current": p === page,
|
|
6329
|
+
children: Math.abs(p - page) <= 8 ? /* @__PURE__ */ jsx(PdfPage, { pdfjs, doc, page: p, scale: 112 / s.width, textLayer: false }) : /* @__PURE__ */ jsx("span", { className: "block py-4 text-center text-xs text-foreground-muted", children: p })
|
|
6330
|
+
},
|
|
6331
|
+
p
|
|
6332
|
+
);
|
|
6333
|
+
}) }),
|
|
6201
6334
|
/* @__PURE__ */ jsx(
|
|
6202
6335
|
"div",
|
|
6203
6336
|
{
|
|
6204
6337
|
ref: scrollRef,
|
|
6205
6338
|
onScroll: (e) => setScrollTop(e.currentTarget.scrollTop),
|
|
6206
6339
|
className: "relative flex-1 overflow-auto bg-background",
|
|
6207
|
-
children:
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6340
|
+
children: !ready || !baseSize ? /* @__PURE__ */ jsx("div", { className: "flex flex-col items-center gap-3 p-6", children: /* @__PURE__ */ jsx(SkeletonBox, { width: Math.min((viewport.w || 528) - 48, 560), height: 680, className: "rounded" }) }) : numPages === 0 ? /* @__PURE__ */ jsx("div", { className: "flex h-full items-center justify-center text-sm text-foreground-muted", children: "Empty document" }) : /* @__PURE__ */ jsx("div", { style: { height: total, position: "relative" }, children: visiblePages.map((p) => {
|
|
6341
|
+
const s = sizes[p - 1] ?? baseSize;
|
|
6342
|
+
return /* @__PURE__ */ jsx(
|
|
6343
|
+
"div",
|
|
6344
|
+
{
|
|
6345
|
+
style: { position: "absolute", top: offsets[p - 1], left: 0, right: 0, display: "flex", justifyContent: "center", paddingTop: GAP / 2 },
|
|
6346
|
+
children: /* @__PURE__ */ jsx("div", { className: "relative shadow-md", style: { width: s.width * scale, height: s.height * scale }, children: /* @__PURE__ */ jsx(PdfPage, { pdfjs, doc, page: p, scale, textLayer, onMeasure: handleMeasure }) })
|
|
6347
|
+
},
|
|
6348
|
+
p
|
|
6349
|
+
);
|
|
6350
|
+
}) })
|
|
6215
6351
|
}
|
|
6216
6352
|
)
|
|
6217
6353
|
] })
|
|
6218
6354
|
] });
|
|
6219
6355
|
}
|
|
6220
|
-
function PdfPage({
|
|
6356
|
+
function PdfPage({
|
|
6357
|
+
pdfjs,
|
|
6358
|
+
doc,
|
|
6359
|
+
page,
|
|
6360
|
+
scale,
|
|
6361
|
+
textLayer,
|
|
6362
|
+
onMeasure
|
|
6363
|
+
}) {
|
|
6221
6364
|
const canvasRef = useRef(null);
|
|
6222
6365
|
const textRef = useRef(null);
|
|
6223
6366
|
useEffect(() => {
|
|
@@ -6227,6 +6370,7 @@ function PdfPage({ pdfjs, doc, page, scale, textLayer }) {
|
|
|
6227
6370
|
const pg = await doc.getPage(page);
|
|
6228
6371
|
if (cancelled) return;
|
|
6229
6372
|
const viewport = pg.getViewport({ scale });
|
|
6373
|
+
onMeasure?.(page, { width: viewport.width / scale, height: viewport.height / scale });
|
|
6230
6374
|
const canvas = canvasRef.current;
|
|
6231
6375
|
if (!canvas) return;
|
|
6232
6376
|
const ratio = typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1;
|
|
@@ -6243,6 +6387,7 @@ function PdfPage({ pdfjs, doc, page, scale, textLayer }) {
|
|
|
6243
6387
|
}
|
|
6244
6388
|
if (cancelled || !textLayer || !textRef.current || !pdfjs?.TextLayer) return;
|
|
6245
6389
|
try {
|
|
6390
|
+
ensureTextLayerStyles();
|
|
6246
6391
|
textRef.current.innerHTML = "";
|
|
6247
6392
|
textRef.current.style.setProperty("--scale-factor", String(scale));
|
|
6248
6393
|
const tl = new pdfjs.TextLayer({ textContentSource: pg.streamTextContent(), container: textRef.current, viewport });
|
|
@@ -6254,17 +6399,20 @@ function PdfPage({ pdfjs, doc, page, scale, textLayer }) {
|
|
|
6254
6399
|
cancelled = true;
|
|
6255
6400
|
renderTask?.cancel?.();
|
|
6256
6401
|
};
|
|
6257
|
-
}, [pdfjs, doc, page, scale, textLayer]);
|
|
6402
|
+
}, [pdfjs, doc, page, scale, textLayer, onMeasure]);
|
|
6258
6403
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6259
6404
|
/* @__PURE__ */ jsx("canvas", { ref: canvasRef, className: "block bg-white" }),
|
|
6260
|
-
textLayer && /* @__PURE__ */ jsx("div", { ref: textRef, className: "textLayer
|
|
6405
|
+
textLayer && /* @__PURE__ */ jsx("div", { ref: textRef, className: "oxy-textLayer", "aria-hidden": "true" })
|
|
6261
6406
|
] });
|
|
6262
6407
|
}
|
|
6263
6408
|
var Chevron5 = ({ dir }) => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: dir === "up" ? "m6 15 6-6 6 6" : "m6 9 6 6 6-6" }) });
|
|
6264
|
-
var
|
|
6409
|
+
var MinusIcon = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", d: "M5 12h14" }) });
|
|
6410
|
+
var PlusIcon = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", d: "M12 5v14M5 12h14" }) });
|
|
6411
|
+
var SearchIcon2 = () => /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4 text-foreground-muted", "aria-hidden": "true", children: [
|
|
6265
6412
|
/* @__PURE__ */ jsx("circle", { cx: "11", cy: "11", r: "7" }),
|
|
6266
6413
|
/* @__PURE__ */ jsx("path", { strokeLinecap: "round", d: "m21 21-4.3-4.3" })
|
|
6267
6414
|
] });
|
|
6415
|
+
var CloseIcon = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", d: "M6 6l12 12M18 6 6 18" }) });
|
|
6268
6416
|
var DownloadIcon = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 3v12m0 0 4-4m-4 4-4-4M4 21h16" }) });
|
|
6269
6417
|
var PrintIcon = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 9V3h12v6M6 18H4v-7h16v7h-2M8 14h8v7H8z" }) });
|
|
6270
6418
|
var FitWidthIcon = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3 12h18m0 0-4-4m4 4-4 4M3 12l4-4m-4 4 4 4" }) });
|
|
@@ -6275,10 +6423,10 @@ var FitPageIcon = () => /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill
|
|
|
6275
6423
|
var DEFAULT_COL_WIDTH = 140;
|
|
6276
6424
|
var GUTTER = 52;
|
|
6277
6425
|
function resolveWidth(w) {
|
|
6278
|
-
if (typeof w === "number") return w;
|
|
6426
|
+
if (typeof w === "number" && Number.isFinite(w)) return w;
|
|
6279
6427
|
if (typeof w === "string") {
|
|
6280
|
-
const
|
|
6281
|
-
if (
|
|
6428
|
+
const m = /^\s*(\d+(?:\.\d+)?)(px)?\s*$/.exec(w);
|
|
6429
|
+
if (m) return parseFloat(m[1]);
|
|
6282
6430
|
}
|
|
6283
6431
|
return DEFAULT_COL_WIDTH;
|
|
6284
6432
|
}
|
|
@@ -6471,13 +6619,16 @@ var xlsxPromise = null;
|
|
|
6471
6619
|
var loadXlsx = () => xlsxPromise ??= import('xlsx');
|
|
6472
6620
|
var jspdfPromise = null;
|
|
6473
6621
|
var loadJspdf = () => jspdfPromise ??= import('jspdf');
|
|
6474
|
-
function
|
|
6475
|
-
|
|
6476
|
-
|
|
6477
|
-
|
|
6478
|
-
|
|
6479
|
-
|
|
6480
|
-
|
|
6622
|
+
function coerceToCellType(prev, next) {
|
|
6623
|
+
if (typeof prev === "number") {
|
|
6624
|
+
const n = Number(next);
|
|
6625
|
+
return next.trim() !== "" && Number.isFinite(n) ? n : next;
|
|
6626
|
+
}
|
|
6627
|
+
if (typeof prev === "boolean") {
|
|
6628
|
+
if (/^(true|false)$/i.test(next.trim())) return next.trim().toLowerCase() === "true";
|
|
6629
|
+
return next;
|
|
6630
|
+
}
|
|
6631
|
+
return next;
|
|
6481
6632
|
}
|
|
6482
6633
|
function Spreadsheet({
|
|
6483
6634
|
source,
|
|
@@ -6545,20 +6696,23 @@ function Spreadsheet({
|
|
|
6545
6696
|
const columns = useMemo(() => sheet ? toColumns(sheet.columns) : [], [sheet]);
|
|
6546
6697
|
const plainRows = useMemo(() => sheet ? toPlainRows(sheet, columns) : [], [sheet, columns]);
|
|
6547
6698
|
const handleCellEdit = useCallback(({ row, column, value }) => {
|
|
6699
|
+
let coerced = value;
|
|
6548
6700
|
setSheets((prev) => {
|
|
6549
6701
|
if (!prev) return prev;
|
|
6550
6702
|
const next = prev.map((s, i) => i === active ? { ...s, rows: s.rows.map((r) => ({ ...r })) } : s);
|
|
6551
6703
|
const target = next[active];
|
|
6552
6704
|
const existing = target.rows[row]?.[column];
|
|
6705
|
+
const prevValue = cellValue(existing);
|
|
6706
|
+
coerced = coerceToCellType(prevValue, value);
|
|
6553
6707
|
if (existing != null && typeof existing === "object" && "value" in existing) {
|
|
6554
|
-
target.rows[row][column] = { ...existing, value };
|
|
6708
|
+
target.rows[row][column] = { ...existing, value: coerced };
|
|
6555
6709
|
} else {
|
|
6556
|
-
target.rows[row][column] =
|
|
6710
|
+
target.rows[row][column] = coerced;
|
|
6557
6711
|
}
|
|
6558
6712
|
onChange?.(next);
|
|
6559
6713
|
return next;
|
|
6560
6714
|
});
|
|
6561
|
-
onCellEdit?.({ sheet: sheets?.[active]?.name ?? "", row, column, value });
|
|
6715
|
+
onCellEdit?.({ sheet: sheets?.[active]?.name ?? "", row, column, value: coerced });
|
|
6562
6716
|
}, [active, onCellEdit, onChange, sheets]);
|
|
6563
6717
|
const baseName = useMemo(
|
|
6564
6718
|
() => (fileName || (typeof source === "object" && "name" in source ? sourceName(source) : null) || "spreadsheet").replace(/\.[^.]+$/, ""),
|
|
@@ -6579,7 +6733,7 @@ function Spreadsheet({
|
|
|
6579
6733
|
XLSX.utils.book_append_sheet(wb, ws, (s.name || "Sheet").slice(0, 31));
|
|
6580
6734
|
});
|
|
6581
6735
|
const out = XLSX.write(wb, { bookType: "xlsx", type: "array" });
|
|
6582
|
-
|
|
6736
|
+
downloadBlob(new Blob([out], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }), `${baseName}.xlsx`);
|
|
6583
6737
|
}, [sheets, sheetAoa, baseName]);
|
|
6584
6738
|
const exportCsv = useCallback(() => {
|
|
6585
6739
|
if (!sheet) return;
|
|
@@ -6589,7 +6743,7 @@ function Spreadsheet({
|
|
|
6589
6743
|
return /[",\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
|
|
6590
6744
|
};
|
|
6591
6745
|
const csv = aoa.map((row) => row.map(esc).join(",")).join("\r\n");
|
|
6592
|
-
|
|
6746
|
+
downloadBlob(new Blob([`\uFEFF${csv}`], { type: "text/csv;charset=utf-8" }), `${baseName}.csv`);
|
|
6593
6747
|
}, [sheet, sheetAoa, baseName]);
|
|
6594
6748
|
const exportPdf = useCallback(async () => {
|
|
6595
6749
|
if (!sheet) return;
|
|
@@ -6645,9 +6799,14 @@ function Spreadsheet({
|
|
|
6645
6799
|
] });
|
|
6646
6800
|
}
|
|
6647
6801
|
const formats = exportFormats || [];
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6802
|
+
const exportLabels = {
|
|
6803
|
+
xlsx: "Excel workbook (.xlsx)",
|
|
6804
|
+
csv: "CSV \u2014 this sheet (.csv)",
|
|
6805
|
+
pdf: "PDF table (.pdf)"
|
|
6806
|
+
};
|
|
6807
|
+
return /* @__PURE__ */ jsxs("div", { className: cx("flex flex-col overflow-hidden rounded-lg border border-border bg-surface-raised", className), style, children: [
|
|
6808
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-shrink-0 items-center gap-2 border-b border-border bg-surface px-2 py-1.5", children: [
|
|
6809
|
+
sheets.length > 1 ? /* @__PURE__ */ jsx("div", { role: "tablist", "aria-label": "Sheets", className: "flex min-w-0 flex-1 items-center gap-0.5 overflow-x-auto", children: sheets.map((s, i) => /* @__PURE__ */ jsx(
|
|
6651
6810
|
"button",
|
|
6652
6811
|
{
|
|
6653
6812
|
role: "tab",
|
|
@@ -6655,14 +6814,40 @@ function Spreadsheet({
|
|
|
6655
6814
|
"aria-selected": i === active,
|
|
6656
6815
|
onClick: () => setActive(i),
|
|
6657
6816
|
className: cx(
|
|
6658
|
-
"rounded-md px-3 py-1 text-sm transition-colors",
|
|
6659
|
-
|
|
6817
|
+
"flex-shrink-0 rounded-md px-3 py-1 text-sm font-medium transition-colors",
|
|
6818
|
+
"focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
|
|
6819
|
+
i === active ? "bg-accent text-accent-fg shadow-sm" : "text-foreground-secondary hover:bg-surface-raised hover:text-foreground"
|
|
6660
6820
|
),
|
|
6661
6821
|
children: s.name || `Sheet ${i + 1}`
|
|
6662
6822
|
},
|
|
6663
6823
|
`${s.name}-${i}`
|
|
6664
|
-
)) }),
|
|
6665
|
-
|
|
6824
|
+
)) }) : /* @__PURE__ */ jsx("span", { className: "flex-1 truncate px-1 text-sm font-medium text-foreground", children: sheet?.name || "Sheet 1" }),
|
|
6825
|
+
/* @__PURE__ */ jsxs("span", { className: "hidden flex-shrink-0 px-1 text-xs tabular-nums text-foreground-muted sm:inline", children: [
|
|
6826
|
+
plainRows.length.toLocaleString(),
|
|
6827
|
+
" ",
|
|
6828
|
+
plainRows.length === 1 ? "row" : "rows",
|
|
6829
|
+
" \xB7 ",
|
|
6830
|
+
columns.length,
|
|
6831
|
+
" cols"
|
|
6832
|
+
] }),
|
|
6833
|
+
formats.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6834
|
+
/* @__PURE__ */ jsx("span", { className: "h-5 w-px flex-shrink-0 bg-border", "aria-hidden": "true" }),
|
|
6835
|
+
/* @__PURE__ */ jsx(
|
|
6836
|
+
MenuButton,
|
|
6837
|
+
{
|
|
6838
|
+
label: "Export",
|
|
6839
|
+
size: "sm",
|
|
6840
|
+
variant: "outline",
|
|
6841
|
+
align: "end",
|
|
6842
|
+
icon: /* @__PURE__ */ jsx(DownloadIcon2, {}),
|
|
6843
|
+
items: formats.map((fmt) => ({
|
|
6844
|
+
key: fmt,
|
|
6845
|
+
label: exportLabels[fmt],
|
|
6846
|
+
onSelect: () => runExport(fmt)
|
|
6847
|
+
}))
|
|
6848
|
+
}
|
|
6849
|
+
)
|
|
6850
|
+
] })
|
|
6666
6851
|
] }),
|
|
6667
6852
|
/* @__PURE__ */ jsx(
|
|
6668
6853
|
DataGrid,
|
|
@@ -6671,11 +6856,13 @@ function Spreadsheet({
|
|
|
6671
6856
|
rows: plainRows,
|
|
6672
6857
|
editable,
|
|
6673
6858
|
virtualize,
|
|
6674
|
-
onCellEdit: handleCellEdit
|
|
6859
|
+
onCellEdit: handleCellEdit,
|
|
6860
|
+
className: "!rounded-none !border-0"
|
|
6675
6861
|
}
|
|
6676
6862
|
)
|
|
6677
6863
|
] });
|
|
6678
6864
|
}
|
|
6865
|
+
var DownloadIcon2 = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 3v12m0 0 4-4m-4 4-4-4M4 21h16" }) });
|
|
6679
6866
|
function ThemeSwitch({ checked, onChange, label = "Toggle dark mode", className = "" }) {
|
|
6680
6867
|
const id = useId();
|
|
6681
6868
|
return /* @__PURE__ */ jsx("label", { htmlFor: id, className: `flex items-center gap-2 cursor-pointer select-none ${className}`.trim(), children: /* @__PURE__ */ jsx(
|