@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.
- package/dist/custom-element.main.esm.js +30 -30
- package/dist/custom-element.main.esm.js.map +4 -4
- package/dist/page.main.esm.js +3 -3
- package/dist/page.main.esm.js.map +4 -4
- package/dist/src/components/createComponent.js +60 -69
- package/dist/src/components/createComponent.js.map +1 -1
- package/dist/src/components/createElement.js +33 -50
- package/dist/src/components/createElement.js.map +1 -1
- package/dist/src/components/createNode.js +8 -1
- package/dist/src/components/createNode.js.map +1 -1
- package/dist/src/components/createNode.test.d.ts +1 -0
- package/dist/src/components/createNode.test.js +608 -0
- package/dist/src/components/createNode.test.js.map +1 -0
- package/dist/src/components/renderComponent.js +2 -4
- package/dist/src/components/renderComponent.js.map +1 -1
- package/dist/src/editor-preview.main.js +4 -4
- package/dist/src/editor-preview.main.js.map +1 -1
- package/dist/src/page.main.js +31 -41
- package/dist/src/page.main.js.map +1 -1
- package/dist/src/styles/CustomPropertyStyleSheet.d.ts +0 -1
- package/dist/src/styles/CustomPropertyStyleSheet.js +1 -1
- package/dist/src/styles/CustomPropertyStyleSheet.js.map +1 -1
- package/dist/src/styles/CustomPropertyStyleSheet.test.js +2 -5
- package/dist/src/styles/CustomPropertyStyleSheet.test.js.map +1 -1
- package/dist/src/utils/BatchQueue.d.ts +1 -0
- package/dist/src/utils/BatchQueue.js +2 -1
- package/dist/src/utils/BatchQueue.js.map +1 -1
- package/dist/src/utils/formulaHasValue.d.ts +2 -0
- package/dist/src/utils/formulaHasValue.js +3 -0
- package/dist/src/utils/formulaHasValue.js.map +1 -0
- package/dist/src/utils/subscribeCustomProperty.d.ts +3 -3
- package/dist/src/utils/subscribeCustomProperty.js +2 -3
- package/dist/src/utils/subscribeCustomProperty.js.map +1 -1
- package/package.json +3 -3
- package/src/components/createComponent.ts +78 -86
- package/src/components/createElement.ts +25 -46
- package/src/components/createNode.test.ts +686 -0
- package/src/components/createNode.ts +8 -1
- package/src/components/renderComponent.ts +2 -4
- package/src/editor-preview.main.ts +4 -4
- package/src/page.main.ts +49 -51
- package/src/styles/CustomPropertyStyleSheet.test.ts +2 -7
- package/src/styles/CustomPropertyStyleSheet.ts +1 -2
- package/src/utils/BatchQueue.ts +2 -2
- package/src/utils/formulaHasValue.ts +7 -0
- package/src/utils/subscribeCustomProperty.ts +1 -5
|
@@ -111,8 +111,7 @@ export function renderComponent({
|
|
|
111
111
|
.subscribe((props) => {
|
|
112
112
|
if (prev) {
|
|
113
113
|
component.onAttributeChange?.actions?.forEach((action) => {
|
|
114
|
-
|
|
115
|
-
handleAction(
|
|
114
|
+
void handleAction(
|
|
116
115
|
action,
|
|
117
116
|
dataSignal.get(),
|
|
118
117
|
ctx,
|
|
@@ -143,8 +142,7 @@ export function renderComponent({
|
|
|
143
142
|
})
|
|
144
143
|
}
|
|
145
144
|
component.onLoad?.actions?.forEach((action) => {
|
|
146
|
-
|
|
147
|
-
handleAction(action, dataSignal.get(), ctx)
|
|
145
|
+
void handleAction(action, dataSignal.get(), ctx)
|
|
148
146
|
})
|
|
149
147
|
})
|
|
150
148
|
return rootElem
|
|
@@ -1710,7 +1710,7 @@ const insertHeadTags = (
|
|
|
1710
1710
|
document.createRange().createContextualFragment(`
|
|
1711
1711
|
<link
|
|
1712
1712
|
data-meta-id="${id}"
|
|
1713
|
-
${Object.entries(entry.attrs)
|
|
1713
|
+
${Object.entries(entry.attrs ?? {})
|
|
1714
1714
|
.map(([key, value]) => `${key}="${applyFormula(value, context)}"`)
|
|
1715
1715
|
.join(' ')}
|
|
1716
1716
|
/>
|
|
@@ -1722,10 +1722,10 @@ const insertHeadTags = (
|
|
|
1722
1722
|
document.createRange().createContextualFragment(`
|
|
1723
1723
|
<script
|
|
1724
1724
|
data-meta-id="${id}"
|
|
1725
|
-
${Object.entries(entry.attrs)
|
|
1725
|
+
${Object.entries(entry.attrs ?? {})
|
|
1726
1726
|
.map(([key, value]) => `${key}="${applyFormula(value, context)}"`)
|
|
1727
1727
|
.join(' ')}
|
|
1728
|
-
|
|
1728
|
+
>${applyFormula(entry.content ?? '', context)}</script>
|
|
1729
1729
|
`),
|
|
1730
1730
|
)
|
|
1731
1731
|
case HeadTagTypes.Style:
|
|
@@ -1734,7 +1734,7 @@ const insertHeadTags = (
|
|
|
1734
1734
|
document.createRange().createContextualFragment(`
|
|
1735
1735
|
<style
|
|
1736
1736
|
data-meta-id="${id}"
|
|
1737
|
-
${Object.entries(entry.attrs)
|
|
1737
|
+
${Object.entries(entry.attrs ?? {})
|
|
1738
1738
|
.map(([key, value]) => `${key}="${applyFormula(value, context)}"`)
|
|
1739
1739
|
.join(' ')}
|
|
1740
1740
|
>
|
package/src/page.main.ts
CHANGED
|
@@ -16,6 +16,7 @@ import type {
|
|
|
16
16
|
Toddle,
|
|
17
17
|
} from '@nordcraft/core/dist/types'
|
|
18
18
|
import { mapObject } from '@nordcraft/core/dist/utils/collections'
|
|
19
|
+
import { VOID_HTML_ELEMENTS } from '@nordcraft/core/dist/utils/html'
|
|
19
20
|
import { isDefined } from '@nordcraft/core/dist/utils/util'
|
|
20
21
|
import * as libActions from '@nordcraft/std-lib/dist/actions'
|
|
21
22
|
import * as libFormulas from '@nordcraft/std-lib/dist/formulas'
|
|
@@ -359,22 +360,21 @@ const setupMetaUpdates = (
|
|
|
359
360
|
component: Component,
|
|
360
361
|
dataSignal: Signal<ComponentData>,
|
|
361
362
|
) => {
|
|
363
|
+
const getFormulaContext = (data: ComponentData) => ({
|
|
364
|
+
data,
|
|
365
|
+
component,
|
|
366
|
+
root: document,
|
|
367
|
+
package: undefined,
|
|
368
|
+
toddle: window.toddle,
|
|
369
|
+
env,
|
|
370
|
+
})
|
|
362
371
|
// Handle dynamic updates of the document language
|
|
363
372
|
const langFormula = component.route?.info?.language?.formula
|
|
364
373
|
const dynamicLang = langFormula && langFormula.type !== 'value'
|
|
365
374
|
if (dynamicLang) {
|
|
366
375
|
dataSignal
|
|
367
|
-
.map
|
|
368
|
-
component
|
|
369
|
-
? applyFormula(langFormula, {
|
|
370
|
-
data: dataSignal.get(),
|
|
371
|
-
component,
|
|
372
|
-
root: document,
|
|
373
|
-
package: undefined,
|
|
374
|
-
toddle: window.toddle,
|
|
375
|
-
env,
|
|
376
|
-
})
|
|
377
|
-
: null,
|
|
376
|
+
.map((data) =>
|
|
377
|
+
component ? applyFormula(langFormula, getFormulaContext(data)) : null,
|
|
378
378
|
)
|
|
379
379
|
.subscribe((newLang) => {
|
|
380
380
|
if (isDefined(newLang) && document.documentElement.lang !== newLang) {
|
|
@@ -388,17 +388,8 @@ const setupMetaUpdates = (
|
|
|
388
388
|
const dynamicTitle = titleFormula && titleFormula.type !== 'value'
|
|
389
389
|
if (dynamicTitle) {
|
|
390
390
|
dataSignal
|
|
391
|
-
.map
|
|
392
|
-
component
|
|
393
|
-
? applyFormula(titleFormula, {
|
|
394
|
-
data: dataSignal.get(),
|
|
395
|
-
component,
|
|
396
|
-
root: document,
|
|
397
|
-
package: undefined,
|
|
398
|
-
toddle: window.toddle,
|
|
399
|
-
env,
|
|
400
|
-
})
|
|
401
|
-
: null,
|
|
391
|
+
.map((data) =>
|
|
392
|
+
component ? applyFormula(titleFormula, getFormulaContext(data)) : null,
|
|
402
393
|
)
|
|
403
394
|
.subscribe((newTitle) => {
|
|
404
395
|
if (isDefined(newTitle) && document.title !== newTitle) {
|
|
@@ -411,10 +402,12 @@ const setupMetaUpdates = (
|
|
|
411
402
|
const meta = component.route?.info?.meta
|
|
412
403
|
const dynamicDescription =
|
|
413
404
|
descriptionFormula && descriptionFormula.type !== 'value'
|
|
414
|
-
const dynamicMetaFormulas = Object.values(meta ?? {}).some(
|
|
415
|
-
|
|
416
|
-
r.
|
|
417
|
-
|
|
405
|
+
const dynamicMetaFormulas = Object.values(meta ?? {}).some(
|
|
406
|
+
(r) =>
|
|
407
|
+
r.content?.type !== 'value' ||
|
|
408
|
+
Object.values(
|
|
409
|
+
r.attrs ?? {}, // fallback to make sure we don't crash on legacy values
|
|
410
|
+
).some((a) => a.type !== 'value'),
|
|
418
411
|
)
|
|
419
412
|
if (dynamicDescription || dynamicMetaFormulas) {
|
|
420
413
|
const findMetaElement = (name: string) =>
|
|
@@ -423,7 +416,11 @@ const setupMetaUpdates = (
|
|
|
423
416
|
) ?? null
|
|
424
417
|
|
|
425
418
|
const updateMetaElement = (
|
|
426
|
-
entry: {
|
|
419
|
+
entry: {
|
|
420
|
+
tag: string
|
|
421
|
+
attrs: Record<string, string>
|
|
422
|
+
content: string | undefined
|
|
423
|
+
},
|
|
427
424
|
id?: string,
|
|
428
425
|
) => {
|
|
429
426
|
let existingElement: HTMLElement | null = null
|
|
@@ -452,19 +449,18 @@ const setupMetaUpdates = (
|
|
|
452
449
|
}
|
|
453
450
|
existingElement!.setAttribute(key, value)
|
|
454
451
|
})
|
|
452
|
+
if (
|
|
453
|
+
typeof entry.content === 'string' &&
|
|
454
|
+
!VOID_HTML_ELEMENTS.includes(entry.tag.toLowerCase())
|
|
455
|
+
) {
|
|
456
|
+
existingElement.textContent = entry.content
|
|
457
|
+
}
|
|
455
458
|
}
|
|
456
459
|
if (dynamicDescription) {
|
|
457
460
|
dataSignal
|
|
458
|
-
.map
|
|
461
|
+
.map((data) =>
|
|
459
462
|
component
|
|
460
|
-
? applyFormula(descriptionFormula,
|
|
461
|
-
data,
|
|
462
|
-
component,
|
|
463
|
-
root: document,
|
|
464
|
-
package: undefined,
|
|
465
|
-
toddle: window.toddle,
|
|
466
|
-
env,
|
|
467
|
-
})
|
|
463
|
+
? applyFormula(descriptionFormula, getFormulaContext(data))
|
|
468
464
|
: null,
|
|
469
465
|
)
|
|
470
466
|
.subscribe((newDescription) => {
|
|
@@ -501,6 +497,7 @@ const setupMetaUpdates = (
|
|
|
501
497
|
property: 'og:description',
|
|
502
498
|
content: newDescription,
|
|
503
499
|
},
|
|
500
|
+
content: undefined,
|
|
504
501
|
})
|
|
505
502
|
}
|
|
506
503
|
}
|
|
@@ -509,36 +506,37 @@ const setupMetaUpdates = (
|
|
|
509
506
|
if (dynamicMetaFormulas) {
|
|
510
507
|
Object.entries(meta ?? {})
|
|
511
508
|
// Filter out meta tags that have no dynamic formulas
|
|
512
|
-
.filter(
|
|
513
|
-
|
|
514
|
-
|
|
509
|
+
.filter(
|
|
510
|
+
([_, entry]) =>
|
|
511
|
+
// fallback to make sure we don't crash on legacy values.
|
|
512
|
+
entry.content?.type !== 'value' ||
|
|
513
|
+
Object.values(entry.attrs ?? {}).some((a) => a.type !== 'value'),
|
|
515
514
|
)
|
|
516
515
|
.forEach(([id, entry]) => {
|
|
517
516
|
dataSignal
|
|
518
|
-
.map
|
|
517
|
+
.map((data) => {
|
|
518
|
+
const context = getFormulaContext(data)
|
|
519
519
|
// Return the new values for all attributes (we assume they're strings)
|
|
520
520
|
const values = Object.entries(entry.attrs ?? {}).reduce(
|
|
521
521
|
(agg, [key, formula]) =>
|
|
522
522
|
component
|
|
523
523
|
? {
|
|
524
524
|
...agg,
|
|
525
|
-
[key]: applyFormula(formula,
|
|
526
|
-
data,
|
|
527
|
-
component,
|
|
528
|
-
root: document,
|
|
529
|
-
package: undefined,
|
|
530
|
-
toddle: window.toddle,
|
|
531
|
-
env,
|
|
532
|
-
}),
|
|
525
|
+
[key]: applyFormula(formula, context),
|
|
533
526
|
}
|
|
534
527
|
: agg,
|
|
535
528
|
{},
|
|
536
529
|
)
|
|
537
|
-
return
|
|
530
|
+
return {
|
|
531
|
+
attrs: values,
|
|
532
|
+
content: entry.content
|
|
533
|
+
? applyFormula(entry.content, context)
|
|
534
|
+
: undefined,
|
|
535
|
+
}
|
|
538
536
|
})
|
|
539
|
-
.subscribe((attrs) =>
|
|
537
|
+
.subscribe(({ attrs, content }) =>
|
|
540
538
|
// Update the meta tags with the new values
|
|
541
|
-
updateMetaElement({ tag: entry.tag, attrs }, id),
|
|
539
|
+
updateMetaElement({ tag: entry.tag, attrs, content }, id),
|
|
542
540
|
)
|
|
543
541
|
})
|
|
544
542
|
}
|
|
@@ -121,7 +121,7 @@ describe('CustomPropertyStyleSheet', () => {
|
|
|
121
121
|
'.my-class { --my-other-property: 512px; }',
|
|
122
122
|
)
|
|
123
123
|
instance.unregisterProperty('.my-class', '--my-other-property')
|
|
124
|
-
expect(instance.getStyleSheet().cssRules
|
|
124
|
+
expect(instance.getStyleSheet().cssRules).toBeEmpty()
|
|
125
125
|
})
|
|
126
126
|
|
|
127
127
|
test('it unregisters a property with media queries', () => {
|
|
@@ -149,11 +149,6 @@ describe('CustomPropertyStyleSheet', () => {
|
|
|
149
149
|
mediaQuery: { 'max-width': '600px' },
|
|
150
150
|
},
|
|
151
151
|
)
|
|
152
|
-
expect(instance.getStyleSheet().cssRules
|
|
153
|
-
`\
|
|
154
|
-
@media (max-width: 600px) {
|
|
155
|
-
.my-class-with-media { }
|
|
156
|
-
}`,
|
|
157
|
-
)
|
|
152
|
+
expect(instance.getStyleSheet().cssRules).toBeEmpty()
|
|
158
153
|
})
|
|
159
154
|
})
|
|
@@ -76,7 +76,6 @@ export class CustomPropertyStyleSheet {
|
|
|
76
76
|
options?: Nullable<{
|
|
77
77
|
mediaQuery?: Nullable<MediaQuery>
|
|
78
78
|
startingStyle?: Nullable<boolean>
|
|
79
|
-
deepClean?: Nullable<boolean>
|
|
80
79
|
}>,
|
|
81
80
|
): void {
|
|
82
81
|
if (!this.ruleMap) {
|
|
@@ -97,7 +96,7 @@ export class CustomPropertyStyleSheet {
|
|
|
97
96
|
|
|
98
97
|
// Cleaning up empty selectors is probably not necessary in production and may have performance implications.
|
|
99
98
|
// However, it is required for the editor-preview as it is a dynamic environment and things may get reordered and canvas reused.
|
|
100
|
-
if (
|
|
99
|
+
if (rule.style.length === 0) {
|
|
101
100
|
this.styleSheet.deleteRule(
|
|
102
101
|
Array.from(this.ruleMap.keys()).indexOf(fullSelector),
|
|
103
102
|
)
|
package/src/utils/BatchQueue.ts
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
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
|
private batchQueue: Array<() => void> = []
|
|
7
8
|
private isProcessing = false
|
|
8
9
|
private processBatch() {
|
|
9
10
|
if (this.isProcessing) return
|
|
10
11
|
this.isProcessing = true
|
|
11
|
-
|
|
12
|
-
requestAnimationFrame(() => {
|
|
12
|
+
queueMicrotask(() => {
|
|
13
13
|
while (this.batchQueue.length > 0) {
|
|
14
14
|
const callback = this.batchQueue.shift()
|
|
15
15
|
callback?.()
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Formula } from '@nordcraft/core/dist/formula/formula'
|
|
2
|
+
import { isDefined } from '@nordcraft/core/dist/utils/util'
|
|
3
|
+
|
|
4
|
+
export const formulaHasValue = (
|
|
5
|
+
formula: Formula | undefined,
|
|
6
|
+
): formula is Formula =>
|
|
7
|
+
isDefined(formula) && !(formula.type === 'value' && !isDefined(formula.value))
|
|
@@ -2,10 +2,9 @@ import type { Signal } from '../signal/signal'
|
|
|
2
2
|
|
|
3
3
|
import { CUSTOM_PROPERTIES_STYLESHEET_ID } from '@nordcraft/core/dist/styling/theme.const'
|
|
4
4
|
import type { StyleVariant } from '@nordcraft/core/dist/styling/variantSelector'
|
|
5
|
-
import type { Runtime } from '@nordcraft/core/dist/types'
|
|
6
5
|
import { CustomPropertyStyleSheet } from '../styles/CustomPropertyStyleSheet'
|
|
7
6
|
|
|
8
|
-
let customPropertiesStylesheet: CustomPropertyStyleSheet | undefined
|
|
7
|
+
export let customPropertiesStylesheet: CustomPropertyStyleSheet | undefined
|
|
9
8
|
|
|
10
9
|
export function subscribeCustomProperty({
|
|
11
10
|
selector,
|
|
@@ -13,14 +12,12 @@ export function subscribeCustomProperty({
|
|
|
13
12
|
signal,
|
|
14
13
|
variant,
|
|
15
14
|
root,
|
|
16
|
-
runtime,
|
|
17
15
|
}: {
|
|
18
16
|
selector: string
|
|
19
17
|
customPropertyName: string
|
|
20
18
|
signal: Signal<string>
|
|
21
19
|
variant?: StyleVariant
|
|
22
20
|
root: Document | ShadowRoot
|
|
23
|
-
runtime: Runtime
|
|
24
21
|
}) {
|
|
25
22
|
customPropertiesStylesheet ??= new CustomPropertyStyleSheet(
|
|
26
23
|
root,
|
|
@@ -43,7 +40,6 @@ export function subscribeCustomProperty({
|
|
|
43
40
|
selector,
|
|
44
41
|
customPropertyName,
|
|
45
42
|
{
|
|
46
|
-
deepClean: runtime === 'preview',
|
|
47
43
|
mediaQuery: variant?.mediaQuery,
|
|
48
44
|
startingStyle: variant?.startingStyle,
|
|
49
45
|
},
|