59 lines
1.7 KiB
TypeScript
59 lines
1.7 KiB
TypeScript
import { MM_TO_PX, type PageFormatId } from "@/lib/drive/page-formats"
|
|
import { DOCS_RULER_INCH_PX } from "@/lib/drive/docs-ruler-scale"
|
|
|
|
export type DocsRulerUnit = "cm" | "inch"
|
|
|
|
/** One centimetre in page coordinate space. */
|
|
export const DOCS_RULER_CM_PX = MM_TO_PX * 10
|
|
|
|
const INCH_FORMAT_IDS = new Set<PageFormatId>(["letter", "legal", "tabloid"])
|
|
const CM_FORMAT_IDS = new Set<PageFormatId>(["a4", "a5"])
|
|
|
|
export function resolveRulerUnit(formatId: PageFormatId): DocsRulerUnit {
|
|
if (INCH_FORMAT_IDS.has(formatId)) return "inch"
|
|
if (CM_FORMAT_IDS.has(formatId)) return "cm"
|
|
return "cm"
|
|
}
|
|
|
|
export type DocsRulerUnitConfig = {
|
|
unit: DocsRulerUnit
|
|
majorStepPx: number
|
|
minorDivisions: number
|
|
}
|
|
|
|
export function getRulerUnitConfig(formatId: PageFormatId): DocsRulerUnitConfig {
|
|
const unit = resolveRulerUnit(formatId)
|
|
if (unit === "inch") {
|
|
return {
|
|
unit,
|
|
majorStepPx: DOCS_RULER_INCH_PX,
|
|
minorDivisions: 8,
|
|
}
|
|
}
|
|
return {
|
|
unit,
|
|
majorStepPx: DOCS_RULER_CM_PX,
|
|
minorDivisions: 10,
|
|
}
|
|
}
|
|
|
|
export function formatRulerMajorLabel(value: number, unit: DocsRulerUnit): string {
|
|
if (value === 0) return "0"
|
|
const abs = Math.abs(value)
|
|
if (unit === "cm") {
|
|
return Number.isInteger(abs) ? String(value) : value.toFixed(1).replace(".", ",")
|
|
}
|
|
return Number.isInteger(abs) ? String(value) : String(Math.round(value * 10) / 10)
|
|
}
|
|
|
|
/** Margin distance from page edge, in the ruler unit for the page format. */
|
|
export function formatMarginDistanceLabel(
|
|
marginPx: number,
|
|
formatId: PageFormatId
|
|
): string {
|
|
const { unit, majorStepPx } = getRulerUnitConfig(formatId)
|
|
const value = marginPx / majorStepPx
|
|
const formatted = formatRulerMajorLabel(value, unit)
|
|
return unit === "inch" ? `${formatted}"` : `${formatted} cm`
|
|
}
|