@webstudio-is/react-sdk 0.82.0 → 0.83.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/LICENSE +661 -21
  2. package/lib/cjs/components/component-meta.js +5 -0
  3. package/lib/cjs/components/components-utils.js +1 -0
  4. package/lib/cjs/css/index.js +0 -1
  5. package/lib/cjs/embed-template.js +30 -1
  6. package/lib/cjs/expression.js +47 -4
  7. package/lib/cjs/index.js +1 -0
  8. package/lib/cjs/props.js +6 -1
  9. package/lib/cjs/tree/root.js +1 -0
  10. package/lib/cjs/tree/webstudio-component.js +24 -10
  11. package/lib/components/component-meta.js +5 -0
  12. package/lib/components/components-utils.js +1 -0
  13. package/lib/css/index.js +0 -1
  14. package/lib/embed-template.js +38 -1
  15. package/lib/expression.js +47 -4
  16. package/lib/index.js +2 -0
  17. package/lib/props.js +6 -1
  18. package/lib/tree/create-elements-tree.js +3 -1
  19. package/lib/tree/root.js +8 -2
  20. package/lib/tree/webstudio-component.js +25 -11
  21. package/lib/types/app/root.d.ts +1 -2
  22. package/lib/types/components/component-meta.d.ts +11 -8
  23. package/lib/types/context.d.ts +1 -1
  24. package/lib/types/css/index.d.ts +0 -1
  25. package/lib/types/css/normalize.d.ts +47 -47
  26. package/lib/types/embed-template.d.ts +14 -1
  27. package/lib/types/expression.d.ts +3 -2
  28. package/lib/types/index.d.ts +1 -1
  29. package/lib/types/props.d.ts +1 -0
  30. package/lib/types/tree/create-elements-tree.d.ts +5 -5
  31. package/lib/types/tree/root.d.ts +4 -4
  32. package/lib/types/tree/webstudio-component.d.ts +15 -7
  33. package/package.json +14 -15
  34. package/src/components/component-meta.ts +5 -0
  35. package/src/context.tsx +1 -0
  36. package/src/css/index.ts +0 -1
  37. package/src/embed-template.test.ts +77 -1
  38. package/src/embed-template.ts +34 -1
  39. package/src/expression.test.ts +74 -6
  40. package/src/expression.ts +55 -2
  41. package/src/index.ts +1 -0
  42. package/src/props.ts +6 -1
  43. package/src/tree/create-elements-tree.tsx +17 -5
  44. package/src/tree/root.ts +14 -3
  45. package/src/tree/webstudio-component.tsx +41 -14
  46. package/lib/cjs/css/get-browser-style.js +0 -83
  47. package/lib/css/get-browser-style.js +0 -65
  48. package/lib/types/css/get-browser-style.d.ts +0 -2
  49. package/src/css/get-browser-style.ts +0 -81
