@vectojs/core 1.32.7 → 1.33.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.
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Caret addressing inside a content projection: the shared vocabulary for
3
+ * describing "this exact position in this projected text".
4
+ *
5
+ * Extracted as a **shared module** rather than as part of any one collaborator
6
+ * because both sides of the extraction-3 cut need it. The selection-preservation
7
+ * pass that moves to {@link ContentSelectionManager} converts a live `Selection`
8
+ * endpoint into a linear character offset and back, while the pointer-to-caret
9
+ * resolution that stays in `Scene.ts` (`nearestTextPositionInProjection` and its
10
+ * per-line helpers) builds the same positions from hit coordinates. Duplicating
11
+ * the offset walk in both places would let the two drift, and a caret that
12
+ * disagrees with the offset it was derived from restores a selection to the wrong
13
+ * text.
14
+ *
15
+ * Every symbol here was module-private in `Scene.ts` and stays module-private to
16
+ * the package: `packages/core/src/index.ts` is `export * from './tree/Scene'`, so
17
+ * re-exporting would silently widen the public API. `DEC-0019` rule 3.
18
+ *
19
+ * Stateless and DOM-only by design — no `Scene`, no entities, no engine state.
20
+ */
21
+ /** A concrete text caret position, usable as a Selection anchor or focus. */
22
+ export interface TextCaretPosition {
23
+ node: Text;
24
+ offset: number;
25
+ }
26
+ export declare function collectTextNodes(root: HTMLElement): Text[];
27
+ export declare function projectionAbsoluteOffset(root: HTMLElement, caret: TextCaretPosition): number | null;
28
+ export declare function projectionCaretAt(root: HTMLElement, absoluteOffset: number, affinity: 'forward' | 'backward'): TextCaretPosition | null;
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Which projected lines a content block materializes for a given visible band.
3
+ *
4
+ * Extracted as a **shared module** rather than onto a collaborator because both
5
+ * sides of the grid cut need it. `Scene.syncContentProjection` calls
6
+ * {@link projectionLineWindow} for the plain carrier branch and stays on the
7
+ * facade; {@link ContentGridProjector} calls {@link projectionGridLineWindow} for
8
+ * the grid branch and has moved. Duplicating the scan would let the two branches
9
+ * disagree about which lines are present, and a window that disagrees with the
10
+ * carriers it drives serves stale geometry to selection and find-in-page.
11
+ *
12
+ * This is the `content-caret` precedent from `DEC-0022`: a stateless helper that
13
+ * outlived the class it was private to.
14
+ *
15
+ * Every symbol here was module-private in `Scene.ts` and stays module-private to
16
+ * the package. The core barrel re-exports everything from `./tree/Scene`, so
17
+ * re-exporting from there would silently widen the public API (`DEC-0019` rule 3).
18
+ *
19
+ * Stateless by design — no `Scene`, no entities, no DOM.
20
+ */
21
+ import type { PreparedContentGrid } from '@vectojs/text';
22
+ import type { ContentProjection } from '../Entity';
23
+ /** Half-open range of projected line indices to materialize. */
24
+ export interface ProjectionLineWindow {
25
+ start: number;
26
+ /** Exclusive. */
27
+ end: number;
28
+ /** False when the whole document is being projected. */
29
+ gated: boolean;
30
+ }
31
+ /**
32
+ * The contiguous run of lines overlapping `band`, in entity-local y.
33
+ *
34
+ * **Contiguous on purpose.** A gap would break selection: the DOM order of
35
+ * carriers is what the browser walks when extending a selection or serialising
36
+ * a copy, so materializing lines 0-9 and 90-99 with nothing between them would
37
+ * let a drag from line 5 to line 95 silently splice out 80 lines of text. A
38
+ * single window can only lose text at its *edges*, where the user cannot reach
39
+ * without scrolling, and scrolling rebuilds the window.
40
+ *
41
+ * Falls back to the whole document whenever the answer is not clearly better:
42
+ * a null band, a document that fits, or a window that would cover everything
43
+ * anyway. Emitting nothing is never correct — projected text is what serves
44
+ * find-in-page, copy and, for static text, the screen reader.
45
+ */
46
+ export declare function projectionLineWindow(lines: ReadonlyArray<{
47
+ y: number;
48
+ lineHeight?: number;
49
+ }>, band: {
50
+ minY: number;
51
+ maxY: number;
52
+ } | null, fallbackLineHeight: number): ProjectionLineWindow;
53
+ /**
54
+ * {@link projectionLineWindow} for a prepared grid.
55
+ *
56
+ * A grid line's y comes from the parallel `projection.lines` entry when present
57
+ * and otherwise from `lineIndex * grid.lineHeight`, which is the same fallback
58
+ * the materialization loop uses for positioning — so the window and the carriers
59
+ * always agree on where a line is.
60
+ */
61
+ export declare function projectionGridLineWindow(grid: PreparedContentGrid, projectionLines: ContentProjection['lines'], band: {
62
+ minY: number;
63
+ maxY: number;
64
+ } | null): ProjectionLineWindow;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vectojs/core",
3
- "version": "1.32.7",
3
+ "version": "1.33.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },