@algenium/blocks 1.7.0-rc.3 → 1.7.0-rc.5
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 +186 -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 +187 -28
- 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 = 176;
|
|
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-2 transition-colors hover:bg-white/5",
|
|
8252
|
+
active ? "bg-white/10" : ""
|
|
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 overflow-hidden rounded-sm bg-black",
|
|
8262
|
+
"aria-hidden": true
|
|
8263
|
+
}
|
|
8264
|
+
),
|
|
8265
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] tabular-nums text-neutral-400", 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,
|
|
@@ -8232,6 +8297,7 @@ function PdfViewer({
|
|
|
8232
8297
|
const errorLabelFallback = mergedLabels.error ?? "Failed to load PDF";
|
|
8233
8298
|
const toolbarId = React2.useId();
|
|
8234
8299
|
const pageInputId = `${toolbarId}-page`;
|
|
8300
|
+
const thumbnailNavId = `${toolbarId}-thumbnails`;
|
|
8235
8301
|
const scrollRef = React2.useRef(null);
|
|
8236
8302
|
const observerRef = React2.useRef(null);
|
|
8237
8303
|
const lastReportedPage = React2.useRef(0);
|
|
@@ -8245,6 +8311,9 @@ function PdfViewer({
|
|
|
8245
8311
|
const [scale, setScale] = React2.useState(initialScale);
|
|
8246
8312
|
const [ratios, setRatios] = React2.useState({});
|
|
8247
8313
|
const [pageInput, setPageInput] = React2.useState(String(initialPage));
|
|
8314
|
+
const [thumbnailSidebarOpen, setThumbnailSidebarOpen] = React2.useState(
|
|
8315
|
+
thumbnailSidebarDefaultOpen
|
|
8316
|
+
);
|
|
8248
8317
|
const baselineScaleRef = React2.useRef(initialScale);
|
|
8249
8318
|
React2.useEffect(() => {
|
|
8250
8319
|
baselineScaleRef.current = initialScale;
|
|
@@ -8255,6 +8324,9 @@ function PdfViewer({
|
|
|
8255
8324
|
const zoomOutLabel = mergedLabels.zoomOut ?? "Zoom out";
|
|
8256
8325
|
const resetZoomLabel = mergedLabels.resetZoom ?? "Reset zoom";
|
|
8257
8326
|
const fitWidthLabel = mergedLabels.fitToWidth ?? "Fit to width";
|
|
8327
|
+
const thumbnailSidebarLabel = mergedLabels.thumbnailSidebar ?? "Page thumbnails";
|
|
8328
|
+
const toggleThumbLabel = mergedLabels.toggleThumbnailSidebar ?? "Toggle page thumbnails";
|
|
8329
|
+
const pageThumbLabel = mergedLabels.pageThumbnail ?? ((n) => `Page ${n}, show in document`);
|
|
8258
8330
|
const pageCount = layouts.length;
|
|
8259
8331
|
const currentVisiblePage = React2.useMemo(() => {
|
|
8260
8332
|
let bestPage = 1;
|
|
@@ -8414,6 +8486,54 @@ function PdfViewer({
|
|
|
8414
8486
|
React2.useEffect(() => {
|
|
8415
8487
|
setScale(clampScaleValue(initialScale));
|
|
8416
8488
|
}, [initialScale, clampScaleValue]);
|
|
8489
|
+
React2.useEffect(() => {
|
|
8490
|
+
const el = scrollRef.current;
|
|
8491
|
+
if (!el || !enablePinchZoom) return;
|
|
8492
|
+
let pinchDist = 0;
|
|
8493
|
+
const onWheel = (e) => {
|
|
8494
|
+
if (!e.ctrlKey) return;
|
|
8495
|
+
e.preventDefault();
|
|
8496
|
+
const delta = -e.deltaY;
|
|
8497
|
+
const factor = Math.exp(delta * 2e-3);
|
|
8498
|
+
setScale((prev) => {
|
|
8499
|
+
const c = clampScaleValue(prev * factor);
|
|
8500
|
+
onScaleChange?.(c);
|
|
8501
|
+
return c;
|
|
8502
|
+
});
|
|
8503
|
+
};
|
|
8504
|
+
const onTouchStart = (e) => {
|
|
8505
|
+
if (e.touches.length === 2) {
|
|
8506
|
+
pinchDist = touchPairDistance(e.touches);
|
|
8507
|
+
}
|
|
8508
|
+
};
|
|
8509
|
+
const onTouchMove = (e) => {
|
|
8510
|
+
if (e.touches.length !== 2 || pinchDist <= 0) return;
|
|
8511
|
+
e.preventDefault();
|
|
8512
|
+
const d = touchPairDistance(e.touches);
|
|
8513
|
+
const ratio = d / pinchDist;
|
|
8514
|
+
pinchDist = d;
|
|
8515
|
+
setScale((prev) => {
|
|
8516
|
+
const c = clampScaleValue(prev * ratio);
|
|
8517
|
+
onScaleChange?.(c);
|
|
8518
|
+
return c;
|
|
8519
|
+
});
|
|
8520
|
+
};
|
|
8521
|
+
const endPinch = (e) => {
|
|
8522
|
+
if (e.touches.length < 2) pinchDist = 0;
|
|
8523
|
+
};
|
|
8524
|
+
el.addEventListener("wheel", onWheel, { passive: false });
|
|
8525
|
+
el.addEventListener("touchstart", onTouchStart, { passive: true });
|
|
8526
|
+
el.addEventListener("touchmove", onTouchMove, { passive: false });
|
|
8527
|
+
el.addEventListener("touchend", endPinch);
|
|
8528
|
+
el.addEventListener("touchcancel", endPinch);
|
|
8529
|
+
return () => {
|
|
8530
|
+
el.removeEventListener("wheel", onWheel);
|
|
8531
|
+
el.removeEventListener("touchstart", onTouchStart);
|
|
8532
|
+
el.removeEventListener("touchmove", onTouchMove);
|
|
8533
|
+
el.removeEventListener("touchend", endPinch);
|
|
8534
|
+
el.removeEventListener("touchcancel", endPinch);
|
|
8535
|
+
};
|
|
8536
|
+
}, [enablePinchZoom, clampScaleValue, onScaleChange]);
|
|
8417
8537
|
React2.useEffect(() => {
|
|
8418
8538
|
if (layouts.length === 0) return;
|
|
8419
8539
|
const frame = requestAnimationFrame(() => {
|
|
@@ -8519,6 +8639,7 @@ function PdfViewer({
|
|
|
8519
8639
|
resetZoomAct
|
|
8520
8640
|
]
|
|
8521
8641
|
);
|
|
8642
|
+
const thumbnailsRailEligible = enableThumbnailSidebar && !busy && pagesMap !== null && pageCount > 0;
|
|
8522
8643
|
if (loadError) {
|
|
8523
8644
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8524
8645
|
"div",
|
|
@@ -8548,6 +8669,20 @@ function PdfViewer({
|
|
|
8548
8669
|
toolbarClassName
|
|
8549
8670
|
),
|
|
8550
8671
|
children: [
|
|
8672
|
+
thumbnailsRailEligible ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8673
|
+
Button,
|
|
8674
|
+
{
|
|
8675
|
+
type: "button",
|
|
8676
|
+
variant: "outline",
|
|
8677
|
+
size: "icon-sm",
|
|
8678
|
+
className: "hidden md:inline-flex",
|
|
8679
|
+
onClick: () => setThumbnailSidebarOpen((v) => !v),
|
|
8680
|
+
"aria-label": toggleThumbLabel,
|
|
8681
|
+
"aria-expanded": thumbnailSidebarOpen,
|
|
8682
|
+
"aria-controls": thumbnailNavId,
|
|
8683
|
+
children: thumbnailSidebarOpen ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PanelLeftOpen, { className: "size-4", "aria-hidden": true }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PanelRightOpen, { className: "size-4", "aria-hidden": true })
|
|
8684
|
+
}
|
|
8685
|
+
) : null,
|
|
8551
8686
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-xs tabular-nums sm:text-sm", children: busy || pagesMap === null ? "\u2014" : pageOfFormatter(currentVisiblePage, pageCount) }),
|
|
8552
8687
|
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: pageInputId, className: "sr-only", children: resolvedGoToLabel }),
|
|
8553
8688
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -8558,7 +8693,7 @@ function PdfViewer({
|
|
|
8558
8693
|
min: 1,
|
|
8559
8694
|
max: Math.max(pageCount, 1),
|
|
8560
8695
|
disabled: busy || pageCount === 0,
|
|
8561
|
-
className:
|
|
8696
|
+
className: PAGE_INPUT_CLASS,
|
|
8562
8697
|
"aria-label": resolvedGoToLabel,
|
|
8563
8698
|
value: pageInput,
|
|
8564
8699
|
onChange: (ev) => setPageInput(ev.target.value),
|
|
@@ -8622,32 +8757,56 @@ function PdfViewer({
|
|
|
8622
8757
|
]
|
|
8623
8758
|
}
|
|
8624
8759
|
),
|
|
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
|
-
|
|
8760
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-1 overflow-hidden", children: [
|
|
8761
|
+
thumbnailsRailEligible && thumbnailSidebarOpen ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8762
|
+
"nav",
|
|
8763
|
+
{
|
|
8764
|
+
id: thumbnailNavId,
|
|
8765
|
+
className: "hidden w-[220px] shrink-0 flex-col overflow-y-auto border-r border-neutral-900 bg-black py-3 pl-3 pr-2 md:flex",
|
|
8766
|
+
"aria-label": thumbnailSidebarLabel,
|
|
8767
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2", children: layouts.map((layout) => {
|
|
8768
|
+
const pg = pagesMap.get(layout.pageNumber);
|
|
8769
|
+
return pg ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8770
|
+
PdfThumbnailStrip,
|
|
8771
|
+
{
|
|
8772
|
+
page: pg,
|
|
8773
|
+
pageNumber: layout.pageNumber,
|
|
8774
|
+
active: layout.pageNumber === currentVisiblePage,
|
|
8775
|
+
onPick: scrollToPage,
|
|
8776
|
+
label: pageThumbLabel(layout.pageNumber)
|
|
8777
|
+
},
|
|
8778
|
+
`thumb-${layout.pageNumber}`
|
|
8779
|
+
) : null;
|
|
8780
|
+
}) })
|
|
8781
|
+
}
|
|
8782
|
+
) : null,
|
|
8783
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8784
|
+
"div",
|
|
8785
|
+
{
|
|
8786
|
+
ref: scrollRef,
|
|
8787
|
+
tabIndex: 0,
|
|
8788
|
+
onKeyDown: handleKeyDown,
|
|
8789
|
+
className: "relative min-h-[240px] min-w-0 flex-1 overflow-auto outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
8790
|
+
"aria-busy": busy,
|
|
8791
|
+
"aria-label": busy ? loadingLabel : "PDF pages",
|
|
8792
|
+
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) => {
|
|
8793
|
+
const pg = pagesMap.get(layout.pageNumber);
|
|
8794
|
+
const visible = (ratios[layout.pageNumber] ?? 0) >= 1e-3;
|
|
8795
|
+
return pg ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8796
|
+
PdfPageCanvas,
|
|
8797
|
+
{
|
|
8798
|
+
page: pg,
|
|
8799
|
+
layout,
|
|
8800
|
+
scale,
|
|
8801
|
+
visible,
|
|
8802
|
+
pageClassName
|
|
8803
|
+
},
|
|
8804
|
+
layout.pageNumber
|
|
8805
|
+
) : null;
|
|
8806
|
+
}) })
|
|
8807
|
+
}
|
|
8808
|
+
)
|
|
8809
|
+
] })
|
|
8651
8810
|
]
|
|
8652
8811
|
}
|
|
8653
8812
|
);
|