mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-11-08 21:15:18 +09:00
create a css rule when previewStyle was triggered before a css rule was created
when first action user does is not actually saving a style but uses any of the preview logic
This commit is contained in:
1 parent
005baac2ed
commit
1ae993edbb
1 file changed
+76
-58
@@ -15,56 +15,10 @@ import {
|
||||
validStaticValueTypes,
|
||||
} from "@webstudio-is/react-sdk";
|
||||
import { globalCss } from "@webstudio-is/design-system";
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useEffect } from "react";
|
||||
import { createCssEngine, type StyleRule } from "@webstudio-is/css-engine";
|
||||
import { useIsomorphicLayoutEffect } from "react-use";
|
||||
|
||||
const setCssVar = (id: string, property: string, value?: StyleValue) => {
|
||||
const customProperty = `--${toVarNamespace(id, property)}`;
|
||||
if (value === undefined) {
|
||||
document.body.style.removeProperty(customProperty);
|
||||
return;
|
||||
}
|
||||
document.body.style.setProperty(customProperty, toValue(value));
|
||||
};
|
||||
|
||||
const useUpdateStyle = () => {
|
||||
const [selectedInstance] = useSelectedInstance();
|
||||
useSubscribe("updateStyle", ({ id, updates, breakpoint }) => {
|
||||
// Only update styles if they match the selected instance
|
||||
// It can potentially happen that we selected a difference instance right after we changed the style in style panel.
|
||||
if (id !== selectedInstance?.id) return;
|
||||
|
||||
for (const update of updates) {
|
||||
setCssVar(id, update.property, undefined);
|
||||
}
|
||||
|
||||
store.createTransaction([rootInstanceContainer], (rootInstance) => {
|
||||
if (rootInstance === undefined) {
|
||||
return;
|
||||
}
|
||||
setInstanceStyleMutable(rootInstance, id, updates, breakpoint);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const usePreviewStyle = () => {
|
||||
useSubscribe("previewStyle", ({ id, updates }) => {
|
||||
for (const update of updates) {
|
||||
setCssVar(id, update.property, update.value);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Once we rendered the tree in editing mode, we have rendered all styles in a <style> tag.
|
||||
// We keep the SSR styles just for the page on canvas to show up like it does in preview.
|
||||
const useRemoveSsrStyles = () => {
|
||||
useEffect(() => {
|
||||
const link = document.head.querySelector('[data-webstudio="ssr"]');
|
||||
link?.parentElement?.removeChild(link);
|
||||
}, []);
|
||||
};
|
||||
|
||||
const voidElements =
|
||||
"area, base, br, col, embed, hr, img, input, link, meta, source, track, wbr";
|
||||
|
||||
@@ -140,6 +94,24 @@ export const addMediaRules = (breakpoints: Array<Breakpoint>) => {
|
||||
}
|
||||
};
|
||||
|
||||
const wrappedRulesMap = new Map<string, StyleRule>();
|
||||
|
||||
const addRule = (id: string, cssRule: CssRule) => {
|
||||
const key = id + cssRule.breakpoint;
|
||||
const selectorText = `[data-ws-id="${id}"]`;
|
||||
const rule = cssEngine.addStyleRule(selectorText, {
|
||||
...cssRule,
|
||||
style: toVarStyleWithFallback(id, cssRule.style),
|
||||
});
|
||||
wrappedRulesMap.set(key, rule);
|
||||
return rule;
|
||||
};
|
||||
|
||||
const getRule = (id: string, breakpoint: string) => {
|
||||
const key = id + breakpoint;
|
||||
return wrappedRulesMap.get(key);
|
||||
};
|
||||
|
||||
export const useCssRules = ({
|
||||
id,
|
||||
cssRules,
|
||||
@@ -147,22 +119,15 @@ export const useCssRules = ({
|
||||
id: string;
|
||||
cssRules: Array<CssRule>;
|
||||
}) => {
|
||||
const ruleMap = useRef<Map<string, StyleRule>>(new Map());
|
||||
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
for (const cssRule of cssRules) {
|
||||
const key = id + cssRule.breakpoint;
|
||||
|
||||
let rule = ruleMap.current.get(key);
|
||||
const rule = getRule(id, cssRule.breakpoint);
|
||||
// It's the first time the rule is being used
|
||||
if (rule === undefined) {
|
||||
const selectorText = `[data-ws-id="${id}"]`;
|
||||
rule = cssEngine.addStyleRule(selectorText, {
|
||||
...cssRule,
|
||||
style: toVarStyleWithFallback(id, cssRule.style),
|
||||
});
|
||||
ruleMap.current.set(key, rule);
|
||||
addRule(id, cssRule);
|
||||
continue;
|
||||
}
|
||||
// It's an update to an existing rule
|
||||
const dynamicStyle = toVarStyleWithFallback(id, cssRule.style);
|
||||
let property: StyleProperty;
|
||||
for (property in dynamicStyle) {
|
||||
@@ -172,3 +137,56 @@ export const useCssRules = ({
|
||||
cssEngine.render();
|
||||
}, [id, cssRules]);
|
||||
};
|
||||
|
||||
const setCssVar = (id: string, property: string, value?: StyleValue) => {
|
||||
const customProperty = `--${toVarNamespace(id, property)}`;
|
||||
if (value === undefined) {
|
||||
document.body.style.removeProperty(customProperty);
|
||||
return;
|
||||
}
|
||||
document.body.style.setProperty(customProperty, toValue(value));
|
||||
};
|
||||
|
||||
const useUpdateStyle = () => {
|
||||
const [selectedInstance] = useSelectedInstance();
|
||||
useSubscribe("updateStyle", ({ id, updates, breakpoint }) => {
|
||||
// Only update styles if they match the selected instance
|
||||
// It can potentially happen that we selected a difference instance right after we changed the style in style panel.
|
||||
if (id !== selectedInstance?.id) return;
|
||||
|
||||
for (const update of updates) {
|
||||
setCssVar(id, update.property, undefined);
|
||||
}
|
||||
|
||||
store.createTransaction([rootInstanceContainer], (rootInstance) => {
|
||||
if (rootInstance === undefined) {
|
||||
return;
|
||||
}
|
||||
setInstanceStyleMutable(rootInstance, id, updates, breakpoint);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const usePreviewStyle = () => {
|
||||
useSubscribe("previewStyle", ({ id, updates, breakpoint }) => {
|
||||
if (getRule(id, breakpoint.id) === undefined) {
|
||||
const rule = addRule(id, { breakpoint: breakpoint.id, style: {} });
|
||||
for (const update of updates) {
|
||||
rule.styleMap.set(update.property, update.value);
|
||||
}
|
||||
cssEngine.render();
|
||||
}
|
||||
for (const update of updates) {
|
||||
setCssVar(id, update.property, update.value);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Once we rendered the tree in editing mode, we have rendered all styles in a <style> tag.
|
||||
// We keep the SSR styles just for the page on canvas to show up like it does in preview.
|
||||
const useRemoveSsrStyles = () => {
|
||||
useEffect(() => {
|
||||
const link = document.head.querySelector('[data-webstudio="ssr"]');
|
||||
link?.parentElement?.removeChild(link);
|
||||
}, []);
|
||||
};
|
||||
Reference in new issue
Block a user