@nordcraft/core 1.0.93 → 1.0.95

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 (47) hide show
  1. package/dist/api/LegacyToddleApi.js +2 -2
  2. package/dist/api/LegacyToddleApi.js.map +1 -1
  3. package/dist/api/ToddleApiV2.js +2 -2
  4. package/dist/api/ToddleApiV2.js.map +1 -1
  5. package/dist/api/api.js.map +1 -1
  6. package/dist/api/apiTypes.js +1 -2
  7. package/dist/api/apiTypes.js.map +1 -1
  8. package/dist/api/headers.js.map +1 -1
  9. package/dist/api/template.js.map +1 -1
  10. package/dist/component/ToddleComponent.js +6 -0
  11. package/dist/component/ToddleComponent.js.map +1 -1
  12. package/dist/component/actionUtils.js.map +1 -1
  13. package/dist/component/component.types.js +1 -2
  14. package/dist/component/component.types.js.map +1 -1
  15. package/dist/component/schemas/formula-schema.js.map +1 -1
  16. package/dist/formula/ToddleFormula.js.map +1 -1
  17. package/dist/formula/formula.d.ts +11 -11
  18. package/dist/formula/formula.js +24 -7
  19. package/dist/formula/formula.js.map +1 -1
  20. package/dist/formula/formulaUtils.js +2 -2
  21. package/dist/formula/formulaUtils.js.map +1 -1
  22. package/dist/styling/className.js.map +1 -1
  23. package/dist/styling/customProperty.js +3 -3
  24. package/dist/styling/customProperty.js.map +1 -1
  25. package/dist/styling/hash.js.map +1 -1
  26. package/dist/styling/style.css.js.map +1 -1
  27. package/dist/styling/theme.js.map +1 -1
  28. package/dist/utils/collections.js.map +1 -1
  29. package/dist/utils/customElements.js.map +1 -1
  30. package/dist/utils/getNodeSelector.js.map +1 -1
  31. package/dist/utils/handlerUtils.js.map +1 -1
  32. package/dist/utils/hash.js.map +1 -1
  33. package/dist/utils/json.js.map +1 -1
  34. package/dist/utils/measure.d.ts +1 -0
  35. package/dist/utils/measure.js +54 -0
  36. package/dist/utils/measure.js.map +1 -0
  37. package/dist/utils/sha1.js.map +1 -1
  38. package/dist/utils/url.js.map +1 -1
  39. package/package.json +1 -1
  40. package/src/api/LegacyToddleApi.ts +2 -2
  41. package/src/api/ToddleApiV2.ts +2 -2
  42. package/src/component/ToddleComponent.formulasInComponent.test.ts +48 -6
  43. package/src/component/ToddleComponent.ts +6 -0
  44. package/src/formula/formula.ts +36 -17
  45. package/src/formula/formulaUtils.ts +2 -2
  46. package/src/styling/customProperty.ts +3 -3
  47. package/src/utils/measure.ts +59 -0
@@ -9,6 +9,7 @@ import type {
9
9
  Runtime,
10
10
  Toddle,
11
11
  } from '../types'
12
+ import { measure } from '../utils/measure'
12
13
  import { isDefined, toBoolean } from '../utils/util'
13
14
  import { type PluginFormula, type ToddleFormula } from './formulaTypes'
14
15
 
@@ -38,13 +39,13 @@ export interface FunctionOperation extends BaseOperation {
38
39
  name: string
39
40
  display_name?: Nullable<string>
40
41
  package?: Nullable<string>
41
- arguments: FunctionArgument[]
42
+ arguments?: Nullable<FunctionArgument[]>
42
43
  variableArguments?: Nullable<boolean>
43
44
  }
44
45
 
45
46
  export interface RecordOperation extends BaseOperation {
46
47
  type: 'record'
47
- entries: FunctionArgument[]
48
+ entries?: Nullable<FunctionArgument[]>
48
49
  }
49
50
 
