import type { ChartType, PPTAudioElement, PPTChartElement, PPTImageElement, PPTLatexElement, PPTLineElement, PPTTableElement, PPTTextElement, PPTVideoElement, } from '@openmaic/dsl'; import type { LineCreateGeometry, TextCreateRect } from '../../react/types'; import type { EditorAsset } from '../host'; import type { LatexEditorResult } from '../latex/latex-editor'; import type { LineInsertPreset } from '../insert/LineInsertPicker'; export function createDefaultTextElement( id: string, rect: TextCreateRect = { left: 120, top: 120, width: 360, height: 72 }, ): PPTTextElement { return { id, type: 'text', ...rect, rotate: 0, content: '


', defaultFontName: '', defaultColor: '#333333', }; } export interface ImageDimensions { readonly width: number; readonly height: number; } export function fitImageSize(width: number, height: number): ImageDimensions { if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) { return { width: 360, height: 220 }; } const scale = Math.min(1, 600 / width, 400 / height); return { width: Math.round(width * scale), height: Math.round(height * scale) }; } export function createDefaultImageElement( id: string, src: string, dimensions?: ImageDimensions, ): PPTImageElement { const size = dimensions ? fitImageSize(dimensions.width, dimensions.height) : { width: 360, height: 220 }; return { id, type: 'image', left: 180, top: 140, width: size.width, height: size.height, rotate: 0, fixedRatio: true, src, }; } export function createDefaultTableElement( id: string, requestedRows: number, requestedColumns: number, ): PPTTableElement { const rows = Math.max(1, Math.floor(requestedRows)); const columns = Math.max(1, Math.floor(requestedColumns)); return { id, type: 'table', left: 120, top: 120, width: 360, height: Math.max(120, rows * 36), rotate: 0, colWidths: Array.from({ length: columns }, () => 1 / columns), cellMinHeight: 36, data: Array.from({ length: rows }, (_, rowIndex) => Array.from({ length: columns }, (_, columnIndex) => ({ id: `${id}-cell-${rowIndex}-${columnIndex}`, colspan: 1, rowspan: 1, text: '', })), ), outline: { width: 2, color: '#eeece1', style: 'solid' }, }; } export function createDefaultChartElement(id: string, chartType: ChartType): PPTChartElement { return { id, type: 'chart', left: 160, top: 140, width: 420, height: 260, rotate: 0, chartType, data: { labels: ['A', 'B', 'C', 'D'], legends: ['Series 1'], series: [[24, 36, 28, 42]], }, themeColors: ['#5b8def', '#8b5cf6', '#10b981', '#f59e0b'], textColor: '#333333', lineColor: '#d4d4d8', }; } export function createDefaultLatexElement(id: string, result: LatexEditorResult): PPTLatexElement { return { id, type: 'latex', left: 160, top: 160, width: result.width, height: result.height, rotate: 0, latex: result.latex, html: result.html, color: '#333333', align: 'center', fixedRatio: true, }; } export function createDefaultVideoElement(id: string, asset: EditorAsset): PPTVideoElement { return { id, type: 'video', left: 180, top: 140, width: 360, height: 203, rotate: 0, src: asset.src, autoplay: false, ...(asset.ext ? { ext: asset.ext } : {}), }; } export function createDefaultAudioElement(id: string, asset: EditorAsset): PPTAudioElement { return { id, type: 'audio', left: 180, top: 180, width: 48, height: 48, rotate: 0, fixedRatio: true, color: '#7c3aed', loop: false, autoplay: false, src: asset.src, ...(asset.ext ? { ext: asset.ext } : {}), }; } const DEFAULT_LINE_PRESET: LineInsertPreset = { path: 'M 0 0 L 20 20', style: 'solid', points: ['', ''], }; export function createDefaultLineElement( id: string, geometry: LineCreateGeometry, preset: LineInsertPreset = DEFAULT_LINE_PRESET, ): PPTLineElement { const [startX, startY] = geometry.start; const [endX, endY] = geometry.end; const left = Math.min(startX, endX); const top = Math.min(startY, endY); const start: [number, number] = [startX - left, startY - top]; const end: [number, number] = [endX - left, endY - top]; const midpointX = (start[0] + end[0]) / 2; const controls = preset.isCubic ? { cubic: [ [end[0], start[1]], [start[0], end[1]], ] as [[number, number], [number, number]], } : preset.isCurve ? { curve: [start[0], end[1]] as [number, number] } : preset.isBroken2 ? { broken2: [midpointX, start[1]] as [number, number] } : preset.isBroken ? { broken: [start[0], end[1]] as [number, number] } : {}; return { id, type: 'line', left, top, width: 2, start, end, style: preset.style, color: '#333333', points: preset.points, ...controls, }; }