@poco-ai/agentero-dsh-pdf 0.0.0-stage → 0.1.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.
Files changed (44) hide show
  1. package/lib/client/bookmark.d.ts +34 -0
  2. package/lib/client/button.d.ts +16 -0
  3. package/lib/client/chat-actions.d.ts +7 -0
  4. package/lib/client/cn.d.ts +3 -0
  5. package/lib/client/comment-cards.d.ts +35 -0
  6. package/lib/client/embed-reader.d.ts +48 -0
  7. package/lib/client/engine.d.ts +3 -0
  8. package/lib/client/find.d.ts +22 -0
  9. package/lib/client/highlight-color-stack.d.ts +24 -0
  10. package/lib/client/index.d.ts +31 -0
  11. package/lib/client/link-layer.d.ts +27 -0
  12. package/lib/client/link-target.d.ts +2 -0
  13. package/lib/client/locale.d.ts +80 -0
  14. package/lib/client/outline.d.ts +25 -0
  15. package/lib/client/page-theme.d.ts +36 -0
  16. package/lib/client/palette.d.ts +25 -0
  17. package/lib/client/pan-drag.d.ts +31 -0
  18. package/lib/client/pan-handler.d.ts +20 -0
  19. package/lib/client/pdf-bottom-bar.d.ts +25 -0
  20. package/lib/client/pdf-chrome-surface.d.ts +23 -0
  21. package/lib/client/pdf-panel.d.ts +66 -0
  22. package/lib/client/pdf-toolbar.d.ts +11 -0
  23. package/lib/client/popover.d.ts +10 -0
  24. package/lib/client/selection-menu.d.ts +30 -0
  25. package/lib/client/tooltip.d.ts +7 -0
  26. package/lib/client/translate-card.d.ts +37 -0
  27. package/lib/client/translation/coverage.d.ts +15 -0
  28. package/lib/client/translation/extract.d.ts +7 -0
  29. package/lib/client/translation/fonts.d.ts +6 -0
  30. package/lib/client/translation/layout.d.ts +19 -0
  31. package/lib/client/translation/page-overlay.d.ts +10 -0
  32. package/lib/client/translation/reading-order.d.ts +20 -0
  33. package/lib/client/translation/regions.d.ts +17 -0
  34. package/lib/client/translation/translate-paragraph.d.ts +5 -0
  35. package/lib/client/translation/types.d.ts +107 -0
  36. package/lib/client/translation/use-page-translation.d.ts +23 -0
  37. package/lib/client/zoom.d.ts +32 -0
  38. package/lib/client.js +58413 -0
  39. package/lib/index.d.ts +4 -0
  40. package/lib/index.js +5 -0
  41. package/lib/index.js.map +1 -0
  42. package/package.json +57 -3
  43. package/src/client/translation/MOTIF-LICENSE.txt +21 -0
  44. package/README.md +0 -3
