diff --git a/apps/designer/app/canvas/features/wrapper-component/selected-instance-connector.ts b/apps/designer/app/canvas/features/wrapper-component/selected-instance-connector.ts index 588f40f690..4c388d9324 100644 --- a/apps/designer/app/canvas/features/wrapper-component/selected-instance-connector.ts +++ b/apps/designer/app/canvas/features/wrapper-component/selected-instance-connector.ts @@ -1,5 +1,5 @@ import { useEffect } from "react"; -import type { Instance, Styles, UserProp } from "@webstudio-is/react-sdk"; +import type { Instance, PropsItem, Styles } from "@webstudio-is/react-sdk"; import { getBrowserStyle } from "@webstudio-is/react-sdk"; import { publish, subscribe, subscribeAll } from "~/shared/pubsub"; import { @@ -53,7 +53,7 @@ export const SelectedInstanceConnector = ({ instanceElementRef: { current: undefined | HTMLElement }; instance: Instance; instanceStyles: Styles; - instanceProps: undefined | UserProp[]; + instanceProps: undefined | PropsItem[]; }) => { useEffect(() => { const element = instanceElementRef.current; diff --git a/apps/designer/app/canvas/features/wrapper-component/wrapper-component.tsx b/apps/designer/app/canvas/features/wrapper-component/wrapper-component.tsx index 2532650512..355284fbf1 100644 --- a/apps/designer/app/canvas/features/wrapper-component/wrapper-component.tsx +++ b/apps/designer/app/canvas/features/wrapper-component/wrapper-component.tsx @@ -5,7 +5,7 @@ import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext import { type Instance, type OnChangeChildren, - type UserProp, + type PropsItem, renderWrapperComponentChildren, getComponent, idAttribute, @@ -44,7 +44,7 @@ const ContentEditable = ({ return ; }; -type UserProps = Record; +type UserProps = Record; type WrapperComponentDevProps = { instance: Instance; @@ -81,7 +81,7 @@ export const WrapperComponentDev = ({ } for (const item of instanceProps) { if (item.type !== "asset") { - result[item.prop] = item.value; + result[item.name] = item.value; } } return result; diff --git a/apps/designer/app/canvas/shared/instance.ts b/apps/designer/app/canvas/shared/instance.ts index d4620411c1..d2c3ad7be8 100644 --- a/apps/designer/app/canvas/shared/instance.ts +++ b/apps/designer/app/canvas/shared/instance.ts @@ -1,7 +1,7 @@ import { useEffect } from "react"; import { type Instance, - type UserProp, + type PropsItem, getComponentMeta, allUserPropsContainer, } from "@webstudio-is/react-sdk"; @@ -31,7 +31,7 @@ declare module "~/shared/pubsub" { insertInstance: { instance: Instance; dropTarget?: { parentId: Instance["id"]; position: number }; - props?: Array; + props?: Array; }; unselectInstance: undefined; } diff --git a/apps/designer/app/designer/features/props-panel/control.stories.tsx b/apps/designer/app/designer/features/props-panel/control.stories.tsx index 847eed1c35..aac3ec4a90 100644 --- a/apps/designer/app/designer/features/props-panel/control.stories.tsx +++ b/apps/designer/app/designer/features/props-panel/control.stories.tsx @@ -9,8 +9,9 @@ export const Primitive: ComponentStoryObj = { args: { component: "Image", userProp: { - prop: "src", + name: "src", id: "ddf20afe-65a8-478e-a52d-1be2d2f70830", + instanceId: "instanceId", type: "string", value: "", }, @@ -21,8 +22,9 @@ export const Options: ComponentStoryObj = { args: { component: "Image", userProp: { - prop: "loading", + name: "loading", id: "ddf20afe-65a8-478e-a52d-1be2d2f70830", + instanceId: "instanceId", type: "string", value: "", }, diff --git a/apps/designer/app/designer/features/props-panel/control.tsx b/apps/designer/app/designer/features/props-panel/control.tsx index ea47191d69..d541c6ac3d 100644 --- a/apps/designer/app/designer/features/props-panel/control.tsx +++ b/apps/designer/app/designer/features/props-panel/control.tsx @@ -1,7 +1,7 @@ import { getComponentMetaProps, type Instance, - type UserProp, + type PropsItem, } from "@webstudio-is/react-sdk"; import warnOnce from "warn-once"; import { @@ -179,7 +179,7 @@ const assertUnreachable = (_arg: never, errorMessage: string) => { type ControlProps = { component: Instance["component"]; - userProp: UserProp; + userProp: PropsItem; onChangePropValue: (value: UserPropValue) => void; setCssProperty: SetProperty; }; @@ -193,7 +193,7 @@ export function Control({ }: ControlProps) { const meta = getComponentMetaProps(component); - const argType = meta[userProp.prop]; + const argType = meta[userProp.name]; // argType can be undefined in case of new property created const defaultValue = argType?.defaultValue ?? ""; @@ -202,7 +202,7 @@ export function Control({ if (type == null) { warnOnce( true, - `No control type for prop "${userProp.prop}" component "${component}" found` + `No control type for prop "${userProp.name}" component "${component}" found` ); return ; } @@ -211,14 +211,14 @@ export function Control({ warnOnce( true, `Control type "${typeof type}" for prop "${ - userProp.prop + userProp.name }" component "${component}" is not a string` ); return ; } - if (component === "Image" && userProp.prop === "src") { + if (component === "Image" && userProp.name === "src") { const asset = userProp.type === "asset" ? userProp.value : null; return ( @@ -298,7 +298,7 @@ export function Control({ warnOnce( options == null, - `options is not an array of strings for prop: ${userProp.prop} component: ${component}` + `options is not an array of strings for prop: ${userProp.name} component: ${component}` ); const DEFAULT_OPTIONS: string[] = []; @@ -356,7 +356,7 @@ export function Control({ warnOnce( true, - `Control type "${type}" is not implemented for prop: "${userProp.prop}" in component "${component}"` + `Control type "${type}" is not implemented for prop: "${userProp.name}" in component "${component}"` ); return ; diff --git a/apps/designer/app/designer/features/props-panel/props-panel.stories.tsx b/apps/designer/app/designer/features/props-panel/props-panel.stories.tsx index fd8e8019aa..5276efc931 100644 --- a/apps/designer/app/designer/features/props-panel/props-panel.stories.tsx +++ b/apps/designer/app/designer/features/props-panel/props-panel.stories.tsx @@ -2,7 +2,7 @@ import type { ComponentStory } from "@storybook/react"; import { allUserPropsContainer, getComponentMetaProps, - type UserProp, + type PropsItem, } from "@webstudio-is/react-sdk"; import { PropsPanel } from "./props-panel"; @@ -16,7 +16,8 @@ export const NoProps: ComponentStory = () => { "1": [ { id: "disabled", - prop: "disabled", + instanceId: "instanceId", + name: "disabled", type: "boolean", value: true, }, @@ -73,12 +74,12 @@ const meta = getComponentMetaProps("Button"); export const AllProps: ComponentStory = () => { allUserPropsContainer.set({ - "3": Object.entries(meta).map(([prop, value]) => { + "3": Object.entries(meta).map(([name, value]) => { return { - id: prop, - prop, + id: name, + name, value: value?.defaultValue ?? "", - } as UserProp; + } as PropsItem; }), }); return ( diff --git a/apps/designer/app/designer/features/props-panel/props-panel.tsx b/apps/designer/app/designer/features/props-panel/props-panel.tsx index 5186909665..23bb9ec87c 100644 --- a/apps/designer/app/designer/features/props-panel/props-panel.tsx +++ b/apps/designer/app/designer/features/props-panel/props-panel.tsx @@ -5,7 +5,7 @@ import { getComponentMetaProps, useAllUserProps, type Instance, - type UserProp, + type PropsItem, } from "@webstudio-is/react-sdk"; import { type Publish } from "~/shared/pubsub"; import { Control } from "./control"; @@ -124,7 +124,7 @@ const Combobox = ({ }; type PropertyProps = { - userProp: UserProp; + userProp: PropsItem; component: Instance["component"]; onChangePropName: (name: string) => void; onChangePropValue: (value: UserPropValue) => void; @@ -146,12 +146,12 @@ const Property = ({ }: PropertyProps) => { const metaProps = getComponentMetaProps(component); - const argType = metaProps[userProp.prop as keyof typeof metaProps]; + const argType = metaProps[userProp.name as keyof typeof metaProps]; const isInvalid = - userProp.prop != null && - userProp.prop.length > 0 && + userProp.name != null && + userProp.name.length > 0 && typeof argType === "undefined" && - !userProp.prop.match(/^data-(.)+/); + !userProp.name.match(/^data-(.)+/); const allProps = Object.keys(metaProps).filter( (propName) => existingProps.includes(propName) === false @@ -167,12 +167,12 @@ const Property = ({ placeholder="Property" readOnly={true} state={isInvalid ? "invalid" : undefined} - value={userProp.prop} + value={userProp.name} /> ) : ( { if (name != null) { setError(undefined); @@ -195,7 +195,7 @@ const Property = ({ /> )} {isInvalid || error !== undefined ? ( - + ) : ( @@ -282,7 +282,7 @@ export const PropsPanel = ({ /> ); - const existingProps = userProps.map((userProp) => userProp.prop); + const existingProps = userProps.map((userProp) => userProp.name); return ( diff --git a/apps/designer/app/designer/features/props-panel/use-props-logic.test.ts b/apps/designer/app/designer/features/props-panel/use-props-logic.test.ts index 9c96f37c97..66b27a5211 100644 --- a/apps/designer/app/designer/features/props-panel/use-props-logic.test.ts +++ b/apps/designer/app/designer/features/props-panel/use-props-logic.test.ts @@ -27,7 +27,7 @@ describe("usePropsLogic", () => { ); expect(result.current.userProps.length).toEqual(1); expect(result.current.userProps[0]).toMatchObject({ - prop: "href", + name: "href", value: "", }); }); @@ -50,11 +50,11 @@ describe("usePropsLogic", () => { }) ); expect(res1.current.userProps[0]).toMatchObject({ - prop: "tag", + name: "tag", value: "h1", }); expect(res2.current.userProps[0]).toMatchObject({ - prop: "type", + name: "type", value: "submit", }); }); @@ -70,7 +70,7 @@ describe("usePropsLogic", () => { ); expect(result.current.userProps.length).toEqual(1); expect(result.current.userProps[0]).toMatchObject({ - prop: "type", + name: "type", value: "submit", }); }); @@ -81,7 +81,8 @@ describe("usePropsLogic", () => { props: [ { id: "default", - prop: "type", + instanceId: "instanceId", + name: "type", type: "string", value: "submit", }, @@ -93,7 +94,7 @@ describe("usePropsLogic", () => { ); expect(result.current.userProps.length).toEqual(1); expect(result.current.userProps[0]).toMatchObject({ - prop: "type", + name: "type", value: "submit", }); }); @@ -115,7 +116,7 @@ describe("usePropsLogic", () => { }); expect(result.current.userProps.length).toEqual(2); - expect(result.current.userProps[1]).toMatchObject({ prop: "", value: "" }); + expect(result.current.userProps[1]).toMatchObject({ name: "", value: "" }); }); test("should respect initialProps ordering", () => { @@ -124,35 +125,40 @@ describe("usePropsLogic", () => { props: [ { id: "22", - prop: "aria-label", + instanceId: "instanceId", + name: "aria-label", type: "string", value: "https://example.com", required: false, }, { id: "0", - prop: "alt", + instanceId: "instanceId", + name: "alt", type: "string", value: "alt text", required: true, }, { id: "1", - prop: "width", + instanceId: "instanceId", + name: "width", type: "number", value: 101, required: false, }, { id: "33", - prop: "title", + instanceId: "instanceId", + name: "title", type: "string", value: "title text", required: true, }, { id: "2", - prop: "src", + instanceId: "instanceId", + name: "src", type: "string", value: "https://example.com", required: true, @@ -166,7 +172,7 @@ describe("usePropsLogic", () => { const imgMeta = getComponentMeta("Image"); - const propNames = result.current.userProps.map((userProp) => userProp.prop); + const propNames = result.current.userProps.map((userProp) => userProp.name); expect(imgMeta.initialProps).toEqual( propNames.slice(0, imgMeta.initialProps?.length ?? 0) @@ -175,9 +181,9 @@ describe("usePropsLogic", () => { expect(propNames.slice(imgMeta.initialProps?.length ?? 0)).toEqual( result.current.userProps .filter( - (userProp) => imgMeta.initialProps?.includes(userProp.prop) === false + (userProp) => imgMeta.initialProps?.includes(userProp.name) === false ) - .map((userProp) => userProp.prop) + .map((userProp) => userProp.name) ); }); @@ -194,7 +200,8 @@ describe("usePropsLogic", () => { expect( result.current.isRequired({ id: "2", - prop: "src", + instanceId: "instanceId", + name: "src", type: "string", value: "https://example.com", required: false, @@ -215,7 +222,8 @@ describe("usePropsLogic", () => { expect( result.current.isRequired({ id: "2", - prop: "arial-label", + instanceId: "instanceId", + name: "arial-label", type: "string", value: "https://example.com", required: true, @@ -225,7 +233,8 @@ describe("usePropsLogic", () => { expect( result.current.isRequired({ id: "2", - prop: "arial-label", + instanceId: "instanceId", + name: "arial-label", type: "string", value: "https://example.com", required: false, diff --git a/apps/designer/app/designer/features/props-panel/use-props-logic.ts b/apps/designer/app/designer/features/props-panel/use-props-logic.ts index dddfa34cb4..7a1c355dd0 100644 --- a/apps/designer/app/designer/features/props-panel/use-props-logic.ts +++ b/apps/designer/app/designer/features/props-panel/use-props-logic.ts @@ -2,7 +2,8 @@ import { useMemo, useState } from "react"; import ObjectId from "bson-objectid"; import warnOnce from "warn-once"; import type { - UserProp, + Instance, + PropsItem, MetaProps, ComponentName, } from "@webstudio-is/react-sdk"; @@ -12,7 +13,7 @@ import { } from "@webstudio-is/react-sdk"; import type { SelectedInstanceData } from "@webstudio-is/project"; -export type UserPropValue = UserProp extends infer T +export type UserPropValue = PropsItem extends infer T ? T extends { value: unknown; type: unknown } ? { value: T["value"]; type: T["type"] } : never @@ -73,20 +74,25 @@ const getRequiredPropsList = (component: ComponentName) => { }; type UsePropsLogic = { - props: UserProp[]; + props: PropsItem[]; selectedInstanceData: SelectedInstanceData; - updateProps: (update: UserProp) => void; - deleteProp: (id: UserProp["id"]) => void; + updateProps: (update: PropsItem) => void; + deleteProp: (id: PropsItem["id"]) => void; }; -const getPropsItemFromMetaProps = (metaProps: MetaProps, name: string) => { +const getPropsItemFromMetaProps = ( + instanceId: Instance["id"], + metaProps: MetaProps, + name: string +) => { const metaPropValue = metaProps[name]; if (metaPropValue === undefined) { return undefined; } return { id: ObjectId().toString(), - prop: name, + instanceId, + name, ...getValueFromPropMeta(metaPropValue), }; }; @@ -100,7 +106,7 @@ export const usePropsLogic = ({ updateProps, deleteProp, }: UsePropsLogic) => { - const { component } = selectedInstanceData; + const { id: instanceId, component } = selectedInstanceData; const metaProps = useMemo( () => getComponentMetaProps(component), @@ -110,24 +116,24 @@ export const usePropsLogic = ({ () => getRequiredPropsList(component), [component] ); - const requiredPropsByName = new Map(); + const requiredPropsByName = new Map(); for (const name of requiredPropsList) { - const propsItem = getPropsItemFromMetaProps(metaProps, name); + const propsItem = getPropsItemFromMetaProps(instanceId, metaProps, name); if (propsItem) { requiredPropsByName.set(name, propsItem); } } - const [addedProps, setAddedProps] = useState([]); - const addedPropsById = new Map(); + const [addedProps, setAddedProps] = useState([]); + const addedPropsById = new Map(); for (const propsItem of addedProps) { addedPropsById.set(propsItem.id, propsItem); } - const propsById = new Map(); + const propsById = new Map(); for (const propsItem of props) { - if (requiredPropsByName.has(propsItem.prop)) { - requiredPropsByName.set(propsItem.prop, propsItem); + if (requiredPropsByName.has(propsItem.name)) { + requiredPropsByName.set(propsItem.name, propsItem); continue; } if (addedPropsById.has(propsItem.id)) { @@ -145,20 +151,23 @@ export const usePropsLogic = ({ ...addedPropsById.values(), ]; - const handleChangePropName = (propsItem: UserProp, name: string) => { + const handleChangePropName = (propsItem: PropsItem, name: string) => { // prevent changing name of required props if (isRequired(propsItem)) { return; } const typedValue = getValueFromPropMeta(metaProps[name]); - updateProps({ id: propsItem.id, prop: name, ...typedValue }); + updateProps({ id: propsItem.id, instanceId, name, ...typedValue }); }; - const handleChangePropValue = (propsItem: UserProp, value: UserPropValue) => { + const handleChangePropValue = ( + propsItem: PropsItem, + value: UserPropValue + ) => { updateProps({ ...propsItem, ...value }); }; - const handleDeleteProp = (propsItem: UserProp) => { + const handleDeleteProp = (propsItem: PropsItem) => { // required prop should never be deleted if (isRequired(propsItem)) { return; @@ -173,15 +182,16 @@ export const usePropsLogic = ({ ...prev, { id: ObjectId().toString(), - prop: "", + instanceId, + name: "", type: "string", value: "", }, ]); }; - const isRequired = (propsItem: UserProp) => { - return propsItem.required || requiredPropsList.includes(propsItem.prop); + const isRequired = (propsItem: PropsItem) => { + return propsItem.required || requiredPropsList.includes(propsItem.name); }; return { diff --git a/apps/designer/app/shared/copy-paste/serialize.ts b/apps/designer/app/shared/copy-paste/serialize.ts index 50c1a19038..e69c9db8ff 100644 --- a/apps/designer/app/shared/copy-paste/serialize.ts +++ b/apps/designer/app/shared/copy-paste/serialize.ts @@ -1,11 +1,11 @@ -import { Instance, UserProps } from "@webstudio-is/react-sdk"; +import { Instance, Props } from "@webstudio-is/react-sdk"; import { z } from "zod"; const TYPE = "@webstudio/instance/v0.1" as const; const InstanceCopyData = z.object({ instance: Instance, - props: UserProps.optional(), + props: Props.optional(), }); export type InstanceCopyData = z.infer; diff --git a/apps/designer/app/shared/copy-paste/use-instance-copy-paste.ts b/apps/designer/app/shared/copy-paste/use-instance-copy-paste.ts index fcbae1d2f8..51bb85ce52 100644 --- a/apps/designer/app/shared/copy-paste/use-instance-copy-paste.ts +++ b/apps/designer/app/shared/copy-paste/use-instance-copy-paste.ts @@ -1,5 +1,5 @@ import { utils } from "@webstudio-is/project"; -import type { Instance, UserProp } from "@webstudio-is/react-sdk"; +import type { Instance, PropsItem } from "@webstudio-is/react-sdk"; import { useEffect, useMemo } from "react"; import { type InstanceCopyData, serialize, deserialize } from "./serialize"; @@ -38,7 +38,7 @@ const isInstanceClipboardEvent = ( type Props = { selectedInstanceData?: InstanceCopyData | undefined; allowAnyTarget?: boolean; - onPaste: (instance: Instance, props?: UserProp[]) => void; + onPaste: (instance: Instance, props?: PropsItem[]) => void; onCut: (instance: Instance) => void; }; diff --git a/packages/project/src/db/props.ts b/packages/project/src/db/props.ts index 212451485a..dbc5467f76 100644 --- a/packages/project/src/db/props.ts +++ b/packages/project/src/db/props.ts @@ -3,8 +3,7 @@ import { type Tree, type AllUserProps, type InstanceProps, - type PropsItem, - Props, + StoredProps, } from "@webstudio-is/react-sdk"; import { applyPatches, type Patch } from "immer"; import { prisma } from "@webstudio-is/prisma-client"; @@ -19,7 +18,7 @@ export const loadByTreeId = async (treeId: Tree["id"]) => { return []; } - const props = Props.parse(JSON.parse(tree.props)); + const props = StoredProps.parse(JSON.parse(tree.props)); // Fin all assetId in all props const assetIds: string[] = []; @@ -64,7 +63,8 @@ export const loadByTreeId = async (treeId: Tree["id"]) => { if (asset) { instanceProps.props.push({ id: propsItem.id, - prop: propsItem.name, + instanceId: propsItem.instanceId, + name: propsItem.name, required: propsItem.required, type: propsItem.type, value: asset, @@ -77,13 +77,7 @@ export const loadByTreeId = async (treeId: Tree["id"]) => { continue; } - instanceProps.props.push({ - id: propsItem.id, - prop: propsItem.name, - required: propsItem.required, - type: propsItem.type, - value: propsItem.value, - } as InstanceProps["props"][number]); + instanceProps.props.push(propsItem); } return Array.from(instancePropsMap.values()); @@ -107,28 +101,21 @@ export const patch = async ( patches ); - const props: Props = []; + const props: StoredProps = []; for (const [instanceId, instanceProps] of Object.entries(nextProps)) { - for (const prop of instanceProps) { - if (prop.type === "asset") { + for (const propsItem of instanceProps) { + if (propsItem.type === "asset") { props.push({ - id: prop.id, + id: propsItem.id, instanceId, - name: prop.prop, - required: prop.required, - type: prop.type, - value: prop.value.id, + name: propsItem.name, + required: propsItem.required, + type: propsItem.type, + value: propsItem.value.id, }); continue; } - props.push({ - id: prop.id, - instanceId, - name: prop.prop, - required: prop.required, - type: prop.type, - value: prop.value, - } as PropsItem); + props.push(propsItem); } } diff --git a/packages/project/src/shared/props/clone-user-props.ts b/packages/project/src/shared/props/clone-user-props.ts index 002c5c73ce..251622bba3 100644 --- a/packages/project/src/shared/props/clone-user-props.ts +++ b/packages/project/src/shared/props/clone-user-props.ts @@ -1,5 +1,5 @@ -import type { UserProp } from "@webstudio-is/react-sdk"; +import type { PropsItem } from "@webstudio-is/react-sdk"; import ObjectId from "bson-objectid"; -export const cloneUserProps = (props: Array): Array => +export const cloneUserProps = (props: Array): Array => props.map((prop) => ({ ...prop, id: ObjectId().toString() })); diff --git a/packages/react-sdk/src/db/props.ts b/packages/react-sdk/src/db/props.ts index a6cfe00523..144456e79e 100644 --- a/packages/react-sdk/src/db/props.ts +++ b/packages/react-sdk/src/db/props.ts @@ -1,4 +1,5 @@ import { z } from "zod"; +import { Asset } from "@webstudio-is/asset-uploader"; const basePropsItem = { id: z.string(), @@ -7,7 +8,7 @@ const basePropsItem = { required: z.optional(z.boolean()), }; -export const PropsItem = z.discriminatedUnion("type", [ +const SharedPropsItem = z.union([ z.object({ ...basePropsItem, type: z.literal("number"), @@ -23,14 +24,33 @@ export const PropsItem = z.discriminatedUnion("type", [ type: z.literal("boolean"), value: z.boolean(), }), +]); + +export const StoredPropsItem = z.union([ + SharedPropsItem, z.object({ ...basePropsItem, type: z.literal("asset"), - // In database we hold asset.id + // asset.id is stored in database value: z.string(), }), ]); +export type StoredPropsItem = z.infer; + +export const StoredProps = z.array(StoredPropsItem); + +export type StoredProps = z.infer; + +export const PropsItem = z.union([ + SharedPropsItem, + z.object({ + ...basePropsItem, + type: z.literal("asset"), + value: Asset, + }), +]); + export type PropsItem = z.infer; export const Props = z.array(PropsItem); diff --git a/packages/react-sdk/src/db/types.ts b/packages/react-sdk/src/db/types.ts index c20872087d..42dc55e754 100644 --- a/packages/react-sdk/src/db/types.ts +++ b/packages/react-sdk/src/db/types.ts @@ -1,7 +1,6 @@ import type { InstanceProps as DbInstanceProps } from "@webstudio-is/prisma-client"; -import type { UserProp } from "../user-props"; import type { Instance } from "./instance"; -import type { Props } from "./props"; +import type { Props, PropsItem } from "./props"; import type { PresetStyles, Styles } from "./style"; export type Tree = { @@ -13,5 +12,5 @@ export type Tree = { }; export type InstanceProps = Omit & { - props: Array; + props: Array; }; diff --git a/packages/react-sdk/src/user-props/all-user-props.ts b/packages/react-sdk/src/user-props/all-user-props.ts index 9b714cd89d..4ae128e4cc 100644 --- a/packages/react-sdk/src/user-props/all-user-props.ts +++ b/packages/react-sdk/src/user-props/all-user-props.ts @@ -1,11 +1,10 @@ import { useRef } from "react"; import { atom } from "nanostores"; import { useStore } from "@nanostores/react"; -import type { InstanceProps, Instance } from "../db"; -import { UserProp } from "./schema"; +import type { InstanceProps, Instance, PropsItem } from "../db"; export type AllUserProps = { - [id: Instance["id"]]: UserProp[]; + [id: Instance["id"]]: PropsItem[]; }; export const allUserPropsContainer = atom({}); diff --git a/packages/react-sdk/src/user-props/index.ts b/packages/react-sdk/src/user-props/index.ts index 0c44558bc4..e8e6330a95 100644 --- a/packages/react-sdk/src/user-props/index.ts +++ b/packages/react-sdk/src/user-props/index.ts @@ -1,3 +1,2 @@ export * from "./all-user-props"; export * from "./use-user-props"; -export * from "./schema"; diff --git a/packages/react-sdk/src/user-props/schema.ts b/packages/react-sdk/src/user-props/schema.ts deleted file mode 100644 index af29ce6bde..0000000000 --- a/packages/react-sdk/src/user-props/schema.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { z } from "zod"; -import { Asset } from "@webstudio-is/asset-uploader"; - -const baseUserProps = { - id: z.string(), - prop: z.string(), - required: z.optional(z.boolean()), -}; - -export const UserProp = z.discriminatedUnion("type", [ - z.object({ - ...baseUserProps, - type: z.literal("number"), - value: z.number(), - }), - z.object({ - ...baseUserProps, - type: z.literal("string"), - value: z.string(), - }), - z.object({ - ...baseUserProps, - type: z.literal("boolean"), - value: z.boolean(), - }), - z.object({ - ...baseUserProps, - type: z.literal("asset"), - value: Asset, - }), -]); - -export const UserProps = z.array(UserProp); - -export type UserProp = z.infer; diff --git a/packages/react-sdk/src/user-props/use-user-props-asset.ts b/packages/react-sdk/src/user-props/use-user-props-asset.ts index 9a2e48deab..5f7810430b 100644 --- a/packages/react-sdk/src/user-props/use-user-props-asset.ts +++ b/packages/react-sdk/src/user-props/use-user-props-asset.ts @@ -1,6 +1,5 @@ import { useMemo } from "react"; -import { type Instance } from "../db"; -import { type UserProp } from "./schema"; +import { PropsItem, type Instance } from "../db"; import { useAllUserProps } from "./all-user-props"; import type { Asset } from "@webstudio-is/asset-uploader"; @@ -9,7 +8,7 @@ import type { Asset } from "@webstudio-is/asset-uploader"; */ export const useUserPropsAsset = ( instanceId: Instance["id"], - propName: UserProp["prop"] + propName: PropsItem["name"] ): Asset | undefined => { const allUserProps = useAllUserProps(); @@ -18,7 +17,7 @@ export const useUserPropsAsset = ( if (propsData == null) { return undefined; } - const prop = propsData.find((prop) => prop.prop === propName); + const prop = propsData.find((prop) => prop.name === propName); if (prop == null) { return undefined; diff --git a/packages/react-sdk/src/user-props/use-user-props.ts b/packages/react-sdk/src/user-props/use-user-props.ts index 02f4716b5b..2d3a903555 100644 --- a/packages/react-sdk/src/user-props/use-user-props.ts +++ b/packages/react-sdk/src/user-props/use-user-props.ts @@ -1,9 +1,8 @@ import { useMemo } from "react"; -import { type Instance } from "../db"; -import { type UserProp } from "./schema"; +import type { Instance, PropsItem } from "../db"; import { useAllUserProps } from "./all-user-props"; -type UserProps = { [prop: UserProp["prop"]]: string | number | boolean }; +type UserProps = { [name: PropsItem["name"]]: string | number | boolean }; /** * User props mapped in prop:value format, @@ -21,7 +20,7 @@ export const useUserProps = (instanceId: Instance["id"]) => { for (const userProp of propsData) { if (userProp.type !== "asset") { - result[userProp.prop] = userProp.value; + result[userProp.name] = userProp.value; } }