diff --git a/package-lock.json b/package-lock.json index 36680ca..9028ef4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -57,7 +57,6 @@ "react": "^19.0.0", "react-day-picker": "^9.7.0", "react-dom": "^19.0.0", - "react-error-boundary": "^6.0.0", "react-hook-form": "^7.57.0", "react-konva": "^19.0.6", "react-resizable-panels": "^3.0.2", @@ -7209,18 +7208,6 @@ "react": "^19.1.0" } }, - "node_modules/react-error-boundary": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-6.0.0.tgz", - "integrity": "sha512-gdlJjD7NWr0IfkPlaREN2d9uUZUlksrfOx7SX62VRerwXbMY6ftGCIZua1VG1aXFNOimhISsTq+Owp725b9SiA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.12.5" - }, - "peerDependencies": { - "react": ">=16.13.1" - } - }, "node_modules/react-hook-form": { "version": "7.57.0", "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.57.0.tgz", diff --git a/package.json b/package.json index e344180..e12f6fe 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,6 @@ "react": "^19.0.0", "react-day-picker": "^9.7.0", "react-dom": "^19.0.0", - "react-error-boundary": "^6.0.0", "react-hook-form": "^7.57.0", "react-konva": "^19.0.6", "react-resizable-panels": "^3.0.2", diff --git a/resources/fonts/Montserrat/Montserrat-Italic-VariableFont_wght.ttf b/resources/fonts/Montserrat/Montserrat-Italic-VariableFont_wght.ttf deleted file mode 100644 index 9f89c9d..0000000 Binary files a/resources/fonts/Montserrat/Montserrat-Italic-VariableFont_wght.ttf and /dev/null differ diff --git a/resources/fonts/Montserrat/Montserrat-VariableFont_wght.ttf b/resources/fonts/Montserrat/Montserrat-VariableFont_wght.ttf deleted file mode 100644 index df7379c..0000000 Binary files a/resources/fonts/Montserrat/Montserrat-VariableFont_wght.ttf and /dev/null differ diff --git a/resources/fonts/Montserrat/OFL.txt b/resources/fonts/Montserrat/OFL.txt deleted file mode 100644 index 4515774..0000000 --- a/resources/fonts/Montserrat/OFL.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2024 The Montserrat.Git Project Authors (https://github.com/JulietaUla/Montserrat.git) - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -https://openfontlicense.org - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/resources/fonts/Montserrat/README.txt b/resources/fonts/Montserrat/README.txt deleted file mode 100644 index 526747d..0000000 --- a/resources/fonts/Montserrat/README.txt +++ /dev/null @@ -1,81 +0,0 @@ -Montserrat Variable Font -======================== - -This download contains Montserrat as both variable fonts and static fonts. - -Montserrat is a variable font with this axis: - wght - -This means all the styles are contained in these files: - Montserrat-VariableFont_wght.ttf - Montserrat-Italic-VariableFont_wght.ttf - -If your app fully supports variable fonts, you can now pick intermediate styles -that aren’t available as static fonts. Not all apps support variable fonts, and -in those cases you can use the static font files for Montserrat: - static/Montserrat-Thin.ttf - static/Montserrat-ExtraLight.ttf - static/Montserrat-Light.ttf - static/Montserrat-Regular.ttf - static/Montserrat-Medium.ttf - static/Montserrat-SemiBold.ttf - static/Montserrat-Bold.ttf - static/Montserrat-ExtraBold.ttf - static/Montserrat-Black.ttf - static/Montserrat-ThinItalic.ttf - static/Montserrat-ExtraLightItalic.ttf - static/Montserrat-LightItalic.ttf - static/Montserrat-Italic.ttf - static/Montserrat-MediumItalic.ttf - static/Montserrat-SemiBoldItalic.ttf - static/Montserrat-BoldItalic.ttf - static/Montserrat-ExtraBoldItalic.ttf - static/Montserrat-BlackItalic.ttf - -Get started ------------ - -1. Install the font files you want to use - -2. Use your app's font picker to view the font family and all the -available styles - -Learn more about variable fonts -------------------------------- - - https://developers.google.com/web/fundamentals/design-and-ux/typography/variable-fonts - https://variablefonts.typenetwork.com - https://medium.com/variable-fonts - -In desktop apps - - https://theblog.adobe.com/can-variable-fonts-illustrator-cc - https://helpx.adobe.com/nz/photoshop/using/fonts.html#variable_fonts - -Online - - https://developers.google.com/fonts/docs/getting_started - https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide - https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts - -Installing fonts - - MacOS: https://support.apple.com/en-us/HT201749 - Linux: https://www.google.com/search?q=how+to+install+a+font+on+gnu%2Blinux - Windows: https://support.microsoft.com/en-us/help/314960/how-to-install-or-remove-a-font-in-windows - -Android Apps - - https://developers.google.com/fonts/docs/android - https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts - -License -------- -Please read the full license text (OFL.txt) to understand the permissions, -restrictions and requirements for usage, redistribution, and modification. - -You can use them in your products & projects – print or digital, -commercial or otherwise. - -This isn't legal advice, please consider consulting a lawyer and see the full -license for all details. diff --git a/resources/fonts/Montserrat/static/Montserrat-Black.ttf b/resources/fonts/Montserrat/static/Montserrat-Black.ttf deleted file mode 100644 index 2d31930..0000000 Binary files a/resources/fonts/Montserrat/static/Montserrat-Black.ttf and /dev/null differ diff --git a/resources/fonts/Montserrat/static/Montserrat-BlackItalic.ttf b/resources/fonts/Montserrat/static/Montserrat-BlackItalic.ttf deleted file mode 100644 index 40c6e1e..0000000 Binary files a/resources/fonts/Montserrat/static/Montserrat-BlackItalic.ttf and /dev/null differ diff --git a/resources/fonts/Montserrat/static/Montserrat-Bold.ttf b/resources/fonts/Montserrat/static/Montserrat-Bold.ttf deleted file mode 100644 index 02ff6ff..0000000 Binary files a/resources/fonts/Montserrat/static/Montserrat-Bold.ttf and /dev/null differ diff --git a/resources/fonts/Montserrat/static/Montserrat-BoldItalic.ttf b/resources/fonts/Montserrat/static/Montserrat-BoldItalic.ttf deleted file mode 100644 index 998ed88..0000000 Binary files a/resources/fonts/Montserrat/static/Montserrat-BoldItalic.ttf and /dev/null differ diff --git a/resources/fonts/Montserrat/static/Montserrat-ExtraBold.ttf b/resources/fonts/Montserrat/static/Montserrat-ExtraBold.ttf deleted file mode 100644 index 5922551..0000000 Binary files a/resources/fonts/Montserrat/static/Montserrat-ExtraBold.ttf and /dev/null differ diff --git a/resources/fonts/Montserrat/static/Montserrat-ExtraBoldItalic.ttf b/resources/fonts/Montserrat/static/Montserrat-ExtraBoldItalic.ttf deleted file mode 100644 index 7415509..0000000 Binary files a/resources/fonts/Montserrat/static/Montserrat-ExtraBoldItalic.ttf and /dev/null differ diff --git a/resources/fonts/Montserrat/static/Montserrat-ExtraLight.ttf b/resources/fonts/Montserrat/static/Montserrat-ExtraLight.ttf deleted file mode 100644 index 491c6ec..0000000 Binary files a/resources/fonts/Montserrat/static/Montserrat-ExtraLight.ttf and /dev/null differ diff --git a/resources/fonts/Montserrat/static/Montserrat-ExtraLightItalic.ttf b/resources/fonts/Montserrat/static/Montserrat-ExtraLightItalic.ttf deleted file mode 100644 index 23dd23f..0000000 Binary files a/resources/fonts/Montserrat/static/Montserrat-ExtraLightItalic.ttf and /dev/null differ diff --git a/resources/fonts/Montserrat/static/Montserrat-Italic.ttf b/resources/fonts/Montserrat/static/Montserrat-Italic.ttf deleted file mode 100644 index 84bc0f4..0000000 Binary files a/resources/fonts/Montserrat/static/Montserrat-Italic.ttf and /dev/null differ diff --git a/resources/fonts/Montserrat/static/Montserrat-Light.ttf b/resources/fonts/Montserrat/static/Montserrat-Light.ttf deleted file mode 100644 index 9d89492..0000000 Binary files a/resources/fonts/Montserrat/static/Montserrat-Light.ttf and /dev/null differ diff --git a/resources/fonts/Montserrat/static/Montserrat-LightItalic.ttf b/resources/fonts/Montserrat/static/Montserrat-LightItalic.ttf deleted file mode 100644 index bf854d4..0000000 Binary files a/resources/fonts/Montserrat/static/Montserrat-LightItalic.ttf and /dev/null differ diff --git a/resources/fonts/Montserrat/static/Montserrat-Medium.ttf b/resources/fonts/Montserrat/static/Montserrat-Medium.ttf deleted file mode 100644 index dfbcfe4..0000000 Binary files a/resources/fonts/Montserrat/static/Montserrat-Medium.ttf and /dev/null differ diff --git a/resources/fonts/Montserrat/static/Montserrat-MediumItalic.ttf b/resources/fonts/Montserrat/static/Montserrat-MediumItalic.ttf deleted file mode 100644 index 1e67477..0000000 Binary files a/resources/fonts/Montserrat/static/Montserrat-MediumItalic.ttf and /dev/null differ diff --git a/resources/fonts/Montserrat/static/Montserrat-Regular.ttf b/resources/fonts/Montserrat/static/Montserrat-Regular.ttf deleted file mode 100644 index 48ba65e..0000000 Binary files a/resources/fonts/Montserrat/static/Montserrat-Regular.ttf and /dev/null differ diff --git a/resources/fonts/Montserrat/static/Montserrat-SemiBold.ttf b/resources/fonts/Montserrat/static/Montserrat-SemiBold.ttf deleted file mode 100644 index 8dbcdb3..0000000 Binary files a/resources/fonts/Montserrat/static/Montserrat-SemiBold.ttf and /dev/null differ diff --git a/resources/fonts/Montserrat/static/Montserrat-SemiBoldItalic.ttf b/resources/fonts/Montserrat/static/Montserrat-SemiBoldItalic.ttf deleted file mode 100644 index 8604419..0000000 Binary files a/resources/fonts/Montserrat/static/Montserrat-SemiBoldItalic.ttf and /dev/null differ diff --git a/resources/fonts/Montserrat/static/Montserrat-Thin.ttf b/resources/fonts/Montserrat/static/Montserrat-Thin.ttf deleted file mode 100644 index 2a85a52..0000000 Binary files a/resources/fonts/Montserrat/static/Montserrat-Thin.ttf and /dev/null differ diff --git a/resources/fonts/Montserrat/static/Montserrat-ThinItalic.ttf b/resources/fonts/Montserrat/static/Montserrat-ThinItalic.ttf deleted file mode 100644 index 5dc7160..0000000 Binary files a/resources/fonts/Montserrat/static/Montserrat-ThinItalic.ttf and /dev/null differ diff --git a/resources/js/app.tsx b/resources/js/app.tsx index 912dda2..f3e5e5c 100644 --- a/resources/js/app.tsx +++ b/resources/js/app.tsx @@ -3,8 +3,6 @@ import '../css/app.css'; import { createInertiaApp } from '@inertiajs/react'; import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers'; import { createRoot } from 'react-dom/client'; -import { ErrorBoundary } from 'react-error-boundary'; -import DetailedErrorFallback from './components/custom/detailed-error-feedback'; // Import your component import { initializeTheme } from './hooks/use-appearance'; import { AxiosProvider } from './plugins/AxiosContext'; import { MittProvider } from './plugins/MittContext'; @@ -18,26 +16,13 @@ createInertiaApp({ const root = createRoot(el); const app = ( - { - // Log to console for debugging - console.error('Error caught by boundary:', error, errorInfo); - - // You could also send to an error reporting service here - // e.g., Sentry, LogRocket, etc. - }} - onReset={() => { - // Optional: Clear any error state in your app - console.log('Error boundary reset'); - }} - > + <> - + ); root.render(app); @@ -47,4 +32,5 @@ createInertiaApp({ }, }); +// This will set light / dark mode on load... initializeTheme(); diff --git a/resources/js/components/custom/detailed-error-feedback.jsx b/resources/js/components/custom/detailed-error-feedback.jsx deleted file mode 100644 index 14440c6..0000000 --- a/resources/js/components/custom/detailed-error-feedback.jsx +++ /dev/null @@ -1,71 +0,0 @@ -import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; -import { AlertCircle } from 'lucide-react'; - -function DetailedErrorFallback({ error, resetErrorBoundary }) { - return ( -
- - - Runtime Error - -
- {/* Error Message */} -
-

