@nordcraft/runtime 1.0.95 → 1.0.97
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/dist/api/createAPI.js +29 -11
- package/dist/api/createAPI.js.map +1 -1
- package/dist/api/createAPIv2.js +49 -11
- package/dist/api/createAPIv2.js.map +1 -1
- package/dist/components/createComponent.js +19 -10
- package/dist/components/createComponent.js.map +1 -1
- package/dist/components/createElement.js +48 -16
- package/dist/components/createElement.js.map +1 -1
- package/dist/components/createNode.js +22 -11
- package/dist/components/createNode.js.map +1 -1
- package/dist/components/createNode.test.js +3 -3
- package/dist/components/createNode.test.js.map +1 -1
- package/dist/components/createSlot.js +2 -1
- package/dist/components/createSlot.js.map +1 -1
- package/dist/components/createText.js +7 -2
- package/dist/components/createText.js.map +1 -1
- package/dist/components/renderComponent.d.ts +4 -1
- package/dist/components/renderComponent.js +4 -2
- package/dist/components/renderComponent.js.map +1 -1
- package/dist/context/subscribeToContext.js +12 -2
- package/dist/context/subscribeToContext.js.map +1 -1
- package/dist/custom-element/ToddleComponent.js +12 -4
- package/dist/custom-element/ToddleComponent.js.map +1 -1
- package/dist/custom-element.main.esm.js +29 -29
- package/dist/custom-element.main.esm.js.map +4 -4
- package/dist/editor/editorUtils.d.ts +2 -0
- package/dist/editor/editorUtils.js +26 -0
- package/dist/editor/editorUtils.js.map +1 -0
- package/dist/editor/types.d.ts +4 -0
- package/dist/editor/types.js.map +1 -1
- package/dist/editor-preview.main.js +82 -18
- package/dist/editor-preview.main.js.map +1 -1
- package/dist/events/handleAction.js +74 -42
- package/dist/events/handleAction.js.map +1 -1
- package/dist/page.main.esm.js +3 -3
- package/dist/page.main.esm.js.map +4 -4
- package/dist/page.main.js +39 -8
- package/dist/page.main.js.map +1 -1
- package/dist/utils/createFormulaCache.js.map +1 -1
- package/dist/utils/nodes.d.ts +1 -0
- package/dist/utils/nodes.js +9 -0
- package/dist/utils/nodes.js.map +1 -1
- package/dist/utils/nodes.test.d.ts +1 -0
- package/dist/utils/nodes.test.js +192 -0
- package/dist/utils/nodes.test.js.map +1 -0
- package/dist/utils/subscribeCustomProperty.d.ts +1 -1
- package/dist/utils/subscribeCustomProperty.js +8 -4
- package/dist/utils/subscribeCustomProperty.js.map +1 -1
- package/dist/utils/subscribeCustomProperty.test.d.ts +1 -0
- package/dist/utils/subscribeCustomProperty.test.js +63 -0
- package/dist/utils/subscribeCustomProperty.test.js.map +1 -0
- package/package.json +3 -3
- package/src/api/createAPI.ts +90 -46
- package/src/api/createAPIv2.ts +79 -13
- package/src/components/createComponent.ts +123 -85
- package/src/components/createElement.ts +63 -27
- package/src/components/createNode.test.ts +3 -3
- package/src/components/createNode.ts +55 -31
- package/src/components/createSlot.ts +2 -1
- package/src/components/createText.ts +35 -18
- package/src/components/renderComponent.ts +8 -1
- package/src/context/subscribeToContext.ts +12 -2
- package/src/custom-element/ToddleComponent.ts +37 -22
- package/src/editor/editorUtils.ts +28 -0
- package/src/editor/types.ts +5 -0
- package/src/editor-preview.main.ts +137 -46
- package/src/events/handleAction.ts +190 -113
- package/src/page.main.ts +64 -26
- package/src/types.d.ts +3 -0
- package/src/utils/createFormulaCache.ts +2 -2
- package/src/utils/nodes.test.ts +246 -0
- package/src/utils/nodes.ts +11 -0
- package/src/utils/subscribeCustomProperty.test.ts +78 -0
- package/src/utils/subscribeCustomProperty.ts +21 -22
|
@@ -60,6 +60,7 @@ export function createElement({
|
|
|
60
60
|
package: ctx.package,
|
|
61
61
|
toddle: ctx.toddle,
|
|
62
62
|
env: ctx.env,
|
|
63
|
+
reportFormulaEvaluation: ctx.reportFormulaEvaluation,
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
elem.setAttribute('data-node-id', id)
|
|
@@ -107,12 +108,19 @@ export function createElement({
|
|
|
107
108
|
if (value.type === 'value') {
|
|
108
109
|
setAttribute(elem, attr, value?.value)
|
|
109
110
|
} else {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
111
|
+
const attrPath = ['nodes', id, 'attrs', attr]
|
|
112
|
+
o = dataSignal.map((data) => {
|
|
113
|
+
const val = applyFormula(
|
|
114
|
+
value,
|
|
115
|
+
{
|
|
116
|
+
...formulaCtx,
|
|
117
|
+
data,
|
|
118
|
+
},
|
|
119
|
+
attrPath,
|
|
120
|
+
)
|
|
121
|
+
ctx.reportFormulaEvaluation?.(attrPath, val, ctx)
|
|
122
|
+
return val
|
|
123
|
+
})
|
|
116
124
|
o.subscribe((val) => {
|
|
117
125
|
setAttribute(elem, attr, val)
|
|
118
126
|
})
|
|
@@ -135,13 +143,19 @@ export function createElement({
|
|
|
135
143
|
setupAttribute()
|
|
136
144
|
}
|
|
137
145
|
})
|
|
138
|
-
node['style-variables']?.forEach((styleVariable) => {
|
|
146
|
+
node['style-variables']?.forEach((styleVariable, i) => {
|
|
139
147
|
const { name, formula, unit } = styleVariable
|
|
148
|
+
const styleVarPath = ['nodes', id, 'style-variables', i, 'formula']
|
|
140
149
|
const signal = dataSignal.map((data) => {
|
|
141
|
-
const value = applyFormula(
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
150
|
+
const value = applyFormula(
|
|
151
|
+
formula,
|
|
152
|
+
{
|
|
153
|
+
...formulaCtx,
|
|
154
|
+
data,
|
|
155
|
+
},
|
|
156
|
+
styleVarPath,
|
|
157
|
+
)
|
|
158
|
+
ctx.reportFormulaEvaluation?.(styleVarPath, value, ctx)
|
|
145
159
|
return unit ? value + unit : value
|
|
146
160
|
})
|
|
147
161
|
|
|
@@ -151,6 +165,13 @@ export function createElement({
|
|
|
151
165
|
Object.entries(node.customProperties ?? {})
|
|
152
166
|
.filter(([_, { formula }]) => formulaHasValue(formula))
|
|
153
167
|
.forEach(([customPropertyName, { formula, unit }]) => {
|
|
168
|
+
const cpPath = [
|
|
169
|
+
'nodes',
|
|
170
|
+
id,
|
|
171
|
+
'customProperties',
|
|
172
|
+
customPropertyName,
|
|
173
|
+
'formula',
|
|
174
|
+
]
|
|
154
175
|
subscribeCustomProperty({
|
|
155
176
|
customPropertyName,
|
|
156
177
|
selector:
|
|
@@ -159,38 +180,53 @@ export function createElement({
|
|
|
159
180
|
path === '0'
|
|
160
181
|
? `${getNodeSelector(path)}, :host`
|
|
161
182
|
: getNodeSelector(path),
|
|
162
|
-
signal: dataSignal.map((data) =>
|
|
163
|
-
|
|
164
|
-
|
|
183
|
+
signal: dataSignal.map((data) => {
|
|
184
|
+
const val = applyFormula(
|
|
185
|
+
formula,
|
|
186
|
+
{
|
|
165
187
|
...formulaCtx,
|
|
166
188
|
data,
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
)
|
|
170
|
-
|
|
189
|
+
},
|
|
190
|
+
cpPath,
|
|
191
|
+
)
|
|
192
|
+
ctx.reportFormulaEvaluation?.(cpPath, val, ctx)
|
|
193
|
+
return appendUnit(val, unit)
|
|
194
|
+
}),
|
|
171
195
|
root: ctx.root,
|
|
172
196
|
})
|
|
173
197
|
})
|
|
174
198
|
|
|
175
|
-
node.variants?.forEach((variant) => {
|
|
199
|
+
node.variants?.forEach((variant, variantIndex) => {
|
|
176
200
|
Object.entries(variant.customProperties ?? {})
|
|
177
201
|
.filter(([_, { formula }]) => formulaHasValue(formula))
|
|
178
202
|
.forEach(([customPropertyName, { formula, unit }]) => {
|
|
203
|
+
const variantCpPath = [
|
|
204
|
+
'nodes',
|
|
205
|
+
id,
|
|
206
|
+
'variants',
|
|
207
|
+
variantIndex,
|
|
208
|
+
'customProperties',
|
|
209
|
+
customPropertyName,
|
|
210
|
+
'formula',
|
|
211
|
+
]
|
|
179
212
|
subscribeCustomProperty({
|
|
180
213
|
customPropertyName,
|
|
181
214
|
selector: getNodeSelector(path, {
|
|
182
215
|
variant,
|
|
183
216
|
}),
|
|
184
217
|
variant,
|
|
185
|
-
signal: dataSignal.map((data) =>
|
|
186
|
-
|
|
187
|
-
|
|
218
|
+
signal: dataSignal.map((data) => {
|
|
219
|
+
const val = applyFormula(
|
|
220
|
+
formula,
|
|
221
|
+
{
|
|
188
222
|
...formulaCtx,
|
|
189
223
|
data,
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
)
|
|
193
|
-
|
|
224
|
+
},
|
|
225
|
+
variantCpPath,
|
|
226
|
+
)
|
|
227
|
+
ctx.reportFormulaEvaluation?.(variantCpPath, val, ctx)
|
|
228
|
+
return appendUnit(val, unit)
|
|
229
|
+
}),
|
|
194
230
|
root: ctx.root,
|
|
195
231
|
})
|
|
196
232
|
})
|
|
@@ -260,7 +296,7 @@ export function createElement({
|
|
|
260
296
|
id: child,
|
|
261
297
|
path: path + '.' + i,
|
|
262
298
|
dataSignal,
|
|
263
|
-
ctx,
|
|
299
|
+
ctx: { ...ctx, jsonPath: ['nodes', child] },
|
|
264
300
|
namespace,
|
|
265
301
|
instance,
|
|
266
302
|
}),
|
|
@@ -4,7 +4,7 @@ import { describe, expect, test } from 'bun:test'
|
|
|
4
4
|
import '../happydom'
|
|
5
5
|
import { signal } from '../signal/signal'
|
|
6
6
|
import type { ComponentContext } from '../types'
|
|
7
|
-
import {
|
|
7
|
+
import { customPropertiesStylesheets } from '../utils/subscribeCustomProperty'
|
|
8
8
|
import { createNode } from './createNode'
|
|
9
9
|
|
|
10
10
|
describe('createNode()', () => {
|
|
@@ -114,7 +114,7 @@ describe('createNode()', () => {
|
|
|
114
114
|
})
|
|
115
115
|
|
|
116
116
|
// Custom properties stylesheet should be created and have the custom property from the node
|
|
117
|
-
const sheet =
|
|
117
|
+
const sheet = customPropertiesStylesheets.get(document)?.getStyleSheet()
|
|
118
118
|
expect(sheet).toBeTruthy()
|
|
119
119
|
expect(sheet?.cssRules.length).toBe(3)
|
|
120
120
|
expect(sheet?.cssRules[0].cssText).toBe(
|
|
@@ -675,7 +675,7 @@ describe('createNode()', () => {
|
|
|
675
675
|
instance: {},
|
|
676
676
|
})
|
|
677
677
|
|
|
678
|
-
const sheet =
|
|
678
|
+
const sheet = customPropertiesStylesheets.get(ctx.root)?.getStyleSheet()
|
|
679
679
|
// Test that the order makes sense
|
|
680
680
|
expect(Array.from(sheet?.cssRules ?? []).map((r) => r.cssText)).toEqual([
|
|
681
681
|
`[data-id="0"] { --color: ${innermostColor}; }`,
|
|
@@ -63,6 +63,9 @@ export function createNode({
|
|
|
63
63
|
...ctx,
|
|
64
64
|
package:
|
|
65
65
|
node.package ?? (isLocalComponent ? undefined : ctx.package),
|
|
66
|
+
// Skip sub-component formula evaluation for now as editor only needs the scope for the selected component
|
|
67
|
+
// TODO: Letting the AI get the state of a deep component may be useful in the future, but we need a better way at precising scope for it to not overwhelm it.
|
|
68
|
+
reportFormulaEvaluation: undefined,
|
|
66
69
|
},
|
|
67
70
|
parentElement,
|
|
68
71
|
})
|
|
@@ -86,19 +89,28 @@ export function createNode({
|
|
|
86
89
|
}: NodeRenderer<NodeModel>): ReadonlyArray<Element | Text> {
|
|
87
90
|
let firstRun = true
|
|
88
91
|
let childDataSignal: Signal<ComponentData> | null = null
|
|
89
|
-
const showSignal = dataSignal.map((data) =>
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
92
|
+
const showSignal = dataSignal.map((data) => {
|
|
93
|
+
const conditionPath = ['nodes', id, 'condition']
|
|
94
|
+
const show = toBoolean(
|
|
95
|
+
applyFormula(
|
|
96
|
+
node.condition,
|
|
97
|
+
{
|
|
98
|
+
data,
|
|
99
|
+
component: ctx.component,
|
|
100
|
+
formulaCache: ctx.formulaCache,
|
|
101
|
+
root: ctx.root,
|
|
102
|
+
package: ctx.package,
|
|
103
|
+
toddle: ctx.toddle,
|
|
104
|
+
env: ctx.env,
|
|
105
|
+
jsonPath: ctx.jsonPath,
|
|
106
|
+
reportFormulaEvaluation: ctx.reportFormulaEvaluation,
|
|
107
|
+
},
|
|
108
|
+
conditionPath,
|
|
109
|
+
),
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
return show
|
|
113
|
+
})
|
|
102
114
|
|
|
103
115
|
const elements: Array<Element | Text> = []
|
|
104
116
|
const toggle = (show: boolean) => {
|
|
@@ -182,15 +194,21 @@ export function createNode({
|
|
|
182
194
|
}
|
|
183
195
|
>()
|
|
184
196
|
const repeatSignal = dataSignal.map((data) => {
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
197
|
+
const listPath = ['nodes', id, 'repeat']
|
|
198
|
+
const list = applyFormula(
|
|
199
|
+
node?.repeat,
|
|
200
|
+
{
|
|
201
|
+
data,
|
|
202
|
+
component: ctx.component,
|
|
203
|
+
formulaCache: ctx.formulaCache,
|
|
204
|
+
root: ctx.root,
|
|
205
|
+
package: ctx.package,
|
|
206
|
+
toddle: ctx.toddle,
|
|
207
|
+
env: ctx.env,
|
|
208
|
+
},
|
|
209
|
+
listPath,
|
|
210
|
+
)
|
|
211
|
+
|
|
194
212
|
if (typeof list !== 'object') {
|
|
195
213
|
return []
|
|
196
214
|
}
|
|
@@ -216,16 +234,21 @@ export function createNode({
|
|
|
216
234
|
Key,
|
|
217
235
|
},
|
|
218
236
|
}
|
|
237
|
+
const repeatKeyPath = ['nodes', id, 'repeatKey']
|
|
219
238
|
let childKey = node?.repeatKey
|
|
220
|
-
? applyFormula(
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
239
|
+
? applyFormula(
|
|
240
|
+
node.repeatKey,
|
|
241
|
+
{
|
|
242
|
+
data: childData,
|
|
243
|
+
component: ctx.component,
|
|
244
|
+
formulaCache: ctx.formulaCache,
|
|
245
|
+
root: ctx.root,
|
|
246
|
+
package: ctx.package,
|
|
247
|
+
toddle: ctx.toddle,
|
|
248
|
+
env: ctx.env,
|
|
249
|
+
},
|
|
250
|
+
repeatKeyPath,
|
|
251
|
+
)
|
|
229
252
|
: Key
|
|
230
253
|
|
|
231
254
|
if (seenKeys.has(childKey)) {
|
|
@@ -380,6 +403,7 @@ export function createNode({
|
|
|
380
403
|
instance,
|
|
381
404
|
})
|
|
382
405
|
}
|
|
406
|
+
|
|
383
407
|
export type NodeRenderer<NodeType> = {
|
|
384
408
|
node: NodeType
|
|
385
409
|
dataSignal: Signal<ComponentData>
|
|
@@ -37,6 +37,7 @@ export function createSlot({
|
|
|
37
37
|
ctx: {
|
|
38
38
|
...child.ctx,
|
|
39
39
|
providers: ctx.providers,
|
|
40
|
+
jsonPath: ['nodes', child.id],
|
|
40
41
|
},
|
|
41
42
|
instance,
|
|
42
43
|
namespace,
|
|
@@ -53,7 +54,7 @@ export function createSlot({
|
|
|
53
54
|
id: child,
|
|
54
55
|
path: path + '.' + i,
|
|
55
56
|
dataSignal,
|
|
56
|
-
ctx,
|
|
57
|
+
ctx: { ...ctx, jsonPath: ['nodes', child] },
|
|
57
58
|
parentElement,
|
|
58
59
|
instance,
|
|
59
60
|
namespace,
|
|
@@ -48,21 +48,32 @@ export function createText({
|
|
|
48
48
|
if (value.type !== 'value') {
|
|
49
49
|
const sig = dataSignal.map((data) =>
|
|
50
50
|
String(
|
|
51
|
-
applyFormula(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
51
|
+
applyFormula(
|
|
52
|
+
value,
|
|
53
|
+
{
|
|
54
|
+
data,
|
|
55
|
+
component: ctx.component,
|
|
56
|
+
formulaCache: ctx.formulaCache,
|
|
57
|
+
root: ctx.root,
|
|
58
|
+
package: ctx.package,
|
|
59
|
+
toddle: ctx.toddle,
|
|
60
|
+
env: ctx.env,
|
|
61
|
+
jsonPath: ctx.jsonPath,
|
|
62
|
+
reportFormulaEvaluation: ctx.reportFormulaEvaluation,
|
|
63
|
+
},
|
|
64
|
+
['value'],
|
|
65
|
+
),
|
|
60
66
|
),
|
|
61
67
|
)
|
|
62
68
|
sig.subscribe((value) => {
|
|
63
69
|
elem.innerText = value
|
|
64
70
|
})
|
|
65
71
|
} else {
|
|
72
|
+
ctx.reportFormulaEvaluation?.(
|
|
73
|
+
[...(ctx.jsonPath ?? []), 'value'],
|
|
74
|
+
value.value,
|
|
75
|
+
ctx,
|
|
76
|
+
)
|
|
66
77
|
elem.innerText = String(value.value)
|
|
67
78
|
}
|
|
68
79
|
return elem
|
|
@@ -82,15 +93,21 @@ export function createTextNS({
|
|
|
82
93
|
if (value.type !== 'value') {
|
|
83
94
|
const sig = dataSignal.map((data) =>
|
|
84
95
|
String(
|
|
85
|
-
applyFormula(
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
96
|
+
applyFormula(
|
|
97
|
+
value,
|
|
98
|
+
{
|
|
99
|
+
data,
|
|
100
|
+
component: ctx.component,
|
|
101
|
+
formulaCache: ctx.formulaCache,
|
|
102
|
+
root: ctx.root,
|
|
103
|
+
package: ctx.package,
|
|
104
|
+
toddle: ctx.toddle,
|
|
105
|
+
env: ctx.env,
|
|
106
|
+
jsonPath: ctx.jsonPath,
|
|
107
|
+
reportFormulaEvaluation: ctx.reportFormulaEvaluation,
|
|
108
|
+
},
|
|
109
|
+
['value'],
|
|
110
|
+
),
|
|
94
111
|
),
|
|
95
112
|
)
|
|
96
113
|
sig.subscribe((value) => {
|
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
SupportedNamespaces,
|
|
5
5
|
} from '@nordcraft/core/dist/component/component.types'
|
|
6
6
|
import type { ToddleEnv } from '@nordcraft/core/dist/formula/formula'
|
|
7
|
+
import type { FormulaEvaluationReporter } from '@nordcraft/core/dist/formula/formulaTypes'
|
|
7
8
|
import type { Toddle } from '@nordcraft/core/dist/types'
|
|
8
9
|
import { measure } from '@nordcraft/core/dist/utils/measure'
|
|
9
10
|
import fastDeepEqual from 'fast-deep-equal'
|
|
@@ -49,6 +50,8 @@ interface RenderComponentProps {
|
|
|
49
50
|
toddle: Toddle<LocationSignal, PreviewShowSignal>
|
|
50
51
|
namespace?: SupportedNamespaces
|
|
51
52
|
env: ToddleEnv
|
|
53
|
+
jsonPath: Array<string | number> | undefined
|
|
54
|
+
reportFormulaEvaluation?: FormulaEvaluationReporter
|
|
52
55
|
}
|
|
53
56
|
|
|
54
57
|
const BATCH_QUEUE = new BatchQueue()
|
|
@@ -73,6 +76,8 @@ export function renderComponent({
|
|
|
73
76
|
toddle,
|
|
74
77
|
namespace,
|
|
75
78
|
env,
|
|
79
|
+
jsonPath,
|
|
80
|
+
reportFormulaEvaluation,
|
|
76
81
|
}: RenderComponentProps): ReadonlyArray<Element | Text> {
|
|
77
82
|
const stopMeasure = measure(`Render component: ${component.name}`, {
|
|
78
83
|
component: component.name,
|
|
@@ -94,13 +99,15 @@ export function renderComponent({
|
|
|
94
99
|
package: packageName,
|
|
95
100
|
toddle,
|
|
96
101
|
env,
|
|
102
|
+
jsonPath,
|
|
103
|
+
reportFormulaEvaluation,
|
|
97
104
|
}
|
|
98
105
|
|
|
99
106
|
const rootElem = createNode({
|
|
100
107
|
id: 'root',
|
|
101
108
|
path,
|
|
102
109
|
dataSignal,
|
|
103
|
-
ctx,
|
|
110
|
+
ctx: { ...ctx, jsonPath: ['nodes', 'root'] },
|
|
104
111
|
parentElement,
|
|
105
112
|
namespace,
|
|
106
113
|
instance,
|
|
@@ -83,6 +83,8 @@ export function subscribeToContext(
|
|
|
83
83
|
package: testProviderPackage ?? ctx?.package,
|
|
84
84
|
toddle: ctx.toddle,
|
|
85
85
|
env: ctx.env,
|
|
86
|
+
jsonPath: ctx.jsonPath,
|
|
87
|
+
reportFormulaEvaluation: ctx.reportFormulaEvaluation,
|
|
86
88
|
}
|
|
87
89
|
|
|
88
90
|
if (testProvider.route) {
|
|
@@ -102,7 +104,11 @@ export function subscribeToContext(
|
|
|
102
104
|
testProvider.variables ?? {},
|
|
103
105
|
([name, variable]) => [
|
|
104
106
|
name,
|
|
105
|
-
applyFormula(variable.initialValue,
|
|
107
|
+
applyFormula(variable.initialValue, {
|
|
108
|
+
...formulaContext,
|
|
109
|
+
// We should not report formula evaluations for test data on context providers
|
|
110
|
+
reportFormulaEvaluation: undefined,
|
|
111
|
+
}),
|
|
106
112
|
],
|
|
107
113
|
)
|
|
108
114
|
|
|
@@ -123,7 +129,11 @@ export function subscribeToContext(
|
|
|
123
129
|
|
|
124
130
|
return [
|
|
125
131
|
formulaName,
|
|
126
|
-
applyFormula(formula.formula,
|
|
132
|
+
applyFormula(formula.formula, {
|
|
133
|
+
...formulaContext,
|
|
134
|
+
// We should not report formula evaluations for test data on context providers
|
|
135
|
+
reportFormulaEvaluation: undefined,
|
|
136
|
+
}),
|
|
127
137
|
]
|
|
128
138
|
}),
|
|
129
139
|
),
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
import type { Toddle } from '@nordcraft/core/dist/types'
|
|
15
15
|
import { mapObject } from '@nordcraft/core/dist/utils/collections'
|
|
16
16
|
import { isDefined } from '@nordcraft/core/dist/utils/util'
|
|
17
|
+
import type { ComponentAPI } from '@nordcraft/core/src/api/apiTypes'
|
|
17
18
|
import { isContextApiV2 } from '../api/apiUtils'
|
|
18
19
|
import { createLegacyAPI } from '../api/createAPI'
|
|
19
20
|
import { createAPI } from '../api/createAPIv2'
|
|
@@ -97,23 +98,32 @@ export class ToddleComponent extends HTMLElement {
|
|
|
97
98
|
package: undefined,
|
|
98
99
|
toddle,
|
|
99
100
|
env,
|
|
101
|
+
jsonPath: [],
|
|
100
102
|
}
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
connectedCallback() {
|
|
104
|
-
sortApiObjects(
|
|
105
|
-
(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
106
|
+
sortApiObjects(
|
|
107
|
+
Object.entries(this.#component.apis ?? {}).filter(
|
|
108
|
+
(entry): entry is [string, ComponentAPI] => isDefined(entry[1]),
|
|
109
|
+
),
|
|
110
|
+
).forEach(([name, api]) => {
|
|
111
|
+
if (isLegacyApi(api)) {
|
|
112
|
+
this.#ctx.apis[name] = createLegacyAPI(api, {
|
|
113
|
+
...this.#ctx,
|
|
114
|
+
jsonPath: ['apis', name],
|
|
115
|
+
})
|
|
116
|
+
} else {
|
|
117
|
+
this.#ctx.apis[name] = createAPI({
|
|
118
|
+
apiRequest: api,
|
|
119
|
+
ctx: {
|
|
120
|
+
...this.#ctx,
|
|
121
|
+
jsonPath: ['apis', name],
|
|
122
|
+
},
|
|
123
|
+
componentData: this.#signal.get(),
|
|
124
|
+
})
|
|
125
|
+
}
|
|
126
|
+
})
|
|
117
127
|
Object.values(this.#ctx.apis)
|
|
118
128
|
.filter(isContextApiV2)
|
|
119
129
|
.forEach((api) => {
|
|
@@ -129,15 +139,20 @@ export class ToddleComponent extends HTMLElement {
|
|
|
129
139
|
.map(([name, formula]) => [
|
|
130
140
|
name,
|
|
131
141
|
this.#signal.map((data) =>
|
|
132
|
-
applyFormula(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
142
|
+
applyFormula(
|
|
143
|
+
formula.formula,
|
|
144
|
+
{
|
|
145
|
+
data,
|
|
146
|
+
component: this.#component,
|
|
147
|
+
formulaCache: this.#ctx.formulaCache,
|
|
148
|
+
root: this.#ctx.root,
|
|
149
|
+
package: this.#ctx.package,
|
|
150
|
+
toddle: this.#ctx.toddle,
|
|
151
|
+
env: this.#ctx.env,
|
|
152
|
+
jsonPath: [],
|
|
153
|
+
},
|
|
154
|
+
['formulas', name],
|
|
155
|
+
),
|
|
141
156
|
),
|
|
142
157
|
]),
|
|
143
158
|
)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export const debounce = (func: () => void, wait: number, immediate = false) => {
|
|
2
|
+
let timeout: ReturnType<typeof setTimeout> | undefined = undefined
|
|
3
|
+
return () => {
|
|
4
|
+
const callNow = immediate && !timeout
|
|
5
|
+
clearTimeout(timeout)
|
|
6
|
+
timeout = setTimeout(() => {
|
|
7
|
+
func()
|
|
8
|
+
}, wait)
|
|
9
|
+
if (callNow) {
|
|
10
|
+
func()
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const throttleToIdleCallback = (func: () => void) => {
|
|
16
|
+
let scheduled = false
|
|
17
|
+
return () => {
|
|
18
|
+
if (!scheduled) {
|
|
19
|
+
scheduled = true
|
|
20
|
+
;(globalThis.requestIdleCallback ?? globalThis.requestAnimationFrame)(
|
|
21
|
+
() => {
|
|
22
|
+
func()
|
|
23
|
+
scheduled = false
|
|
24
|
+
},
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
package/src/editor/types.ts
CHANGED
|
@@ -189,6 +189,11 @@ export type EditorPostMessageType =
|
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
191
|
| { type: 'data'; data: ComponentData }
|
|
192
|
+
| {
|
|
193
|
+
type: 'componentFormulaData'
|
|
194
|
+
data: Record<string, any>
|
|
195
|
+
component?: string
|
|
196
|
+
}
|
|
192
197
|
| {
|
|
193
198
|
type: 'selectionRect'
|
|
194
199
|
rect: ReturnType<typeof getRectData>
|