@algenium/blocks 1.7.0-rc.3 → 1.7.0-rc.4
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 +182 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -1
- package/dist/index.d.ts +19 -1
- package/dist/index.js +182 -27
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -8205,6 +8205,68 @@ function PdfPageCanvas({
|
|
|
8205
8205
|
}
|
|
8206
8206
|
);
|
|
8207
8207
|
}
|
|
8208
|
+
var PAGE_INPUT_CLASS = "h-8 w-14 rounded-md border px-2 text-sm tabular-nums shadow-sm border-neutral-300 bg-white text-neutral-950 caret-neutral-950 selection:bg-neutral-200 selection:text-neutral-950 dark:border-neutral-600 dark:bg-neutral-950 dark:text-neutral-50 dark:caret-neutral-50 dark:selection:bg-neutral-700 dark:selection:text-neutral-50";
|
|
8209
|
+
function touchPairDistance(touches) {
|
|
8210
|
+
if (touches.length < 2) return 0;
|
|
8211
|
+
const a = touches.item(0);
|
|
8212
|
+
const b = touches.item(1);
|
|
8213
|
+
return Math.hypot(a.clientX - b.clientX, a.clientY - b.clientY);
|
|
8214
|
+
}
|
|
8215
|
+
function PdfThumbnailStrip({
|
|
8216
|
+
page,
|
|
8217
|
+
pageNumber,
|
|
8218
|
+
active,
|
|
8219
|
+
onPick,
|
|
8220
|
+
label
|
|
8221
|
+
}) {
|
|
8222
|
+
const canvasRef = React2.useRef(null);
|
|
8223
|
+
React2.useEffect(() => {
|
|
8224
|
+
const canvas = canvasRef.current;
|
|
8225
|
+
if (!canvas) return;
|
|
8226
|
+
const viewport = page.getViewport({ scale: 1 });
|
|
8227
|
+
const thumbMax = 112;
|
|
8228
|
+
const s = thumbMax / Math.max(viewport.width, viewport.height);
|
|
8229
|
+
const vp = page.getViewport({ scale: s });
|
|
8230
|
+
const ctx = canvas.getContext("2d");
|
|
8231
|
+
if (!ctx) return;
|
|
8232
|
+
canvas.width = vp.width;
|
|
8233
|
+
canvas.height = vp.height;
|
|
8234
|
+
const task = page.render({
|
|
8235
|
+
canvasContext: ctx,
|
|
8236
|
+
viewport: vp,
|
|
8237
|
+
canvas
|
|
8238
|
+
});
|
|
8239
|
+
task.promise.catch(() => {
|
|
8240
|
+
});
|
|
8241
|
+
return () => {
|
|
8242
|
+
task.cancel();
|
|
8243
|
+
};
|
|
8244
|
+
}, [page]);
|
|
8245
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8246
|
+
"button",
|
|
8247
|
+
{
|
|
8248
|
+
type: "button",
|
|
8249
|
+
onClick: () => onPick(pageNumber),
|
|
8250
|
+
className: cn(
|
|
8251
|
+
"flex w-full flex-col items-center gap-1 rounded-md p-1 transition-colors hover:bg-muted/80",
|
|
8252
|
+
active ? "bg-muted ring-2 ring-ring" : ""
|
|
8253
|
+
),
|
|
8254
|
+
"aria-label": label,
|
|
8255
|
+
"aria-current": active ? "page" : void 0,
|
|
8256
|
+
children: [
|
|
8257
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8258
|
+
"canvas",
|
|
8259
|
+
{
|
|
8260
|
+
ref: canvasRef,
|
|
8261
|
+
className: "block max-w-full rounded-sm shadow-sm",
|
|
8262
|
+
"aria-hidden": true
|
|
8263
|
+
}
|
|
8264
|
+
),
|
|
8265
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-[10px] tabular-nums", children: pageNumber })
|
|
8266
|
+
]
|
|
8267
|
+
}
|
|
8268
|
+
);
|
|
8269
|
+
}
|
|
8208
8270
|
function PdfViewer({
|
|
8209
8271
|
src,
|
|
8210
8272
|
workerSrc,
|
|
@@ -8215,6 +8277,9 @@ function PdfViewer({
|
|
|
8215
8277
|
maxScale = 4,
|
|
8216
8278
|
scaleStep = 0.2,
|
|
8217
8279
|
enableKeyboardShortcuts = true,
|
|
8280
|
+
enablePinchZoom = true,
|
|
8281
|
+
enableThumbnailSidebar = true,
|
|
8282
|
+
thumbnailSidebarDefaultOpen = true,
|
|
8218
8283
|
labels,
|
|
8219
8284
|
onLoad,
|
|
8220
8285
|
onError,
|
|
@@ -8245,6 +8310,9 @@ function PdfViewer({
|
|
|
8245
8310
|
const [scale, setScale] = React2.useState(initialScale);
|
|
8246
8311
|
const [ratios, setRatios] = React2.useState({});
|
|
8247
8312
|
const [pageInput, setPageInput] = React2.useState(String(initialPage));
|
|
8313
|
+
const [thumbnailSidebarOpen, setThumbnailSidebarOpen] = React2.useState(
|
|
8314
|
+
thumbnailSidebarDefaultOpen
|
|
8315
|
+
);
|
|
8248
8316
|
const baselineScaleRef = React2.useRef(initialScale);
|
|
8249
8317
|
React2.useEffect(() => {
|
|
8250
8318
|
baselineScaleRef.current = initialScale;
|
|
@@ -8255,6 +8323,9 @@ function PdfViewer({
|
|
|
8255
8323
|
const zoomOutLabel = mergedLabels.zoomOut ?? "Zoom out";
|
|
8256
8324
|
const resetZoomLabel = mergedLabels.resetZoom ?? "Reset zoom";
|
|
8257
8325
|
const fitWidthLabel = mergedLabels.fitToWidth ?? "Fit to width";
|
|
8326
|
+
const thumbnailSidebarLabel = mergedLabels.thumbnailSidebar ?? "Page thumbnails";
|
|
8327
|
+
const toggleThumbLabel = mergedLabels.toggleThumbnailSidebar ?? "Toggle page thumbnails";
|
|
8328
|
+
const pageThumbLabel = mergedLabels.pageThumbnail ?? ((n) => `Page ${n}, show in document`);
|
|
8258
8329
|
const pageCount = layouts.length;
|
|
8259
8330
|
const currentVisiblePage = React2.useMemo(() => {
|
|
8260
8331
|
let bestPage = 1;
|
|
@@ -8414,6 +8485,54 @@ function PdfViewer({
|
|
|
8414
8485
|
React2.useEffect(() => {
|
|
8415
8486
|
setScale(clampScaleValue(initialScale));
|
|
8416
8487
|
}, [initialScale, clampScaleValue]);
|
|
8488
|
+
React2.useEffect(() => {
|
|
8489
|
+
const el = scrollRef.current;
|
|
8490
|
+
if (!el || !enablePinchZoom) return;
|
|
8491
|
+
let pinchDist = 0;
|
|
8492
|
+
const onWheel = (e) => {
|
|
8493
|
+
if (!e.ctrlKey) return;
|
|
8494
|
+
e.preventDefault();
|
|
8495
|
+
const delta = -e.deltaY;
|
|
8496
|
+
const factor = Math.exp(delta * 2e-3);
|
|
8497
|
+
setScale((prev) => {
|
|
8498
|
+
const c = clampScaleValue(prev * factor);
|
|
8499
|
+
onScaleChange?.(c);
|
|
8500
|
+
return c;
|
|
8501
|
+
});
|
|
8502
|
+
};
|
|
8503
|
+
const onTouchStart = (e) => {
|
|
8504
|
+
if (e.touches.length === 2) {
|
|
8505
|
+
pinchDist = touchPairDistance(e.touches);
|
|
8506
|
+
}
|
|
8507
|
+
};
|
|
8508
|
+
const onTouchMove = (e) => {
|
|
8509
|
+
if (e.touches.length !== 2 || pinchDist <= 0) return;
|
|
8510
|
+
e.preventDefault();
|
|
8511
|
+
const d = touchPairDistance(e.touches);
|
|
8512
|
+
const ratio = d / pinchDist;
|
|
8513
|
+
pinchDist = d;
|
|
8514
|
+
setScale((prev) => {
|
|
8515
|
+
const c = clampScaleValue(prev * ratio);
|
|
8516
|
+
onScaleChange?.(c);
|
|
8517
|
+
return c;
|
|
8518
|
+
});
|
|
8519
|
+
};
|
|
8520
|
+
const endPinch = (e) => {
|
|
8521
|
+
if (e.touches.length < 2) pinchDist = 0;
|
|
8522
|
+
};
|
|
8523
|
+
el.addEventListener("wheel", onWheel, { passive: false });
|
|
8524
|
+
el.addEventListener("touchstart", onTouchStart, { passive: true });
|
|
8525
|
+
el.addEventListener("touchmove", onTouchMove, { passive: false });
|
|
8526
|
+
el.addEventListener("touchend", endPinch);
|
|
8527
|
+
el.addEventListener("touchcancel", endPinch);
|
|
8528
|
+
return () => {
|
|
8529
|
+
el.removeEventListener("wheel", onWheel);
|
|
8530
|
+
el.removeEventListener("touchstart", onTouchStart);
|
|
8531
|
+
el.removeEventListener("touchmove", onTouchMove);
|
|
8532
|
+
el.removeEventListener("touchend", endPinch);
|
|
8533
|
+
el.removeEventListener("touchcancel", endPinch);
|
|
8534
|
+
};
|
|
8535
|
+
}, [enablePinchZoom, clampScaleValue, onScaleChange]);
|
|
8417
8536
|
React2.useEffect(() => {
|
|
8418
8537
|
if (layouts.length === 0) return;
|
|
8419
8538
|
const frame = requestAnimationFrame(() => {
|
|
@@ -8558,7 +8677,7 @@ function PdfViewer({
|
|
|
8558
8677
|
min: 1,
|
|
8559
8678
|
max: Math.max(pageCount, 1),
|
|
8560
8679
|
disabled: busy || pageCount === 0,
|
|
8561
|
-
className:
|
|
8680
|
+
className: PAGE_INPUT_CLASS,
|
|
8562
8681
|
"aria-label": resolvedGoToLabel,
|
|
8563
8682
|
value: pageInput,
|
|
8564
8683
|
onChange: (ev) => setPageInput(ev.target.value),
|
|
@@ -8622,32 +8741,68 @@ function PdfViewer({
|
|
|
8622
8741
|
]
|
|
8623
8742
|
}
|
|
8624
8743
|
),
|
|
8625
|
-
/* @__PURE__ */ jsxRuntime.
|
|
8626
|
-
|
|
8627
|
-
|
|
8628
|
-
|
|
8629
|
-
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
|
|
8633
|
-
|
|
8634
|
-
|
|
8635
|
-
|
|
8636
|
-
|
|
8637
|
-
|
|
8638
|
-
|
|
8639
|
-
|
|
8640
|
-
|
|
8641
|
-
|
|
8642
|
-
|
|
8643
|
-
|
|
8644
|
-
|
|
8645
|
-
|
|
8646
|
-
|
|
8647
|
-
|
|
8648
|
-
|
|
8649
|
-
|
|
8650
|
-
|
|
8744
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-1 overflow-hidden", children: [
|
|
8745
|
+
enableThumbnailSidebar && !busy && pagesMap !== null && pageCount > 0 && thumbnailSidebarOpen ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8746
|
+
"nav",
|
|
8747
|
+
{
|
|
8748
|
+
className: "bg-muted/30 flex w-[132px] shrink-0 flex-col overflow-y-auto border-r py-2 pl-2 pr-1",
|
|
8749
|
+
"aria-label": thumbnailSidebarLabel,
|
|
8750
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-1", children: layouts.map((layout) => {
|
|
8751
|
+
const pg = pagesMap.get(layout.pageNumber);
|
|
8752
|
+
return pg ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8753
|
+
PdfThumbnailStrip,
|
|
8754
|
+
{
|
|
8755
|
+
page: pg,
|
|
8756
|
+
pageNumber: layout.pageNumber,
|
|
8757
|
+
active: layout.pageNumber === currentVisiblePage,
|
|
8758
|
+
onPick: scrollToPage,
|
|
8759
|
+
label: pageThumbLabel(layout.pageNumber)
|
|
8760
|
+
},
|
|
8761
|
+
`thumb-${layout.pageNumber}`
|
|
8762
|
+
) : null;
|
|
8763
|
+
}) })
|
|
8764
|
+
}
|
|
8765
|
+
) : null,
|
|
8766
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 min-w-0 flex-1", children: [
|
|
8767
|
+
enableThumbnailSidebar && !busy && pagesMap !== null && pageCount > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8768
|
+
"button",
|
|
8769
|
+
{
|
|
8770
|
+
type: "button",
|
|
8771
|
+
className: "text-muted-foreground hover:bg-muted/60 flex w-9 shrink-0 flex-col items-center justify-center border-r bg-transparent transition-colors",
|
|
8772
|
+
onClick: () => setThumbnailSidebarOpen((v) => !v),
|
|
8773
|
+
"aria-label": toggleThumbLabel,
|
|
8774
|
+
"aria-expanded": thumbnailSidebarOpen,
|
|
8775
|
+
children: thumbnailSidebarOpen ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { className: "size-4", "aria-hidden": true }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "size-4", "aria-hidden": true })
|
|
8776
|
+
}
|
|
8777
|
+
) : null,
|
|
8778
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8779
|
+
"div",
|
|
8780
|
+
{
|
|
8781
|
+
ref: scrollRef,
|
|
8782
|
+
tabIndex: 0,
|
|
8783
|
+
onKeyDown: handleKeyDown,
|
|
8784
|
+
className: "relative min-h-[240px] min-w-0 flex-1 overflow-auto outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
8785
|
+
"aria-busy": busy,
|
|
8786
|
+
"aria-label": busy ? loadingLabel : "PDF pages",
|
|
8787
|
+
children: busy || pagesMap === null ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground p-6 text-sm", children: loadingLabel }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col items-center gap-4 pb-8 pt-2", children: layouts.map((layout) => {
|
|
8788
|
+
const pg = pagesMap.get(layout.pageNumber);
|
|
8789
|
+
const visible = (ratios[layout.pageNumber] ?? 0) >= 1e-3;
|
|
8790
|
+
return pg ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8791
|
+
PdfPageCanvas,
|
|
8792
|
+
{
|
|
8793
|
+
page: pg,
|
|
8794
|
+
layout,
|
|
8795
|
+
scale,
|
|
8796
|
+
visible,
|
|
8797
|
+
pageClassName
|
|
8798
|
+
},
|
|
8799
|
+
layout.pageNumber
|
|
8800
|
+
) : null;
|
|
8801
|
+
}) })
|
|
8802
|
+
}
|
|
8803
|
+
)
|
|
8804
|
+
] })
|
|
8805
|
+
] })
|
|
8651
8806
|
]
|
|
8652
8807
|
}
|
|
8653
8808
|
);
|