@nordcraft/runtime 1.0.74 → 1.0.76
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/README.md +1 -1
- package/dist/api/createAPI.d.ts +3 -2
- package/dist/api/createAPI.js.map +1 -1
- package/dist/components/createComponent.js +8 -8
- package/dist/components/createComponent.js.map +1 -1
- package/dist/components/createElement.js +2 -2
- package/dist/components/createElement.js.map +1 -1
- package/dist/components/createNode.js +4 -4
- package/dist/components/createNode.js.map +1 -1
- package/dist/components/renderComponent.js +4 -4
- package/dist/components/renderComponent.js.map +1 -1
- package/dist/context/subscribeToContext.js +2 -5
- package/dist/context/subscribeToContext.js.map +1 -1
- package/dist/custom-element/ToddleComponent.js +4 -4
- package/dist/custom-element/ToddleComponent.js.map +1 -1
- package/dist/custom-element.main.esm.js +15 -15
- package/dist/custom-element.main.esm.js.map +3 -3
- package/dist/editor/types.d.ts +4 -0
- package/dist/editor/types.js.map +1 -1
- package/dist/editor-preview.main.js +55 -39
- package/dist/editor-preview.main.js.map +1 -1
- package/dist/page.main.esm.js +3 -3
- package/dist/page.main.esm.js.map +3 -3
- package/dist/page.main.js +2 -2
- package/dist/page.main.js.map +1 -1
- package/dist/styles/CustomPropertyStyleSheet.d.ts +11 -10
- package/dist/styles/CustomPropertyStyleSheet.js.map +1 -1
- package/dist/utils/nodes.js +1 -1
- package/dist/utils/nodes.js.map +1 -1
- package/package.json +4 -4
- package/src/api/createAPI.ts +2 -1
- package/src/api/createAPIv2.ts +7 -7
- package/src/components/createComponent.ts +43 -37
- package/src/components/createElement.ts +2 -2
- package/src/components/createNode.ts +5 -5
- package/src/components/renderComponent.ts +4 -4
- package/src/context/subscribeToContext.ts +5 -5
- package/src/custom-element/ToddleComponent.ts +24 -21
- package/src/editor/types.ts +4 -0
- package/src/editor-preview.main.ts +79 -47
- package/src/page.main.ts +14 -12
- package/src/styles/CustomPropertyStyleSheet.ts +18 -14
- package/src/utils/nodes.ts +1 -1
|
@@ -453,7 +453,7 @@ export const createRoot = (
|
|
|
453
453
|
|
|
454
454
|
const node = getDOMNodeFromNodeId(selectedNodeId)
|
|
455
455
|
const element =
|
|
456
|
-
component?.nodes[node?.getAttribute('data-node-id') ?? '']
|
|
456
|
+
component?.nodes?.[node?.getAttribute('data-node-id') ?? '']
|
|
457
457
|
if (
|
|
458
458
|
node &&
|
|
459
459
|
element &&
|
|
@@ -544,7 +544,7 @@ export const createRoot = (
|
|
|
544
544
|
return false
|
|
545
545
|
}
|
|
546
546
|
const nodeId = getNodeId(component, id.split('.').slice(1))
|
|
547
|
-
const node = nodeId ? component?.nodes[nodeId] : undefined
|
|
547
|
+
const node = nodeId ? component?.nodes?.[nodeId] : undefined
|
|
548
548
|
if (!node) {
|
|
549
549
|
return false
|
|
550
550
|
}
|
|
@@ -562,7 +562,7 @@ export const createRoot = (
|
|
|
562
562
|
if (message.data.metaKey) {
|
|
563
563
|
// Figure out if the clicked element is a text element
|
|
564
564
|
// or if one of its descendants is a text element
|
|
565
|
-
const root = component.nodes
|
|
565
|
+
const root = component.nodes?.root
|
|
566
566
|
if (root && id) {
|
|
567
567
|
const nodeLookup = getNodeAndAncestors(component, root, id)
|
|
568
568
|
if (nodeLookup?.node.type === 'text') {
|
|
@@ -574,7 +574,7 @@ export const createRoot = (
|
|
|
574
574
|
const firstTextChild =
|
|
575
575
|
nodeLookup?.node.type === 'element'
|
|
576
576
|
? nodeLookup.node.children.find(
|
|
577
|
-
(c) => component?.nodes[c]?.type === 'text',
|
|
577
|
+
(c) => component?.nodes?.[c]?.type === 'text',
|
|
578
578
|
)
|
|
579
579
|
: undefined
|
|
580
580
|
if (firstTextChild) {
|
|
@@ -603,7 +603,7 @@ export const createRoot = (
|
|
|
603
603
|
mode === 'design'
|
|
604
604
|
) {
|
|
605
605
|
// Figure out if the clicked element is a component
|
|
606
|
-
const root = component.nodes
|
|
606
|
+
const root = component.nodes?.root
|
|
607
607
|
if (root) {
|
|
608
608
|
const nodeLookup = getNodeAndAncestors(component, root, id)
|
|
609
609
|
if (
|
|
@@ -659,7 +659,7 @@ export const createRoot = (
|
|
|
659
659
|
}
|
|
660
660
|
case 'introspect_qraphql_api': {
|
|
661
661
|
const { apiKey } = message.data
|
|
662
|
-
const api = component?.apis[apiKey]
|
|
662
|
+
const api = component?.apis?.[apiKey]
|
|
663
663
|
if (api && !isLegacyApi(api) && component) {
|
|
664
664
|
const formulaContext: FormulaContext = {
|
|
665
665
|
component,
|
|
@@ -737,7 +737,7 @@ export const createRoot = (
|
|
|
737
737
|
parent: parentDataId,
|
|
738
738
|
index: !isNaN(nextSiblingId)
|
|
739
739
|
? nextSiblingId
|
|
740
|
-
: component?.nodes[parentNodeId]?.children?.length,
|
|
740
|
+
: component?.nodes?.[parentNodeId]?.children?.length,
|
|
741
741
|
})
|
|
742
742
|
dragState = null
|
|
743
743
|
})
|
|
@@ -913,43 +913,75 @@ export const createRoot = (
|
|
|
913
913
|
})
|
|
914
914
|
break
|
|
915
915
|
case 'preview_style':
|
|
916
|
-
const { styles: previewStyleStyles, theme } = message.data
|
|
916
|
+
const { styles: previewStyleStyles, theme, resources } = message.data
|
|
917
917
|
cancelAnimationFrame(previewStyleAnimationFrame)
|
|
918
918
|
previewStyleAnimationFrame = requestAnimationFrame(() => {
|
|
919
|
+
// Allow for temporarily adding preview resources (e.g. fonts).
|
|
920
|
+
const resourceElements = Array.from(
|
|
921
|
+
document.head.querySelectorAll('[data-id="preview-resource"]'),
|
|
922
|
+
)
|
|
923
|
+
// Remove any resources that are no longer needed
|
|
924
|
+
resourceElements.forEach((el) => {
|
|
925
|
+
if (
|
|
926
|
+
!resources ||
|
|
927
|
+
resources.length === 0 ||
|
|
928
|
+
!resources.some((res) => res.href === el.getAttribute('href'))
|
|
929
|
+
) {
|
|
930
|
+
el.remove()
|
|
931
|
+
}
|
|
932
|
+
})
|
|
933
|
+
resources
|
|
934
|
+
?.filter(
|
|
935
|
+
(resource) =>
|
|
936
|
+
!resourceElements.some(
|
|
937
|
+
(el) => el.getAttribute('href') === resource.href,
|
|
938
|
+
),
|
|
939
|
+
)
|
|
940
|
+
.forEach((resource) => {
|
|
941
|
+
const resourceElement = document.createElement('link')
|
|
942
|
+
resourceElement.setAttribute('data-id', 'preview-resource')
|
|
943
|
+
resourceElement.rel = 'stylesheet'
|
|
944
|
+
resourceElement.href = resource.href
|
|
945
|
+
document.head.appendChild(resourceElement)
|
|
946
|
+
})
|
|
947
|
+
|
|
919
948
|
// Update or create a new style tag and set the given styles with important priority
|
|
920
|
-
let
|
|
949
|
+
let styleElement = document.head.querySelector(
|
|
921
950
|
'[data-id="selected-node-styles"]',
|
|
922
951
|
)
|
|
923
952
|
|
|
924
953
|
// Cleanup when null styles are sent
|
|
925
954
|
if (!previewStyleStyles) {
|
|
926
|
-
|
|
955
|
+
styleElement?.remove()
|
|
927
956
|
return
|
|
928
957
|
}
|
|
929
958
|
|
|
930
|
-
if (!
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
document.head.appendChild(
|
|
959
|
+
if (!styleElement) {
|
|
960
|
+
styleElement = document.createElement('style')
|
|
961
|
+
styleElement.setAttribute('data-id', 'selected-node-styles')
|
|
962
|
+
document.head.appendChild(styleElement)
|
|
934
963
|
}
|
|
935
964
|
|
|
936
965
|
// If style variant targets a pseudo-element, apply styles to it instead
|
|
937
966
|
let pseudoElement = ''
|
|
938
967
|
if (component && styleVariantSelection) {
|
|
939
|
-
const
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
968
|
+
const rootNode = component.nodes?.root
|
|
969
|
+
if (rootNode) {
|
|
970
|
+
const nodeLookup = getNodeAndAncestors(
|
|
971
|
+
component,
|
|
972
|
+
rootNode,
|
|
973
|
+
styleVariantSelection.nodeId,
|
|
974
|
+
)
|
|
944
975
|
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
976
|
+
if (
|
|
977
|
+
(nodeLookup?.node.type === 'element' ||
|
|
978
|
+
nodeLookup?.node.type === 'component') &&
|
|
979
|
+
nodeLookup.node.variants?.[
|
|
980
|
+
styleVariantSelection.styleVariantIndex
|
|
981
|
+
].pseudoElement
|
|
982
|
+
) {
|
|
983
|
+
pseudoElement = `::${nodeLookup.node.variants[styleVariantSelection.styleVariantIndex].pseudoElement}`
|
|
984
|
+
}
|
|
953
985
|
}
|
|
954
986
|
}
|
|
955
987
|
|
|
@@ -1003,12 +1035,12 @@ export const createRoot = (
|
|
|
1003
1035
|
getThemeEntries(theme.value, theme.key),
|
|
1004
1036
|
),
|
|
1005
1037
|
)
|
|
1006
|
-
|
|
1038
|
+
styleElement.innerHTML = cssBlocks.join('\n')
|
|
1007
1039
|
} else {
|
|
1008
1040
|
const previewStyles = Object.entries(previewStyleStyles)
|
|
1009
1041
|
.map(([key, value]) => `${key}: ${value} !important;`)
|
|
1010
1042
|
.join('\n')
|
|
1011
|
-
|
|
1043
|
+
styleElement.innerHTML = `[data-id="${selectedNodeId}"]${pseudoElement}, [data-id="${selectedNodeId}"] ~ [data-id^="${selectedNodeId}("]${pseudoElement} {
|
|
1012
1044
|
${previewStyles}
|
|
1013
1045
|
transition: none !important;
|
|
1014
1046
|
}`
|
|
@@ -1049,7 +1081,7 @@ export const createRoot = (
|
|
|
1049
1081
|
}
|
|
1050
1082
|
if (mode === 'design') {
|
|
1051
1083
|
if (selectedNodeId !== null) {
|
|
1052
|
-
const root = _component?.nodes
|
|
1084
|
+
const root = _component?.nodes?.root
|
|
1053
1085
|
if (root) {
|
|
1054
1086
|
const nodeLookup = getNodeAndAncestors(
|
|
1055
1087
|
_component,
|
|
@@ -1077,7 +1109,7 @@ export const createRoot = (
|
|
|
1077
1109
|
nodeId: selectedNodeId,
|
|
1078
1110
|
styleVariantIndex: variantIndex,
|
|
1079
1111
|
}
|
|
1080
|
-
const root = component?.nodes
|
|
1112
|
+
const root = component?.nodes?.root
|
|
1081
1113
|
if (root && component) {
|
|
1082
1114
|
const nodeLookup = getNodeAndAncestors(component, root, selectedNodeId)
|
|
1083
1115
|
if (nodeLookup) {
|
|
@@ -1158,10 +1190,10 @@ export const createRoot = (
|
|
|
1158
1190
|
if (
|
|
1159
1191
|
fastDeepEqual(ctx?.component.attributes, _component.attributes) === false
|
|
1160
1192
|
) {
|
|
1161
|
-
Attributes = mapObject(
|
|
1162
|
-
|
|
1163
|
-
testValue,
|
|
1164
|
-
|
|
1193
|
+
Attributes = mapObject(
|
|
1194
|
+
_component.attributes ?? {},
|
|
1195
|
+
([name, { testValue }]) => [name, testValue],
|
|
1196
|
+
)
|
|
1165
1197
|
}
|
|
1166
1198
|
if (
|
|
1167
1199
|
_component.route &&
|
|
@@ -1205,10 +1237,10 @@ export const createRoot = (
|
|
|
1205
1237
|
)
|
|
1206
1238
|
}
|
|
1207
1239
|
|
|
1208
|
-
Attributes = mapObject(
|
|
1209
|
-
|
|
1210
|
-
testValue,
|
|
1211
|
-
|
|
1240
|
+
Attributes = mapObject(
|
|
1241
|
+
_component.attributes ?? {},
|
|
1242
|
+
([name, { testValue }]) => [name, testValue],
|
|
1243
|
+
)
|
|
1212
1244
|
}
|
|
1213
1245
|
if (
|
|
1214
1246
|
fastDeepEqual(
|
|
@@ -1253,7 +1285,7 @@ export const createRoot = (
|
|
|
1253
1285
|
const formulaContext: FormulaContext = {
|
|
1254
1286
|
data: {
|
|
1255
1287
|
Attributes: mapObject(
|
|
1256
|
-
providerComponent.attributes,
|
|
1288
|
+
providerComponent.attributes ?? {},
|
|
1257
1289
|
([name, attr]) => [name, attr.testValue],
|
|
1258
1290
|
),
|
|
1259
1291
|
// Recursively resolve contexts providers before their children to build up the fake context tree in preview mode
|
|
@@ -1287,7 +1319,7 @@ export const createRoot = (
|
|
|
1287
1319
|
}
|
|
1288
1320
|
}
|
|
1289
1321
|
formulaContext.data.Variables = mapObject(
|
|
1290
|
-
providerComponent.variables,
|
|
1322
|
+
providerComponent.variables ?? {},
|
|
1291
1323
|
([name, variable]) => [
|
|
1292
1324
|
name,
|
|
1293
1325
|
applyFormula(variable.initialValue, formulaContext),
|
|
@@ -1321,7 +1353,7 @@ export const createRoot = (
|
|
|
1321
1353
|
fastDeepEqual(_component.variables, ctx?.component.variables) === false
|
|
1322
1354
|
) {
|
|
1323
1355
|
Variables = mapObject(
|
|
1324
|
-
_component.variables,
|
|
1356
|
+
_component.variables ?? {},
|
|
1325
1357
|
([name, { initialValue }]) => [
|
|
1326
1358
|
name,
|
|
1327
1359
|
applyFormula(initialValue, {
|
|
@@ -1359,7 +1391,7 @@ export const createRoot = (
|
|
|
1359
1391
|
for (const api in newCtx.component.apis) {
|
|
1360
1392
|
// check if the api has changed (ignoring onCompleted and onFailed).
|
|
1361
1393
|
const apiInstance = newCtx.component.apis[api]
|
|
1362
|
-
const previousApiInstance = ctx?.component.apis[api]
|
|
1394
|
+
const previousApiInstance = ctx?.component.apis?.[api]
|
|
1363
1395
|
if (isLegacyApi(apiInstance)) {
|
|
1364
1396
|
if (
|
|
1365
1397
|
fastDeepEqual(
|
|
@@ -1376,7 +1408,7 @@ export const createRoot = (
|
|
|
1376
1408
|
Apis: omitKeys(data.Apis ?? {}, [
|
|
1377
1409
|
...Object.keys(data.Apis ?? {}).filter(
|
|
1378
1410
|
// remove any data from an api that is not part of the component
|
|
1379
|
-
(key) => !newCtx.component.apis[key],
|
|
1411
|
+
(key) => !newCtx.component.apis?.[key],
|
|
1380
1412
|
),
|
|
1381
1413
|
api,
|
|
1382
1414
|
]),
|
|
@@ -1427,7 +1459,7 @@ export const createRoot = (
|
|
|
1427
1459
|
parentElement: domNode,
|
|
1428
1460
|
instance: { [newCtx.component.name]: 'root' },
|
|
1429
1461
|
})
|
|
1430
|
-
newCtx.component.onLoad?.actions
|
|
1462
|
+
newCtx.component.onLoad?.actions?.forEach((action) => {
|
|
1431
1463
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
1432
1464
|
handleAction(action, dataSignal.get(), newCtx)
|
|
1433
1465
|
})
|
|
@@ -1576,7 +1608,7 @@ export const createRoot = (
|
|
|
1576
1608
|
const updateConditionalElements = () => {
|
|
1577
1609
|
const displayedNodes: string[] = []
|
|
1578
1610
|
if (selectedNodeId && component) {
|
|
1579
|
-
const root = component.nodes
|
|
1611
|
+
const root = component.nodes?.root
|
|
1580
1612
|
if (root) {
|
|
1581
1613
|
const nodeLookup = getNodeAndAncestors(component, root, selectedNodeId)
|
|
1582
1614
|
if (isNodeOrAncestorConditional(nodeLookup)) {
|
|
@@ -1692,7 +1724,7 @@ function getNodeId(component: Component, path: string[]) {
|
|
|
1692
1724
|
if (nextChild === undefined || currentId === undefined) {
|
|
1693
1725
|
return currentId ?? null
|
|
1694
1726
|
}
|
|
1695
|
-
const currentNode = component.nodes[currentId]
|
|
1727
|
+
const currentNode = component.nodes?.[currentId]
|
|
1696
1728
|
if (!currentNode?.children) {
|
|
1697
1729
|
return null
|
|
1698
1730
|
}
|
package/src/page.main.ts
CHANGED
|
@@ -162,7 +162,7 @@ export const createRoot = (domNode: HTMLElement) => {
|
|
|
162
162
|
...window.toddle.pageState,
|
|
163
163
|
// Re-initialize variables since some of them might rely on client-side
|
|
164
164
|
// state (e.g. localStorage, sensors etc.)
|
|
165
|
-
Variables: mapObject(component.variables, ([name, variable]) => [
|
|
165
|
+
Variables: mapObject(component.variables ?? {}, ([name, variable]) => [
|
|
166
166
|
name,
|
|
167
167
|
applyFormula(variable.initialValue, {
|
|
168
168
|
data: window.toddle.pageState,
|
|
@@ -213,17 +213,19 @@ export const createRoot = (domNode: HTMLElement) => {
|
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
// Note: this function must run procedurally to ensure apis (which are in correct order) can reference each other
|
|
216
|
-
sortApiObjects(Object.entries(component.apis)).forEach(
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
216
|
+
sortApiObjects(Object.entries(component.apis ?? {})).forEach(
|
|
217
|
+
([name, api]) => {
|
|
218
|
+
if (isLegacyApi(api)) {
|
|
219
|
+
ctx.apis[name] = createLegacyAPI(api, ctx)
|
|
220
|
+
} else {
|
|
221
|
+
ctx.apis[name] = createAPI({
|
|
222
|
+
apiRequest: api,
|
|
223
|
+
ctx,
|
|
224
|
+
componentData: dataSignal.get(),
|
|
225
|
+
})
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
)
|
|
227
229
|
// Trigger actions for all APIs after all of them are created.
|
|
228
230
|
Object.values(ctx.apis)
|
|
229
231
|
.filter(isContextApiV2)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { MediaQuery } from '@nordcraft/core/dist/component/component.types'
|
|
2
|
+
import type { Nullable } from '@nordcraft/core/dist/types'
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* CustomPropertyStyleSheet is a utility class that manages CSS custom properties
|
|
@@ -15,7 +16,10 @@ export class CustomPropertyStyleSheet {
|
|
|
15
16
|
// Selector to rule index mapping
|
|
16
17
|
private ruleMap: Map<string, CSSStyleRule | CSSNestedDeclarations> | undefined
|
|
17
18
|
|
|
18
|
-
constructor(
|
|
19
|
+
constructor(
|
|
20
|
+
root: Document | ShadowRoot,
|
|
21
|
+
styleSheet?: Nullable<CSSStyleSheet>,
|
|
22
|
+
) {
|
|
19
23
|
if (styleSheet) {
|
|
20
24
|
this.styleSheet = styleSheet
|
|
21
25
|
} else {
|
|
@@ -30,10 +34,10 @@ export class CustomPropertyStyleSheet {
|
|
|
30
34
|
public registerProperty(
|
|
31
35
|
selector: string,
|
|
32
36
|
name: string,
|
|
33
|
-
options?: {
|
|
34
|
-
mediaQuery?: MediaQuery
|
|
35
|
-
startingStyle?: boolean
|
|
36
|
-
}
|
|
37
|
+
options?: Nullable<{
|
|
38
|
+
mediaQuery?: Nullable<MediaQuery>
|
|
39
|
+
startingStyle?: Nullable<boolean>
|
|
40
|
+
}>,
|
|
37
41
|
): (newValue: string) => void {
|
|
38
42
|
this.ruleMap ??= this.hydrateFromBase()
|
|
39
43
|
const fullSelector = CustomPropertyStyleSheet.getFullSelector(
|
|
@@ -69,11 +73,11 @@ export class CustomPropertyStyleSheet {
|
|
|
69
73
|
public unregisterProperty(
|
|
70
74
|
selector: string,
|
|
71
75
|
name: string,
|
|
72
|
-
options?: {
|
|
73
|
-
mediaQuery?: MediaQuery
|
|
74
|
-
startingStyle?: boolean
|
|
75
|
-
deepClean?: boolean
|
|
76
|
-
}
|
|
76
|
+
options?: Nullable<{
|
|
77
|
+
mediaQuery?: Nullable<MediaQuery>
|
|
78
|
+
startingStyle?: Nullable<boolean>
|
|
79
|
+
deepClean?: Nullable<boolean>
|
|
80
|
+
}>,
|
|
77
81
|
): void {
|
|
78
82
|
if (!this.ruleMap) {
|
|
79
83
|
return
|
|
@@ -161,10 +165,10 @@ export class CustomPropertyStyleSheet {
|
|
|
161
165
|
|
|
162
166
|
private static getFullSelector(
|
|
163
167
|
selector: string,
|
|
164
|
-
options?: {
|
|
165
|
-
mediaQuery?: MediaQuery
|
|
166
|
-
startingStyle?: boolean
|
|
167
|
-
}
|
|
168
|
+
options?: Nullable<{
|
|
169
|
+
mediaQuery?: Nullable<MediaQuery>
|
|
170
|
+
startingStyle?: Nullable<boolean>
|
|
171
|
+
}>,
|
|
168
172
|
) {
|
|
169
173
|
let result =
|
|
170
174
|
selector + (options?.startingStyle ? ' { @starting-style { }}' : ' { }')
|
package/src/utils/nodes.ts
CHANGED