@@ -218,13 +218,16 @@ declare const EmbedTemplateProp: z.ZodUnion<[z.ZodObject<{
218
218
  name: z.ZodString;
219
219
  value: z.ZodArray<z.ZodObject<{
220
220
  type: z.ZodLiteral<"execute">;
221
+ args: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
221
222
  code: z.ZodString;
222
223
  }, "strip", z.ZodTypeAny, {
223
224
  code: string;
224
225
  type: "execute";
226
+ args?: string[] | undefined;
225
227
  }, {
226
228
  code: string;
227
229
  type: "execute";
230
+ args?: string[] | undefined;
228
231
  }>, "many">;
229
232
  }, "strip", z.ZodTypeAny, {
230
233
  name: string;
@@ -232,6 +235,7 @@ declare const EmbedTemplateProp: z.ZodUnion<[z.ZodObject<{
232
235
  value: {
233
236
  code: string;
234
237
  type: "execute";
238
+ args?: string[] | undefined;
235
239
  }[];
236
240
  }, {
237
241
  name: string;
@@ -239,6 +243,7 @@ declare const EmbedTemplateProp: z.ZodUnion<[z.ZodObject<{
239
243
  value: {
240
244
  code: string;
241
245
  type: "execute";
246
+ args?: string[] | undefined;
242
247
  }[];
243
248
  }>]>;
244
249
  type EmbedTemplateProp = z.infer<typeof EmbedTemplateProp>;
@@ -2390,6 +2395,7 @@ export declare const generateDataFromEmbedTemplate: (treeTemplate: ({
2390
2395
  value: {
2391
2396
  code: string;
2392
2397
  type: "execute";
2398
+ args: string[];
2393
2399
  }[];
2394
2400
  id: string;
2395
2401
  instanceId: string;
@@ -2645,8 +2651,15 @@ export declare const generateDataFromEmbedTemplate: (treeTemplate: ({
2645
2651
  styleSourceId: string;
2646
2652
  breakpointId: string;
2647
2653
  state?: string | undefined;
2648
- property: "filter" | "float" | "fontFamily" | "width" | "height" | "clip" | "top" | "right" | `--${string}` | "accentColor" | "alignContent" | "alignItems" | "alignSelf" | "alignTracks" | "animationComposition" | "animationDelay" | "animationDirection" | "animationDuration" | "animationFillMode" | "animationIterationCount" | "animationName" | "animationPlayState" | "animationTimingFunction" | "animationTimeline" | "appearance" | "aspectRatio" | "backdropFilter" | "backfaceVisibility" | "backgroundAttachment" | "backgroundBlendMode" | "backgroundClip" | "backgroundColor" | "backgroundImage" | "backgroundOrigin" | "backgroundPosition" | "backgroundPositionX" | "backgroundPositionY" | "backgroundRepeat" | "backgroundSize" | "blockOverflow" | "blockSize" | "borderBlockColor" | "borderBlockStyle" | "borderBlockWidth" | "borderBlockEndColor" | "borderBlockEndStyle" | "borderBlockEndWidth" | "borderBlockStartColor" | "borderBlockStartStyle" | "borderBlockStartWidth" | "borderBottomColor" | "borderBottomLeftRadius" | "borderBottomRightRadius" | "borderBottomStyle" | "borderBottomWidth" | "borderCollapse" | "borderEndEndRadius" | "borderEndStartRadius" | "borderImageOutset" | "borderImageRepeat" | "borderImageSlice" | "borderImageSource" | "borderImageWidth" | "borderInlineColor" | "borderInlineStyle" | "borderInlineWidth" | "borderInlineEndColor" | "borderInlineEndStyle" | "borderInlineEndWidth" | "borderInlineStartColor" | "borderInlineStartStyle" | "borderInlineStartWidth" | "borderLeftColor" | "borderLeftStyle" | "borderLeftWidth" | "borderRightColor" | "borderRightStyle" | "borderRightWidth" | "borderSpacing" | "borderStartEndRadius" | "borderStartStartRadius" | "borderTopColor" | "borderTopLeftRadius" | "borderTopRightRadius" | "borderTopStyle" | "borderTopWidth" | "bottom" | "boxDecorationBreak" | "boxShadow" | "boxSizing" | "breakAfter" | "breakBefore" | "breakInside" | "captionSide" | "caretColor" | "caretShape" | "clear" | "clipPath" | "color" | "printColorAdjust" | "colorScheme" | "columnCount" | "columnFill" | "columnGap" | "columnRuleColor" | "columnRuleStyle" | "columnRuleWidth" | "columnSpan" | "columnWidth" | "contain" | "containIntrinsicBlockSize" | "containIntrinsicHeight" | "containIntrinsicInlineSize" | "containIntrinsicWidth" | "content" | "contentVisibility" | "counterIncrement" | "counterReset" | "counterSet" | "cursor" | "direction" | "display" | "emptyCells" | "flexBasis" | "flexDirection" | "flexGrow" | "flexShrink" | "flexWrap" | "fontFeatureSettings" | "fontKerning" | "fontLanguageOverride" | "fontOpticalSizing" | "fontVariationSettings" | "fontSize" | "fontSizeAdjust" | "fontStretch" | "fontStyle" | "fontSynthesis" | "fontVariant" | "fontVariantAlternates" | "fontVariantCaps" | "fontVariantEastAsian" | "fontVariantLigatures" | "fontVariantNumeric" | "fontVariantPosition" | "fontWeight" | "forcedColorAdjust" | "gridAutoColumns" | "gridAutoFlow" | "gridAutoRows" | "gridColumnEnd" | "gridColumnStart" | "gridRowEnd" | "gridRowStart" | "gridTemplateAreas" | "gridTemplateColumns" | "gridTemplateRows" | "hangingPunctuation" | "hyphenateCharacter" | "hyphens" | "imageOrientation" | "imageRendering" | "imageResolution" | "initialLetter" | "initialLetterAlign" | "inlineSize" | "inputSecurity" | "insetBlockEnd" | "insetBlockStart" | "insetInlineEnd" | "insetInlineStart" | "isolation" | "justifyContent" | "justifyItems" | "justifySelf" | "justifyTracks" | "left" | "letterSpacing" | "lineBreak" | "lineClamp" | "lineHeight" | "lineHeightStep" | "listStyleImage" | "listStylePosition" | "listStyleType" | "marginBlockEnd" | "marginBlockStart" | "marginBottom" | "marginInlineEnd" | "marginInlineStart" | "marginLeft" | "marginRight" | "marginTop" | "marginTrim" | "maskBorderMode" | "maskBorderOutset" | "maskBorderRepeat" | "maskBorderSlice" | "maskBorderSource" | "maskBorderWidth" | "maskClip" | "maskComposite" | "maskImage" | "maskMode" | "maskOrigin" | "maskPosition" | "maskRepeat" | "maskSize" | "maskType" | "masonryAutoFlow" | "mathDepth" | "mathShift" | "mathStyle" | "maxBlockSize" | "maxHeight" | "maxInlineSize" | "maxLines" | "maxWidth" | "minBlockSize" | "minHeight" | "minInlineSize" | "minWidth" | "mixBlendMode" | "objectFit" | "objectPosition" | "offsetAnchor" | "offsetDistance" | "offsetPath" | "offsetPosition" | "offsetRotate" | "opacity" | "order" | "orphans" | "outlineColor" | "outlineOffset" | "outlineStyle" | "outlineWidth" | "overflow" | "overflowAnchor" | "overflowBlock" | "overflowClipMargin" | "overflowInline" | "overflowWrap" | "overflowX" | "overflowY" | "overscrollBehavior" | "overscrollBehaviorBlock" | "overscrollBehaviorInline" | "overscrollBehaviorX" | "overscrollBehaviorY" | "paddingBlockEnd" | "paddingBlockStart" | "paddingBottom" | "paddingInlineEnd" | "paddingInlineStart" | "paddingLeft" | "paddingRight" | "paddingTop" | "pageBreakAfter" | "pageBreakBefore" | "pageBreakInside" | "paintOrder" | "perspective" | "perspectiveOrigin" | "pointerEvents" | "position" | "quotes" | "resize" | "rotate" | "rowGap" | "rubyAlign" | "rubyMerge" | "rubyPosition" | "scale" | "scrollbarColor" | "scrollbarGutter" | "scrollbarWidth" | "scrollBehavior" | "scrollMarginBlockStart" | "scrollMarginBlockEnd" | "scrollMarginBottom" | "scrollMarginInlineStart" | "scrollMarginInlineEnd" | "scrollMarginLeft" | "scrollMarginRight" | "scrollMarginTop" | "scrollPaddingBlockStart" | "scrollPaddingBlockEnd" | "scrollPaddingBottom" | "scrollPaddingInlineStart" | "scrollPaddingInlineEnd" | "scrollPaddingLeft" | "scrollPaddingRight" | "scrollPaddingTop" | "scrollSnapAlign" | "scrollSnapStop" | "scrollSnapType" | "scrollTimelineAxis" | "scrollTimelineName" | "shapeImageThreshold" | "shapeMargin" | "shapeOutside" | "tabSize" | "tableLayout" | "textAlign" | "textAlignLast" | "textCombineUpright" | "textDecorationColor" | "textDecorationLine" | "textDecorationSkip" | "textDecorationSkipInk" | "textDecorationStyle" | "textDecorationThickness" | "textEmphasisColor" | "textEmphasisPosition" | "textEmphasisStyle" | "textIndent" | "textJustify" | "textOrientation" | "textOverflow" | "textRendering" | "textShadow" | "textSizeAdjust" | "textTransform" | "textUnderlineOffset" | "textUnderlinePosition" | "touchAction" | "transform" | "transformBox" | "transformOrigin" | "transformStyle" | "transitionDelay" | "transitionDuration" | "transitionProperty" | "transitionTimingFunction" | "translate" | "unicodeBidi" | "userSelect" | "verticalAlign" | "visibility" | "whiteSpace" | "widows" | "willChange" | "wordBreak" | "wordSpacing" | "wordWrap" | "writingMode" | "zIndex";
2654
+ property: "filter" | "float" | "fontFamily" | "width" | "height" | "clip" | "top" | "right" | `--${string}` | "WebkitFontSmoothing" | "MozOsxFontSmoothing" | "accentColor" | "alignContent" | "alignItems" | "alignSelf" | "alignTracks" | "animationComposition" | "animationDelay" | "animationDirection" | "animationDuration" | "animationFillMode" | "animationIterationCount" | "animationName" | "animationPlayState" | "animationTimingFunction" | "animationTimeline" | "appearance" | "aspectRatio" | "backdropFilter" | "backfaceVisibility" | "backgroundAttachment" | "backgroundBlendMode" | "backgroundClip" | "backgroundColor" | "backgroundImage" | "backgroundOrigin" | "backgroundPosition" | "backgroundPositionX" | "backgroundPositionY" | "backgroundRepeat" | "backgroundSize" | "blockOverflow" | "blockSize" | "borderBlockColor" | "borderBlockStyle" | "borderBlockWidth" | "borderBlockEndColor" | "borderBlockEndStyle" | "borderBlockEndWidth" | "borderBlockStartColor" | "borderBlockStartStyle" | "borderBlockStartWidth" | "borderBottomColor" | "borderBottomLeftRadius" | "borderBottomRightRadius" | "borderBottomStyle" | "borderBottomWidth" | "borderCollapse" | "borderEndEndRadius" | "borderEndStartRadius" | "borderImageOutset" | "borderImageRepeat" | "borderImageSlice" | "borderImageSource" | "borderImageWidth" | "borderInlineColor" | "borderInlineStyle" | "borderInlineWidth" | "borderInlineEndColor" | "borderInlineEndStyle" | "borderInlineEndWidth" | "borderInlineStartColor" | "borderInlineStartStyle" | "borderInlineStartWidth" | "borderLeftColor" | "borderLeftStyle" | "borderLeftWidth" | "borderRightColor" | "borderRightStyle" | "borderRightWidth" | "borderSpacing" | "borderStartEndRadius" | "borderStartStartRadius" | "borderTopColor" | "borderTopLeftRadius" | "borderTopRightRadius" | "borderTopStyle" | "borderTopWidth" | "bottom" | "boxDecorationBreak" | "boxShadow" | "boxSizing" | "breakAfter" | "breakBefore" | "breakInside" | "captionSide" | "caretColor" | "caretShape" | "clear" | "clipPath" | "color" | "printColorAdjust" | "colorScheme" | "columnCount" | "columnFill" | "columnGap" | "columnRuleColor" | "columnRuleStyle" | "columnRuleWidth" | "columnSpan" | "columnWidth" | "contain" | "containIntrinsicBlockSize" | "containIntrinsicHeight" | "containIntrinsicInlineSize" | "containIntrinsicWidth" | "content" | "contentVisibility" | "counterIncrement" | "counterReset" | "counterSet" | "cursor" | "direction" | "display" | "emptyCells" | "flexBasis" | "flexDirection" | "flexGrow" | "flexShrink" | "flexWrap" | "fontFeatureSettings" | "fontKerning" | "fontLanguageOverride" | "fontOpticalSizing" | "fontVariationSettings" | "fontSize" | "fontSizeAdjust" | "fontStretch" | "fontStyle" | "fontSynthesis" | "fontVariant" | "fontVariantAlternates" | "fontVariantCaps" | "fontVariantEastAsian" | "fontVariantLigatures" | "fontVariantNumeric" | "fontVariantPosition" | "fontWeight" | "forcedColorAdjust" | "gridAutoColumns" | "gridAutoFlow" | "gridAutoRows" | "gridColumnEnd" | "gridColumnStart" | "gridRowEnd" | "gridRowStart" | "gridTemplateAreas" | "gridTemplateColumns" | "gridTemplateRows" | "hangingPunctuation" | "hyphenateCharacter" | "hyphens" | "imageOrientation" | "imageRendering" | "imageResolution" | "initialLetter" | "initialLetterAlign" | "inlineSize" | "inputSecurity" | "insetBlockEnd" | "insetBlockStart" | "insetInlineEnd" | "insetInlineStart" | "isolation" | "justifyContent" | "justifyItems" | "justifySelf" | "justifyTracks" | "left" | "letterSpacing" | "lineBreak" | "lineClamp" | "lineHeight" | "lineHeightStep" | "listStyleImage" | "listStylePosition" | "listStyleType" | "marginBlockEnd" | "marginBlockStart" | "marginBottom" | "marginInlineEnd" | "marginInlineStart" | "marginLeft" | "marginRight" | "marginTop" | "marginTrim" | "maskBorderMode" | "maskBorderOutset" | "maskBorderRepeat" | "maskBorderSlice" | "maskBorderSource" | "maskBorderWidth" | "maskClip" | "maskComposite" | "maskImage" | "maskMode" | "maskOrigin" | "maskPosition" | "maskRepeat" | "maskSize" | "maskType" | "masonryAutoFlow" | "mathDepth" | "mathShift" | "mathStyle" | "maxBlockSize" | "maxHeight" | "maxInlineSize" | "maxLines" | "maxWidth" | "minBlockSize" | "minHeight" | "minInlineSize" | "minWidth" | "mixBlendMode" | "objectFit" | "objectPosition" | "offsetAnchor" | "offsetDistance" | "offsetPath" | "offsetPosition" | "offsetRotate" | "opacity" | "order" | "orphans" | "outlineColor" | "outlineOffset" | "outlineStyle" | "outlineWidth" | "overflow" | "overflowAnchor" | "overflowBlock" | "overflowClipMargin" | "overflowInline" | "overflowWrap" | "overflowX" | "overflowY" | "overscrollBehavior" | "overscrollBehaviorBlock" | "overscrollBehaviorInline" | "overscrollBehaviorX" | "overscrollBehaviorY" | "paddingBlockEnd" | "paddingBlockStart" | "paddingBottom" | "paddingInlineEnd" | "paddingInlineStart" | "paddingLeft" | "paddingRight" | "paddingTop" | "pageBreakAfter" | "pageBreakBefore" | "pageBreakInside" | "paintOrder" | "perspective" | "perspectiveOrigin" | "pointerEvents" | "position" | "quotes" | "resize" | "rotate" | "rowGap" | "rubyAlign" | "rubyMerge" | "rubyPosition" | "scale" | "scrollbarColor" | "scrollbarGutter" | "scrollbarWidth" | "scrollBehavior" | "scrollMarginBlockStart" | "scrollMarginBlockEnd" | "scrollMarginBottom" | "scrollMarginInlineStart" | "scrollMarginInlineEnd" | "scrollMarginLeft" | "scrollMarginRight" | "scrollMarginTop" | "scrollPaddingBlockStart" | "scrollPaddingBlockEnd" | "scrollPaddingBottom" | "scrollPaddingInlineStart" | "scrollPaddingInlineEnd" | "scrollPaddingLeft" | "scrollPaddingRight" | "scrollPaddingTop" | "scrollSnapAlign" | "scrollSnapStop" | "scrollSnapType" | "scrollTimelineAxis" | "scrollTimelineName" | "shapeImageThreshold" | "shapeMargin" | "shapeOutside" | "tabSize" | "tableLayout" | "textAlign" | "textAlignLast" | "textCombineUpright" | "textDecorationColor" | "textDecorationLine" | "textDecorationSkip" | "textDecorationSkipInk" | "textDecorationStyle" | "textDecorationThickness" | "textEmphasisColor" | "textEmphasisPosition" | "textEmphasisStyle" | "textIndent" | "textJustify" | "textOrientation" | "textOverflow" | "textRendering" | "textShadow" | "textSizeAdjust" | "textTransform" | "textUnderlineOffset" | "textUnderlinePosition" | "touchAction" | "transform" | "transformBox" | "transformOrigin" | "transformStyle" | "transitionDelay" | "transitionDuration" | "transitionProperty" | "transitionTimingFunction" | "translate" | "unicodeBidi" | "userSelect" | "verticalAlign" | "visibility" | "whiteSpace" | "widows" | "willChange" | "wordBreak" | "wordSpacing" | "wordWrap" | "writingMode" | "zIndex";
2649
2655
  }[];
2650
2656
  };
2651
2657
  export type EmbedTemplateData = ReturnType<typeof generateDataFromEmbedTemplate>;
2658
+ export declare const namespaceEmbedTemplateComponents: (template: ({
2659
+ type: "text";
2660
+ value: string;
2661
+ } | EmbedTemplateInstance)[], namespace: string, components: Set<EmbedTemplateInstance["component"]>) => ({
2662
+ type: "text";
2663
+ value: string;
2664
+ } | EmbedTemplateInstance)[];
2652
2665
  export {};
@@ -9,8 +9,9 @@ export declare const validateExpression: (code: string, options?: {
9
9
  */
10
10
  export declare const generateComputingExpressions: (expressions: Map<string, string>, allowedVariables: Set<string>) => string;
11
11
  export declare const executeComputingExpressions: (expressions: Map<string, string>, variables: Map<string, unknown>) => Map<string, unknown>;
12
- export declare const generateEffectfulExpression: (code: string, allowedVariables: Set<string>) => string;
13
- export declare const executeEffectfulExpression: (code: string, variables: Map<string, unknown>) => Map<string, unknown>;
12
+ export declare const generateEffectfulExpression: (code: string, args: Set<string>, allowedVariables: Set<string>) => string;
13
+ export declare const executeEffectfulExpression: (code: string, args: Map<string, unknown>, variables: Map<string, unknown>) => Map<string, unknown>;
14
+ export declare const computeExpressionsDependencies: (expressions: Map<string, string>) => Map<string, Set<string>>;
14
15
  type Values = Map<string, unknown>;
15
16
  export declare const encodeDataSourceVariable: (id: string) => string;
16
17
  export declare const encodeVariablesMap: (values: Values) => Values;
@@ -7,4 +7,4 @@ export { type WsComponentPropsMeta, type WsComponentMeta, type ComponentState, t
7
7
  export * from "./embed-template";
8
8
  export { useInstanceProps, usePropUrl, usePropAsset, getInstanceIdFromComponentProps, } from "./props";
9
9
  export { type Params, ReactSdkContext } from "./context";
10
- export { validateExpression, generateComputingExpressions, executeComputingExpressions, generateEffectfulExpression, executeEffectfulExpression, encodeDataSourceVariable, encodeVariablesMap, decodeDataSourceVariable, decodeVariablesMap, } from "./expression";
10
+ export { validateExpression, generateComputingExpressions, executeComputingExpressions, generateEffectfulExpression, executeEffectfulExpression, computeExpressionsDependencies, encodeDataSourceVariable, encodeVariablesMap, decodeDataSourceVariable, decodeVariablesMap, } from "./expression";
@@ -63,6 +63,7 @@ export declare const getPropsByInstanceId: (props: Map<string, {
63
63
  value: {
64
64
  code: string;
65
65
  type: "execute";
66
+ args: string[];
66
67
  }[];
67
68
  id: string;
68
69
  instanceId: string;
@@ -1,11 +1,11 @@
1
- import { type ComponentProps } from "react";
1
+ import { type ForwardRefExoticComponent, type RefAttributes } from "react";
2
2
  import type { ReadableAtom } from "nanostores";
3
3
  import type { Assets } from "@webstudio-is/asset-uploader";
4
4
  import type { Instance, Instances } from "@webstudio-is/project-build";
5
5
  import type { Components } from "../components/components-utils";
6
6
  import { type Params, type DataSourceValues } from "../context";
7
7
  import type { Pages, PropsByInstanceId } from "../props";
8
- import type { WebstudioComponent } from "./webstudio-component";
8
+ import type { WebstudioComponentProps } from "./webstudio-component";
9
9
  export declare const createElementsTree: ({ renderer, imageBaseUrl, assetBaseUrl, instances, rootInstanceId, propsByInstanceIdStore, assetsStore, pagesStore, dataSourceValuesStore, executeEffectfulExpression, onDataSourceUpdate, Component, components, }: Params & {
10
10
  instances: Map<string, {
11
11
  type: "instance";
@@ -24,9 +24,9 @@ export declare const createElementsTree: ({ renderer, imageBaseUrl, assetBaseUrl
24
24
  propsByInstanceIdStore: ReadableAtom<PropsByInstanceId>;
25
25
  assetsStore: ReadableAtom<Assets>;
26
26
  pagesStore: ReadableAtom<Pages>;
27
- executeEffectfulExpression: (expression: string, values: DataSourceValues) => DataSourceValues;
27
+ executeEffectfulExpression: (expression: string, args: DataSourceValues, values: DataSourceValues) => DataSourceValues;
28
28
  dataSourceValuesStore: ReadableAtom<DataSourceValues>;
29
29
  onDataSourceUpdate: (newValues: DataSourceValues) => void;
30
- Component: (props: ComponentProps<typeof WebstudioComponent>) => JSX.Element;
30
+ Component: ForwardRefExoticComponent<WebstudioComponentProps & RefAttributes<HTMLElement>>;
31
31
  components: Components;
32
- }) => JSX.Element | null;
32
+ }) => import("react/jsx-runtime").JSX.Element | null;
@@ -1,7 +1,7 @@
1
- import { type ComponentProps } from "react";
1
+ import { type ForwardRefExoticComponent, type RefAttributes } from "react";
2
2
  import { type Build, type Page } from "@webstudio-is/project-build";
3
3
  import type { Asset } from "@webstudio-is/asset-uploader";
4
- import { WebstudioComponent } from "./webstudio-component";
4
+ import { type WebstudioComponentProps } from "./webstudio-component";
5
5
  import type { Components } from "../components/components-utils";
6
6
  import type { Params, DataSourceValues } from "../context";
7
7
  export type Data = {
@@ -17,8 +17,8 @@ export type RootPropsData = Omit<Data, "build"> & {
17
17
  type RootProps = {
18
18
  data: RootPropsData;
19
19
  executeComputingExpressions: (values: DataSourceValues) => DataSourceValues;
20
- executeEffectfulExpression: (expression: string, values: DataSourceValues) => DataSourceValues;
21
- Component?: (props: ComponentProps<typeof WebstudioComponent>) => JSX.Element;
20
+ executeEffectfulExpression: (expression: string, args: DataSourceValues, values: DataSourceValues) => DataSourceValues;
21
+ Component?: ForwardRefExoticComponent<WebstudioComponentProps & RefAttributes<HTMLElement>>;
22
22
  components: Components;
23
23
  };
24
24
  export declare const InstanceRoot: ({ data, executeComputingExpressions, executeEffectfulExpression, Component, components, }: RootProps) => JSX.Element | null;
@@ -2,15 +2,23 @@
2
2
  import type { Instance } from "@webstudio-is/project-build";
3
3
  import type { Components } from "../components/components-utils";
4
4
  export declare const renderWebstudioComponentChildren: (children: Array<JSX.Element | string> | undefined) => Array<JSX.Element | string | Array<JSX.Element | string>> | undefined;
5
- type WebstudioComponentProps = {
5
+ export type WebstudioComponentProps = {
6
6
  instance: Instance;
7
7
  instanceSelector: Instance["id"][];
8
8
  children: Array<JSX.Element | string>;
9
9
  components: Components;
10
10
  };
11
- export declare const WebstudioComponent: ({ instance, instanceSelector, children, components, ...rest }: WebstudioComponentProps) => JSX.Element;
12
- export declare const idAttribute = "data-ws-id";
13
- export declare const componentAttribute = "data-ws-component";
14
- export declare const showAttribute = "data-ws-show";
15
- export declare const collapsedAttribute = "data-ws-collapsed";
16
- export {};
11
+ export declare const WebstudioComponent: import("react").ForwardRefExoticComponent<WebstudioComponentProps & import("react").RefAttributes<HTMLElement>>;
12
+ export declare const idAttribute: "data-ws-id";
13
+ export declare const selectorIdAttribute: "data-ws-selector";
14
+ export declare const componentAttribute: "data-ws-component";
15
+ export declare const showAttribute: "data-ws-show";
16
+ export declare const collapsedAttribute: "data-ws-collapsed";
17
+ export type WebstudioAttributes = {
18
+ [idAttribute]?: string | undefined;
19
+ [selectorIdAttribute]?: string | undefined;
20
+ [componentAttribute]?: string | undefined;
21
+ [showAttribute]?: string | undefined;
22
+ [collapsedAttribute]?: string | undefined;
23
+ };
24
+ export declare const splitPropsWithWebstudioAttributes: <P extends WebstudioAttributes>({ [idAttribute]: idAttributeValue, [componentAttribute]: componentAttributeValue, [showAttribute]: showAttributeValue, [collapsedAttribute]: collapsedAttributeValue, [selectorIdAttribute]: parentIdAttributeValue, ...props }: P) => [WebstudioAttributes, Omit<P, keyof WebstudioAttributes>];
package/package.json CHANGED
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "name": "@webstudio-is/react-sdk",
3
- "version": "0.82.0",
3
+ "version": "0.83.0",
4
4
  "description": "Webstudio JavaScript / TypeScript API",
5
5
  "author": "Webstudio <github@webstudio.is>",
6
6
  "homepage": "https://webstudio.is",
7
7
  "type": "module",
8
8
  "devDependencies": {
9
- "@jest/globals": "^29.6.1",
9
+ "@jest/globals": "^29.6.2",
10
10
  "@remix-run/react": "^1.18.1",
11
- "@types/react": "^18.0.35",
12
- "@types/react-dom": "^18.0.11",
13
- "jest": "^29.6.1",
11
+ "@types/react": "^18.2.16",
12
+ "@types/react-dom": "^18.2.7",
13
+ "jest": "^29.6.2",
14
14
  "react": "^18.2.0",
15
15
  "react-dom": "^18.2.0",
16
16
  "type-fest": "^3.7.1",
17
- "typescript": "5.1.3",
17
+ "typescript": "5.1.6",
18
18
  "zod": "^3.21.4",
19
19
  "@webstudio-is/jest-config": "^1.0.6",
20
20
  "@webstudio-is/scripts": "^0.0.0",
@@ -29,18 +29,17 @@
29
29
  "dependencies": {
30
30
  "@jsep-plugin/assignment": "^1.2.1",
31
31
  "@nanostores/react": "^0.7.1",
32
- "detect-font": "^0.1.5",
33
32
  "html-tags": "^3.3.1",
34
33
  "jsep": "^1.3.8",
35
34
  "nanoevents": "^8.0.0",
36
35
  "nanoid": "^4.0.2",
37
36
  "nanostores": "^0.9.3",
38
- "@webstudio-is/asset-uploader": "^0.82.0",
39
- "@webstudio-is/css-data": "^0.82.0",
40
- "@webstudio-is/css-engine": "^0.82.0",
41
- "@webstudio-is/fonts": "^0.82.0",
42
- "@webstudio-is/generate-arg-types": "^0.82.0",
43
- "@webstudio-is/project-build": "^0.82.0"
37
+ "@webstudio-is/asset-uploader": "^0.83.0",
38
+ "@webstudio-is/css-data": "^0.83.0",
39
+ "@webstudio-is/css-engine": "^0.83.0",
40
+ "@webstudio-is/fonts": "^0.83.0",
41
+ "@webstudio-is/generate-arg-types": "^0.83.0",
42
+ "@webstudio-is/project-build": "^0.83.0"
44
43
  },
45
44
  "exports": {
46
45
  ".": {
@@ -61,7 +60,7 @@
61
60
  "src/*",
62
61
  "!*.test.*"
63
62
  ],
64
- "license": "MIT",
63
+ "license": "AGPL-3.0-or-later",
65
64
  "private": false,
66
65
  "sideEffects": false,
67
66
  "scripts": {
@@ -69,7 +68,7 @@
69
68
  "build": "build-package",
70
69
  "build:args": "generate-arg-types './src/components/*.tsx ./src/app/custom-components/*.tsx !./src/**/*.stories.tsx !./src/**/*.ws.tsx' && prettier --write \"**/*.props.ts\"",
71
70
  "dts": "tsc --project tsconfig.dts.json",
72
- "typecheck": "tsc --noEmit --emitDeclarationOnly false",
71
+ "typecheck": "tsc",
73
72
  "test": "NODE_OPTIONS=--experimental-vm-modules jest --passWithNoTests",
74
73
  "checks": "pnpm typecheck && pnpm test"
75
74
  }
@@ -22,6 +22,7 @@ export const componentCategories = [
22
22
  "text",
23
23
  "media",
24
24
  "forms",
25
+ "radix",
25
26
  "hidden",
26
27
  ] as const;
27
28
 
@@ -53,6 +54,10 @@ const WsComponentMeta = z.object({
53
54
  requiredAncestors: z.optional(z.array(z.string())),
54
55
  invalidAncestors: z.optional(z.array(z.string())),
55
56
  stylable: z.optional(z.boolean()),
57
+ // specifies whether the instance can be deleted,
58
+ // copied or dragged out of its parent instance
59
+ // true by default
60
+ detachable: z.optional(z.boolean()),
56
61
  label: z.string(),
57
62
  description: z.string().optional(),
58
63
  icon: z.string(),
package/src/context.tsx CHANGED
@@ -41,6 +41,7 @@ export const ReactSdkContext = createContext<
41
41
  dataSourceValuesStore: ReadableAtom<DataSourceValues>;
42
42
  executeEffectfulExpression: (
43
43
  expression: string,
44
+ args: DataSourceValues,
44
45
  values: DataSourceValues
45
46
  ) => DataSourceValues;
46
47
  setDataSourceValues: (newValues: DataSourceValues) => void;
package/src/css/index.ts CHANGED
@@ -1,4 +1,3 @@
1
- export * from "./get-browser-style";
2
1
  export * from "./global-rules";
3
2
  export * from "./style-rules";
4
3
  export * from "./css";
@@ -1,5 +1,8 @@
1
1
  import { expect, test } from "@jest/globals";
2
- import { generateDataFromEmbedTemplate } from "./embed-template";
2
+ import {
3
+ generateDataFromEmbedTemplate,
4
+ namespaceEmbedTemplateComponents,
5
+ } from "./embed-template";
3
6
  import { showAttribute } from "./tree";
4
7
 
5
8
  const expectString = expect.any(String);
@@ -407,6 +410,17 @@ test("generate data for embedding from action props", () => {
407
410
  name: "onClick",
408
411
  value: [{ type: "execute", code: `boxState = 'success'` }],
409
412
  },
413
+ {
414
+ type: "action",
415
+ name: "onChange",
416
+ value: [
417
+ {
418
+ type: "execute",
419
+ args: ["value"],
420
+ code: `boxState = value`,
421
+ },
422
+ ],
423
+ },
410
424
  ],
411
425
  children: [],
412
426
  },
@@ -442,10 +456,24 @@ test("generate data for embedding from action props", () => {
442
456
  value: [
443
457
  {
444
458
  type: "execute",
459
+ args: [],
445
460
  code: expect.stringMatching(/\$ws\$dataSource\$\w+ = 'success'/),
446
461
  },
447
462
  ],
448
463
  },
464
+ {
465
+ id: expectString,
466
+ instanceId: expectString,
467
+ type: "action",
468
+ name: "onChange",
469
+ value: [
470
+ {
471
+ type: "execute",
472
+ args: ["value"],
473
+ code: expect.stringMatching(/\$ws\$dataSource\$\w+ = value/),
474
+ },
475
+ ],
476
+ },
449
477
  ],
450
478
  dataSources: [
451
479
  {
@@ -464,3 +492,51 @@ test("generate data for embedding from action props", () => {
464
492
  styles: [],
465
493
  });
466
494
  });
495
+
496
+ test("add namespace to selected components in embed template", () => {
497
+ expect(
498
+ namespaceEmbedTemplateComponents(
499
+ [
500
+ {
501
+ type: "instance",
502
+ component: "Tooltip",
503
+ children: [
504
+ { type: "text", value: "Some text" },
505
+ {
506
+ type: "instance",
507
+ component: "Box",
508
+ children: [
509
+ {
510
+ type: "instance",
511
+ component: "Button",
512
+ children: [],
513
+ },
514
+ ],
515
+ },
516
+ ],
517
+ },
518
+ ],
519
+ "my-namespace",
520
+ new Set(["Tooltip", "Button"])
521
+ )
522
+ ).toEqual([
523
+ {
524
+ type: "instance",
525
+ component: "my-namespace:Tooltip",
526
+ children: [
527
+ { type: "text", value: "Some text" },
528
+ {
529
+ type: "instance",
530
+ component: "Box",
531
+ children: [
532
+ {
533
+ type: "instance",
534
+ component: "my-namespace:Button",
535
+ children: [],
536
+ },
537
+ ],
538
+ },
539
+ ],
540
+ },
541
+ ]);
542
+ });
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { nanoid } from "nanoid";
3
3
  import {
4
- type Instance,
4
+ Instance,
5
5
  type InstancesList,
6
6
  PropsList,
7
7
  StyleSourceSelectionsList,
@@ -66,6 +66,7 @@ const EmbedTemplateProp = z.union([
66
66
  value: z.array(
67
67
  z.object({
68
68
  type: z.literal("execute"),
69
+ args: z.optional(z.array(z.string())),
69
70
  code: z.string(),
70
71
  })
71
72
  ),
@@ -144,12 +145,18 @@ const createInstancesFromTemplate = (
144
145
  type: "action",
145
146
  name: prop.name,
146
147
  value: prop.value.map((value) => {
148
+ const args = value.args ?? [];
147
149
  return {
148
150
  type: "execute",
151
+ args,
149
152
  // replace all references with variable names
150
153
  code: validateExpression(value.code, {
151
154
  effectful: true,
152
155
  transformIdentifier: (ref) => {
156
+ // bypass arguments without changes
157
+ if (args.includes(ref)) {
158
+ return ref;
159
+ }
153
160
  const id = dataSourceByRef.get(ref)?.id ?? ref;
154
161
  return encodeDataSourceVariable(id);
155
162
  },
@@ -301,3 +308,29 @@ export const generateDataFromEmbedTemplate = (
301
308
  export type EmbedTemplateData = ReturnType<
302
309
  typeof generateDataFromEmbedTemplate
303
310
  >;
311
+
312
+ export const namespaceEmbedTemplateComponents = (
313
+ template: WsEmbedTemplate,
314
+ namespace: string,
315
+ components: Set<EmbedTemplateInstance["component"]>
316
+ ): WsEmbedTemplate => {
317
+ return template.map((item) => {
318
+ if (item.type === "text") {
319
+ return item;
320
+ }
321
+ if (item.type === "instance") {
322
+ const prefix = components.has(item.component) ? `${namespace}:` : "";
323
+ return {
324
+ ...item,
325
+ component: `${prefix}${item.component}`,
326
+ children: namespaceEmbedTemplateComponents(
327
+ item.children,
328
+ namespace,
329
+ components
330
+ ),
331
+ };
332
+ }
333
+ item satisfies never;
334
+ throw Error("Impossible case");
335
+ });
336
+ };
@@ -4,6 +4,7 @@ import {
4
4
  encodeDataSourceVariable,
5
5
  executeComputingExpressions,
6
6
  executeEffectfulExpression,
7
+ computeExpressionsDependencies,
7
8
  generateComputingExpressions,
8
9
  generateEffectfulExpression,
9
10
  validateExpression,
@@ -186,7 +187,11 @@ test("encode/decode variable names", () => {
186
187
 
187
188
  test("generate effectful expression", () => {
188
189
  expect(
189
- generateEffectfulExpression(`var0 = var0 + var1`, new Set(["var0", "var1"]))
190
+ generateEffectfulExpression(
191
+ `var0 = var0 + var1`,
192
+ new Set(),
193
+ new Set(["var0", "var1"])
194
+ )
190
195
  ).toMatchInlineSnapshot(`
191
196
  "let var0 = _variables.get('var0');
192
197
  let var1 = _variables.get('var1');
@@ -197,7 +202,11 @@ test("generate effectful expression", () => {
197
202
  `);
198
203
 
199
204
  expect(
200
- generateEffectfulExpression(`var0 = var1 + 1`, new Set(["var0", "var1"]))
205
+ generateEffectfulExpression(
206
+ `var0 = var1 + 1`,
207
+ new Set(),
208
+ new Set(["var0", "var1"])
209
+ )
201
210
  ).toMatchInlineSnapshot(`
202
211
  "let var1 = _variables.get('var1');
203
212
  let var0;
@@ -212,6 +221,7 @@ test("add only used variables in effectful expression", () => {
212
221
  expect(
213
222
  generateEffectfulExpression(
214
223
  `var0 = var1 + 1`,
224
+ new Set(),
215
225
  new Set(["var0", "var1", "var2"])
216
226
  )
217
227
  ).toMatchInlineSnapshot(`
@@ -224,10 +234,34 @@ test("add only used variables in effectful expression", () => {
224
234
  `);
225
235
  });
226
236
 
227
- test("forbid not allowed variables in effectful expression", () => {
237
+ test("support effectful expression arguments", () => {
238
+ expect(
239
+ generateEffectfulExpression(
240
+ `var0 = arg0 + 1`,
241
+ new Set(["arg0"]),
242
+ new Set(["var0"])
243
+ )
244
+ ).toMatchInlineSnapshot(`
245
+ "let arg0 = _args.get('arg0');
246
+ let var0;
247
+ var0 = arg0 + 1;
248
+ return new Map([
249
+ ['var0', var0],
250
+ ]);"
251
+ `);
252
+ });
253
+
254
+ test("forbid not allowed variables or arguments in effectful expression", () => {
228
255
  expect(() => {
229
- generateEffectfulExpression(`var0 = var0 + var1`, new Set(["var0"]));
256
+ generateEffectfulExpression(
257
+ `var0 = var0 + var1`,
258
+ new Set(),
259
+ new Set(["var0"])
260
+ );
230
261
  }).toThrowError(/Unknown dependency "var1"/);
262
+ expect(() => {
263
+ generateEffectfulExpression(`var0 = arg0`, new Set(), new Set(["var0"]));
264
+ }).toThrowError(/Unknown dependency "arg0"/);
231
265
  });
232
266
 
233
267
  test("execute effectful expression", () => {
@@ -235,7 +269,41 @@ test("execute effectful expression", () => {
235
269
  ["var0", 2],
236
270
  ["var1", 3],
237
271
  ]);
238
- expect(executeEffectfulExpression(`var0 = var0 + var1`, variables)).toEqual(
239
- new Map([["var0", 5]])
272
+ expect(
273
+ executeEffectfulExpression(`var0 = var0 + var1`, new Map(), variables)
274
+ ).toEqual(new Map([["var0", 5]]));
275
+
276
+ expect(
277
+ executeEffectfulExpression(`arg0 = 5`, new Map([["arg0", 0]]), new Map())
278
+ ).toEqual(new Map());
279
+ });
280
+
281
+ test("compute expressions dependencies", () => {
282
+ const expressions = new Map([
283
+ ["exp1", `var1`],
284
+ ["exp2", `exp1 + exp1`],
285
+ ["exp3", `exp1 + exp2`],
286
+ ["exp4", `var1 + exp1`],
287
+ ]);
288
+ expect(computeExpressionsDependencies(expressions)).toEqual(
289
+ new Map([
290
+ ["exp4", new Set(["var1", "exp1"])],
291
+ ["exp3", new Set(["var1", "exp1", "exp2"])],
292
+ ["exp2", new Set(["var1", "exp1"])],
293
+ ["exp1", new Set(["var1"])],
294
+ ])
295
+ );
296
+ });
297
+
298
+ test("handle cyclic dependencies", () => {
299
+ const expressions = new Map([
300
+ ["exp1", `exp2 + var1`],
301
+ ["exp2", `exp1 + var1`],
302
+ ]);
303
+ expect(computeExpressionsDependencies(expressions)).toEqual(
304
+ new Map([
305
+ ["exp2", new Set(["var1", "exp1", "exp2"])],
306
+ ["exp1", new Set(["var1", "exp1", "exp2"])],
307
+ ])
240
308
  );
241
309
  });