Error Message:

-

{error.message}

-
- - {/* Component Stack */} -
-

Component Stack:

-
-                                {error.componentStack || error.stack}
-                            
-
- - {/* Additional Error Info */} - {error.fileName && ( -
-

File:

-

{error.fileName}

-
- )} - - {error.lineNumber && ( -
-

Line:

-

{error.lineNumber}

-
- )} - - {/* Error Properties */} -
-

Additional Details:

-
-                                {JSON.stringify(error, Object.getOwnPropertyNames(error), 2)}
-                            
-
- - {/* Actions */} -
- - -
-
-
-
-
- ); -} - -export default DetailedErrorFallback; diff --git a/resources/js/modules/editor/partials/canvas/sample-timeline-data.jsx b/resources/js/modules/editor/partials/canvas/sample-timeline-data.jsx index 098da47..5eeec54 100644 --- a/resources/js/modules/editor/partials/canvas/sample-timeline-data.jsx +++ b/resources/js/modules/editor/partials/canvas/sample-timeline-data.jsx @@ -57,12 +57,10 @@ const sampleTimelineElements = [ startTime: 0, layer: 2, duration: 4, - x: 90, - y: 180, - fontSize: 40, - fontFamily: 'Montserrat', - fontWeight: 'bold', - fontStyle: 'normal', + x: 50, + y: 600, + fontSize: 24, + fontWeight: 'bold', // ADD THIS LINE fill: 'white', stroke: 'black', strokeWidth: 1, @@ -78,9 +76,7 @@ const sampleTimelineElements = [ x: 50, y: 650, fontSize: 20, - fontFamily: 'Montserrat', - fontWeight: 'bold', - fontStyle: 'normal', + fontWeight: 'bold', // ADD THIS LINE fill: 'yellow', stroke: 'red', strokeWidth: 2, diff --git a/resources/js/modules/editor/partials/canvas/video-editor.jsx b/resources/js/modules/editor/partials/canvas/video-editor.jsx index 435a562..2fa8754 100644 --- a/resources/js/modules/editor/partials/canvas/video-editor.jsx +++ b/resources/js/modules/editor/partials/canvas/video-editor.jsx @@ -70,7 +70,7 @@ const VideoEditor = ({ width, height }) => { }); }; - // Handle element transformations (position, scale, rotation) + // NEW: Handle element transformations (position, scale, rotation) const handleElementUpdate = useCallback( (elementId, updates) => { setTimelineElements((prev) => @@ -553,7 +553,7 @@ const VideoEditor = ({ width, height }) => { handleSeek={handleSeek} copyFFmpegCommand={copyFFmpegCommand} exportVideo={exportVideo} - onElementUpdate={handleElementUpdate} + onElementUpdate={handleElementUpdate} // NEW: Pass the update handler layerRef={layerRef} /> diff --git a/resources/js/modules/editor/partials/canvas/video-export.jsx b/resources/js/modules/editor/partials/canvas/video-export.jsx index f143071..e6b9ae9 100644 --- a/resources/js/modules/editor/partials/canvas/video-export.jsx +++ b/resources/js/modules/editor/partials/canvas/video-export.jsx @@ -98,29 +98,16 @@ const useVideoExport = ({ timelineElements, dimensions, totalDuration }) => { showConsoleLogs && console.log('🎡 Audio args:', audioArgs); - // Process text elements with font family support + // Process text elements with centering texts.forEach((t, i) => { const escapedText = t.text.replace(/'/g, is_string ? "\\'" : "'").replace(/:/g, '\\:'); - // Determine font file based on weight and style - let fontFile = 'Montserrat-Regular.ttf'; // default - const isBold = t.fontWeight === 'bold' || t.fontWeight === 700; - const isItalic = t.fontStyle === 'italic'; - - if (isBold && isItalic) { - fontFile = 'Montserrat-BoldItalic.ttf'; - } else if (isBold) { - fontFile = 'Montserrat-Bold.ttf'; - } else if (isItalic) { - fontFile = 'Montserrat-Italic.ttf'; - } - // Center the text: x position is the center point, y is adjusted for baseline const centerX = Math.round(t.x); const centerY = Math.round(t.y + t.fontSize * 0.3); // Adjust for text baseline filters.push( - `[${videoLayer}]drawtext=fontfile=/${fontFile}:text='${escapedText}':x=${centerX}:y=${centerY}:fontsize=${t.fontSize}:fontcolor=${t.fill}:borderw=${t.strokeWidth}:bordercolor=${ + `[${videoLayer}]drawtext=fontfile=/arial.ttf:text='${escapedText}':x=${centerX}:y=${centerY}:fontsize=${t.fontSize}:fontcolor=${t.fill}:borderw=${t.strokeWidth}:bordercolor=${ t.stroke }:text_align=center:enable='between(t,${t.startTime},${t.startTime + t.duration})'[t${i}]`, ); @@ -224,25 +211,9 @@ const useVideoExport = ({ timelineElements, dimensions, totalDuration }) => { showConsoleLogs && console.log('FFmpeg loaded!'); setExportProgress(20); - setExportStatus('Loading fonts...'); - // Load Montserrat font variants - await ffmpeg.writeFile( - 'Montserrat-Regular.ttf', - await fetchFile('https://fonts.gstatic.com/s/montserrat/v26/JTUSjIg1_i6t8kCHKm459Wlhyw.ttf'), - ); - await ffmpeg.writeFile( - 'Montserrat-Bold.ttf', - await fetchFile('https://fonts.gstatic.com/s/montserrat/v26/JTUSjIg1_i6t8kCHKm459W1hyw.ttf'), - ); - await ffmpeg.writeFile( - 'Montserrat-Italic.ttf', - await fetchFile('https://fonts.gstatic.com/s/montserrat/v26/JTUSjIg1_i6t8kCHKm459WxhywMDPA.ttf'), - ); - await ffmpeg.writeFile( - 'Montserrat-BoldItalic.ttf', - await fetchFile('https://fonts.gstatic.com/s/montserrat/v26/JTUSjIg1_i6t8kCHKm459W1hywMDPA.ttf'), - ); - showConsoleLogs && console.log('Fonts loaded!'); + setExportStatus('Loading font...'); + await ffmpeg.writeFile('arial.ttf', await fetchFile('https://raw.githubusercontent.com/ffmpegwasm/testdata/master/arial.ttf')); + showConsoleLogs && console.log('Font loaded!'); setExportProgress(30); setExportStatus('Downloading media...'); diff --git a/resources/js/modules/editor/partials/canvas/video-preview.jsx b/resources/js/modules/editor/partials/canvas/video-preview.jsx index d4efa27..56f1f6a 100644 --- a/resources/js/modules/editor/partials/canvas/video-preview.jsx +++ b/resources/js/modules/editor/partials/canvas/video-preview.jsx @@ -58,10 +58,6 @@ const VideoPreview = ({ // Snap settings const POSITION_SNAP_THRESHOLD = 10; // Pixels within which to snap to center - // Font size constraints (same as in text-sidebar.jsx) - const MIN_FONT_SIZE = 8; - const MAX_FONT_SIZE = 120; - // Function to determine which image source to use for videos const getImageSource = (element) => { const isVideoActive = videoStates[element.id] && isPlaying; @@ -280,7 +276,7 @@ const VideoPreview = ({ [onElementUpdate, timelineElements], ); - // Handle transform events (scale, rotate) with fontSize conversion for text + // Handle transform events (scale, rotate) with snapping - USES NATIVE KONVA ROTATION SNAPPING const handleTransform = useCallback( (elementId) => { const node = elementRefs.current[elementId]; @@ -295,29 +291,11 @@ const VideoPreview = ({ const scaleY = node.scaleY(); let newWidth, newHeight; - let updates = {}; if (element.type === 'text') { - // OPTION A: Convert scale change to fontSize change - const scale = Math.max(Math.abs(scaleX), Math.abs(scaleY)); - const newFontSize = Math.round(element.fontSize * scale); - - // Clamp fontSize to valid range - const clampedFontSize = Math.max(MIN_FONT_SIZE, Math.min(MAX_FONT_SIZE, newFontSize)); - - // Reset scale to 1 since we're converting to fontSize - node.scaleX(1); - node.scaleY(1); - - // βœ… FIX: Always get current width/height for text elements too - newWidth = node.width(); - newHeight = node.height(); - - updates.fontSize = clampedFontSize; - updates.width = newWidth; // βœ… Always include width - updates.height = newHeight; // βœ… Always include height - - console.log(`Text transform: scale=${scale.toFixed(2)}, oldFontSize=${element.fontSize}, newFontSize=${clampedFontSize}`); + // For text, allow free scaling + newWidth = node.width() * scaleX; + newHeight = node.height() * scaleY; } else { // For images/videos, maintain aspect ratio by using the larger scale const scale = Math.max(Math.abs(scaleX), Math.abs(scaleY)); @@ -333,9 +311,6 @@ const VideoPreview = ({ // Update offset for center rotation node.offsetX(newWidth / 2); node.offsetY(newHeight / 2); - - updates.width = newWidth; - updates.height = newHeight; } // Calculate position for snapping @@ -345,8 +320,8 @@ const VideoPreview = ({ // Convert center position to top-left for snapping const centerX = node.x(); const centerY = node.y(); - topLeftX = centerX - newWidth / 2; // βœ… newWidth is now always defined - topLeftY = centerY - newHeight / 2; // βœ… newHeight is now always defined + topLeftX = centerX - newWidth / 2; + topLeftY = centerY - newHeight / 2; } else { // Use position directly for text topLeftX = node.x(); @@ -384,23 +359,18 @@ const VideoPreview = ({ }); } - // Always update position and rotation - updates.x = topLeftX; - updates.y = topLeftY; - updates.rotation = rotation; + // Update state with the final calculated values + const finalTransform = { + x: topLeftX, + y: topLeftY, + width: newWidth, + height: newHeight, + rotation: rotation, + }; - // Update state with the calculated values - onElementUpdate(elementId, updates); - - // If this is a text element and fontSize changed, emit update for sidebar (without opening it) - if (element.type === 'text' && updates.fontSize && updates.fontSize !== element.fontSize) { - // Small delay to ensure state is updated first - setTimeout(() => { - emitter.emit('text-element-updated', { ...element, ...updates }); - }, 50); - } + onElementUpdate(elementId, finalTransform); }, - [onElementUpdate, dimensions.width, dimensions.height, timelineElements, emitter], + [onElementUpdate, dimensions.width, dimensions.height, timelineElements], ); // Update transformer when selection changes @@ -463,10 +433,6 @@ const VideoPreview = ({ /> ); } else if (element.type === 'text') { - // Build font style string - const fontWeight = element.fontWeight === 'bold' || element.fontWeight === 700 ? 'bold' : 'normal'; - const fontStyle = element.fontStyle === 'italic' ? 'italic' : 'normal'; - return ( { - const emitter = useMitt(); - - // Selection state - const [selectedElementId, setSelectedElementId] = useState(null); - const transformerRef = useRef(null); - const stageRef = useRef(null); - - // Refs for each element to connect with transformer - const elementRefs = useRef({}); - - // Guide lines state - const [guideLines, setGuideLines] = useState({ - vertical: null, - horizontal: null, - showVertical: false, - showHorizontal: false, - }); - - // Snap settings - const POSITION_SNAP_THRESHOLD = 10; // Pixels within which to snap to center - - // Font size constraints (same as in text-sidebar.jsx) - const MIN_FONT_SIZE = 8; - const MAX_FONT_SIZE = 120; - - // Function to determine which image source to use for videos - const getImageSource = (element) => { - const isVideoActive = videoStates[element.id] && isPlaying; - - if (isVideoActive && element.videoElement && element.isVideoReady) { - return element.videoElement; - } else if (element.posterImage && element.isVideoPoster) { - return element.posterImage; - } - - return null; - }; - - // Check if element uses center-offset positioning - const usesCenterPositioning = (elementType) => { - return elementType === 'video' || elementType === 'image'; - }; - - // Check if position should snap to center and calculate guide lines - const calculateSnapAndGuides = (elementId, newX, newY, width, height) => { - const centerX = dimensions.width / 2; - const centerY = dimensions.height / 2; - - // Calculate element center - const elementCenterX = newX + width / 2; - const elementCenterY = newY + height / 2; - - let snapX = newX; - let snapY = newY; - let showVertical = false; - let showHorizontal = false; - let verticalLine = null; - let horizontalLine = null; - - // Check vertical center snap - if (Math.abs(elementCenterX - centerX) < POSITION_SNAP_THRESHOLD) { - snapX = centerX - width / 2; - showVertical = true; - verticalLine = centerX; - } - - // Check horizontal center snap - if (Math.abs(elementCenterY - centerY) < POSITION_SNAP_THRESHOLD) { - snapY = centerY - height / 2; - showHorizontal = true; - horizontalLine = centerY; - } - - return { - x: snapX, - y: snapY, - guideLines: { - vertical: verticalLine, - horizontal: horizontalLine, - showVertical, - showHorizontal, - }, - }; - }; - - // Handle element selection - const handleElementSelect = useCallback( - (elementId) => { - setSelectedElementId(elementId); - - // Find the selected element - const element = timelineElements.find((el) => el.id === elementId); - - // If it's a text element, emit text-element-selected event - if (element && element.type === 'text') { - emitter.emit('text-element-selected', element); - } - - // Clear guide lines when selecting - setGuideLines({ - vertical: null, - horizontal: null, - showVertical: false, - showHorizontal: false, - }); - }, - [emitter, timelineElements], - ); - - // Handle clicking on empty space to deselect - const handleStageClick = useCallback((e) => { - // If clicking on stage (not on an element), deselect - if (e.target === e.target.getStage()) { - setSelectedElementId(null); - setGuideLines({ - vertical: null, - horizontal: null, - showVertical: false, - showHorizontal: false, - }); - } - }, []); - - // Handle drag events with snapping - const handleDragMove = useCallback( - (elementId, e) => { - const node = e.target; - const element = timelineElements.find((el) => el.id === elementId); - if (!element) return; - - const width = node.width() * node.scaleX(); - const height = node.height() * node.scaleY(); - - let topLeftX, topLeftY; - - if (usesCenterPositioning(element.type)) { - // For center-positioned elements (video/image), convert center to top-left - const elementCenterX = node.x(); - const elementCenterY = node.y(); - topLeftX = elementCenterX - width / 2; - topLeftY = elementCenterY - height / 2; - } else { - // For top-left positioned elements (text) - topLeftX = node.x(); - topLeftY = node.y(); - } - - const snapResult = calculateSnapAndGuides(elementId, topLeftX, topLeftY, width, height); - - // Update guide lines - setGuideLines(snapResult.guideLines); - - // Update state during drag - if (onElementUpdate) { - onElementUpdate(elementId, { - x: snapResult.x, - y: snapResult.y, - }); - } - }, - [onElementUpdate, dimensions.width, dimensions.height, timelineElements], - ); - - // Create drag bound function for real-time snapping - const createDragBoundFunc = useCallback( - (elementId) => { - return (pos) => { - const element = timelineElements.find((el) => el.id === elementId); - if (!element) return pos; - - const node = elementRefs.current[elementId]; - if (!node) return pos; - - const width = node.width() * node.scaleX(); - const height = node.height() * node.scaleY(); - - let topLeftX, topLeftY; - - if (usesCenterPositioning(element.type)) { - // Convert center position to top-left for snapping calculations - topLeftX = pos.x - width / 2; - topLeftY = pos.y - height / 2; - } else { - topLeftX = pos.x; - topLeftY = pos.y; - } - - const snapResult = calculateSnapAndGuides(elementId, topLeftX, topLeftY, width, height); - - if (usesCenterPositioning(element.type)) { - // Convert back to center position - return { - x: snapResult.x + width / 2, - y: snapResult.y + height / 2, - }; - } else { - return { - x: snapResult.x, - y: snapResult.y, - }; - } - }; - }, - [timelineElements, dimensions.width, dimensions.height], - ); - - const handleDragEnd = useCallback( - (elementId, e) => { - const node = e.target; - const element = timelineElements.find((el) => el.id === elementId); - if (!element) return; - - // Clear guide lines when drag ends - setGuideLines({ - vertical: null, - horizontal: null, - showVertical: false, - showHorizontal: false, - }); - - // Final position update - const width = node.width() * node.scaleX(); - const height = node.height() * node.scaleY(); - - let finalX, finalY; - if (usesCenterPositioning(element.type)) { - finalX = node.x() - width / 2; - finalY = node.y() - height / 2; - } else { - finalX = node.x(); - finalY = node.y(); - } - - if (onElementUpdate) { - onElementUpdate(elementId, { - x: finalX, - y: finalY, - }); - } - }, - [onElementUpdate, timelineElements], - ); - - // Handle transform events (scale, rotate) with fontSize conversion for text - const handleTransform = useCallback( - (elementId) => { - const node = elementRefs.current[elementId]; - const element = timelineElements.find((el) => el.id === elementId); - if (!node || !onElementUpdate || !element) return; - - // Get rotation - Konva handles snapping automatically with rotationSnaps - const rotation = node.rotation(); - - // Get the scale values from Konva - const scaleX = node.scaleX(); - const scaleY = node.scaleY(); - - let newWidth, - newHeight, - updates = {}; - - if (element.type === 'text') { - // OPTION A: Convert scale change to fontSize change - const scale = Math.max(Math.abs(scaleX), Math.abs(scaleY)); - const newFontSize = Math.round(element.fontSize * scale); - - // Clamp fontSize to valid range - const clampedFontSize = Math.max(MIN_FONT_SIZE, Math.min(MAX_FONT_SIZE, newFontSize)); - - // Reset scale to 1 since we're converting to fontSize - node.scaleX(1); - node.scaleY(1); - - // The width/height will be automatically calculated by Konva based on fontSize - // For text elements, we let Konva handle the natural dimensions - updates.fontSize = clampedFontSize; - - console.log(`Text transform: scale=${scale.toFixed(2)}, oldFontSize=${element.fontSize}, newFontSize=${clampedFontSize}`); - } else { - // For images/videos, maintain aspect ratio by using the larger scale - const scale = Math.max(Math.abs(scaleX), Math.abs(scaleY)); - newWidth = node.width() * scale; - newHeight = node.height() * scale; - - // Reset scale to 1 and update dimensions to maintain aspect ratio - node.scaleX(1); - node.scaleY(1); - node.width(newWidth); - node.height(newHeight); - - // Update offset for center rotation - node.offsetX(newWidth / 2); - node.offsetY(newHeight / 2); - - updates.width = newWidth; - updates.height = newHeight; - } - - // Calculate position for snapping - let topLeftX, topLeftY; - - if (usesCenterPositioning(element.type)) { - // Convert center position to top-left for snapping - const centerX = node.x(); - const centerY = node.y(); - const currentWidth = element.type === 'text' ? node.width() : newWidth; - const currentHeight = element.type === 'text' ? node.height() : newHeight; - topLeftX = centerX - currentWidth / 2; - topLeftY = centerY - currentHeight / 2; - } else { - // Use position directly for text - topLeftX = node.x(); - topLeftY = node.y(); - } - - // Check for position snapping during transform (but be less aggressive during rotation) - const isRotating = Math.abs(rotation % 90) > 5; // Not close to perpendicular - if (!isRotating) { - const currentWidth = element.type === 'text' ? node.width() : newWidth; - const currentHeight = element.type === 'text' ? node.height() : newHeight; - const snapResult = calculateSnapAndGuides(elementId, topLeftX, topLeftY, currentWidth, currentHeight); - - if (Math.abs(snapResult.x - topLeftX) > 5 || Math.abs(snapResult.y - topLeftY) > 5) { - if (usesCenterPositioning(element.type)) { - // Convert back to center position - const newCenterX = snapResult.x + currentWidth / 2; - const newCenterY = snapResult.y + currentHeight / 2; - node.x(newCenterX); - node.y(newCenterY); - } else { - // Apply directly for text - node.x(snapResult.x); - node.y(snapResult.y); - } - setGuideLines(snapResult.guideLines); - topLeftX = snapResult.x; - topLeftY = snapResult.y; - } - } else { - // Clear guide lines during rotation - setGuideLines({ - vertical: null, - horizontal: null, - showVertical: false, - showHorizontal: false, - }); - } - - // Always update position and rotation - updates.x = topLeftX; - updates.y = topLeftY; - updates.rotation = rotation; - - // Update state with the calculated values - onElementUpdate(elementId, updates); - - // If this is a text element and fontSize changed, emit update for sidebar - if (element.type === 'text' && updates.fontSize && updates.fontSize !== element.fontSize) { - // Small delay to ensure state is updated first - setTimeout(() => { - emitter.emit('text-element-selected', { ...element, ...updates }); - }, 50); - } - }, - [onElementUpdate, dimensions.width, dimensions.height, timelineElements, emitter], - ); - - // Update transformer when selection changes - useEffect(() => { - if (transformerRef.current) { - const selectedNode = selectedElementId ? elementRefs.current[selectedElementId] : null; - - if (selectedNode) { - transformerRef.current.nodes([selectedNode]); - transformerRef.current.getLayer().batchDraw(); - } else { - transformerRef.current.nodes([]); - } - } - }, [selectedElementId, activeElements]); +import { Button } from '@/components/ui/button'; +import { Checkbox } from '@/components/ui/checkbox'; +import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog'; +import { Sheet, SheetContent, SheetHeader, SheetTitle } from '@/components/ui/sheet'; +import useLocalSettingsStore from '@/stores/localSettingsStore'; +import { SettingsIcon } from 'lucide-react'; + +export default function EditNavSidebar({ isOpen, onClose }) { + const { getSetting, setSetting } = useLocalSettingsStore(); return ( -
- - - {activeElements.map((element) => { - const isSelected = selectedElementId === element.id; + !open && onClose()}> + + + +
MEMEAIGEN
+
+
- if (element.type === 'video') { - const imageSource = getImageSource(element); +
+ + + + + + + Settings + Change your settings here. + - if (!imageSource) { - return null; - } - - return ( - { - if (node) { - elementRefs.current[element.id] = node; - } - }} - image={imageSource} - // Use center position for x,y when offset is set - x={element.x + element.width / 2} - y={element.y + element.height / 2} - width={element.width} - height={element.height} - // Set offset to center for proper rotation - offsetX={element.width / 2} - offsetY={element.height / 2} - rotation={element.rotation || 0} - draggable - dragBoundFunc={createDragBoundFunc(element.id)} - onClick={() => handleElementSelect(element.id)} - onTap={() => handleElementSelect(element.id)} - onDragMove={(e) => handleDragMove(element.id, e)} - onDragEnd={(e) => handleDragEnd(element.id, e)} - onTransform={() => handleTransform(element.id)} - // Visual feedback for selection - stroke={isSelected ? '#0066ff' : undefined} - strokeWidth={isSelected ? 2 : 0} - strokeScaleEnabled={false} +
+ setSetting('genAlphaSlang', !getSetting('genAlphaSlang'))} /> - ); - } else if (element.type === 'text') { - // Build font style string - const fontWeight = element.fontWeight === 'bold' || element.fontWeight === 700 ? 'bold' : 'normal'; - const fontStyle = element.fontStyle === 'italic' ? 'italic' : 'normal'; + +
- return ( - { - if (node) { - elementRefs.current[element.id] = node; - } - }} - text={element.text} - x={element.x} - y={element.y} - fontSize={element.fontSize} - fontStyle={`${fontStyle} ${fontWeight}`} - fontFamily={element.fontFamily || 'Montserrat'} - fill={element.fill} - stroke={element.stroke} - strokeWidth={element.strokeWidth} - rotation={element.rotation || 0} - // Center the text horizontally - align="center" - // Let text have natural width and height for multiline support - wrap="word" - draggable - dragBoundFunc={createDragBoundFunc(element.id)} - onClick={() => handleElementSelect(element.id)} - onTap={() => handleElementSelect(element.id)} - onDragMove={(e) => handleDragMove(element.id, e)} - onDragEnd={(e) => handleDragEnd(element.id, e)} - onTransform={() => handleTransform(element.id)} - // Visual feedback for selection - shadowColor={isSelected ? '#0066ff' : undefined} - shadowBlur={isSelected ? 4 : 0} - shadowOpacity={isSelected ? 0.3 : 0} - /> - ); - } else if (element.type === 'image' && element.imageElement && element.isImageReady) { - return ( - { - if (node) { - elementRefs.current[element.id] = node; - } - }} - image={element.imageElement} - // Use center position for x,y when offset is set - x={element.x + element.width / 2} - y={element.y + element.height / 2} - width={element.width} - height={element.height} - // Set offset to center for proper rotation - offsetX={element.width / 2} - offsetY={element.height / 2} - rotation={element.rotation || 0} - draggable - dragBoundFunc={createDragBoundFunc(element.id)} - onClick={() => handleElementSelect(element.id)} - onTap={() => handleElementSelect(element.id)} - onDragMove={(e) => handleDragMove(element.id, e)} - onDragEnd={(e) => handleDragEnd(element.id, e)} - onTransform={() => handleTransform(element.id)} - // Visual feedback for selection - stroke={isSelected ? '#0066ff' : undefined} - strokeWidth={isSelected ? 2 : 0} - strokeScaleEnabled={false} - /> - ); - } - return null; - })} - - {/* Guide Lines Layer */} - {guideLines.showVertical && ( - - )} - {guideLines.showHorizontal && ( - - )} - - {/* Transformer for selected element */} - { - // Limit resize to prevent elements from becoming too small - if (newBox.width < 20 || newBox.height < 20) { - return oldBox; - } - return newBox; - }} - // Transformer styling - Figma-like appearance - borderStroke="#0066ff" - borderStrokeWidth={2} - anchorStroke="#0066ff" - anchorFill="white" - anchorSize={14} - anchorCornerRadius={2} - // Enable only corner anchors for aspect ratio - enabledAnchors={['top-left', 'top-right', 'bottom-right', 'bottom-left']} - // Rotation handle - rotateAnchorOffset={30} - // Built-in Konva rotation snapping - rotationSnaps={[0, 90, 180, 270]} - rotationSnapTolerance={8} - // Clear guide lines when transform ends - onTransformEnd={() => { - setGuideLines({ - vertical: null, - horizontal: null, - showVertical: false, - showHorizontal: false, - }); - }} - // Style the rotation anchor to be circular - anchorStyleFunc={(anchor) => { - if (anchor.hasName('.rotater')) { - // Make it circular by setting corner radius to half the width - anchor.cornerRadius(anchor.width() / 2); - anchor.fill('#0066ff'); - anchor.stroke('white'); - anchor.strokeWidth(1); - } - }} - /> - - -
+ + + +
+ + ); -}; - -export default VideoPreview; +} diff --git a/resources/js/modules/editor/partials/text-sidebar.jsx b/resources/js/modules/editor/partials/text-sidebar.jsx index 09980a8..443b55c 100644 --- a/resources/js/modules/editor/partials/text-sidebar.jsx +++ b/resources/js/modules/editor/partials/text-sidebar.jsx @@ -1,72 +1,32 @@ import { Button } from '@/components/ui/button'; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Sheet, SheetContent, SheetHeader, SheetTitle } from '@/components/ui/sheet'; import { Textarea } from '@/components/ui/textarea'; import { useMitt } from '@/plugins/MittContext'; import useVideoEditorStore from '@/stores/VideoEditorStore'; -import { Bold, Italic, Minus, Plus, Type } from 'lucide-react'; +import { Bold, Minus, Plus, Type } from 'lucide-react'; import { useEffect, useState } from 'react'; -// Font configuration -const DEFAULT_FONT_FAMILY = 'Montserrat'; -const AVAILABLE_FONTS = [{ value: 'Montserrat', label: 'Montserrat' }]; - export default function TextSidebar({ isOpen, onClose }) { const { selectedTextElement } = useVideoEditorStore(); const emitter = useMitt(); const [textValue, setTextValue] = useState(''); - const [fontSize, setFontSize] = useState(24); - const [fontFamily, setFontFamily] = useState(DEFAULT_FONT_FAMILY); - const [isBold, setIsBold] = useState(true); - const [isItalic, setIsItalic] = useState(false); + const [fontSize, setFontSize] = useState(24); // Default font size + const [isBold, setIsBold] = useState(true); // Default to bold // Font size constraints const MIN_FONT_SIZE = 8; const MAX_FONT_SIZE = 120; const FONT_SIZE_STEP = 2; - // Update all state when selected element changes + // Update textarea, fontSize, and bold when selected element changes useEffect(() => { if (selectedTextElement) { setTextValue(selectedTextElement.text || ''); setFontSize(selectedTextElement.fontSize || 24); - setFontFamily(selectedTextElement.fontFamily || DEFAULT_FONT_FAMILY); - setIsBold(selectedTextElement.fontWeight === 'bold' || selectedTextElement.fontWeight === 700 || true); - setIsItalic(selectedTextElement.fontStyle === 'italic' || false); + setIsBold(selectedTextElement.fontWeight === 'bold' || selectedTextElement.fontWeight === 700 || true); // Default to bold if not set } }, [selectedTextElement]); - // Listen for fontSize changes from canvas transformations (separate from selection) - useEffect(() => { - const handleTextElementUpdate = (updatedElement) => { - if (selectedTextElement && updatedElement.id === selectedTextElement.id) { - // Update local state to reflect changes from canvas - if (updatedElement.fontSize !== undefined) { - setFontSize(updatedElement.fontSize); - } - if (updatedElement.text !== undefined) { - setTextValue(updatedElement.text); - } - if (updatedElement.fontFamily !== undefined) { - setFontFamily(updatedElement.fontFamily); - } - if (updatedElement.fontWeight !== undefined) { - setIsBold(updatedElement.fontWeight === 'bold' || updatedElement.fontWeight === 700); - } - if (updatedElement.fontStyle !== undefined) { - setIsItalic(updatedElement.fontStyle === 'italic'); - } - } - }; - - // Listen for updates from canvas transforms (doesn't open sidebar) - emitter.on('text-element-updated', handleTextElementUpdate); - - return () => { - emitter.off('text-element-updated', handleTextElementUpdate); - }; - }, [emitter, selectedTextElement]); - // Handle text changes const handleTextChange = (e) => { const newText = e.target.value; @@ -80,18 +40,6 @@ export default function TextSidebar({ isOpen, onClose }) { } }; - // Handle font family changes - const handleFontFamilyChange = (newFontFamily) => { - setFontFamily(newFontFamily); - - if (selectedTextElement) { - emitter.emit('text-update', { - elementId: selectedTextElement.id, - updates: { fontFamily: newFontFamily }, - }); - } - }; - // Handle font size changes const handleFontSizeChange = (newSize) => { const clampedSize = Math.max(MIN_FONT_SIZE, Math.min(MAX_FONT_SIZE, newSize)); @@ -118,19 +66,6 @@ export default function TextSidebar({ isOpen, onClose }) { } }; - // Handle italic toggle - const handleItalicToggle = () => { - const newItalicState = !isItalic; - setIsItalic(newItalicState); - - if (selectedTextElement) { - emitter.emit('text-update', { - elementId: selectedTextElement.id, - updates: { fontStyle: newItalicState ? 'italic' : 'normal' }, - }); - } - }; - // Increase font size const increaseFontSize = () => { handleFontSizeChange(fontSize + FONT_SIZE_STEP); @@ -161,46 +96,11 @@ export default function TextSidebar({ isOpen, onClose }) { value={textValue} onChange={handleTextChange} placeholder="Enter your text..." - className="mt-2 border-2 text-center text-nowrap" + className="mt-2 text-center" rows={4} - style={{ - fontFamily: fontFamily, - fontSize: `${fontSize * 0.45}px`, // Better scaling - fontWeight: isBold ? 'bold' : 'normal', - fontStyle: isItalic ? 'italic' : 'normal', - lineHeight: '1.4', - }} /> - {/* Font Fa - - {/* Font Family */} -
- - -
- {/* Font Size Controls */}
@@ -235,35 +135,20 @@ export default function TextSidebar({ isOpen, onClose }) {
Size range: {MIN_FONT_SIZE}px - {MAX_FONT_SIZE}px
- - {/* Visual feedback for canvas scaling */} -
- πŸ’‘ Tip: You can also resize text by dragging the corners on the canvas -
{/* Font Style Controls */}
-
+
- -
diff --git a/resources/js/modules/editor/templates/single_caption_meme_background.json b/resources/js/modules/editor/templates/single_caption_meme_background.json deleted file mode 100644 index 5bbea0b..0000000 --- a/resources/js/modules/editor/templates/single_caption_meme_background.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "id": "single_caption_meme_background", - - "max_duration_based_on": "memes", - - "number_of_backgrounds": 1, - "number_of_memes": 1, - "number_of_captions": 1, - - "timeline": [ - { - "id": "6", - "type": "image", - "source": "https://cdn.memeaigen.com/g1/webp/este-cat-dance.webp", - "name": "Este cat dance", - "startTime": 0, - "layer": 5, - "inPoint": 1, - "duration": 6, - "x": 200, - "y": 200, - "width": 280, - "height": 180, - "rotation": 0 - } - ] -}