50
51
  export interface ObjectOperation extends BaseOperation {
@@ -54,23 +55,23 @@ export interface ObjectOperation extends BaseOperation {
54
55
 
55
56
  export interface ArrayOperation extends BaseOperation {
56
57
  type: 'array'
57
- arguments: Array<{ formula: Formula }>
58
+ arguments?: Nullable<Array<{ formula: Formula }>>
58
59
  }
59
60
 
60
61
  export interface OrOperation extends BaseOperation {
61
62
  type: 'or'
62
- arguments: Array<{ formula: Formula }>
63
+ arguments?: Nullable<Array<{ formula: Formula }>>
63
64
  }
64
65
 
65
66
  export interface AndOperation extends BaseOperation {
66
67
  type: 'and'
67
- arguments: Array<{ formula: Formula }>
68
+ arguments?: Nullable<Array<{ formula: Formula }>>
68
69
  }
69
70
 
70
71
  export interface ApplyOperation extends BaseOperation {
71
72
  type: 'apply'
72
73
  name: string
73
- arguments: FunctionArgument[]
74
+ arguments?: Nullable<FunctionArgument[]>
74
75
  }
75
76
 
76
77
  export interface ValueOperation extends BaseOperation {
@@ -82,10 +83,12 @@ export type ValueOperationValue = string | number | boolean | null | object
82
83
 
83
84
  export interface SwitchOperation extends BaseOperation {
84
85
  type: 'switch'
85
- cases: Array<{
86
- condition: Formula
87
- formula: Formula
88
- }>
86
+ cases?: Nullable<
87
+ Array<{
88
+ condition: Formula
89
+ formula: Formula
90
+ }>
91
+ >
89
92
  default: Formula
90
93
  }
91
94
 
@@ -204,7 +207,7 @@ export function applyFormula(
204
207
  return input
205
208
  }
206
209
  case 'switch': {
207
- for (const branch of formula.cases) {
210
+ for (const branch of formula.cases ?? []) {
208
211
  if (toBoolean(applyFormula(branch.condition, ctx))) {
209
212
  return applyFormula(branch.formula, ctx)
210
213
  }
@@ -212,7 +215,7 @@ export function applyFormula(
212
215
  return applyFormula(formula.default, ctx)
213
216
  }
214
217
  case 'or': {
215
- for (const entry of formula.arguments) {
218
+ for (const entry of formula.arguments ?? []) {
216
219
  if (toBoolean(applyFormula(entry.formula, ctx))) {
217
220
  return true
218
221
  }
@@ -220,7 +223,7 @@ export function applyFormula(
220
223
  return false
221
224
  }
222
225
  case 'and': {
223
- for (const entry of formula.arguments) {
226
+ for (const entry of formula.arguments ?? []) {
224
227
  if (!toBoolean(applyFormula(entry.formula, ctx))) {
225
228
  return false
226
229
  }
@@ -228,6 +231,10 @@ export function applyFormula(
228
231
  return true
229
232
  }
230
233
  case 'function': {
234
+ const stopMeasure = measure(`Formula: ${formula.name}`, {
235
+ formula,
236
+ component: ctx.component?.name,
237
+ })
231
238
  const packageName = formula.package ?? ctx.package ?? undefined
232
239
  const newFunc = (
233
240
  ctx.toddle ??
@@ -235,7 +242,9 @@ export function applyFormula(
235
242
  )?.getCustomFormula(formula.name, packageName)
236
243
  if (isDefined(newFunc)) {
237
244
  ctx.package = packageName
238
- const args = formula.arguments.reduce<Record<string, unknown>>(
245
+ const args = (formula.arguments ?? []).reduce<
246
+ Record<string, unknown>
247
+ >(
239
248
  (args, arg, i) => ({
240
249
  ...args,
241
250
  [arg.name ?? `${i}`]: arg.isFunction
@@ -271,6 +280,8 @@ export function applyFormula(
271
280
  console.error(e)
272
281
  }
273
282
  return null
283
+ } finally {
284
+ stopMeasure()
274
285
  }
275
286
  } else {
276
287
  // Lookup legacy formula
@@ -301,6 +312,8 @@ export function applyFormula(
301
312
  console.error(e)
302
313
  }
303
314
  return null
315
+ } finally {
316
+ stopMeasure()
304
317
  }
305
318
  }
306
319
  }
@@ -323,13 +336,13 @@ export function applyFormula(
323
336
  )
324
337
  case 'record': // object used to be called record, there are still examples in the wild.
325
338
  return Object.fromEntries(
326
- formula.entries.map((entry) => [
339
+ (formula.entries ?? []).map((entry) => [
327
340
  entry.name,
328
341
  applyFormula(entry.formula, ctx),
329
342
  ]),
330
343
  )
331
344
  case 'array':
332
- return formula.arguments.map((entry) =>
345
+ return (formula.arguments ?? []).map((entry) =>
333
346
  applyFormula(entry.formula, ctx),
334
347
  )
335
348
  case 'apply': {
@@ -343,8 +356,12 @@ export function applyFormula(
343
356
  }
344
357
  return null
345
358
  }
359
+ const stopMeasure = measure(`Formula: ${componentFormula.name}`, {
360
+ formula,
361
+ component: ctx.component?.name,
362
+ })
346
363
  const Input = Object.fromEntries(
347
- formula.arguments.map((arg) =>
364
+ (formula.arguments ?? []).map((arg) =>
348
365
  arg.isFunction
349
366
  ? [
350
367
  arg.name,
@@ -371,6 +388,7 @@ export function applyFormula(
371
388
  const cache = ctx.formulaCache?.[formula.name]?.get(data)
372
389
 
373
390
  if (cache?.hit) {
391
+ stopMeasure({ cache: 'hit' })
374
392
  return cache.data
375
393
  } else {
376
394
  const result = applyFormula(componentFormula.formula, {
@@ -378,6 +396,7 @@ export function applyFormula(
378
396
  data,
379
397
  })
380
398
  ctx.formulaCache?.[formula.name]?.set(data, result)
399
+ stopMeasure({ cache: 'miss' })
381
400
  return result
382
401
  }
383
402
  }
@@ -67,7 +67,7 @@ export function* getFormulasInFormula<Handler>({
67
67
  case 'value':
68
68
  break
69
69
  case 'record':
70
- for (const [key, entry] of formula.entries.entries()) {
70
+ for (const [key, entry] of (formula.entries ?? []).entries()) {
71
71
  yield* getFormulasInFormula({
72
72
  formula: entry.formula,
73
73
  globalFormulas,
@@ -148,7 +148,7 @@ export function* getFormulasInFormula<Handler>({
148
148
  }
149
149
  break
150
150
  case 'switch':
151
- for (const [key, c] of formula.cases.entries()) {
151
+ for (const [key, c] of formula.cases?.entries() ?? []) {
152
152
  yield* getFormulasInFormula({
153
153
  formula: c.condition,
154
154
  globalFormulas,
@@ -129,15 +129,15 @@ const FALLBACK_VALUES: Record<CssSyntax | CssCustomSyntax, string> = {
129
129
  angle: '0deg',
130
130
  time: '0s',
131
131
  resolution: '0dpi',
132
- 'custom-ident': 'none',
132
+ 'custom-ident': '',
133
133
  string: '""',
134
134
  image: 'none',
135
135
  url: 'none',
136
136
  'transform-function': 'none',
137
137
  'transform-list': 'none',
138
138
  integer: '0',
139
- 'font-family': 'initial',
140
- '*': 'initial',
139
+ 'font-family': 'sans-serif',
140
+ '*': '',
141
141
  }
142
142
 
143
143
  export const appendUnit = (value: any, unit: Nullable<string>) =>
@@ -0,0 +1,59 @@
1
+ const globalScope: any = typeof globalThis !== 'undefined' ? globalThis : window
2
+ globalScope.__nc_measure_max_depth = 10
3
+ globalScope.__nc_measure_enabled =
4
+ typeof sessionStorage !== 'undefined' &&
5
+ sessionStorage.getItem('__nc_measure') === 'true'
6
+
7
+ globalScope.__nc_enableMeasure = (enabled = true, maxDepth = 10) => {
8
+ if (enabled) {
9
+ sessionStorage.setItem('__nc_measure', 'true')
10
+ } else {
11
+ sessionStorage.removeItem('__nc_measure')
12
+ }
13
+ globalScope.__nc_measure_enabled = enabled
14
+ globalScope.__nc_measure_max_depth = maxDepth
15
+ }
16
+
17
+ let measureCount = 0
18
+ const STACK: string[] = []
19
+ const NOOP = () => {}
20
+
21
+ export const measure = (key: string, details: Record<string, unknown>) => {
22
+ if (!globalScope.__nc_measure_enabled) {
23
+ return NOOP
24
+ }
25
+
26
+ const selfIndex = measureCount++
27
+ if (STACK.length >= globalScope.__nc_measure_max_depth) {
28
+ return NOOP
29
+ }
30
+
31
+ const start = performance.now()
32
+ STACK.push(key)
33
+
34
+ return (extraDetails?: Record<string, unknown>) => {
35
+ const end = performance.now()
36
+ const mergedDetails = extraDetails
37
+ ? { ...details, ...extraDetails }
38
+ : details
39
+
40
+ performance.measure(key, {
41
+ start,
42
+ end,
43
+ detail: {
44
+ devtools: {
45
+ dataType: 'track-entry',
46
+ track: 'Nordcraft devtools',
47
+ properties: [
48
+ ...Object.entries(mergedDetails).map(([k, v]) => [k, String(v)]),
49
+ ['Stack', STACK.join(' > ')],
50
+ ['Measure index', selfIndex],
51
+ ['Sub-measures', measureCount - selfIndex],
52
+ ],
53
+ tooltipText: `${selfIndex}. ${key}`,
54
+ },
55
+ },
56
+ })
57
+ STACK.pop()
58
+ }
59
+ }