74 lines
1.8 KiB
TypeScript
74 lines
1.8 KiB
TypeScript
export const DOCS_RULER_MIN_MARGIN_PX = 12
|
|
export const DOCS_RULER_MIN_BODY_PX = 48
|
|
|
|
export type DocsRulerMarginSide = "left" | "right" | "top" | "bottom"
|
|
|
|
export type DocsPageMarginsPx = {
|
|
top: number
|
|
right: number
|
|
bottom: number
|
|
left: number
|
|
}
|
|
|
|
export function clampPageMarginPx(
|
|
side: DocsRulerMarginSide,
|
|
valuePx: number,
|
|
margins: DocsPageMarginsPx,
|
|
pageWidth: number,
|
|
pageHeight: number
|
|
): number {
|
|
const min = DOCS_RULER_MIN_MARGIN_PX
|
|
const bodyMin = DOCS_RULER_MIN_BODY_PX
|
|
|
|
switch (side) {
|
|
case "left":
|
|
return Math.round(
|
|
Math.max(min, Math.min(valuePx, pageWidth - margins.right - bodyMin))
|
|
)
|
|
case "right": {
|
|
const right = Math.round(
|
|
Math.max(min, Math.min(valuePx, pageWidth - margins.left - bodyMin))
|
|
)
|
|
return right
|
|
}
|
|
case "top":
|
|
return Math.round(
|
|
Math.max(min, Math.min(valuePx, pageHeight - margins.bottom - bodyMin))
|
|
)
|
|
case "bottom": {
|
|
const bottom = Math.round(
|
|
Math.max(min, Math.min(valuePx, pageHeight - margins.top - bodyMin))
|
|
)
|
|
return bottom
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Horizontal ruler X → left margin px. */
|
|
export function pagePxFromHorizontalPointer(
|
|
pointerX: number,
|
|
rulerLeft: number,
|
|
scale: number
|
|
): number {
|
|
if (scale <= 0) return 0
|
|
return (pointerX - rulerLeft) / scale
|
|
}
|
|
|
|
/** Vertical ruler Y → distance from page top px. */
|
|
export function pagePxFromVerticalPointer(
|
|
pointerY: number,
|
|
rulerTop: number,
|
|
scale: number
|
|
): number {
|
|
if (scale <= 0) return 0
|
|
return (pointerY - rulerTop) / scale
|
|
}
|
|
|
|
export function mergeMarginPreview(
|
|
margins: DocsPageMarginsPx,
|
|
preview: Partial<DocsPageMarginsPx> | null | undefined
|
|
): DocsPageMarginsPx {
|
|
if (!preview) return margins
|
|
return { ...margins, ...preview }
|
|
}
|