@webiny/website-builder-sdk 6.3.0 → 6.4.0-beta.1
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/BindingsApi.js +29 -36
- package/BindingsApi.js.map +1 -1
- package/BindingsProcessor.js +34 -43
- package/BindingsProcessor.js.map +1 -1
- package/BindingsProcessor.test.js +82 -78
- package/BindingsProcessor.test.js.map +1 -1
- package/BindingsResolver.js +92 -119
- package/BindingsResolver.js.map +1 -1
- package/BindingsResolver.test.js +399 -363
- package/BindingsResolver.test.js.map +1 -1
- package/ComponentInputTraverser.js +28 -49
- package/ComponentInputTraverser.js.map +1 -1
- package/ComponentManifestToAstConverter.js +20 -21
- package/ComponentManifestToAstConverter.js.map +1 -1
- package/ComponentRegistry.js +26 -45
- package/ComponentRegistry.js.map +1 -1
- package/ComponentResolver.js +25 -29
- package/ComponentResolver.js.map +1 -1
- package/ConstraintEvaluator.js +246 -353
- package/ConstraintEvaluator.js.map +1 -1
- package/ConstraintEvaluator.test.js +1616 -1438
- package/ConstraintEvaluator.test.js.map +1 -1
- package/ContentSdk.js +83 -90
- package/ContentSdk.js.map +1 -1
- package/DocumentStore.js +47 -59
- package/DocumentStore.js.map +1 -1
- package/DocumentStoreManager.js +17 -16
- package/DocumentStoreManager.js.map +1 -1
- package/EditingSdk.js +87 -121
- package/EditingSdk.js.map +1 -1
- package/ElementFactory.js +126 -174
- package/ElementFactory.js.map +1 -1
- package/ElementFactory.test.js +234 -263
- package/ElementFactory.test.js.map +1 -1
- package/Environment.js +18 -19
- package/Environment.js.map +1 -1
- package/FunctionConverter.js +8 -7
- package/FunctionConverter.js.map +1 -1
- package/HashObject.js +11 -26
- package/HashObject.js.map +1 -1
- package/HotkeyManager.js +40 -47
- package/HotkeyManager.js.map +1 -1
- package/IBindingsUpdater.js +0 -3
- package/IRedirects.js +0 -3
- package/InheritanceProcessor.js +99 -139
- package/InheritanceProcessor.js.map +1 -1
- package/InheritanceProcessor.test.js +178 -179
- package/InheritanceProcessor.test.js.map +1 -1
- package/InheritedValueResolver.js +15 -20
- package/InheritedValueResolver.js.map +1 -1
- package/InputBindingsProcessor.js +187 -307
- package/InputBindingsProcessor.js.map +1 -1
- package/InputsBindingsProcessor.test.js +334 -315
- package/InputsBindingsProcessor.test.js.map +1 -1
- package/InputsUpdater.js +23 -26
- package/InputsUpdater.js.map +1 -1
- package/LiveSdk.js +12 -13
- package/LiveSdk.js.map +1 -1
- package/Logger.js +9 -8
- package/Logger.js.map +1 -1
- package/MouseTracker.js +77 -83
- package/MouseTracker.js.map +1 -1
- package/NullSdk.js +22 -21
- package/NullSdk.js.map +1 -1
- package/PreviewDocument.js +27 -30
- package/PreviewDocument.js.map +1 -1
- package/PreviewSdk.js +16 -17
- package/PreviewSdk.js.map +1 -1
- package/PreviewViewport.js +51 -63
- package/PreviewViewport.js.map +1 -1
- package/ResizeObserver.js +24 -31
- package/ResizeObserver.js.map +1 -1
- package/StylesBindingsProcessor.js +40 -79
- package/StylesBindingsProcessor.js.map +1 -1
- package/StylesUpdater.js +20 -25
- package/StylesUpdater.js.map +1 -1
- package/Theme.js +28 -25
- package/Theme.js.map +1 -1
- package/ViewportManager.js +89 -101
- package/ViewportManager.js.map +1 -1
- package/constants.js +7 -6
- package/constants.js.map +1 -1
- package/createElement.js +5 -6
- package/createElement.js.map +1 -1
- package/createInput.js +85 -143
- package/createInput.js.map +1 -1
- package/createTheme.js +2 -3
- package/createTheme.js.map +1 -1
- package/dataProviders/ApiClient.js +40 -49
- package/dataProviders/ApiClient.js.map +1 -1
- package/dataProviders/DefaultDataProvider.js +56 -58
- package/dataProviders/DefaultDataProvider.js.map +1 -1
- package/dataProviders/GET_PAGE_BY_ID.js +2 -1
- package/dataProviders/GET_PAGE_BY_ID.js.map +1 -1
- package/dataProviders/GET_PAGE_BY_PATH.js +2 -1
- package/dataProviders/GET_PAGE_BY_PATH.js.map +1 -1
- package/dataProviders/LIST_PUBLISHED_PAGES.js +2 -1
- package/dataProviders/LIST_PUBLISHED_PAGES.js.map +1 -1
- package/dataProviders/NullDataProvider.js +21 -20
- package/dataProviders/NullDataProvider.js.map +1 -1
- package/dataProviders/RedirectsProvider.js +24 -27
- package/dataProviders/RedirectsProvider.js.map +1 -1
- package/defaultBreakpoints.js +23 -22
- package/defaultBreakpoints.js.map +1 -1
- package/documentOperations/$addElementReferenceToParent.js +29 -32
- package/documentOperations/$addElementReferenceToParent.js.map +1 -1
- package/documentOperations/AddElement.js +8 -7
- package/documentOperations/AddElement.js.map +1 -1
- package/documentOperations/AddToParent.js +14 -13
- package/documentOperations/AddToParent.js.map +1 -1
- package/documentOperations/IDocumentOperation.js +0 -3
- package/documentOperations/RemoveElement.js +9 -15
- package/documentOperations/RemoveElement.js.map +1 -1
- package/documentOperations/SetGlobalInputBinding.js +23 -22
- package/documentOperations/SetGlobalInputBinding.js.map +1 -1
- package/documentOperations/SetGlobalStyleBinding.js +23 -23
- package/documentOperations/SetGlobalStyleBinding.js.map +1 -1
- package/documentOperations/SetInputBindingOverride.js +30 -29
- package/documentOperations/SetInputBindingOverride.js.map +1 -1
- package/documentOperations/SetStyleBindingOverride.js +30 -31
- package/documentOperations/SetStyleBindingOverride.js.map +1 -1
- package/documentOperations/index.js +9 -8
- package/documentOperations/index.js.map +1 -1
- package/findMatchingAstNode.js +11 -13
- package/findMatchingAstNode.js.map +1 -1
- package/generateElementId.js +2 -1
- package/generateElementId.js.map +1 -1
- package/headersProvider.js +4 -3
- package/headersProvider.js.map +1 -1
- package/index.js +0 -2
- package/jsonPatch.js +5 -9
- package/jsonPatch.js.map +1 -1
- package/messages.js +12 -11
- package/messages.js.map +1 -1
- package/messenger/MessageOrigin.js +12 -11
- package/messenger/MessageOrigin.js.map +1 -1
- package/messenger/Messenger.js +58 -69
- package/messenger/Messenger.js.map +1 -1
- package/messenger/index.js +0 -2
- package/package.json +5 -5
- package/registerComponentGroup.js +5 -6
- package/registerComponentGroup.js.map +1 -1
- package/types/ShorthandCssProperties.js +0 -3
- package/types/WebsiteBuilderTheme.js +0 -3
- package/types.d.ts +3 -0
- package/types.js +0 -3
- package/IBindingsUpdater.js.map +0 -1
- package/IRedirects.js.map +0 -1
- package/documentOperations/IDocumentOperation.js.map +0 -1
- package/index.js.map +0 -1
- package/messenger/index.js.map +0 -1
- package/types/ShorthandCssProperties.js.map +0 -1
- package/types/WebsiteBuilderTheme.js.map +0 -1
- package/types.js.map +0 -1
package/ConstraintEvaluator.js
CHANGED
|
@@ -1,395 +1,288 @@
|
|
|
1
1
|
class ConstraintBlockError extends Error {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
constructor(message){
|
|
3
|
+
super(message);
|
|
4
|
+
}
|
|
5
5
|
}
|
|
6
6
|
function block(message) {
|
|
7
|
-
|
|
7
|
+
throw new ConstraintBlockError(message);
|
|
8
8
|
}
|
|
9
|
-
/**
|
|
10
|
-
* Build a regex pattern from a slot path, replacing the numeric index with \d+.
|
|
11
|
-
* E.g., "steps/2/step" → /^steps\/\d+\/step$/
|
|
12
|
-
* Returns undefined if the slot has no index segment.
|
|
13
|
-
*/
|
|
14
9
|
function buildSlotPattern(slot) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
return
|
|
18
|
-
}
|
|
19
|
-
return new RegExp("^" + slot.replace(/\/\d+\//, "/\\d+/") + "$");
|
|
10
|
+
const match = slot.match(/\/(\d+)\//);
|
|
11
|
+
if (!match) return;
|
|
12
|
+
return new RegExp("^" + slot.replace(/\/\d+\//, "/\\d+/") + "$");
|
|
20
13
|
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Find the actual index and sibling count for an element in its parent's bindings.
|
|
24
|
-
* Instead of trusting element.parent.slot (which may be stale after reordering),
|
|
25
|
-
* we scan the parent's binding keys to find which slot holds this element's ID.
|
|
26
|
-
* Returns { index, count } or undefined if not in a list slot.
|
|
27
|
-
*/
|
|
28
14
|
function findChildPosition(element, document) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (directBinding && Array.isArray(directBinding.static)) {
|
|
43
|
-
const index = directBinding.static.indexOf(element.id);
|
|
44
|
-
if (index !== -1) {
|
|
45
|
-
return {
|
|
46
|
-
index,
|
|
47
|
-
count: directBinding.static.length
|
|
48
|
-
};
|
|
49
|
-
}
|
|
15
|
+
if (!element.parent?.id || !element.parent.slot) return;
|
|
16
|
+
const inputs = document.bindings[element.parent.id]?.inputs;
|
|
17
|
+
if (!inputs) return;
|
|
18
|
+
const slotName = element.parent.slot;
|
|
19
|
+
if (!/\/\d+\//.test(slotName)) {
|
|
20
|
+
const directBinding = inputs[slotName];
|
|
21
|
+
if (directBinding && Array.isArray(directBinding.static)) {
|
|
22
|
+
const index = directBinding.static.indexOf(element.id);
|
|
23
|
+
if (-1 !== index) return {
|
|
24
|
+
index,
|
|
25
|
+
count: directBinding.static.length
|
|
26
|
+
};
|
|
27
|
+
}
|
|
50
28
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
for (const key in inputs) {
|
|
60
|
-
if (pattern.test(key)) {
|
|
61
|
-
const m = key.match(/\/(\d+)\//);
|
|
62
|
-
if (m) {
|
|
63
|
-
siblingKeys.push({
|
|
64
|
-
key,
|
|
65
|
-
idx: parseInt(m[1], 10)
|
|
29
|
+
const pattern = buildSlotPattern(slotName);
|
|
30
|
+
if (!pattern) return;
|
|
31
|
+
const siblingKeys = [];
|
|
32
|
+
for(const key in inputs)if (pattern.test(key)) {
|
|
33
|
+
const m = key.match(/\/(\d+)\//);
|
|
34
|
+
if (m) siblingKeys.push({
|
|
35
|
+
key,
|
|
36
|
+
idx: parseInt(m[1], 10)
|
|
66
37
|
});
|
|
67
|
-
}
|
|
68
38
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (position === -1) {
|
|
81
|
-
return undefined;
|
|
82
|
-
}
|
|
83
|
-
return {
|
|
84
|
-
index: position,
|
|
85
|
-
count: siblingKeys.length
|
|
86
|
-
};
|
|
39
|
+
siblingKeys.sort((a, b)=>a.idx - b.idx);
|
|
40
|
+
const position = siblingKeys.findIndex(({ key })=>{
|
|
41
|
+
const val = inputs[key]?.static;
|
|
42
|
+
if (Array.isArray(val)) return val.includes(element.id);
|
|
43
|
+
return val === element.id;
|
|
44
|
+
});
|
|
45
|
+
if (-1 === position) return;
|
|
46
|
+
return {
|
|
47
|
+
index: position,
|
|
48
|
+
count: siblingKeys.length
|
|
49
|
+
};
|
|
87
50
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
return
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
},
|
|
118
|
-
isFirstChild() {
|
|
119
|
-
const pos = findChildPosition(element, document);
|
|
120
|
-
return pos !== undefined && pos.index === 0;
|
|
121
|
-
}
|
|
122
|
-
};
|
|
51
|
+
function buildElementContext(element, components, document) {
|
|
52
|
+
const manifest = components[element.component.name];
|
|
53
|
+
if (!manifest) return;
|
|
54
|
+
return {
|
|
55
|
+
name: element.component.name,
|
|
56
|
+
tags: manifest.tags ?? [],
|
|
57
|
+
getParent () {
|
|
58
|
+
if (!element.parent?.id) return;
|
|
59
|
+
const parentEl = document.elements[element.parent.id];
|
|
60
|
+
if (!parentEl) return;
|
|
61
|
+
return buildElementContext(parentEl, components, document);
|
|
62
|
+
},
|
|
63
|
+
childIndex () {
|
|
64
|
+
const pos = findChildPosition(element, document);
|
|
65
|
+
return pos ? pos.index : -1;
|
|
66
|
+
},
|
|
67
|
+
childCount () {
|
|
68
|
+
const pos = findChildPosition(element, document);
|
|
69
|
+
return pos ? pos.count : -1;
|
|
70
|
+
},
|
|
71
|
+
isLastChild () {
|
|
72
|
+
const pos = findChildPosition(element, document);
|
|
73
|
+
return void 0 !== pos && pos.index === pos.count - 1;
|
|
74
|
+
},
|
|
75
|
+
isFirstChild () {
|
|
76
|
+
const pos = findChildPosition(element, document);
|
|
77
|
+
return void 0 !== pos && 0 === pos.index;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
123
80
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
if (current.parent?.id) {
|
|
136
|
-
current = document.elements[current.parent.id];
|
|
137
|
-
} else {
|
|
138
|
-
break;
|
|
81
|
+
function buildAncestors(parentElement, components, document) {
|
|
82
|
+
const ancestors = [];
|
|
83
|
+
let current = parentElement;
|
|
84
|
+
while(current){
|
|
85
|
+
const manifest = components[current.component.name];
|
|
86
|
+
if (manifest) ancestors.push({
|
|
87
|
+
element: current,
|
|
88
|
+
manifest
|
|
89
|
+
});
|
|
90
|
+
if (current.parent?.id) current = document.elements[current.parent.id];
|
|
91
|
+
else break;
|
|
139
92
|
}
|
|
140
|
-
|
|
141
|
-
return ancestors;
|
|
93
|
+
return ancestors;
|
|
142
94
|
}
|
|
143
95
|
function countInstances(document, componentName) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
count++;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
return count;
|
|
96
|
+
let count = 0;
|
|
97
|
+
for(const id in document.elements)if (document.elements[id].component.name === componentName) count++;
|
|
98
|
+
return count;
|
|
151
99
|
}
|
|
152
100
|
function hasDescendantWithTag(document, components, elementId, tag) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
if (!isDescendant) {
|
|
169
|
-
continue;
|
|
170
|
-
}
|
|
171
|
-
const elManifest = components[el.component.name];
|
|
172
|
-
if (elManifest?.tags?.includes(tag)) {
|
|
173
|
-
return true;
|
|
101
|
+
for(const id in document.elements){
|
|
102
|
+
const el = document.elements[id];
|
|
103
|
+
if (id === elementId) continue;
|
|
104
|
+
let current = el.parent?.id ? document.elements[el.parent.id] : void 0;
|
|
105
|
+
let isDescendant = false;
|
|
106
|
+
while(current){
|
|
107
|
+
if (current.id === elementId) {
|
|
108
|
+
isDescendant = true;
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
current = current.parent?.id ? document.elements[current.parent.id] : void 0;
|
|
112
|
+
}
|
|
113
|
+
if (!isDescendant) continue;
|
|
114
|
+
const elManifest = components[el.component.name];
|
|
115
|
+
if (elManifest?.tags?.includes(tag)) return true;
|
|
174
116
|
}
|
|
175
|
-
|
|
176
|
-
return false;
|
|
117
|
+
return false;
|
|
177
118
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
componentName
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
document,
|
|
184
|
-
components
|
|
185
|
-
} = params;
|
|
186
|
-
const componentManifest = components[componentName];
|
|
187
|
-
if (!componentManifest) {
|
|
188
|
-
return {
|
|
189
|
-
allowed: true
|
|
119
|
+
function evaluateConstraints(params) {
|
|
120
|
+
const { componentName, parentId, slot, document, components } = params;
|
|
121
|
+
const componentManifest = components[componentName];
|
|
122
|
+
if (!componentManifest) return {
|
|
123
|
+
allowed: true
|
|
190
124
|
};
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
return {
|
|
195
|
-
allowed: true
|
|
125
|
+
const parentElement = document.elements[parentId];
|
|
126
|
+
if (!parentElement) return {
|
|
127
|
+
allowed: true
|
|
196
128
|
};
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
return {
|
|
201
|
-
allowed: true
|
|
129
|
+
const parentCtx = buildElementContext(parentElement, components, document);
|
|
130
|
+
if (!parentCtx) return {
|
|
131
|
+
allowed: true
|
|
202
132
|
};
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
// Evaluate the placed component's own constraints.
|
|
255
|
-
if (componentManifest.constraints) {
|
|
256
|
-
for (const constraint of componentManifest.constraints) {
|
|
257
|
-
const violation = runConstraint(constraint, `Cannot place ${componentManifest.label} here.`);
|
|
258
|
-
if (violation) {
|
|
259
|
-
return {
|
|
260
|
-
allowed: false,
|
|
261
|
-
violation
|
|
133
|
+
const ancestors = buildAncestors(parentElement, components, document);
|
|
134
|
+
const parentInputs = document.bindings[parentElement.id]?.inputs ?? {};
|
|
135
|
+
const ctx = {
|
|
136
|
+
component: {
|
|
137
|
+
name: componentManifest.name,
|
|
138
|
+
tags: componentManifest.tags ?? [],
|
|
139
|
+
getParent: ()=>parentCtx,
|
|
140
|
+
childIndex: ()=>-1,
|
|
141
|
+
childCount: ()=>-1,
|
|
142
|
+
isLastChild: ()=>false,
|
|
143
|
+
isFirstChild: ()=>false
|
|
144
|
+
},
|
|
145
|
+
parent: parentCtx,
|
|
146
|
+
slot,
|
|
147
|
+
isChildOf: (name)=>parentElement.component.name === name,
|
|
148
|
+
isDescendantOf: (name)=>ancestors.some((a)=>a.manifest.name === name),
|
|
149
|
+
getAncestor: (name)=>{
|
|
150
|
+
const found = ancestors.find((a)=>a.manifest.name === name);
|
|
151
|
+
return found ? buildElementContext(found.element, components, document) : void 0;
|
|
152
|
+
},
|
|
153
|
+
hasTag: (tag)=>componentManifest.tags?.includes(tag) ?? false,
|
|
154
|
+
slotChildCount: ()=>{
|
|
155
|
+
const items = parentInputs[slot]?.static;
|
|
156
|
+
return Array.isArray(items) ? items.length : 0;
|
|
157
|
+
},
|
|
158
|
+
countInstances: (name)=>countInstances(document, name),
|
|
159
|
+
hasDescendantWithTag: ()=>false,
|
|
160
|
+
getAncestorInputs: ()=>void 0,
|
|
161
|
+
getElementInputs: ()=>({}),
|
|
162
|
+
log: (...args)=>console.log(...args),
|
|
163
|
+
block: block
|
|
164
|
+
};
|
|
165
|
+
const runConstraint = (constraint, fallbackMessage)=>{
|
|
166
|
+
try {
|
|
167
|
+
constraint(ctx);
|
|
168
|
+
} catch (err) {
|
|
169
|
+
if (err instanceof ConstraintBlockError) return {
|
|
170
|
+
message: err.message
|
|
171
|
+
};
|
|
172
|
+
return {
|
|
173
|
+
message: err instanceof Error && err.message ? err.message : fallbackMessage
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
if (componentManifest.constraints) for (const constraint of componentManifest.constraints){
|
|
178
|
+
const violation = runConstraint(constraint, `Cannot place ${componentManifest.label} here.`);
|
|
179
|
+
if (violation) return {
|
|
180
|
+
allowed: false,
|
|
181
|
+
violation
|
|
262
182
|
};
|
|
263
|
-
}
|
|
264
183
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
// Evaluate descendantConstraints from all ancestors (including direct parent).
|
|
268
|
-
for (const ancestor of ancestors) {
|
|
269
|
-
if (ancestor.manifest.descendantConstraints) {
|
|
270
|
-
for (const constraint of ancestor.manifest.descendantConstraints) {
|
|
184
|
+
for (const ancestor of ancestors)if (ancestor.manifest.descendantConstraints) for (const constraint of ancestor.manifest.descendantConstraints){
|
|
271
185
|
const violation = runConstraint(constraint, `Cannot place ${componentName} inside ${ancestor.manifest.label}.`);
|
|
272
|
-
if (violation) {
|
|
273
|
-
return {
|
|
186
|
+
if (violation) return {
|
|
274
187
|
allowed: false,
|
|
275
188
|
violation
|
|
276
|
-
|
|
277
|
-
}
|
|
278
|
-
}
|
|
189
|
+
};
|
|
279
190
|
}
|
|
280
|
-
}
|
|
281
|
-
return {
|
|
282
|
-
allowed: true
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
export function evaluateDeleteConstraint(params) {
|
|
286
|
-
const {
|
|
287
|
-
elementId,
|
|
288
|
-
document,
|
|
289
|
-
components
|
|
290
|
-
} = params;
|
|
291
|
-
const element = document.elements[elementId];
|
|
292
|
-
if (!element) {
|
|
293
191
|
return {
|
|
294
|
-
|
|
192
|
+
allowed: true
|
|
295
193
|
};
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
194
|
+
}
|
|
195
|
+
function evaluateDeleteConstraint(params) {
|
|
196
|
+
const { elementId, document, components } = params;
|
|
197
|
+
const element = document.elements[elementId];
|
|
198
|
+
if (!element) return {
|
|
199
|
+
allowed: true
|
|
301
200
|
};
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
} = manifest;
|
|
306
|
-
|
|
307
|
-
// undefined or true → allowed
|
|
308
|
-
if (canDelete === undefined || canDelete === true) {
|
|
309
|
-
return {
|
|
310
|
-
allowed: true
|
|
201
|
+
const manifest = components[element.component.name];
|
|
202
|
+
if (!manifest) return {
|
|
203
|
+
allowed: true
|
|
311
204
|
};
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
if (canDelete === false) {
|
|
316
|
-
return {
|
|
317
|
-
allowed: false,
|
|
318
|
-
violation: {
|
|
319
|
-
message: `${manifest.label} cannot be deleted.`
|
|
320
|
-
}
|
|
205
|
+
const { canDelete } = manifest;
|
|
206
|
+
if (void 0 === canDelete || true === canDelete) return {
|
|
207
|
+
allowed: true
|
|
321
208
|
};
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
// ComponentConstraint → evaluate dynamically
|
|
325
|
-
const parentElement = element.parent?.id ? document.elements[element.parent.id] : undefined;
|
|
326
|
-
const parentCtx = parentElement ? buildElementContext(parentElement, components, document) : undefined;
|
|
327
|
-
const ancestors = parentElement ? buildAncestors(parentElement, components, document) : [];
|
|
328
|
-
const parentInputs = parentElement ? document.bindings[parentElement.id]?.inputs ?? {} : {};
|
|
329
|
-
const slot = element.parent?.slot ?? "";
|
|
330
|
-
const elementCtx = buildElementContext(element, components, document);
|
|
331
|
-
const ctx = {
|
|
332
|
-
component: elementCtx,
|
|
333
|
-
parent: parentCtx ?? {
|
|
334
|
-
name: "",
|
|
335
|
-
tags: [],
|
|
336
|
-
getParent: () => undefined,
|
|
337
|
-
childIndex: () => -1,
|
|
338
|
-
childCount: () => -1,
|
|
339
|
-
isLastChild: () => false,
|
|
340
|
-
isFirstChild: () => false
|
|
341
|
-
},
|
|
342
|
-
slot,
|
|
343
|
-
isChildOf: name => parentElement?.component.name === name,
|
|
344
|
-
isDescendantOf: name => ancestors.some(a => a.manifest.name === name),
|
|
345
|
-
getAncestor: name => {
|
|
346
|
-
const found = ancestors.find(a => a.manifest.name === name);
|
|
347
|
-
return found ? buildElementContext(found.element, components, document) : undefined;
|
|
348
|
-
},
|
|
349
|
-
hasTag: tag => manifest.tags?.includes(tag) ?? false,
|
|
350
|
-
slotChildCount: () => {
|
|
351
|
-
const items = parentInputs[slot]?.static;
|
|
352
|
-
return Array.isArray(items) ? items.length : 0;
|
|
353
|
-
},
|
|
354
|
-
countInstances: name => countInstances(document, name),
|
|
355
|
-
hasDescendantWithTag: tag => hasDescendantWithTag(document, components, element.id, tag),
|
|
356
|
-
getAncestorInputs: name => {
|
|
357
|
-
const found = ancestors.find(a => a.manifest.name === name);
|
|
358
|
-
if (!found) {
|
|
359
|
-
return undefined;
|
|
360
|
-
}
|
|
361
|
-
const bindings = document.bindings[found.element.id]?.inputs ?? {};
|
|
362
|
-
return Object.fromEntries(Object.entries(bindings).map(([k, v]) => [k, v?.static]));
|
|
363
|
-
},
|
|
364
|
-
getElementInputs: () => {
|
|
365
|
-
const bindings = document.bindings[element.id]?.inputs ?? {};
|
|
366
|
-
return Object.fromEntries(Object.entries(bindings).map(([k, v]) => [k, v?.static]));
|
|
367
|
-
},
|
|
368
|
-
log: (...args) => console.log(...args),
|
|
369
|
-
block
|
|
370
|
-
};
|
|
371
|
-
const fallbackMessage = `${manifest.label} cannot be deleted.`;
|
|
372
|
-
try {
|
|
373
|
-
canDelete(ctx);
|
|
374
|
-
} catch (err) {
|
|
375
|
-
if (err instanceof ConstraintBlockError) {
|
|
376
|
-
return {
|
|
209
|
+
if (false === canDelete) return {
|
|
377
210
|
allowed: false,
|
|
378
211
|
violation: {
|
|
379
|
-
|
|
212
|
+
message: `${manifest.label} cannot be deleted.`
|
|
380
213
|
}
|
|
381
|
-
|
|
214
|
+
};
|
|
215
|
+
const parentElement = element.parent?.id ? document.elements[element.parent.id] : void 0;
|
|
216
|
+
const parentCtx = parentElement ? buildElementContext(parentElement, components, document) : void 0;
|
|
217
|
+
const ancestors = parentElement ? buildAncestors(parentElement, components, document) : [];
|
|
218
|
+
const parentInputs = parentElement ? document.bindings[parentElement.id]?.inputs ?? {} : {};
|
|
219
|
+
const slot = element.parent?.slot ?? "";
|
|
220
|
+
const elementCtx = buildElementContext(element, components, document);
|
|
221
|
+
const ctx = {
|
|
222
|
+
component: elementCtx,
|
|
223
|
+
parent: parentCtx ?? {
|
|
224
|
+
name: "",
|
|
225
|
+
tags: [],
|
|
226
|
+
getParent: ()=>void 0,
|
|
227
|
+
childIndex: ()=>-1,
|
|
228
|
+
childCount: ()=>-1,
|
|
229
|
+
isLastChild: ()=>false,
|
|
230
|
+
isFirstChild: ()=>false
|
|
231
|
+
},
|
|
232
|
+
slot,
|
|
233
|
+
isChildOf: (name)=>parentElement?.component.name === name,
|
|
234
|
+
isDescendantOf: (name)=>ancestors.some((a)=>a.manifest.name === name),
|
|
235
|
+
getAncestor: (name)=>{
|
|
236
|
+
const found = ancestors.find((a)=>a.manifest.name === name);
|
|
237
|
+
return found ? buildElementContext(found.element, components, document) : void 0;
|
|
238
|
+
},
|
|
239
|
+
hasTag: (tag)=>manifest.tags?.includes(tag) ?? false,
|
|
240
|
+
slotChildCount: ()=>{
|
|
241
|
+
const items = parentInputs[slot]?.static;
|
|
242
|
+
return Array.isArray(items) ? items.length : 0;
|
|
243
|
+
},
|
|
244
|
+
countInstances: (name)=>countInstances(document, name),
|
|
245
|
+
hasDescendantWithTag: (tag)=>hasDescendantWithTag(document, components, element.id, tag),
|
|
246
|
+
getAncestorInputs: (name)=>{
|
|
247
|
+
const found = ancestors.find((a)=>a.manifest.name === name);
|
|
248
|
+
if (!found) return;
|
|
249
|
+
const bindings = document.bindings[found.element.id]?.inputs ?? {};
|
|
250
|
+
return Object.fromEntries(Object.entries(bindings).map(([k, v])=>[
|
|
251
|
+
k,
|
|
252
|
+
v?.static
|
|
253
|
+
]));
|
|
254
|
+
},
|
|
255
|
+
getElementInputs: ()=>{
|
|
256
|
+
const bindings = document.bindings[element.id]?.inputs ?? {};
|
|
257
|
+
return Object.fromEntries(Object.entries(bindings).map(([k, v])=>[
|
|
258
|
+
k,
|
|
259
|
+
v?.static
|
|
260
|
+
]));
|
|
261
|
+
},
|
|
262
|
+
log: (...args)=>console.log(...args),
|
|
263
|
+
block: block
|
|
264
|
+
};
|
|
265
|
+
const fallbackMessage = `${manifest.label} cannot be deleted.`;
|
|
266
|
+
try {
|
|
267
|
+
canDelete(ctx);
|
|
268
|
+
} catch (err) {
|
|
269
|
+
if (err instanceof ConstraintBlockError) return {
|
|
270
|
+
allowed: false,
|
|
271
|
+
violation: {
|
|
272
|
+
message: err.message
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
return {
|
|
276
|
+
allowed: false,
|
|
277
|
+
violation: {
|
|
278
|
+
message: err instanceof Error && err.message ? err.message : fallbackMessage
|
|
279
|
+
}
|
|
280
|
+
};
|
|
382
281
|
}
|
|
383
282
|
return {
|
|
384
|
-
|
|
385
|
-
violation: {
|
|
386
|
-
message: err instanceof Error && err.message ? err.message : fallbackMessage
|
|
387
|
-
}
|
|
283
|
+
allowed: true
|
|
388
284
|
};
|
|
389
|
-
}
|
|
390
|
-
return {
|
|
391
|
-
allowed: true
|
|
392
|
-
};
|
|
393
285
|
}
|
|
286
|
+
export { buildAncestors, buildElementContext, evaluateConstraints, evaluateDeleteConstraint };
|
|
394
287
|
|
|
395
288
|
//# sourceMappingURL=ConstraintEvaluator.js.map
|