diff --git a/apps/builder/app/builder/features/settings-panel/controls/tag-control.tsx b/apps/builder/app/builder/features/settings-panel/controls/tag-control.tsx index 91f3d900967c..9f86a379acd8 100644 --- a/apps/builder/app/builder/features/settings-panel/controls/tag-control.tsx +++ b/apps/builder/app/builder/features/settings-panel/controls/tag-control.tsx @@ -1,17 +1,70 @@ +import { useState } from "react"; +import { computed } from "nanostores"; import { useStore } from "@nanostores/react"; -import { Box, Select, theme } from "@webstudio-is/design-system"; +import { Box, Combobox, Select, theme } from "@webstudio-is/design-system"; import { elementsByTag } from "@webstudio-is/html-data"; -import { $selectedInstance } from "~/shared/awareness"; +import { tags } from "@webstudio-is/sdk"; +import { $selectedInstance, $selectedInstancePath } from "~/shared/awareness"; import { updateWebstudioData } from "~/shared/instance-utils"; +import { isTreeSatisfyingContentModel } from "~/shared/content-model"; +import { + $instances, + $props, + $registeredComponentMetas, +} from "~/shared/nano-states"; import { type ControlProps, VerticalLayout } from "../shared"; import { FieldLabel } from "../property-label"; +const $satisfyingTags = computed( + [$selectedInstancePath, $instances, $props, $registeredComponentMetas], + (instancePath, instances, props, metas) => { + const satisfyingTags: string[] = []; + if (instancePath === undefined) { + return satisfyingTags; + } + const [{ instance, instanceSelector }] = instancePath; + const newInstances = new Map(instances); + for (const tag of tags) { + newInstances.set(instance.id, { ...instance, tag }); + const isSatisfying = isTreeSatisfyingContentModel({ + instances: newInstances, + props, + metas, + instanceSelector, + }); + if (isSatisfying) { + satisfyingTags.push(tag); + } + } + return satisfyingTags; + } +); + export const TagControl = ({ meta, prop }: ControlProps<"tag">) => { const instance = useStore($selectedInstance); const propTag = prop?.type === "string" ? prop.value : undefined; const instanceTag = instance?.tag; const defaultTag = meta.options[0]; - const value = propTag ?? instanceTag ?? defaultTag; + const computedTag = instanceTag ?? propTag ?? defaultTag; + const satisfyingTags = useStore($satisfyingTags); + const options = meta.options.filter((tag) => satisfyingTags.includes(tag)); + const [value, setValue] = useState(); + const updateTag = (value: string) => { + if (instance === undefined) { + return; + } + const instanceId = instance.id; + updateWebstudioData((data) => { + // clean legacy and + if (prop) { + data.props.delete(prop.id); + } + const instance = data.instances.get(instanceId); + if (instance) { + instance.tag = value; + } + }); + }; return ( ) => { } > - ( + + {elementsByTag[item]?.description} + + )} + /> + )} ); };