diff --git a/components/settings/asr-settings.tsx b/components/settings/asr-settings.tsx
index 5666db0e..8c01ab48 100644
--- a/components/settings/asr-settings.tsx
+++ b/components/settings/asr-settings.tsx
@@ -89,6 +89,9 @@ export function ASRSettings({ selectedProviderId }: ASRSettingsProps) {
setIsRecording(true);
} else {
try {
+ if (!navigator.mediaDevices?.getUserMedia) {
+ throw new Error('mediaDevices API not available (requires HTTPS or localhost)');
+ }
const stream = await navigator.mediaDevices.getUserMedia({
audio: true,
});
diff --git a/components/slide-renderer/components/element/LatexElement/BaseLatexElement.tsx b/components/slide-renderer/components/element/LatexElement/BaseLatexElement.tsx
index a1a1c15b..2601e5ac 100644
--- a/components/slide-renderer/components/element/LatexElement/BaseLatexElement.tsx
+++ b/components/slide-renderer/components/element/LatexElement/BaseLatexElement.tsx
@@ -3,6 +3,15 @@
import { useRef, useState, useLayoutEffect } from 'react';
import type { PPTLatexElement } from '@/lib/types/slides';
+function getViewBoxDims(viewBox: [number, number] | string | undefined): [number, number] {
+ if (Array.isArray(viewBox)) return viewBox;
+ if (typeof viewBox === 'string') {
+ const parts = viewBox.trim().split(/\s+/).map(Number);
+ return parts.length >= 4 ? [parts[2], parts[3]] : parts.length >= 2 ? [parts[0], parts[1]] : [0, 0];
+ }
+ return [0, 0];
+}
+
export interface BaseLatexElementProps {
elementInfo: PPTLatexElement;
}
@@ -47,9 +56,12 @@ export function BaseLatexElement({ elementInfo }: BaseLatexElementProps) {
className="transform-origin-[0_0] overflow-visible"
>
{
+ const [vbW, vbH] = getViewBoxDims(elementInfo.viewBox);
+ const sx = vbW > 0 ? elementInfo.width / vbW : 1;
+ const sy = vbH > 0 ? elementInfo.height / vbH : 1;
+ return `scale(${sx}, ${sy}) translate(0,0) matrix(1,0,0,1,0,0)`;
+ })()}
>
diff --git a/components/slide-renderer/components/element/LatexElement/index.tsx b/components/slide-renderer/components/element/LatexElement/index.tsx
index 9709cda6..fe47c8f9 100644
--- a/components/slide-renderer/components/element/LatexElement/index.tsx
+++ b/components/slide-renderer/components/element/LatexElement/index.tsx
@@ -3,6 +3,15 @@
import { useRef, useState, useLayoutEffect } from 'react';
import type { PPTLatexElement } from '@/lib/types/slides';
+function getViewBoxDims(viewBox: [number, number] | string | undefined): [number, number] {
+ if (Array.isArray(viewBox)) return viewBox;
+ if (typeof viewBox === 'string') {
+ const parts = viewBox.trim().split(/\s+/).map(Number);
+ return parts.length >= 4 ? [parts[2], parts[3]] : parts.length >= 2 ? [parts[0], parts[1]] : [0, 0];
+ }
+ return [0, 0];
+}
+
export { BaseLatexElement } from './BaseLatexElement';
export interface LatexElementProps {
@@ -61,9 +70,12 @@ export function LatexElement({ elementInfo, selectElement }: LatexElementProps)
className="transform-origin-[0_0]"
>
{
+ const [vbW, vbH] = getViewBoxDims(elementInfo.viewBox);
+ const sx = vbW > 0 ? elementInfo.width / vbW : 1;
+ const sy = vbH > 0 ? elementInfo.height / vbH : 1;
+ return `scale(${sx}, ${sy}) translate(0,0) matrix(1,0,0,1,0,0)`;
+ })()}
>
diff --git a/components/slide-renderer/components/element/ShapeElement/BaseShapeElement.tsx b/components/slide-renderer/components/element/ShapeElement/BaseShapeElement.tsx
index 66cde759..4a11e514 100644
--- a/components/slide-renderer/components/element/ShapeElement/BaseShapeElement.tsx
+++ b/components/slide-renderer/components/element/ShapeElement/BaseShapeElement.tsx
@@ -8,6 +8,15 @@ import { useElementFill } from '../hooks/useElementFill';
import { GradientDefs } from './GradientDefs';
import { PatternDefs } from './PatternDefs';
+function getViewBoxDims(viewBox: [number, number] | string | undefined): [number, number] {
+ if (Array.isArray(viewBox)) return viewBox;
+ if (typeof viewBox === 'string') {
+ const parts = viewBox.trim().split(/\s+/).map(Number);
+ return parts.length >= 4 ? [parts[2], parts[3]] : parts.length >= 2 ? [parts[0], parts[1]] : [0, 0];
+ }
+ return [0, 0];
+}
+
export interface BaseShapeElementProps {
elementInfo: PPTShapeElement;
}
@@ -72,9 +81,12 @@ export function BaseShapeElement({ elementInfo }: BaseShapeElementProps) {
)}
{
+ const [vbW, vbH] = getViewBoxDims(elementInfo.viewBox);
+ const sx = vbW > 0 ? elementInfo.width / vbW : 1;
+ const sy = vbH > 0 ? elementInfo.height / vbH : 1;
+ return `scale(${sx}, ${sy}) translate(0,0) matrix(1,0,0,1,0,0)`;
+ })()}
>
= 4 ? [parts[2], parts[3]] : parts.length >= 2 ? [parts[0], parts[1]] : [0, 0];
+ }
+ return [0, 0];
+}
+
export { BaseShapeElement } from './BaseShapeElement';
export interface ShapeElementProps {
@@ -144,9 +153,12 @@ export function ShapeElement({ elementInfo, selectElement }: ShapeElementProps)
)}
{
+ const [vbW, vbH] = getViewBoxDims(elementInfo.viewBox);
+ const sx = vbW > 0 ? elementInfo.width / vbW : 1;
+ const sy = vbH > 0 ? elementInfo.height / vbH : 1;
+ return `scale(${sx}, ${sy}) translate(0,0) matrix(1,0,0,1,0,0)`;
+ })()}
>
{
+ const parts = String(el.viewBox).trim().split(/\s+/).map(Number);
+ return parts.length >= 4 ? [parts[2], parts[3]] : parts.length >= 2 ? [parts[0], parts[1]] : [0, 0];
+ })();
const scale = {
- x: el.width / el.viewBox[0],
- y: el.height / el.viewBox[1],
+ x: vb[0] > 0 ? el.width / vb[0] : 1,
+ y: vb[1] > 0 ? el.height / vb[1] : 1,
};
const points = formatPoints(toPoints(el.path), ratioPx2Inch, scale);
diff --git a/lib/generation/scene-generator.ts b/lib/generation/scene-generator.ts
index 1dc22937..cd65ad70 100644
--- a/lib/generation/scene-generator.ts
+++ b/lib/generation/scene-generator.ts
@@ -394,8 +394,8 @@ function fixElementDefaults(
if (el.type === 'shape') {
const shapeEl = el as Record;
- if (!shapeEl.viewBox) {
- shapeEl.viewBox = `0 0 ${el.width ?? 100} ${el.height ?? 100}`;
+ if (!shapeEl.viewBox || !Array.isArray(shapeEl.viewBox)) {
+ shapeEl.viewBox = [el.width ?? 100, el.height ?? 100];
}
if (!shapeEl.path) {
// Default to rectangle