@nordcraft/runtime 1.0.87 → 1.0.89

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 (46) hide show
  1. package/dist/custom-element.main.esm.js +30 -30
  2. package/dist/custom-element.main.esm.js.map +4 -4
  3. package/dist/page.main.esm.js +3 -3
  4. package/dist/page.main.esm.js.map +4 -4
  5. package/dist/src/components/createComponent.js +60 -69
  6. package/dist/src/components/createComponent.js.map +1 -1
  7. package/dist/src/components/createElement.js +33 -50
  8. package/dist/src/components/createElement.js.map +1 -1
  9. package/dist/src/components/createNode.js +8 -1
  10. package/dist/src/components/createNode.js.map +1 -1
  11. package/dist/src/components/createNode.test.d.ts +1 -0
  12. package/dist/src/components/createNode.test.js +608 -0
  13. package/dist/src/components/createNode.test.js.map +1 -0
  14. package/dist/src/components/renderComponent.js +2 -4
  15. package/dist/src/components/renderComponent.js.map +1 -1
  16. package/dist/src/editor-preview.main.js +4 -4
  17. package/dist/src/editor-preview.main.js.map +1 -1
  18. package/dist/src/page.main.js +31 -41
  19. package/dist/src/page.main.js.map +1 -1
  20. package/dist/src/styles/CustomPropertyStyleSheet.d.ts +0 -1
  21. package/dist/src/styles/CustomPropertyStyleSheet.js +1 -1
  22. package/dist/src/styles/CustomPropertyStyleSheet.js.map +1 -1
  23. package/dist/src/styles/CustomPropertyStyleSheet.test.js +2 -5
  24. package/dist/src/styles/CustomPropertyStyleSheet.test.js.map +1 -1
  25. package/dist/src/utils/BatchQueue.d.ts +1 -0
  26. package/dist/src/utils/BatchQueue.js +2 -1
  27. package/dist/src/utils/BatchQueue.js.map +1 -1
  28. package/dist/src/utils/formulaHasValue.d.ts +2 -0
  29. package/dist/src/utils/formulaHasValue.js +3 -0
  30. package/dist/src/utils/formulaHasValue.js.map +1 -0
  31. package/dist/src/utils/subscribeCustomProperty.d.ts +3 -3
  32. package/dist/src/utils/subscribeCustomProperty.js +2 -3
  33. package/dist/src/utils/subscribeCustomProperty.js.map +1 -1
  34. package/package.json +3 -3
  35. package/src/components/createComponent.ts +78 -86
  36. package/src/components/createElement.ts +25 -46
  37. package/src/components/createNode.test.ts +686 -0
  38. package/src/components/createNode.ts +8 -1
  39. package/src/components/renderComponent.ts +2 -4
  40. package/src/editor-preview.main.ts +4 -4
  41. package/src/page.main.ts +49 -51
  42. package/src/styles/CustomPropertyStyleSheet.test.ts +2 -7
  43. package/src/styles/CustomPropertyStyleSheet.ts +1 -2
  44. package/src/utils/BatchQueue.ts +2 -2
  45. package/src/utils/formulaHasValue.ts +7 -0
  46. package/src/utils/subscribeCustomProperty.ts +1 -5
@@ -3,13 +3,14 @@
3
3
  * This is more efficient than processing each callback in a separate requestAnimationFrame due to the overhead.
4
4
  */
