fixed slides titles issue
This commit is contained in:
parent
fd57a3bf10
commit
b5f8f30360
@ -334,20 +334,20 @@ export function useElementSettingsForm(options: UseElementSettingsFormOptions) {
|
|||||||
galleryTextFontFamily: String(settings.galleryTextFontFamily || ''),
|
galleryTextFontFamily: String(settings.galleryTextFontFamily || ''),
|
||||||
galleryCards: Array.isArray(settings.galleryCards)
|
galleryCards: Array.isArray(settings.galleryCards)
|
||||||
? settings.galleryCards.map(
|
? settings.galleryCards.map(
|
||||||
(card: Record<string, unknown>, index: number) => ({
|
(card: Record<string, unknown>) => ({
|
||||||
id: String(card?.id || createLocalId()),
|
id: String(card?.id || createLocalId()),
|
||||||
imageUrl: String(card?.imageUrl || ''),
|
imageUrl: String(card?.imageUrl ?? ''),
|
||||||
title: String(card?.title || `Card ${index + 1}`),
|
title: String(card?.title ?? ''),
|
||||||
description: String(card?.description || ''),
|
description: String(card?.description ?? ''),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
: [],
|
: [],
|
||||||
carouselSlides: Array.isArray(settings.carouselSlides)
|
carouselSlides: Array.isArray(settings.carouselSlides)
|
||||||
? settings.carouselSlides.map(
|
? settings.carouselSlides.map(
|
||||||
(slide: Record<string, unknown>, index: number) => ({
|
(slide: Record<string, unknown>) => ({
|
||||||
id: String(slide?.id || createLocalId()),
|
id: String(slide?.id || createLocalId()),
|
||||||
imageUrl: String(slide?.imageUrl || ''),
|
imageUrl: String(slide?.imageUrl ?? ''),
|
||||||
caption: String(slide?.caption || `Slide ${index + 1}`),
|
caption: String(slide?.caption ?? ''),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
: [],
|
: [],
|
||||||
@ -687,7 +687,7 @@ export function useElementSettingsForm(options: UseElementSettingsFormOptions) {
|
|||||||
settings.galleryCards = state.galleryCards.map((card, index) => ({
|
settings.galleryCards = state.galleryCards.map((card, index) => ({
|
||||||
id: String(card.id || createLocalId()),
|
id: String(card.id || createLocalId()),
|
||||||
imageUrl: card.imageUrl.trim(),
|
imageUrl: card.imageUrl.trim(),
|
||||||
title: card.title.trim() || `Card ${index + 1}`,
|
title: card.title.trim(),
|
||||||
description: card.description,
|
description: card.description,
|
||||||
}));
|
}));
|
||||||
settings.galleryTitleFontFamily = state.galleryTitleFontFamily.trim();
|
settings.galleryTitleFontFamily = state.galleryTitleFontFamily.trim();
|
||||||
@ -696,10 +696,10 @@ export function useElementSettingsForm(options: UseElementSettingsFormOptions) {
|
|||||||
|
|
||||||
// Carousel type settings
|
// Carousel type settings
|
||||||
if (isCarouselType) {
|
if (isCarouselType) {
|
||||||
settings.carouselSlides = state.carouselSlides.map((slide, index) => ({
|
settings.carouselSlides = state.carouselSlides.map((slide) => ({
|
||||||
id: String(slide.id || createLocalId()),
|
id: String(slide.id || createLocalId()),
|
||||||
imageUrl: slide.imageUrl.trim(),
|
imageUrl: slide.imageUrl.trim(),
|
||||||
caption: slide.caption.trim() || `Slide ${index + 1}`,
|
caption: slide.caption.trim(),
|
||||||
}));
|
}));
|
||||||
settings.carouselPrevIconUrl = state.carouselPrevIconUrl.trim();
|
settings.carouselPrevIconUrl = state.carouselPrevIconUrl.trim();
|
||||||
settings.carouselNextIconUrl = state.carouselNextIconUrl.trim();
|
settings.carouselNextIconUrl = state.carouselNextIconUrl.trim();
|
||||||
|
|||||||
@ -70,8 +70,12 @@ interface UseConstructorElementsResult {
|
|||||||
clearSelection: () => void;
|
clearSelection: () => void;
|
||||||
/** Add a new element of the given type */
|
/** Add a new element of the given type */
|
||||||
addElement: (type: CanvasElementType) => void;
|
addElement: (type: CanvasElementType) => void;
|
||||||
/** Update the selected element with a partial patch */
|
/** Update the selected element with a partial patch (or callback for fresh state) */
|
||||||
updateSelectedElement: (patch: Partial<CanvasElement>) => void;
|
updateSelectedElement: (
|
||||||
|
patchOrFn:
|
||||||
|
| Partial<CanvasElement>
|
||||||
|
| ((current: CanvasElement) => Partial<CanvasElement>),
|
||||||
|
) => void;
|
||||||
/** Update an element by ID with a partial patch */
|
/** Update an element by ID with a partial patch */
|
||||||
updateElement: (elementId: string, patch: Partial<CanvasElement>) => void;
|
updateElement: (elementId: string, patch: Partial<CanvasElement>) => void;
|
||||||
/** Remove the selected element */
|
/** Remove the selected element */
|
||||||
@ -227,13 +231,20 @@ export function useConstructorElements({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const updateSelectedElement = useCallback(
|
const updateSelectedElement = useCallback(
|
||||||
(patch: Partial<CanvasElement>) => {
|
(
|
||||||
|
patchOrFn:
|
||||||
|
| Partial<CanvasElement>
|
||||||
|
| ((current: CanvasElement) => Partial<CanvasElement>),
|
||||||
|
) => {
|
||||||
if (!selectedElementId) return;
|
if (!selectedElementId) return;
|
||||||
|
|
||||||
setElements((prev) => {
|
setElements((prev) => {
|
||||||
const next = prev.map((el) =>
|
const next = prev.map((el) => {
|
||||||
el.id === selectedElementId ? { ...el, ...patch } : el,
|
if (el.id !== selectedElementId) return el;
|
||||||
);
|
const patch =
|
||||||
|
typeof patchOrFn === 'function' ? patchOrFn(el) : patchOrFn;
|
||||||
|
return { ...el, ...patch };
|
||||||
|
});
|
||||||
onElementsChange?.(next);
|
onElementsChange?.(next);
|
||||||
return next;
|
return next;
|
||||||
});
|
});
|
||||||
@ -328,10 +339,12 @@ export function useConstructorElements({
|
|||||||
update: (cardId: string, patch: Partial<GalleryCard>) => {
|
update: (cardId: string, patch: Partial<GalleryCard>) => {
|
||||||
if (!selectedElement || !isGalleryElementType(selectedElement.type))
|
if (!selectedElement || !isGalleryElementType(selectedElement.type))
|
||||||
return;
|
return;
|
||||||
const nextCards = (selectedElement.galleryCards || []).map((card) =>
|
// Use callback to get fresh element state (avoids stale closure on rapid updates)
|
||||||
card.id === cardId ? { ...card, ...patch } : card,
|
updateSelectedElement((current) => ({
|
||||||
);
|
galleryCards: (current.galleryCards || []).map((card) =>
|
||||||
updateSelectedElement({ galleryCards: nextCards });
|
card.id === cardId ? { ...card, ...patch } : card,
|
||||||
|
),
|
||||||
|
}));
|
||||||
},
|
},
|
||||||
remove: (cardId: string) => {
|
remove: (cardId: string) => {
|
||||||
if (!selectedElement || !isGalleryElementType(selectedElement.type))
|
if (!selectedElement || !isGalleryElementType(selectedElement.type))
|
||||||
@ -363,10 +376,12 @@ export function useConstructorElements({
|
|||||||
update: (spanId: string, patch: Partial<GalleryInfoSpan>) => {
|
update: (spanId: string, patch: Partial<GalleryInfoSpan>) => {
|
||||||
if (!selectedElement || !isGalleryElementType(selectedElement.type))
|
if (!selectedElement || !isGalleryElementType(selectedElement.type))
|
||||||
return;
|
return;
|
||||||
const nextSpans = (selectedElement.galleryInfoSpans || []).map(
|
// Use callback to get fresh element state (avoids stale closure on rapid updates)
|
||||||
(span) => (span.id === spanId ? { ...span, ...patch } : span),
|
updateSelectedElement((current) => ({
|
||||||
);
|
galleryInfoSpans: (current.galleryInfoSpans || []).map((span) =>
|
||||||
updateSelectedElement({ galleryInfoSpans: nextSpans });
|
span.id === spanId ? { ...span, ...patch } : span,
|
||||||
|
),
|
||||||
|
}));
|
||||||
},
|
},
|
||||||
remove: (spanId: string) => {
|
remove: (spanId: string) => {
|
||||||
if (!selectedElement || !isGalleryElementType(selectedElement.type))
|
if (!selectedElement || !isGalleryElementType(selectedElement.type))
|
||||||
@ -399,10 +414,12 @@ export function useConstructorElements({
|
|||||||
update: (slideId: string, patch: Partial<CarouselSlide>) => {
|
update: (slideId: string, patch: Partial<CarouselSlide>) => {
|
||||||
if (!selectedElement || !isCarouselElementType(selectedElement.type))
|
if (!selectedElement || !isCarouselElementType(selectedElement.type))
|
||||||
return;
|
return;
|
||||||
const nextSlides = (selectedElement.carouselSlides || []).map(
|
// Use callback to get fresh element state (avoids stale closure on rapid updates)
|
||||||
(slide) => (slide.id === slideId ? { ...slide, ...patch } : slide),
|
updateSelectedElement((current) => ({
|
||||||
);
|
carouselSlides: (current.carouselSlides || []).map((slide) =>
|
||||||
updateSelectedElement({ carouselSlides: nextSlides });
|
slide.id === slideId ? { ...slide, ...patch } : slide,
|
||||||
|
),
|
||||||
|
}));
|
||||||
},
|
},
|
||||||
remove: (slideId: string) => {
|
remove: (slideId: string) => {
|
||||||
if (!selectedElement || !isCarouselElementType(selectedElement.type))
|
if (!selectedElement || !isCarouselElementType(selectedElement.type))
|
||||||
|
|||||||
@ -224,12 +224,11 @@ export const createDefaultElement = (
|
|||||||
*/
|
*/
|
||||||
export const normalizeGalleryCard = (
|
export const normalizeGalleryCard = (
|
||||||
card: Record<string, unknown>,
|
card: Record<string, unknown>,
|
||||||
index: number,
|
|
||||||
): GalleryCard => ({
|
): GalleryCard => ({
|
||||||
id: String(card?.id || createLocalId()),
|
id: String(card?.id || createLocalId()),
|
||||||
imageUrl: String(card?.imageUrl || ''),
|
imageUrl: String(card?.imageUrl ?? ''),
|
||||||
title: String(card?.title || `Card ${index + 1}`),
|
title: String(card?.title ?? ''),
|
||||||
description: String(card?.description || ''),
|
description: String(card?.description ?? ''),
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -239,7 +238,7 @@ export const normalizeGalleryInfoSpan = (
|
|||||||
span: Record<string, unknown>,
|
span: Record<string, unknown>,
|
||||||
): GalleryInfoSpan => ({
|
): GalleryInfoSpan => ({
|
||||||
id: String(span?.id || createLocalId()),
|
id: String(span?.id || createLocalId()),
|
||||||
text: String(span?.text || ''),
|
text: String(span?.text ?? ''),
|
||||||
iconUrl: span?.iconUrl ? String(span.iconUrl) : undefined,
|
iconUrl: span?.iconUrl ? String(span.iconUrl) : undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -248,11 +247,10 @@ export const normalizeGalleryInfoSpan = (
|
|||||||
*/
|
*/
|
||||||
export const normalizeCarouselSlide = (
|
export const normalizeCarouselSlide = (
|
||||||
slide: Record<string, unknown>,
|
slide: Record<string, unknown>,
|
||||||
index: number,
|
|
||||||
): CarouselSlide => ({
|
): CarouselSlide => ({
|
||||||
id: String(slide?.id || createLocalId()),
|
id: String(slide?.id || createLocalId()),
|
||||||
imageUrl: String(slide?.imageUrl || ''),
|
imageUrl: String(slide?.imageUrl ?? ''),
|
||||||
caption: String(slide?.caption || `Slide ${index + 1}`),
|
caption: String(slide?.caption ?? ''),
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -323,8 +321,8 @@ export const mergeElementWithDefaults = (
|
|||||||
: Array.isArray(defaults.galleryCards)
|
: Array.isArray(defaults.galleryCards)
|
||||||
? defaults.galleryCards
|
? defaults.galleryCards
|
||||||
: element.galleryCards || [];
|
: element.galleryCards || [];
|
||||||
merged.galleryCards = cards.map((card, i) =>
|
merged.galleryCards = cards.map((card) =>
|
||||||
normalizeGalleryCard(card as unknown as Record<string, unknown>, i),
|
normalizeGalleryCard(card as unknown as Record<string, unknown>),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Handle gallery info spans array
|
// Handle gallery info spans array
|
||||||
@ -349,8 +347,8 @@ export const mergeElementWithDefaults = (
|
|||||||
: Array.isArray(defaults.carouselSlides)
|
: Array.isArray(defaults.carouselSlides)
|
||||||
? defaults.carouselSlides
|
? defaults.carouselSlides
|
||||||
: element.carouselSlides || [];
|
: element.carouselSlides || [];
|
||||||
merged.carouselSlides = slides.map((slide, i) =>
|
merged.carouselSlides = slides.map((slide) =>
|
||||||
normalizeCarouselSlide(slide as unknown as Record<string, unknown>, i),
|
normalizeCarouselSlide(slide as unknown as Record<string, unknown>),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -380,8 +378,8 @@ export const parseElementSettings = (
|
|||||||
|
|
||||||
// Parse gallery cards if present
|
// Parse gallery cards if present
|
||||||
if (Array.isArray(settings.galleryCards)) {
|
if (Array.isArray(settings.galleryCards)) {
|
||||||
settings.galleryCards = settings.galleryCards.map((card, i) =>
|
settings.galleryCards = settings.galleryCards.map((card) =>
|
||||||
normalizeGalleryCard(card as Record<string, unknown>, i),
|
normalizeGalleryCard(card as Record<string, unknown>),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,8 +392,8 @@ export const parseElementSettings = (
|
|||||||
|
|
||||||
// Parse carousel slides if present
|
// Parse carousel slides if present
|
||||||
if (Array.isArray(settings.carouselSlides)) {
|
if (Array.isArray(settings.carouselSlides)) {
|
||||||
settings.carouselSlides = settings.carouselSlides.map((slide, i) =>
|
settings.carouselSlides = settings.carouselSlides.map((slide) =>
|
||||||
normalizeCarouselSlide(slide as Record<string, unknown>, i),
|
normalizeCarouselSlide(slide as Record<string, unknown>),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -550,18 +548,18 @@ export const buildElementSettings = (
|
|||||||
// Gallery type settings
|
// Gallery type settings
|
||||||
if (isGalleryElementType(elementType)) {
|
if (isGalleryElementType(elementType)) {
|
||||||
if (Array.isArray(element.galleryCards)) {
|
if (Array.isArray(element.galleryCards)) {
|
||||||
settings.galleryCards = element.galleryCards.map((card, i) => ({
|
settings.galleryCards = element.galleryCards.map((card) => ({
|
||||||
id: String(card.id || createLocalId()),
|
id: String(card.id || createLocalId()),
|
||||||
imageUrl: card.imageUrl || '',
|
imageUrl: card.imageUrl ?? '',
|
||||||
title: card.title || `Card ${i + 1}`,
|
title: card.title ?? '',
|
||||||
description: card.description || '',
|
description: card.description ?? '',
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
if (Array.isArray(element.galleryInfoSpans)) {
|
if (Array.isArray(element.galleryInfoSpans)) {
|
||||||
settings.galleryInfoSpans = element.galleryInfoSpans.map((span) => ({
|
settings.galleryInfoSpans = element.galleryInfoSpans.map((span) => ({
|
||||||
id: String(span.id || createLocalId()),
|
id: String(span.id || createLocalId()),
|
||||||
text: span.text || '',
|
text: span.text ?? '',
|
||||||
iconUrl: span.iconUrl || undefined,
|
iconUrl: span.iconUrl ?? undefined,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
addIfNotEmpty(
|
addIfNotEmpty(
|
||||||
@ -592,10 +590,10 @@ export const buildElementSettings = (
|
|||||||
// Carousel type settings
|
// Carousel type settings
|
||||||
if (isCarouselElementType(elementType)) {
|
if (isCarouselElementType(elementType)) {
|
||||||
if (Array.isArray(element.carouselSlides)) {
|
if (Array.isArray(element.carouselSlides)) {
|
||||||
settings.carouselSlides = element.carouselSlides.map((slide, i) => ({
|
settings.carouselSlides = element.carouselSlides.map((slide) => ({
|
||||||
id: String(slide.id || createLocalId()),
|
id: String(slide.id || createLocalId()),
|
||||||
imageUrl: slide.imageUrl || '',
|
imageUrl: slide.imageUrl ?? '',
|
||||||
caption: slide.caption || `Slide ${i + 1}`,
|
caption: slide.caption ?? '',
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
addIfNotEmpty(settings, 'carouselPrevIconUrl', element.carouselPrevIconUrl);
|
addIfNotEmpty(settings, 'carouselPrevIconUrl', element.carouselPrevIconUrl);
|
||||||
|
|||||||
@ -820,11 +820,11 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
item.appearDurationSec,
|
item.appearDurationSec,
|
||||||
),
|
),
|
||||||
galleryCards: Array.isArray(item.galleryCards)
|
galleryCards: Array.isArray(item.galleryCards)
|
||||||
? item.galleryCards.map((card: any, index: number) => ({
|
? item.galleryCards.map((card: any) => ({
|
||||||
id: String(card?.id || createLocalId()),
|
id: String(card?.id || createLocalId()),
|
||||||
imageUrl: String(card?.imageUrl || ''),
|
imageUrl: String(card?.imageUrl ?? ''),
|
||||||
title: String(card?.title || `Card ${index + 1}`),
|
title: String(card?.title ?? ''),
|
||||||
description: String(card?.description || ''),
|
description: String(card?.description ?? ''),
|
||||||
}))
|
}))
|
||||||
: undefined,
|
: undefined,
|
||||||
galleryHeaderImageUrl:
|
galleryHeaderImageUrl:
|
||||||
@ -838,7 +838,7 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
galleryInfoSpans: Array.isArray(item.galleryInfoSpans)
|
galleryInfoSpans: Array.isArray(item.galleryInfoSpans)
|
||||||
? item.galleryInfoSpans.map((span: any) => ({
|
? item.galleryInfoSpans.map((span: any) => ({
|
||||||
id: String(span?.id || createLocalId()),
|
id: String(span?.id || createLocalId()),
|
||||||
text: String(span?.text || ''),
|
text: String(span?.text ?? ''),
|
||||||
}))
|
}))
|
||||||
: undefined,
|
: undefined,
|
||||||
galleryColumns:
|
galleryColumns:
|
||||||
@ -846,10 +846,10 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
? item.galleryColumns
|
? item.galleryColumns
|
||||||
: undefined,
|
: undefined,
|
||||||
carouselSlides: Array.isArray(item.carouselSlides)
|
carouselSlides: Array.isArray(item.carouselSlides)
|
||||||
? item.carouselSlides.map((slide: any, index: number) => ({
|
? item.carouselSlides.map((slide: any) => ({
|
||||||
id: String(slide?.id || createLocalId()),
|
id: String(slide?.id || createLocalId()),
|
||||||
imageUrl: String(slide?.imageUrl || ''),
|
imageUrl: String(slide?.imageUrl ?? ''),
|
||||||
caption: String(slide?.caption || `Slide ${index + 1}`),
|
caption: String(slide?.caption ?? ''),
|
||||||
}))
|
}))
|
||||||
: undefined,
|
: undefined,
|
||||||
iconUrl: typeof item.iconUrl === 'string' ? item.iconUrl : '',
|
iconUrl: typeof item.iconUrl === 'string' ? item.iconUrl : '',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user