fix: Enable proper editing of layout text objects
Browse filesMark layout text objects as modified when content or properties change:
- Text content changes now set isModified flag (Canvas.tsx:660)
- Font family changes mark as modified (App.tsx:1132)
- Bold/font weight changes mark as modified (App.tsx:1181)
- Italic changes mark as modified (App.tsx:1238)
This prevents layout text from being unexpectedly replaced during
layout switches and fixes MCP create_thumbnail text customization.
Fixes #text-editing-bug
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
- src/App.tsx +15 -6
- src/components/Canvas/Canvas.tsx +5 -2
src/App.tsx
CHANGED
|
@@ -1128,6 +1128,9 @@ function App() {
|
|
| 1128 |
onFontFamilyChange={(font) => {
|
| 1129 |
const updatedObjects = objects.map((o: CanvasObject) => {
|
| 1130 |
if (o.type === 'text' && selectedTextObjects.some(selected => selected.id === o.id)) {
|
|
|
|
|
|
|
|
|
|
| 1131 |
// Recalculate text dimensions with new font
|
| 1132 |
try {
|
| 1133 |
const tempText = new Konva.Text({
|
|
@@ -1141,10 +1144,10 @@ function App() {
|
|
| 1141 |
const newHeight = Math.max(40, tempText.height() + 10);
|
| 1142 |
|
| 1143 |
tempText.destroy();
|
| 1144 |
-
return { ...o, fontFamily: font, width: newWidth, height: newHeight };
|
| 1145 |
} catch (error) {
|
| 1146 |
console.error('Error recalculating text size:', error);
|
| 1147 |
-
return { ...o, fontFamily: font };
|
| 1148 |
}
|
| 1149 |
}
|
| 1150 |
return o;
|
|
@@ -1174,6 +1177,9 @@ function App() {
|
|
| 1174 |
onBoldToggle={() => {
|
| 1175 |
const updatedObjects = objects.map((o: CanvasObject) => {
|
| 1176 |
if (o.type === 'text' && selectedTextObjects.some(selected => selected.id === o.id)) {
|
|
|
|
|
|
|
|
|
|
| 1177 |
// Check if font supports BLACK weight
|
| 1178 |
const supportsBlack = o.fontFamily === 'Source Sans 3';
|
| 1179 |
const currentWeight = o.fontWeight || 'normal';
|
|
@@ -1215,10 +1221,10 @@ function App() {
|
|
| 1215 |
const newHeight = Math.max(40, tempText.height() + 10);
|
| 1216 |
|
| 1217 |
tempText.destroy();
|
| 1218 |
-
return { ...o, bold: newBold, fontWeight: newWeight, width: newWidth, height: newHeight };
|
| 1219 |
} catch (error) {
|
| 1220 |
console.error('Error recalculating text size:', error);
|
| 1221 |
-
return { ...o, bold: newBold, fontWeight: newWeight };
|
| 1222 |
}
|
| 1223 |
}
|
| 1224 |
return o;
|
|
@@ -1228,6 +1234,9 @@ function App() {
|
|
| 1228 |
onItalicToggle={() => {
|
| 1229 |
const updatedObjects = objects.map((o: CanvasObject) => {
|
| 1230 |
if (o.type === 'text' && selectedTextObjects.some(selected => selected.id === o.id)) {
|
|
|
|
|
|
|
|
|
|
| 1231 |
const newItalic = !o.italic;
|
| 1232 |
// Recalculate text dimensions with new italic state
|
| 1233 |
try {
|
|
@@ -1242,10 +1251,10 @@ function App() {
|
|
| 1242 |
const newHeight = Math.max(40, tempText.height() + 10);
|
| 1243 |
|
| 1244 |
tempText.destroy();
|
| 1245 |
-
return { ...o, italic: newItalic, width: newWidth, height: newHeight };
|
| 1246 |
} catch (error) {
|
| 1247 |
console.error('Error recalculating text size:', error);
|
| 1248 |
-
return { ...o, italic: newItalic };
|
| 1249 |
}
|
| 1250 |
}
|
| 1251 |
return o;
|
|
|
|
| 1128 |
onFontFamilyChange={(font) => {
|
| 1129 |
const updatedObjects = objects.map((o: CanvasObject) => {
|
| 1130 |
if (o.type === 'text' && selectedTextObjects.some(selected => selected.id === o.id)) {
|
| 1131 |
+
// Mark layout objects as modified when font family changes
|
| 1132 |
+
const isModified = o.isFromLayout ? true : o.isModified;
|
| 1133 |
+
|
| 1134 |
// Recalculate text dimensions with new font
|
| 1135 |
try {
|
| 1136 |
const tempText = new Konva.Text({
|
|
|
|
| 1144 |
const newHeight = Math.max(40, tempText.height() + 10);
|
| 1145 |
|
| 1146 |
tempText.destroy();
|
| 1147 |
+
return { ...o, fontFamily: font, width: newWidth, height: newHeight, isModified };
|
| 1148 |
} catch (error) {
|
| 1149 |
console.error('Error recalculating text size:', error);
|
| 1150 |
+
return { ...o, fontFamily: font, isModified };
|
| 1151 |
}
|
| 1152 |
}
|
| 1153 |
return o;
|
|
|
|
| 1177 |
onBoldToggle={() => {
|
| 1178 |
const updatedObjects = objects.map((o: CanvasObject) => {
|
| 1179 |
if (o.type === 'text' && selectedTextObjects.some(selected => selected.id === o.id)) {
|
| 1180 |
+
// Mark layout objects as modified when bold changes
|
| 1181 |
+
const isModified = o.isFromLayout ? true : o.isModified;
|
| 1182 |
+
|
| 1183 |
// Check if font supports BLACK weight
|
| 1184 |
const supportsBlack = o.fontFamily === 'Source Sans 3';
|
| 1185 |
const currentWeight = o.fontWeight || 'normal';
|
|
|
|
| 1221 |
const newHeight = Math.max(40, tempText.height() + 10);
|
| 1222 |
|
| 1223 |
tempText.destroy();
|
| 1224 |
+
return { ...o, bold: newBold, fontWeight: newWeight, width: newWidth, height: newHeight, isModified };
|
| 1225 |
} catch (error) {
|
| 1226 |
console.error('Error recalculating text size:', error);
|
| 1227 |
+
return { ...o, bold: newBold, fontWeight: newWeight, isModified };
|
| 1228 |
}
|
| 1229 |
}
|
| 1230 |
return o;
|
|
|
|
| 1234 |
onItalicToggle={() => {
|
| 1235 |
const updatedObjects = objects.map((o: CanvasObject) => {
|
| 1236 |
if (o.type === 'text' && selectedTextObjects.some(selected => selected.id === o.id)) {
|
| 1237 |
+
// Mark layout objects as modified when italic changes
|
| 1238 |
+
const isModified = o.isFromLayout ? true : o.isModified;
|
| 1239 |
+
|
| 1240 |
const newItalic = !o.italic;
|
| 1241 |
// Recalculate text dimensions with new italic state
|
| 1242 |
try {
|
|
|
|
| 1251 |
const newHeight = Math.max(40, tempText.height() + 10);
|
| 1252 |
|
| 1253 |
tempText.destroy();
|
| 1254 |
+
return { ...o, italic: newItalic, width: newWidth, height: newHeight, isModified };
|
| 1255 |
} catch (error) {
|
| 1256 |
console.error('Error recalculating text size:', error);
|
| 1257 |
+
return { ...o, italic: newItalic, isModified };
|
| 1258 |
}
|
| 1259 |
}
|
| 1260 |
return o;
|
src/components/Canvas/Canvas.tsx
CHANGED
|
@@ -656,9 +656,12 @@ export default function Canvas({
|
|
| 656 |
const handleTextChange = (id: string, text: string, width: number, height: number) => {
|
| 657 |
const updatedObjects = objects.map(obj => {
|
| 658 |
if (obj.id === id && obj.type === 'text') {
|
| 659 |
-
//
|
|
|
|
| 660 |
const dimensionsChanged = obj.width !== width || obj.height !== height;
|
| 661 |
-
const isModified =
|
|
|
|
|
|
|
| 662 |
|
| 663 |
return { ...obj, text, width, height, isModified };
|
| 664 |
}
|
|
|
|
| 656 |
const handleTextChange = (id: string, text: string, width: number, height: number) => {
|
| 657 |
const updatedObjects = objects.map(obj => {
|
| 658 |
if (obj.id === id && obj.type === 'text') {
|
| 659 |
+
// Mark as modified if: text changed OR dimensions changed (for layout objects)
|
| 660 |
+
const textChanged = obj.text !== text;
|
| 661 |
const dimensionsChanged = obj.width !== width || obj.height !== height;
|
| 662 |
+
const isModified = obj.isFromLayout && (textChanged || dimensionsChanged)
|
| 663 |
+
? true
|
| 664 |
+
: obj.isModified;
|
| 665 |
|
| 666 |
return { ...obj, text, width, height, isModified };
|
| 667 |
}
|