@sobree/core 0.1.6 → 0.1.8

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,13 @@
1
+ /**
2
+ * The narrow surface gesture controllers drive the Viewport through.
3
+ * Controllers translate raw input events into these calls; the Viewport
4
+ * owns all transform state, clamping, and raster behaviour.
5
+ */
6
+ export interface GestureHost {
7
+ /** Pan the stage by `(dx, dy)` CSS pixels. */
8
+ panBy(dx: number, dy: number): void;
9
+ /** Zoom to `scale`, anchoring the point at (clientX, clientY). */
10
+ zoomTo(scale: number, clientX: number, clientY: number): void;
11
+ /** Current visual scale (zoom deltas are multiplicative on this). */
12
+ getScale(): number;
13
+ }
@@ -0,0 +1,38 @@
1
+ import { GestureHost } from './gestureHost';
2
+ /**
3
+ * Touch gestures (mobile): one-finger drag pans, two-finger pinch zooms
4
+ * anchored at the finger midpoint, and translating both fingers pans.
5
+ * Mouse/pen pointers are deliberately ignored — their drag is text
6
+ * selection, not pan. The container has `touch-action: none`, so without
7
+ * this controller touch devices could neither scroll nor zoom.
8
+ */
9
+ export declare class TouchGestures {
10
+ private readonly container;
11
+ private readonly host;
12
+ /** Live touch pointers (pointerId → last client position). */
13
+ private readonly points;
14
+ /** `idle` → no touches; `tap` → one finger down, within slop; `pan` →
15
+ * one finger past slop; `pinch` → two fingers. */
16
+ private mode;
17
+ /** First touch's start position — slop is measured from here. */
18
+ private startX;
19
+ private startY;
20
+ /** Finger distance and scale captured when a pinch begins. */
21
+ private pinchStartDist;
22
+ private pinchStartScale;
23
+ /** Set when a pan/pinch actually moved the stage — the synthetic click
24
+ * browsers fire after the touch sequence must not reach the editor
25
+ * (it would teleport the caret to wherever the drag ended). */
26
+ private suppressNextClick;
27
+ private readonly onPointerDown;
28
+ private readonly onPointerMove;
29
+ private readonly onPointerEnd;
30
+ private readonly onClickCapture;
31
+ constructor(container: HTMLElement, host: GestureHost);
32
+ destroy(): void;
33
+ private handleDown;
34
+ private handleMove;
35
+ private movePinch;
36
+ private handleEnd;
37
+ private beginPinch;
38
+ }
@@ -1,3 +1,4 @@
1
+ import { GestureHost } from './gestureHost';
1
2
  export interface ViewportOptions {
2
3
  minScale?: number;
3
4
  maxScale?: number;
@@ -7,11 +8,11 @@ export interface ViewportOptions {
7
8
  pinchZoomSensitivity?: number;
8
9
  onScaleChange?: (scale: number) => void;
9
10
  /**
10
- * Fires when the render tier changes an integer ≥1 chosen from the
11
- * current scale. The stage is laid out at that tier via CSS `zoom` so
12
- * text rasterises at the zoomed size rather than being blitted from a
13
- * 1× bitmap. Callers that care about layout (e.g. a paginator) should
14
- * re-run their measurement + layout pass when the tier changes.
11
+ * @deprecated Inert never fires. Layout-side zoom tiers are retired
12
+ * (see `pickRenderTier`): the tier is permanently 1, because tiered
13
+ * CSS-`zoom` re-layout rewrapped text and shifted pagination at tier
14
+ * boundaries. Zoom is a pure `transform: scale`; sharpness comes from
15
+ * the settle-phase re-raster. Retained so existing wiring compiles.
15
16
  */
16
17
  onRenderTierChange?: (tier: number) => void;
17
18
  /**
@@ -31,19 +32,18 @@ export interface ViewportOptions {
31
32
  * └ stage (absolutely positioned, transform: translate(tx,ty) scale(s))
32
33
  * └ slot (where the embedded content lives — caller mounts here)
33
34
  *
34
- * Gestures:
35
- * - Zoom: wheel with shiftKey OR ctrlKey (macOS pinch emits ctrlKey).
36
- * The point under the cursor stays under the cursor (zoom-to-cursor).
37
- * - Pan: wheel without modifiers two-finger trackpad scroll deltas move
38
- * the stage. Also supports click-drag with middle mouse or space.
39
- * - Touch (mobile): one-finger drag pans (after a small slop so taps
40
- * still place the caret); two-finger pinch zooms anchored at the
41
- * finger midpoint, and moving both fingers pans. Mouse/pen
42
- * pointers are deliberately excludedmouse drag is text
43
- * selection. The container has `touch-action: none`, so without
44
- * these handlers touch devices could neither scroll nor zoom.
35
+ * Input handling lives in two controllers driving this class through the
36
+ * GestureHost interface:
37
+ * - WheelGestures: zoom on shift/ctrl/meta+wheel (macOS pinch emits
38
+ * ctrlKey), pan on bare wheel with axis-locking.
39
+ * - TouchGestures (mobile): one-finger drag pans (after a small slop so
40
+ * taps still place the caret); two-finger pinch zooms anchored at the
41
+ * finger midpoint. Mouse/pen drag stays text selection.
42
+ *
43
+ * Viewport itself implements GestureHost panBy / zoomTo / getScale are
44
+ * its public API, so the controllers just receive `this`.
45
45
  */
46
- export declare class Viewport {
46
+ export declare class Viewport implements GestureHost {
47
47
  readonly container: HTMLElement;
48
48
  readonly slot: HTMLElement;
49
49
  private readonly stage;
@@ -52,61 +52,25 @@ export declare class Viewport {
52
52
  private ty;
53
53
  private readonly minScale;
54
54
  private readonly maxScale;
55
- private readonly wheelZoomSensitivity;
56
- private readonly pinchZoomSensitivity;
57
55
  private readonly onScaleChange;
58
56
  private readonly onRenderTierChange;
59
57
  private readonly onTransformChange;
60
- private readonly onWheel;
58
+ private readonly wheelGestures;
59
+ private readonly touchGestures;
61
60
  /** Current layout-side zoom factor (integer ≥ 1). See ViewportOptions. */
62
61
  private renderTier;
63
62
  /** Suppresses `onTransformChange` during the constructor's initial
64
63
  * `applyTransform` so consumers can capture `viewport` in their
65
64
  * callback without TDZ traps. Flipped true at the end of the ctor. */
66
65
  private constructed;
67
- /** Timestamp of the last wheel event, used to delimit gestures. */
68
- private gestureLastTime;
69
- /** Dominant axis for the current gesture. Null until detected, cleared at gesture end. */
70
- private gesturePrimaryAxis;
71
- /**
72
- * Signed cumulative dx within the current gesture. Drives lock release:
73
- * wobble (±3-5px back-and-forth) cancels out; sustained one-way motion
74
- * accumulates past the threshold quickly. Reset at gesture end.
75
- */
76
- private gestureSignedDx;
77
- /**
78
- * Sticky horizontal-lock flag. Engaged by `fitTo` so alignment survives
79
- * gentle diagonal trackpad gestures; broken when the gesture's signed
80
- * cumulative dx crosses `X_RELEASE_THRESHOLD` — the user clearly intends
81
- * sustained horizontal motion.
82
- */
83
- private horizontalLock;
84
- /** Live touch pointers (pointerId → last client position). Mouse and
85
- * pen never enter this map — their drag is text selection, not pan. */
86
- private readonly touchPoints;
87
- /** `idle` → no touches; `tap` → one finger down, within slop (a tap
88
- * must still reach the editor to place the caret); `pan` → one finger
89
- * past slop; `pinch` → two fingers. */
90
- private touchMode;
91
- /** First touch's start position — slop is measured from here. */
92
- private touchStartX;
93
- private touchStartY;
94
- /** Finger distance and scale captured when a pinch begins. */
95
- private pinchStartDist;
96
- private pinchStartScale;
97
- private readonly onPointerDown;
98
- private readonly onPointerMove;
99
- private readonly onPointerEnd;
100
- private readonly onClickCapture;
101
- /** Set when a pan/pinch actually moved the stage — the synthetic click
102
- * browsers fire after the touch sequence must not reach the editor
103
- * (it would teleport the caret to wherever the drag ended). */
104
- private suppressNextClick;
66
+ /** Debounce handle for the crisp-text settle pass (see scheduleSettle). */
67
+ private settleTimer;
105
68
  constructor(container: HTMLElement, options?: ViewportOptions);
106
69
  /** Reset pan to origin and scale to 1. */
107
70
  reset(): void;
108
71
  getScale(): number;
109
- /** Integer layout-side zoom currently applied via CSS `zoom` on the stage. */
72
+ /** @deprecated Always `1` — layout-side zoom tiers are retired (see
73
+ * `pickRenderTier`). Retained so existing wiring compiles. */
110
74
  getRenderTier(): number;
111
75
  /**
112
76
  * Fit `target` to the viewport.
@@ -129,24 +93,32 @@ export declare class Viewport {
129
93
  /** Zoom to `nextScale`, anchoring the point at (clientX, clientY) in container space. */
130
94
  zoomTo(nextScale: number, clientX: number, clientY: number): void;
131
95
  destroy(): void;
132
- private handleWheel;
133
- private handleTouchDown;
134
- private handleTouchMove;
135
- private handleTouchEnd;
136
- private beginPinch;
96
+ private applyTransform;
137
97
  /**
138
- * Axis-lock for pan gestures:
139
- * - Within a gesture (events GESTURE_GAP_MS apart), a clear dominant
140
- * axis zeros the other axis so a nearly-vertical swipe doesn't also
141
- * drift the paper sideways.
142
- * - An explicit `horizontalLock` set by `fitTo` survives across gestures,
143
- * keeping fit-page / fit-width alignment stable.
144
- * - Both locks release when the gesture's signed cumulative dx crosses
145
- * `X_RELEASE_THRESHOLD`. Signed sum cancels wobble (back-and-forth
146
- * averages to zero) while sustained one-way motion accumulates fast.
98
+ * The stage transform, expressed in the render tier's coordinate space.
99
+ * Chrome applies transforms post-`zoom`, so a `translate(tx, ty)` on an
100
+ * element with `zoom: k` moves by `(tx*k, ty*k)` screen px. We store
101
+ * tx/ty in pre-zoom (container) pixels — the scheme cursor-anchored
102
+ * zoomTo relies on so divide by the tier to cancel zoom's translate
103
+ * multiplication. (Tier is permanently 1; kept for the single code path.)
104
+ *
105
+ * `threeD` selects the gesture-time form (`translate3d` — forces a
106
+ * compositor layer) vs the settled form (plain `translate` — lets the
107
+ * compositor drop the layer pin and re-rasterise text at the effective
108
+ * scale). Same matrix either way; only raster-cache behaviour differs.
147
109
  */
148
- private applyScrollAxisLock;
149
- private applyTransform;
110
+ private transformCss;
111
+ /**
112
+ * Crisp-text pass: once no transform has been written for SETTLE_MS,
113
+ * drop `will-change` and the 3D form so the compositor re-rasterises
114
+ * the (now static) stage at `devicePixelRatio × scale` — text is then
115
+ * as sharp at 3× as a 3×-laid-out page, with zero layout involvement.
116
+ * Both pins are needed: either `will-change: transform` or a 3D
117
+ * transform alone keeps browsers (Safari especially) stretching the
118
+ * stale 1× texture. The next gesture frame re-pins before moving.
119
+ */
120
+ private scheduleSettle;
121
+ private settle;
150
122
  /**
151
123
  * Apply the current transform with a CSS transition. Used only for
152
124
  * programmatic fits — wheel pan/zoom must stay instant or feel sluggish.
@@ -0,0 +1,54 @@
1
+ import { GestureHost } from './gestureHost';
2
+ export interface WheelGestureOptions {
3
+ /** Scale change per unit of wheel deltaY for shift+wheel. */
4
+ wheelZoomSensitivity: number;
5
+ /** Scale change per unit of wheel deltaY for pinch (ctrlKey). */
6
+ pinchZoomSensitivity: number;
7
+ }
8
+ /**
9
+ * Wheel gestures: zoom on shift/ctrl/meta+wheel (macOS trackpad pinch
10
+ * synthesises ctrlKey wheel events), pan on bare wheel — with an
11
+ * axis-lock so a nearly-vertical swipe doesn't drift the paper sideways.
12
+ */
13
+ export declare class WheelGestures {
14
+ private readonly container;
15
+ private readonly host;
16
+ private readonly opts;
17
+ /** Timestamp of the last wheel event, used to delimit gestures. */
18
+ private gestureLastTime;
19
+ /** Dominant axis for the current gesture. Null until detected, cleared at gesture end. */
20
+ private gesturePrimaryAxis;
21
+ /**
22
+ * Signed cumulative dx within the current gesture. Drives lock release:
23
+ * wobble (±3-5px back-and-forth) cancels out; sustained one-way motion
24
+ * accumulates past the threshold quickly. Reset at gesture end.
25
+ */
26
+ private gestureSignedDx;
27
+ /**
28
+ * Sticky horizontal-lock flag. Engaged by `fitTo` so alignment survives
29
+ * gentle diagonal trackpad gestures; broken when the gesture's signed
30
+ * cumulative dx crosses `X_RELEASE_THRESHOLD` — the user clearly
31
+ * intends sustained horizontal motion.
32
+ */
33
+ private horizontalLock;
34
+ private readonly onWheel;
35
+ constructor(container: HTMLElement, host: GestureHost, opts: WheelGestureOptions);
36
+ destroy(): void;
37
+ /** Engage the sticky horizontal lock (fit-* picked an X alignment). */
38
+ engageHorizontalLock(): void;
39
+ /** Clear all gesture and lock state (viewport reset). */
40
+ resetLocks(): void;
41
+ private handleWheel;
42
+ /**
43
+ * Axis-lock for pan gestures:
44
+ * - Within a gesture (events ≤ GESTURE_GAP_MS apart), a clear dominant
45
+ * axis zeros the other axis so a nearly-vertical swipe doesn't also
46
+ * drift the paper sideways.
47
+ * - An explicit `horizontalLock` set by `fitTo` survives across gestures,
48
+ * keeping fit-page / fit-width alignment stable.
49
+ * - Both locks release when the gesture's signed cumulative dx crosses
50
+ * `X_RELEASE_THRESHOLD`. Signed sum cancels wobble (back-and-forth
51
+ * averages to zero) while sustained one-way motion accumulates fast.
52
+ */
53
+ private applyScrollAxisLock;
54
+ }
package/dist/index.css CHANGED
@@ -1 +1 @@
1
- .paper-stack{display:flex;flex-direction:column;padding:48px;gap:28px;outline:none}.paper-row{display:flex;flex-direction:row;align-items:flex-start;gap:24px}.paper{position:relative;background:#fff;border:1px solid rgba(0,0,0,.3);box-shadow:0 1px 2px #00000014,0 18px 60px #0000001f;padding-top:var(--margin-top, 25mm);padding-right:var(--margin-right, 20mm);padding-bottom:var(--margin-bottom, 25mm);padding-left:var(--margin-left, 20mm);overflow:hidden;flex:none}.paper-header,.paper-footer{position:absolute;left:var(--margin-left, 20mm);right:var(--margin-right, 20mm);font-size:10pt;color:#555;white-space:pre-wrap}.paper-header{top:0;min-height:var(--margin-top, 25mm);padding-top:var(--header-offset-mm, 12.7mm);padding-bottom:4mm;border-bottom:1px dashed transparent}.paper-footer{bottom:0;min-height:var(--margin-bottom, 25mm);padding-top:4mm;text-align:center;border-top:1px dashed transparent}.paper-anchors{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;isolation:isolate;z-index:1}.paper-anchors.is-empty{display:none}.paper-anchors-behind{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;isolation:isolate;z-index:0}.paper-anchors-behind.is-empty{display:none}.paper-zone-anchors{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;isolation:isolate;z-index:2}.paper-zone-anchors.is-empty{display:none}.paper-anchor{position:absolute;box-sizing:border-box;overflow:hidden}.paper-header>p,.paper-footer>p,.paper-header>ul,.paper-header>ol,.paper-footer>ul,.paper-footer>ol{margin:0}.paper-footnotes{position:absolute;left:var(--margin-left, 20mm);right:var(--margin-right, 20mm);bottom:var(--margin-bottom, 25mm);font-size:.85em;padding-top:.5em;border-top:1pt solid currentColor;background:#fffffff5;z-index:1;max-height:40%;overflow:hidden}.paper-footnotes.is-empty{display:none}.paper-comments{flex:0 0 70mm;max-width:70mm;font-size:.85em;padding:0 .5em;align-self:stretch;overflow-y:auto}.paper-comments.is-empty{display:none}.paper-footnotes .sobree-footnotes__list{margin:0;padding-left:1.5em}.paper-footnotes .sobree-footnotes__item{margin:.25em 0}.paper-content a{color:inherit;text-decoration:none}.paper-content{position:relative;height:100%;min-height:100px;display:flow-root}.paper-content td p:not([style*=line-height]),.paper-content td li:not([style*=line-height]),.paper-content th p:not([style*=line-height]),.paper-content th li:not([style*=line-height]){line-height:1}.paper-content td p:not([style*=margin]),.paper-content th p:not([style*=margin]){margin:0}.paper-content .sobree-hang>li{list-style:none}.paper-content .sobree-hang>li:before{display:inline-block;box-sizing:border-box;width:var(--sobree-list-hang, 0);margin-left:calc(-1 * var(--sobree-list-hang, 0));white-space:nowrap;color:var(--sobree-marker-color, currentColor);font-family:var(--sobree-marker-font, inherit);font-size:var(--sobree-marker-size, inherit)}.paper-content .sobree-hang.lst-bullet>li:before{content:var(--sobree-bullet, "•")}.paper-content .sobree-hang.lst-decimal>li:before{content:var(--mk-pre, "") counter(list-item,decimal) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-decimal-zero>li:before{content:var(--mk-pre, "") counter(list-item,decimal-leading-zero) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-lower-latin>li:before{content:var(--mk-pre, "") counter(list-item,lower-latin) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-upper-latin>li:before{content:var(--mk-pre, "") counter(list-item,upper-latin) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-lower-roman>li:before{content:var(--mk-pre, "") counter(list-item,lower-roman) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-upper-roman>li:before{content:var(--mk-pre, "") counter(list-item,upper-roman) var(--mk-suf, ".")}.paper-content .sobree-tab-spread{display:flex;justify-content:space-between;align-items:baseline;gap:1em;white-space:nowrap}.paper-content .sobree-tab-spread .sobree-tab-spread__before,.paper-content .sobree-tab-spread .sobree-tab-spread__after{white-space:pre-wrap;min-width:0}.paper-content table.sobree-table-bordered td,.paper-content table.sobree-table-bordered th{border:var(--table-cell-border, none);padding:0 4px}.sobree-editor{position:relative;outline:none}.sobree-editor>:first-child{margin-top:0}.sobree-editor p,.sobree-editor h1,.sobree-editor h2,.sobree-editor h3,.sobree-editor h4,.sobree-editor h5,.sobree-editor h6,.sobree-editor ul,.sobree-editor ol,.sobree-editor li,.sobree-editor blockquote,.sobree-editor pre{margin:0;padding:0}.sobree-editor ul,.sobree-editor ol{padding-left:1.5em}.sobree-editor li.sobree-li-continuation{list-style-type:none}.sobree-editor li.sobree-li-continuation::marker{content:""}.sobree-editor .sobree-fragment-continued{text-align-last:justify}.sobree-editor .sobree-footnote-ref a{color:inherit;text-decoration:none}.sobree-editor .sobree-footnote-ref a:hover{text-decoration:underline}.sobree-editor .sobree-footnotes{margin-top:2em;padding-top:.5em;border-top:1pt solid currentColor;font-size:.85em}.sobree-editor .sobree-footnotes__list{padding-left:1.5em}.sobree-editor .sobree-footnotes__item{margin:.25em 0}.sobree-editor ins.sobree-revision-ins{text-decoration:underline}.sobree-editor del.sobree-revision-del{text-decoration:line-through}.sobree-editor .sobree-revision-format{text-decoration:underline dashed var(--sobree-format-revision-color, currentColor);text-underline-offset:3px}.sobree-editor [data-block-revision=ins]:after,.sobree-editor [data-block-revision=del]:after{content:" ¶";color:var(--sobree-block-revision-color, currentColor);opacity:.65;font-weight:600;-webkit-user-select:none;user-select:none}.sobree-editor [data-block-revision=del]:after{text-decoration:line-through}.sobree-editor .sobree-comment-range{background:var(--sobree-comment-range-bg, rgba(255, 217, 0, .25));border-bottom:1px dotted var(--sobree-comment-range-border, rgba(180, 130, 0, .5))}.sobree-editor .sobree-comment-ref{display:inline;font-size:.85em;margin:0 .1em}.sobree-editor .sobree-comment-ref a{color:inherit;text-decoration:none}.sobree-editor .sobree-comment-ref a:hover{filter:brightness(.7)}.sobree-editor h1,.sobree-editor h2,.sobree-editor h3,.sobree-editor h4,.sobree-editor h5,.sobree-editor h6{font-size:inherit;font-weight:inherit}.sobree-editor table{border-collapse:collapse;width:100%;position:relative}.sobree-editor th,.sobree-editor td{border:none;padding:0 .08in;vertical-align:top;transition:border-color .12s ease}.sobree-editor .sobree-section-break{display:flex;align-items:center;gap:8px;margin:8px 0;color:var(--fg-subtle, #7c7764);font-size:11px;letter-spacing:.04em;text-transform:uppercase;-webkit-user-select:none;user-select:none}.sobree-editor .sobree-section-break--continuous{visibility:hidden;height:0;margin:0;padding:0;border:none;overflow:hidden;font-size:0;line-height:0}.sobree-editor .sobree-section-break:before,.sobree-editor .sobree-section-break:after{content:"";flex:1;border-top:1px dashed var(--border, #dedbd0)}.sobree-editor .sobree-section-break__label{flex:none;padding:0 6px;background:var(--bg-elevated, #fff)}.sobree-editor .sobree-textbox-frame p{line-height:1.2}.sobree-editor .paper-content p,.sobree-editor .paper-content li,.sobree-editor .paper-header p,.sobree-editor .paper-header li,.sobree-editor .paper-footer p,.sobree-editor .paper-footer li,.sobree-editor .sobree-textbox-frame p{white-space:pre-wrap}.sobree-editor .sobree-section-trailer-empty{height:0;line-height:0;font-size:0;margin:0;padding:0;overflow:hidden}.sobree-editor .sobree-textbox-frame--placeholder{border:1px solid var(--border, #c8c4b8)}.sobree-editor .sobree-textbox-frame--placeholder.sobree-textbox-frame--filled{border:none;z-index:-1}.sobree-editor img.is-selected{outline:2px solid var(--sobree-primary, #d4521f);outline-offset:2px}.sobree-image-resize-handle{position:absolute;width:16px;height:16px;background:var(--sobree-primary, #d4521f);border:2px solid #fff;border-radius:3px;cursor:nwse-resize;z-index:1000;-webkit-user-select:none;user-select:none}.sobree-viewport{position:relative;overflow:hidden;overscroll-behavior:contain;touch-action:none;background:#ececee}.sobree-viewport__stage{position:absolute;top:0;left:0;transform-origin:0 0;will-change:transform}.sobree-viewport__stage.is-animating{transition:transform .32s cubic-bezier(.2,.7,.2,1)}.sobree-viewport__slot{display:block}.paper-stack .paper-content,.paper-stack .paper-header,.paper-stack .paper-footer{transition:opacity .2s ease}.paper-stack.is-zone-editing .paper-content,.paper-stack.is-zone-editing .paper-header,.paper-stack.is-zone-editing .paper-footer{opacity:.2}.paper-stack.is-zone-editing .paper-header[contenteditable=true],.paper-stack.is-zone-editing .paper-footer[contenteditable=true]{opacity:1}.paper-header[contenteditable=true],.paper-footer[contenteditable=true]{outline:2px dotted var(--primary, #c96f22);outline-offset:4px;background:var(--primary-soft, #fdf6ee);color:var(--fg-strong, #14130f);border-radius:2px}
1
+ .paper-stack{display:flex;flex-direction:column;padding:48px;gap:28px;outline:none}.paper-row{display:flex;flex-direction:row;align-items:flex-start;gap:24px}.paper{position:relative;background:#fff;border:1px solid rgba(0,0,0,.3);box-shadow:0 1px 2px #00000014,0 18px 60px #0000001f;padding-top:var(--margin-top, 25mm);padding-right:var(--margin-right, 20mm);padding-bottom:var(--margin-bottom, 25mm);padding-left:var(--margin-left, 20mm);overflow:hidden;flex:none}.paper-header,.paper-footer{position:absolute;left:var(--margin-left, 20mm);right:var(--margin-right, 20mm);font-size:10pt;color:#555;white-space:pre-wrap}.paper-header{top:0;min-height:var(--margin-top, 25mm);padding-top:var(--header-offset-mm, 12.7mm);padding-bottom:4mm;border-bottom:1px dashed transparent}.paper-footer{bottom:0;min-height:var(--margin-bottom, 25mm);padding-top:4mm;text-align:center;border-top:1px dashed transparent}.paper-anchors{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;isolation:isolate;z-index:1}.paper-anchors.is-empty{display:none}.paper-anchors-behind{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;isolation:isolate;z-index:0}.paper-anchors-behind.is-empty{display:none}.paper-zone-anchors{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;isolation:isolate;z-index:2}.paper-zone-anchors.is-empty{display:none}.paper-anchor{position:absolute;box-sizing:border-box;overflow:hidden}.paper-header>p,.paper-footer>p,.paper-header>ul,.paper-header>ol,.paper-footer>ul,.paper-footer>ol{margin:0}.paper-footnotes{position:absolute;left:var(--margin-left, 20mm);right:var(--margin-right, 20mm);bottom:var(--margin-bottom, 25mm);font-size:.85em;padding-top:.5em;border-top:1pt solid currentColor;background:#fffffff5;z-index:1;max-height:40%;overflow:hidden}.paper-footnotes.is-empty{display:none}.paper-comments{flex:0 0 70mm;max-width:70mm;font-size:.85em;padding:0 .5em;align-self:stretch;overflow-y:auto}.paper-comments.is-empty{display:none}.paper-footnotes .sobree-footnotes__list{margin:0;padding-left:1.5em}.paper-footnotes .sobree-footnotes__item{margin:.25em 0}.paper-content a{color:inherit;text-decoration:none}.paper-content{position:relative;height:100%;min-height:100px;display:flow-root}.paper-content td p:not([style*=line-height]),.paper-content td li:not([style*=line-height]),.paper-content th p:not([style*=line-height]),.paper-content th li:not([style*=line-height]){line-height:1}.paper-content td p:not([style*=margin]),.paper-content th p:not([style*=margin]){margin:0}.paper-content .sobree-hang>li{list-style:none}.paper-content .sobree-hang>li:before{display:inline-block;box-sizing:border-box;width:var(--sobree-list-hang, 0);margin-left:calc(-1 * var(--sobree-list-hang, 0));white-space:nowrap;color:var(--sobree-marker-color, currentColor);font-family:var(--sobree-marker-font, inherit);font-size:var(--sobree-marker-size, inherit)}.paper-content .sobree-hang.lst-bullet>li:before{content:var(--sobree-bullet, "•")}.paper-content .sobree-hang.lst-decimal>li:before{content:var(--mk-pre, "") counter(list-item,decimal) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-decimal-zero>li:before{content:var(--mk-pre, "") counter(list-item,decimal-leading-zero) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-lower-latin>li:before{content:var(--mk-pre, "") counter(list-item,lower-latin) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-upper-latin>li:before{content:var(--mk-pre, "") counter(list-item,upper-latin) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-lower-roman>li:before{content:var(--mk-pre, "") counter(list-item,lower-roman) var(--mk-suf, ".")}.paper-content .sobree-hang.lst-upper-roman>li:before{content:var(--mk-pre, "") counter(list-item,upper-roman) var(--mk-suf, ".")}.paper-content .sobree-tab-spread{display:flex;justify-content:space-between;align-items:baseline;gap:1em;white-space:nowrap}.paper-content .sobree-tab-spread .sobree-tab-spread__before,.paper-content .sobree-tab-spread .sobree-tab-spread__after{white-space:pre-wrap;min-width:0}.paper-content table.sobree-table-bordered td,.paper-content table.sobree-table-bordered th{border:var(--table-cell-border, none);padding:0 4px}.sobree-editor{position:relative;outline:none}.sobree-editor>:first-child{margin-top:0}.sobree-editor p,.sobree-editor h1,.sobree-editor h2,.sobree-editor h3,.sobree-editor h4,.sobree-editor h5,.sobree-editor h6,.sobree-editor ul,.sobree-editor ol,.sobree-editor li,.sobree-editor blockquote,.sobree-editor pre{margin:0;padding:0}.sobree-editor ul,.sobree-editor ol{padding-left:1.5em}.sobree-editor li.sobree-li-continuation{list-style-type:none}.sobree-editor li.sobree-li-continuation::marker{content:""}.sobree-editor .sobree-fragment-continued{text-align-last:justify}.sobree-editor .sobree-footnote-ref a{color:inherit;text-decoration:none}.sobree-editor .sobree-footnote-ref a:hover{text-decoration:underline}.sobree-editor .sobree-footnotes{margin-top:2em;padding-top:.5em;border-top:1pt solid currentColor;font-size:.85em}.sobree-editor .sobree-footnotes__list{padding-left:1.5em}.sobree-editor .sobree-footnotes__item{margin:.25em 0}.sobree-editor ins.sobree-revision-ins{text-decoration:underline}.sobree-editor del.sobree-revision-del{text-decoration:line-through}.sobree-editor .sobree-revision-format{text-decoration:underline dashed var(--sobree-format-revision-color, currentColor);text-underline-offset:3px}.sobree-editor [data-block-revision=ins]:after,.sobree-editor [data-block-revision=del]:after{content:" ¶";color:var(--sobree-block-revision-color, currentColor);opacity:.65;font-weight:600;-webkit-user-select:none;user-select:none}.sobree-editor [data-block-revision=del]:after{text-decoration:line-through}.sobree-editor .sobree-comment-range{background:var(--sobree-comment-range-bg, rgba(255, 217, 0, .25));border-bottom:1px dotted var(--sobree-comment-range-border, rgba(180, 130, 0, .5))}.sobree-editor .sobree-comment-ref{display:inline;font-size:.85em;margin:0 .1em}.sobree-editor .sobree-comment-ref a{color:inherit;text-decoration:none}.sobree-editor .sobree-comment-ref a:hover{filter:brightness(.7)}.sobree-editor h1,.sobree-editor h2,.sobree-editor h3,.sobree-editor h4,.sobree-editor h5,.sobree-editor h6{font-size:inherit;font-weight:inherit}.sobree-editor table{border-collapse:collapse;width:100%;position:relative}.sobree-editor th,.sobree-editor td{border:none;padding:0 .08in;vertical-align:top;transition:border-color .12s ease}.sobree-editor .sobree-section-break{display:flex;align-items:center;gap:8px;margin:8px 0;color:var(--fg-subtle, #7c7764);font-size:11px;letter-spacing:.04em;text-transform:uppercase;-webkit-user-select:none;user-select:none}.sobree-editor .sobree-section-break--continuous{visibility:hidden;height:0;margin:0;padding:0;border:none;overflow:hidden;font-size:0;line-height:0}.sobree-editor .sobree-section-break:before,.sobree-editor .sobree-section-break:after{content:"";flex:1;border-top:1px dashed var(--border, #dedbd0)}.sobree-editor .sobree-section-break__label{flex:none;padding:0 6px;background:var(--bg-elevated, #fff)}.sobree-editor .sobree-textbox-frame p{line-height:1.2}.sobree-editor .paper-content p,.sobree-editor .paper-content li,.sobree-editor .paper-header p,.sobree-editor .paper-header li,.sobree-editor .paper-footer p,.sobree-editor .paper-footer li,.sobree-editor .sobree-textbox-frame p{white-space:pre-wrap}.sobree-editor .sobree-section-trailer-empty{height:0;line-height:0;font-size:0;margin:0;padding:0;overflow:hidden}.sobree-editor .sobree-textbox-frame--placeholder{border:1px solid var(--border, #c8c4b8)}.sobree-editor .sobree-textbox-frame--placeholder.sobree-textbox-frame--filled{border:none;z-index:-1}.sobree-editor img.is-selected{outline:2px solid var(--sobree-primary, #d4521f);outline-offset:2px}.sobree-image-resize-handle{position:absolute;width:16px;height:16px;background:var(--sobree-primary, #d4521f);border:2px solid #fff;border-radius:3px;cursor:nwse-resize;z-index:1000;-webkit-user-select:none;user-select:none}.sobree-viewport{position:relative;overflow:hidden;overscroll-behavior:contain;touch-action:none;background:#ececee}.sobree-viewport__stage{position:absolute;top:0;left:0;transform-origin:0 0}.sobree-viewport__stage.is-gesturing,.sobree-viewport__stage.is-animating{will-change:transform}.sobree-viewport__stage.is-animating{transition:transform .32s cubic-bezier(.2,.7,.2,1)}.sobree-viewport__slot{display:block}.paper-stack .paper-content,.paper-stack .paper-header,.paper-stack .paper-footer{transition:opacity .2s ease}.paper-stack.is-zone-editing .paper-content,.paper-stack.is-zone-editing .paper-header,.paper-stack.is-zone-editing .paper-footer{opacity:.2}.paper-stack.is-zone-editing .paper-header[contenteditable=true],.paper-stack.is-zone-editing .paper-footer[contenteditable=true]{opacity:1}.paper-header[contenteditable=true],.paper-footer[contenteditable=true]{outline:2px dotted var(--primary, #c96f22);outline-offset:4px;background:var(--primary-soft, #fdf6ee);color:var(--fg-strong, #14130f);border-radius:2px}
package/dist/index.d.ts CHANGED
@@ -21,16 +21,15 @@ export type { ApiRangeType, RevisionSpan, BlockInfo, ChangePayload, CommandBus,
21
21
  export * from './doc/types';
22
22
  export * from './doc/builders';
23
23
  export { resolveStyleCascade } from './doc/styles';
24
- export { collectLivePartPaths, pruneOrphanParts } from './doc/parts';
25
- export { embedFontIntoDoc, removeFontFromDoc, FontFaceRegistry, generateFontKey, obfuscate, deobfuscate, isUnobfuscated, canEmbed, readFsType, } from './fonts';
24
+ export { embedFontIntoDoc, removeFontFromDoc, FontFaceRegistry, generateFontKey, obfuscate, deobfuscate, canEmbed, readFsType, } from './fonts';
26
25
  export type { EmbedFontFaces, EmbedFontOptions, EmbedFontResult, EmbedMode, FsTypeReport, } from './fonts';
27
26
  export { DEFAULT_HISTORY_CONFIG, History } from './history';
28
27
  export type { HistoryConfig, HistoryDepth, HistoryEvent, HistoryListener, } from './history';
29
- export { templateToBlocks, blocksToTemplate, pageSetupToSection, sectionToPageSetup } from './doc/pageSetupBridge';
28
+ export { templateToBlocks, blocksToTemplate } from './doc/pageSetupBridge';
30
29
  export type { Selection, BlockRef, InlinePosition, Range } from './doc/api';
31
30
  export { PaperStack } from './paperStack/paperStack';
32
31
  export { Paper } from './paperStack/paper';
33
- export { PAGE_SIZES, DEFAULT_PAGE_SETUP, resolvedDimensions, substituteVariables, zoneTemplateFor, } from './paperStack/pageSetup';
32
+ export { PAGE_SIZES, DEFAULT_PAGE_SETUP } from './paperStack/pageSetup';
34
33
  export type { PageSetup, PageSizeKey, PageZoneText, VerticalAlign, Orientation, Margins } from './paperStack/pageSetup';
35
34
  export { Viewport } from './embed/viewport';
36
35
  export type { ViewportOptions } from './embed/viewport';
@@ -41,9 +40,7 @@ export { MARK_COMMAND_DEFS, MARK_PROP, MARK_ON, toggleMark, isMarkActive, rangeA
41
40
  export type { MarkCommandDef, ToggleableMark } from './plugins/marks';
42
41
  export { enterZoneEdit } from './zoneEdit';
43
42
  export type { ZoneKind, EnterZoneEditOptions } from './zoneEdit';
44
- export { Y_BLOCK_AST_KEY, Y_BLOCK_ID_KEY, Y_BLOCK_KIND_KEY, Y_BLOCK_PROPS_KEY, Y_BLOCK_TEXT_KEY, Y_BODY_KEY, Y_META_FIELDS, Y_META_KEY, Y_PARTS_KEY, applyDocumentToYDoc, buildBlockYMap, diffApplyText, populateParagraphYMap, projectBlock, projectYDoc, seedYDoc, } from './ydoc';
45
- export { attrsToRunProps, deltaToRuns, runPropsToAttrs, runsToDelta, } from './ydoc';
46
- export type { DeltaOp, EmbedContent, LinkMark } from './ydoc';
43
+ export { applyDocumentToYDoc, projectYDoc, seedYDoc } from './ydoc';
47
44
  export { BlobCache, BlobStoreError, fetchBlobStore, inMemoryBlobStore, isBlobHash, sha256Hex, } from './blob';
48
45
  export type { BlobCacheOptions, BlobHash, BlobStore, FetchBlobStoreOptions, } from './blob';
49
46
  export { HeadlessSobree } from './headless';