From 7bb0898c78bf9d58bd38a5ae11819ef8a8467ead Mon Sep 17 00:00:00 2001 From: Bogdan Chadkin Date: Tue, 9 Sep 2025 13:50:01 +0300 Subject: [PATCH] fix: show href on link in content mode --- .../props-section/use-props-logic.ts | 36 ++++++++++------- packages/html-data/bin/attributes.ts | 4 ++ .../html-data/src/__generated__/attributes.ts | 40 ++++++++++++++----- 3 files changed, 55 insertions(+), 25 deletions(-) diff --git a/apps/builder/app/builder/features/settings-panel/props-section/use-props-logic.ts b/apps/builder/app/builder/features/settings-panel/props-section/use-props-logic.ts index 4a46c2b613b8..1eff9bb6dbed 100644 --- a/apps/builder/app/builder/features/settings-panel/props-section/use-props-logic.ts +++ b/apps/builder/app/builder/features/settings-panel/props-section/use-props-logic.ts @@ -16,13 +16,14 @@ import { $registeredComponentMetas, } from "~/shared/nano-states"; import { isRichText } from "~/shared/content-model"; -import { $selectedInstancePath } from "~/shared/awareness"; +import { $selectedInstance, $selectedInstancePath } from "~/shared/awareness"; import { $selectedInstanceInitialPropNames, $selectedInstancePropsMetas, showAttributeMeta, type PropValue, } from "../shared"; +import { $instanceTags } from "../../style-panel/shared/model"; type PropOrName = { prop?: Prop; propName: string }; @@ -157,6 +158,21 @@ const $canHaveTextContent = computed( } ); +const contentModePropertiesByTag: Partial> = { + img: ["src", "width", "height", "alt"], + a: ["href"], +}; + +const $selectedInstanceTag = computed( + [$selectedInstance, $instanceTags], + (selectedInstance, instanceTags) => { + if (selectedInstance === undefined) { + return; + } + return instanceTags.get(selectedInstance.id); + } +); + /** usePropsLogic expects that key={instanceId} is used on the ancestor component */ export const usePropsLogic = ({ instance, @@ -164,25 +180,19 @@ export const usePropsLogic = ({ updateProp, }: UsePropsLogicInput) => { const isContentMode = useStore($isContentMode); + const selectedInstanceTag = useStore($selectedInstanceTag); /** * In content edit mode we show only Image and Link props * In the future I hope the only thing we will show will be Components */ const isPropVisible = (propName: string) => { - const contentModeWhiteList: Partial> = { - Image: ["src", "width", "height", "alt"], - Link: ["href"], - RichTextLink: ["href"], - }; - if (!isContentMode) { return true; } - - const propsWhiteList = contentModeWhiteList[instance.component] ?? []; - - return propsWhiteList.includes(propName); + const allowedProperties = + contentModePropertiesByTag[selectedInstanceTag ?? ""] ?? []; + return allowedProperties.includes(propName); }; const savedProps = props; @@ -231,11 +241,7 @@ export const usePropsLogic = ({ const initialProps: PropAndMeta[] = []; for (const name of initialPropNames) { const propMeta = propsMetas.get(name); - if (propMeta === undefined) { - console.error( - `The prop "${name}" is defined in meta.initialProps but not in meta.props` - ); continue; } diff --git a/packages/html-data/bin/attributes.ts b/packages/html-data/bin/attributes.ts index fb3072e46250..7e01f686275f 100644 --- a/packages/html-data/bin/attributes.ts +++ b/packages/html-data/bin/attributes.ts @@ -77,6 +77,10 @@ const overrides: Record>> = { closedby: false, }, img: { + src: { required: true }, + alt: { required: true }, + width: { required: true }, + height: { required: true }, ismap: false, }, input: { diff --git a/packages/html-data/src/__generated__/attributes.ts b/packages/html-data/src/__generated__/attributes.ts index 744ea347aa19..05e416d4c7b9 100644 --- a/packages/html-data/src/__generated__/attributes.ts +++ b/packages/html-data/src/__generated__/attributes.ts @@ -873,12 +873,6 @@ const attribute_preserveAspectRatio_19as3ta: Attribute = { type: "string", }; -const attribute_alt_1j06s5r: Attribute = { - name: "alt", - description: "Replacement text for use when images are not available", - type: "string", -}; - const attribute_crossorigin_jl1m2v: Attribute = { name: "crossorigin", description: "How the element handles crossorigin requests", @@ -893,6 +887,12 @@ const attribute_loading_yzzdw4: Attribute = { options: ["lazy", "eager"], }; +const attribute_alt_1j06s5r: Attribute = { + name: "alt", + description: "Replacement text for use when images are not available", + type: "string", +}; + const attribute_disabled_1ceu012: Attribute = { name: "disabled", description: "Whether the form control is disabled", @@ -3824,7 +3824,12 @@ export const attributesByTag: Record = { attribute_y_14t62ez, ], img: [ - attribute_alt_1j06s5r, + { + name: "alt", + description: "Replacement text for use when images are not available", + type: "string", + required: true, + }, attribute_crossorigin_jl1m2v, { name: "decoding", @@ -3839,18 +3844,33 @@ export const attributesByTag: Record = { type: "select", options: ["auto", "high", "low"], }, - attribute_height_10887hn, + { + name: "height", + description: "Vertical dimension", + type: "number", + required: true, + }, attribute_loading_yzzdw4, attribute_referrerpolicy_tpprqt, attribute_sizes_o9chmv, - attribute_src_hol6ri, + { + name: "src", + description: "Address of the resource", + type: "string", + required: true, + }, attribute_srcset_1xpiw3a, { name: "usemap", description: "Name of image map to use", type: "string", }, - attribute_width_d9q964, + { + name: "width", + description: "Horizontal dimension", + type: "number", + required: true, + }, ], input: [ {