@webstudio-is/css-engine 0.50.0 → 0.51.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/cjs/core/index.cjs +1 -0
- package/lib/cjs/core/match-media.cjs +28 -0
- package/lib/cjs/core/rules.cjs +4 -6
- package/lib/core/index.js +1 -0
- package/lib/core/match-media.js +8 -0
- package/lib/core/rules.js +4 -6
- package/package.json +3 -3
- package/src/core/css-engine.test.ts +39 -0
- package/src/core/index.ts +1 -0
- package/src/core/match-media.test.ts +24 -0
- package/src/core/match-media.ts +7 -0
- package/src/core/rules.ts +4 -6
package/lib/cjs/core/index.cjs
CHANGED
|
@@ -25,3 +25,4 @@ module.exports = __toCommonJS(core_exports);
|
|
|
25
25
|
var import_css_engine = require("./css-engine");
|
|
26
26
|
__reExport(core_exports, require("./create-css-engine"), module.exports);
|
|
27
27
|
__reExport(core_exports, require("./to-value"), module.exports);
|
|
28
|
+
__reExport(core_exports, require("./match-media"), module.exports);
|
|
@@ -0,0 +1,28 @@
|
|
|
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 match_media_exports = {};
|
|
20
|
+
__export(match_media_exports, {
|
|
21
|
+
matchMedia: () => matchMedia
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(match_media_exports);
|
|
24
|
+
const matchMedia = (options, width) => {
|
|
25
|
+
const minWidth = options.minWidth ?? Number.MIN_SAFE_INTEGER;
|
|
26
|
+
const maxWidth = options.maxWidth ?? Number.MAX_SAFE_INTEGER;
|
|
27
|
+
return width >= minWidth && width <= maxWidth;
|
|
28
|
+
};
|
package/lib/cjs/core/rules.cjs
CHANGED
|
@@ -119,6 +119,7 @@ class MediaRule {
|
|
|
119
119
|
// Sort media rules by minWidth.
|
|
120
120
|
// Needed to ensure that more specific media rules are inserted after less specific ones.
|
|
121
121
|
// So that they get a higher specificity.
|
|
122
|
+
// @todo remove this once we have ability to control order from the UI
|
|
122
123
|
static sort(mediaRules) {
|
|
123
124
|
return Array.from(mediaRules).sort((ruleA, ruleB) => {
|
|
124
125
|
return (ruleA.options.minWidth ?? -Number.MAX_SAFE_INTEGER) - (ruleB.options.minWidth ?? -Number.MAX_SAFE_INTEGER);
|
|
@@ -139,15 +140,12 @@ class MediaRule {
|
|
|
139
140
|
let conditionText = "";
|
|
140
141
|
const { minWidth, maxWidth } = this.options;
|
|
141
142
|
if (minWidth !== void 0) {
|
|
142
|
-
conditionText = `min-width: ${minWidth}px`;
|
|
143
|
+
conditionText = ` and (min-width: ${minWidth}px)`;
|
|
143
144
|
}
|
|
144
145
|
if (maxWidth !== void 0) {
|
|
145
|
-
conditionText
|
|
146
|
+
conditionText += ` and (max-width: ${maxWidth}px)`;
|
|
146
147
|
}
|
|
147
|
-
|
|
148
|
-
conditionText = `and (${conditionText}) `;
|
|
149
|
-
}
|
|
150
|
-
return `@media ${__privateGet(this, _mediaType)} ${conditionText}{
|
|
148
|
+
return `@media ${__privateGet(this, _mediaType)}${conditionText} {
|
|
151
149
|
${rules.join(
|
|
152
150
|
"\n"
|
|
153
151
|
)}
|
package/lib/core/index.js
CHANGED
package/lib/core/rules.js
CHANGED
|
@@ -93,6 +93,7 @@ class MediaRule {
|
|
|
93
93
|
// Sort media rules by minWidth.
|
|
94
94
|
// Needed to ensure that more specific media rules are inserted after less specific ones.
|
|
95
95
|
// So that they get a higher specificity.
|
|
96
|
+
// @todo remove this once we have ability to control order from the UI
|
|
96
97
|
static sort(mediaRules) {
|
|
97
98
|
return Array.from(mediaRules).sort((ruleA, ruleB) => {
|
|
98
99
|
return (ruleA.options.minWidth ?? -Number.MAX_SAFE_INTEGER) - (ruleB.options.minWidth ?? -Number.MAX_SAFE_INTEGER);
|
|
@@ -113,15 +114,12 @@ class MediaRule {
|
|
|
113
114
|
let conditionText = "";
|
|
114
115
|
const { minWidth, maxWidth } = this.options;
|
|
115
116
|
if (minWidth !== void 0) {
|
|
116
|
-
conditionText = `min-width: ${minWidth}px`;
|
|
117
|
+
conditionText = ` and (min-width: ${minWidth}px)`;
|
|
117
118
|
}
|
|
118
119
|
if (maxWidth !== void 0) {
|
|
119
|
-
conditionText
|
|
120
|
+
conditionText += ` and (max-width: ${maxWidth}px)`;
|
|
120
121
|
}
|
|
121
|
-
|
|
122
|
-
conditionText = `and (${conditionText}) `;
|
|
123
|
-
}
|
|
124
|
-
return `@media ${__privateGet(this, _mediaType)} ${conditionText}{
|
|
122
|
+
return `@media ${__privateGet(this, _mediaType)}${conditionText} {
|
|
125
123
|
${rules.join(
|
|
126
124
|
"\n"
|
|
127
125
|
)}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webstudio-is/css-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.51.0",
|
|
4
4
|
"description": "CSS Renderer for Webstudio",
|
|
5
5
|
"author": "Webstudio <github@webstudio.is>",
|
|
6
6
|
"homepage": "https://webstudio.is",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"hyphenate-style-name": "^1.0.4",
|
|
10
10
|
"react": "^17.0.2",
|
|
11
11
|
"react-dom": "^17.0.2",
|
|
12
|
-
"@webstudio-is/fonts": "^0.
|
|
12
|
+
"@webstudio-is/fonts": "^0.51.0"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
15
|
"@jest/globals": "^29.3.1",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"@types/react-dom": "^17.0.9",
|
|
20
20
|
"jest": "^29.3.1",
|
|
21
21
|
"typescript": "4.9.5",
|
|
22
|
-
"@webstudio-is/css-data": "^0.
|
|
22
|
+
"@webstudio-is/css-data": "^0.51.0",
|
|
23
23
|
"@webstudio-is/jest-config": "^1.0.2",
|
|
24
24
|
"@webstudio-is/scripts": "^0.0.0",
|
|
25
25
|
"@webstudio-is/storybook-config": "^0.0.0",
|
|
@@ -29,6 +29,45 @@ describe("CssEngine", () => {
|
|
|
29
29
|
|
|
30
30
|
beforeEach(reset);
|
|
31
31
|
|
|
32
|
+
test("minWidth media rule", () => {
|
|
33
|
+
engine.addMediaRule("0", { minWidth: 0 });
|
|
34
|
+
engine.addStyleRule(".c1", {
|
|
35
|
+
style: { color: { type: "keyword", value: "red" } },
|
|
36
|
+
breakpoint: "0",
|
|
37
|
+
});
|
|
38
|
+
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
39
|
+
"@media all and (min-width: 0px) {
|
|
40
|
+
.c1 { color: red }
|
|
41
|
+
}"
|
|
42
|
+
`);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test("maxWidth media rule", () => {
|
|
46
|
+
engine.addMediaRule("0", { maxWidth: 1000 });
|
|
47
|
+
engine.addStyleRule(".c1", {
|
|
48
|
+
style: { color: { type: "keyword", value: "red" } },
|
|
49
|
+
breakpoint: "0",
|
|
50
|
+
});
|
|
51
|
+
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
52
|
+
"@media all and (max-width: 1000px) {
|
|
53
|
+
.c1 { color: red }
|
|
54
|
+
}"
|
|
55
|
+
`);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("maxWidth and maxWith media rule", () => {
|
|
59
|
+
engine.addMediaRule("0", { maxWidth: 1000, minWidth: 360 });
|
|
60
|
+
engine.addStyleRule(".c1", {
|
|
61
|
+
style: { color: { type: "keyword", value: "red" } },
|
|
62
|
+
breakpoint: "0",
|
|
63
|
+
});
|
|
64
|
+
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
65
|
+
"@media all and (min-width: 360px) and (max-width: 1000px) {
|
|
66
|
+
.c1 { color: red }
|
|
67
|
+
}"
|
|
68
|
+
`);
|
|
69
|
+
});
|
|
70
|
+
|
|
32
71
|
test("use default media rule when there is no matching one registered", () => {
|
|
33
72
|
engine.addStyleRule(".c", {
|
|
34
73
|
style: style0,
|
package/src/core/index.ts
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { describe, expect, test } from "@jest/globals";
|
|
2
|
+
import { matchMedia } from "./match-media";
|
|
3
|
+
|
|
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
|
+
|
|
11
|
+
test("maxWidth", () => {
|
|
12
|
+
expect(matchMedia({ maxWidth: 100 }, 101)).toBe(false);
|
|
13
|
+
expect(matchMedia({ maxWidth: 100 }, 100)).toBe(true);
|
|
14
|
+
expect(matchMedia({ maxWidth: 100 }, 10)).toBe(true);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test("minWidth and maxWidth", () => {
|
|
18
|
+
expect(matchMedia({ maxWidth: 100, minWidth: 10 }, 9)).toBe(false);
|
|
19
|
+
expect(matchMedia({ maxWidth: 100, minWidth: 10 }, 101)).toBe(false);
|
|
20
|
+
expect(matchMedia({ maxWidth: 100, minWidth: 10 }, 100)).toBe(true);
|
|
21
|
+
expect(matchMedia({ maxWidth: 100, minWidth: 10 }, 10)).toBe(true);
|
|
22
|
+
expect(matchMedia({ maxWidth: 100, minWidth: 10 }, 11)).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { MediaRuleOptions } from "./rules";
|
|
2
|
+
|
|
3
|
+
export const matchMedia = (options: MediaRuleOptions, width: number) => {
|
|
4
|
+
const minWidth = options.minWidth ?? Number.MIN_SAFE_INTEGER;
|
|
5
|
+
const maxWidth = options.maxWidth ?? Number.MAX_SAFE_INTEGER;
|
|
6
|
+
return width >= minWidth && width <= maxWidth;
|
|
7
|
+
};
|
package/src/core/rules.ts
CHANGED
|
@@ -76,6 +76,7 @@ export class MediaRule {
|
|
|
76
76
|
// Sort media rules by minWidth.
|
|
77
77
|
// Needed to ensure that more specific media rules are inserted after less specific ones.
|
|
78
78
|
// So that they get a higher specificity.
|
|
79
|
+
// @todo remove this once we have ability to control order from the UI
|
|
79
80
|
static sort(mediaRules: Iterable<MediaRule>) {
|
|
80
81
|
return Array.from(mediaRules).sort((ruleA, ruleB) => {
|
|
81
82
|
return (
|
|
@@ -106,15 +107,12 @@ export class MediaRule {
|
|
|
106
107
|
let conditionText = "";
|
|
107
108
|
const { minWidth, maxWidth } = this.options;
|
|
108
109
|
if (minWidth !== undefined) {
|
|
109
|
-
conditionText = `min-width: ${minWidth}px`;
|
|
110
|
+
conditionText = ` and (min-width: ${minWidth}px)`;
|
|
110
111
|
}
|
|
111
112
|
if (maxWidth !== undefined) {
|
|
112
|
-
conditionText
|
|
113
|
+
conditionText += ` and (max-width: ${maxWidth}px)`;
|
|
113
114
|
}
|
|
114
|
-
|
|
115
|
-
conditionText = `and (${conditionText}) `;
|
|
116
|
-
}
|
|
117
|
-
return `@media ${this.#mediaType} ${conditionText}{\n${rules.join(
|
|
115
|
+
return `@media ${this.#mediaType}${conditionText} {\n${rules.join(
|
|
118
116
|
"\n"
|
|
119
117
|
)}\n}`;
|
|
120
118
|
}
|