@nordcraft/runtime 1.0.33 → 1.0.34

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.
Files changed (33) hide show
  1. package/dist/components/createComponent.js +4 -0
  2. package/dist/components/createComponent.js.map +1 -1
  3. package/dist/components/createElement.js +9 -1
  4. package/dist/components/createElement.js.map +1 -1
  5. package/dist/custom-element.main.esm.js +17 -17
  6. package/dist/custom-element.main.esm.js.map +4 -4
  7. package/dist/debug/panicScreen.d.ts +6 -0
  8. package/dist/debug/panicScreen.js +25 -0
  9. package/dist/debug/panicScreen.js.map +1 -0
  10. package/dist/debug/sendEditorToast.d.ts +3 -0
  11. package/dist/debug/sendEditorToast.js +9 -0
  12. package/dist/debug/sendEditorToast.js.map +1 -0
  13. package/dist/editor-preview.main.js +65 -29
  14. package/dist/editor-preview.main.js.map +1 -1
  15. package/dist/page.main.esm.js +3 -3
  16. package/dist/page.main.esm.js.map +4 -4
  17. package/dist/styles/CustomPropertyStyleSheet.d.ts +2 -1
  18. package/dist/styles/CustomPropertyStyleSheet.js +14 -5
  19. package/dist/styles/CustomPropertyStyleSheet.js.map +1 -1
  20. package/dist/styles/CustomPropertyStyleSheet.test.js +7 -7
  21. package/dist/styles/CustomPropertyStyleSheet.test.js.map +1 -1
  22. package/dist/utils/subscribeCustomProperty.d.ts +4 -1
  23. package/dist/utils/subscribeCustomProperty.js +11 -4
  24. package/dist/utils/subscribeCustomProperty.js.map +1 -1
  25. package/package.json +3 -3
  26. package/src/components/createComponent.ts +4 -0
  27. package/src/components/createElement.ts +10 -1
  28. package/src/debug/panicScreen.ts +37 -0
  29. package/src/debug/sendEditorToast.ts +19 -0
  30. package/src/editor-preview.main.ts +81 -40
  31. package/src/styles/CustomPropertyStyleSheet.test.ts +7 -7
  32. package/src/styles/CustomPropertyStyleSheet.ts +22 -5
  33. package/src/utils/subscribeCustomProperty.ts +25 -12
