@nordcraft/runtime 1.0.33 → 1.0.35
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/components/createComponent.js +4 -0
- package/dist/components/createComponent.js.map +1 -1
- package/dist/components/createElement.js +9 -1
- package/dist/components/createElement.js.map +1 -1
- package/dist/components/createNode.js +3 -3
- package/dist/components/createNode.js.map +1 -1
- package/dist/custom-element.main.esm.js +17 -17
- package/dist/custom-element.main.esm.js.map +4 -4
- package/dist/debug/panicScreen.d.ts +6 -0
- package/dist/debug/panicScreen.js +25 -0
- package/dist/debug/panicScreen.js.map +1 -0
- package/dist/debug/sendEditorToast.d.ts +3 -0
- package/dist/debug/sendEditorToast.js +9 -0
- package/dist/debug/sendEditorToast.js.map +1 -0
- package/dist/editor/graphql.d.ts +12 -0
- package/dist/editor/graphql.js +150 -0
- package/dist/editor/graphql.js.map +1 -0
- package/dist/editor-preview.main.js +142 -71
- package/dist/editor-preview.main.js.map +1 -1
- package/dist/page.main.esm.js +3 -3
- package/dist/page.main.esm.js.map +4 -4
- package/dist/styles/CustomPropertyStyleSheet.d.ts +2 -1
- package/dist/styles/CustomPropertyStyleSheet.js +14 -5
- package/dist/styles/CustomPropertyStyleSheet.js.map +1 -1
- package/dist/styles/CustomPropertyStyleSheet.test.js +7 -7
- package/dist/styles/CustomPropertyStyleSheet.test.js.map +1 -1
- package/dist/utils/subscribeCustomProperty.d.ts +4 -1
- package/dist/utils/subscribeCustomProperty.js +11 -4
- package/dist/utils/subscribeCustomProperty.js.map +1 -1
- package/package.json +3 -3
- package/src/components/createComponent.ts +4 -0
- package/src/components/createElement.ts +10 -1
- package/src/components/createNode.ts +3 -3
- package/src/debug/panicScreen.ts +37 -0
- package/src/debug/sendEditorToast.ts +19 -0
- package/src/editor/graphql.ts +167 -0
- package/src/editor-preview.main.ts +319 -215
- package/src/styles/CustomPropertyStyleSheet.test.ts +7 -7
- package/src/styles/CustomPropertyStyleSheet.ts +22 -5
- package/src/utils/subscribeCustomProperty.ts +25 -12
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
/* eslint-disable no-case-declarations */
|
|
4
4
|
/* eslint-disable no-fallthrough */
|
|
5
5
|
import { isLegacyApi } from '@nordcraft/core/dist/api/api'
|
|
6
|
+
import { type ApiRequest } from '@nordcraft/core/dist/api/apiTypes'
|
|
6
7
|
import type {
|
|
7
8
|
AnimationKeyframe,
|
|
8
9
|
Component,
|
|
@@ -38,10 +39,13 @@ import { createLegacyAPI } from './api/createAPI'
|
|
|
38
39
|
import { createAPI } from './api/createAPIv2'
|
|
39
40
|
import { createNode } from './components/createNode'
|
|
40
41
|
import { isContextProvider } from './context/isContextProvider'
|
|
42
|
+
import { createPanicScreen } from './debug/panicScreen'
|
|
43
|
+
import { sendEditorToast } from './debug/sendEditorToast'
|
|
41
44
|
import { dragEnded } from './editor/drag-drop/dragEnded'
|
|
42
45
|
import { dragMove } from './editor/drag-drop/dragMove'
|
|
43
46
|
import { dragReorder } from './editor/drag-drop/dragReorder'
|
|
44
47
|
import { dragStarted } from './editor/drag-drop/dragStarted'
|
|
48
|
+
import { introspectApiRequest } from './editor/graphql'
|
|
45
49
|
import type { DragState } from './editor/types'
|
|
46
50
|
import { handleAction } from './events/handleAction'
|
|
47
51
|
import type { Signal } from './signal/signal'
|
|
@@ -97,6 +101,7 @@ type ToddlePreviewEvent =
|
|
|
97
101
|
| { type: 'update_inner_text'; innerText: string }
|
|
98
102
|
| { type: 'reload' }
|
|
99
103
|
| { type: 'fetch_api'; apiKey: string }
|
|
104
|
+
| { type: 'introspect_qraphql_api'; apiKey: string }
|
|
100
105
|
| { type: 'drag-started'; x: number; y: number }
|
|
101
106
|
| { type: 'drag-ended'; canceled?: true }
|
|
102
107
|
| { type: 'keydown'; key: string; altKey: boolean; metaKey: boolean }
|
|
@@ -336,7 +341,7 @@ export const createRoot = (
|
|
|
336
341
|
|
|
337
342
|
window.addEventListener(
|
|
338
343
|
'message',
|
|
339
|
-
(message: MessageEvent<ToddlePreviewEvent>) => {
|
|
344
|
+
async (message: MessageEvent<ToddlePreviewEvent>) => {
|
|
340
345
|
if (!message.isTrusted) {
|
|
341
346
|
console.error('UNTRUSTED MESSAGE')
|
|
342
347
|
}
|
|
@@ -487,27 +492,21 @@ export const createRoot = (
|
|
|
487
492
|
element.value.type === 'value'
|
|
488
493
|
) {
|
|
489
494
|
const computedStyle = window.getComputedStyle(node)
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
},
|
|
500
|
-
'*',
|
|
501
|
-
)
|
|
495
|
+
postMessageToEditor({
|
|
496
|
+
type: 'textComputedStyle',
|
|
497
|
+
computedStyle: Object.fromEntries(
|
|
498
|
+
Object.values(TextNodeComputedStyles).map((style) => [
|
|
499
|
+
style,
|
|
500
|
+
computedStyle.getPropertyValue(style),
|
|
501
|
+
]),
|
|
502
|
+
),
|
|
503
|
+
})
|
|
502
504
|
} else if (node && node.getAttribute('data-node-type') !== 'text') {
|
|
503
505
|
// Reset computed style on blur
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
},
|
|
509
|
-
'*',
|
|
510
|
-
)
|
|
506
|
+
postMessageToEditor({
|
|
507
|
+
type: 'textComputedStyle',
|
|
508
|
+
computedStyle: {},
|
|
509
|
+
})
|
|
511
510
|
}
|
|
512
511
|
}
|
|
513
512
|
return
|
|
@@ -566,7 +565,7 @@ export const createRoot = (
|
|
|
566
565
|
}
|
|
567
566
|
const { x, y, type } = message.data
|
|
568
567
|
const elementsAtPoint = document.elementsFromPoint(x, y)
|
|
569
|
-
|
|
568
|
+
const element = elementsAtPoint.find((elem) => {
|
|
570
569
|
const id = elem.getAttribute('data-id')
|
|
571
570
|
if (
|
|
572
571
|
typeof id !== 'string' ||
|
|
@@ -583,31 +582,12 @@ export const createRoot = (
|
|
|
583
582
|
if (elem.getAttribute('data-node-type') === 'text') {
|
|
584
583
|
return (
|
|
585
584
|
// 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'
|
|
585
|
+
metaKey || type === 'dblclick'
|
|
592
586
|
)
|
|
593
587
|
}
|
|
594
588
|
return true
|
|
595
589
|
})
|
|
596
590
|
|
|
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
591
|
const id = element?.getAttribute('data-id') ?? null
|
|
612
592
|
if (type === 'click' && id !== selectedNodeId) {
|
|
613
593
|
if (message.data.metaKey) {
|
|
@@ -617,13 +597,10 @@ export const createRoot = (
|
|
|
617
597
|
if (root && id) {
|
|
618
598
|
const nodeLookup = getNodeAndAncestors(component, root, id)
|
|
619
599
|
if (nodeLookup?.node.type === 'text') {
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
},
|
|
625
|
-
'*',
|
|
626
|
-
)
|
|
600
|
+
postMessageToEditor({
|
|
601
|
+
type: 'selection',
|
|
602
|
+
selectedNodeId: id,
|
|
603
|
+
})
|
|
627
604
|
} else {
|
|
628
605
|
const firstTextChild =
|
|
629
606
|
nodeLookup?.node.type === 'element'
|
|
@@ -632,33 +609,24 @@ export const createRoot = (
|
|
|
632
609
|
)
|
|
633
610
|
: undefined
|
|
634
611
|
if (firstTextChild) {
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
},
|
|
640
|
-
'*',
|
|
641
|
-
)
|
|
612
|
+
postMessageToEditor({
|
|
613
|
+
type: 'selection',
|
|
614
|
+
selectedNodeId: `${id}.0`,
|
|
615
|
+
})
|
|
642
616
|
}
|
|
643
617
|
}
|
|
644
618
|
}
|
|
645
619
|
} else {
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
},
|
|
651
|
-
'*',
|
|
652
|
-
)
|
|
620
|
+
postMessageToEditor({
|
|
621
|
+
type: 'selection',
|
|
622
|
+
selectedNodeId: id,
|
|
623
|
+
})
|
|
653
624
|
}
|
|
654
625
|
} else if (type === 'mousemove' && id !== highlightedNodeId) {
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
},
|
|
660
|
-
'*',
|
|
661
|
-
)
|
|
626
|
+
postMessageToEditor({
|
|
627
|
+
type: 'highlight',
|
|
628
|
+
highlightedNodeId: id,
|
|
629
|
+
})
|
|
662
630
|
} else if (
|
|
663
631
|
type === 'dblclick' &&
|
|
664
632
|
id &&
|
|
@@ -673,23 +641,17 @@ export const createRoot = (
|
|
|
673
641
|
nodeLookup?.node.type === 'component' &&
|
|
674
642
|
nodeLookup.node.name
|
|
675
643
|
) {
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
},
|
|
681
|
-
'*',
|
|
682
|
-
)
|
|
644
|
+
postMessageToEditor({
|
|
645
|
+
type: 'navigate',
|
|
646
|
+
name: nodeLookup.node.name,
|
|
647
|
+
})
|
|
683
648
|
}
|
|
684
649
|
// Double click on text node should select the text node for editing
|
|
685
650
|
else if (nodeLookup?.node.type === 'text') {
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
},
|
|
691
|
-
'*',
|
|
692
|
-
)
|
|
651
|
+
postMessageToEditor({
|
|
652
|
+
type: 'selection',
|
|
653
|
+
selectedNodeId: id,
|
|
654
|
+
})
|
|
693
655
|
}
|
|
694
656
|
}
|
|
695
657
|
}
|
|
@@ -701,19 +663,16 @@ export const createRoot = (
|
|
|
701
663
|
// We request manually instead of automatic to avoid mutation observer spam.
|
|
702
664
|
// Also, reporting automatically proved unreliable when elements' height was in %
|
|
703
665
|
case 'report_document_scroll_size':
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
},
|
|
710
|
-
'*',
|
|
711
|
-
)
|
|
666
|
+
postMessageToEditor({
|
|
667
|
+
type: 'documentScrollSize',
|
|
668
|
+
scrollHeight: domNode.scrollHeight,
|
|
669
|
+
scrollWidth: domNode.scrollWidth,
|
|
670
|
+
})
|
|
712
671
|
break
|
|
713
672
|
case 'reload':
|
|
714
673
|
window.location.reload()
|
|
715
674
|
break
|
|
716
|
-
case 'fetch_api':
|
|
675
|
+
case 'fetch_api': {
|
|
717
676
|
const { apiKey } = message.data
|
|
718
677
|
dataSignal.update((data) => ({
|
|
719
678
|
...data,
|
|
@@ -728,6 +687,36 @@ export const createRoot = (
|
|
|
728
687
|
}))
|
|
729
688
|
void ctx?.apis[apiKey]?.fetch({} as any)
|
|
730
689
|
break
|
|
690
|
+
}
|
|
691
|
+
case 'introspect_qraphql_api': {
|
|
692
|
+
const { apiKey } = message.data
|
|
693
|
+
const api = component?.apis[apiKey]
|
|
694
|
+
if (api && !isLegacyApi(api) && component) {
|
|
695
|
+
const Attributes = mapObject(
|
|
696
|
+
component.attributes,
|
|
697
|
+
([name, { testValue }]) => [name, testValue],
|
|
698
|
+
)
|
|
699
|
+
const formulaContext: FormulaContext = {
|
|
700
|
+
component,
|
|
701
|
+
data: { Attributes },
|
|
702
|
+
root: document,
|
|
703
|
+
package: ctx?.package,
|
|
704
|
+
toddle: window.toddle,
|
|
705
|
+
env,
|
|
706
|
+
}
|
|
707
|
+
const introspectionResult = await introspectApiRequest({
|
|
708
|
+
api: api as ApiRequest,
|
|
709
|
+
componentName: component.name,
|
|
710
|
+
formulaContext,
|
|
711
|
+
})
|
|
712
|
+
postMessageToEditor({
|
|
713
|
+
type: 'introspectionResult',
|
|
714
|
+
data: introspectionResult,
|
|
715
|
+
apiKey,
|
|
716
|
+
})
|
|
717
|
+
}
|
|
718
|
+
break
|
|
719
|
+
}
|
|
731
720
|
case 'drag-started':
|
|
732
721
|
const draggedElement = getDOMNodeFromNodeId(selectedNodeId)
|
|
733
722
|
if (!draggedElement || !draggedElement.parentElement) {
|
|
@@ -777,17 +766,14 @@ export const createRoot = (
|
|
|
777
766
|
dragState?.copy)
|
|
778
767
|
) {
|
|
779
768
|
void dragEnded(dragState, false).then(() => {
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
},
|
|
789
|
-
'*',
|
|
790
|
-
)
|
|
769
|
+
postMessageToEditor({
|
|
770
|
+
type: 'nodeMoved',
|
|
771
|
+
copy: Boolean(dragState?.copy),
|
|
772
|
+
parent: parentDataId,
|
|
773
|
+
index: !isNaN(nextSiblingId)
|
|
774
|
+
? nextSiblingId
|
|
775
|
+
: component?.nodes[parentNodeId]?.children?.length,
|
|
776
|
+
})
|
|
791
777
|
dragState = null
|
|
792
778
|
})
|
|
793
779
|
} else {
|
|
@@ -803,16 +789,12 @@ export const createRoot = (
|
|
|
803
789
|
]
|
|
804
790
|
if (selectedPermutation && !message.data.canceled) {
|
|
805
791
|
void dragEnded(dragState, false).then(() => {
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
index: selectedPermutation?.index,
|
|
813
|
-
},
|
|
814
|
-
'*',
|
|
815
|
-
)
|
|
792
|
+
postMessageToEditor({
|
|
793
|
+
type: 'nodeMoved',
|
|
794
|
+
copy: Boolean(dragState?.copy),
|
|
795
|
+
parent: selectedPermutation?.parent.getAttribute('data-id'),
|
|
796
|
+
index: selectedPermutation?.index,
|
|
797
|
+
})
|
|
816
798
|
dragState = null
|
|
817
799
|
})
|
|
818
800
|
} else {
|
|
@@ -860,18 +842,15 @@ export const createRoot = (
|
|
|
860
842
|
|
|
861
843
|
const { styles } = message.data
|
|
862
844
|
const computedStyle = window.getComputedStyle(selectedNode)
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
},
|
|
873
|
-
'*',
|
|
874
|
-
)
|
|
845
|
+
postMessageToEditor({
|
|
846
|
+
type: 'computedStyle',
|
|
847
|
+
computedStyle: Object.fromEntries(
|
|
848
|
+
(styles ?? []).map((style) => [
|
|
849
|
+
style,
|
|
850
|
+
computedStyle.getPropertyValue(style),
|
|
851
|
+
]),
|
|
852
|
+
),
|
|
853
|
+
})
|
|
875
854
|
break
|
|
876
855
|
|
|
877
856
|
case 'set_timeline_keyframes':
|
|
@@ -986,10 +965,30 @@ export const createRoot = (
|
|
|
986
965
|
document.head.appendChild(styleTag)
|
|
987
966
|
}
|
|
988
967
|
|
|
968
|
+
// If style variant targets a pseudo-element, apply styles to it instead
|
|
969
|
+
let pseudoElement = ''
|
|
970
|
+
if (component && styleVariantSelection) {
|
|
971
|
+
const nodeLookup = getNodeAndAncestors(
|
|
972
|
+
component,
|
|
973
|
+
component.nodes.root,
|
|
974
|
+
styleVariantSelection.nodeId,
|
|
975
|
+
)
|
|
976
|
+
|
|
977
|
+
if (
|
|
978
|
+
nodeLookup?.node.type === 'element' ||
|
|
979
|
+
(nodeLookup?.node.type === 'component' &&
|
|
980
|
+
nodeLookup.node.variants?.[
|
|
981
|
+
styleVariantSelection.styleVariantIndex
|
|
982
|
+
].pseudoElement)
|
|
983
|
+
) {
|
|
984
|
+
pseudoElement = `::${nodeLookup.node.variants?.[styleVariantSelection.styleVariantIndex].pseudoElement}`
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
|
|
989
988
|
const previewStyles = Object.entries(previewStyleStyles)
|
|
990
989
|
.map(([key, value]) => `${key}: ${value} !important;`)
|
|
991
990
|
.join('\n')
|
|
992
|
-
styleTag.innerHTML = `[data-id="${selectedNodeId}"], [data-id="${selectedNodeId}"] ~ [data-id^="${selectedNodeId}("] {
|
|
991
|
+
styleTag.innerHTML = `[data-id="${selectedNodeId}"]${pseudoElement}, [data-id="${selectedNodeId}"] ~ [data-id^="${selectedNodeId}("]${pseudoElement} {
|
|
993
992
|
${previewStyles}
|
|
994
993
|
transition: none !important;
|
|
995
994
|
}`
|
|
@@ -1054,9 +1053,10 @@ export const createRoot = (
|
|
|
1054
1053
|
(nodeLookup.node.type === 'element' ||
|
|
1055
1054
|
nodeLookup.node.type === 'component')
|
|
1056
1055
|
) {
|
|
1057
|
-
const selectedStyleVariant =
|
|
1058
|
-
|
|
1059
|
-
|
|
1056
|
+
const selectedStyleVariant =
|
|
1057
|
+
nodeLookup.node.variants?.[
|
|
1058
|
+
styleVariantSelection.styleVariantIndex
|
|
1059
|
+
] ?? ({ style: {} } as StyleVariant)
|
|
1060
1060
|
// Add a style element specific to the selected element which
|
|
1061
1061
|
// is only applied when the preview is in design mode
|
|
1062
1062
|
const styleVariantCustomProperties = Object.entries(
|
|
@@ -1081,12 +1081,15 @@ export const createRoot = (
|
|
|
1081
1081
|
.filter(({ value }) => value !== undefined)
|
|
1082
1082
|
|
|
1083
1083
|
const styleElem = document.createElement('style')
|
|
1084
|
+
const pseudoElement = selectedStyleVariant.pseudoElement
|
|
1085
|
+
? `::${selectedStyleVariant.pseudoElement}`
|
|
1086
|
+
: ''
|
|
1084
1087
|
styleElem.setAttribute('data-hash', selectedNodeId)
|
|
1085
1088
|
styleElem.appendChild(
|
|
1086
1089
|
document.createTextNode(`
|
|
1087
|
-
body[data-mode="design"] [data-id="${selectedNodeId}"] {
|
|
1090
|
+
body[data-mode="design"] [data-id="${selectedNodeId}"]${pseudoElement} {
|
|
1088
1091
|
${styleToCss({
|
|
1089
|
-
...nodeLookup.node.style,
|
|
1092
|
+
...(!pseudoElement && nodeLookup.node.style),
|
|
1090
1093
|
...selectedStyleVariant.style,
|
|
1091
1094
|
...Object.fromEntries(
|
|
1092
1095
|
styleVariantCustomProperties.map(
|
|
@@ -1406,28 +1409,59 @@ export const createRoot = (
|
|
|
1406
1409
|
// Clear old root signal and create a new one to not keep old signals with previous root around
|
|
1407
1410
|
ctxDataSignal?.destroy()
|
|
1408
1411
|
ctxDataSignal = dataSignal.map((data) => data)
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1412
|
+
try {
|
|
1413
|
+
const rootElem = createNode({
|
|
1414
|
+
id: 'root',
|
|
1415
|
+
path: '0',
|
|
1416
|
+
dataSignal: ctxDataSignal,
|
|
1417
|
+
ctx: newCtx,
|
|
1418
|
+
parentElement: domNode,
|
|
1419
|
+
instance: { [newCtx.component.name]: 'root' },
|
|
1420
|
+
})
|
|
1421
|
+
newCtx.component.onLoad?.actions.forEach((action) => {
|
|
1422
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
1423
|
+
handleAction(action, dataSignal.get(), newCtx)
|
|
1424
|
+
})
|
|
1425
|
+
rootElem.forEach((elem) => domNode.appendChild(elem))
|
|
1426
|
+
} catch (error: unknown) {
|
|
1427
|
+
const isPage = isPageComponent(newCtx.component)
|
|
1428
|
+
let name = `Unexpected error while rendering ${isPage ? 'page' : 'component'}`
|
|
1429
|
+
let message = error instanceof Error ? error.message : String(error)
|
|
1430
|
+
let panic = false
|
|
1431
|
+
if (error instanceof RangeError) {
|
|
1432
|
+
// RangeError is unrecoverable
|
|
1433
|
+
panic = true
|
|
1434
|
+
name = 'Infinite loop detected'
|
|
1435
|
+
message =
|
|
1436
|
+
'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.'
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
// Send a toast to the editor with the error
|
|
1440
|
+
sendEditorToast(name, message, {
|
|
1441
|
+
type: 'critical',
|
|
1442
|
+
})
|
|
1443
|
+
|
|
1444
|
+
if (panic) {
|
|
1445
|
+
// Show error overlay in the editor until next update
|
|
1446
|
+
const panicScreen = createPanicScreen({
|
|
1447
|
+
name: name,
|
|
1448
|
+
message,
|
|
1449
|
+
isPage,
|
|
1450
|
+
cause: error,
|
|
1451
|
+
})
|
|
1452
|
+
|
|
1453
|
+
// Replace the inner HTML of the editor preview with the panic screen
|
|
1454
|
+
domNode.innerHTML = ''
|
|
1455
|
+
domNode.appendChild(panicScreen)
|
|
1456
|
+
}
|
|
1457
|
+
console.error(name, message, error)
|
|
1458
|
+
}
|
|
1459
|
+
postMessageToEditor({
|
|
1460
|
+
type: 'style',
|
|
1461
|
+
time: new Intl.DateTimeFormat('en-GB', {
|
|
1462
|
+
timeStyle: 'long',
|
|
1463
|
+
}).format(new Date()),
|
|
1420
1464
|
})
|
|
1421
|
-
rootElem.forEach((elem) => domNode.appendChild(elem))
|
|
1422
|
-
window.parent?.postMessage(
|
|
1423
|
-
{
|
|
1424
|
-
type: 'style',
|
|
1425
|
-
time: new Intl.DateTimeFormat('en-GB', {
|
|
1426
|
-
timeStyle: 'long',
|
|
1427
|
-
}).format(new Date()),
|
|
1428
|
-
},
|
|
1429
|
-
'*',
|
|
1430
|
-
)
|
|
1431
1465
|
}
|
|
1432
1466
|
}
|
|
1433
1467
|
|
|
@@ -1442,17 +1476,14 @@ export const createRoot = (
|
|
|
1442
1476
|
component,
|
|
1443
1477
|
components,
|
|
1444
1478
|
triggerEvent: (event, data) => {
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
},
|
|
1454
|
-
'*',
|
|
1455
|
-
)
|
|
1479
|
+
postMessageToEditor({
|
|
1480
|
+
type: 'component event',
|
|
1481
|
+
event,
|
|
1482
|
+
time: new Intl.DateTimeFormat('en-GB', {
|
|
1483
|
+
timeStyle: 'long',
|
|
1484
|
+
}).format(new Date()),
|
|
1485
|
+
data,
|
|
1486
|
+
})
|
|
1456
1487
|
},
|
|
1457
1488
|
dataSignal,
|
|
1458
1489
|
root: document,
|
|
@@ -1511,64 +1542,55 @@ export const createRoot = (
|
|
|
1511
1542
|
event.preventDefault()
|
|
1512
1543
|
}
|
|
1513
1544
|
}
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
altKey: event.altKey,
|
|
1522
|
-
},
|
|
1545
|
+
postMessageToEditor({
|
|
1546
|
+
type: 'keydown',
|
|
1547
|
+
event: {
|
|
1548
|
+
key: event.key,
|
|
1549
|
+
metaKey: event.metaKey,
|
|
1550
|
+
shiftKey: event.shiftKey,
|
|
1551
|
+
altKey: event.altKey,
|
|
1523
1552
|
},
|
|
1524
|
-
|
|
1525
|
-
)
|
|
1553
|
+
})
|
|
1526
1554
|
})
|
|
1527
1555
|
document.addEventListener('keyup', (event) => {
|
|
1528
1556
|
if (isInputTarget(event)) {
|
|
1529
1557
|
return
|
|
1530
1558
|
}
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
altKey: event.altKey,
|
|
1539
|
-
},
|
|
1559
|
+
postMessageToEditor({
|
|
1560
|
+
type: 'keyup',
|
|
1561
|
+
event: {
|
|
1562
|
+
key: event.key,
|
|
1563
|
+
metaKey: event.metaKey,
|
|
1564
|
+
shiftKey: event.shiftKey,
|
|
1565
|
+
altKey: event.altKey,
|
|
1540
1566
|
},
|
|
1541
|
-
|
|
1542
|
-
)
|
|
1567
|
+
})
|
|
1543
1568
|
})
|
|
1544
1569
|
document.addEventListener('keypress', (event) => {
|
|
1545
1570
|
if (isInputTarget(event)) {
|
|
1546
1571
|
return
|
|
1547
1572
|
}
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
altKey: event.altKey,
|
|
1556
|
-
},
|
|
1573
|
+
postMessageToEditor({
|
|
1574
|
+
type: 'keypress',
|
|
1575
|
+
event: {
|
|
1576
|
+
key: event.key,
|
|
1577
|
+
metaKey: event.metaKey,
|
|
1578
|
+
shiftKey: event.shiftKey,
|
|
1579
|
+
altKey: event.altKey,
|
|
1557
1580
|
},
|
|
1558
|
-
|
|
1559
|
-
)
|
|
1581
|
+
})
|
|
1560
1582
|
})
|
|
1561
1583
|
|
|
1562
1584
|
dataSignal.subscribe((data) => {
|
|
1563
1585
|
if (component && components && packageComponents && data) {
|
|
1564
1586
|
try {
|
|
1565
|
-
|
|
1587
|
+
postMessageToEditor({ type: 'data', data })
|
|
1566
1588
|
} catch {
|
|
1567
1589
|
// If we're unable to send the data, let's try to JSON serialize it
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
)
|
|
1590
|
+
postMessageToEditor({
|
|
1591
|
+
type: 'data',
|
|
1592
|
+
data: JSON.parse(JSON.stringify(data)),
|
|
1593
|
+
})
|
|
1572
1594
|
}
|
|
1573
1595
|
}
|
|
1574
1596
|
})
|
|
@@ -1614,24 +1636,18 @@ export const createRoot = (
|
|
|
1614
1636
|
) {
|
|
1615
1637
|
const selectionRect = getRectData(getDOMNodeFromNodeId(selectedNodeId))
|
|
1616
1638
|
if (!fastDeepEqual(prevSelectionRect, selectionRect)) {
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
},
|
|
1622
|
-
'*',
|
|
1623
|
-
)
|
|
1639
|
+
postMessageToEditor({
|
|
1640
|
+
type: 'selectionRect',
|
|
1641
|
+
rect: selectionRect,
|
|
1642
|
+
})
|
|
1624
1643
|
}
|
|
1625
1644
|
|
|
1626
1645
|
const highlightRect = getRectData(getDOMNodeFromNodeId(highlightedNodeId))
|
|
1627
1646
|
if (!fastDeepEqual(prevHighlightedRect, highlightRect)) {
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
},
|
|
1633
|
-
'*',
|
|
1634
|
-
)
|
|
1647
|
+
postMessageToEditor({
|
|
1648
|
+
type: 'highlightRect',
|
|
1649
|
+
rect: highlightRect,
|
|
1650
|
+
})
|
|
1635
1651
|
}
|
|
1636
1652
|
|
|
1637
1653
|
requestAnimationFrame(() => syncOverlayRects(selectionRect, highlightRect))
|
|
@@ -1755,3 +1771,91 @@ const insertTheme = (parent: HTMLElement, theme: Theme | OldTheme) => {
|
|
|
1755
1771
|
})
|
|
1756
1772
|
parent.appendChild(styleElem)
|
|
1757
1773
|
}
|
|
1774
|
+
|
|
1775
|
+
type PostMessageType =
|
|
1776
|
+
| {
|
|
1777
|
+
type: 'textComputedStyle'
|
|
1778
|
+
computedStyle: Record<string, string>
|
|
1779
|
+
}
|
|
1780
|
+
| {
|
|
1781
|
+
type: 'selection'
|
|
1782
|
+
selectedNodeId: string | null
|
|
1783
|
+
}
|
|
1784
|
+
| {
|
|
1785
|
+
type: 'highlight'
|
|
1786
|
+
highlightedNodeId: string | null
|
|
1787
|
+
}
|
|
1788
|
+
| {
|
|
1789
|
+
type: 'navigate'
|
|
1790
|
+
name: string
|
|
1791
|
+
}
|
|
1792
|
+
| {
|
|
1793
|
+
type: 'documentScrollSize'
|
|
1794
|
+
scrollHeight: number
|
|
1795
|
+
scrollWidth: number
|
|
1796
|
+
}
|
|
1797
|
+
| {
|
|
1798
|
+
type: 'nodeMoved'
|
|
1799
|
+
copy: boolean
|
|
1800
|
+
parent?: string | null
|
|
1801
|
+
index?: number
|
|
1802
|
+
}
|
|
1803
|
+
| {
|
|
1804
|
+
type: 'computedStyle'
|
|
1805
|
+
computedStyle: Record<string, string>
|
|
1806
|
+
}
|
|
1807
|
+
| {
|
|
1808
|
+
type: 'style'
|
|
1809
|
+
time: string
|
|
1810
|
+
}
|
|
1811
|
+
| {
|
|
1812
|
+
type: 'component event'
|
|
1813
|
+
event: any
|
|
1814
|
+
time: string
|
|
1815
|
+
data: any
|
|
1816
|
+
}
|
|
1817
|
+
| {
|
|
1818
|
+
type: 'keydown'
|
|
1819
|
+
event: {
|
|
1820
|
+
key: string
|
|
1821
|
+
metaKey: boolean
|
|
1822
|
+
shiftKey: boolean
|
|
1823
|
+
altKey: boolean
|
|
1824
|
+
}
|
|
1825
|
+
}
|
|
1826
|
+
| {
|
|
1827
|
+
type: 'keyup'
|
|
1828
|
+
event: {
|
|
1829
|
+
key: string
|
|
1830
|
+
metaKey: boolean
|
|
1831
|
+
shiftKey: boolean
|
|
1832
|
+
altKey: boolean
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1835
|
+
| {
|
|
1836
|
+
type: 'keypress'
|
|
1837
|
+
event: {
|
|
1838
|
+
key: string
|
|
1839
|
+
metaKey: boolean
|
|
1840
|
+
shiftKey: boolean
|
|
1841
|
+
altKey: boolean
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
| { type: 'data'; data: ComponentData }
|
|
1845
|
+
| {
|
|
1846
|
+
type: 'selectionRect'
|
|
1847
|
+
rect: ReturnType<typeof getRectData>
|
|
1848
|
+
}
|
|
1849
|
+
| {
|
|
1850
|
+
type: 'highlightRect'
|
|
1851
|
+
rect: ReturnType<typeof getRectData>
|
|
1852
|
+
}
|
|
1853
|
+
| {
|
|
1854
|
+
type: 'introspectionResult'
|
|
1855
|
+
data: any
|
|
1856
|
+
apiKey: string
|
|
1857
|
+
}
|
|
1858
|
+
|
|
1859
|
+
const postMessageToEditor = (message: PostMessageType) => {
|
|
1860
|
+
window.parent?.postMessage(message, '*')
|
|
1861
|
+
}
|