5
5
  export class BatchQueue {
6
+ constructor() { }
6
7
  batchQueue = [];
7
8
  isProcessing = false;
8
9
  processBatch() {
9
10
  if (this.isProcessing)
10
11
  return;
11
12
  this.isProcessing = true;
12
- requestAnimationFrame(() => {
13
+ queueMicrotask(() => {
13
14
  while (this.batchQueue.length > 0) {
14
15
  const callback = this.batchQueue.shift();
15
16
  callback?.();
@@ -1 +1 @@
1
- {"version":3,"file":"BatchQueue.js","sourceRoot":"","sources":["../../../src/utils/BatchQueue.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,OAAO,UAAU;IACb,UAAU,GAAsB,EAAE,CAAA;IAClC,YAAY,GAAG,KAAK,CAAA;IACpB,YAAY,GAAG;QACrB,IAAI,IAAI,CAAC,YAAY;YAAE,OAAM;QAC7B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAA;QAExB,qBAAqB,CAAC,GAAG,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAA;gBACxC,QAAQ,EAAE,EAAE,CAAA;YACd,CAAC;YACD,IAAI,CAAC,YAAY,GAAG,KAAK,CAAA;QAAA,CAC1B,CAAC,CAAA;IAAA,CACH;IACM,GAAG,CAAC,QAAoB,EAAE;QAC/B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAC9B,IAAI,CAAC,YAAY,EAAE,CAAA;IAAA,CACpB;CACF"}
1
+ {"version":3,"file":"BatchQueue.js","sourceRoot":"","sources":["../../../src/utils/BatchQueue.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,OAAO,UAAU;IACrB,cAAc,EAAC,CAAC;IACR,UAAU,GAAsB,EAAE,CAAA;IAClC,YAAY,GAAG,KAAK,CAAA;IACpB,YAAY,GAAG;QACrB,IAAI,IAAI,CAAC,YAAY;YAAE,OAAM;QAC7B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAA;QACxB,cAAc,CAAC,GAAG,EAAE,CAAC;YACnB,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAA;gBACxC,QAAQ,EAAE,EAAE,CAAA;YACd,CAAC;YACD,IAAI,CAAC,YAAY,GAAG,KAAK,CAAA;QAAA,CAC1B,CAAC,CAAA;IAAA,CACH;IACM,GAAG,CAAC,QAAoB,EAAE;QAC/B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAC9B,IAAI,CAAC,YAAY,EAAE,CAAA;IAAA,CACpB;CACF"}
@@ -0,0 +1,2 @@
1
+ import type { Formula } from '@nordcraft/core/dist/formula/formula';
2
+ export declare const formulaHasValue: (formula: Formula | undefined) => formula is Formula;
@@ -0,0 +1,3 @@
1
+ import { isDefined } from '@nordcraft/core/dist/utils/util';
2
+ export const formulaHasValue = (formula) => isDefined(formula) && !(formula.type === 'value' && !isDefined(formula.value));
3
+ //# sourceMappingURL=formulaHasValue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formulaHasValue.js","sourceRoot":"","sources":["../../../src/utils/formulaHasValue.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAA;AAE3D,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,OAA4B,EACR,EAAE,CACtB,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA"}
@@ -1,11 +1,11 @@
1
1
  import type { Signal } from '../signal/signal';
2
2
  import type { StyleVariant } from '@nordcraft/core/dist/styling/variantSelector';
3
- import type { Runtime } from '@nordcraft/core/dist/types';
4
- export declare function subscribeCustomProperty({ selector, customPropertyName, signal, variant, root, runtime }: {
3
+ import { CustomPropertyStyleSheet } from '../styles/CustomPropertyStyleSheet';
4
+ export declare let customPropertiesStylesheet: CustomPropertyStyleSheet | undefined;
5
+ export declare function subscribeCustomProperty({ selector, customPropertyName, signal, variant, root }: {
5
6
  selector: string;
6
7
  customPropertyName: string;
7
8
  signal: Signal<string>;
8
9
  variant?: StyleVariant;
9
10
  root: Document | ShadowRoot;
10
- runtime: Runtime;
11
11
  }): void;
@@ -1,12 +1,11 @@
1
1
  import { CUSTOM_PROPERTIES_STYLESHEET_ID } from '@nordcraft/core/dist/styling/theme.const';
2
2
  import { CustomPropertyStyleSheet } from '../styles/CustomPropertyStyleSheet';
3
- let customPropertiesStylesheet;
4
- export function subscribeCustomProperty({ selector, customPropertyName, signal, variant, root, runtime, }) {
3
+ export let customPropertiesStylesheet;
4
+ export function subscribeCustomProperty({ selector, customPropertyName, signal, variant, root, }) {
5
5
  customPropertiesStylesheet ??= new CustomPropertyStyleSheet(root, root.getElementById(CUSTOM_PROPERTIES_STYLESHEET_ID)?.sheet);
6
6
  signal.subscribe(customPropertiesStylesheet.registerProperty(selector, customPropertyName, variant), {
7
7
  destroy: () => {
8
8
  customPropertiesStylesheet?.unregisterProperty(selector, customPropertyName, {
9
- deepClean: runtime === 'preview',
10
9
  mediaQuery: variant?.mediaQuery,
11
10
  startingStyle: variant?.startingStyle,
12
11
  });
@@ -1 +1 @@
1
- {"version":3,"file":"subscribeCustomProperty.js","sourceRoot":"","sources":["../../../src/utils/subscribeCustomProperty.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,+BAA+B,EAAE,MAAM,0CAA0C,CAAA;AAG1F,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,EAAE;IACD,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,CAAC;YACb,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;QAAA,CACF;KACF,CACF,CAAA;AAAA,CACF"}
1
+ {"version":3,"file":"subscribeCustomProperty.js","sourceRoot":"","sources":["../../../src/utils/subscribeCustomProperty.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,+BAA+B,EAAE,MAAM,0CAA0C,CAAA;AAE1F,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAA;AAE7E,MAAM,CAAC,IAAI,0BAAgE,CAAA;AAE3E,MAAM,UAAU,uBAAuB,CAAC,EACtC,QAAQ,EACR,kBAAkB,EAClB,MAAM,EACN,OAAO,EACP,IAAI,GAOL,EAAE;IACD,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,CAAC;YACb,0BAA0B,EAAE,kBAAkB,CAC5C,QAAQ,EACR,kBAAkB,EAClB;gBACE,UAAU,EAAE,OAAO,EAAE,UAAU;gBAC/B,aAAa,EAAE,OAAO,EAAE,aAAa;aACtC,CACF,CAAA;QAAA,CACF;KACF,CACF,CAAA;AAAA,CACF"}
package/package.json CHANGED
@@ -9,8 +9,8 @@
9
9
  "directory": "packages/runtime"
10
10
  },
11
11
  "dependencies": {
12
- "@nordcraft/core": "1.0.87",
13
- "@nordcraft/std-lib": "1.0.87",
12
+ "@nordcraft/core": "1.0.89",
13
+ "@nordcraft/std-lib": "1.0.89",
14
14
  "fast-deep-equal": "3.1.3",
15
15
  "path-to-regexp": "6.3.0"
16
16
  },
@@ -23,5 +23,5 @@
23
23
  "files": ["dist", "src"],
24
24
  "main": "dist/page.main.js",
25
25
  "types": "dist/page.main.d.ts",
26
- "version": "1.0.87"
26
+ "version": "1.0.89"
27
27
  }
@@ -20,6 +20,7 @@ import type { Signal } from '../signal/signal'
20
20
  import { signal } from '../signal/signal'
21
21
  import type { ComponentChild, ComponentContext, ContextApi } from '../types'
22
22
  import { createFormulaCache } from '../utils/createFormulaCache'
23
+ import { formulaHasValue } from '../utils/formulaHasValue'
23
24
  import { subscribeCustomProperty } from '../utils/subscribeCustomProperty'
24
25
  import { renderComponent } from './renderComponent'
25
26
 
@@ -55,78 +56,25 @@ export function createComponent({
55
56
  )
56
57
  return []
57
58
  }
59
+ const formulaCtx = {
60
+ component: ctx.component,
61
+ formulaCache: ctx.formulaCache,
62
+ root: ctx.root,
63
+ package: ctx.package,
64
+ toddle: ctx.toddle,
65
+ env: ctx.env,
66
+ }
58
67
  const attributesSignal = dataSignal.map((data) => {
59
68
  return mapObject(node.attrs, ([attr, value]) => [
60
69
  attr,
61
70
  value?.type !== 'value'
62
71
  ? applyFormula(value, {
72
+ ...formulaCtx,
63
73
  data,
64
- component: ctx.component,
65
- formulaCache: ctx.formulaCache,
66
- root: ctx.root,
67
- package: ctx.package,
68
- toddle: ctx.toddle,
69
- env: ctx.env,
70
74
  })
71
75
  : value?.value,
72
76
  ])
73
77
  })
74
- Object.entries(node.customProperties ?? {}).forEach(
75
- ([customPropertyName, customProperty]) =>
76
- subscribeCustomProperty({
77
- selector: getNodeSelector(path, {
78
- componentName: ctx.component.name,
79
- nodeId: node.id,
80
- }),
81
- signal: dataSignal.map((data) =>
82
- appendUnit(
83
- applyFormula(customProperty.formula, {
84
- data,
85
- component: ctx.component,
86
- formulaCache: ctx.formulaCache,
87
- root: ctx.root,
88
- package: ctx.package,
89
- toddle: ctx.toddle,
90
- env: ctx.env,
91
- }),
92
- customProperty.unit,
93
- ),
94
- ),
95
- customPropertyName,
96
- root: ctx.root,
97
- runtime: ctx.env.runtime,
98
- }),
99
- )
100
- node.variants?.forEach((variant) => {
101
- Object.entries(variant.customProperties ?? {}).forEach(
102
- ([customPropertyName, customProperty]) =>
103
- subscribeCustomProperty({
104
- selector: getNodeSelector(path, {
105
- componentName: ctx.component.name,
106
- nodeId: node.id,
107
- variant,
108
- }),
109
- signal: dataSignal.map((data) =>
110
- appendUnit(
111
- applyFormula(customProperty.formula, {
112
- data,
113
- component: ctx.component,
114
- formulaCache: ctx.formulaCache,
115
- root: ctx.root,
116
- package: ctx.package,
117
- toddle: ctx.toddle,
118
- env: ctx.env,
119
- }),
120
- customProperty.unit,
121
- ),
122
- ),
123
- customPropertyName,
124
- variant,
125
- root: ctx.root,
126
- runtime: ctx.env.runtime,
127
- }),
128
- )
129
- })
130
78
 
131
79
  const componentDataSignal = signal<ComponentData>({
132
80
  Location: dataSignal.get().Location,
@@ -138,13 +86,9 @@ export function createComponent({
138
86
  isLoading:
139
87
  api.autoFetch &&
140
88
  applyFormula(api.autoFetch, {
141
- data: dataSignal.get(),
89
+ ...formulaCtx,
142
90
  component,
143
- formulaCache: ctx.formulaCache,
144
- root: ctx.root,
145
- package: ctx.package,
146
- toddle: ctx.toddle,
147
- env: ctx.env,
91
+ data: dataSignal.get(),
148
92
  })
149
93
  ? true
150
94
  : false,
@@ -152,6 +96,19 @@ export function createComponent({
152
96
  },
153
97
  ]),
154
98
  })
99
+
100
+ // Subscribe to global stores (currently only theme)
101
+ // We subscribe before calculating variable initial values to ensure they can reference global store values
102
+ ctx.stores.theme.subscribe((newTheme) => {
103
+ componentDataSignal.update((data) => ({
104
+ ...data,
105
+ Page: {
106
+ ...data.Page,
107
+ Theme: newTheme,
108
+ },
109
+ }))
110
+ })
111
+
155
112
  // Subscribe context before calculating variable initial values to ensure they can reference context values
156
113
  subscribeToContext(componentDataSignal, component, ctx)
157
114
  componentDataSignal.update((data) => ({
@@ -160,13 +117,9 @@ export function createComponent({
160
117
  name,
161
118
  applyFormula(variable.initialValue, {
162
119
  // Initial value
163
- data: componentDataSignal.get(),
120
+ ...formulaCtx,
164
121
  component,
165
- formulaCache: ctx.formulaCache,
166
- root: ctx.root,
167
- package: ctx.package,
168
- toddle: ctx.toddle,
169
- env: ctx.env,
122
+ data: componentDataSignal.get(),
170
123
  }),
171
124
  ]),
172
125
  }))
@@ -310,17 +263,6 @@ export function createComponent({
310
263
  })
311
264
  }
312
265
 
313
- // Subscribe to global stores (currently only theme)
314
- ctx.stores.theme.subscribe((newTheme) => {
315
- componentDataSignal.update((data) => ({
316
- ...data,
317
- Page: {
318
- ...data.Page,
319
- Theme: newTheme,
320
- },
321
- }))
322
- })
323
-
324
266
  attributesSignal.subscribe(
325
267
  (Attributes) =>
326
268
  componentDataSignal.update((data) => ({
@@ -330,7 +272,7 @@ export function createComponent({
330
272
  { destroy: () => componentDataSignal.destroy() },
331
273
  )
332
274
 
333
- return renderComponent({
275
+ const renderedComponent = renderComponent({
334
276
  dataSignal: componentDataSignal,
335
277
  component,
336
278
  components: ctx.components,
@@ -355,4 +297,54 @@ export function createComponent({
355
297
  ? { ...instance, [ctx.component.name]: 'root' }
356
298
  : { [ctx.component.name]: node.id ?? '' },
357
299
  })
300
+
301
+ // Custom properties instance overrides are added after the child tree is rendered to ensure correct order
302
+ Object.entries(node.customProperties ?? {})
303
+ .filter(([_, { formula }]) => formulaHasValue(formula))
304
+ .forEach(([customPropertyName, customProperty]) =>
305
+ subscribeCustomProperty({
306
+ selector: getNodeSelector(path, {
307
+ componentName: ctx.component.name,
308
+ nodeId: node.id,
309
+ }),
310
+ signal: dataSignal.map((data) =>
311
+ appendUnit(
312
+ applyFormula(customProperty.formula, {
313
+ ...formulaCtx,
314
+ data,
315
+ }),
316
+ customProperty.unit,
317
+ ),
318
+ ),
319
+ customPropertyName,
320
+ root: ctx.root,
321
+ }),
322
+ )
323
+ node.variants?.forEach((variant) => {
324
+ Object.entries(variant.customProperties ?? {})
325
+ .filter(([_, { formula }]) => formulaHasValue(formula))
326
+ .forEach(([customPropertyName, customProperty]) =>
327
+ subscribeCustomProperty({
328
+ selector: getNodeSelector(path, {
329
+ componentName: ctx.component.name,
330
+ nodeId: node.id,
331
+ variant,
332
+ }),
333
+ signal: dataSignal.map((data) =>
334
+ appendUnit(
335
+ applyFormula(customProperty.formula, {
336
+ ...formulaCtx,
337
+ data,
338
+ }),
339
+ customProperty.unit,
340
+ ),
341
+ ),
342
+ customPropertyName,
343
+ variant,
344
+ root: ctx.root,
345
+ }),
346
+ )
347
+ })
348
+
349
+ return renderedComponent
358
350
  }
@@ -15,6 +15,7 @@ import type { ComponentData } from '@nordcraft/core/src/component/component.type
15
15
  import { handleAction } from '../events/handleAction'
16
16
  import type { Signal } from '../signal/signal'
17
17
  import type { ComponentContext } from '../types'
18
+ import { formulaHasValue } from '../utils/formulaHasValue'
18
19
  import { getDragData } from '../utils/getDragData'
19
20
  import { getElementTagName } from '../utils/getElementTagName'
20
21
  import { setAttribute } from '../utils/setAttribute'
@@ -52,6 +53,15 @@ export function createElement({
52
53
  ? (document.createElementNS(namespace, tag) as SVGElement | MathMLElement)
53
54
  : document.createElement(tag)
54
55
 
56
+ const formulaCtx = {
57
+ component: ctx.component,
58
+ formulaCache: ctx.formulaCache,
59
+ root: ctx.root,
60
+ package: ctx.package,
61
+ toddle: ctx.toddle,
62
+ env: ctx.env,
63
+ }
64
+
55
65
  elem.setAttribute('data-node-id', id)
56
66
  if (path) {
57
67
  elem.setAttribute('data-id', path)
@@ -72,13 +82,8 @@ export function createElement({
72
82
  const classSignal = dataSignal.map((data) =>
73
83
  toBoolean(
74
84
  applyFormula(formula, {
85
+ ...formulaCtx,
75
86
  data,
76
- component: ctx.component,
77
- formulaCache: ctx.formulaCache,
78
- root: ctx.root,
79
- package: ctx.package,
80
- toddle: ctx.toddle,
81
- env: ctx.env,
82
87
  }),
83
88
  ),
84
89
  )
@@ -104,13 +109,8 @@ export function createElement({
104
109
  } else {
105
110
  o = dataSignal.map((data) =>
106
111
  applyFormula(value, {
112
+ ...formulaCtx,
107
113
  data,
108
- component: ctx.component,
109
- formulaCache: ctx.formulaCache,
110
- root: ctx.root,
111
- package: ctx.package,
112
- toddle: ctx.toddle,
113
- env: ctx.env,
114
114
  }),
115
115
  )
116
116
  o.subscribe((val) => {
@@ -139,13 +139,8 @@ export function createElement({
139
139
  const { name, formula, unit } = styleVariable
140
140
  const signal = dataSignal.map((data) => {
141
141
  const value = applyFormula(formula, {
142
+ ...formulaCtx,
142
143
  data,
143
- component: ctx.component,
144
- formulaCache: ctx.formulaCache,
145
- root: ctx.root,
146
- package: ctx.package,
147
- toddle: ctx.toddle,
148
- env: ctx.env,
149
144
  })
150
145
  return unit ? value + unit : value
151
146
  })
@@ -153,8 +148,9 @@ export function createElement({
153
148
  signal.subscribe((value) => elem.style.setProperty(`--${name}`, value))
154
149
  })
155
150
 
156
- Object.entries(node.customProperties ?? {}).forEach(
157
- ([customPropertyName, { formula, unit }]) =>
151
+ Object.entries(node.customProperties ?? {})
152
+ .filter(([_, { formula }]) => formulaHasValue(formula))
153
+ .forEach(([customPropertyName, { formula, unit }]) => {
158
154
  subscribeCustomProperty({
159
155
  customPropertyName,
160
156
  selector:
@@ -166,25 +162,20 @@ export function createElement({
166
162
  signal: dataSignal.map((data) =>
167
163
  appendUnit(
168
164
  applyFormula(formula, {
165
+ ...formulaCtx,
169
166
  data,
170
- component: ctx.component,
171
- formulaCache: ctx.formulaCache,
172
- root: ctx.root,
173
- package: ctx.package,
174
- toddle: ctx.toddle,
175
- env: ctx.env,
176
167
  }),
177
168
  unit,
178
169
  ),
179
170
  ),
180
171
  root: ctx.root,
181
- runtime: ctx.env.runtime,
182
- }),
183
- )
172
+ })
173
+ })
184
174
 
185
175
  node.variants?.forEach((variant) => {
186
- Object.entries(variant.customProperties ?? {}).forEach(
187
- ([customPropertyName, { formula, unit }]) => {
176
+ Object.entries(variant.customProperties ?? {})
177
+ .filter(([_, { formula }]) => formulaHasValue(formula))
178
+ .forEach(([customPropertyName, { formula, unit }]) => {
188
179
  subscribeCustomProperty({
189
180
  customPropertyName,
190
181
  selector: getNodeSelector(path, {
@@ -194,22 +185,15 @@ export function createElement({
194
185
  signal: dataSignal.map((data) =>
195
186
  appendUnit(
196
187
  applyFormula(formula, {
188
+ ...formulaCtx,
197
189
  data,
198
- component: ctx.component,
199
- formulaCache: ctx.formulaCache,
200
- root: ctx.root,
201
- package: ctx.package,
202
- toddle: ctx.toddle,
203
- env: ctx.env,
204
190
  }),
205
191
  unit,
206
192
  ),
207
193
  ),
208
194
  root: ctx.root,
209
- runtime: ctx.env.runtime,
210
195
  })
211
- },
212
- )
196
+ })
213
197
  })
214
198
 
215
199
  const eventHandlers: [string, (e: Event) => boolean][] = []
@@ -243,13 +227,8 @@ export function createElement({
243
227
  const textSignal = dataSignal.map((data) => {
244
228
  return String(
245
229
  applyFormula(node.value, {
230
+ ...formulaCtx,
246
231
  data,
247
- component: ctx.component,
248
- formulaCache: ctx.formulaCache,
249
- root: ctx.root,
250
- package: ctx.package,
251
- toddle: ctx.toddle,
252
- env: ctx.env,
253
232
  }),
254
233
  )
255
234
  })