@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.
@@ -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
+ };
@@ -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 = `max-width: ${maxWidth}px`;
146
+ conditionText += ` and (max-width: ${maxWidth}px)`;
146
147
  }
147
- if (conditionText) {
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
@@ -1,6 +1,7 @@
1
1
  import { CssEngine } from "./css-engine";
2
2
  export * from "./create-css-engine";
3
3
  export * from "./to-value";
4
+ export * from "./match-media";
4
5
  export {
5
6
  CssEngine
6
7
  };
@@ -0,0 +1,8 @@
1
+ const matchMedia = (options, width) => {
2
+ const minWidth = options.minWidth ?? Number.MIN_SAFE_INTEGER;
3
+ const maxWidth = options.maxWidth ?? Number.MAX_SAFE_INTEGER;
4
+ return width >= minWidth && width <= maxWidth;
5
+ };
6
+ export {
7
+ matchMedia
8
+ };
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 = `max-width: ${maxWidth}px`;
120
+ conditionText += ` and (max-width: ${maxWidth}px)`;
120
121
  }
121
- if (conditionText) {
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.50.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.50.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.50.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
@@ -8,3 +8,4 @@ export type {
8
8
  } from "./rules";
9
9
  export * from "./create-css-engine";
10
10
  export * from "./to-value";
11
+ export * from "./match-media";
@@ -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 = `max-width: ${maxWidth}px`;
113
+ conditionText += ` and (max-width: ${maxWidth}px)`;
113
114
  }
114
- if (conditionText) {
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
  }