@embedpdf/core-annotation 3.0.0-next.1 → 3.0.0-next.10

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.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { AnnotationDTO, AnnotationFlags, AnnotationFlags as AnnotationFlags$1, AnnotationRef, BlendMode, BlendMode as BlendMode$1, CaretIntent, InkIntent, LineEnding, LineEndings, NO_ANNOTATION_FLAGS, PdfLinkTarget, PdfPoint, PdfRect, StrikeoutIntent } from "@embedpdf/engine-core/runtime";
2
2
  import { PageObjectNumber } from "@embedpdf/core";
3
- import { PageRotation, Point, Rect as Rect$1, Size } from "@embedpdf/core-geometry";
3
+ import { PageRotation, Point, Rect as Rect$1, Size, TextQuad, TextQuad as TextQuad$1 } from "@embedpdf/core-geometry";
4
4
  //#region src/flags.d.ts
5
5
  /** The `/F` every freshly DRAWN annotation starts with: `print` set (Acrobat
6
6
  * parity — without it the annotation silently disappears when printed). */
@@ -22,14 +22,27 @@ declare const interactive: (f: AnnotationFlags) => boolean;
22
22
  interface FlagBearer {
23
23
  subtype: string;
24
24
  flags: AnnotationFlags;
25
+ /** Session authority projected at ingest (permissions.md). Absent =
26
+ * unstamped (drafts, wildcard local engines, tests) = allowed. */
27
+ authority?: {
28
+ update: boolean;
29
+ delete: boolean;
30
+ };
25
31
  }
26
32
  /** Interaction gate for a concrete annotation: widget kinds ignore `readOnly`
27
33
  * (ISO 32000 — a ReadOnly form field must still be movable by a form designer;
28
34
  * the form-filling layer enforces field ReadOnly itself). */
29
35
  declare const annotInteractive: (a: FlagBearer) => boolean;
30
- /** Geometry/style/delete mutations — `locked` freezes the OBJECT, not its
31
- * contents (that's `lockedContents`). */
36
+ /**
37
+ * Geometry/style mutations — `locked` freezes the OBJECT, not its contents
38
+ * (that's `lockedContents`), AND the session must hold update authority over
39
+ * the record. One predicate for hit-test, chrome, and props alike, so a
40
+ * record you may not edit renders and behaves exactly like a locked one.
41
+ */
32
42
  declare const annotTransformable: (a: FlagBearer) => boolean;
43
+ /** Deletion — the delete half of the authority split (a narrowed grant can
44
+ * allow update but not delete, or vice versa). Flags gate like transforms. */
45
+ declare const annotDeletable: (a: FlagBearer) => boolean;
33
46
  /** `/Contents` text edits — the contents counterpart of `locked`. */
34
47
  declare const annotContentsEditable: (a: FlagBearer) => boolean;
35
48
  //#endregion
@@ -42,8 +55,19 @@ declare const annotContentsEditable: (a: FlagBearer) => boolean;
42
55
  */
43
56
  type Vec = Point;
44
57
  type Rect = Rect$1;
45
- /** Four content-space points (a /QuadPoints quad). */
58
+ /** Four POSITIONAL content-space points — selection chrome / OBB corners.
59
+ * Text-markup geometry uses the corner-NAMED {@link TextQuad} instead. */
46
60
  type Quad = [Vec, Vec, Vec, Vec];
61
+ /**
62
+ * Where a text-edit annotation (caret / replace-text) anchors: the boundary
63
+ * glyph's oriented cell plus the READING direction along its baseline
64
+ * (+1 = toward `end`, −1 = toward `start` — sequence-derived, never inferred
65
+ * from geometry).
66
+ */
67
+ interface TextEndAnchor {
68
+ glyphQuad: TextQuad$1;
69
+ advance: 1 | -1;
70
+ }
47
71
  type Id = string;
48
72
  type Cursor = string;
49
73
  type PolySubtype = 'polygon' | 'polyline';