@@ -11,7 +11,7 @@ import type { MediaQuery } from '@nordcraft/core/dist/component/component.types'
11
11
  export declare class CustomPropertyStyleSheet {
12
12
  private styleSheet;
13
13
  private ruleMap;
14
- constructor(styleSheet?: CSSStyleSheet | null);
14
+ constructor(root: Document | ShadowRoot, styleSheet?: CSSStyleSheet | null);
15
15
  /**
16
16
  * @returns A function to update the property value efficiently.
17
17
  */
@@ -22,6 +22,7 @@ export declare class CustomPropertyStyleSheet {
22
22
  unregisterProperty(selector: string, name: string, options?: {
23
23
  mediaQuery?: MediaQuery;
24
24
  startingStyle?: boolean;
25
+ deepClean?: boolean;
25
26
  }): void;
26
27
  getStyleSheet(): CSSStyleSheet;
27
28
  /**
@@ -11,13 +11,13 @@ export class CustomPropertyStyleSheet {
11
11
  styleSheet;
12
12
  // Selector to rule index mapping
13
13
  ruleMap;
14
- constructor(styleSheet) {
14
+ constructor(root, styleSheet) {
15
15
  if (styleSheet) {
16
16
  this.styleSheet = styleSheet;
17
17
  }
18
18
  else {
19
19
  this.styleSheet = new CSSStyleSheet();
20
- document.adoptedStyleSheets.push(this.getStyleSheet());
20
+ root.adoptedStyleSheets.push(this.getStyleSheet());
21
21
  }
22
22
  }
23
23
  /**
@@ -29,7 +29,7 @@ export class CustomPropertyStyleSheet {
29
29
  // Check if the selector already exists
30
30
  let rule = this.ruleMap.get(fullSelector);
31
31
  if (!rule) {
32
- const ruleIndex = this.styleSheet.insertRule(fullSelector);
32
+ const ruleIndex = this.styleSheet.insertRule(fullSelector, this.styleSheet.cssRules.length);
33
33
  let newRule = this.styleSheet.cssRules[ruleIndex];
34
34
  // We are only interested in the dynamic style, so get the actual style rule, not media or other nested rules. Loop until we are at the bottom most rule.
35
35
  while (newRule.cssRules &&
@@ -48,8 +48,17 @@ export class CustomPropertyStyleSheet {
48
48
  return;
49
49
  }
50
50
  const fullSelector = CustomPropertyStyleSheet.getFullSelector(selector, options);
51
- // We only clean up the property, as we assume that the rule will be reused.
52
- this.ruleMap.get(fullSelector)?.style.removeProperty(name);
51
+ const rule = this.ruleMap.get(fullSelector);
52
+ if (!rule) {
53
+ return;
54
+ }
55
+ rule.style.removeProperty(name);
56
+ // Cleaning up empty selectors is probably not necessary in production and may have performance implications.
57
+ // However, it is required for the editor-preview as it is a dynamic environment and things may get reordered and canvas reused.
58
+ if (options?.deepClean && rule.style.length === 0) {
59
+ this.styleSheet.deleteRule(Array.from(this.ruleMap.keys()).indexOf(fullSelector));
60
+ this.ruleMap.delete(fullSelector);
61
+ }
53
62
  }
54
63
  getStyleSheet() {
55
64
  return this.styleSheet;
@@ -1 +1 @@
1
- {"version":3,"file":"CustomPropertyStyleSheet.js","sourceRoot":"","sources":["../../src/styles/CustomPropertyStyleSheet.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,OAAO,wBAAwB;IAC3B,UAAU,CAAe;IAEjC,iCAAiC;IACzB,OAAO,CAA+D;IAE9E,YAAY,UAAiC;QAC3C,IAAI,UAAU,EAAE,CAAC;YACf,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;QAC9B,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,UAAU,GAAG,IAAI,aAAa,EAAE,CAAA;YACrC,QAAQ,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAA;QACxD,CAAC;IACH,CAAC;IAED;;OAEG;IACI,gBAAgB,CACrB,QAAgB,EAChB,IAAY,EACZ,OAGC;QAED,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,eAAe,EAAE,CAAA;QACvC,MAAM,YAAY,GAAG,wBAAwB,CAAC,eAAe,CAC3D,QAAQ,EACR,OAAO,CACR,CAAA;QAED,uCAAuC;QACvC,IAAI,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;QACzC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,YAAY,CAAC,CAAA;YAC1D,IAAI,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;YAEjD,yJAAyJ;YACzJ,OACG,OAAe,CAAC,QAAQ;gBACxB,OAA2B,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAChD,CAAC;gBACD,OAAO,GAAI,OAA2B,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;YACpD,CAAC;YACD,IAAI,GAAG,OAA+C,CAAA;YACtD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,CAAA;QACtC,CAAC;QAED,OAAO,CAAC,KAAa,EAAE,EAAE;YACvB,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QACrC,CAAC,CAAA;IACH,CAAC;IAEM,kBAAkB,CACvB,QAAgB,EAChB,IAAY,EACZ,OAGC;QAED,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,OAAM;QACR,CAAC;QAED,MAAM,YAAY,GAAG,wBAAwB,CAAC,eAAe,CAC3D,QAAQ,EACR,OAAO,CACR,CAAA;QAED,4EAA4E;QAC5E,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,CAAA;IAC5D,CAAC;IAEM,aAAa;QAClB,OAAO,IAAI,CAAC,UAAU,CAAA;IACxB,CAAC;IAED;;;OAGG;IACK,eAAe;QACrB,MAAM,SAAS,GAA8B,IAAI,GAAG,EAAE,CAAA;QACtD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACzD,IAAI,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;YACtC,MAAM,QAAQ,GAAG,wBAAwB,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAA;YACnE,mFAAmF;YACnF,OACG,IAAwB,CAAC,QAAQ;gBACjC,IAAwB,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAC7C,CAAC;gBACD,IAAI,GAAI,IAAwB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;YAC9C,CAAC;YAED,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAoB,CAAC,CAAA;QAC/C,CAAC;QACD,OAAO,SAAS,CAAA;IAClB,CAAC;IAEO,MAAM,CAAC,mBAAmB,CAAC,IAAa;QAC9C,QAAQ,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;YAC9B,KAAK,cAAc;gBACjB,oFAAoF;gBACpF,OAAO,GAAI,IAAqB,CAAC,YAAY,MAAM,KAAK,CAAC,IAAI,CAC1D,IAAqB,CAAC,QAAQ,CAChC;qBACE,GAAG,CAAC,wBAAwB,CAAC,mBAAmB,CAAC;qBACjD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAA;YAClB,KAAK,sBAAsB;gBACzB,OAAO,qBAAqB,KAAK,CAAC,IAAI,CACnC,IAA6B,CAAC,QAAQ,CACxC;qBACE,GAAG,CAAC,wBAAwB,CAAC,mBAAmB,CAAC;qBACjD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAA;YAClB,KAAK,cAAc;gBACjB,OAAO,UAAW,IAAqB,CAAC,KAAK,CAAC,SAAS,MAAM,KAAK,CAAC,IAAI,CACpE,IAAqB,CAAC,QAAQ,CAChC;qBACE,GAAG,CAAC,wBAAwB,CAAC,mBAAmB,CAAC;qBACjD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAA;YAClB,KAAK,uBAAuB;gBAC1B,OAAO,EAAE,CAAA;YACX;gBACE,sCAAsC;gBACtC,OAAO,CAAC,IAAI,CACV,8BAA8B,IAAI,CAAC,WAAW,CAAC,IAAI,6BAA6B,CACjF,CAAA;gBACD,OAAO,EAAE,CAAA;QACb,CAAC;IACH,CAAC;IAEO,MAAM,CAAC,eAAe,CAC5B,QAAgB,EAChB,OAGC;QAED,IAAI,MAAM,GACR,QAAQ,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;QAC1E,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC;YACxB,MAAM,GAAG,WAAW,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC;iBACnD,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,KAAK,EAAE,CAAC;iBACzC,MAAM,CAAC,OAAO,CAAC;iBACf,IAAI,CAAC,SAAS,CAAC,OAAO,MAAM,GAAG,CAAA;QACpC,CAAC;QAED,OAAO,MAAM,CAAA;IACf,CAAC;CACF"}
1
+ {"version":3,"file":"CustomPropertyStyleSheet.js","sourceRoot":"","sources":["../../src/styles/CustomPropertyStyleSheet.ts"],"names":[],"mappings":"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"}
@@ -2,18 +2,18 @@ import { describe, expect, test } from 'bun:test';
2
2
  import { CustomPropertyStyleSheet } from './CustomPropertyStyleSheet';
3
3
  describe('CustomPropertyStyleSheet', () => {
4
4
  test('it creates a new stylesheet', () => {
5
- const instance = new CustomPropertyStyleSheet();
5
+ const instance = new CustomPropertyStyleSheet(document);
6
6
  expect(instance).toBeInstanceOf(CustomPropertyStyleSheet);
7
7
  expect(instance.getStyleSheet().cssRules).toHaveLength(0);
8
8
  });
9
9
  test('it adds a property definition', () => {
10
- const instance = new CustomPropertyStyleSheet();
10
+ const instance = new CustomPropertyStyleSheet(document);
11
11
  instance.registerProperty('.my-class', '--my-property');
12
12
  expect(instance.getStyleSheet().cssRules.length).toBe(1);
13
13
  expect(instance.getStyleSheet().cssRules[0].cssText).toBe('.my-class { }');
14
14
  });
15
15
  test('it puts different selectors in different rules', () => {
16
- const instance = new CustomPropertyStyleSheet();
16
+ const instance = new CustomPropertyStyleSheet(document);
17
17
  instance.registerProperty('.my-class', '--my-property')('256px');
18
18
  instance.registerProperty('.my-other-class', '--my-property')('256px');
19
19
  expect(instance.getStyleSheet().cssRules.length).toBe(2);
@@ -21,7 +21,7 @@ describe('CustomPropertyStyleSheet', () => {
21
21
  expect(instance.getStyleSheet().cssRules[1].cssText).toBe('.my-other-class { --my-property: 256px; }');
22
22
  });
23
23
  test('it can update properties', () => {
24
- const instance = new CustomPropertyStyleSheet();
24
+ const instance = new CustomPropertyStyleSheet(document);
25
25
  const setter = instance.registerProperty('.my-class', '--my-property');
26
26
  setter('256px');
27
27
  expect(instance.getStyleSheet().cssRules.length).toBe(1);
@@ -30,7 +30,7 @@ describe('CustomPropertyStyleSheet', () => {
30
30
  expect(instance.getStyleSheet().cssRules[0].cssText).toBe('.my-class { --my-property: inherit; }');
31
31
  });
32
32
  test('it works with media queries', () => {
33
- const instance = new CustomPropertyStyleSheet();
33
+ const instance = new CustomPropertyStyleSheet(document);
34
34
  instance.registerProperty('.my-class', '--my-property', {
35
35
  mediaQuery: { 'max-width': '600px' },
36
36
  })('256px');
@@ -38,7 +38,7 @@ describe('CustomPropertyStyleSheet', () => {
38
38
  expect(instance.getStyleSheet().cssRules[0].cssText).toBe('@media (max-width: 600px) { .my-class { --my-property: 256px; } }');
39
39
  });
40
40
  test('it unregisters a property', () => {
41
- const instance = new CustomPropertyStyleSheet();
41
+ const instance = new CustomPropertyStyleSheet(document);
42
42
  const setter = instance.registerProperty('.my-class', '--my-property');
43
43
  setter('256px');
44
44
  const setter2 = instance.registerProperty('.my-class', '--my-other-property');
@@ -50,7 +50,7 @@ describe('CustomPropertyStyleSheet', () => {
50
50
  expect(instance.getStyleSheet().cssRules[0].cssText).toBe('.my-class { }');
51
51
  });
52
52
  test('it unregisters a property with media queries', () => {
53
- const instance = new CustomPropertyStyleSheet();
53
+ const instance = new CustomPropertyStyleSheet(document);
54
54
  const setter = instance.registerProperty('.my-class-with-media', '--my-property-with-media', {
55
55
  mediaQuery: { 'max-width': '600px' },
56
56
  });
@@ -1 +1 @@
1
- {"version":3,"file":"CustomPropertyStyleSheet.test.js","sourceRoot":"","sources":["../../src/styles/CustomPropertyStyleSheet.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CustomPropertyStyleSheet.test.js","sourceRoot":"","sources":["../../src/styles/CustomPropertyStyleSheet.test.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,11 @@
1
1
  import type { StyleVariant } from '@nordcraft/core/dist/component/component.types';
2
2
  import type { Signal } from '../signal/signal';
3
- export declare function subscribeCustomProperty({ selector, customPropertyName, signal, variant, }: {
3
+ import type { Runtime } from '@nordcraft/core/dist/types';
4
+ export declare function subscribeCustomProperty({ selector, customPropertyName, signal, variant, root, runtime, }: {
4
5
  selector: string;
5
6
  customPropertyName: string;
6
7
  signal: Signal<string>;
7
8
  variant?: StyleVariant;
9
+ root: Document | ShadowRoot;
10
+ runtime: Runtime;
8
11
  }): void;
@@ -1,9 +1,16 @@
1
1
  import { CUSTOM_PROPERTIES_STYLESHEET_ID } from '@nordcraft/core/dist/styling/theme.const';
2
2
  import { CustomPropertyStyleSheet } from '../styles/CustomPropertyStyleSheet';
3
- const CUSTOM_PROPERTIES_STYLESHEET = new CustomPropertyStyleSheet(document.getElementById(CUSTOM_PROPERTIES_STYLESHEET_ID)?.sheet);
4
- export function subscribeCustomProperty({ selector, customPropertyName, signal, variant, }) {
5
- signal.subscribe(CUSTOM_PROPERTIES_STYLESHEET.registerProperty(selector, customPropertyName, variant), {
6
- destroy: () => CUSTOM_PROPERTIES_STYLESHEET.unregisterProperty(selector, customPropertyName, variant),
3
+ let customPropertiesStylesheet;
4
+ export function subscribeCustomProperty({ selector, customPropertyName, signal, variant, root, runtime, }) {
5
+ customPropertiesStylesheet ??= new CustomPropertyStyleSheet(root, root.getElementById(CUSTOM_PROPERTIES_STYLESHEET_ID)?.sheet);
6
+ signal.subscribe(customPropertiesStylesheet.registerProperty(selector, customPropertyName, variant), {
7
+ destroy: () => {
8
+ customPropertiesStylesheet?.unregisterProperty(selector, customPropertyName, {
9
+ deepClean: runtime === 'preview',
10
+ mediaQuery: variant?.mediaQuery,
11
+ startingStyle: variant?.startingStyle,
12
+ });
13
+ },
7
14
  });
8
15
  }
9
16
  //# sourceMappingURL=subscribeCustomProperty.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"subscribeCustomProperty.js","sourceRoot":"","sources":["../../src/utils/subscribeCustomProperty.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,+BAA+B,EAAE,MAAM,0CAA0C,CAAA;AAC1F,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAA;AAE7E,MAAM,4BAA4B,GAAG,IAAI,wBAAwB,CAE7D,QAAQ,CAAC,cAAc,CAAC,+BAA+B,CAGxD,EAAE,KAAK,CACT,CAAA;AAED,MAAM,UAAU,uBAAuB,CAAC,EACtC,QAAQ,EACR,kBAAkB,EAClB,MAAM,EACN,OAAO,GAMR;IACC,MAAM,CAAC,SAAS,CACd,4BAA4B,CAAC,gBAAgB,CAC3C,QAAQ,EACR,kBAAkB,EAClB,OAAO,CACR,EACD;QACE,OAAO,EAAE,GAAG,EAAE,CACZ,4BAA4B,CAAC,kBAAkB,CAC7C,QAAQ,EACR,kBAAkB,EAClB,OAAO,CACR;KACJ,CACF,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"subscribeCustomProperty.js","sourceRoot":"","sources":["../../src/utils/subscribeCustomProperty.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,+BAA+B,EAAE,MAAM,0CAA0C,CAAA;AAE1F,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAA;AAE7E,IAAI,0BAAgE,CAAA;AAEpE,MAAM,UAAU,uBAAuB,CAAC,EACtC,QAAQ,EACR,kBAAkB,EAClB,MAAM,EACN,OAAO,EACP,IAAI,EACJ,OAAO,GAQR;IACC,0BAA0B,KAAK,IAAI,wBAAwB,CACzD,IAAI,EAEF,IAAI,CAAC,cAAc,CAAC,+BAA+B,CAGpD,EAAE,KAAK,CACT,CAAA;IAED,MAAM,CAAC,SAAS,CACd,0BAA0B,CAAC,gBAAgB,CACzC,QAAQ,EACR,kBAAkB,EAClB,OAAO,CACR,EACD;QACE,OAAO,EAAE,GAAG,EAAE;YACZ,0BAA0B,EAAE,kBAAkB,CAC5C,QAAQ,EACR,kBAAkB,EAClB;gBACE,SAAS,EAAE,OAAO,KAAK,SAAS;gBAChC,UAAU,EAAE,OAAO,EAAE,UAAU;gBAC/B,aAAa,EAAE,OAAO,EAAE,aAAa;aACtC,CACF,CAAA;QACH,CAAC;KACF,CACF,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -4,8 +4,8 @@
4
4
  "type": "module",
5
5
  "homepage": "https://github.com/nordcraftengine/nordcraft",
6
6
  "dependencies": {
7
- "@nordcraft/core": "1.0.33",
8
- "@nordcraft/std-lib": "1.0.33",
7
+ "@nordcraft/core": "1.0.34",
8
+ "@nordcraft/std-lib": "1.0.34",
9
9
  "fast-deep-equal": "3.1.3",
10
10
  "path-to-regexp": "6.3.0"
11
11
  },
@@ -21,5 +21,5 @@
21
21
  "files": ["dist", "src"],
22
22
  "main": "dist/page.main.js",
23
23
  "types": "dist/page.main.d.ts",
24
- "version": "1.0.33"
24
+ "version": "1.0.34"
25
25
  }
@@ -89,6 +89,8 @@ export function createComponent({
89
89
  })
90
90
  }),
91
91
  customPropertyName,
92
+ root: ctx.root,
93
+ runtime: ctx.env.runtime,
92
94
  }),
93
95
  )
94
96
  node.variants?.forEach((variant) => {
@@ -113,6 +115,8 @@ export function createComponent({
113
115
  ),
114
116
  customPropertyName,
115
117
  variant,
118
+ root: ctx.root,
119
+ runtime: ctx.env.runtime,
116
120
  }),
117
121
  )
118
122
  })
@@ -154,7 +154,12 @@ export function createElement({
154
154
  ([customPropertyName, { formula }]) =>
155
155
  subscribeCustomProperty({
156
156
  customPropertyName,
157
- selector: getNodeSelector(path),
157
+ selector:
158
+ ctx.env.runtime === 'custom-element' &&
159
+ ctx.isRootComponent &&
160
+ path === '0'
161
+ ? `${getNodeSelector(path)}, :host`
162
+ : getNodeSelector(path),
158
163
  signal: dataSignal.map((data) =>
159
164
  applyFormula(formula, {
160
165
  data,
@@ -166,6 +171,8 @@ export function createElement({
166
171
  env: ctx.env,
167
172
  }),
168
173
  ),
174
+ root: ctx.root,
175
+ runtime: ctx.env.runtime,
169
176
  }),
170
177
  )
171
178
 
@@ -189,6 +196,8 @@ export function createElement({
189
196
  env: ctx.env,
190
197
  }),
191
198
  ),
199
+ root: ctx.root,
200
+ runtime: ctx.env.runtime,
192
201
  })
193
202
  },
194
203
  )
@@ -0,0 +1,37 @@
1
+ export const createPanicScreen = ({
2
+ name,
3
+ message,
4
+ isPage,
5
+ cause,
6
+ }: {
7
+ name: string
8
+ message: string
9
+ isPage?: boolean
10
+ cause?: unknown
11
+ }) => {
12
+ let content = getContent(name, message, isPage)
13
+
14
+ // Easter egg for RangeError
15
+ if (cause instanceof RangeError) {
16
+ for (let i = 0; i < 10; i++) {
17
+ content += `<div style="transform-origin: 15% 15%; scale: ${1 / (i * 0.225 + 1.225)}; font-size: ${22 / ((i * 0.6) ** 2 + 1)}px">${getContent(name, message, isPage)}</div>`
18
+ }
19
+ }
20
+
21
+ return document.createRange().createContextualFragment(`
22
+ <main style="background-color: blue; color: white; font-family: 'Courier New', monospace; font-weight: 100; display: flex; justify-content: flex-start; align-items: flex-start; margin: 0px; padding: 0px;">
23
+ <div style="display: flex; flex-direction: column; justify-content: space-between; align-items: flex-start; height: 100vh;">
24
+ <div style="display: flex; flex-direction: column; gap: 20px; padding: 80px; font-size: 22px;">
25
+ ${content}
26
+ </div>
27
+ </div>
28
+ <div style="position:fixed; pointer-events: none; width: 100vw; height: 100vh; background-image: linear-gradient(0deg, rgba(0,0,0,0) 25%, rgba(0,0,0,0.33) 25%, rgba(0,0,0,0.33) 50%, rgba(0,0,0,0) 50%, rgba(0,0,0,0) 75%, rgba(0,0,0,0.33) 75%, rgba(0,0,0,0.33) 100%); background-size: 4px 4px;"></div>
29
+ <div style="position:fixed; pointer-events: none; width: 100vw; height: 100vh; background-image: radial-gradient(ellipse at center, rgba(0,0,0,0) 50%, rgba(0,0,0,0.25) 100%);"></div>
30
+ </main>
31
+ `)
32
+ }
33
+
34
+ const getContent = (name: string, message: string, isPage?: boolean) => `
35
+ <h1 style="display: inline; font-size: 1em; background: white; color: blue; padding: 0.4em 0.8em;">${name}</h1>
36
+ <p style="font-size: 0.8em;">The ${isPage ? 'page' : 'component'} could not be rendered. Fix the issue and try again. Join our <a style="color:white" href="https://discord.gg/nordcraft" target="_blank">Discord</a> for help.</p>
37
+ <p style="font-size: 0.81em;">Error Message: ${message}</p>`
@@ -0,0 +1,19 @@
1
+ export function sendEditorToast(
2
+ title: string,
3
+ message: string,
4
+ {
5
+ type = 'neutral',
6
+ }: {
7
+ type?: 'neutral' | 'warning' | 'critical'
8
+ },
9
+ ) {
10
+ window.parent?.postMessage(
11
+ {
12
+ type: 'emitToast',
13
+ toastType: type,
14
+ title,
15
+ message,
16
+ },
17
+ '*',
18
+ )
19
+ }
@@ -38,6 +38,8 @@ import { createLegacyAPI } from './api/createAPI'
38
38
  import { createAPI } from './api/createAPIv2'
39
39
  import { createNode } from './components/createNode'
40
40
  import { isContextProvider } from './context/isContextProvider'
41
+ import { createPanicScreen } from './debug/panicScreen'
42
+ import { sendEditorToast } from './debug/sendEditorToast'
41
43
  import { dragEnded } from './editor/drag-drop/dragEnded'
42
44
  import { dragMove } from './editor/drag-drop/dragMove'
43
45
  import { dragReorder } from './editor/drag-drop/dragReorder'
@@ -566,7 +568,7 @@ export const createRoot = (
566
568
  }
567
569
  const { x, y, type } = message.data
568
570
  const elementsAtPoint = document.elementsFromPoint(x, y)
569
- let element = elementsAtPoint.find((elem) => {
571
+ const element = elementsAtPoint.find((elem) => {
570
572
  const id = elem.getAttribute('data-id')
571
573
  if (
572
574
  typeof id !== 'string' ||
@@ -583,31 +585,12 @@ export const createRoot = (
583
585
  if (elem.getAttribute('data-node-type') === 'text') {
584
586
  return (
585
587
  // Select text nodes if the meta key is pressed or the text node is double-clicked
586
- metaKey ||
587
- type === 'dblclick' ||
588
- // Select text nodes if the selected node is a text node. This is useful as the user is likely in a text editing mode
589
- getDOMNodeFromNodeId(selectedNodeId)?.getAttribute(
590
- 'data-node-type',
591
- ) === 'text'
588
+ metaKey || type === 'dblclick'
592
589
  )
593
590
  }
594
591
  return true
595
592
  })
596
593
 
597
- // Bubble selection to the topmost parent that has the exact same size as the element.
598
- // This is important for drag and drop as you are often left with childless parents after dragging.
599
- while (
600
- element?.parentElement &&
601
- element.getAttribute('data-node-id') !== 'root' &&
602
- fastDeepEqual(
603
- element.getBoundingClientRect().toJSON(),
604
- element.parentElement.getBoundingClientRect().toJSON(),
605
- ) &&
606
- element.getAttribute('data-node-type') !== 'text'
607
- ) {
608
- element = element.parentElement
609
- }
610
-
611
594
  const id = element?.getAttribute('data-id') ?? null
612
595
  if (type === 'click' && id !== selectedNodeId) {
613
596
  if (message.data.metaKey) {
@@ -986,10 +969,30 @@ export const createRoot = (
986
969
  document.head.appendChild(styleTag)
987
970
  }
988
971
 
972
+ // If style variant targets a pseudo-element, apply styles to it instead
973
+ let pseudoElement = ''
974
+ if (component && styleVariantSelection) {
975
+ const nodeLookup = getNodeAndAncestors(
976
+ component,
977
+ component.nodes.root,
978
+ styleVariantSelection.nodeId,
979
+ )
980
+
981
+ if (
982
+ nodeLookup?.node.type === 'element' ||
983
+ (nodeLookup?.node.type === 'component' &&
984
+ nodeLookup.node.variants?.[
985
+ styleVariantSelection.styleVariantIndex
986
+ ].pseudoElement)
987
+ ) {
988
+ pseudoElement = `::${nodeLookup.node.variants?.[styleVariantSelection.styleVariantIndex].pseudoElement}`
989
+ }
990
+ }
991
+
989
992
  const previewStyles = Object.entries(previewStyleStyles)
990
993
  .map(([key, value]) => `${key}: ${value} !important;`)
991
994
  .join('\n')
992
- styleTag.innerHTML = `[data-id="${selectedNodeId}"], [data-id="${selectedNodeId}"] ~ [data-id^="${selectedNodeId}("] {
995
+ styleTag.innerHTML = `[data-id="${selectedNodeId}"]${pseudoElement}, [data-id="${selectedNodeId}"] ~ [data-id^="${selectedNodeId}("]${pseudoElement} {
993
996
  ${previewStyles}
994
997
  transition: none !important;
995
998
  }`
@@ -1054,9 +1057,10 @@ export const createRoot = (
1054
1057
  (nodeLookup.node.type === 'element' ||
1055
1058
  nodeLookup.node.type === 'component')
1056
1059
  ) {
1057
- const selectedStyleVariant = nodeLookup.node.variants?.[
1058
- styleVariantSelection.styleVariantIndex
1059
- ] ?? { style: {} }
1060
+ const selectedStyleVariant =
1061
+ nodeLookup.node.variants?.[
1062
+ styleVariantSelection.styleVariantIndex
1063
+ ] ?? ({ style: {} } as StyleVariant)
1060
1064
  // Add a style element specific to the selected element which
1061
1065
  // is only applied when the preview is in design mode
1062
1066
  const styleVariantCustomProperties = Object.entries(
@@ -1081,12 +1085,15 @@ export const createRoot = (
1081
1085
  .filter(({ value }) => value !== undefined)
1082
1086
 
1083
1087
  const styleElem = document.createElement('style')
1088
+ const pseudoElement = selectedStyleVariant.pseudoElement
1089
+ ? `::${selectedStyleVariant.pseudoElement}`
1090
+ : ''
1084
1091
  styleElem.setAttribute('data-hash', selectedNodeId)
1085
1092
  styleElem.appendChild(
1086
1093
  document.createTextNode(`
1087
- body[data-mode="design"] [data-id="${selectedNodeId}"] {
1094
+ body[data-mode="design"] [data-id="${selectedNodeId}"]${pseudoElement} {
1088
1095
  ${styleToCss({
1089
- ...nodeLookup.node.style,
1096
+ ...(!pseudoElement && nodeLookup.node.style),
1090
1097
  ...selectedStyleVariant.style,
1091
1098
  ...Object.fromEntries(
1092
1099
  styleVariantCustomProperties.map(
@@ -1406,19 +1413,53 @@ export const createRoot = (
1406
1413
  // Clear old root signal and create a new one to not keep old signals with previous root around
1407
1414
  ctxDataSignal?.destroy()
1408
1415
  ctxDataSignal = dataSignal.map((data) => data)
1409
- const rootElem = createNode({
1410
- id: 'root',
1411
- path: '0',
1412
- dataSignal: ctxDataSignal,
1413
- ctx: newCtx,
1414
- parentElement: domNode,
1415
- instance: { [newCtx.component.name]: 'root' },
1416
- })
1417
- newCtx.component.onLoad?.actions.forEach((action) => {
1418
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
1419
- handleAction(action, dataSignal.get(), newCtx)
1420
- })
1421
- rootElem.forEach((elem) => domNode.appendChild(elem))
1416
+ try {
1417
+ const rootElem = createNode({
1418
+ id: 'root',
1419
+ path: '0',
1420
+ dataSignal: ctxDataSignal,
1421
+ ctx: newCtx,
1422
+ parentElement: domNode,
1423
+ instance: { [newCtx.component.name]: 'root' },
1424
+ })
1425
+ newCtx.component.onLoad?.actions.forEach((action) => {
1426
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
1427
+ handleAction(action, dataSignal.get(), newCtx)
1428
+ })
1429
+ rootElem.forEach((elem) => domNode.appendChild(elem))
1430
+ } catch (error: unknown) {
1431
+ const isPage = isPageComponent(newCtx.component)
1432
+ let name = `Unexpected error while rendering ${isPage ? 'page' : 'component'}`
1433
+ let message = error instanceof Error ? error.message : String(error)
1434
+ let panic = false
1435
+ if (error instanceof RangeError) {
1436
+ // RangeError is unrecoverable
1437
+ panic = true
1438
+ name = 'Infinite loop detected'
1439
+ message =
1440
+ 'RangeError (Maximum call stack size exceeded): Remove any circular dependencies or recursive calls. This is most likely caused by components, formulas or actions using themselves without an exit case.'
1441
+ }
1442
+
1443
+ // Send a toast to the editor with the error
1444
+ sendEditorToast(name, message, {
1445
+ type: 'critical',
1446
+ })
1447
+
1448
+ if (panic) {
1449
+ // Show error overlay in the editor until next update
1450
+ const panicScreen = createPanicScreen({
1451
+ name: name,
1452
+ message,
1453
+ isPage,
1454
+ cause: error,
1455
+ })
1456
+
1457
+ // Replace the inner HTML of the editor preview with the panic screen
1458
+ domNode.innerHTML = ''
1459
+ domNode.appendChild(panicScreen)
1460
+ }
1461
+ console.error(name, message, error)
1462
+ }
1422
1463
  window.parent?.postMessage(
1423
1464
  {
1424
1465
  type: 'style',
@@ -3,20 +3,20 @@ import { CustomPropertyStyleSheet } from './CustomPropertyStyleSheet'
3
3
 
4
4
  describe('CustomPropertyStyleSheet', () => {
5
5
  test('it creates a new stylesheet', () => {
6
- const instance = new CustomPropertyStyleSheet()
6
+ const instance = new CustomPropertyStyleSheet(document)
7
7
  expect(instance).toBeInstanceOf(CustomPropertyStyleSheet)
8
8
  expect(instance.getStyleSheet().cssRules).toHaveLength(0)
9
9
  })
10
10
 
11
11
  test('it adds a property definition', () => {
12
- const instance = new CustomPropertyStyleSheet()
12
+ const instance = new CustomPropertyStyleSheet(document)
13
13
  instance.registerProperty('.my-class', '--my-property')
14
14
  expect(instance.getStyleSheet().cssRules.length).toBe(1)
15
15
  expect(instance.getStyleSheet().cssRules[0].cssText).toBe('.my-class { }')
16
16
  })
17
17
 
18
18
  test('it puts different selectors in different rules', () => {
19
- const instance = new CustomPropertyStyleSheet()
19
+ const instance = new CustomPropertyStyleSheet(document)
20
20
  instance.registerProperty('.my-class', '--my-property')('256px')
21
21
  instance.registerProperty('.my-other-class', '--my-property')('256px')
22
22
  expect(instance.getStyleSheet().cssRules.length).toBe(2)
@@ -29,7 +29,7 @@ describe('CustomPropertyStyleSheet', () => {
29
29
  })
30
30
 
31
31
  test('it can update properties', () => {
32
- const instance = new CustomPropertyStyleSheet()
32
+ const instance = new CustomPropertyStyleSheet(document)
33
33
  const setter = instance.registerProperty('.my-class', '--my-property')
34
34
  setter('256px')
35
35
  expect(instance.getStyleSheet().cssRules.length).toBe(1)
@@ -44,7 +44,7 @@ describe('CustomPropertyStyleSheet', () => {
44
44
  })
45
45
 
46
46
  test('it works with media queries', () => {
47
- const instance = new CustomPropertyStyleSheet()
47
+ const instance = new CustomPropertyStyleSheet(document)
48
48
  instance.registerProperty('.my-class', '--my-property', {
49
49
  mediaQuery: { 'max-width': '600px' },
50
50
  })('256px')
@@ -55,7 +55,7 @@ describe('CustomPropertyStyleSheet', () => {
55
55
  })
56
56
 
57
57
  test('it unregisters a property', () => {
58
- const instance = new CustomPropertyStyleSheet()
58
+ const instance = new CustomPropertyStyleSheet(document)
59
59
  const setter = instance.registerProperty('.my-class', '--my-property')
60
60
  setter('256px')
61
61
  const setter2 = instance.registerProperty(
@@ -76,7 +76,7 @@ describe('CustomPropertyStyleSheet', () => {
76
76
  })
77
77
 
78
78
  test('it unregisters a property with media queries', () => {
79
- const instance = new CustomPropertyStyleSheet()
79
+ const instance = new CustomPropertyStyleSheet(document)
80
80
  const setter = instance.registerProperty(
81
81
  '.my-class-with-media',
82
82
  '--my-property-with-media',
@@ -15,12 +15,12 @@ export class CustomPropertyStyleSheet {
15
15
  // Selector to rule index mapping
16
16
  private ruleMap: Map<string, CSSStyleRule | CSSNestedDeclarations> | undefined
17
17
 
18
- constructor(styleSheet?: CSSStyleSheet | null) {
18
+ constructor(root: Document | ShadowRoot, styleSheet?: CSSStyleSheet | null) {
19
19
  if (styleSheet) {
20
20
  this.styleSheet = styleSheet
21
21
  } else {
22
22
  this.styleSheet = new CSSStyleSheet()
23
- document.adoptedStyleSheets.push(this.getStyleSheet())
23
+ root.adoptedStyleSheets.push(this.getStyleSheet())
24
24
  }
25
25
  }
26
26
 
@@ -44,7 +44,10 @@ export class CustomPropertyStyleSheet {
44
44
  // Check if the selector already exists
45
45
  let rule = this.ruleMap.get(fullSelector)
46
46
  if (!rule) {
47
- const ruleIndex = this.styleSheet.insertRule(fullSelector)
47
+ const ruleIndex = this.styleSheet.insertRule(
48
+ fullSelector,
49
+ this.styleSheet.cssRules.length,
50
+ )
48
51
  let newRule = this.styleSheet.cssRules[ruleIndex]
49
52
 
50
53
  // We are only interested in the dynamic style, so get the actual style rule, not media or other nested rules. Loop until we are at the bottom most rule.
@@ -69,6 +72,7 @@ export class CustomPropertyStyleSheet {
69
72
  options?: {
70
73
  mediaQuery?: MediaQuery
71
74
  startingStyle?: boolean
75
+ deepClean?: boolean
72
76
  },
73
77
  ): void {
74
78
  if (!this.ruleMap) {
@@ -80,8 +84,21 @@ export class CustomPropertyStyleSheet {
80
84
  options,
81
85
  )
82
86
 
83
- // We only clean up the property, as we assume that the rule will be reused.
84
- this.ruleMap.get(fullSelector)?.style.removeProperty(name)
87
+ const rule = this.ruleMap.get(fullSelector)
88
+ if (!rule) {
89
+ return
90
+ }
91
+
92
+ rule.style.removeProperty(name)
93
+
94
+ // Cleaning up empty selectors is probably not necessary in production and may have performance implications.
95
+ // However, it is required for the editor-preview as it is a dynamic environment and things may get reordered and canvas reused.
96
+ if (options?.deepClean && rule.style.length === 0) {
97
+ this.styleSheet.deleteRule(
98
+ Array.from(this.ruleMap.keys()).indexOf(fullSelector),
99
+ )
100
+ this.ruleMap.delete(fullSelector)
101
+ }
85
102
  }
86
103
 
87
104
  public getStyleSheet(): CSSStyleSheet {