@webstudio-is/react-sdk 0.19.0 → 0.21.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.
@@ -29,7 +29,6 @@ const layout = [
29
29
  "alignItems",
30
30
  "justifyContent",
31
31
  "alignContent",
32
- "placeContent",
33
32
  "justifyItems",
34
33
  "rowGap",
35
34
  "columnGap",
@@ -56,7 +55,7 @@ const gridChild = [
56
55
  "justifySelf",
57
56
  "order"
58
57
  ];
59
- const spacing = [
58
+ const space = [
60
59
  "marginTop",
61
60
  "marginRight",
62
61
  "marginBottom",
@@ -75,6 +74,7 @@ const size = [
75
74
  "maxHeight",
76
75
  "overflow",
77
76
  "objectFit",
77
+ "objectPosition",
78
78
  "aspectRatio"
79
79
  ];
80
80
  const position = [
@@ -214,7 +214,7 @@ const categories = {
214
214
  properties: gridChild,
215
215
  moreFrom: ""
216
216
  },
217
- spacing: { label: "Spacing", properties: spacing, moreFrom: "" },
217
+ space: { label: "Space", properties: space, moreFrom: "" },
218
218
  size: { label: "Size", properties: size, moreFrom: "" },
219
219
  position: { label: "Position", properties: position, moreFrom: "" },
220
220
  typography: {
@@ -23,14 +23,15 @@ __export(get_browser_style_exports, {
23
23
  module.exports = __toCommonJS(get_browser_style_exports);
24
24
  var import_detect_font = require("detect-font");
25
25
  var import_css_data = require("@webstudio-is/css-data");
26
- const unitRegex = new RegExp(`${import_css_data.units.join("|")}`);
26
+ const unitsList = Object.values(import_css_data.units).flat();
27
+ const unitRegex = new RegExp(`${unitsList.join("|")}`);
27
28
  const parseValue = (property, value) => {
28
- const number = parseFloat(value);
29
+ const number = Number.parseFloat(value);
29
30
  const parsedUnit = unitRegex.exec(value);
30
31
  if (value === "rgba(0, 0, 0, 0)") {
31
32
  value = "transparent";
32
33
  }
33
- if (isNaN(number) || parsedUnit === null) {
34
+ if (Number.isNaN(number)) {
34
35
  return {
35
36
  type: "keyword",
36
37
  value
@@ -39,6 +40,13 @@ const parseValue = (property, value) => {
39
40
  if (number === 0 && property in import_css_data.properties) {
40
41
  return import_css_data.properties[property].initial;
41
42
  }
43
+ if (parsedUnit === null) {
44
+ return {
45
+ type: "unit",
46
+ unit: "number",
47
+ value: number
48
+ };
49
+ }
42
50
  return {
43
51
  type: "unit",
44
52
  unit: parsedUnit[0],
@@ -17,3 +17,4 @@ var db_exports = {};
17
17
  module.exports = __toCommonJS(db_exports);
18
18
  __reExport(db_exports, require("./types"), module.exports);
19
19
  __reExport(db_exports, require("./instance"), module.exports);
20
+ __reExport(db_exports, require("./style"), module.exports);
@@ -18,32 +18,42 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var instance_exports = {};
20
20
  __export(instance_exports, {
21
+ Id: () => Id,
21
22
  Instance: () => Instance,
23
+ Instances: () => Instances,
24
+ InstancesItem: () => InstancesItem,
22
25
  Text: () => Text,
23
26
  toBaseInstance: () => toBaseInstance
24
27
  });
25
28
  module.exports = __toCommonJS(instance_exports);
26
- var import_css_data = require("@webstudio-is/css-data");
27
29
  var import_zod = require("zod");
30
+ var import_components = require("../components");
28
31
  const toBaseInstance = (instance) => {
29
32
  return {
30
33
  id: instance.id,
31
- component: instance.component,
32
- cssRules: instance.cssRules
34
+ component: instance.component
33
35
  };
34
36
  };
35
- const Text = import_zod.z.lazy(
36
- () => import_zod.z.object({
37
- type: import_zod.z.literal("text"),
38
- value: import_zod.z.string()
39
- })
40
- );
37
+ const Text = import_zod.z.object({
38
+ type: import_zod.z.literal("text"),
39
+ value: import_zod.z.string()
40
+ });
41
+ const Id = import_zod.z.object({
42
+ type: import_zod.z.literal("id"),
43
+ value: import_zod.z.string()
44
+ });
45
+ const InstancesItem = import_zod.z.object({
46
+ type: import_zod.z.literal("instance"),
47
+ id: import_zod.z.string(),
48
+ component: import_zod.z.enum((0, import_components.getComponentNames)()),
49
+ children: import_zod.z.array(import_zod.z.union([Id, Text]))
50
+ });
51
+ const Instances = import_zod.z.array(InstancesItem);
41
52
  const Instance = import_zod.z.lazy(
42
53
  () => import_zod.z.object({
43
54
  type: import_zod.z.literal("instance"),
44
55
  id: import_zod.z.string(),
45
- component: import_zod.z.string(),
46
- children: import_zod.z.array(import_zod.z.union([Instance, Text])),
47
- cssRules: import_zod.z.array(import_css_data.CssRule)
56
+ component: import_zod.z.enum((0, import_components.getComponentNames)()),
57
+ children: import_zod.z.array(import_zod.z.union([Instance, Text]))
48
58
  })
49
59
  );
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var style_exports = {};
20
+ __export(style_exports, {
21
+ PresetStyles: () => PresetStyles,
22
+ PresetStylesItem: () => PresetStylesItem,
23
+ Styles: () => Styles,
24
+ StylesItem: () => StylesItem,
25
+ findMissingPresetStyles: () => findMissingPresetStyles
26
+ });
27
+ module.exports = __toCommonJS(style_exports);
28
+ var import_zod = require("zod");
29
+ var import_css_data = require("@webstudio-is/css-data");
30
+ var import_components = require("../components");
31
+ const PresetStylesItem = import_zod.z.object({
32
+ component: import_zod.z.enum((0, import_components.getComponentNames)()),
33
+ property: import_zod.z.string(),
34
+ value: import_css_data.SharedStyleValue
35
+ });
36
+ const PresetStyles = import_zod.z.array(PresetStylesItem);
37
+ const findMissingPresetStyles = (presetStyles, components) => {
38
+ const populatedComponents = /* @__PURE__ */ new Set();
39
+ for (const style of presetStyles) {
40
+ populatedComponents.add(style.component);
41
+ }
42
+ const missingPresetStyles = [];
43
+ for (const component of components) {
44
+ if (populatedComponents.has(component)) {
45
+ continue;
46
+ }
47
+ const meta = (0, import_components.getComponentMeta)(component);
48
+ if (meta.presetStyle === void 0) {
49
+ continue;
50
+ }
51
+ for (const [property, value] of Object.entries(meta.presetStyle)) {
52
+ missingPresetStyles.push({
53
+ component,
54
+ property,
55
+ value
56
+ });
57
+ }
58
+ }
59
+ return missingPresetStyles;
60
+ };
61
+ const StylesItem = import_zod.z.object({
62
+ breakpointId: import_zod.z.string(),
63
+ instanceId: import_zod.z.string(),
64
+ property: import_zod.z.string(),
65
+ value: import_css_data.SharedStyleValue
66
+ });
67
+ const Styles = import_zod.z.array(StylesItem);
@@ -19,6 +19,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  var wrapper_component_exports = {};
20
20
  __export(wrapper_component_exports, {
21
21
  WrapperComponent: () => WrapperComponent,
22
+ componentAttribute: () => componentAttribute,
22
23
  idAttribute: () => idAttribute,
23
24
  renderWrapperComponentChildren: () => renderWrapperComponentChildren
24
25
  });
@@ -52,10 +53,16 @@ const WrapperComponent = ({
52
53
  }) => {
53
54
  const Component = (0, import_components.getComponent)(instance.component);
54
55
  const userProps = (0, import_use_user_props.useUserProps)(instance.id);
55
- const props = { ...userProps, ...rest, [idAttribute]: instance.id };
56
+ const props = {
57
+ ...userProps,
58
+ ...rest,
59
+ [idAttribute]: instance.id,
60
+ [componentAttribute]: instance.component
61
+ };
56
62
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, {
57
63
  ...props,
58
64
  children: renderWrapperComponentChildren(children)
59
65
  });
60
66
  };
61
67
  const idAttribute = "data-ws-id";
68
+ const componentAttribute = "data-ws-component";
@@ -23,17 +23,18 @@ __export(all_user_props_exports, {
23
23
  });
24
24
  module.exports = __toCommonJS(all_user_props_exports);
25
25
  var import_react = require("react");
26
- var import_react_nano_state = require("react-nano-state");
27
- const allUserPropsContainer = (0, import_react_nano_state.createValueContainer)({});
26
+ var import_nanostores = require("nanostores");
27
+ var import_react2 = require("@nanostores/react");
28
+ const allUserPropsContainer = (0, import_nanostores.atom)({});
28
29
  const useAllUserProps = (initialUserProps) => {
29
30
  const ref = (0, import_react.useRef)(false);
30
31
  if (ref.current === false && initialUserProps !== void 0) {
31
32
  const propsMap = {};
32
- for (const props of initialUserProps) {
33
- propsMap[props.instanceId] = props;
33
+ for (const item of initialUserProps) {
34
+ propsMap[item.instanceId] = item.props;
34
35
  }
35
- allUserPropsContainer.value = propsMap;
36
+ allUserPropsContainer.set(propsMap);
36
37
  ref.current = true;
37
38
  }
38
- return (0, import_react_nano_state.useValue)(allUserPropsContainer);
39
+ return (0, import_react2.useStore)(allUserPropsContainer);
39
40
  };
@@ -17,5 +17,4 @@ var user_props_exports = {};
17
17
  module.exports = __toCommonJS(user_props_exports);
18
18
  __reExport(user_props_exports, require("./all-user-props"), module.exports);
19
19
  __reExport(user_props_exports, require("./use-user-props"), module.exports);
20
- __reExport(user_props_exports, require("./types"), module.exports);
21
20
  __reExport(user_props_exports, require("./schema"), module.exports);
@@ -24,13 +24,13 @@ module.exports = __toCommonJS(use_user_props_asset_exports);
24
24
  var import_react = require("react");
25
25
  var import_all_user_props = require("./all-user-props");
26
26
  const useUserPropsAsset = (instanceId, propName) => {
27
- const [allUserProps] = (0, import_all_user_props.useAllUserProps)();
27
+ const allUserProps = (0, import_all_user_props.useAllUserProps)();
28
28
  const propsData = allUserProps[instanceId];
29
29
  const asset = (0, import_react.useMemo)(() => {
30
30
  if (propsData == null) {
31
31
  return void 0;
32
32
  }
33
- const prop = propsData.props.find((prop2) => prop2.prop === propName);
33
+ const prop = propsData.find((prop2) => prop2.prop === propName);
34
34
  if (prop == null) {
35
35
  return void 0;
36
36
  }
@@ -24,14 +24,14 @@ module.exports = __toCommonJS(use_user_props_exports);
24
24
  var import_react = require("react");
25
25
  var import_all_user_props = require("./all-user-props");
26
26
  const useUserProps = (instanceId) => {
27
- const [allUserProps] = (0, import_all_user_props.useAllUserProps)();
27
+ const allUserProps = (0, import_all_user_props.useAllUserProps)();
28
28
  const propsData = allUserProps[instanceId];
29
29
  const props = (0, import_react.useMemo)(() => {
30
30
  if (propsData == null) {
31
31
  return {};
32
32
  }
33
33
  const result = {};
34
- for (const userProp of propsData.props) {
34
+ for (const userProp of propsData) {
35
35
  if (userProp.type !== "asset") {
36
36
  result[userProp.prop] = userProp.value;
37
37
  }
@@ -5,7 +5,6 @@ const layout = [
5
5
  "alignItems",
6
6
  "justifyContent",
7
7
  "alignContent",
8
- "placeContent",
9
8
  "justifyItems",
10
9
  "rowGap",
11
10
  "columnGap",
@@ -32,7 +31,7 @@ const gridChild = [
32
31
  "justifySelf",
33
32
  "order"
34
33
  ];
35
- const spacing = [
34
+ const space = [
36
35
  "marginTop",
37
36
  "marginRight",
38
37
  "marginBottom",
@@ -51,6 +50,7 @@ const size = [
51
50
  "maxHeight",
52
51
  "overflow",
53
52
  "objectFit",
53
+ "objectPosition",
54
54
  "aspectRatio"
55
55
  ];
56
56
  const position = [
@@ -190,7 +190,7 @@ const categories = {
190
190
  properties: gridChild,
191
191
  moreFrom: ""
192
192
  },
193
- spacing: { label: "Spacing", properties: spacing, moreFrom: "" },
193
+ space: { label: "Space", properties: space, moreFrom: "" },
194
194
  size: { label: "Size", properties: size, moreFrom: "" },
195
195
  position: { label: "Position", properties: position, moreFrom: "" },
196
196
  typography: {
@@ -1,13 +1,14 @@
1
1
  import { detectFont } from "detect-font";
2
2
  import { properties, units } from "@webstudio-is/css-data";
3
- const unitRegex = new RegExp(`${units.join("|")}`);
3
+ const unitsList = Object.values(units).flat();
4
+ const unitRegex = new RegExp(`${unitsList.join("|")}`);
4
5
  const parseValue = (property, value) => {
5
- const number = parseFloat(value);
6
+ const number = Number.parseFloat(value);
6
7
  const parsedUnit = unitRegex.exec(value);
7
8
  if (value === "rgba(0, 0, 0, 0)") {
8
9
  value = "transparent";
9
10
  }
10
- if (isNaN(number) || parsedUnit === null) {
11
+ if (Number.isNaN(number)) {
11
12
  return {
12
13
  type: "keyword",
13
14
  value
@@ -16,6 +17,13 @@ const parseValue = (property, value) => {
16
17
  if (number === 0 && property in properties) {
17
18
  return properties[property].initial;
18
19
  }
20
+ if (parsedUnit === null) {
21
+ return {
22
+ type: "unit",
23
+ unit: "number",
24
+ value: number
25
+ };
26
+ }
19
27
  return {
20
28
  type: "unit",
21
29
  unit: parsedUnit[0],
package/lib/db/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from "./types";
2
2
  export * from "./instance";
3
+ export * from "./style";
@@ -1,29 +1,39 @@
1
- import { CssRule } from "@webstudio-is/css-data";
2
1
  import { z } from "zod";
2
+ import { getComponentNames } from "../components";
3
3
  const toBaseInstance = (instance) => {
4
4
  return {
5
5
  id: instance.id,
6
- component: instance.component,
7
- cssRules: instance.cssRules
6
+ component: instance.component
8
7
  };
9
8
  };
10
- const Text = z.lazy(
11
- () => z.object({
12
- type: z.literal("text"),
13
- value: z.string()
14
- })
15
- );
9
+ const Text = z.object({
10
+ type: z.literal("text"),
11
+ value: z.string()
12
+ });
13
+ const Id = z.object({
14
+ type: z.literal("id"),
15
+ value: z.string()
16
+ });
17
+ const InstancesItem = z.object({
18
+ type: z.literal("instance"),
19
+ id: z.string(),
20
+ component: z.enum(getComponentNames()),
21
+ children: z.array(z.union([Id, Text]))
22
+ });
23
+ const Instances = z.array(InstancesItem);
16
24
  const Instance = z.lazy(
17
25
  () => z.object({
18
26
  type: z.literal("instance"),
19
27
  id: z.string(),
20
- component: z.string(),
21
- children: z.array(z.union([Instance, Text])),
22
- cssRules: z.array(CssRule)
28
+ component: z.enum(getComponentNames()),
29
+ children: z.array(z.union([Instance, Text]))
23
30
  })
24
31
  );
25
32
  export {
33
+ Id,
26
34
  Instance,
35
+ Instances,
36
+ InstancesItem,
27
37
  Text,
28
38
  toBaseInstance
29
39
  };
@@ -0,0 +1,50 @@
1
+ import { z } from "zod";
2
+ import { SharedStyleValue } from "@webstudio-is/css-data";
3
+ import {
4
+ getComponentMeta,
5
+ getComponentNames
6
+ } from "../components";
7
+ const PresetStylesItem = z.object({
8
+ component: z.enum(getComponentNames()),
9
+ property: z.string(),
10
+ value: SharedStyleValue
11
+ });
12
+ const PresetStyles = z.array(PresetStylesItem);
13
+ const findMissingPresetStyles = (presetStyles, components) => {
14
+ const populatedComponents = /* @__PURE__ */ new Set();
15
+ for (const style of presetStyles) {
16
+ populatedComponents.add(style.component);
17
+ }
18
+ const missingPresetStyles = [];
19
+ for (const component of components) {
20
+ if (populatedComponents.has(component)) {
21
+ continue;
22
+ }
23
+ const meta = getComponentMeta(component);
24
+ if (meta.presetStyle === void 0) {
25
+ continue;
26
+ }
27
+ for (const [property, value] of Object.entries(meta.presetStyle)) {
28
+ missingPresetStyles.push({
29
+ component,
30
+ property,
31
+ value
32
+ });
33
+ }
34
+ }
35
+ return missingPresetStyles;
36
+ };
37
+ const StylesItem = z.object({
38
+ breakpointId: z.string(),
39
+ instanceId: z.string(),
40
+ property: z.string(),
41
+ value: SharedStyleValue
42
+ });
43
+ const Styles = z.array(StylesItem);
44
+ export {
45
+ PresetStyles,
46
+ PresetStylesItem,
47
+ Styles,
48
+ StylesItem,
49
+ findMissingPresetStyles
50
+ };
@@ -27,15 +27,22 @@ const WrapperComponent = ({
27
27
  }) => {
28
28
  const Component = getComponent(instance.component);
29
29
  const userProps = useUserProps(instance.id);
30
- const props = { ...userProps, ...rest, [idAttribute]: instance.id };
30
+ const props = {
31
+ ...userProps,
32
+ ...rest,
33
+ [idAttribute]: instance.id,
34
+ [componentAttribute]: instance.component
35
+ };
31
36
  return /* @__PURE__ */ jsx(Component, {
32
37
  ...props,
33
38
  children: renderWrapperComponentChildren(children)
34
39
  });
35
40
  };
36
41
  const idAttribute = "data-ws-id";
42
+ const componentAttribute = "data-ws-component";
37
43
  export {
38
44
  WrapperComponent,
45
+ componentAttribute,
39
46
  idAttribute,
40
47
  renderWrapperComponentChildren
41
48
  };
@@ -1,17 +1,18 @@
1
1
  import { useRef } from "react";
2
- import { createValueContainer, useValue } from "react-nano-state";
3
- const allUserPropsContainer = createValueContainer({});
2
+ import { atom } from "nanostores";
3
+ import { useStore } from "@nanostores/react";
4
+ const allUserPropsContainer = atom({});
4
5
  const useAllUserProps = (initialUserProps) => {
5
6
  const ref = useRef(false);
6
7
  if (ref.current === false && initialUserProps !== void 0) {
7
8
  const propsMap = {};
8
- for (const props of initialUserProps) {
9
- propsMap[props.instanceId] = props;
9
+ for (const item of initialUserProps) {
10
+ propsMap[item.instanceId] = item.props;
10
11
  }
11
- allUserPropsContainer.value = propsMap;
12
+ allUserPropsContainer.set(propsMap);
12
13
  ref.current = true;
13
14
  }
14
- return useValue(allUserPropsContainer);
15
+ return useStore(allUserPropsContainer);
15
16
  };
16
17
  export {
17
18
  allUserPropsContainer,
@@ -1,4 +1,3 @@
1
1
  export * from "./all-user-props";
2
2
  export * from "./use-user-props";
3
- export * from "./types";
4
3
  export * from "./schema";
@@ -1,13 +1,13 @@
1
1
  import { useMemo } from "react";
2
2
  import { useAllUserProps } from "./all-user-props";
3
3
  const useUserPropsAsset = (instanceId, propName) => {
4
- const [allUserProps] = useAllUserProps();
4
+ const allUserProps = useAllUserProps();
5
5
  const propsData = allUserProps[instanceId];
6
6
  const asset = useMemo(() => {
7
7
  if (propsData == null) {
8
8
  return void 0;
9
9
  }
10
- const prop = propsData.props.find((prop2) => prop2.prop === propName);
10
+ const prop = propsData.find((prop2) => prop2.prop === propName);
11
11
  if (prop == null) {
12
12
  return void 0;
13
13
  }
@@ -1,14 +1,14 @@
1
1
  import { useMemo } from "react";
2
2
  import { useAllUserProps } from "./all-user-props";
3
3
  const useUserProps = (instanceId) => {
4
- const [allUserProps] = useAllUserProps();
4
+ const allUserProps = useAllUserProps();
5
5
  const propsData = allUserProps[instanceId];
6
6
  const props = useMemo(() => {
7
7
  if (propsData == null) {
8
8
  return {};
9
9
  }
10
10
  const result = {};
11
- for (const userProp of propsData.props) {
11
+ for (const userProp of propsData) {
12
12
  if (userProp.type !== "asset") {
13
13
  result[userProp.prop] = userProp.value;
14
14
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webstudio-is/react-sdk",
3
- "version": "0.19.0",
3
+ "version": "0.21.0",
4
4
  "description": "Webstudio JavaScript / TypeScript API",
5
5
  "author": "Webstudio <github@webstudio.is>",
6
6
  "homepage": "https://webstudio.is",
@@ -9,9 +9,9 @@
9
9
  "@babel/core": "^7.20.2",
10
10
  "@esbuild-kit/esm-loader": "^2.4.2",
11
11
  "@jest/globals": "^29.3.1",
12
- "@remix-run/node": "^1.6.4",
13
- "@remix-run/react": "^1.2.3",
14
- "@remix-run/server-runtime": "^1.2.3",
12
+ "@remix-run/node": "1.9.0",
13
+ "@remix-run/react": "1.9.0",
14
+ "@remix-run/server-runtime": "1.9.0",
15
15
  "@storybook/react": "^6.5.14",
16
16
  "@storybook/testing-library": "^0.0.11",
17
17
  "@types/node": "^17.0.21",
@@ -34,25 +34,25 @@
34
34
  "@webstudio-is/tsconfig": "^1.0.1"
35
35
  },
36
36
  "peerDependencies": {
37
- "@remix-run/react": "^1.2.3",
38
- "@remix-run/server-runtime": "^1.2.3",
37
+ "@remix-run/react": "1.9.0",
38
+ "@remix-run/server-runtime": "1.9.0",
39
39
  "react": "^17.0.2",
40
40
  "react-dom": "^17.0.2",
41
41
  "remix-utils": "^4.1.0",
42
42
  "zod": "^3.19.1"
43
43
  },
44
44
  "dependencies": {
45
+ "@nanostores/react": "^0.4.1",
45
46
  "detect-font": "^0.1.5",
46
- "immer": "^9.0.12",
47
47
  "mitt": "^3.0.0",
48
- "react-nano-state": "^0.4.0",
48
+ "nanostores": "^0.7.1",
49
49
  "warn-once": "^0.1.1",
50
- "@webstudio-is/asset-uploader": "^0.19.0",
51
- "@webstudio-is/css-data": "^0.19.0",
52
- "@webstudio-is/design-tokens": "^0.19.0",
53
- "@webstudio-is/icons": "^0.19.0",
54
- "@webstudio-is/image": "^0.19.0",
55
- "@webstudio-is/prisma-client": "^0.19.0"
50
+ "@webstudio-is/asset-uploader": "^0.21.0",
51
+ "@webstudio-is/css-data": "^0.21.0",
52
+ "@webstudio-is/design-tokens": "^0.21.0",
53
+ "@webstudio-is/icons": "^0.21.0",
54
+ "@webstudio-is/image": "^0.21.0",
55
+ "@webstudio-is/prisma-client": "^0.21.0"
56
56
  },
57
57
  "exports": {
58
58
  "import": "./lib/index.js",
@@ -10,7 +10,6 @@ const layout = [
10
10
  "justifyContent",
11
11
  "alignContent",
12
12
  // Grid
13
- "placeContent",
14
13
  "justifyItems",
15
14
  "rowGap",
16
15
  "columnGap",
@@ -40,7 +39,7 @@ const gridChild = [
40
39
  "order",
41
40
  ] as const;
42
41
 
43
- const spacing = [
42
+ const space = [
44
43
  "marginTop",
45
44
  "marginRight",
46
45
  "marginBottom",
@@ -60,6 +59,7 @@ const size = [
60
59
  "maxHeight",
61
60
  "overflow",
62
61
  "objectFit",
62
+ "objectPosition",
63
63
  "aspectRatio",
64
64
  ] as const;
65
65
 
@@ -217,7 +217,7 @@ export const categories = {
217
217
  properties: gridChild,
218
218
  moreFrom: "",
219
219
  },
220
- spacing: { label: "Spacing", properties: spacing, moreFrom: "" },
220
+ space: { label: "Space", properties: space, moreFrom: "" },
221
221
  size: { label: "Size", properties: size, moreFrom: "" },
222
222
  position: { label: "Position", properties: position, moreFrom: "" },
223
223
  typography: {
@@ -2,19 +2,20 @@ import { detectFont } from "detect-font";
2
2
  import type { Style, StyleValue, Unit } from "@webstudio-is/css-data";
3
3
  import { properties, units } from "@webstudio-is/css-data";
4
4
 
5
- const unitRegex = new RegExp(`${units.join("|")}`);
5
+ const unitsList = Object.values(units).flat();
6
+ const unitRegex = new RegExp(`${unitsList.join("|")}`);
6
7
 
7
8
  // @todo use a parser
8
9
  const parseValue = (
9
10
  property: keyof typeof properties,
10
11
  value: string
11
12
  ): StyleValue => {
12
- const number = parseFloat(value);
13
+ const number = Number.parseFloat(value);
13
14
  const parsedUnit = unitRegex.exec(value);
14
15
  if (value === "rgba(0, 0, 0, 0)") {
15
16
  value = "transparent";
16
17
  }
17
- if (isNaN(number) || parsedUnit === null) {
18
+ if (Number.isNaN(number)) {
18
19
  return {
19
20
  type: "keyword",
20
21
  value,
@@ -25,6 +26,14 @@ const parseValue = (
25
26
  return properties[property].initial;
26
27
  }
27
28
 
29
+ if (parsedUnit === null) {
30
+ return {
31
+ type: "unit",
32
+ unit: "number",
33
+ value: number,
34
+ };
35
+ }
36
+
28
37
  return {
29
38
  type: "unit",
30
39
  unit: parsedUnit[0] as Unit,
package/src/db/index.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from "./types";
2
2
  export * from "./instance";
3
+ export * from "./style";
@@ -1,18 +1,11 @@
1
- import { CssRule } from "@webstudio-is/css-data";
2
1
  import { z } from "zod";
3
- import { ComponentName } from "../components";
2
+ import { type ComponentName, getComponentNames } from "../components";
4
3
 
5
4
  // This should be used when passing a lot of data is potentially costly.
6
5
  // For example, when passing data from an iframe.
7
6
  export type BaseInstance = {
8
7
  id: string;
9
8
  component: ComponentName;
10
- cssRules: Array<CssRule>;
11
- };
12
-
13
- export type Text = {
14
- type: "text";
15
- value: string;
16
9
  };
17
10
 
18
11
  export type Instance = BaseInstance & {
@@ -24,25 +17,40 @@ export const toBaseInstance = (instance: Instance): BaseInstance => {
24
17
  return {
25
18
  id: instance.id,
26
19
  component: instance.component,
27
- cssRules: instance.cssRules,
28
20
  };
29
21
  };
30
22
 
31
- export const Text = z.lazy(() =>
23
+ export const Text = z.object({
24
+ type: z.literal("text"),
25
+ value: z.string(),
26
+ });
27
+
28
+ export type Text = z.infer<typeof Text>;
29
+
30
+ export const Id = z.object({
31
+ type: z.literal("id"),
32
+ value: z.string(),
33
+ });
34
+ export type Id = z.infer<typeof Id>;
35
+
36
+ export const InstancesItem = z.object({
37
+ type: z.literal("instance"),
38
+ id: z.string(),
39
+ component: z.enum(getComponentNames() as [ComponentName]),
40
+ children: z.array(z.union([Id, Text])),
41
+ });
42
+
43
+ export type InstancesItem = z.infer<typeof InstancesItem>;
44
+
45
+ export const Instances = z.array(InstancesItem);
46
+
47
+ export type Instances = z.infer<typeof Instances>;
48
+
49
+ export const Instance: z.ZodType<Instance> = z.lazy(() =>
32
50
  z.object({
33
- type: z.literal("text"),
34
- value: z.string(),
51
+ type: z.literal("instance"),
52
+ id: z.string(),
53
+ component: z.enum(getComponentNames() as [ComponentName]),
54
+ children: z.array(z.union([Instance, Text])),
35
55
  })
36
56
  );
37
-
38
- export const Instance = z.lazy(
39
- () =>
40
- z.object({
41
- type: z.literal("instance"),
42
- id: z.string(),
43
- component: z.string(),
44
- children: z.array(z.union([Instance, Text])),
45
- cssRules: z.array(CssRule),
46
- })
47
- // @todo can't figure out how to make component to be z.enum(Object.keys(components))
48
- ) as z.ZodType<Instance>;
@@ -0,0 +1,63 @@
1
+ import { z } from "zod";
2
+ import type { StyleProperty, StyleValue } from "@webstudio-is/css-data";
3
+ import { SharedStyleValue } from "@webstudio-is/css-data";
4
+ import {
5
+ type ComponentName,
6
+ getComponentMeta,
7
+ getComponentNames,
8
+ } from "../components";
9
+
10
+ export const PresetStylesItem = z.object({
11
+ component: z.enum(getComponentNames() as [ComponentName]),
12
+ // @todo can't figure out how to make property to be enum
13
+ property: z.string() as z.ZodType<StyleProperty>,
14
+ value: SharedStyleValue as z.ZodType<StyleValue>,
15
+ });
16
+
17
+ export type PresetStylesItem = z.infer<typeof PresetStylesItem>;
18
+
19
+ export const PresetStyles = z.array(PresetStylesItem);
20
+
21
+ export type PresetStyles = z.infer<typeof PresetStyles>;
22
+
23
+ export const findMissingPresetStyles = (
24
+ presetStyles: PresetStyles,
25
+ components: ComponentName[]
26
+ ) => {
27
+ const populatedComponents = new Set();
28
+ for (const style of presetStyles) {
29
+ populatedComponents.add(style.component);
30
+ }
31
+ const missingPresetStyles: PresetStyles = [];
32
+ for (const component of components) {
33
+ if (populatedComponents.has(component)) {
34
+ continue;
35
+ }
36
+ const meta = getComponentMeta(component);
37
+ if (meta.presetStyle === undefined) {
38
+ continue;
39
+ }
40
+ for (const [property, value] of Object.entries(meta.presetStyle)) {
41
+ missingPresetStyles.push({
42
+ component,
43
+ property: property as StyleProperty,
44
+ value,
45
+ });
46
+ }
47
+ }
48
+ return missingPresetStyles;
49
+ };
50
+
51
+ export const StylesItem = z.object({
52
+ breakpointId: z.string(),
53
+ instanceId: z.string(),
54
+ // @todo can't figure out how to make property to be enum
55
+ property: z.string() as z.ZodType<StyleProperty>,
56
+ value: SharedStyleValue as z.ZodType<StyleValue>,
57
+ });
58
+
59
+ export type StylesItem = z.infer<typeof StylesItem>;
60
+
61
+ export const Styles = z.array(StylesItem);
62
+
63
+ export type Styles = z.infer<typeof Styles>;
package/src/db/types.ts CHANGED
@@ -1,10 +1,13 @@
1
1
  import type { InstanceProps as DbInstanceProps } from "@webstudio-is/prisma-client";
2
2
  import type { UserProp } from "../user-props";
3
3
  import type { Instance } from "./instance";
4
+ import type { PresetStyles, Styles } from "./style";
4
5
 
5
6
  export type Tree = {
6
7
  id: string;
7
8
  root: Instance;
9
+ presetStyles: PresetStyles;
10
+ styles: Styles;
8
11
  };
9
12
 
10
13
  export type Props = {
@@ -13,6 +16,7 @@ export type Props = {
13
16
  instanceId: string;
14
17
  treeId: string;
15
18
  };
19
+
16
20
  export type InstanceProps = Omit<DbInstanceProps, "props"> & {
17
21
  props: Array<UserProp>;
18
22
  };
@@ -41,10 +41,16 @@ export const WrapperComponent = ({
41
41
  }: WrapperComponentProps) => {
42
42
  const Component = getComponent(instance.component);
43
43
  const userProps = useUserProps(instance.id);
44
- const props = { ...userProps, ...rest, [idAttribute]: instance.id };
44
+ const props = {
45
+ ...userProps,
46
+ ...rest,
47
+ [idAttribute]: instance.id,
48
+ [componentAttribute]: instance.component,
49
+ };
45
50
  return (
46
51
  <Component {...props}>{renderWrapperComponentChildren(children)}</Component>
47
52
  );
48
53
  };
49
54
 
50
55
  export const idAttribute = "data-ws-id";
56
+ export const componentAttribute = "data-ws-component";
@@ -1,22 +1,26 @@
1
1
  import { useRef } from "react";
2
- import { createValueContainer, useValue } from "react-nano-state";
2
+ import { atom } from "nanostores";
3
+ import { useStore } from "@nanostores/react";
3
4
  import type { InstanceProps, Instance } from "../db";
5
+ import { UserProp } from "./schema";
4
6
 
5
- export type AllUserProps = { [id: Instance["id"]]: InstanceProps };
7
+ export type AllUserProps = {
8
+ [id: Instance["id"]]: UserProp[];
9
+ };
6
10
 
7
- export const allUserPropsContainer = createValueContainer<AllUserProps>({});
11
+ export const allUserPropsContainer = atom<AllUserProps>({});
8
12
 
9
13
  export const useAllUserProps = (initialUserProps?: Array<InstanceProps>) => {
10
14
  // @todo ssr workaround for https://github.com/webstudio-is/webstudio-designer/issues/213
11
15
  const ref = useRef(false);
12
16
  if (ref.current === false && initialUserProps !== undefined) {
13
17
  const propsMap: AllUserProps = {};
14
- for (const props of initialUserProps) {
15
- propsMap[props.instanceId] = props;
18
+ for (const item of initialUserProps) {
19
+ propsMap[item.instanceId] = item.props;
16
20
  }
17
21
  //We don't need to trigger rerender when setting the initial value
18
- allUserPropsContainer.value = propsMap;
22
+ allUserPropsContainer.set(propsMap);
19
23
  ref.current = true;
20
24
  }
21
- return useValue(allUserPropsContainer);
25
+ return useStore(allUserPropsContainer);
22
26
  };
@@ -1,4 +1,3 @@
1
1
  export * from "./all-user-props";
2
2
  export * from "./use-user-props";
3
- export * from "./types";
4
3
  export * from "./schema";
@@ -11,14 +11,14 @@ export const useUserPropsAsset = (
11
11
  instanceId: Instance["id"],
12
12
  propName: UserProp["prop"]
13
13
  ): Asset | undefined => {
14
- const [allUserProps] = useAllUserProps();
14
+ const allUserProps = useAllUserProps();
15
15
 
16
16
  const propsData = allUserProps[instanceId];
17
17
  const asset = useMemo(() => {
18
18
  if (propsData == null) {
19
19
  return undefined;
20
20
  }
21
- const prop = propsData.props.find((prop) => prop.prop === propName);
21
+ const prop = propsData.find((prop) => prop.prop === propName);
22
22
 
23
23
  if (prop == null) {
24
24
  return undefined;
@@ -10,7 +10,7 @@ type UserProps = { [prop: UserProp["prop"]]: string | number | boolean };
10
10
  * up to date with props panel.
11
11
  */
12
12
  export const useUserProps = (instanceId: Instance["id"]) => {
13
- const [allUserProps] = useAllUserProps();
13
+ const allUserProps = useAllUserProps();
14
14
 
15
15
  const propsData = allUserProps[instanceId];
16
16
  const props = useMemo(() => {
@@ -19,7 +19,7 @@ export const useUserProps = (instanceId: Instance["id"]) => {
19
19
  }
20
20
  const result: UserProps = {};
21
21
 
22
- for (const userProp of propsData.props) {
22
+ for (const userProp of propsData) {
23
23
  if (userProp.type !== "asset") {
24
24
  result[userProp.prop] = userProp.value;
25
25
  }
@@ -1,16 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __copyProps = (to, from, except, desc) => {
7
- if (from && typeof from === "object" || typeof from === "function") {
8
- for (let key of __getOwnPropNames(from))
9
- if (!__hasOwnProp.call(to, key) && key !== except)
10
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
- }
12
- return to;
13
- };
14
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
- var types_exports = {};
16
- module.exports = __toCommonJS(types_exports);
File without changes
@@ -1,13 +0,0 @@
1
- import type { InstanceProps, Instance } from "../db";
2
- import { UserProp } from "./schema";
3
-
4
- export type UserPropsUpdates = {
5
- instanceId: Instance["id"];
6
- propsId?: InstanceProps["id"];
7
- updates: Array<UserProp>;
8
- };
9
-
10
- export type DeleteProp = {
11
- instanceId: Instance["id"];
12
- propId: UserProp["id"];
13
- };