From dd26d12da293d896a486bbeb82a572700950f30a Mon Sep 17 00:00:00 2001 From: Bogdan Chadkin Date: Sun, 18 May 2025 18:37:36 +0300 Subject: [PATCH 1/2] experimental: add icons to html elements Ref https://github.com/webstudio-is/webstudio/issues/3632 --- .../features/command-panel/command-panel.tsx | 15 ++- .../features/components/components.tsx | 20 ++- .../features/components/use-draggable.tsx | 14 +- .../builder/features/footer/breadcrumbs.tsx | 10 +- .../features/navigator/navigator-tree.tsx | 13 +- .../animation/subject-select.tsx | 3 +- .../settings-panel/settings-section.tsx | 5 +- .../features/style-panel/property-label.tsx | 2 +- .../outline/block-instance-outline.tsx | 7 +- .../workspace/canvas-tools/outline/label.tsx | 16 +-- apps/builder/app/builder/inspector.tsx | 13 +- .../app/builder/shared/instance-label.tsx | 122 ++++++++++++++++++ apps/builder/app/builder/shared/meta-icon.tsx | 13 -- apps/builder/app/shared/html.ts | 2 +- apps/builder/app/shared/instance-utils.ts | 31 +---- .../src/components/component-card.tsx | 9 +- .../sdk-components-react/src/blockquote.ws.ts | 2 - packages/sdk-components-react/src/body.ws.ts | 2 - packages/sdk-components-react/src/bold.ws.ts | 2 - packages/sdk-components-react/src/box.ws.ts | 2 - .../sdk-components-react/src/button.ws.ts | 2 - packages/sdk-components-react/src/form.ws.ts | 2 - .../sdk-components-react/src/heading.ws.ts | 2 - packages/sdk-components-react/src/image.ws.ts | 2 - packages/sdk-components-react/src/input.ws.ts | 2 - .../sdk-components-react/src/italic.ws.ts | 2 - packages/sdk-components-react/src/label.ws.ts | 2 - packages/sdk-components-react/src/link.ws.ts | 2 - .../sdk-components-react/src/list-item.ws.ts | 2 - packages/sdk-components-react/src/list.ws.ts | 2 - .../sdk-components-react/src/option.ws.ts | 2 - .../sdk-components-react/src/paragraph.ws.ts | 2 - .../sdk-components-react/src/select.ws.ts | 2 - .../sdk-components-react/src/separator.ws.ts | 2 - .../sdk-components-react/src/subscript.ws.ts | 2 - .../src/superscript.ws.ts | 2 - .../sdk-components-react/src/textarea.ws.ts | 2 - packages/sdk-components-react/src/time.ws.ts | 2 - packages/sdk/src/core-metas.ts | 2 - packages/sdk/src/schema/component-meta.ts | 2 +- 40 files changed, 183 insertions(+), 160 deletions(-) create mode 100644 apps/builder/app/builder/shared/instance-label.tsx delete mode 100644 apps/builder/app/builder/shared/meta-icon.tsx diff --git a/apps/builder/app/builder/features/command-panel/command-panel.tsx b/apps/builder/app/builder/features/command-panel/command-panel.tsx index 9120acfb1dbb..c72fd2b6df07 100644 --- a/apps/builder/app/builder/features/command-panel/command-panel.tsx +++ b/apps/builder/app/builder/features/command-panel/command-panel.tsx @@ -39,7 +39,6 @@ import { } from "~/shared/nano-states"; import { getComponentTemplateData, - getInstanceLabel, insertWebstudioFragmentAt, } from "~/shared/instance-utils"; import { humanizeString } from "~/shared/string-utils"; @@ -50,6 +49,10 @@ import { setActiveSidebarPanel } from "~/builder/shared/nano-states"; import { $commandMetas } from "~/shared/commands-emitter"; import { emitCommand } from "~/builder/shared/commands"; import { isFeatureEnabled } from "@webstudio-is/feature-flags"; +import { + getInstanceLabel, + InstanceIcon, +} from "~/builder/shared/instance-label"; const $commandPanel = atom< | undefined @@ -88,7 +91,7 @@ type ComponentOption = { component: string; label: string; category: TemplateMeta["category"]; - icon: string; + icon: undefined | string; order: undefined | number; }; @@ -177,7 +180,7 @@ const $componentOptions = computed( component: name, label, category: meta.category, - icon: meta.icon ?? componentMeta?.icon ?? "", + icon: meta.icon ?? componentMeta?.icon, order: meta.order, }); } @@ -211,9 +214,9 @@ const ComponentOptionsGroup = ({ options }: { options: ComponentOption[] }) => { }} > - + + + {label}{" "} diff --git a/apps/builder/app/builder/features/components/components.tsx b/apps/builder/app/builder/features/components/components.tsx index 2016712e9c55..362ce3f21cf6 100644 --- a/apps/builder/app/builder/features/components/components.tsx +++ b/apps/builder/app/builder/features/components/components.tsx @@ -31,20 +31,22 @@ import { } from "@webstudio-is/design-system"; import { CollapsibleSection } from "~/builder/shared/collapsible-section"; import { dragItemAttribute, useDraggable } from "./use-draggable"; -import { MetaIcon } from "~/builder/shared/meta-icon"; import { $registeredComponentMetas, $registeredTemplates, } from "~/shared/nano-states"; import { getComponentTemplateData, - getInstanceLabel, insertWebstudioElementAt, insertWebstudioFragmentAt, } from "~/shared/instance-utils"; import type { Publish } from "~/shared/pubsub"; import { $selectedPage } from "~/shared/awareness"; import { mapGroupBy } from "~/shared/shim"; +import { + getInstanceLabel, + InstanceIcon, +} from "~/builder/shared/instance-label"; type Meta = { name: string; @@ -52,7 +54,7 @@ type Meta = { order: undefined | number; label: string; description: undefined | string; - icon: string; + icon?: string; }; const $metas = computed( @@ -85,7 +87,6 @@ const $metas = computed( order: componentMeta.order, label: getInstanceLabel({ component: name }, componentMeta), description: componentMeta.description, - icon: componentMeta.icon, }); } for (const [name, templateMeta] of templates) { @@ -111,7 +112,7 @@ const $metas = computed( componentMeta?.label ?? getInstanceLabel({ component: name }, templateMeta), description: templateMeta.description, - icon: templateMeta.icon ?? componentMeta?.icon ?? "", + icon: templateMeta.icon, }); } const metasByCategory = mapGroupBy(metas, (meta) => meta.category); @@ -335,7 +336,14 @@ export const ComponentsPanel = ({ {...{ [dragItemAttribute]: meta.name }} label={meta.label} description={meta.description} - icon={} + icon={ + + } /> ))} diff --git a/apps/builder/app/builder/features/components/use-draggable.tsx b/apps/builder/app/builder/features/components/use-draggable.tsx index aa4ca6805085..7e5545fc6fc4 100644 --- a/apps/builder/app/builder/features/components/use-draggable.tsx +++ b/apps/builder/app/builder/features/components/use-draggable.tsx @@ -10,11 +10,9 @@ import { useDisableCanvasPointerEvents, rawTheme, } from "@webstudio-is/design-system"; -import { $registeredComponentMetas } from "~/shared/nano-states"; import { useSubscribe, type Publish } from "~/shared/pubsub"; import { $canvasRect, $scale } from "~/builder/shared/nano-states"; -import { getInstanceLabel } from "~/shared/instance-utils"; -import { MetaIcon } from "~/builder/shared/meta-icon"; +import { InstanceIcon, InstanceLabel } from "~/builder/shared/instance-label"; const DragLayer = ({ component, @@ -23,12 +21,6 @@ const DragLayer = ({ component: Instance["component"]; point: Point; }) => { - const metas = useStore($registeredComponentMetas); - const meta = metas.get(component); - if (meta === undefined) { - return null; - } - return createPortal( } + label={} + icon={} style={{ transform: `translate3d(${point.x}px, ${point.y}px, 0)`, width: rawTheme.spacing[20], diff --git a/apps/builder/app/builder/features/footer/breadcrumbs.tsx b/apps/builder/app/builder/features/footer/breadcrumbs.tsx index ca794917519b..72272380b7cb 100644 --- a/apps/builder/app/builder/features/footer/breadcrumbs.tsx +++ b/apps/builder/app/builder/features/footer/breadcrumbs.tsx @@ -2,14 +2,12 @@ import { Fragment } from "react"; import { useStore } from "@nanostores/react"; import { ChevronRightIcon } from "@webstudio-is/icons"; import { theme, Button, Flex, Text } from "@webstudio-is/design-system"; -import { $registeredComponentMetas } from "~/shared/nano-states"; import { $textEditingInstanceSelector } from "~/shared/nano-states"; -import { getInstanceLabel } from "~/shared/instance-utils"; import { $selectedInstancePath, selectInstance } from "~/shared/awareness"; +import { InstanceLabel } from "~/builder/shared/instance-label"; export const Breadcrumbs = () => { const instancePath = useStore($selectedInstancePath); - const metas = useStore($registeredComponentMetas); return ( {instancePath === undefined ? ( @@ -20,10 +18,6 @@ export const Breadcrumbs = () => { .slice() .reverse() .map(({ instance, instanceSelector }, index) => { - const meta = metas.get(instance.component); - if (meta === undefined) { - return; - } return ( {/* hide the last one */} {index < instancePath.length - 1 && } diff --git a/apps/builder/app/builder/features/navigator/navigator-tree.tsx b/apps/builder/app/builder/features/navigator/navigator-tree.tsx index 0770d982bd87..b446ab863d19 100644 --- a/apps/builder/app/builder/features/navigator/navigator-tree.tsx +++ b/apps/builder/app/builder/features/navigator/navigator-tree.tsx @@ -55,8 +55,7 @@ import { } from "~/shared/nano-states"; import type { InstanceSelector } from "~/shared/tree-utils"; import { serverSyncStore } from "~/shared/sync"; -import { MetaIcon } from "~/builder/shared/meta-icon"; -import { getInstanceLabel, reparentInstance } from "~/shared/instance-utils"; +import { reparentInstance } from "~/shared/instance-utils"; import { emitCommand } from "~/builder/shared/commands"; import { useContentEditable } from "~/shared/dom-hooks"; import { @@ -69,6 +68,10 @@ import { isRichTextContent, isTreeSatisfyingContentModel, } from "~/shared/content-model"; +import { + getInstanceLabel, + InstanceIcon, +} from "~/builder/shared/instance-label"; type TreeItemAncestor = | undefined @@ -430,7 +433,7 @@ const TreeNodeContent = ({ }); return ( - }> + }> { } > - }> + } + > {rootMeta.label} diff --git a/apps/builder/app/builder/features/settings-panel/props-section/animation/subject-select.tsx b/apps/builder/app/builder/features/settings-panel/props-section/animation/subject-select.tsx index c635e79f888a..eb8b3890aa81 100644 --- a/apps/builder/app/builder/features/settings-panel/props-section/animation/subject-select.tsx +++ b/apps/builder/app/builder/features/settings-panel/props-section/animation/subject-select.tsx @@ -8,10 +8,11 @@ import { $selectedInstanceSelector, } from "~/shared/nano-states"; import { getInstanceStyleDecl } from "~/builder/features/style-panel/shared/model"; -import { getInstanceLabel, updateWebstudioData } from "~/shared/instance-utils"; +import { updateWebstudioData } from "~/shared/instance-utils"; import { toValue } from "@webstudio-is/css-engine"; import type { AnimationAction } from "@webstudio-is/sdk"; import { setListedCssProperty } from "./set-css-property"; +import { getInstanceLabel } from "~/builder/shared/instance-label"; const initSubjects = () => { const selectedInstanceSelector = $selectedInstanceSelector.get(); diff --git a/apps/builder/app/builder/features/settings-panel/settings-section.tsx b/apps/builder/app/builder/features/settings-panel/settings-section.tsx index 78110be4ce51..189a4b20ef1e 100644 --- a/apps/builder/app/builder/features/settings-panel/settings-section.tsx +++ b/apps/builder/app/builder/features/settings-panel/settings-section.tsx @@ -4,9 +4,9 @@ import type { Instance } from "@webstudio-is/sdk"; import { InputField } from "@webstudio-is/design-system"; import { $instances, $registeredComponentMetas } from "~/shared/nano-states"; import { HorizontalLayout, Label, Row, useLocalValue } from "./shared"; -import { getInstanceLabel } from "~/shared/instance-utils"; import { serverSyncStore } from "~/shared/sync"; import { $selectedInstance } from "~/shared/awareness"; +import { getInstanceLabel } from "~/builder/shared/instance-label"; const saveLabel = (label: string, selectedInstance: Instance) => { serverSyncStore.createTransaction([$instances], (instances) => { @@ -32,9 +32,6 @@ export const SettingsSection = () => { } const meta = metas.get(selectedInstance.component); - if (meta === undefined) { - return; - } const placeholder = getInstanceLabel(selectedInstance, meta); return ( diff --git a/apps/builder/app/builder/features/style-panel/property-label.tsx b/apps/builder/app/builder/features/style-panel/property-label.tsx index c995b367106b..4e15db2d5363 100644 --- a/apps/builder/app/builder/features/style-panel/property-label.tsx +++ b/apps/builder/app/builder/features/style-panel/property-label.tsx @@ -23,7 +23,6 @@ import { $registeredComponentMetas, $styleSources, } from "~/shared/nano-states"; -import { getInstanceLabel } from "~/shared/instance-utils"; import type { ComputedStyleDecl, StyleValueSourceColor, @@ -32,6 +31,7 @@ import { useComputedStyles } from "./shared/model"; import { StyleSourceBadge } from "./style-source"; import { createBatchUpdate } from "./shared/use-style-data"; import { $virtualInstances } from "~/shared/awareness"; +import { getInstanceLabel } from "~/builder/shared/instance-label"; const $isAltPressed = atom(false); if (typeof window !== "undefined") { diff --git a/apps/builder/app/builder/features/workspace/canvas-tools/outline/block-instance-outline.tsx b/apps/builder/app/builder/features/workspace/canvas-tools/outline/block-instance-outline.tsx index 2b1af992472a..b44d030284a8 100644 --- a/apps/builder/app/builder/features/workspace/canvas-tools/outline/block-instance-outline.tsx +++ b/apps/builder/app/builder/features/workspace/canvas-tools/outline/block-instance-outline.tsx @@ -19,7 +19,6 @@ import { } from "@webstudio-is/design-system"; import type { Instance } from "@webstudio-is/sdk"; import { PlusIcon, TrashIcon } from "@webstudio-is/icons"; -import { BoxIcon } from "@webstudio-is/icons/svg"; import { $blockChildOutline, $hoveredInstanceOutline, @@ -27,7 +26,6 @@ import { $instances, $isContentMode, $modifierKeys, - $registeredComponentMetas, findBlockSelector, findTemplates, type BlockChildOutline, @@ -38,13 +36,13 @@ import { deleteInstanceMutable, updateWebstudioData, } from "~/shared/instance-utils"; -import { MetaIcon } from "~/builder/shared/meta-icon"; import { skipInertHandlersAttribute } from "~/builder/shared/inert-handlers"; import { useEffectEvent } from "~/shared/hook-utils/effect-event"; import { getInstancePath } from "~/shared/awareness"; import { insertTemplateAt } from "./block-utils"; import { Outline } from "./outline"; import { applyScale } from "./apply-scale"; +import { InstanceIcon } from "~/builder/shared/instance-label"; export const TemplatesMenu = ({ onOpenChange, @@ -74,7 +72,6 @@ export const TemplatesMenu = ({ preventFocusOnHover: boolean; }) => { const instances = useStore($instances); - const metas = useStore($registeredComponentMetas); const modifierKeys = useStore($modifierKeys); const blockInstanceSelector = findBlockSelector(anchor, instances); @@ -105,7 +102,7 @@ export const TemplatesMenu = ({ const menuItems = templates?.map(([template, templateSelector]) => ({ id: template.id, - icon: , + icon: , title: template.label ?? template.component, value: templateSelector, })); diff --git a/apps/builder/app/builder/features/workspace/canvas-tools/outline/label.tsx b/apps/builder/app/builder/features/workspace/canvas-tools/outline/label.tsx index 489a9466089c..b68c1fc155bf 100644 --- a/apps/builder/app/builder/features/workspace/canvas-tools/outline/label.tsx +++ b/apps/builder/app/builder/features/workspace/canvas-tools/outline/label.tsx @@ -1,11 +1,8 @@ import { useCallback, useState } from "react"; -import { useStore } from "@nanostores/react"; import { styled, type Rect } from "@webstudio-is/design-system"; import type { Instance } from "@webstudio-is/sdk"; import { theme } from "@webstudio-is/design-system"; -import { MetaIcon } from "~/builder/shared/meta-icon"; -import { $registeredComponentMetas } from "~/shared/nano-states"; -import { getInstanceLabel } from "~/shared/instance-utils"; +import { InstanceIcon, InstanceLabel } from "~/builder/shared/instance-label"; type LabelPosition = "top" | "inside" | "bottom"; type LabelRefCallback = (element: HTMLElement | null) => void; @@ -99,17 +96,10 @@ type LabelProps = { export const Label = ({ instance, instanceRect, variant }: LabelProps) => { const [labelRef, position] = useLabelPosition(instanceRect); - const metas = useStore($registeredComponentMetas); - const meta = metas.get(instance.component); - - if (meta === undefined) { - return <>; - } - return ( - - {getInstanceLabel(instance, meta)} + + ); }; diff --git a/apps/builder/app/builder/inspector.tsx b/apps/builder/app/builder/inspector.tsx index 63aa09dc6dce..8a80c72355cd 100644 --- a/apps/builder/app/builder/inspector.tsx +++ b/apps/builder/app/builder/inspector.tsx @@ -27,8 +27,6 @@ import { } from "~/shared/nano-states"; import { NavigatorTree } from "~/builder/features/navigator"; import type { Settings } from "~/builder/shared/client-settings"; -import { MetaIcon } from "~/builder/shared/meta-icon"; -import { getInstanceLabel } from "~/shared/instance-utils"; import { BindingPopoverProvider } from "~/builder/shared/binding-popover"; import { $activeInspectorPanel } from "~/builder/shared/nano-states"; import { @@ -37,19 +35,14 @@ import { $selectedPage, } from "~/shared/awareness"; import { $styleSourceInputElement } from "./shared/commands"; +import { InstanceIcon, InstanceLabel } from "./shared/instance-label"; const InstanceInfo = ({ instance }: { instance: Instance }) => { - const metas = useStore($registeredComponentMetas); - const componentMeta = metas.get(instance.component); - if (componentMeta === undefined) { - return null; - } - const label = getInstanceLabel(instance, componentMeta); return ( - + - {label} + ); diff --git a/apps/builder/app/builder/shared/instance-label.tsx b/apps/builder/app/builder/shared/instance-label.tsx new file mode 100644 index 000000000000..5f0270813a53 --- /dev/null +++ b/apps/builder/app/builder/shared/instance-label.tsx @@ -0,0 +1,122 @@ +import type { HtmlTags } from "html-tags"; +import { useStore } from "@nanostores/react"; +import { + BlockquoteIcon, + BodyIcon, + BoldIcon, + BoxIcon, + ButtonElementIcon, + CalendarIcon, + FormIcon, + FormTextAreaIcon, + FormTextFieldIcon, + HeadingIcon, + ImageIcon, + ItemIcon, + LabelIcon, + LinkIcon, + ListIcon, + ListItemIcon, + MinusIcon, + SelectIcon, + SubscriptIcon, + SuperscriptIcon, + TextAlignLeftIcon, + TextItalicIcon, +} from "@webstudio-is/icons/svg"; +import { + elementComponent, + parseComponentName, + type Instance, +} from "@webstudio-is/sdk"; +import { $registeredComponentMetas } from "~/shared/nano-states"; +import { humanizeString } from "~/shared/string-utils"; + +const htmlIcons: Record = { + // typography + h1: HeadingIcon, + h2: HeadingIcon, + h3: HeadingIcon, + h4: HeadingIcon, + h5: HeadingIcon, + h6: HeadingIcon, + p: TextAlignLeftIcon, + blockquote: BlockquoteIcon, + ul: ListIcon, + ol: ListIcon, + li: ListItemIcon, + hr: MinusIcon, + // rich text + b: BoldIcon, + strong: BoldIcon, + i: TextItalicIcon, + em: TextItalicIcon, + sub: SubscriptIcon, + sup: SuperscriptIcon, + a: LinkIcon, + // form + form: FormIcon, + textarea: FormTextAreaIcon, + button: ButtonElementIcon, + input: FormTextFieldIcon, + label: LabelIcon, + select: SelectIcon, + option: ItemIcon, + // misc + body: BodyIcon, + time: CalendarIcon, + img: ImageIcon, +} satisfies Partial>; + +type InstanceLike = { + component: string; + label?: string; + tag?: string; +}; + +type Props = { + size?: number | string; + instance: InstanceLike; + icon?: string; +}; + +export const InstanceIcon = ({ size = 16, instance, icon }: Props) => { + const metas = useStore($registeredComponentMetas); + const meta = metas.get(instance.component); + // element component should be treated as div when no tag specified + const elementTag = + instance.component === elementComponent ? "div" : undefined; + const tag = + instance.tag ?? elementTag ?? Object.keys(meta?.presetStyle ?? {})[0]; + const computedIcon = icon ?? meta?.icon ?? htmlIcons[tag] ?? BoxIcon; + return ( +
+ ); +}; + +const getLabelFromComponentName = (component: Instance["component"]) => { + const [_namespace, componentName] = parseComponentName(component); + return humanizeString(componentName); +}; + +export const getInstanceLabel = ( + instance: InstanceLike, + meta: undefined | { label?: string } +) => { + if (instance.label) { + return instance.label; + } + if (instance.component === elementComponent && instance.tag) { + return `<${instance.tag}>`; + } + return meta?.label || getLabelFromComponentName(instance.component); +}; + +export const InstanceLabel = ({ instance }: { instance: InstanceLike }) => { + const metas = useStore($registeredComponentMetas); + const meta = metas.get(instance.component); + return getInstanceLabel(instance, meta); +}; diff --git a/apps/builder/app/builder/shared/meta-icon.tsx b/apps/builder/app/builder/shared/meta-icon.tsx deleted file mode 100644 index 714cc482c622..000000000000 --- a/apps/builder/app/builder/shared/meta-icon.tsx +++ /dev/null @@ -1,13 +0,0 @@ -type Props = { - size?: number | string; - icon: string; -}; - -export const MetaIcon = ({ size = 16, icon }: Props) => { - return ( -
- ); -}; diff --git a/apps/builder/app/shared/html.ts b/apps/builder/app/shared/html.ts index ea158f28197c..1d4bd887e3dd 100644 --- a/apps/builder/app/shared/html.ts +++ b/apps/builder/app/shared/html.ts @@ -15,9 +15,9 @@ import { StyleSourceSelection, } from "@webstudio-is/sdk"; import { ariaAttributes, attributesByTag } from "@webstudio-is/html-data"; +import { camelCaseProperty, parseCss } from "@webstudio-is/css-data"; import { richTextContentTags } from "./content-model"; import { setIsSubsetOf } from "./shim"; -import { camelCaseProperty, parseCss } from "@webstudio-is/css-data"; type ElementNode = DefaultTreeAdapterMap["element"]; diff --git a/apps/builder/app/shared/instance-utils.ts b/apps/builder/app/shared/instance-utils.ts index 6528d22b7089..303b9a6a33d7 100644 --- a/apps/builder/app/shared/instance-utils.ts +++ b/apps/builder/app/shared/instance-utils.ts @@ -28,7 +28,6 @@ import { portalComponent, collectionComponent, Prop, - parseComponentName, Props, elementComponent, tags, @@ -57,7 +56,6 @@ import { wrapEditableChildrenAroundDropTargetMutable, } from "./tree-utils"; import { removeByMutable } from "./array-utils"; -import { humanizeString } from "./string-utils"; import { serverSyncStore } from "./sync"; import { setDifference, setUnion } from "./shim"; import { breakCyclesMutable, findCycles } from "@webstudio-is/project-build"; @@ -81,6 +79,7 @@ import { isTreeSatisfyingContentModel, } from "./content-model"; import type { Project } from "@webstudio-is/project"; +import { getInstanceLabel } from "~/builder/shared/instance-label"; /** * structuredClone can be invoked on draft and throw error @@ -166,28 +165,6 @@ export const getWebstudioData = (): WebstudioData => { }; }; -const getLabelFromComponentName = (component: Instance["component"]) => { - if (component.includes(":")) { - // strip namespace - const [_namespace, baseName] = component.split(":"); - component = baseName; - } - return humanizeString(component); -}; - -export const getInstanceLabel = ( - instance: { component: string; label?: string; tag?: string }, - meta: { label?: string } -) => { - if (instance.label) { - return instance.label; - } - if (instance.component === elementComponent && instance.tag) { - return `<${instance.tag}>`; - } - return meta.label || getLabelFromComponentName(instance.component); -}; - export const findAllEditableInstanceSelector = ({ instanceSelector, instances, @@ -1349,10 +1326,8 @@ export const findClosestInsertable = ( instanceSelector: instanceSelector.slice(closestContainerIndex), fragment, onError: (message) => { - const [_namespace, componentName] = parseComponentName( - fragment.instances[0].component - ); - const label = humanizeString(componentName); + const component = fragment.instances[0].component; + const label = getInstanceLabel({ component }, {}); toast.warn(message || `"${label}" has no place here`); }, }); diff --git a/packages/design-system/src/components/component-card.tsx b/packages/design-system/src/components/component-card.tsx index 06ef9d1dd9b7..28516ea865ae 100644 --- a/packages/design-system/src/components/component-card.tsx +++ b/packages/design-system/src/components/component-card.tsx @@ -3,7 +3,12 @@ * https://www.figma.com/file/sfCE7iLS0k25qCxiifQNLE/%F0%9F%93%9A-Webstudio-Library?node-id=2608-8921 */ -import { forwardRef, type ComponentProps, type JSX } from "react"; +import { + forwardRef, + type ComponentProps, + type JSX, + type ReactNode, +} from "react"; import { css, theme } from "../stitches.config"; import { textVariants } from "./text"; import { Tooltip } from "./tooltip"; @@ -59,7 +64,7 @@ const textStyle = css(textVariants.small, { }); type ComponentCardProps = { - label: string; + label: ReactNode; description?: string; icon: JSX.Element; state?: "hover" | "disabled" | "selected"; diff --git a/packages/sdk-components-react/src/blockquote.ws.ts b/packages/sdk-components-react/src/blockquote.ws.ts index ef5f066b692d..ae83691bef06 100644 --- a/packages/sdk-components-react/src/blockquote.ws.ts +++ b/packages/sdk-components-react/src/blockquote.ws.ts @@ -1,4 +1,3 @@ -import { BlockquoteIcon } from "@webstudio-is/icons/svg"; import { defaultStates, type PresetStyle, @@ -59,7 +58,6 @@ const presetStyle = { } satisfies PresetStyle; export const meta: WsComponentMeta = { - icon: BlockquoteIcon, states: defaultStates, presetStyle, initialProps: ["id", "class", "cite"], diff --git a/packages/sdk-components-react/src/body.ws.ts b/packages/sdk-components-react/src/body.ws.ts index 994c1d668270..c8b16b20e5d2 100644 --- a/packages/sdk-components-react/src/body.ws.ts +++ b/packages/sdk-components-react/src/body.ws.ts @@ -1,4 +1,3 @@ -import { BodyIcon } from "@webstudio-is/icons/svg"; import { defaultStates, type PresetStyle, @@ -23,7 +22,6 @@ const presetStyle = { } satisfies PresetStyle; export const meta: WsComponentMeta = { - icon: BodyIcon, states: defaultStates, presetStyle, initialProps: ["id", "class"], diff --git a/packages/sdk-components-react/src/bold.ws.ts b/packages/sdk-components-react/src/bold.ws.ts index 9dc9ee9d6748..0fb6717162f9 100644 --- a/packages/sdk-components-react/src/bold.ws.ts +++ b/packages/sdk-components-react/src/bold.ws.ts @@ -1,11 +1,9 @@ -import { BoldIcon } from "@webstudio-is/icons/svg"; import { defaultStates, type WsComponentMeta } from "@webstudio-is/sdk"; import { b } from "@webstudio-is/sdk/normalize.css"; import { props } from "./__generated__/bold.props"; export const meta: WsComponentMeta = { label: "Bold Text", - icon: BoldIcon, states: defaultStates, presetStyle: { b }, initialProps: ["id", "class"], diff --git a/packages/sdk-components-react/src/box.ws.ts b/packages/sdk-components-react/src/box.ws.ts index 2d5970e11159..918cd406de3e 100644 --- a/packages/sdk-components-react/src/box.ws.ts +++ b/packages/sdk-components-react/src/box.ws.ts @@ -1,4 +1,3 @@ -import { BoxIcon } from "@webstudio-is/icons/svg"; import { defaultStates, type WsComponentMeta } from "@webstudio-is/sdk"; import { div, @@ -18,7 +17,6 @@ export const meta: WsComponentMeta = { category: "general", description: "A container for content. By default this is a Div, but the tag can be changed in settings.", - icon: BoxIcon, states: defaultStates, presetStyle: { div, diff --git a/packages/sdk-components-react/src/button.ws.ts b/packages/sdk-components-react/src/button.ws.ts index c5f2cc349f7d..8b44d3d5e83a 100644 --- a/packages/sdk-components-react/src/button.ws.ts +++ b/packages/sdk-components-react/src/button.ws.ts @@ -1,4 +1,3 @@ -import { ButtonElementIcon } from "@webstudio-is/icons/svg"; import { defaultStates, type PresetStyle, @@ -13,7 +12,6 @@ const presetStyle = { } satisfies PresetStyle; export const meta: WsComponentMeta = { - icon: ButtonElementIcon, presetStyle, states: [ ...defaultStates, diff --git a/packages/sdk-components-react/src/form.ws.ts b/packages/sdk-components-react/src/form.ws.ts index 34fe4b7e29d2..0b78c2d982a4 100644 --- a/packages/sdk-components-react/src/form.ws.ts +++ b/packages/sdk-components-react/src/form.ws.ts @@ -1,4 +1,3 @@ -import { FormIcon } from "@webstudio-is/icons/svg"; import { defaultStates, type PresetStyle, @@ -19,7 +18,6 @@ export const meta: WsComponentMeta = { category: "forms", label: "Form", description: "Create filters, surveys, searches and more.", - icon: FormIcon, states: defaultStates, presetStyle, order: 0, diff --git a/packages/sdk-components-react/src/heading.ws.ts b/packages/sdk-components-react/src/heading.ws.ts index 100be098e508..7f5ea714d35a 100644 --- a/packages/sdk-components-react/src/heading.ws.ts +++ b/packages/sdk-components-react/src/heading.ws.ts @@ -1,10 +1,8 @@ -import { HeadingIcon } from "@webstudio-is/icons/svg"; import { defaultStates, type WsComponentMeta } from "@webstudio-is/sdk"; import { h1, h2, h3, h4, h5, h6 } from "@webstudio-is/sdk/normalize.css"; import { props } from "./__generated__/heading.props"; export const meta: WsComponentMeta = { - icon: HeadingIcon, states: defaultStates, presetStyle: { h1, diff --git a/packages/sdk-components-react/src/image.ws.ts b/packages/sdk-components-react/src/image.ws.ts index 4fbf2c173270..9a1d3665a0a1 100644 --- a/packages/sdk-components-react/src/image.ws.ts +++ b/packages/sdk-components-react/src/image.ws.ts @@ -1,4 +1,3 @@ -import { ImageIcon } from "@webstudio-is/icons/svg"; import { defaultStates, type PresetStyle, @@ -37,7 +36,6 @@ export const meta: WsComponentMeta = { category: "media", description: "Add an image asset to the page. Webstudio automatically converts images to WebP or AVIF format and makes them responsive for best performance.", - icon: ImageIcon, states: defaultStates, presetStyle, order: 0, diff --git a/packages/sdk-components-react/src/input.ws.ts b/packages/sdk-components-react/src/input.ws.ts index b3a04a4da192..d71fb9d01204 100644 --- a/packages/sdk-components-react/src/input.ws.ts +++ b/packages/sdk-components-react/src/input.ws.ts @@ -1,4 +1,3 @@ -import { FormTextFieldIcon } from "@webstudio-is/icons/svg"; import { defaultStates, type PresetStyle, @@ -23,7 +22,6 @@ export const meta: WsComponentMeta = { label: "Text Input", description: "A single-line text input for collecting string data from your users.", - icon: FormTextFieldIcon, presetStyle, order: 3, states: [ diff --git a/packages/sdk-components-react/src/italic.ws.ts b/packages/sdk-components-react/src/italic.ws.ts index 083683e2b191..b9074c286685 100644 --- a/packages/sdk-components-react/src/italic.ws.ts +++ b/packages/sdk-components-react/src/italic.ws.ts @@ -1,4 +1,3 @@ -import { TextItalicIcon } from "@webstudio-is/icons/svg"; import type { defaultTag } from "./italic"; import { defaultStates, @@ -20,7 +19,6 @@ const presetStyle = { export const meta: WsComponentMeta = { label: "Italic Text", - icon: TextItalicIcon, states: defaultStates, presetStyle, initialProps: ["id", "class"], diff --git a/packages/sdk-components-react/src/label.ws.ts b/packages/sdk-components-react/src/label.ws.ts index 10bdefd4917a..cba9e5577517 100644 --- a/packages/sdk-components-react/src/label.ws.ts +++ b/packages/sdk-components-react/src/label.ws.ts @@ -1,4 +1,3 @@ -import { LabelIcon } from "@webstudio-is/icons/svg"; import { type WsComponentMeta, type PresetStyle, @@ -17,7 +16,6 @@ const presetStyle = { export const meta: WsComponentMeta = { label: "Input Label", - icon: LabelIcon, states: defaultStates, presetStyle, initialProps: ["id", "class", "for"], diff --git a/packages/sdk-components-react/src/link.ws.ts b/packages/sdk-components-react/src/link.ws.ts index 39ab444d6ab6..20b2a1b3d563 100644 --- a/packages/sdk-components-react/src/link.ws.ts +++ b/packages/sdk-components-react/src/link.ws.ts @@ -1,4 +1,3 @@ -import { LinkIcon } from "@webstudio-is/icons/svg"; import { defaultStates, type PresetStyle, @@ -19,7 +18,6 @@ const presetStyle = { } satisfies PresetStyle; export const meta: WsComponentMeta = { - icon: LinkIcon, presetStyle, states: [ ...defaultStates, diff --git a/packages/sdk-components-react/src/list-item.ws.ts b/packages/sdk-components-react/src/list-item.ws.ts index 817892dfc45e..198e8727cfde 100644 --- a/packages/sdk-components-react/src/list-item.ws.ts +++ b/packages/sdk-components-react/src/list-item.ws.ts @@ -1,10 +1,8 @@ -import { ListItemIcon } from "@webstudio-is/icons/svg"; import { defaultStates, type WsComponentMeta } from "@webstudio-is/sdk"; import { li } from "@webstudio-is/sdk/normalize.css"; import { props } from "./__generated__/list-item.props"; export const meta: WsComponentMeta = { - icon: ListItemIcon, states: defaultStates, presetStyle: { li }, initialProps: ["id", "class"], diff --git a/packages/sdk-components-react/src/list.ws.ts b/packages/sdk-components-react/src/list.ws.ts index ce62825d86fa..53388a9fe1f9 100644 --- a/packages/sdk-components-react/src/list.ws.ts +++ b/packages/sdk-components-react/src/list.ws.ts @@ -1,4 +1,3 @@ -import { ListIcon } from "@webstudio-is/icons/svg"; import { defaultStates, type PresetStyle, @@ -42,7 +41,6 @@ const presetStyle = { } satisfies PresetStyle; export const meta: WsComponentMeta = { - icon: ListIcon, states: defaultStates, presetStyle, initialProps: ["id", "class", "ordered", "start", "reversed"], diff --git a/packages/sdk-components-react/src/option.ws.ts b/packages/sdk-components-react/src/option.ws.ts index 1062045cce9a..285abf79298c 100644 --- a/packages/sdk-components-react/src/option.ws.ts +++ b/packages/sdk-components-react/src/option.ws.ts @@ -1,4 +1,3 @@ -import { ItemIcon } from "@webstudio-is/icons/svg"; import type { PresetStyle, WsComponentMeta } from "@webstudio-is/sdk"; import type { defaultTag } from "./option"; @@ -24,7 +23,6 @@ export const meta: WsComponentMeta = { category: "hidden", description: "An item within a drop-down menu that users can select as their chosen value.", - icon: ItemIcon, presetStyle, states: [ // Applies when option is being activated (clicked) diff --git a/packages/sdk-components-react/src/paragraph.ws.ts b/packages/sdk-components-react/src/paragraph.ws.ts index 777c7250170d..ef8514aa3b20 100644 --- a/packages/sdk-components-react/src/paragraph.ws.ts +++ b/packages/sdk-components-react/src/paragraph.ws.ts @@ -1,10 +1,8 @@ -import { TextAlignLeftIcon } from "@webstudio-is/icons/svg"; import { defaultStates, type WsComponentMeta } from "@webstudio-is/sdk"; import { p } from "@webstudio-is/sdk/normalize.css"; import { props } from "./__generated__/paragraph.props"; export const meta: WsComponentMeta = { - icon: TextAlignLeftIcon, states: defaultStates, presetStyle: { p }, initialProps: ["id", "class"], diff --git a/packages/sdk-components-react/src/select.ws.ts b/packages/sdk-components-react/src/select.ws.ts index 2c295356cae3..b5ebf1312071 100644 --- a/packages/sdk-components-react/src/select.ws.ts +++ b/packages/sdk-components-react/src/select.ws.ts @@ -1,4 +1,3 @@ -import { SelectIcon } from "@webstudio-is/icons/svg"; import { defaultStates, type PresetStyle, @@ -19,7 +18,6 @@ const presetStyle = { } satisfies PresetStyle; export const meta: WsComponentMeta = { - icon: SelectIcon, presetStyle, states: [ ...defaultStates, diff --git a/packages/sdk-components-react/src/separator.ws.ts b/packages/sdk-components-react/src/separator.ws.ts index 06ecd260ae14..db3ea8068e9e 100644 --- a/packages/sdk-components-react/src/separator.ws.ts +++ b/packages/sdk-components-react/src/separator.ws.ts @@ -1,4 +1,3 @@ -import { MinusIcon } from "@webstudio-is/icons/svg"; import { defaultStates, type PresetStyle, @@ -43,7 +42,6 @@ export const meta: WsComponentMeta = { category: "general", description: "Used to visually divide sections of content, helping to improve readability and organization within a webpage.", - icon: MinusIcon, states: defaultStates, presetStyle, order: 3, diff --git a/packages/sdk-components-react/src/subscript.ws.ts b/packages/sdk-components-react/src/subscript.ws.ts index dbf52b25a118..72bae98fa767 100644 --- a/packages/sdk-components-react/src/subscript.ws.ts +++ b/packages/sdk-components-react/src/subscript.ws.ts @@ -1,11 +1,9 @@ -import { SubscriptIcon } from "@webstudio-is/icons/svg"; import { defaultStates, type WsComponentMeta } from "@webstudio-is/sdk"; import { sub } from "@webstudio-is/sdk/normalize.css"; import { props } from "./__generated__/subscript.props"; export const meta: WsComponentMeta = { label: "Subscript Text", - icon: SubscriptIcon, states: defaultStates, presetStyle: { sub }, initialProps: ["id", "class"], diff --git a/packages/sdk-components-react/src/superscript.ws.ts b/packages/sdk-components-react/src/superscript.ws.ts index 041fa6ca92e3..4bcee0a23541 100644 --- a/packages/sdk-components-react/src/superscript.ws.ts +++ b/packages/sdk-components-react/src/superscript.ws.ts @@ -1,11 +1,9 @@ -import { SuperscriptIcon } from "@webstudio-is/icons/svg"; import { defaultStates, type WsComponentMeta } from "@webstudio-is/sdk"; import { sup } from "@webstudio-is/sdk/normalize.css"; import { props } from "./__generated__/superscript.props"; export const meta: WsComponentMeta = { label: "Superscript Text", - icon: SuperscriptIcon, states: defaultStates, presetStyle: { sup }, initialProps: ["id", "class"], diff --git a/packages/sdk-components-react/src/textarea.ws.ts b/packages/sdk-components-react/src/textarea.ws.ts index bf664514e55c..19ce31de8351 100644 --- a/packages/sdk-components-react/src/textarea.ws.ts +++ b/packages/sdk-components-react/src/textarea.ws.ts @@ -1,4 +1,3 @@ -import { FormTextAreaIcon } from "@webstudio-is/icons/svg"; import { type WsComponentMeta, type PresetStyle, @@ -25,7 +24,6 @@ export const meta: WsComponentMeta = { label: "Text Area", description: "A multi-line text input for collecting longer string data from your users.", - icon: FormTextAreaIcon, presetStyle, order: 4, contentModel: { diff --git a/packages/sdk-components-react/src/time.ws.ts b/packages/sdk-components-react/src/time.ws.ts index 05bd5370907e..3a7ca160ab11 100644 --- a/packages/sdk-components-react/src/time.ws.ts +++ b/packages/sdk-components-react/src/time.ws.ts @@ -1,4 +1,3 @@ -import { CalendarIcon } from "@webstudio-is/icons/svg"; import { defaultStates, type WsComponentMeta } from "@webstudio-is/sdk"; import { time } from "@webstudio-is/sdk/normalize.css"; import { props } from "./__generated__/time.props"; @@ -7,7 +6,6 @@ export const meta: WsComponentMeta = { category: "localization", description: "Converts machine-readable date and time to a human-readable format.", - icon: CalendarIcon, contentModel: { category: "instance", children: [], diff --git a/packages/sdk/src/core-metas.ts b/packages/sdk/src/core-metas.ts index 4438ff50d1b1..7b6cd7b43041 100644 --- a/packages/sdk/src/core-metas.ts +++ b/packages/sdk/src/core-metas.ts @@ -4,7 +4,6 @@ import { PaintBrushIcon, SettingsIcon, AddTemplateInstanceIcon, - BoxIcon, } from "@webstudio-is/icons/svg"; import { html } from "./__generated__/normalize.css"; import * as normalize from "./__generated__/normalize.css"; @@ -27,7 +26,6 @@ export const elementComponent = "ws:element"; const elementMeta: WsComponentMeta = { label: "Element", - icon: BoxIcon, // convert [object Module] to [object Object] to enable structured cloning presetStyle: { ...normalize }, initialProps: [tagProperty, "id", "class"], diff --git a/packages/sdk/src/schema/component-meta.ts b/packages/sdk/src/schema/component-meta.ts index 2b2c53c902eb..f249f7a49bc0 100644 --- a/packages/sdk/src/schema/component-meta.ts +++ b/packages/sdk/src/schema/component-meta.ts @@ -90,7 +90,7 @@ export const WsComponentMeta = z.object({ indexWithinAncestor: z.optional(z.string()), label: z.optional(z.string()), description: z.string().optional(), - icon: z.string(), + icon: z.string().optional(), presetStyle: z.optional(z.record(z.string(), z.array(PresetStyleDecl))), states: z.optional(z.array(ComponentState)), order: z.number().optional(), From 25f58d534c3eabe893f9f2a0d78a4aee243eae2c Mon Sep 17 00:00:00 2001 From: Bogdan Chadkin Date: Sun, 18 May 2025 18:46:51 +0300 Subject: [PATCH 2/2] Remove empty icon from meta --- .../props-section/props-section.stories.tsx | 1 - .../src/component-generator.test.tsx | 15 ++++++-------- .../sdk-components-react/src/fragment.ws.ts | 4 +--- packages/sdk/src/css.test.tsx | 20 ------------------- packages/sdk/src/instances-utils.test.tsx | 12 ++++------- 5 files changed, 11 insertions(+), 41 deletions(-) diff --git a/apps/builder/app/builder/features/settings-panel/props-section/props-section.stories.tsx b/apps/builder/app/builder/features/settings-panel/props-section/props-section.stories.tsx index 31ba8e8d668a..452c2f89ee0b 100644 --- a/apps/builder/app/builder/features/settings-panel/props-section/props-section.stories.tsx +++ b/apps/builder/app/builder/features/settings-panel/props-section/props-section.stories.tsx @@ -202,7 +202,6 @@ registerComponentLibrary({ templates: {}, metas: { Box: { - icon: "", props: { initialText: textProp("", "multi\nline"), initialShortText: shortTextProp(), diff --git a/packages/react-sdk/src/component-generator.test.tsx b/packages/react-sdk/src/component-generator.test.tsx index 738bf43024e5..798cd9310fdd 100644 --- a/packages/react-sdk/src/component-generator.test.tsx +++ b/packages/react-sdk/src/component-generator.test.tsx @@ -1166,8 +1166,8 @@ test("generate prop with index within ancestor", () => { rootInstanceId: "body", parameters: [], metas: new Map([ - ["TabsTrigger", { icon: "", indexWithinAncestor: "Tabs" }], - ["TabsContent", { icon: "", indexWithinAncestor: "Tabs" }], + ["TabsTrigger", { indexWithinAncestor: "Tabs" }], + ["TabsContent", { indexWithinAncestor: "Tabs" }], ]), ...renderData( <$.Body ws:id="body"> @@ -1224,7 +1224,7 @@ test("ignore ws:block-template when generate index attribute", () => { rootInstanceId: "bodyId", parameters: [], metas: new Map([ - ["TabsTrigger", { icon: "", indexWithinAncestor: "Tabs" }], + ["TabsTrigger", { indexWithinAncestor: "Tabs" }], ]), ...renderData( <$.Body ws:id="bodyId"> @@ -1387,9 +1387,7 @@ test("convert attributes to react compatible when render ws:element", () => { name: "Page", rootInstanceId: "bodyId", parameters: [], - metas: new Map([ - [elementComponent, { icon: "", presetStyle: { div: [] } }], - ]), + metas: new Map([[elementComponent, { presetStyle: { div: [] } }]]), ...renderData( <$.Body ws:id="bodyId"> <$.Box class="my-class" for="my-id" autocomplete="off"> @@ -1459,7 +1457,6 @@ test("ignore props similar to standard attributes when react components defines [ "Vimeo", { - icon: "", presetStyle: { div: [] }, props: { autoplay: { type: "boolean", control: "boolean", required: true }, @@ -1495,7 +1492,7 @@ test("ignore props similar to standard attributes on react components without ta name: "Page", rootInstanceId: "bodyId", parameters: [], - metas: new Map([["HeadSlot", { icon: "" }]]), + metas: new Map([["HeadSlot", {}]]), ...renderData( <$.Body ws:id="bodyId"> <$.HeadSlot diff --git a/packages/sdk-components-react/src/fragment.ws.ts b/packages/sdk-components-react/src/fragment.ws.ts index 43327c3a5aac..d7e179d635a8 100644 --- a/packages/sdk-components-react/src/fragment.ws.ts +++ b/packages/sdk-components-react/src/fragment.ws.ts @@ -1,5 +1,3 @@ import type { WsComponentMeta } from "@webstudio-is/sdk"; -export const meta: WsComponentMeta = { - icon: "", -}; +export const meta: WsComponentMeta = {}; diff --git a/packages/sdk/src/css.test.tsx b/packages/sdk/src/css.test.tsx index 1660b9242c63..8a13c3516ffa 100644 --- a/packages/sdk/src/css.test.tsx +++ b/packages/sdk/src/css.test.tsx @@ -163,8 +163,6 @@ test("generate component presets with multiple tags", () => { [ "ListItem", { - type: "container", - icon: "", presetStyle: { div: css` display: block; @@ -219,8 +217,6 @@ test("deduplicate component presets for similarly named components", () => { [ "ListItem", { - type: "container", - icon: "", presetStyle: { div: css` display: block; @@ -231,8 +227,6 @@ test("deduplicate component presets for similarly named components", () => { [ "@webstudio/radix:ListItem", { - type: "container", - icon: "", presetStyle: { div: css` display: flex; @@ -243,8 +237,6 @@ test("deduplicate component presets for similarly named components", () => { [ "@webstudio/aria:ListItem", { - type: "container", - icon: "", presetStyle: { div: css` display: grid; @@ -301,8 +293,6 @@ test("expose preset classes to instances", () => { [ "Body", { - type: "container", - icon: "", presetStyle: { div: css` display: block; @@ -313,8 +303,6 @@ test("expose preset classes to instances", () => { [ "Box", { - type: "container", - icon: "", presetStyle: { div: css` display: flex; @@ -391,8 +379,6 @@ test("generate classes with instance and meta label", () => { [ "Body", { - type: "container", - icon: "", label: "body meta label", presetStyle: { div: css` @@ -404,8 +390,6 @@ test("generate classes with instance and meta label", () => { [ "Box", { - type: "container", - icon: "", label: "box meta label", presetStyle: { div: css` @@ -484,8 +468,6 @@ test("generate :root preset and user styles", () => { [ rootComponent, { - type: "container", - icon: "", label: "Global Root", presetStyle: { html: css` @@ -547,8 +529,6 @@ test("generate presets only for used tags", () => { [ "Box", { - type: "container", - icon: "", presetStyle: { div: css` display: block; diff --git a/packages/sdk/src/instances-utils.test.tsx b/packages/sdk/src/instances-utils.test.tsx index e84d6f777643..30e5ffaaff38 100644 --- a/packages/sdk/src/instances-utils.test.tsx +++ b/packages/sdk/src/instances-utils.test.tsx @@ -9,10 +9,6 @@ import { import type { WsComponentMeta } from "./schema/component-meta"; import type { Instance } from "./schema/instances"; -const createMeta = (meta?: Partial) => { - return { type: "container", label: "", icon: "", ...meta } as const; -}; - test("find all tree instances", () => { const { instances } = renderData( <$.Body ws:id="1"> @@ -80,9 +76,9 @@ test("get indexes within ancestors", () => { ); const metas = new Map([ - ["TabsList", createMeta({ indexWithinAncestor: "Tabs" })], - ["TabsTrigger", createMeta({ indexWithinAncestor: "TabsList" })], - ["TabsContent", createMeta({ indexWithinAncestor: "Tabs" })], + ["TabsList", { indexWithinAncestor: "Tabs" }], + ["TabsTrigger", { indexWithinAncestor: "TabsList" }], + ["TabsContent", { indexWithinAncestor: "Tabs" }], ]); expect(getIndexesWithinAncestors(metas, instances, ["body0"])).toEqual( new Map([ @@ -113,7 +109,7 @@ test("ignore ws:block-template when compute indexes within ancestors", () => { ); const metas = new Map([ - ["TabsTrigger", createMeta({ indexWithinAncestor: "Tabs" })], + ["TabsTrigger", { indexWithinAncestor: "Tabs" }], ]); expect(getIndexesWithinAncestors(metas, instances, ["body0"])).toEqual( new Map([