mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-11-09 14:03:33 +09:00
Represent styles as map (#1008)
Ref https://github.com/webstudio-is/webstudio-designer/issues/696 Here patches by styles indexes are replaced with patch by key to prevent conflicts while collaborating. The unusual part here is map key whiich is combined from a few fields: "styleSourceId:breakpointId:property" This format is enforced with typescript to always use utility getStyleDeclKey to access specific style.
This commit is contained in:
1 parent
2e43ba1b39
commit
85f5f832aa
18 files changed
+191
-142
No files matched your search
@@ -1,6 +1,6 @@
|
||||
import { useEffect } from "react";
|
||||
import { useStore } from "@nanostores/react";
|
||||
import type { Instance, Prop, Styles } from "@webstudio-is/project-build";
|
||||
import type { Instance, Prop, StyleDecl } from "@webstudio-is/project-build";
|
||||
import { getBrowserStyle } from "@webstudio-is/react-sdk";
|
||||
import { publish, subscribe } from "~/shared/pubsub";
|
||||
import {
|
||||
@@ -57,7 +57,7 @@ export const SelectedInstanceConnector = ({
|
||||
}: {
|
||||
instanceElementRef: { current: undefined | HTMLElement };
|
||||
instance: Instance;
|
||||
instanceStyles: Styles;
|
||||
instanceStyles: StyleDecl[];
|
||||
instanceProps: undefined | Prop[];
|
||||
}) => {
|
||||
const rootInstance = useStore(rootInstanceContainer);
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
selectedInstanceIdStore,
|
||||
useBreakpoints,
|
||||
} from "~/shared/nano-states";
|
||||
import type { Styles } from "@webstudio-is/project-build";
|
||||
import type { StyleDecl } from "@webstudio-is/project-build";
|
||||
import {
|
||||
getComponentMeta,
|
||||
getComponentNames,
|
||||
@@ -159,7 +159,7 @@ export const useCssRules = ({
|
||||
instanceStyles,
|
||||
}: {
|
||||
instanceId: string;
|
||||
instanceStyles: Styles;
|
||||
instanceStyles: StyleDecl[];
|
||||
}) => {
|
||||
const [breakpoints] = useBreakpoints();
|
||||
|
||||
|
||||
@@ -69,11 +69,13 @@ export const Breakpoints = () => {
|
||||
const [updatedBreakpoints] = store.createTransaction(
|
||||
[breakpointsContainer, stylesStore],
|
||||
(breakpoints, styles) => {
|
||||
removeByMutable(breakpoints, ({ id }) => id === breakpointToDelete.id);
|
||||
removeByMutable(
|
||||
styles,
|
||||
(style) => style.breakpointId === breakpointToDelete.id
|
||||
);
|
||||
const breakpointId = breakpointToDelete.id;
|
||||
removeByMutable(breakpoints, ({ id }) => id === breakpointId);
|
||||
for (const [styleDeclKey, styleDecl] of styles) {
|
||||
if (styleDecl.breakpointId === breakpointId) {
|
||||
styles.delete(styleDeclKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
if (breakpointToDelete === selectedBreakpoint) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { Breakpoint } from "@webstudio-is/css-data";
|
||||
import type { Instance, Styles } from "@webstudio-is/project-build";
|
||||
import type { Instance, StyleDecl } from "@webstudio-is/project-build";
|
||||
import {
|
||||
getCascadedBreakpointIds,
|
||||
getCascadedInfo,
|
||||
@@ -36,7 +36,7 @@ const cascadedBreakpointIds = getCascadedBreakpointIds(
|
||||
selectedBreakpointId
|
||||
);
|
||||
|
||||
const cascadingStylesByInstanceId = new Map<Instance["id"], Styles>();
|
||||
const cascadingStylesByInstanceId = new Map<Instance["id"], StyleDecl[]>();
|
||||
cascadingStylesByInstanceId.set(selectedInstanceId, [
|
||||
{
|
||||
breakpointId: "1",
|
||||
@@ -92,7 +92,7 @@ const rootInstance: Instance = {
|
||||
],
|
||||
};
|
||||
|
||||
const inheritingStylesByInstanceId = new Map<Instance["id"], Styles>();
|
||||
const inheritingStylesByInstanceId = new Map<Instance["id"], StyleDecl[]>();
|
||||
inheritingStylesByInstanceId.set("1", [
|
||||
// should be inherited even from another breakpoint
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ import { properties } from "@webstudio-is/css-data";
|
||||
import { utils } from "@webstudio-is/project";
|
||||
import type {
|
||||
Instance,
|
||||
Styles,
|
||||
StyleDecl,
|
||||
StyleSource as StyleSourceType,
|
||||
} from "@webstudio-is/project-build";
|
||||
import {
|
||||
@@ -81,7 +81,7 @@ for (const [property, value] of Object.entries(properties)) {
|
||||
}
|
||||
|
||||
const getSelectedStyle = (
|
||||
stylesByStyleSourceId: Map<StyleSourceType["id"], Styles>,
|
||||
stylesByStyleSourceId: Map<StyleSourceType["id"], StyleDecl[]>,
|
||||
breakpointId: string,
|
||||
styleSourceId: string
|
||||
) => {
|
||||
@@ -121,7 +121,7 @@ export const getCascadedBreakpointIds = (
|
||||
* affecting current view
|
||||
*/
|
||||
export const getCascadedInfo = (
|
||||
stylesByInstanceId: Map<Instance["id"], Styles>,
|
||||
stylesByInstanceId: Map<Instance["id"], StyleDecl[]>,
|
||||
instanceId: string,
|
||||
cascadedBreakpointIds: string[]
|
||||
) => {
|
||||
@@ -149,7 +149,7 @@ export const getCascadedInfo = (
|
||||
*/
|
||||
export const getInheritedInfo = (
|
||||
rootInstance: Instance,
|
||||
stylesByInstanceId: Map<Instance["id"], Styles>,
|
||||
stylesByInstanceId: Map<Instance["id"], StyleDecl[]>,
|
||||
instanceId: string,
|
||||
cascadedBreakpointIds: string[],
|
||||
selectedBreakpointId: string
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useCallback } from "react";
|
||||
import store from "immerhin";
|
||||
import warnOnce from "warn-once";
|
||||
import type { Instance } from "@webstudio-is/project-build";
|
||||
import { getStyleDeclKey, type Instance } from "@webstudio-is/project-build";
|
||||
import type { StyleUpdates } from "@webstudio-is/project";
|
||||
import type { StyleProperty, StyleValue } from "@webstudio-is/css-data";
|
||||
import { type Publish } from "~/shared/pubsub";
|
||||
@@ -12,10 +12,6 @@ import {
|
||||
stylesStore,
|
||||
} from "~/shared/nano-states";
|
||||
import { useSelectedBreakpoint } from "~/designer/shared/nano-states";
|
||||
import {
|
||||
removeByMutable,
|
||||
replaceByOrAppendMutable,
|
||||
} from "~/shared/array-utils";
|
||||
// @todo: must be removed, now it's only for compatibility with existing code
|
||||
import { parseCssValue } from "./parse-css-value";
|
||||
import { useStyleInfo } from "./style-info";
|
||||
@@ -101,29 +97,22 @@ export const useStyleData = ({ selectedInstance, publish }: UseStyleData) => {
|
||||
|
||||
for (const update of updates) {
|
||||
if (update.operation === "set") {
|
||||
replaceByOrAppendMutable(
|
||||
styles,
|
||||
{
|
||||
breakpointId,
|
||||
styleSourceId,
|
||||
property: update.property,
|
||||
value: update.value,
|
||||
},
|
||||
(item) =>
|
||||
item.styleSourceId === styleSourceId &&
|
||||
item.breakpointId === breakpointId &&
|
||||
item.property === update.property
|
||||
);
|
||||
const styleDecl = {
|
||||
breakpointId,
|
||||
styleSourceId,
|
||||
property: update.property,
|
||||
value: update.value,
|
||||
};
|
||||
styles.set(getStyleDeclKey(styleDecl), styleDecl);
|
||||
}
|
||||
|
||||
if (update.operation === "delete") {
|
||||
removeByMutable(
|
||||
styles,
|
||||
(item) =>
|
||||
item.styleSourceId === styleSourceId &&
|
||||
item.breakpointId === breakpointId &&
|
||||
item.property === update.property
|
||||
);
|
||||
const styleDeclKey = getStyleDeclKey({
|
||||
breakpointId,
|
||||
styleSourceId,
|
||||
property: update.property,
|
||||
});
|
||||
styles.delete(styleDeclKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,10 @@ import store from "immerhin";
|
||||
import { z } from "zod";
|
||||
import { useEffect } from "react";
|
||||
import {
|
||||
getStyleDeclKey,
|
||||
Instance,
|
||||
Prop,
|
||||
Styles,
|
||||
StyleDecl,
|
||||
StyleSource,
|
||||
StyleSourceSelection,
|
||||
} from "@webstudio-is/project-build";
|
||||
@@ -37,7 +38,7 @@ const InstanceData = z.object({
|
||||
props: z.array(Prop),
|
||||
styleSourceSelections: z.array(StyleSourceSelection),
|
||||
styleSources: z.array(StyleSource),
|
||||
styles: Styles,
|
||||
styles: z.array(StyleDecl),
|
||||
});
|
||||
|
||||
type InstanceData = z.infer<typeof InstanceData>;
|
||||
@@ -118,7 +119,9 @@ const pasteInstance = (data: InstanceData) => {
|
||||
for (const styleSource of data.styleSources) {
|
||||
styleSources.set(styleSource.id, styleSource);
|
||||
}
|
||||
styles.push(...data.styles);
|
||||
for (const styleDecl of data.styles) {
|
||||
styles.set(getStyleDeclKey(styleDecl), styleDecl);
|
||||
}
|
||||
}
|
||||
);
|
||||
selectedInstanceIdStore.set(data.instance.id);
|
||||
|
||||
@@ -58,7 +58,7 @@ export const generateCssText = async (
|
||||
}
|
||||
|
||||
const styleRules = getStyleRules(
|
||||
canvasData.build?.styles,
|
||||
new Map(canvasData.build?.styles),
|
||||
new Map(canvasData.tree?.styleSourceSelections)
|
||||
);
|
||||
for (const { breakpointId, instanceId, style } of styleRules) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import store from "immerhin";
|
||||
import { Instance } from "@webstudio-is/project-build";
|
||||
import type { Instance } from "@webstudio-is/project-build";
|
||||
import {
|
||||
rootInstanceContainer,
|
||||
propsStore,
|
||||
@@ -86,9 +86,11 @@ export const deleteInstance = (targetInstanceId: Instance["id"]) => {
|
||||
for (const styleSourceId of subtreeLocalStyleSourceIds) {
|
||||
styleSources.delete(styleSourceId);
|
||||
}
|
||||
removeByMutable(styles, (styleDecl) =>
|
||||
subtreeLocalStyleSourceIds.has(styleDecl.styleSourceId)
|
||||
);
|
||||
for (const [styleDeclKey, styleDecl] of styles) {
|
||||
if (subtreeLocalStyleSourceIds.has(styleDecl.styleSourceId)) {
|
||||
styles.delete(styleDeclKey);
|
||||
}
|
||||
}
|
||||
|
||||
selectedInstanceIdStore.set(parentInstance.id);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import {
|
||||
Instance,
|
||||
Prop,
|
||||
Props,
|
||||
StyleDecl,
|
||||
StyleDeclKey,
|
||||
Styles,
|
||||
StyleSource,
|
||||
StyleSources,
|
||||
@@ -86,11 +88,11 @@ export const useInstanceProps = (instanceId: undefined | Instance["id"]) => {
|
||||
return instanceProps;
|
||||
};
|
||||
|
||||
export const stylesStore = atom<Styles>([]);
|
||||
export const stylesStore = atom<Styles>(new Map());
|
||||
|
||||
export const useSetStyles = (styles: Styles) => {
|
||||
export const useSetStyles = (styles: [StyleDeclKey, StyleDecl][]) => {
|
||||
useSyncInitializeOnce(() => {
|
||||
stylesStore.set(styles);
|
||||
stylesStore.set(new Map(styles));
|
||||
});
|
||||
};
|
||||
export const useInstanceStyles = (instanceId: undefined | Instance["id"]) => {
|
||||
@@ -165,8 +167,8 @@ export const selectedStyleSourceIdStore = atom<undefined | StyleSource["id"]>(
|
||||
export const stylesIndexStore = computed(
|
||||
[stylesStore, styleSourceSelectionsStore],
|
||||
(styles, styleSourceSelections) => {
|
||||
const stylesByStyleSourceId = new Map<StyleSource["id"], Styles>();
|
||||
for (const styleDecl of styles) {
|
||||
const stylesByStyleSourceId = new Map<StyleSource["id"], StyleDecl[]>();
|
||||
for (const styleDecl of styles.values()) {
|
||||
const { styleSourceId } = styleDecl;
|
||||
let styleSourceStyles = stylesByStyleSourceId.get(styleSourceId);
|
||||
if (styleSourceStyles === undefined) {
|
||||
@@ -176,9 +178,9 @@ export const stylesIndexStore = computed(
|
||||
styleSourceStyles.push(styleDecl);
|
||||
}
|
||||
|
||||
const stylesByInstanceId = new Map<Instance["id"], Styles>();
|
||||
const stylesByInstanceId = new Map<Instance["id"], StyleDecl[]>();
|
||||
for (const { instanceId, values } of styleSourceSelections.values()) {
|
||||
const instanceStyles: Styles = [];
|
||||
const instanceStyles: StyleDecl[] = [];
|
||||
for (const styleSourceId of values) {
|
||||
const styleSourceStyles = stylesByStyleSourceId.get(styleSourceId);
|
||||
if (styleSourceStyles) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import type {
|
||||
Instance,
|
||||
Prop,
|
||||
StyleDecl,
|
||||
Styles,
|
||||
StyleSource,
|
||||
StyleSourceSelection,
|
||||
} from "@webstudio-is/project-build";
|
||||
@@ -73,7 +74,10 @@ const createStyleSourceSelection = (
|
||||
};
|
||||
};
|
||||
|
||||
const createStyleDecl = (styleSourceId: string): StyleDecl => {
|
||||
const createStyleDecl = (
|
||||
styleSourceId: string,
|
||||
breakpointId: string
|
||||
): StyleDecl => {
|
||||
return {
|
||||
styleSourceId,
|
||||
breakpointId: "breakpointId",
|
||||
@@ -389,21 +393,21 @@ test("clone style source selections with applied instance ids and style source i
|
||||
});
|
||||
|
||||
test("clone styles with appled new style source ids", () => {
|
||||
const styles = [
|
||||
createStyleDecl("styleSource1"),
|
||||
createStyleDecl("styleSource2"),
|
||||
createStyleDecl("styleSource1"),
|
||||
createStyleDecl("styleSource3"),
|
||||
createStyleDecl("styleSource1"),
|
||||
createStyleDecl("styleSource3"),
|
||||
];
|
||||
const styles: Styles = new Map([
|
||||
[`styleSource1:bp1:width`, createStyleDecl("styleSource1", "bp1")],
|
||||
[`styleSource2:bp2:width`, createStyleDecl("styleSource2", "bp2")],
|
||||
[`styleSource1:bp3:width`, createStyleDecl("styleSource1", "bp3")],
|
||||
[`styleSource3:bp4:width`, createStyleDecl("styleSource3", "bp4")],
|
||||
[`styleSource1:bp5:width`, createStyleDecl("styleSource1", "bp5")],
|
||||
[`styleSource3:bp6:width`, createStyleDecl("styleSource3", "bp6")],
|
||||
]);
|
||||
const clonedStyleSourceIds = new Map<StyleSource["id"], StyleSource["id"]>();
|
||||
clonedStyleSourceIds.set("styleSource2", "newStyleSource2");
|
||||
clonedStyleSourceIds.set("styleSource3", "newStyleSource3");
|
||||
expect(cloneStyles(styles, clonedStyleSourceIds)).toEqual([
|
||||
createStyleDecl("newStyleSource2"),
|
||||
createStyleDecl("newStyleSource3"),
|
||||
createStyleDecl("newStyleSource3"),
|
||||
createStyleDecl("newStyleSource2", "bp2"),
|
||||
createStyleDecl("newStyleSource3", "bp4"),
|
||||
createStyleDecl("newStyleSource3", "bp6"),
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import type {
|
||||
Instance,
|
||||
Prop,
|
||||
Props,
|
||||
StyleDecl,
|
||||
Styles,
|
||||
StyleSource,
|
||||
StyleSources,
|
||||
@@ -277,8 +278,8 @@ export const cloneStyles = (
|
||||
styles: Styles,
|
||||
clonedStyleSourceIds: Map<Instance["id"], Instance["id"]>
|
||||
) => {
|
||||
const clonedStyles: Styles = [];
|
||||
for (const styleDecl of styles) {
|
||||
const clonedStyles: StyleDecl[] = [];
|
||||
for (const styleDecl of styles.values()) {
|
||||
const styleSourceId = clonedStyleSourceIds.get(styleDecl.styleSourceId);
|
||||
if (styleSourceId === undefined) {
|
||||
continue;
|
||||
|
||||
@@ -34,6 +34,15 @@ export const StyleDecl = z.object({
|
||||
|
||||
export type StyleDecl = z.infer<typeof StyleDecl>;
|
||||
|
||||
export const Styles = z.array(StyleDecl);
|
||||
export type StyleDeclKey =
|
||||
`${StyleDecl["styleSourceId"]}:${StyleDecl["breakpointId"]}:${StyleDecl["property"]}`;
|
||||
|
||||
export const getStyleDeclKey = (
|
||||
styleDecl: Omit<StyleDecl, "value">
|
||||
): StyleDeclKey => {
|
||||
return `${styleDecl.styleSourceId}:${styleDecl.breakpointId}:${styleDecl.property}`;
|
||||
};
|
||||
|
||||
export const Styles = z.map(z.string() as z.ZodType<StyleDeclKey>, StyleDecl);
|
||||
|
||||
export type Styles = z.infer<typeof Styles>;
|
||||
@@ -23,7 +23,7 @@ const parseBuild = async (build: DbBuild): Promise<Build> => {
|
||||
createdAt: build.createdAt.toISOString(),
|
||||
pages,
|
||||
breakpoints: Breakpoints.parse(JSON.parse(build.breakpoints)),
|
||||
styles: await parseStyles(build.projectId, build.styles),
|
||||
styles: Array.from(await parseStyles(build.projectId, build.styles)),
|
||||
styleSources: Array.from(parseStyleSources(build.styleSources)),
|
||||
};
|
||||
};
|
||||
@@ -321,9 +321,9 @@ export async function create(
|
||||
breakpoints: JSON.stringify(
|
||||
props.sourceBuild?.breakpoints ?? db.breakpoints.createValues()
|
||||
),
|
||||
styles: serializeStyles(props.sourceBuild?.styles ?? []),
|
||||
styles: serializeStyles(new Map(props.sourceBuild?.styles)),
|
||||
styleSources: serializeStyleSources(
|
||||
new Map(props.sourceBuild?.styleSources ?? [])
|
||||
new Map(props.sourceBuild?.styleSources)
|
||||
),
|
||||
isDev: props.env === "dev",
|
||||
isProd: props.env === "prod",
|
||||
|
||||
@@ -3,7 +3,13 @@ import { type Patch, applyPatches } from "immer";
|
||||
import { prisma } from "@webstudio-is/prisma-client";
|
||||
import type { Asset } from "@webstudio-is/asset-uploader";
|
||||
import { formatAsset } from "@webstudio-is/asset-uploader/server";
|
||||
import { StoredStyles, Styles } from "@webstudio-is/project-build";
|
||||
import {
|
||||
type StoredStyleDecl,
|
||||
type StyleDecl,
|
||||
getStyleDeclKey,
|
||||
StoredStyles,
|
||||
Styles,
|
||||
} from "@webstudio-is/project-build";
|
||||
import type { Build, Project } from "../shared/schema";
|
||||
import {
|
||||
authorizeProject,
|
||||
@@ -11,7 +17,7 @@ import {
|
||||
} from "@webstudio-is/trpc-interface/server";
|
||||
|
||||
const parseValue = (
|
||||
styleValue: StoredStyles[number]["value"],
|
||||
styleValue: StoredStyleDecl["value"],
|
||||
assetsMap: Map<string, Asset>
|
||||
) => {
|
||||
if (styleValue.type === "image") {
|
||||
@@ -67,14 +73,16 @@ export const parseStyles = async (
|
||||
assetsMap.set(asset.id, formatAsset(asset));
|
||||
}
|
||||
|
||||
const styles: Styles = storedStyles.map((styleDecl) => {
|
||||
return {
|
||||
styleSourceId: styleDecl.styleSourceId,
|
||||
breakpointId: styleDecl.breakpointId,
|
||||
property: styleDecl.property,
|
||||
value: parseValue(styleDecl.value, assetsMap),
|
||||
const styles: Styles = new Map();
|
||||
for (const storedStyleDecl of storedStyles) {
|
||||
const styleDecl = {
|
||||
styleSourceId: storedStyleDecl.styleSourceId,
|
||||
breakpointId: storedStyleDecl.breakpointId,
|
||||
property: storedStyleDecl.property,
|
||||
value: parseValue(storedStyleDecl.value, assetsMap),
|
||||
};
|
||||
});
|
||||
styles.set(getStyleDeclKey(styleDecl), styleDecl);
|
||||
}
|
||||
|
||||
return styles;
|
||||
};
|
||||
@@ -82,7 +90,7 @@ export const parseStyles = async (
|
||||
/**
|
||||
* prepare value to store in db
|
||||
*/
|
||||
const serializeValue = (styleValue: Styles[number]["value"]) => {
|
||||
const serializeValue = (styleValue: StyleDecl["value"]) => {
|
||||
if (styleValue.type === "image") {
|
||||
return {
|
||||
type: "image" as const,
|
||||
@@ -97,14 +105,17 @@ const serializeValue = (styleValue: Styles[number]["value"]) => {
|
||||
};
|
||||
|
||||
export const serializeStyles = (styles: Styles) => {
|
||||
const storedStyles: StoredStyles = styles.map((styleDecl) => {
|
||||
return {
|
||||
breakpointId: styleDecl.breakpointId,
|
||||
styleSourceId: styleDecl.styleSourceId,
|
||||
property: styleDecl.property,
|
||||
value: serializeValue(styleDecl.value),
|
||||
};
|
||||
});
|
||||
const storedStyles: StoredStyles = Array.from(
|
||||
styles.values(),
|
||||
(styleDecl) => {
|
||||
return {
|
||||
breakpointId: styleDecl.breakpointId,
|
||||
styleSourceId: styleDecl.styleSourceId,
|
||||
property: styleDecl.property,
|
||||
value: serializeValue(styleDecl.value),
|
||||
};
|
||||
}
|
||||
);
|
||||
return JSON.stringify(storedStyles);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import { z, type ZodType } from "zod";
|
||||
import type { Breakpoints } from "@webstudio-is/css-data";
|
||||
import type { Styles, StyleSource } from "@webstudio-is/project-build";
|
||||
import type {
|
||||
StyleDecl,
|
||||
StyleDeclKey,
|
||||
StyleSource,
|
||||
} from "@webstudio-is/project-build";
|
||||
import type { Data } from "@webstudio-is/react-sdk";
|
||||
|
||||
const MIN_TITLE_LENGTH = 2;
|
||||
@@ -99,7 +103,7 @@ export type Build = {
|
||||
isProd: boolean;
|
||||
pages: Pages;
|
||||
breakpoints: Breakpoints;
|
||||
styles: Styles;
|
||||
styles: [StyleDeclKey, StyleDecl][];
|
||||
styleSources: [StyleSource["id"], StyleSource][];
|
||||
};
|
||||
|
||||
|
||||
@@ -6,50 +6,71 @@ import type {
|
||||
import { getStyleRules } from "./style-rules";
|
||||
|
||||
test("compute styles from different style sources", () => {
|
||||
const styles: Styles = [
|
||||
{
|
||||
breakpointId: "a",
|
||||
styleSourceId: "styleSource1",
|
||||
property: "width",
|
||||
value: { type: "unit", value: 10, unit: "px" },
|
||||
},
|
||||
{
|
||||
breakpointId: "a",
|
||||
styleSourceId: "styleSource2",
|
||||
property: "display",
|
||||
value: { type: "keyword", value: "block" },
|
||||
},
|
||||
{
|
||||
breakpointId: "a",
|
||||
styleSourceId: "styleSource4",
|
||||
property: "color",
|
||||
value: { type: "keyword", value: "green" },
|
||||
},
|
||||
{
|
||||
breakpointId: "a",
|
||||
styleSourceId: "styleSource4",
|
||||
property: "width",
|
||||
value: { type: "keyword", value: "min-content" },
|
||||
},
|
||||
{
|
||||
breakpointId: "a",
|
||||
styleSourceId: "styleSource3",
|
||||
property: "color",
|
||||
value: { type: "keyword", value: "red" },
|
||||
},
|
||||
{
|
||||
breakpointId: "b",
|
||||
styleSourceId: "styleSource5",
|
||||
property: "color",
|
||||
value: { type: "keyword", value: "orange" },
|
||||
},
|
||||
{
|
||||
breakpointId: "a",
|
||||
styleSourceId: "styleSource6",
|
||||
property: "color",
|
||||
value: { type: "keyword", value: "blue" },
|
||||
},
|
||||
];
|
||||
const styles: Styles = new Map([
|
||||
[
|
||||
"styleSource1:a:width",
|
||||
{
|
||||
breakpointId: "a",
|
||||
styleSourceId: "styleSource1",
|
||||
property: "width",
|
||||
value: { type: "unit", value: 10, unit: "px" },
|
||||
},
|
||||
],
|
||||
[
|
||||
"styleSource2:a:display",
|
||||
{
|
||||
breakpointId: "a",
|
||||
styleSourceId: "styleSource2",
|
||||
property: "display",
|
||||
value: { type: "keyword", value: "block" },
|
||||
},
|
||||
],
|
||||
[
|
||||
"styleSource4:a:color",
|
||||
{
|
||||
breakpointId: "a",
|
||||
styleSourceId: "styleSource4",
|
||||
property: "color",
|
||||
value: { type: "keyword", value: "green" },
|
||||
},
|
||||
],
|
||||
[
|
||||
"styleSource4:a:width",
|
||||
{
|
||||
breakpointId: "a",
|
||||
styleSourceId: "styleSource4",
|
||||
property: "width",
|
||||
value: { type: "keyword", value: "min-content" },
|
||||
},
|
||||
],
|
||||
[
|
||||
"styleSource3:a:color",
|
||||
{
|
||||
breakpointId: "a",
|
||||
styleSourceId: "styleSource3",
|
||||
property: "color",
|
||||
value: { type: "keyword", value: "red" },
|
||||
},
|
||||
],
|
||||
[
|
||||
"styleSource5:b:color",
|
||||
{
|
||||
breakpointId: "b",
|
||||
styleSourceId: "styleSource5",
|
||||
property: "color",
|
||||
value: { type: "keyword", value: "orange" },
|
||||
},
|
||||
],
|
||||
[
|
||||
"styleSource6:a:color",
|
||||
{
|
||||
breakpointId: "a",
|
||||
styleSourceId: "styleSource6",
|
||||
property: "color",
|
||||
value: { type: "keyword", value: "blue" },
|
||||
},
|
||||
],
|
||||
]);
|
||||
const styleSourceSelections: StyleSourceSelections = new Map([
|
||||
[
|
||||
"instance1",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { Breakpoint, Style } from "@webstudio-is/css-data";
|
||||
import type {
|
||||
StyleDecl,
|
||||
Styles,
|
||||
StyleSource,
|
||||
StyleSourceSelections,
|
||||
@@ -16,14 +17,14 @@ type StyleRule = {
|
||||
* and group by instance and breakpoint
|
||||
*/
|
||||
export const getStyleRules = (
|
||||
styles?: Styles,
|
||||
styleSourceSelections?: StyleSourceSelections
|
||||
styles: Styles,
|
||||
styleSourceSelections: StyleSourceSelections
|
||||
) => {
|
||||
if (styles === undefined || styleSourceSelections === undefined) {
|
||||
return [];
|
||||
}
|
||||
const stylesByStyleSourceId = new Map<StyleSource["id"], Styles>();
|
||||
for (const styleDecl of styles) {
|
||||
const stylesByStyleSourceId = new Map<StyleSource["id"], StyleDecl[]>();
|
||||
for (const styleDecl of styles.values()) {
|
||||
const { styleSourceId } = styleDecl;
|
||||
let styleSourceStyles = stylesByStyleSourceId.get(styleSourceId);
|
||||
// instance can be undefined when style is from other tree
|
||||
|
||||
Reference in new issue
Block a user