Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/visual-editor/locales/cs/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/da/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/de/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/en-GB/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/en/visual-editor.json
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@
},
"distance": "Distance",
"emailList": "Email List",
"emptyStateFieldEmpty": "{{entityType}}'s mapped field is empty",
"emptyStateSectionHidden": "Section hidden for this {{entityType}}",
"enterSchemaMarkup": "Enter schema markup...",
"entityTypeField": "{{entityType}} Field",
"event": "Event",
Expand Down
2 changes: 2 additions & 0 deletions packages/visual-editor/locales/es/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/et/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/fi/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/fr/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/hr/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/hu/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/it/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/ja/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/lt/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/lv/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/nb/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/nl/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/pl/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/pt/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/ro/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/sk/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/sv/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/tr/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/zh-TW/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/visual-editor/locales/zh/visual-editor.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

86 changes: 84 additions & 2 deletions packages/visual-editor/src/components/pageSections/Banner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ import {
TranslatableRichText,
msg,
pt,
Body,
} from "@yext/visual-editor";
import { ComponentConfig, Fields } from "@measured/puck";
import { ComponentConfig, Fields, PuckComponent } from "@measured/puck";
import {
backgroundColors,
BackgroundStyle,
} from "../../utils/themeConfigOptions.js";
import { CircleSlash2 } from "lucide-react";
import { useTemplateMetadata } from "../../internal/hooks/useMessageReceivers";
import { resolveYextEntityField } from "../../utils/resolveYextEntityField";

export interface BannerData {
/**
Expand Down Expand Up @@ -105,10 +109,43 @@ const bannerSectionFields: Fields<BannerSectionProps> = {
),
};

const BannerComponent = ({ data, styles }: BannerSectionProps) => {
function isRichTextEmpty(value: any): boolean {
if (!value) {
return true;
}
if (typeof value === "string") {
return value.trim() === "";
}
if (typeof value === "object") {
if ("html" in value) {
return !value.html || value.html.trim() === "";
}
if ("json" in value) {
return (
!value.json ||
(typeof value.json === "string" && value.json.trim() === "")
);
}
}
return false;
}
Comment on lines +112 to +131
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Consider handling object-type JSON in rich text emptiness check.

The isRichTextEmpty function checks value.json only when it's a string (line 126). If json is an object—common with Lexical or Draft.js structures—an empty structure like {root: {children: []}} would bypass this check and potentially render an empty styled container instead of the empty-state placeholder.

Consider adding a branch to handle object-type JSON:

     if ("json" in value) {
-      return (
-        !value.json ||
-        (typeof value.json === "string" && value.json.trim() === "")
-      );
+      if (!value.json) return true;
+      if (typeof value.json === "string") return value.json.trim() === "";
+      if (typeof value.json === "object") {
+        // Check for empty Lexical/Draft.js structure
+        const jsonStr = JSON.stringify(value.json);
+        return jsonStr === "{}" || jsonStr === '{"root":{"children":[]}}' || jsonStr.length < 30;
+      }
+      return false;
     }

Adjust the object-emptiness heuristic to match your actual RTF structure.

🤖 Prompt for AI Agents
In packages/visual-editor/src/components/pageSections/Banner.tsx around lines
112 to 131, the isRichTextEmpty helper only treats value.json as a string and
will miss empty JSON-rich-text objects (e.g., {root:{children:[]}}); update the
function to detect object-type JSON by adding a branch that checks for empty
structures — for example, if value.json is an object, treat it as empty when it
has no meaningful nodes/children (empty arrays or only empty text nodes) or when
its root children array is empty; implement a small safe traversal/heuristic
(check for root/children length, recursively ensure non-whitespace text nodes)
and return true when no real content is found.


const BannerComponent: PuckComponent<BannerSectionProps> = ({
data,
styles,
puck,
}) => {
const { i18n } = useTranslation();
const locale = i18n.language;
const streamDocument = useDocument();
const templateMetadata = useTemplateMetadata();

const isMappedField = !data.text.constantValueEnabled && !!data.text.field;
const rawValue = isMappedField
? resolveYextEntityField(streamDocument, data.text, locale)
: undefined;
const isEmpty = isMappedField && isRichTextEmpty(rawValue);

const resolvedText = resolveComponentData(data.text, locale, streamDocument);

const justifyClass = {
Expand All @@ -117,6 +154,51 @@ const BannerComponent = ({ data, styles }: BannerSectionProps) => {
right: "justify-end",
}[styles.textAlignment];

// Show empty state in editor mode when mapped field is empty
if (isMappedField && isEmpty) {
if (puck.isEditing) {
const entityTypeDisplayName = templateMetadata?.entityTypeDisplayName;

return (
<PageSection
background={backgroundColors.background1.value}
verticalPadding="sm"
className="flex items-center justify-center"
>
<div className="relative h-20 w-full bg-gray-100 rounded-lg border border-gray-200 flex flex-row items-center justify-center gap-3 px-4">
<CircleSlash2 className="w-10 h-10 text-gray-400 flex-shrink-0" />
<div className="flex flex-col items-start gap-0">
<Body variant="sm" className="text-gray-500 font-medium">
{pt(
"emptyStateSectionHidden",
"Section hidden for this {{entityType}}",
{
entityType: entityTypeDisplayName
? entityTypeDisplayName.toLowerCase()
: "page",
}
)}
</Body>
<Body variant="sm" className="text-gray-500 font-normal">
{pt(
"emptyStateFieldEmpty",
"{{entityType}}'s mapped field is empty",
{
entityType: entityTypeDisplayName
? entityTypeDisplayName.charAt(0).toUpperCase() +
entityTypeDisplayName.slice(1)
: "Entity",
}
)}
</Body>
</div>
</div>
</PageSection>
);
}
return <></>;
}

if (!resolvedText) {
return <></>;
}
Expand Down
Loading