@webstudio-is/css-engine 0.49.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
+ };
@@ -116,6 +116,10 @@ class MediaRule {
116
116
  this.options = options;
117
117
  __privateSet(this, _mediaType, options.mediaType ?? "all");
118
118
  }
119
+ // Sort media rules by minWidth.
120
+ // Needed to ensure that more specific media rules are inserted after less specific ones.
121
+ // So that they get a higher specificity.
122
+ // @todo remove this once we have ability to control order from the UI
119
123
  static sort(mediaRules) {
120
124
  return Array.from(mediaRules).sort((ruleA, ruleB) => {
121
125
  return (ruleA.options.minWidth ?? -Number.MAX_SAFE_INTEGER) - (ruleB.options.minWidth ?? -Number.MAX_SAFE_INTEGER);
@@ -136,15 +140,12 @@ class MediaRule {
136
140
  let conditionText = "";
137
141
  const { minWidth, maxWidth } = this.options;
138
142
  if (minWidth !== void 0) {
139
- conditionText = `min-width: ${minWidth}px`;
143
+ conditionText = ` and (min-width: ${minWidth}px)`;
140
144
  }
141
145
  if (maxWidth !== void 0) {
142
- conditionText = `max-width: ${maxWidth}px`;
146
+ conditionText += ` and (max-width: ${maxWidth}px)`;
143
147
  }
144
- if (conditionText) {
145
- conditionText = `and (${conditionText}) `;
146
- }
147
- return `@media ${__privateGet(this, _mediaType)} ${conditionText}{
148
+ return `@media ${__privateGet(this, _mediaType)}${conditionText} {
148
149
  ${rules.join(
149
150
  "\n"
150
151
  )}
@@ -18,6 +18,10 @@ var __copyProps = (to, from, except, desc) => {
18
18
  return to;
19
19
  };
20
20
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
25
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
26
  mod
23
27
  ));
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
@@ -90,6 +90,10 @@ class MediaRule {
90
90
  this.options = options;
91
91
  __privateSet(this, _mediaType, options.mediaType ?? "all");
92
92
  }
93
+ // Sort media rules by minWidth.
94
+ // Needed to ensure that more specific media rules are inserted after less specific ones.
95
+ // So that they get a higher specificity.
96
+ // @todo remove this once we have ability to control order from the UI
93
97
  static sort(mediaRules) {
94
98
  return Array.from(mediaRules).sort((ruleA, ruleB) => {
95
99
  return (ruleA.options.minWidth ?? -Number.MAX_SAFE_INTEGER) - (ruleB.options.minWidth ?? -Number.MAX_SAFE_INTEGER);
@@ -110,15 +114,12 @@ class MediaRule {
110
114
  let conditionText = "";
111
115
  const { minWidth, maxWidth } = this.options;
112
116
  if (minWidth !== void 0) {
113
- conditionText = `min-width: ${minWidth}px`;
117
+ conditionText = ` and (min-width: ${minWidth}px)`;
114
118
  }
115
119
  if (maxWidth !== void 0) {
116
- conditionText = `max-width: ${maxWidth}px`;
120
+ conditionText += ` and (max-width: ${maxWidth}px)`;
117
121
  }
118
- if (conditionText) {
119
- conditionText = `and (${conditionText}) `;
120
- }
121
- return `@media ${__privateGet(this, _mediaType)} ${conditionText}{
122
+ return `@media ${__privateGet(this, _mediaType)}${conditionText} {
122
123
  ${rules.join(
123
124
  "\n"
124
125
  )}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webstudio-is/css-engine",
3
- "version": "0.49.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.49.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.49.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
  }