41 lines
1.3 KiB
TypeScript
41 lines
1.3 KiB
TypeScript
export interface SecondaryDisplayGeometry {
|
|
left: number
|
|
top: number
|
|
width: number
|
|
height: number
|
|
}
|
|
|
|
function boundedInteger(value: unknown, minimum: number, maximum: number): number | null {
|
|
const parsed = typeof value === 'number' ? value : Number(value)
|
|
if (!Number.isFinite(parsed)) return null
|
|
return Math.min(maximum, Math.max(minimum, Math.round(parsed)))
|
|
}
|
|
|
|
export function parseSecondaryDisplayGeometry(value: string | null): SecondaryDisplayGeometry | null {
|
|
if (!value) return null
|
|
try {
|
|
const parsed = JSON.parse(value) as Partial<SecondaryDisplayGeometry>
|
|
const left = boundedInteger(parsed.left, -20_000, 20_000)
|
|
const top = boundedInteger(parsed.top, -20_000, 20_000)
|
|
const width = boundedInteger(parsed.width, 420, 3_840)
|
|
const height = boundedInteger(parsed.height, 520, 2_160)
|
|
return left === null || top === null || width === null || height === null
|
|
? null
|
|
: { left, top, width, height }
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
export function secondaryDisplayFeatures(geometry: SecondaryDisplayGeometry): string {
|
|
return [
|
|
'popup=yes',
|
|
`left=${geometry.left}`,
|
|
`top=${geometry.top}`,
|
|
`width=${geometry.width}`,
|
|
`height=${geometry.height}`,
|
|
'resizable=yes',
|
|
'scrollbars=yes',
|
|
].join(',')
|
|
}
|