@@ -115,10 +139,11 @@ type Geom = {
115
139
  rot?: number;
116
140
  } | {
117
141
  t: 'quads';
118
- quads: Quad[];
142
+ quads: TextQuad$1[];
119
143
  } | {
120
144
  t: 'caret';
121
145
  rect: Rect;
146
+ rot?: number;
122
147
  } | {
123
148
  t: 'ink';
124
149
  strokes: Vec[][];
@@ -274,6 +299,20 @@ interface Annot {
274
299
  * is still pixel-exact, so those cost zero re-renders.
275
300
  */
276
301
  apVersion?: number;
302
+ /**
303
+ * This SESSION's authority over this record, projected from the security
304
+ * service's collab mirrors at ingest (see permissions.md) — model-owned
305
+ * derived state like `apVersion`, never DTO-derived. Fused into
306
+ * `annotTransformable`/`annotDeletable`, so a record the session may not
307
+ * edit renders and behaves exactly like a `locked` one (bare outline, no
308
+ * handles, no drag). Absent = unstamped (a local draft, a wildcard local
309
+ * engine, tests) and treated as allowed — the client gate is a COURTESY
310
+ * that keeps the UI truthful; the engine independently enforces.
311
+ */
312
+ authority?: {
313
+ update: boolean;
314
+ delete: boolean;
315
+ };
277
316
  /**
278
317
  * The canonical engine DTO this annotation was derived from (PDF-space, sRGB)
279
318
  * — the single source of truth for its data. `geom` and `style` are
@@ -285,20 +324,13 @@ interface Annot {
285
324
  /** Normalized PDF `/IT` for intent-bearing annotations authored before a DTO exists. */
286
325
  intent?: CaretIntent | StrikeoutIntent | InkIntent;
287
326
  /**
288
- * The `link` prop's value (see {@link AnnotationProps.link}): the link
289
- * kind's own target, or — on other linkable kinds — the folded attached
290
- * link's target. Editable via `setProps`.
327
+ * The link KIND's own `/A` target (see {@link AnnotationProps.link}) —
328
+ * present only on `subtype: 'link'`. Every OTHER kind's link is an
329
+ * attached child annotation in the substrate, read through the `linkOf`
330
+ * lens and materialized by the shell's `syncLink` reconciler; parents
331
+ * store nothing.
291
332
  */
292
333
  link?: PdfLinkTarget | null;
293
- /**
294
- * INTERNAL join keys, never a prop: the engine refs of the attached link
295
- * child annotation(s) this parent's `link` value is materialized as (one
296
- * per visual segment for markup). Maintained by the repository fold and
297
- * consumed by the shell's `syncLink` reconciler + delete expansion — the
298
- * ONLY code allowed to touch those children. Absent on the link kind
299
- * itself and on anything without an attached link.
300
- */
301
- linkRefs?: AnnotationRef[];
302
334
  /**
303
335
  * Relationship to another annotation. `irt` ("in reply to") links a child to a
304
336
  * parent — a reply in a comment thread, or a caret bound to its strikeout in a
@@ -454,7 +486,7 @@ interface MarkupPreview {
454
486
  subtype: Subtype;
455
487
  /** Defaults key, distinct from subtype for presets such as replace-text. */
456
488
  preset: string;
457
- byPage: Record<number, Quad[]>;
489
+ byPage: Record<number, TextQuad$1[]>;
458
490
  }
459
491
  /** Anchor + affordance state for UI that controls an in-progress creation draft. */
460
492
  interface CreationDraftAnchor {
@@ -613,26 +645,26 @@ type Msg = {
613
645
  } | {
614
646
  t: 'createCaret';
615
647
  pon: PageObjectNumber;
616
- rect: Rect;
648
+ anchor: TextEndAnchor;
617
649
  flags?: Partial<AnnotationFlags$1>;
618
650
  } | {
619
651
  t: 'createReplaceText';
620
652
  pon: PageObjectNumber;
621
- rects: Rect[];
622
- endRect: Rect;
653
+ quads: TextQuad$1[];
654
+ anchor: TextEndAnchor;
623
655
  preset?: string;
624
656
  } | {
625
657
  t: 'createMarkup';
626
658
  subtype: Subtype;
627
659
  pon: PageObjectNumber;
628
- rects: Rect[];
660
+ quads: TextQuad$1[];
629
661
  preset?: string;
630
662
  /** The tool's `/F` seed — merged over {@link DRAWN_FLAGS} at commit. */
631
663
  flags?: Partial<AnnotationFlags$1>;
632
664
  } | {
633
665
  t: 'setMarkupPreview';
634
666
  subtype: Subtype;
635
- rectsByPage: Record<number, Rect[]>;
667
+ quadsByPage: Record<number, TextQuad$1[]>;
636
668
  preset?: string;
637
669
  } | {
638
670
  t: 'clearMarkupPreview';
@@ -673,6 +705,21 @@ type Msg = {
673
705
  } | {
674
706
  t: 'loaded';
675
707
  annots: Annot[];
708
+ } |
709
+ /**
710
+ * Whole-document hydration ingest (and desync re-ingest): the snapshot is
711
+ * the committed TRUTH. Incoming annots overwrite by id (gesture-locked ids
712
+ * excepted, as in `upsert`); committed model entries ABSENT from the
713
+ * snapshot are reaped — they were deleted while we could not watch.
714
+ * Uncommitted `tmp:` drafts and gesture-locked ids are never reaped, and
715
+ * an in-progress draft survives (unlike `remove`). `bumpAp` marks a
716
+ * desync re-ingest: rasters may have changed invisibly during the gap,
717
+ * so every replaced annotation re-fetches once.
718
+ */
719
+ {
720
+ t: 'hydrated';
721
+ annots: Annot[];
722
+ bumpAp?: boolean;
676
723
  } | {
677
724
  t: 'created';
678
725
  tempId: Id;
@@ -739,6 +786,7 @@ type Effect = {
739
786
  {
740
787
  fx: 'syncLink';
741
788
  id: Id;
789
+ target: PdfLinkTarget | null;
742
790
  } | {
743
791
  fx: 'delete';
744
792
  ref: AnnotationRef;
@@ -1198,6 +1246,36 @@ declare function groupMembers(m: Model, id: Id): Id[];
1198
1246
  /** Union of every id's full group — the selection seen as whole groups. */
1199
1247
  declare function expandGroups(m: Model, ids: Id[]): Id[];
1200
1248
  //#endregion
1249
+ //#region src/plane.d.ts
1250
+ /** True when this annotation belongs to the conversation plane only —
1251
+ * never painted, hit, marquee-selected, or counted into a page's
1252
+ * appearance epoch. */
1253
+ declare function isConversationOnly(a: Pick<Annot, 'irt' | 'group' | 'subtype' | 'data'>): boolean;
1254
+ /**
1255
+ * A link CHILD attached to another annotation — a `/Link` grouped
1256
+ * (`/IRT` + `/RT /Group`) under a non-link parent. Pure substrate: it is
1257
+ * the parent's `link` PROPERTY while authoring (derived via `linkOf`) and
1258
+ * the navigation plane's anchor while reading — never painted, never hit
1259
+ * as itself. Its rect is RECONCILED from the parent's geometry, so direct
1260
+ * manipulation would be overwritten anyway.
1261
+ */
1262
+ declare function isAttachedLink(a: Pick<Annot, 'subtype' | 'group'>): boolean;
1263
+ /**
1264
+ * The ONE page-surface cull: everything that lives in the substrate but is
1265
+ * not a page visual of its own — conversation members (replies, review
1266
+ * states) and attached link children. Paint order, hit-testing, marquee
1267
+ * and the appearance epoch all filter through THIS, never the parts.
1268
+ */
1269
+ declare function isSubstrateOnly(a: Pick<Annot, 'irt' | 'group' | 'subtype' | 'data'>): boolean;
1270
+ //#endregion
1271
+ //#region src/links.d.ts
1272
+ /** Every attached link child of `parentId`, in z-order (multi-segment
1273
+ * markup parents carry several children with one shared target). */
1274
+ declare function linkChildrenOf(m: Model, parentId: Id): Annot[];
1275
+ /** The parent's link target, derived from its first attached child — the
1276
+ * read side of the `syncLink` reconciler. Null when no child exists. */
1277
+ declare function linkOf(m: Model, parentId: Id): PdfLinkTarget | null;
1278
+ //#endregion
1201
1279
  //#region src/kinds.d.ts
1202
1280
  /**
1203
1281
  * One editable property of a kind, as a UI contract: which {@link AnnotationProps}
@@ -1386,7 +1464,10 @@ declare const DEFAULT_CHROME_GEOM: {
1386
1464
  };
1387
1465
  /** Normalize degrees into `[0, 360)`. */
1388
1466
  declare const normalizeDeg: (d: number) => number;
1389
- /** A geom's applied rotation (deg), or 0 for the non-rotatable kinds. */
1467
+ /** A geom's applied rotation (deg), or 0 for the non-rotatable kinds. A
1468
+ * caret's `rot` is AUTHORING metadata (its text's baseline tilt): reported
1469
+ * here so the renderer and selection chrome follow it, while the caret's
1470
+ * caps (not movable/resizable) keep every rotate gesture away from it. */
1390
1471
  declare function geomRotation(g: Geom): number;
1391
1472
  /**
1392
1473
  * The rotation PIVOT for a single shape: a box turns about its own `rect`
@@ -1395,7 +1476,10 @@ declare function geomRotation(g: Geom): number;
1395
1476
  * stays cleanly additive across gestures and reset is exact.
1396
1477
  */
1397
1478
  declare function centroidOf(g: Geom): Vec;
1398
- /** Is this kind rotatable (the geometry carries a meaningful `rot`)? */
1479
+ /** Does the geometry carry a meaningful `rot` (an oriented local box exists)?
1480
+ * ORIENTATION is a geometry fact; whether the USER may rotate is the separate
1481
+ * `caps.rotatable` gate — a caret is oriented (it rides its text's tilt) yet
1482
+ * offers no rotate gesture. */
1399
1483
  declare function isRotatableGeom(g: Geom): boolean;
1400
1484
  /**
1401
1485
  * Rotate a geom by `deltaDeg` (clockwise) about `pivot`.
@@ -1404,7 +1488,10 @@ declare function isRotatableGeom(g: Geom): boolean;
1404
1488
  * pivot IS the box centre this is a pure `rot += delta`.
1405
1489
  * - VERTEX (`line`/`poly`/`ink`): map every point through the rotation AND bump
1406
1490
  * the advisory `rot` (the points stay the authoritative visual).
1407
- * Non-rotatable kinds (caret/quads, callouts) are returned unchanged.
1491
+ * Kinds without a rotate VERB are returned unchanged: quads and callouts, and
1492
+ * also the caret — oriented (`isRotatableGeom`) but text-anchored, so its tilt
1493
+ * is authoring metadata that no gesture edits (`geomResetRotation` still
1494
+ * clears it).
1408
1495
  */
1409
1496
  declare function geomRotateAbout(g: Geom, pivot: Vec, deltaDeg: number): Geom;
1410
1497
  /** The AABB of `rect` rotated `deg` about its own centre. */
@@ -1520,6 +1607,26 @@ declare function calloutLinePoints(g: Extract<Geom, {
1520
1607
  */
1521
1608
  declare function shapeRectFor(dragged: Rect, ellipse: boolean, style: Style): Rect;
1522
1609
  declare function caretRectFromTextEnd(lineRect: Rect): Rect;
1610
+ /**
1611
+ * Caret box for a text-edit anchor: half the glyph's ink height, centered on
1612
+ * the TRAILING baseline corner in READING direction (`advance` decides which
1613
+ * end — RTL carets land on the visual left), sitting on the baseline. The box
1614
+ * stays axis-aligned; use {@link caretGeomFromAnchor} for the tilt-carrying
1615
+ * geometry.
1616
+ */
1617
+ declare function caretRectFromAnchor(anchor: TextEndAnchor): Rect;
1618
+ /**
1619
+ * Caret GEOMETRY for a text-edit anchor: the box-family pair — an UNROTATED
1620
+ * box whose centre sits half a caret-size ascent-ward of the trailing
1621
+ * baseline corner, plus `rot` = the text's baseline tilt (deg, CW in y-down
1622
+ * content space). Rotating the box about its centre by `rot` lands it
1623
+ * hugging the rotated baseline, symbol pointing at its text. For upright
1624
+ * anchors this degenerates EXACTLY to {@link caretRectFromAnchor} with no
1625
+ * `rot` key — the dominant case is byte-identical.
1626
+ */
1627
+ declare function caretGeomFromAnchor(anchor: TextEndAnchor): Extract<Geom, {
1628
+ t: 'caret';
1629
+ }>;
1523
1630
  /** Miter limit shared by the bounds math AND the SVG renderer (`stroke-miterlimit`),
1524
1631
  * so the computed box and the drawn stroke always agree on where a sharp join
1525
1632
  * bevels instead of spiking. 10 = the PDF default (also what the baked /AP uses). */
@@ -1632,5 +1739,5 @@ declare function scene(item: RenderItem): SceneNode[];
1632
1739
  */
1633
1740
  declare function straightenInkStroke(points: readonly Vec[], options: InkStraightenOptions): Vec[];
1634
1741
  //#endregion
1635
- export { type AnchorMode, type Annot, type AnnotationFlags, type AnnotationKind, type AnnotationProps, type AnnotationPropsPatch, type BlendMode, type Border, type Callout, type ChromeGeom, type ChromeNode, type ClickCreate, type ClickPlacement, type CreationDraftAnchor, type Cursor, DEFAULT_CHROME_GEOM, DRAWN_FLAGS, type Draft, type Effect, FLAG_KEYS, type FlagBearer, type Geom, type GroupCaps, type Guide, type Handle, type Id, type InkStraightenOptions, KINDS, type KindCaps, type LineEnding, type LineEndings, MIN_DRAG, MITER_LIMIT, type Model, type Msg, NO_ANNOTATION_FLAGS, type Paint, type PatchScope, type PointerInput, type PropKey, type PropSpec, type Quad, RECT_HANDLES, ROTATE_KNOB_OFFSET, type Rect, type RectHandle, type RenderItem, type RenderNode, type SceneNode, type SnapResult, type SnapSettings, type Style, type Subtype, type Target, type TextAlign, type TextBox, type TextStyle, type Vec, type ViewEnv, anchorModeOf, anchorOf, anchoredBox, anchoredGeom, anchoredStrokeWidth, annotContentsEditable, annotInteractive, annotTransformable, applyProps, calloutConnection, calloutLinePoints, canMove, capsFor, caretRectFromTextEnd, centroidOf, chrome, clampRectToBox, clickCreateGeom, cloudyBorderExtent, cloudyPath, computeMoveSnap, contentToPdfPoint, contentToPdfRect, creationDraftAnchor, cursorAt, defaultsFor, expandGroups, fitStampBox, flagsEqual, geomBounds, geomDragHandle, geomHandles, geomHit, geomPdfBounds, geomResetRotation, geomRotateAbout, geomRotation, geomScaleAbout, geomScene, geomTranslate, geomVisualBounds, groupCaps, groupKeyOf, groupMembers, groupResizeAnchor, groupResizeBox, groupResizeFactors, hitTest, initialModel, initialStyle, initialTextStyle, interactive, isRotatableGeom, isSelectable, mergeFlags, normalizeDeg, obbFromGeom, pageItems, pdfToContentPoint, pdfToContentRect, placeRotateKnob, pointInQuad, propsFor, quadIntersectsRect, readProp, rectFromPoints, resolveClickPlacement, rotateDraftDelta, rotateKnob, rotatedAabb, rotatedHandleCursor, scene, selectedItems, selectionAnchor, selectionBounds, selectionBoundsOnPage, selectionCenter, selectionKnob, selectionQuad, shapeRectFor, sharedProps, straightenInkStroke, styleFromProps, textBoxes, textStyleFromProps, transposedAboutCenter, unanchoredGeom, unionRect, update, uprightAnchoredRect, uprightRotation, viewable };
1742
+ export { type AnchorMode, type Annot, type AnnotationFlags, type AnnotationKind, type AnnotationProps, type AnnotationPropsPatch, type BlendMode, type Border, type Callout, type ChromeGeom, type ChromeNode, type ClickCreate, type ClickPlacement, type CreationDraftAnchor, type Cursor, DEFAULT_CHROME_GEOM, DRAWN_FLAGS, type Draft, type Effect, FLAG_KEYS, type FlagBearer, type Geom, type GroupCaps, type Guide, type Handle, type Id, type InkStraightenOptions, KINDS, type KindCaps, type LineEnding, type LineEndings, MIN_DRAG, MITER_LIMIT, type Model, type Msg, NO_ANNOTATION_FLAGS, type Paint, type PatchScope, type PointerInput, type PropKey, type PropSpec, type Quad, RECT_HANDLES, ROTATE_KNOB_OFFSET, type Rect, type RectHandle, type RenderItem, type RenderNode, type SceneNode, type SnapResult, type SnapSettings, type Style, type Subtype, type Target, type TextAlign, type TextBox, type TextEndAnchor, type TextQuad, type TextStyle, type Vec, type ViewEnv, anchorModeOf, anchorOf, anchoredBox, anchoredGeom, anchoredStrokeWidth, annotContentsEditable, annotDeletable, annotInteractive, annotTransformable, applyProps, calloutConnection, calloutLinePoints, canMove, capsFor, caretGeomFromAnchor, caretRectFromAnchor, caretRectFromTextEnd, centroidOf, chrome, clampRectToBox, clickCreateGeom, cloudyBorderExtent, cloudyPath, computeMoveSnap, contentToPdfPoint, contentToPdfRect, creationDraftAnchor, cursorAt, defaultsFor, expandGroups, fitStampBox, flagsEqual, geomBounds, geomDragHandle, geomHandles, geomHit, geomPdfBounds, geomResetRotation, geomRotateAbout, geomRotation, geomScaleAbout, geomScene, geomTranslate, geomVisualBounds, groupCaps, groupKeyOf, groupMembers, groupResizeAnchor, groupResizeBox, groupResizeFactors, hitTest, initialModel, initialStyle, initialTextStyle, interactive, isAttachedLink, isConversationOnly, isRotatableGeom, isSelectable, isSubstrateOnly, linkChildrenOf, linkOf, mergeFlags, normalizeDeg, obbFromGeom, pageItems, pdfToContentPoint, pdfToContentRect, placeRotateKnob, pointInQuad, propsFor, quadIntersectsRect, readProp, rectFromPoints, resolveClickPlacement, rotateDraftDelta, rotateKnob, rotatedAabb, rotatedHandleCursor, scene, selectedItems, selectionAnchor, selectionBounds, selectionBoundsOnPage, selectionCenter, selectionKnob, selectionQuad, shapeRectFor, sharedProps, straightenInkStroke, styleFromProps, textBoxes, textStyleFromProps, transposedAboutCenter, unanchoredGeom, unionRect, update, uprightAnchoredRect, uprightRotation, viewable };
1636
1743
  //# sourceMappingURL=index.d.cts.map
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { AnnotationDTO, AnnotationFlags, AnnotationFlags as AnnotationFlags$1, AnnotationRef, BlendMode, BlendMode as BlendMode$1, CaretIntent, InkIntent, LineEnding, LineEndings, NO_ANNOTATION_FLAGS, PdfLinkTarget, PdfPoint, PdfRect, StrikeoutIntent } from "@embedpdf/engine-core/runtime";
2
- import { PageRotation, Point, Rect as Rect$1, Size } from "@embedpdf/core-geometry";
2
+ import { PageRotation, Point, Rect as Rect$1, Size, TextQuad, TextQuad as TextQuad$1 } from "@embedpdf/core-geometry";
3
3
  import { PageObjectNumber } from "@embedpdf/core";
4
4
  //#region src/flags.d.ts
5
5
  /** The `/F` every freshly DRAWN annotation starts with: `print` set (Acrobat
@@ -22,14 +22,27 @@ declare const interactive: (f: AnnotationFlags) => boolean;
22
22
  interface FlagBearer {
23
23
  subtype: string;
24
24
  flags: AnnotationFlags;
25
+ /** Session authority projected at ingest (permissions.md). Absent =
26
+ * unstamped (drafts, wildcard local engines, tests) = allowed. */
27
+ authority?: {
28
+ update: boolean;
29
+ delete: boolean;
30
+ };
25
31
  }
26
32
  /** Interaction gate for a concrete annotation: widget kinds ignore `readOnly`
27
33
  * (ISO 32000 — a ReadOnly form field must still be movable by a form designer;
28
34
  * the form-filling layer enforces field ReadOnly itself). */
29
35
  declare const annotInteractive: (a: FlagBearer) => boolean;
30
- /** Geometry/style/delete mutations — `locked` freezes the OBJECT, not its
31
- * contents (that's `lockedContents`). */
36
+ /**
37
+ * Geometry/style mutations — `locked` freezes the OBJECT, not its contents
38
+ * (that's `lockedContents`), AND the session must hold update authority over
39
+ * the record. One predicate for hit-test, chrome, and props alike, so a
40
+ * record you may not edit renders and behaves exactly like a locked one.
41
+ */
32
42
  declare const annotTransformable: (a: FlagBearer) => boolean;
43
+ /** Deletion — the delete half of the authority split (a narrowed grant can
44
+ * allow update but not delete, or vice versa). Flags gate like transforms. */
45
+ declare const annotDeletable: (a: FlagBearer) => boolean;
33
46
  /** `/Contents` text edits — the contents counterpart of `locked`. */
34
47
  declare const annotContentsEditable: (a: FlagBearer) => boolean;
35
48
  //#endregion
@@ -42,8 +55,19 @@ declare const annotContentsEditable: (a: FlagBearer) => boolean;
42
55
  */
43
56
  type Vec = Point;
44
57
  type Rect = Rect$1;
45
- /** Four content-space points (a /QuadPoints quad). */
58
+ /** Four POSITIONAL content-space points — selection chrome / OBB corners.
59
+ * Text-markup geometry uses the corner-NAMED {@link TextQuad} instead. */
46
60
  type Quad = [Vec, Vec, Vec, Vec];
61
+ /**
62
+ * Where a text-edit annotation (caret / replace-text) anchors: the boundary
63
+ * glyph's oriented cell plus the READING direction along its baseline
64
+ * (+1 = toward `end`, −1 = toward `start` — sequence-derived, never inferred
65
+ * from geometry).
66
+ */
67
+ interface TextEndAnchor {
68
+ glyphQuad: TextQuad$1;
69
+ advance: 1 | -1;
70
+ }
47
71
  type Id = string;
48
72
  type Cursor = string;
49
73
  type PolySubtype = 'polygon' | 'polyline';
@@ -115,10 +139,11 @@ type Geom = {
115
139
  rot?: number;
116
140
  } | {
117
141
  t: 'quads';
118
- quads: Quad[];
142
+ quads: TextQuad$1[];
119
143
  } | {
120
144
  t: 'caret';
121
145
  rect: Rect;
146
+ rot?: number;
122
147
  } | {
123
148
  t: 'ink';
124
149
  strokes: Vec[][];
@@ -274,6 +299,20 @@ interface Annot {
274
299
  * is still pixel-exact, so those cost zero re-renders.
275
300
  */
276
301
  apVersion?: number;
302
+ /**
303
+ * This SESSION's authority over this record, projected from the security
304
+ * service's collab mirrors at ingest (see permissions.md) — model-owned
305
+ * derived state like `apVersion`, never DTO-derived. Fused into
306
+ * `annotTransformable`/`annotDeletable`, so a record the session may not
307
+ * edit renders and behaves exactly like a `locked` one (bare outline, no
308
+ * handles, no drag). Absent = unstamped (a local draft, a wildcard local
309
+ * engine, tests) and treated as allowed — the client gate is a COURTESY
310
+ * that keeps the UI truthful; the engine independently enforces.
311
+ */
312
+ authority?: {
313
+ update: boolean;
314
+ delete: boolean;
315
+ };
277
316
  /**
278
317
  * The canonical engine DTO this annotation was derived from (PDF-space, sRGB)
279
318
  * — the single source of truth for its data. `geom` and `style` are
@@ -285,20 +324,13 @@ interface Annot {
285
324
  /** Normalized PDF `/IT` for intent-bearing annotations authored before a DTO exists. */
286
325
  intent?: CaretIntent | StrikeoutIntent | InkIntent;
287
326
  /**
288
- * The `link` prop's value (see {@link AnnotationProps.link}): the link
289
- * kind's own target, or — on other linkable kinds — the folded attached
290
- * link's target. Editable via `setProps`.
327
+ * The link KIND's own `/A` target (see {@link AnnotationProps.link}) —
328
+ * present only on `subtype: 'link'`. Every OTHER kind's link is an
329
+ * attached child annotation in the substrate, read through the `linkOf`
330
+ * lens and materialized by the shell's `syncLink` reconciler; parents
331
+ * store nothing.
291
332
  */
292
333
  link?: PdfLinkTarget | null;
293
- /**
294
- * INTERNAL join keys, never a prop: the engine refs of the attached link
295
- * child annotation(s) this parent's `link` value is materialized as (one
296
- * per visual segment for markup). Maintained by the repository fold and
297
- * consumed by the shell's `syncLink` reconciler + delete expansion — the
298
- * ONLY code allowed to touch those children. Absent on the link kind
299
- * itself and on anything without an attached link.
300
- */
301
- linkRefs?: AnnotationRef[];
302
334
  /**
303
335
  * Relationship to another annotation. `irt` ("in reply to") links a child to a
304
336
  * parent — a reply in a comment thread, or a caret bound to its strikeout in a
@@ -454,7 +486,7 @@ interface MarkupPreview {
454
486
  subtype: Subtype;
455
487
  /** Defaults key, distinct from subtype for presets such as replace-text. */
456
488
  preset: string;
457
- byPage: Record<number, Quad[]>;
489
+ byPage: Record<number, TextQuad$1[]>;
458
490
  }
459
491
  /** Anchor + affordance state for UI that controls an in-progress creation draft. */
460
492
  interface CreationDraftAnchor {
@@ -613,26 +645,26 @@ type Msg = {
613
645
  } | {
614
646
  t: 'createCaret';
615
647
  pon: PageObjectNumber;
616
- rect: Rect;
648
+ anchor: TextEndAnchor;
617
649
  flags?: Partial<AnnotationFlags$1>;
618
650
  } | {
619
651
  t: 'createReplaceText';
620
652
  pon: PageObjectNumber;
621
- rects: Rect[];
622
- endRect: Rect;
653
+ quads: TextQuad$1[];
654
+ anchor: TextEndAnchor;
623
655
  preset?: string;
624
656
  } | {
625
657
  t: 'createMarkup';
626
658
  subtype: Subtype;
627
659
  pon: PageObjectNumber;
628
- rects: Rect[];
660
+ quads: TextQuad$1[];
629
661
  preset?: string;
630
662
  /** The tool's `/F` seed — merged over {@link DRAWN_FLAGS} at commit. */
631
663
  flags?: Partial<AnnotationFlags$1>;
632
664
  } | {
633
665
  t: 'setMarkupPreview';
634
666
  subtype: Subtype;
635
- rectsByPage: Record<number, Rect[]>;
667
+ quadsByPage: Record<number, TextQuad$1[]>;
636
668
  preset?: string;
637
669
  } | {
638
670
  t: 'clearMarkupPreview';
@@ -673,6 +705,21 @@ type Msg = {
673
705
  } | {
674
706
  t: 'loaded';
675
707
  annots: Annot[];
708
+ } |
709
+ /**
710
+ * Whole-document hydration ingest (and desync re-ingest): the snapshot is
711
+ * the committed TRUTH. Incoming annots overwrite by id (gesture-locked ids
712
+ * excepted, as in `upsert`); committed model entries ABSENT from the
713
+ * snapshot are reaped — they were deleted while we could not watch.
714
+ * Uncommitted `tmp:` drafts and gesture-locked ids are never reaped, and
715
+ * an in-progress draft survives (unlike `remove`). `bumpAp` marks a
716
+ * desync re-ingest: rasters may have changed invisibly during the gap,
717
+ * so every replaced annotation re-fetches once.
718
+ */
719
+ {
720
+ t: 'hydrated';
721
+ annots: Annot[];
722
+ bumpAp?: boolean;
676
723
  } | {
677
724
  t: 'created';
678
725
  tempId: Id;
@@ -739,6 +786,7 @@ type Effect = {
739
786
  {
740
787
  fx: 'syncLink';
741
788
  id: Id;
789
+ target: PdfLinkTarget | null;
742
790
  } | {
743
791
  fx: 'delete';
744
792
  ref: AnnotationRef;
@@ -1198,6 +1246,36 @@ declare function groupMembers(m: Model, id: Id): Id[];
1198
1246
  /** Union of every id's full group — the selection seen as whole groups. */
1199
1247
  declare function expandGroups(m: Model, ids: Id[]): Id[];
1200
1248
  //#endregion
1249
+ //#region src/plane.d.ts
1250
+ /** True when this annotation belongs to the conversation plane only —
1251
+ * never painted, hit, marquee-selected, or counted into a page's
1252
+ * appearance epoch. */
1253
+ declare function isConversationOnly(a: Pick<Annot, 'irt' | 'group' | 'subtype' | 'data'>): boolean;
1254
+ /**
1255
+ * A link CHILD attached to another annotation — a `/Link` grouped
1256
+ * (`/IRT` + `/RT /Group`) under a non-link parent. Pure substrate: it is
1257
+ * the parent's `link` PROPERTY while authoring (derived via `linkOf`) and
1258
+ * the navigation plane's anchor while reading — never painted, never hit
1259
+ * as itself. Its rect is RECONCILED from the parent's geometry, so direct
1260
+ * manipulation would be overwritten anyway.
1261
+ */
1262
+ declare function isAttachedLink(a: Pick<Annot, 'subtype' | 'group'>): boolean;
1263
+ /**
1264
+ * The ONE page-surface cull: everything that lives in the substrate but is
1265
+ * not a page visual of its own — conversation members (replies, review
1266
+ * states) and attached link children. Paint order, hit-testing, marquee
1267
+ * and the appearance epoch all filter through THIS, never the parts.
1268
+ */
1269
+ declare function isSubstrateOnly(a: Pick<Annot, 'irt' | 'group' | 'subtype' | 'data'>): boolean;
1270
+ //#endregion
1271
+ //#region src/links.d.ts
1272
+ /** Every attached link child of `parentId`, in z-order (multi-segment
1273
+ * markup parents carry several children with one shared target). */
1274
+ declare function linkChildrenOf(m: Model, parentId: Id): Annot[];
1275
+ /** The parent's link target, derived from its first attached child — the
1276
+ * read side of the `syncLink` reconciler. Null when no child exists. */
1277
+ declare function linkOf(m: Model, parentId: Id): PdfLinkTarget | null;
1278
+ //#endregion
1201
1279
  //#region src/kinds.d.ts
1202
1280
  /**
1203
1281
  * One editable property of a kind, as a UI contract: which {@link AnnotationProps}
@@ -1386,7 +1464,10 @@ declare const DEFAULT_CHROME_GEOM: {
1386
1464
  };
1387
1465
  /** Normalize degrees into `[0, 360)`. */
1388
1466
  declare const normalizeDeg: (d: number) => number;
1389
- /** A geom's applied rotation (deg), or 0 for the non-rotatable kinds. */
1467
+ /** A geom's applied rotation (deg), or 0 for the non-rotatable kinds. A
1468
+ * caret's `rot` is AUTHORING metadata (its text's baseline tilt): reported
1469
+ * here so the renderer and selection chrome follow it, while the caret's
1470
+ * caps (not movable/resizable) keep every rotate gesture away from it. */
1390
1471
  declare function geomRotation(g: Geom): number;
1391
1472
  /**
1392
1473
  * The rotation PIVOT for a single shape: a box turns about its own `rect`
@@ -1395,7 +1476,10 @@ declare function geomRotation(g: Geom): number;
1395
1476
  * stays cleanly additive across gestures and reset is exact.
1396
1477
  */
1397
1478
  declare function centroidOf(g: Geom): Vec;
1398
- /** Is this kind rotatable (the geometry carries a meaningful `rot`)? */
1479
+ /** Does the geometry carry a meaningful `rot` (an oriented local box exists)?
1480
+ * ORIENTATION is a geometry fact; whether the USER may rotate is the separate
1481
+ * `caps.rotatable` gate — a caret is oriented (it rides its text's tilt) yet
1482
+ * offers no rotate gesture. */
1399
1483
  declare function isRotatableGeom(g: Geom): boolean;
1400
1484
  /**
1401
1485
  * Rotate a geom by `deltaDeg` (clockwise) about `pivot`.
@@ -1404,7 +1488,10 @@ declare function isRotatableGeom(g: Geom): boolean;
1404
1488
  * pivot IS the box centre this is a pure `rot += delta`.
1405
1489
  * - VERTEX (`line`/`poly`/`ink`): map every point through the rotation AND bump
1406
1490
  * the advisory `rot` (the points stay the authoritative visual).
1407
- * Non-rotatable kinds (caret/quads, callouts) are returned unchanged.
1491
+ * Kinds without a rotate VERB are returned unchanged: quads and callouts, and
1492
+ * also the caret — oriented (`isRotatableGeom`) but text-anchored, so its tilt
1493
+ * is authoring metadata that no gesture edits (`geomResetRotation` still
1494
+ * clears it).
1408
1495
  */
1409
1496
  declare function geomRotateAbout(g: Geom, pivot: Vec, deltaDeg: number): Geom;
1410
1497
  /** The AABB of `rect` rotated `deg` about its own centre. */
@@ -1520,6 +1607,26 @@ declare function calloutLinePoints(g: Extract<Geom, {
1520
1607
  */
1521
1608
  declare function shapeRectFor(dragged: Rect, ellipse: boolean, style: Style): Rect;
1522
1609
  declare function caretRectFromTextEnd(lineRect: Rect): Rect;
1610
+ /**
1611
+ * Caret box for a text-edit anchor: half the glyph's ink height, centered on
1612
+ * the TRAILING baseline corner in READING direction (`advance` decides which
1613
+ * end — RTL carets land on the visual left), sitting on the baseline. The box
1614
+ * stays axis-aligned; use {@link caretGeomFromAnchor} for the tilt-carrying
1615
+ * geometry.
1616
+ */
1617
+ declare function caretRectFromAnchor(anchor: TextEndAnchor): Rect;
1618
+ /**
1619
+ * Caret GEOMETRY for a text-edit anchor: the box-family pair — an UNROTATED
1620
+ * box whose centre sits half a caret-size ascent-ward of the trailing
1621
+ * baseline corner, plus `rot` = the text's baseline tilt (deg, CW in y-down
1622
+ * content space). Rotating the box about its centre by `rot` lands it
1623
+ * hugging the rotated baseline, symbol pointing at its text. For upright
1624
+ * anchors this degenerates EXACTLY to {@link caretRectFromAnchor} with no
1625
+ * `rot` key — the dominant case is byte-identical.
1626
+ */
1627
+ declare function caretGeomFromAnchor(anchor: TextEndAnchor): Extract<Geom, {
1628
+ t: 'caret';
1629
+ }>;
1523
1630
  /** Miter limit shared by the bounds math AND the SVG renderer (`stroke-miterlimit`),
1524
1631
  * so the computed box and the drawn stroke always agree on where a sharp join
1525
1632
  * bevels instead of spiking. 10 = the PDF default (also what the baked /AP uses). */
@@ -1632,5 +1739,5 @@ declare function scene(item: RenderItem): SceneNode[];
1632
1739
  */
1633
1740
  declare function straightenInkStroke(points: readonly Vec[], options: InkStraightenOptions): Vec[];
1634
1741
  //#endregion
1635
- export { type AnchorMode, type Annot, type AnnotationFlags, type AnnotationKind, type AnnotationProps, type AnnotationPropsPatch, type BlendMode, type Border, type Callout, type ChromeGeom, type ChromeNode, type ClickCreate, type ClickPlacement, type CreationDraftAnchor, type Cursor, DEFAULT_CHROME_GEOM, DRAWN_FLAGS, type Draft, type Effect, FLAG_KEYS, type FlagBearer, type Geom, type GroupCaps, type Guide, type Handle, type Id, type InkStraightenOptions, KINDS, type KindCaps, type LineEnding, type LineEndings, MIN_DRAG, MITER_LIMIT, type Model, type Msg, NO_ANNOTATION_FLAGS, type Paint, type PatchScope, type PointerInput, type PropKey, type PropSpec, type Quad, RECT_HANDLES, ROTATE_KNOB_OFFSET, type Rect, type RectHandle, type RenderItem, type RenderNode, type SceneNode, type SnapResult, type SnapSettings, type Style, type Subtype, type Target, type TextAlign, type TextBox, type TextStyle, type Vec, type ViewEnv, anchorModeOf, anchorOf, anchoredBox, anchoredGeom, anchoredStrokeWidth, annotContentsEditable, annotInteractive, annotTransformable, applyProps, calloutConnection, calloutLinePoints, canMove, capsFor, caretRectFromTextEnd, centroidOf, chrome, clampRectToBox, clickCreateGeom, cloudyBorderExtent, cloudyPath, computeMoveSnap, contentToPdfPoint, contentToPdfRect, creationDraftAnchor, cursorAt, defaultsFor, expandGroups, fitStampBox, flagsEqual, geomBounds, geomDragHandle, geomHandles, geomHit, geomPdfBounds, geomResetRotation, geomRotateAbout, geomRotation, geomScaleAbout, geomScene, geomTranslate, geomVisualBounds, groupCaps, groupKeyOf, groupMembers, groupResizeAnchor, groupResizeBox, groupResizeFactors, hitTest, initialModel, initialStyle, initialTextStyle, interactive, isRotatableGeom, isSelectable, mergeFlags, normalizeDeg, obbFromGeom, pageItems, pdfToContentPoint, pdfToContentRect, placeRotateKnob, pointInQuad, propsFor, quadIntersectsRect, readProp, rectFromPoints, resolveClickPlacement, rotateDraftDelta, rotateKnob, rotatedAabb, rotatedHandleCursor, scene, selectedItems, selectionAnchor, selectionBounds, selectionBoundsOnPage, selectionCenter, selectionKnob, selectionQuad, shapeRectFor, sharedProps, straightenInkStroke, styleFromProps, textBoxes, textStyleFromProps, transposedAboutCenter, unanchoredGeom, unionRect, update, uprightAnchoredRect, uprightRotation, viewable };
1742
+ export { type AnchorMode, type Annot, type AnnotationFlags, type AnnotationKind, type AnnotationProps, type AnnotationPropsPatch, type BlendMode, type Border, type Callout, type ChromeGeom, type ChromeNode, type ClickCreate, type ClickPlacement, type CreationDraftAnchor, type Cursor, DEFAULT_CHROME_GEOM, DRAWN_FLAGS, type Draft, type Effect, FLAG_KEYS, type FlagBearer, type Geom, type GroupCaps, type Guide, type Handle, type Id, type InkStraightenOptions, KINDS, type KindCaps, type LineEnding, type LineEndings, MIN_DRAG, MITER_LIMIT, type Model, type Msg, NO_ANNOTATION_FLAGS, type Paint, type PatchScope, type PointerInput, type PropKey, type PropSpec, type Quad, RECT_HANDLES, ROTATE_KNOB_OFFSET, type Rect, type RectHandle, type RenderItem, type RenderNode, type SceneNode, type SnapResult, type SnapSettings, type Style, type Subtype, type Target, type TextAlign, type TextBox, type TextEndAnchor, type TextQuad, type TextStyle, type Vec, type ViewEnv, anchorModeOf, anchorOf, anchoredBox, anchoredGeom, anchoredStrokeWidth, annotContentsEditable, annotDeletable, annotInteractive, annotTransformable, applyProps, calloutConnection, calloutLinePoints, canMove, capsFor, caretGeomFromAnchor, caretRectFromAnchor, caretRectFromTextEnd, centroidOf, chrome, clampRectToBox, clickCreateGeom, cloudyBorderExtent, cloudyPath, computeMoveSnap, contentToPdfPoint, contentToPdfRect, creationDraftAnchor, cursorAt, defaultsFor, expandGroups, fitStampBox, flagsEqual, geomBounds, geomDragHandle, geomHandles, geomHit, geomPdfBounds, geomResetRotation, geomRotateAbout, geomRotation, geomScaleAbout, geomScene, geomTranslate, geomVisualBounds, groupCaps, groupKeyOf, groupMembers, groupResizeAnchor, groupResizeBox, groupResizeFactors, hitTest, initialModel, initialStyle, initialTextStyle, interactive, isAttachedLink, isConversationOnly, isRotatableGeom, isSelectable, isSubstrateOnly, linkChildrenOf, linkOf, mergeFlags, normalizeDeg, obbFromGeom, pageItems, pdfToContentPoint, pdfToContentRect, placeRotateKnob, pointInQuad, propsFor, quadIntersectsRect, readProp, rectFromPoints, resolveClickPlacement, rotateDraftDelta, rotateKnob, rotatedAabb, rotatedHandleCursor, scene, selectedItems, selectionAnchor, selectionBounds, selectionBoundsOnPage, selectionCenter, selectionKnob, selectionQuad, shapeRectFor, sharedProps, straightenInkStroke, styleFromProps, textBoxes, textStyleFromProps, transposedAboutCenter, unanchoredGeom, unionRect, update, uprightAnchoredRect, uprightRotation, viewable };
1636
1743
  //# sourceMappingURL=index.d.ts.map