@@ -0,0 +1,30 @@
1
+ import type { PropsLocale } from "@deepseek-ai/dsh-client-ui-slots";
2
+ import type { HighlightColor } from "./palette";
3
+ type PdfT = PropsLocale<"agentero.pdf">["t"];
4
+ type SelectionMenuProps = {
5
+ /** Screen point near the top-center of the selection (toolbar anchor). */
6
+ screen: {
7
+ x: number;
8
+ y: number;
9
+ };
10
+ mode: "actions" | "comment" | "ask";
11
+ draft: string;
12
+ busy: boolean;
13
+ t: PdfT;
14
+ onCopy: () => Promise<boolean>;
15
+ /** Every swatch calls this with the chosen palette key. */
16
+ onHighlight: (color: HighlightColor) => void;
17
+ onComment: () => void;
18
+ onTranslate: () => void;
19
+ onAsk: () => void;
20
+ onDraftChange: (value: string) => void;
21
+ onSubmitDraft: () => void;
22
+ };
23
+ /**
24
+ * Floating action bar shown next to a text selection: overlapping highlight
25
+ * color dots (fan left on hover), then Translate / Comment / Copy / Quick chat / Add to chat.
26
+ * Copy keeps the bar open and swaps the icon for a check.
27
+ * The bar is pinned by its right edge so expanding colors only grow left.
28
+ */
29
+ export declare function SelectionMenu({ screen, mode, draft, busy, t, onCopy, onHighlight, onComment, onTranslate, onAsk, onDraftChange, onSubmitDraft, }: SelectionMenuProps): import("react").JSX.Element;
30
+ export {};
@@ -0,0 +1,7 @@
1
+ import { Tooltip as TooltipPrimitive } from "radix-ui";
2
+ import type * as React from "react";
3
+ declare function TooltipProvider({ delayDuration, ...props }: React.ComponentProps<typeof TooltipPrimitive.Provider>): React.JSX.Element;
4
+ declare function Tooltip({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Root>): React.JSX.Element;
5
+ declare function TooltipTrigger({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Trigger>): React.JSX.Element;
6
+ declare function TooltipContent({ className, sideOffset, children, ...props }: React.ComponentProps<typeof TooltipPrimitive.Content>): React.JSX.Element;
7
+ export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
@@ -0,0 +1,37 @@
1
+ import type { PropsLocale } from '@deepseek-ai/dsh-client-ui-slots';
2
+ import { type ReactNode } from 'react';
3
+ type PdfT = PropsLocale<'agentero.pdf'>['t'];
4
+ export interface TranslateCardAnchor {
5
+ x: number;
6
+ y: number;
7
+ }
8
+ export interface TranslateCardProps {
9
+ anchor: TranslateCardAnchor;
10
+ result: string;
11
+ error: string;
12
+ loading: boolean;
13
+ pinned: boolean;
14
+ onTogglePin: () => void;
15
+ onClose: () => void;
16
+ t: PdfT;
17
+ }
18
+ /**
19
+ * Selection translation result. Mirrors the motif translate card: a small
20
+ * floating card anchored next to the selected text, with a pin that keeps the
21
+ * result reachable after the card is dismissed.
22
+ */
23
+ export declare function TranslateCard({ anchor, result, error, loading, pinned, onTogglePin, onClose, t, }: TranslateCardProps): ReactNode;
24
+ /**
25
+ * Small chip pinned to the selected text on the page itself. It lives inside
26
+ * the page layer, so it scrolls and zooms with the document instead of
27
+ * drifting across the paper when the reader moves.
28
+ *
29
+ * `x` / `y` are fractions (0–1) of the page box.
30
+ */
31
+ export declare function TranslateCardPin({ x, y, onOpen, t, }: {
32
+ x: number;
33
+ y: number;
34
+ onOpen: (screen: TranslateCardAnchor) => void;
35
+ t: PdfT;
36
+ }): ReactNode;
37
+ export {};
@@ -0,0 +1,15 @@
1
+ import type { CharacterCoverage, CharacterDisposition } from "./types";
2
+ import { type Character, type Paragraph } from "./types";
3
+ /** Use engine angles; retain a conservative fallback for older cached IR. */
4
+ export declare function rotatedCharacterIndexes(chars: readonly Character[]): Set<number>;
5
+ /** Split fallback lines at spatial gaps so separate plot labels never join. */
6
+ export declare function fallbackCharacterGroups(chars: readonly Character[]): Character[][];
7
+ export declare function characterCoverage(chars: readonly Character[], paragraphs: readonly Paragraph[], preserved: ReadonlyMap<number, CharacterDisposition>): CharacterCoverage[];
8
+ /** Rendering observes inherited clipping that PDFium text extraction omits.
9
+ * This is a conservative ink check, not reconstruction of the clipping path.
10
+ */
11
+ export declare function nonPaintingCharacters(chars: readonly Character[], image: {
12
+ width: number;
13
+ height: number;
14
+ data: Uint8ClampedArray;
15
+ }, pageWidth: number, pageHeight: number): Set<number>;
@@ -0,0 +1,7 @@
1
+ import type { PdfDocumentObject, PdfEngine } from "@embedpdf/models";
2
+ import type { LayoutTranslateItem, PdfLayoutRegion } from "./regions";
3
+ import { type Box, type Character, type Paragraph, type ReflowDocument } from "./types";
4
+ /** Detect visual formula islands, including adjacent scripts and punctuation. */
5
+ export declare function paragraphFromCharacters(id: string, pageIndex: number, box: Box, chars: Character[], formulaBoxes: Box[], heading: boolean): Paragraph;
6
+ /** Index-based extraction avoids matching normalized run strings to geometry. */
7
+ export declare function extractReflowDocument(engine: PdfEngine, doc: PdfDocumentObject, items: readonly LayoutTranslateItem[], regions: readonly PdfLayoutRegion[], signal?: AbortSignal): Promise<ReflowDocument>;
@@ -0,0 +1,6 @@
1
+ import type { ReflowFonts } from './layout';
2
+ import type { FontKey } from './types';
3
+ export declare const fontFamily = "\"Noto Serif CJK SC\", \"Songti SC\", \"SimSun\", serif";
4
+ export declare function fontCss(key: FontKey, size: number): string;
5
+ /** Measure the same browser font that paints the page overlay. No font download required. */
6
+ export declare function browserReflowFonts(): ReflowFonts;
@@ -0,0 +1,19 @@
1
+ /** Browser metrics replace pdf-lib fonts; placement and fitting are unchanged. */
2
+ export interface PDFFont {
3
+ encodeText(text: string): unknown;
4
+ widthOfTextAtSize(text: string, size: number): number;
5
+ heightAtSize(size: number, options?: {
6
+ descender: boolean;
7
+ }): number;
8
+ }
9
+ import { type Box, type FontKey, type PageLayout, type Paragraph, type ParagraphLayout, type PlacedUnit, type ReflowDocument, type ReflowPage } from "./types";
10
+ export type ReflowFonts = Record<FontKey, PDFFont>;
11
+ type Unit = Omit<PlacedUnit, "x" | "y"> & {
12
+ cjk: boolean;
13
+ space: boolean;
14
+ };
15
+ export declare function translationUnits(p: Paragraph, text: string, fonts: ReflowFonts): Unit[];
16
+ export declare function layoutParagraph(p: Paragraph, text: string, page: ReflowPage, fonts: ReflowFonts, initialScale?: number, occupied?: Box[]): ParagraphLayout;
17
+ /** Full-document pass, then a translated-unit-weighted common scale pass. */
18
+ export declare function layoutReflowDocument(ir: ReflowDocument, translations: ReadonlyMap<string, string>, fonts: ReflowFonts, commonScale?: boolean): PageLayout[];
19
+ export {};
@@ -0,0 +1,10 @@
1
+ import { type ReactNode } from 'react';
2
+ import type { TranslatedPage } from './use-page-translation';
3
+ import type { PdfPaperTone } from '../page-theme';
4
+ /** Same page boxes and reflow units as motif; source PDF pixels stay underneath. */
5
+ export declare const PageTranslationOverlay: import("react").MemoExoticComponent<({ state, width, height, tone }: {
6
+ state: TranslatedPage | undefined;
7
+ width: number;
8
+ height: number;
9
+ tone: PdfPaperTone;
10
+ }) => ReactNode>;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Reading order for PDF text runs inside one layout box.
3
+ *
4
+ * A bolder or larger word sticks up, so its top is higher than the words
5
+ * beside it, while the bottoms still share a baseline. Group by that bottom,
6
+ * left to right, then the next line down.
7
+ */
8
+ export type ReadingBox = {
9
+ x: number;
10
+ y: number;
11
+ width: number;
12
+ height: number;
13
+ };
14
+ export type ReadingLine<T> = {
15
+ items: T[];
16
+ top: number;
17
+ bottom: number;
18
+ };
19
+ export declare function groupReadingLines<T>(items: readonly T[], boxOf: (item: T) => ReadingBox): ReadingLine<T>[];
20
+ export declare function orderByReadingLine<T>(items: readonly T[], boxOf: (item: T) => ReadingBox): T[];
@@ -0,0 +1,17 @@
1
+ import type { PdfTextRun } from '@embedpdf/models';
2
+ import { type Box } from './types';
3
+ export interface PdfLayoutRegion {
4
+ id: string;
5
+ pageIndex: number;
6
+ kind: string;
7
+ label: string;
8
+ score: number;
9
+ readingOrder: number;
10
+ rect: Box;
11
+ bbox: Box;
12
+ }
13
+ export type LayoutTranslateItem = Pick<PdfLayoutRegion, 'id' | 'pageIndex' | 'kind' | 'bbox'>;
14
+ /** Motif stores normalized boxes in source/layout.json. Ignore unusable records. */
15
+ export declare function parseLayoutRegions(raw: unknown): PdfLayoutRegion[];
16
+ /** Text-only fallback: baseline grouping from motif, split columns before joining paragraphs. */
17
+ export declare function regionsFromRuns(runs: readonly PdfTextRun[], pageIndex: number, width: number, height: number): PdfLayoutRegion[];
@@ -0,0 +1,5 @@
1
+ import { type Paragraph } from './types';
2
+ type Translate = (text: string, signal?: AbortSignal) => Promise<string>;
3
+ /** Motif's protected-spans fallback: keep formula/style boundaries outside the model. */
4
+ export declare function translateParagraph(paragraph: Paragraph, translate: Translate, signal: AbortSignal): Promise<string>;
5
+ export {};
@@ -0,0 +1,107 @@
1
+ /** Coordinates throughout the IR are page points, top-left origin. */
2
+ export type Box = {
3
+ x: number;
4
+ y: number;
5
+ w: number;
6
+ h: number;
7
+ };
8
+ export type CharacterStyle = {
9
+ font: string;
10
+ size: number;
11
+ bold: boolean;
12
+ italic: boolean;
13
+ color: {
14
+ r: number;
15
+ g: number;
16
+ b: number;
17
+ };
18
+ };
19
+ export type CharacterDisposition = "translated" | "formula" | "table" | "excluded" | "rotated" | "unresolved" | "nonpainting" | "clipped";
20
+ export type CharacterCoverage = {
21
+ index: number;
22
+ text: string;
23
+ disposition: CharacterDisposition;
24
+ paragraphId?: string;
25
+ };
26
+ export type Character = {
27
+ clipBoxes?: number[][];
28
+ renderMode?: number;
29
+ textAngle?: number;
30
+ textMatrix?: number[];
31
+ textObjectId?: number;
32
+ index: number;
33
+ text: string;
34
+ box: Box;
35
+ visualBox: Box;
36
+ style: CharacterStyle;
37
+ };
38
+ export type Formula = {
39
+ id: string;
40
+ text: string;
41
+ box: Box;
42
+ characterIndexes: number[];
43
+ baselineOffset: number;
44
+ };
45
+ export type Paragraph = {
46
+ id: string;
47
+ pageIndex: number;
48
+ box: Box;
49
+ characters: Character[];
50
+ formulas: Formula[];
51
+ styles: Record<string, CharacterStyle>;
52
+ source: string;
53
+ protectedText: string;
54
+ style: CharacterStyle;
55
+ firstLineIndent: number;
56
+ heading: boolean;
57
+ /** Table cells cannot borrow neighboring cell space. */
58
+ fixedBox?: boolean;
59
+ /** Available placement space, distinct from the source text removal bounds. */
60
+ layoutBox?: Box;
61
+ origin?: "detected" | "table" | "fallback";
62
+ };
63
+ export type ReflowPage = {
64
+ index: number;
65
+ width: number;
66
+ height: number;
67
+ paragraphs: Paragraph[];
68
+ obstacles: Box[];
69
+ coverage?: CharacterCoverage[];
70
+ };
71
+ export type ReflowDocument = {
72
+ version: 1;
73
+ pages: ReflowPage[];
74
+ };
75
+ export type FontKey = "regular" | "bold" | "italic" | "boldItalic" | "cjk" | "cjkBold";
76
+ export type PlacedUnit = {
77
+ text: string;
78
+ x: number;
79
+ y: number;
80
+ width: number;
81
+ height: number;
82
+ font: FontKey;
83
+ fontSize: number;
84
+ formula?: Formula;
85
+ color: CharacterStyle["color"];
86
+ };
87
+ export type ParagraphLayout = {
88
+ id: string;
89
+ pageIndex: number;
90
+ sourceBox: Box;
91
+ box: Box;
92
+ scale: number;
93
+ units: PlacedUnit[];
94
+ fits: boolean;
95
+ };
96
+ export type PageLayout = {
97
+ index: number;
98
+ width: number;
99
+ height: number;
100
+ paragraphs: ParagraphLayout[];
101
+ };
102
+ export declare const formulaToken: (id: string) => string;
103
+ export declare function unionBoxes(boxes: readonly Box[]): Box;
104
+ export declare function intersects(a: Box, b: Box): boolean;
105
+ /** Formula and style tags are a structural contract, not ordinary prose. */
106
+ export declare function validReflowTranslation(p: Paragraph, text: string): boolean;
107
+ export declare function reflowDisplayText(p: Paragraph, text: string): string;
@@ -0,0 +1,23 @@
1
+ import type { PdfDocumentObject, PdfEngine } from '@embedpdf/models';
2
+ import { type ParagraphLayout, type ReflowPage } from './types';
3
+ export interface TranslatedPage {
4
+ source: ReflowPage;
5
+ layouts: ParagraphLayout[];
6
+ formulas: Map<string, string>;
7
+ translations: Map<string, string>;
8
+ error: string;
9
+ done: boolean;
10
+ }
11
+ export declare function usePageTranslation(options: {
12
+ open: boolean;
13
+ currentPage: number;
14
+ document: PdfDocumentObject | null | undefined;
15
+ engine: PdfEngine;
16
+ loadLayout: (signal?: AbortSignal) => Promise<unknown>;
17
+ translate: (text: string, signal?: AbortSignal) => Promise<string>;
18
+ }): {
19
+ pages: ReadonlyMap<number, TranslatedPage>;
20
+ running: boolean;
21
+ error: string;
22
+ retry: () => void;
23
+ };
@@ -0,0 +1,32 @@
1
+ export declare const PDF_ZOOM_MIN = 0.5;
2
+ export declare const PDF_ZOOM_MAX = 3;
3
+ /** Parse a user-entered percentage and clamp it to the viewer's zoom range. */
4
+ export declare function parsePdfZoomPercentage(value: string): number | null;
5
+ /**
6
+ * Preview scale for a zoom gesture (magnification relative to the zoom it
7
+ * started from), kept inside the viewer range so the preview matches the zoom
8
+ * that gets committed on release.
9
+ */
10
+ export declare function clampZoomPreviewScale(scale: number, baseZoom: number): number;
11
+ /**
12
+ * Translate that keeps a point of the transformed element under the pointer.
13
+ * Used with `transform-origin: 0 0` so a pinch scales around the fingers
14
+ * instead of the viewport center; `localX` / `localY` are the pointer position
15
+ * in the element's coordinate space before the transform is applied.
16
+ */
17
+ export declare function zoomPreviewTranslate(localX: number, localY: number, scale: number): {
18
+ x: number;
19
+ y: number;
20
+ };
21
+ /**
22
+ * Follow the reader's centered-page geometry while the document is narrower
23
+ * than its reading area, then blend to the gesture point as it overflows.
24
+ */
25
+ export declare function zoomPreviewTranslateForViewport(localX: number, localY: number, scale: number, elementWidth: number, viewportWidth: number): {
26
+ x: number;
27
+ y: number;
28
+ };
29
+ /** Step the viewer zoom by 10 percentage points, staying inside the range. */
30
+ export declare function stepPdfZoom(zoom: number, direction: -1 | 1): number;
31
+ /** Keep one decimal place when needed without showing a trailing `.0`. */
32
+ export declare function formatPdfZoomPercentage(zoom: number): string;