@webstudio-is/css-engine 0.95.0 → 0.97.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.
- package/lib/index.js +561 -3
- package/package.json +5 -5
- package/lib/__generated__/types.js +0 -1
- package/lib/core/compare-media.js +0 -16
- package/lib/core/compare-media.test.js +0 -63
- package/lib/core/create-css-engine.js +0 -5
- package/lib/core/css-engine.js +0 -105
- package/lib/core/css-engine.stories.js +0 -48
- package/lib/core/css-engine.test.js +0 -451
- package/lib/core/equal-media.js +0 -4
- package/lib/core/equal-media.test.js +0 -29
- package/lib/core/find-applicable-media.js +0 -11
- package/lib/core/find-applicable-media.test.js +0 -42
- package/lib/core/index.js +0 -9
- package/lib/core/match-media.js +0 -6
- package/lib/core/match-media.test.js +0 -22
- package/lib/core/rules.js +0 -162
- package/lib/core/style-element.js +0 -39
- package/lib/core/style-sheet.js +0 -14
- package/lib/core/to-property.js +0 -8
- package/lib/core/to-property.test.js +0 -11
- package/lib/core/to-value.js +0 -76
- package/lib/core/to-value.test.js +0 -123
- package/lib/schema.js +0 -98
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { describe, expect, test } from "@jest/globals";
|
|
3
|
-
import { matchMedia } from "./match-media";
|
|
4
|
-
describe("matchMedia", () => {
|
|
5
|
-
test("minWidth", () => {
|
|
6
|
-
expect(matchMedia({ minWidth: 100 }, 10)).toBe(false);
|
|
7
|
-
expect(matchMedia({ minWidth: 100 }, 100)).toBe(true);
|
|
8
|
-
expect(matchMedia({ minWidth: 100 }, 101)).toBe(true);
|
|
9
|
-
});
|
|
10
|
-
test("maxWidth", () => {
|
|
11
|
-
expect(matchMedia({ maxWidth: 100 }, 101)).toBe(false);
|
|
12
|
-
expect(matchMedia({ maxWidth: 100 }, 100)).toBe(true);
|
|
13
|
-
expect(matchMedia({ maxWidth: 100 }, 10)).toBe(true);
|
|
14
|
-
});
|
|
15
|
-
test("minWidth and maxWidth", () => {
|
|
16
|
-
expect(matchMedia({ maxWidth: 100, minWidth: 10 }, 9)).toBe(false);
|
|
17
|
-
expect(matchMedia({ maxWidth: 100, minWidth: 10 }, 101)).toBe(false);
|
|
18
|
-
expect(matchMedia({ maxWidth: 100, minWidth: 10 }, 100)).toBe(true);
|
|
19
|
-
expect(matchMedia({ maxWidth: 100, minWidth: 10 }, 10)).toBe(true);
|
|
20
|
-
expect(matchMedia({ maxWidth: 100, minWidth: 10 }, 11)).toBe(true);
|
|
21
|
-
});
|
|
22
|
-
});
|
package/lib/core/rules.js
DELETED
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { toValue } from "./to-value";
|
|
3
|
-
import { toProperty } from "./to-property";
|
|
4
|
-
class StylePropertyMap {
|
|
5
|
-
#styleMap = /* @__PURE__ */ new Map();
|
|
6
|
-
#isDirty = false;
|
|
7
|
-
#string = "";
|
|
8
|
-
#indent = 0;
|
|
9
|
-
#transformValue;
|
|
10
|
-
onChange;
|
|
11
|
-
constructor(transformValue) {
|
|
12
|
-
this.#transformValue = transformValue;
|
|
13
|
-
}
|
|
14
|
-
setTransformer(transformValue) {
|
|
15
|
-
this.#transformValue = transformValue;
|
|
16
|
-
}
|
|
17
|
-
set(property, value) {
|
|
18
|
-
this.#styleMap.set(property, value);
|
|
19
|
-
this.#isDirty = true;
|
|
20
|
-
this.onChange?.();
|
|
21
|
-
}
|
|
22
|
-
has(property) {
|
|
23
|
-
return this.#styleMap.has(property);
|
|
24
|
-
}
|
|
25
|
-
get size() {
|
|
26
|
-
return this.#styleMap.size;
|
|
27
|
-
}
|
|
28
|
-
keys() {
|
|
29
|
-
return this.#styleMap.keys();
|
|
30
|
-
}
|
|
31
|
-
delete(property) {
|
|
32
|
-
this.#styleMap.delete(property);
|
|
33
|
-
this.#isDirty = true;
|
|
34
|
-
this.onChange?.();
|
|
35
|
-
}
|
|
36
|
-
clear() {
|
|
37
|
-
this.#styleMap.clear();
|
|
38
|
-
this.#isDirty = true;
|
|
39
|
-
this.onChange?.();
|
|
40
|
-
}
|
|
41
|
-
toString({ indent = 0 } = {}) {
|
|
42
|
-
if (this.#isDirty === false && indent === this.#indent) {
|
|
43
|
-
return this.#string;
|
|
44
|
-
}
|
|
45
|
-
this.#indent = indent;
|
|
46
|
-
const block = [];
|
|
47
|
-
const spaces = " ".repeat(indent);
|
|
48
|
-
for (const [property, value] of this.#styleMap) {
|
|
49
|
-
if (value === void 0) {
|
|
50
|
-
continue;
|
|
51
|
-
}
|
|
52
|
-
block.push(
|
|
53
|
-
`${spaces}${toProperty(property)}: ${toValue(
|
|
54
|
-
value,
|
|
55
|
-
this.#transformValue
|
|
56
|
-
)}`
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
this.#string = block.join(";\n");
|
|
60
|
-
this.#isDirty = false;
|
|
61
|
-
return this.#string;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
export class StyleRule {
|
|
65
|
-
styleMap;
|
|
66
|
-
selectorText;
|
|
67
|
-
onChange;
|
|
68
|
-
constructor(selectorText, style, transformValue) {
|
|
69
|
-
this.styleMap = new StylePropertyMap(transformValue);
|
|
70
|
-
this.selectorText = selectorText;
|
|
71
|
-
let property;
|
|
72
|
-
for (property in style) {
|
|
73
|
-
this.styleMap.set(property, style[property]);
|
|
74
|
-
}
|
|
75
|
-
this.styleMap.onChange = this.#onChange;
|
|
76
|
-
}
|
|
77
|
-
#onChange = () => {
|
|
78
|
-
this.onChange?.();
|
|
79
|
-
};
|
|
80
|
-
get cssText() {
|
|
81
|
-
return this.toString();
|
|
82
|
-
}
|
|
83
|
-
toString(options = { indent: 0 }) {
|
|
84
|
-
const spaces = " ".repeat(options.indent);
|
|
85
|
-
return `${spaces}${this.selectorText} {
|
|
86
|
-
${this.styleMap.toString({
|
|
87
|
-
indent: options.indent + 2
|
|
88
|
-
})}
|
|
89
|
-
${spaces}}`;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
export class MediaRule {
|
|
93
|
-
options;
|
|
94
|
-
rules = [];
|
|
95
|
-
#mediaType;
|
|
96
|
-
constructor(options = {}) {
|
|
97
|
-
this.options = options;
|
|
98
|
-
this.#mediaType = options.mediaType ?? "all";
|
|
99
|
-
}
|
|
100
|
-
insertRule(rule) {
|
|
101
|
-
this.rules.push(rule);
|
|
102
|
-
return rule;
|
|
103
|
-
}
|
|
104
|
-
get cssText() {
|
|
105
|
-
return this.toString();
|
|
106
|
-
}
|
|
107
|
-
toString() {
|
|
108
|
-
if (this.rules.length === 0) {
|
|
109
|
-
return "";
|
|
110
|
-
}
|
|
111
|
-
const rules = [];
|
|
112
|
-
for (const rule of this.rules) {
|
|
113
|
-
rules.push(rule.toString({ indent: 2 }));
|
|
114
|
-
}
|
|
115
|
-
let conditionText = "";
|
|
116
|
-
const { minWidth, maxWidth } = this.options;
|
|
117
|
-
if (minWidth !== void 0) {
|
|
118
|
-
conditionText = ` and (min-width: ${minWidth}px)`;
|
|
119
|
-
}
|
|
120
|
-
if (maxWidth !== void 0) {
|
|
121
|
-
conditionText += ` and (max-width: ${maxWidth}px)`;
|
|
122
|
-
}
|
|
123
|
-
return `@media ${this.#mediaType}${conditionText} {
|
|
124
|
-
${rules.join(
|
|
125
|
-
"\n"
|
|
126
|
-
)}
|
|
127
|
-
}`;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
export class PlaintextRule {
|
|
131
|
-
cssText;
|
|
132
|
-
styleMap = new StylePropertyMap();
|
|
133
|
-
constructor(cssText) {
|
|
134
|
-
this.cssText = cssText;
|
|
135
|
-
}
|
|
136
|
-
toString() {
|
|
137
|
-
return this.cssText;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
export class FontFaceRule {
|
|
141
|
-
options;
|
|
142
|
-
constructor(options) {
|
|
143
|
-
this.options = options;
|
|
144
|
-
}
|
|
145
|
-
get cssText() {
|
|
146
|
-
return this.toString();
|
|
147
|
-
}
|
|
148
|
-
toString() {
|
|
149
|
-
const decls = [];
|
|
150
|
-
const { fontFamily, fontStyle, fontWeight, fontDisplay, src } = this.options;
|
|
151
|
-
decls.push(
|
|
152
|
-
`font-family: ${/\s/.test(fontFamily) ? `"${fontFamily}"` : fontFamily}`
|
|
153
|
-
);
|
|
154
|
-
decls.push(`font-style: ${fontStyle}`);
|
|
155
|
-
decls.push(`font-weight: ${fontWeight}`);
|
|
156
|
-
decls.push(`font-display: ${fontDisplay}`);
|
|
157
|
-
decls.push(`src: ${src}`);
|
|
158
|
-
return `@font-face {
|
|
159
|
-
${decls.join("; ")};
|
|
160
|
-
}`;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
export class StyleElement {
|
|
3
|
-
#element;
|
|
4
|
-
#name;
|
|
5
|
-
constructor(name = "") {
|
|
6
|
-
this.#name = name;
|
|
7
|
-
}
|
|
8
|
-
get isMounted() {
|
|
9
|
-
return this.#element?.parentElement != null;
|
|
10
|
-
}
|
|
11
|
-
mount() {
|
|
12
|
-
if (this.isMounted === false) {
|
|
13
|
-
this.#element = document.createElement("style");
|
|
14
|
-
this.#element.setAttribute("data-webstudio", this.#name);
|
|
15
|
-
document.head.appendChild(this.#element);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
unmount() {
|
|
19
|
-
if (this.isMounted) {
|
|
20
|
-
this.#element?.parentElement?.removeChild(this.#element);
|
|
21
|
-
this.#element = void 0;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
render(cssText) {
|
|
25
|
-
if (this.#element) {
|
|
26
|
-
this.#element.textContent = cssText;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
setAttribute(name, value) {
|
|
30
|
-
if (this.#element) {
|
|
31
|
-
this.#element.setAttribute(name, value);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
getAttribute(name) {
|
|
35
|
-
if (this.#element) {
|
|
36
|
-
return this.#element.getAttribute(name);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
package/lib/core/style-sheet.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
export class StyleSheet {
|
|
3
|
-
#cssText = "";
|
|
4
|
-
#element;
|
|
5
|
-
constructor(element) {
|
|
6
|
-
this.#element = element;
|
|
7
|
-
}
|
|
8
|
-
replaceSync(cssText) {
|
|
9
|
-
if (cssText !== this.#cssText) {
|
|
10
|
-
this.#cssText = cssText;
|
|
11
|
-
this.#element.render(cssText);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
}
|
package/lib/core/to-property.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { describe, test, expect } from "@jest/globals";
|
|
3
|
-
import { toProperty } from "./to-property";
|
|
4
|
-
describe("toProperty", () => {
|
|
5
|
-
test("boxSizing", () => {
|
|
6
|
-
expect(toProperty("boxSizing")).toBe("box-sizing");
|
|
7
|
-
});
|
|
8
|
-
test("backgroundClip", () => {
|
|
9
|
-
expect(toProperty("backgroundClip")).toBe("-webkit-background-clip");
|
|
10
|
-
});
|
|
11
|
-
});
|
package/lib/core/to-value.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { captureError } from "@webstudio-is/error-utils";
|
|
3
|
-
import { DEFAULT_FONT_FALLBACK, SYSTEM_FONTS } from "@webstudio-is/fonts";
|
|
4
|
-
const fallbackTransform = (styleValue) => {
|
|
5
|
-
if (styleValue.type === "fontFamily") {
|
|
6
|
-
const firstFontFamily = styleValue.value[0];
|
|
7
|
-
const fallbacks = SYSTEM_FONTS.get(firstFontFamily);
|
|
8
|
-
const fontFamily = [...styleValue.value];
|
|
9
|
-
if (Array.isArray(fallbacks)) {
|
|
10
|
-
fontFamily.push(...fallbacks);
|
|
11
|
-
} else {
|
|
12
|
-
fontFamily.push(DEFAULT_FONT_FALLBACK);
|
|
13
|
-
}
|
|
14
|
-
return {
|
|
15
|
-
type: "fontFamily",
|
|
16
|
-
value: fontFamily
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
export const toValue = (styleValue, transformValue) => {
|
|
21
|
-
if (styleValue === void 0) {
|
|
22
|
-
return "";
|
|
23
|
-
}
|
|
24
|
-
const transformedValue = transformValue?.(styleValue) ?? fallbackTransform(styleValue);
|
|
25
|
-
const value = transformedValue ?? styleValue;
|
|
26
|
-
if (value.type === "unit") {
|
|
27
|
-
return value.value + (value.unit === "number" ? "" : value.unit);
|
|
28
|
-
}
|
|
29
|
-
if (value.type === "fontFamily") {
|
|
30
|
-
return value.value.join(", ");
|
|
31
|
-
}
|
|
32
|
-
if (value.type === "var") {
|
|
33
|
-
const fallbacks = [];
|
|
34
|
-
for (const fallback of value.fallbacks) {
|
|
35
|
-
fallbacks.push(toValue(fallback, transformValue));
|
|
36
|
-
}
|
|
37
|
-
const fallbacksString = fallbacks.length > 0 ? `, ${fallbacks.join(", ")}` : "";
|
|
38
|
-
return `var(--${value.value}${fallbacksString})`;
|
|
39
|
-
}
|
|
40
|
-
if (value.type === "keyword") {
|
|
41
|
-
return value.value;
|
|
42
|
-
}
|
|
43
|
-
if (value.type === "invalid") {
|
|
44
|
-
return value.value;
|
|
45
|
-
}
|
|
46
|
-
if (value.type === "unset") {
|
|
47
|
-
return value.value;
|
|
48
|
-
}
|
|
49
|
-
if (value.type === "rgb") {
|
|
50
|
-
return `rgba(${value.r}, ${value.g}, ${value.b}, ${value.alpha})`;
|
|
51
|
-
}
|
|
52
|
-
if (value.type === "image") {
|
|
53
|
-
if (value.hidden || value.value.type !== "url") {
|
|
54
|
-
return "none";
|
|
55
|
-
}
|
|
56
|
-
return `url(${value.value.url})`;
|
|
57
|
-
}
|
|
58
|
-
if (value.type === "unparsed") {
|
|
59
|
-
if (value.hidden) {
|
|
60
|
-
return "none";
|
|
61
|
-
}
|
|
62
|
-
return value.value;
|
|
63
|
-
}
|
|
64
|
-
if (value.type === "layers") {
|
|
65
|
-
const valueString = value.value.filter(
|
|
66
|
-
(layer) => "hidden" in layer === false || "hidden" in layer && layer.hidden === false
|
|
67
|
-
).map((layer) => {
|
|
68
|
-
return toValue(layer, transformValue);
|
|
69
|
-
}).join(", ");
|
|
70
|
-
return valueString === "" ? "none" : valueString;
|
|
71
|
-
}
|
|
72
|
-
if (value.type === "tuple") {
|
|
73
|
-
return value.value.map((value2) => toValue(value2, transformValue)).join(" ");
|
|
74
|
-
}
|
|
75
|
-
return captureError(new Error("Unknown value type"), value);
|
|
76
|
-
};
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { describe, test, expect } from "@jest/globals";
|
|
3
|
-
import { toValue } from "./to-value";
|
|
4
|
-
describe("Convert WS CSS Values to native CSS strings", () => {
|
|
5
|
-
test("keyword", () => {
|
|
6
|
-
const value = toValue({ type: "keyword", value: "red" });
|
|
7
|
-
expect(value).toBe("red");
|
|
8
|
-
});
|
|
9
|
-
test("unit", () => {
|
|
10
|
-
const value = toValue({ type: "unit", value: 10, unit: "px" });
|
|
11
|
-
expect(value).toBe("10px");
|
|
12
|
-
});
|
|
13
|
-
test("invalid", () => {
|
|
14
|
-
const value = toValue({ type: "invalid", value: "bad" });
|
|
15
|
-
expect(value).toBe("bad");
|
|
16
|
-
});
|
|
17
|
-
test("unset", () => {
|
|
18
|
-
const value = toValue({ type: "unset", value: "" });
|
|
19
|
-
expect(value).toBe("");
|
|
20
|
-
});
|
|
21
|
-
test("var", () => {
|
|
22
|
-
const value = toValue({ type: "var", value: "namespace", fallbacks: [] });
|
|
23
|
-
expect(value).toBe("var(--namespace)");
|
|
24
|
-
});
|
|
25
|
-
test("var with fallbacks", () => {
|
|
26
|
-
const value = toValue({
|
|
27
|
-
type: "var",
|
|
28
|
-
value: "namespace",
|
|
29
|
-
fallbacks: [
|
|
30
|
-
{
|
|
31
|
-
type: "keyword",
|
|
32
|
-
value: "normal"
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
type: "unit",
|
|
36
|
-
value: 10,
|
|
37
|
-
unit: "px"
|
|
38
|
-
}
|
|
39
|
-
]
|
|
40
|
-
});
|
|
41
|
-
expect(value).toBe("var(--namespace, normal, 10px)");
|
|
42
|
-
});
|
|
43
|
-
test("fontFamily", () => {
|
|
44
|
-
const value = toValue({
|
|
45
|
-
type: "fontFamily",
|
|
46
|
-
value: ["Courier New"]
|
|
47
|
-
});
|
|
48
|
-
expect(value).toBe("Courier New, monospace");
|
|
49
|
-
});
|
|
50
|
-
test("Transform font family value to override default fallback", () => {
|
|
51
|
-
const value = toValue(
|
|
52
|
-
{
|
|
53
|
-
type: "fontFamily",
|
|
54
|
-
value: ["Courier New"]
|
|
55
|
-
},
|
|
56
|
-
(styleValue) => {
|
|
57
|
-
if (styleValue.type === "fontFamily") {
|
|
58
|
-
return {
|
|
59
|
-
type: "fontFamily",
|
|
60
|
-
value: [styleValue.value[0]]
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
);
|
|
65
|
-
expect(value).toBe("Courier New");
|
|
66
|
-
});
|
|
67
|
-
test("array", () => {
|
|
68
|
-
const assets = /* @__PURE__ */ new Map([
|
|
69
|
-
["1234567890", { path: "foo.png" }]
|
|
70
|
-
]);
|
|
71
|
-
const value = toValue(
|
|
72
|
-
{
|
|
73
|
-
type: "layers",
|
|
74
|
-
value: [
|
|
75
|
-
{
|
|
76
|
-
type: "keyword",
|
|
77
|
-
value: "auto"
|
|
78
|
-
},
|
|
79
|
-
{ type: "unit", value: 10, unit: "px" },
|
|
80
|
-
{ type: "unparsed", value: "calc(10px)" },
|
|
81
|
-
{
|
|
82
|
-
type: "image",
|
|
83
|
-
value: {
|
|
84
|
-
type: "asset",
|
|
85
|
-
value: "1234567890"
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
]
|
|
89
|
-
},
|
|
90
|
-
(styleValue) => {
|
|
91
|
-
if (styleValue.type === "image" && styleValue.value.type === "asset") {
|
|
92
|
-
const asset = assets.get(styleValue.value.value);
|
|
93
|
-
if (asset === void 0) {
|
|
94
|
-
return {
|
|
95
|
-
type: "keyword",
|
|
96
|
-
value: "none"
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
return {
|
|
100
|
-
type: "image",
|
|
101
|
-
value: {
|
|
102
|
-
type: "url",
|
|
103
|
-
url: asset.path
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
);
|
|
109
|
-
expect(value).toBe("auto, 10px, calc(10px), url(foo.png)");
|
|
110
|
-
});
|
|
111
|
-
test("tuple", () => {
|
|
112
|
-
const value = toValue({
|
|
113
|
-
type: "tuple",
|
|
114
|
-
value: [
|
|
115
|
-
{ type: "unit", value: 10, unit: "px" },
|
|
116
|
-
{ type: "unit", value: 20, unit: "px" },
|
|
117
|
-
{ type: "unit", value: 30, unit: "px" },
|
|
118
|
-
{ type: "unit", value: 40, unit: "px" }
|
|
119
|
-
]
|
|
120
|
-
});
|
|
121
|
-
expect(value).toBe("10px 20px 30px 40px");
|
|
122
|
-
});
|
|
123
|
-
});
|
package/lib/schema.js
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
const Unit = z.string();
|
|
4
|
-
export const UnitValue = z.object({
|
|
5
|
-
type: z.literal("unit"),
|
|
6
|
-
unit: Unit,
|
|
7
|
-
value: z.number()
|
|
8
|
-
});
|
|
9
|
-
export const KeywordValue = z.object({
|
|
10
|
-
type: z.literal("keyword"),
|
|
11
|
-
// @todo use exact type
|
|
12
|
-
value: z.string()
|
|
13
|
-
});
|
|
14
|
-
export const UnparsedValue = z.object({
|
|
15
|
-
type: z.literal("unparsed"),
|
|
16
|
-
value: z.string(),
|
|
17
|
-
// For the builder we want to be able to hide background-image
|
|
18
|
-
hidden: z.boolean().optional()
|
|
19
|
-
});
|
|
20
|
-
const FontFamilyValue = z.object({
|
|
21
|
-
type: z.literal("fontFamily"),
|
|
22
|
-
value: z.array(z.string())
|
|
23
|
-
});
|
|
24
|
-
const RgbValue = z.object({
|
|
25
|
-
type: z.literal("rgb"),
|
|
26
|
-
r: z.number(),
|
|
27
|
-
g: z.number(),
|
|
28
|
-
b: z.number(),
|
|
29
|
-
alpha: z.number()
|
|
30
|
-
});
|
|
31
|
-
export const ImageValue = z.object({
|
|
32
|
-
type: z.literal("image"),
|
|
33
|
-
value: z.union([
|
|
34
|
-
z.object({ type: z.literal("asset"), value: z.string() }),
|
|
35
|
-
// url is not stored in db and only used by css-engine transformValue
|
|
36
|
-
// to prepare image value for rendering
|
|
37
|
-
z.object({ type: z.literal("url"), url: z.string() })
|
|
38
|
-
]),
|
|
39
|
-
// For the builder we want to be able to hide images
|
|
40
|
-
hidden: z.boolean().optional()
|
|
41
|
-
});
|
|
42
|
-
export const InvalidValue = z.object({
|
|
43
|
-
type: z.literal("invalid"),
|
|
44
|
-
value: z.string()
|
|
45
|
-
});
|
|
46
|
-
const UnsetValue = z.object({
|
|
47
|
-
type: z.literal("unset"),
|
|
48
|
-
value: z.literal("")
|
|
49
|
-
});
|
|
50
|
-
export const TupleValueItem = z.union([
|
|
51
|
-
UnitValue,
|
|
52
|
-
KeywordValue,
|
|
53
|
-
UnparsedValue,
|
|
54
|
-
RgbValue
|
|
55
|
-
]);
|
|
56
|
-
export const TupleValue = z.object({
|
|
57
|
-
type: z.literal("tuple"),
|
|
58
|
-
value: z.array(TupleValueItem),
|
|
59
|
-
hidden: z.boolean().optional()
|
|
60
|
-
});
|
|
61
|
-
const LayerValueItem = z.union([
|
|
62
|
-
UnitValue,
|
|
63
|
-
KeywordValue,
|
|
64
|
-
UnparsedValue,
|
|
65
|
-
ImageValue,
|
|
66
|
-
TupleValue,
|
|
67
|
-
InvalidValue
|
|
68
|
-
]);
|
|
69
|
-
export const LayersValue = z.object({
|
|
70
|
-
type: z.literal("layers"),
|
|
71
|
-
value: z.array(LayerValueItem)
|
|
72
|
-
});
|
|
73
|
-
const ValidStaticStyleValue = z.union([
|
|
74
|
-
ImageValue,
|
|
75
|
-
LayersValue,
|
|
76
|
-
UnitValue,
|
|
77
|
-
KeywordValue,
|
|
78
|
-
FontFamilyValue,
|
|
79
|
-
RgbValue,
|
|
80
|
-
UnparsedValue,
|
|
81
|
-
TupleValue
|
|
82
|
-
]);
|
|
83
|
-
export const isValidStaticStyleValue = (styleValue) => {
|
|
84
|
-
const staticStyleValue = styleValue;
|
|
85
|
-
return staticStyleValue.type === "image" || staticStyleValue.type === "layers" || staticStyleValue.type === "unit" || staticStyleValue.type === "keyword" || staticStyleValue.type === "fontFamily" || staticStyleValue.type === "rgb" || staticStyleValue.type === "unparsed" || staticStyleValue.type === "tuple";
|
|
86
|
-
};
|
|
87
|
-
const VarValue = z.object({
|
|
88
|
-
type: z.literal("var"),
|
|
89
|
-
value: z.string(),
|
|
90
|
-
fallbacks: z.array(ValidStaticStyleValue)
|
|
91
|
-
});
|
|
92
|
-
export const StyleValue = z.union([
|
|
93
|
-
ValidStaticStyleValue,
|
|
94
|
-
InvalidValue,
|
|
95
|
-
UnsetValue,
|
|
96
|
-
VarValue
|
|
97
|
-
]);
|
|
98
|
-
const Style = z.record(z.string(), StyleValue);
|