@builder.io/sdk-svelte 0.12.6 → 0.12.8
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/lib/browser/components/block/animator.d.ts +5 -0
- package/lib/browser/components/block/animator.js +243 -0
- package/lib/browser/components/block/block.svelte +15 -1
- package/lib/browser/components/content/components/enable-editor.svelte +18 -27
- package/lib/browser/components/content/components/enable-editor.svelte.d.ts +1 -1
- package/lib/browser/components/content-variants/helpers.d.ts +1 -1
- package/lib/browser/constants/sdk-version.d.ts +1 -1
- package/lib/browser/constants/sdk-version.js +1 -1
- package/lib/browser/helpers/subscribe-to-editor.d.ts +35 -0
- package/lib/browser/helpers/subscribe-to-editor.js +60 -0
- package/lib/browser/server-index.d.ts +18 -3
- package/lib/browser/server-index.js +8 -1
- package/lib/browser/types/builder-block.d.ts +18 -1
- package/lib/edge/components/block/animator.d.ts +5 -0
- package/lib/edge/components/block/animator.js +243 -0
- package/lib/edge/components/block/block.svelte +15 -1
- package/lib/edge/components/content/components/enable-editor.svelte +18 -27
- package/lib/edge/components/content/components/enable-editor.svelte.d.ts +1 -1
- package/lib/edge/components/content-variants/helpers.d.ts +1 -1
- package/lib/edge/constants/sdk-version.d.ts +1 -1
- package/lib/edge/constants/sdk-version.js +1 -1
- package/lib/edge/helpers/subscribe-to-editor.d.ts +35 -0
- package/lib/edge/helpers/subscribe-to-editor.js +60 -0
- package/lib/edge/server-index.d.ts +18 -3
- package/lib/edge/server-index.js +8 -1
- package/lib/edge/types/builder-block.d.ts +18 -1
- package/lib/node/components/block/animator.d.ts +5 -0
- package/lib/node/components/block/animator.js +243 -0
- package/lib/node/components/block/block.svelte +15 -1
- package/lib/node/components/content/components/enable-editor.svelte +18 -27
- package/lib/node/components/content/components/enable-editor.svelte.d.ts +1 -1
- package/lib/node/components/content-variants/helpers.d.ts +1 -1
- package/lib/node/constants/sdk-version.d.ts +1 -1
- package/lib/node/constants/sdk-version.js +1 -1
- package/lib/node/helpers/subscribe-to-editor.d.ts +35 -0
- package/lib/node/helpers/subscribe-to-editor.js +60 -0
- package/lib/node/server-index.d.ts +18 -3
- package/lib/node/server-index.js +8 -1
- package/lib/node/types/builder-block.d.ts +18 -1
- package/package.json +1 -1
- package/src/components/block/animator.ts +254 -0
- package/src/components/block/block.svelte +17 -0
- package/src/components/content/components/enable-editor.svelte +18 -28
- package/src/constants/sdk-version.ts +1 -1
- package/src/helpers/subscribe-to-editor.ts +95 -0
- package/src/server-index.ts +23 -4
- package/src/types/builder-block.ts +23 -2
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
2
|
+
function throttle(func, wait, options = {}) {
|
|
3
|
+
let context;
|
|
4
|
+
let args;
|
|
5
|
+
let result;
|
|
6
|
+
let timeout = null;
|
|
7
|
+
let previous = 0;
|
|
8
|
+
const later = function () {
|
|
9
|
+
previous = options.leading === false ? 0 : Date.now();
|
|
10
|
+
timeout = null;
|
|
11
|
+
result = func.apply(context, args);
|
|
12
|
+
if (!timeout)
|
|
13
|
+
context = args = null;
|
|
14
|
+
};
|
|
15
|
+
return function () {
|
|
16
|
+
const now = Date.now();
|
|
17
|
+
if (!previous && options.leading === false)
|
|
18
|
+
previous = now;
|
|
19
|
+
const remaining = wait - (now - previous);
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
21
|
+
context = this;
|
|
22
|
+
// eslint-disable-next-line prefer-rest-params
|
|
23
|
+
args = arguments;
|
|
24
|
+
if (remaining <= 0 || remaining > wait) {
|
|
25
|
+
if (timeout) {
|
|
26
|
+
clearTimeout(timeout);
|
|
27
|
+
timeout = null;
|
|
28
|
+
}
|
|
29
|
+
previous = now;
|
|
30
|
+
result = func.apply(context, args);
|
|
31
|
+
if (!timeout)
|
|
32
|
+
context = args = null;
|
|
33
|
+
}
|
|
34
|
+
else if (!timeout && options.trailing !== false) {
|
|
35
|
+
timeout = setTimeout(later, remaining);
|
|
36
|
+
}
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function assign(target, ..._args) {
|
|
41
|
+
const to = Object(target);
|
|
42
|
+
for (let index = 1; index < arguments.length; index++) {
|
|
43
|
+
// eslint-disable-next-line prefer-rest-params
|
|
44
|
+
const nextSource = arguments[index];
|
|
45
|
+
if (nextSource != null) {
|
|
46
|
+
// Skip over if undefined or null
|
|
47
|
+
for (const nextKey in nextSource) {
|
|
48
|
+
// Avoid bugs when hasOwnProperty is shadowed
|
|
49
|
+
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
|
|
50
|
+
to[nextKey] = nextSource[nextKey];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return to;
|
|
56
|
+
}
|
|
57
|
+
const camelCaseToKebabCase = (str) => str ? str.replace(/([A-Z])/g, g => `-${g[0].toLowerCase()}`) : '';
|
|
58
|
+
export function bindAnimations(animations) {
|
|
59
|
+
for (const animation of animations) {
|
|
60
|
+
switch (animation.trigger) {
|
|
61
|
+
case 'pageLoad':
|
|
62
|
+
triggerAnimation(animation);
|
|
63
|
+
break;
|
|
64
|
+
case 'hover':
|
|
65
|
+
bindHoverAnimation(animation);
|
|
66
|
+
break;
|
|
67
|
+
case 'scrollInView':
|
|
68
|
+
bindScrollInViewAnimation(animation);
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function warnElementNotPresent(id) {
|
|
74
|
+
console.warn(`Cannot animate element: element with ID ${id} not found!`);
|
|
75
|
+
}
|
|
76
|
+
function augmentAnimation(animation, element) {
|
|
77
|
+
const stylesUsed = getAllStylesUsed(animation);
|
|
78
|
+
const computedStyle = getComputedStyle(element);
|
|
79
|
+
// const computedStyle = getComputedStyle(element);
|
|
80
|
+
// // FIXME: this will break if original load is in one reponsive size then resize to another hmmm
|
|
81
|
+
// Need to use transform instead of left since left can change on screen sizes
|
|
82
|
+
const firstStyles = animation.steps[0].styles;
|
|
83
|
+
const lastStyles = animation.steps[animation.steps.length - 1].styles;
|
|
84
|
+
const bothStyles = [firstStyles, lastStyles];
|
|
85
|
+
// FIXME: this won't work as expected for augmented animations - may need the editor itself to manage this
|
|
86
|
+
for (const styles of bothStyles) {
|
|
87
|
+
for (const style of stylesUsed) {
|
|
88
|
+
if (!(style in styles)) {
|
|
89
|
+
styles[style] = computedStyle[style];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function getAllStylesUsed(animation) {
|
|
95
|
+
const properties = [];
|
|
96
|
+
for (const step of animation.steps) {
|
|
97
|
+
for (const key in step.styles) {
|
|
98
|
+
if (properties.indexOf(key) === -1) {
|
|
99
|
+
properties.push(key);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return properties;
|
|
104
|
+
}
|
|
105
|
+
export function triggerAnimation(animation) {
|
|
106
|
+
// TODO: do for ALL elements
|
|
107
|
+
const elements = Array.prototype.slice.call(document.getElementsByClassName(animation.elementId || animation.id || ''));
|
|
108
|
+
if (!elements.length) {
|
|
109
|
+
warnElementNotPresent(animation.elementId || animation.id || '');
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
Array.from(elements).forEach(element => {
|
|
113
|
+
augmentAnimation(animation, element);
|
|
114
|
+
// TODO: do this properly, may have other animations of different properties
|
|
115
|
+
// TODO: only override the properties
|
|
116
|
+
// TODO: if there is an entrance and hover animation, the transition duration will get effed
|
|
117
|
+
// element.setAttribute('style', '');
|
|
118
|
+
// const styledUsed = this.getAllStylesUsed(animation);
|
|
119
|
+
element.style.transition = 'none';
|
|
120
|
+
element.style.transitionDelay = '0';
|
|
121
|
+
assign(element.style, animation.steps[0].styles);
|
|
122
|
+
// TODO: queue/batch these timeouts
|
|
123
|
+
// TODO: only include properties explicitly set in the animation
|
|
124
|
+
// using Object.keys(styles)
|
|
125
|
+
setTimeout(() => {
|
|
126
|
+
element.style.transition = `all ${animation.duration}s ${camelCaseToKebabCase(animation.easing)}`;
|
|
127
|
+
if (animation.delay) {
|
|
128
|
+
element.style.transitionDelay = animation.delay + 's';
|
|
129
|
+
}
|
|
130
|
+
assign(element.style, animation.steps[1].styles);
|
|
131
|
+
// TODO: maybe remove/reset transitoin property after animation duration
|
|
132
|
+
// TODO: queue timers
|
|
133
|
+
setTimeout(() => {
|
|
134
|
+
// TODO: what if has other transition (reset back to what it was)
|
|
135
|
+
element.style.transition = '';
|
|
136
|
+
element.style.transitionDelay = '';
|
|
137
|
+
}, (animation.delay || 0) * 1000 + animation.duration * 1000 + 100);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
export function bindHoverAnimation(animation) {
|
|
142
|
+
// TODO: is it multiple binding when editing...?
|
|
143
|
+
// TODO: unbind on element remove
|
|
144
|
+
// TODO: apply to ALL elements
|
|
145
|
+
const elements = Array.prototype.slice.call(document.getElementsByClassName(animation.elementId || animation.id || ''));
|
|
146
|
+
if (!elements.length) {
|
|
147
|
+
warnElementNotPresent(animation.elementId || animation.id || '');
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
Array.from(elements).forEach(element => {
|
|
151
|
+
augmentAnimation(animation, element);
|
|
152
|
+
const defaultState = animation.steps[0].styles;
|
|
153
|
+
const hoverState = animation.steps[1].styles;
|
|
154
|
+
function attachDefaultState() {
|
|
155
|
+
assign(element.style, defaultState);
|
|
156
|
+
}
|
|
157
|
+
function attachHoverState() {
|
|
158
|
+
assign(element.style, hoverState);
|
|
159
|
+
}
|
|
160
|
+
attachDefaultState();
|
|
161
|
+
element.addEventListener('mouseenter', attachHoverState);
|
|
162
|
+
element.addEventListener('mouseleave', attachDefaultState);
|
|
163
|
+
// TODO: queue/batch these timeouts
|
|
164
|
+
setTimeout(() => {
|
|
165
|
+
element.style.transition = `all ${animation.duration}s ${camelCaseToKebabCase(animation.easing)}`;
|
|
166
|
+
if (animation.delay) {
|
|
167
|
+
element.style.transitionDelay = animation.delay + 's';
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
// TODO: unbind on element remove
|
|
173
|
+
export function bindScrollInViewAnimation(animation) {
|
|
174
|
+
// TODO: apply to ALL matching elements
|
|
175
|
+
const elements = Array.prototype.slice.call(document.getElementsByClassName(animation.elementId || animation.id || ''));
|
|
176
|
+
if (!elements.length) {
|
|
177
|
+
warnElementNotPresent(animation.elementId || animation.id || '');
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
// TODO: if server side rendered and scrolled into view don't animate...
|
|
181
|
+
Array.from(elements).forEach(element => {
|
|
182
|
+
augmentAnimation(animation, element);
|
|
183
|
+
let triggered = false;
|
|
184
|
+
let pendingAnimation = false;
|
|
185
|
+
function immediateOnScroll() {
|
|
186
|
+
if (!triggered && isScrolledIntoView(element)) {
|
|
187
|
+
triggered = true;
|
|
188
|
+
pendingAnimation = true;
|
|
189
|
+
setTimeout(() => {
|
|
190
|
+
assign(element.style, animation.steps[1].styles);
|
|
191
|
+
if (!animation.repeat) {
|
|
192
|
+
document.removeEventListener('scroll', onScroll);
|
|
193
|
+
}
|
|
194
|
+
setTimeout(() => {
|
|
195
|
+
pendingAnimation = false;
|
|
196
|
+
if (!animation.repeat) {
|
|
197
|
+
element.style.transition = '';
|
|
198
|
+
element.style.transitionDelay = '';
|
|
199
|
+
}
|
|
200
|
+
}, (animation.duration + (animation.delay || 0)) * 1000 + 100);
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
else if (animation.repeat && triggered && !pendingAnimation && !isScrolledIntoView(element)) {
|
|
204
|
+
// we want to repeat the animation every time the the element is out of view and back again
|
|
205
|
+
triggered = false;
|
|
206
|
+
assign(element.style, animation.steps[0].styles);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// TODO: roll all of these in one for more efficiency of checking all the rects
|
|
210
|
+
const onScroll = throttle(immediateOnScroll, 200, {
|
|
211
|
+
leading: false
|
|
212
|
+
});
|
|
213
|
+
// TODO: fully in view or partially
|
|
214
|
+
function isScrolledIntoView(elem) {
|
|
215
|
+
const rect = elem.getBoundingClientRect();
|
|
216
|
+
const windowHeight = window.innerHeight;
|
|
217
|
+
const thresholdPercent = (animation.thresholdPercent || 0) / 100;
|
|
218
|
+
const threshold = thresholdPercent * windowHeight;
|
|
219
|
+
// TODO: partial in view? or what if element is larger than screen itself
|
|
220
|
+
return rect.bottom > threshold && rect.top < windowHeight - threshold // Element is peeking top or bottom
|
|
221
|
+
;
|
|
222
|
+
}
|
|
223
|
+
const defaultState = animation.steps[0].styles;
|
|
224
|
+
function attachDefaultState() {
|
|
225
|
+
assign(element.style, defaultState);
|
|
226
|
+
}
|
|
227
|
+
attachDefaultState();
|
|
228
|
+
// TODO: queue/batch these timeouts!
|
|
229
|
+
setTimeout(() => {
|
|
230
|
+
element.style.transition = `all ${animation.duration}s ${camelCaseToKebabCase(animation.easing)}`;
|
|
231
|
+
if (animation.delay) {
|
|
232
|
+
element.style.transitionDelay = animation.delay + 's';
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
// TODO: one listener for everything
|
|
236
|
+
document.addEventListener('scroll', onScroll, {
|
|
237
|
+
capture: true,
|
|
238
|
+
passive: true
|
|
239
|
+
});
|
|
240
|
+
// Do an initial check
|
|
241
|
+
immediateOnScroll();
|
|
242
|
+
});
|
|
243
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
<script context="module"></script>
|
|
2
2
|
|
|
3
|
-
<script>import {
|
|
3
|
+
<script>import { onMount } from "svelte";
|
|
4
|
+
import { writable } from "svelte/store";
|
|
4
5
|
import "../../functions/extract-text-styles.js";
|
|
5
6
|
import { getBlockComponentOptions } from "../../functions/get-block-component-options.js";
|
|
6
7
|
import { getProcessedBlock } from "../../functions/get-processed-block.js";
|
|
7
8
|
import "../../functions/get-style.js";
|
|
9
|
+
import { bindAnimations } from "./animator.js";
|
|
8
10
|
import { getComponent, getRepeatItemData } from "./block.helpers.js";
|
|
9
11
|
import BlockStyles from "./components/block-styles.svelte";
|
|
10
12
|
import BlockWrapper from "./components/block-wrapper.svelte";
|
|
@@ -100,6 +102,18 @@ $: componentRefProps = () => {
|
|
|
100
102
|
};
|
|
101
103
|
};
|
|
102
104
|
let childrenContext = writable($context);
|
|
105
|
+
onMount(() => {
|
|
106
|
+
const blockId = processedBlock().id;
|
|
107
|
+
const animations = processedBlock().animations;
|
|
108
|
+
if (animations && blockId) {
|
|
109
|
+
bindAnimations(animations
|
|
110
|
+
.filter((item) => item.trigger !== "hover")
|
|
111
|
+
.map((animation) => ({
|
|
112
|
+
...animation,
|
|
113
|
+
elementId: blockId,
|
|
114
|
+
})));
|
|
115
|
+
}
|
|
116
|
+
});
|
|
103
117
|
</script>
|
|
104
118
|
|
|
105
119
|
{#if canShowBlock()}
|
|
@@ -8,7 +8,6 @@ import { fetchOneEntry } from "../../../functions/get-content/index.js";
|
|
|
8
8
|
import { fetch } from "../../../functions/get-fetch.js";
|
|
9
9
|
import { isBrowser } from "../../../functions/is-browser.js";
|
|
10
10
|
import { isEditing } from "../../../functions/is-editing.js";
|
|
11
|
-
import { isFromTrustedHost } from "../../../functions/is-from-trusted-host.js";
|
|
12
11
|
import { isPreviewing } from "../../../functions/is-previewing.js";
|
|
13
12
|
import { createRegisterComponentMessage } from "../../../functions/register-component.js";
|
|
14
13
|
import { _track } from "../../../functions/track/index.js";
|
|
@@ -16,11 +15,13 @@ import { getInteractionPropertiesForEvent } from "../../../functions/track/inter
|
|
|
16
15
|
import { getDefaultCanTrack } from "../../../helpers/canTrack.js";
|
|
17
16
|
import { logger } from "../../../helpers/logger.js";
|
|
18
17
|
import "../../../helpers/preview-lru-cache/set.js";
|
|
18
|
+
import { createEditorListener } from "../../../helpers/subscribe-to-editor.js";
|
|
19
19
|
import { registerInsertMenu, setupBrowserForEditing, } from "../../../scripts/init-editing.js";
|
|
20
|
+
import { triggerAnimation } from "../../block/animator.js";
|
|
20
21
|
export let builderContextSignal;
|
|
21
22
|
export let contentWrapper = undefined;
|
|
22
|
-
export let trustedHosts = undefined;
|
|
23
23
|
export let model = undefined;
|
|
24
|
+
export let trustedHosts = undefined;
|
|
24
25
|
export let context = undefined;
|
|
25
26
|
export let canTrack = undefined;
|
|
26
27
|
export let apiKey;
|
|
@@ -61,14 +62,11 @@ function mergeNewContent(newContent) {
|
|
|
61
62
|
$builderContextSignal.content = newContentValue;
|
|
62
63
|
}
|
|
63
64
|
function processMessage(event) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
switch (data.type) {
|
|
70
|
-
case "builder.configureSdk": {
|
|
71
|
-
const messageContent = data.data;
|
|
65
|
+
return createEditorListener({
|
|
66
|
+
model: model,
|
|
67
|
+
trustedHosts: trustedHosts,
|
|
68
|
+
callbacks: {
|
|
69
|
+
configureSdk: (messageContent) => {
|
|
72
70
|
const { breakpoints, contentId } = messageContent;
|
|
73
71
|
if (!contentId || contentId !== $builderContextSignal.content?.id) {
|
|
74
72
|
return;
|
|
@@ -79,25 +77,18 @@ function processMessage(event) {
|
|
|
79
77
|
breakpoints,
|
|
80
78
|
},
|
|
81
79
|
});
|
|
82
|
-
}
|
|
83
|
-
forceReRenderCount = forceReRenderCount + 1; // This is a hack to force Qwik to re-render.
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
case "builder.contentUpdate": {
|
|
87
|
-
const messageContent = data.data;
|
|
88
|
-
const key = messageContent.key ||
|
|
89
|
-
messageContent.alias ||
|
|
90
|
-
messageContent.entry ||
|
|
91
|
-
messageContent.modelName;
|
|
92
|
-
const contentData = messageContent.data;
|
|
93
|
-
if (key === model) {
|
|
94
|
-
mergeNewContent(contentData);
|
|
95
80
|
forceReRenderCount = forceReRenderCount + 1; // This is a hack to force Qwik to re-render.
|
|
96
81
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
82
|
+
},
|
|
83
|
+
animation: (animation) => {
|
|
84
|
+
triggerAnimation(animation);
|
|
85
|
+
},
|
|
86
|
+
contentUpdate: (newContent) => {
|
|
87
|
+
mergeNewContent(newContent);
|
|
88
|
+
forceReRenderCount = forceReRenderCount + 1; // This is a hack to force Qwik to re-render.
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
})(event);
|
|
101
92
|
}
|
|
102
93
|
function evaluateJsCode() {
|
|
103
94
|
// run any dynamic JS code attached to content
|
|
@@ -11,8 +11,8 @@ declare const __propDef: {
|
|
|
11
11
|
props: {
|
|
12
12
|
builderContextSignal: BuilderEditorProps["builderContextSignal"];
|
|
13
13
|
contentWrapper?: BuilderEditorProps["contentWrapper"];
|
|
14
|
-
trustedHosts?: BuilderEditorProps["trustedHosts"];
|
|
15
14
|
model?: BuilderEditorProps["model"];
|
|
15
|
+
trustedHosts?: BuilderEditorProps["trustedHosts"];
|
|
16
16
|
context?: BuilderEditorProps["context"];
|
|
17
17
|
canTrack?: BuilderEditorProps["canTrack"];
|
|
18
18
|
apiKey: BuilderEditorProps["apiKey"];
|
|
@@ -6,7 +6,7 @@ export declare const getVariants: (content: Nullable<BuilderContent>) => {
|
|
|
6
6
|
data?: {
|
|
7
7
|
[key: string]: any;
|
|
8
8
|
title?: string | undefined;
|
|
9
|
-
blocks?: import("../../
|
|
9
|
+
blocks?: import("../../server-index.js").BuilderBlock[] | undefined;
|
|
10
10
|
inputs?: import("../../types/input.js").Input[] | undefined;
|
|
11
11
|
state?: {
|
|
12
12
|
[key: string]: any;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "0.12.
|
|
1
|
+
export declare const SDK_VERSION = "0.12.8";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const SDK_VERSION = "0.12.
|
|
1
|
+
export const SDK_VERSION = "0.12.8";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ContentProps } from '../components/content/content.types.js';
|
|
2
|
+
import type { BuilderAnimation } from '../types/builder-block.js';
|
|
3
|
+
import type { BuilderContent } from '../types/builder-content.js';
|
|
4
|
+
type ContentListener = Required<Pick<ContentProps, 'model' | 'trustedHosts'>> & {
|
|
5
|
+
callbacks: {
|
|
6
|
+
contentUpdate: (updatedContent: BuilderContent) => void;
|
|
7
|
+
animation: (updatedContent: BuilderAnimation) => void;
|
|
8
|
+
configureSdk: (updatedContent: any) => void;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
export declare const createEditorListener: ({ model, trustedHosts, callbacks }: ContentListener) => (event: MessageEvent<any>) => void;
|
|
12
|
+
type SubscribeToEditor = (
|
|
13
|
+
/**
|
|
14
|
+
* The Builder `model` to subscribe to
|
|
15
|
+
*/
|
|
16
|
+
model: string,
|
|
17
|
+
/**
|
|
18
|
+
* The callback function to call when the content is updated.
|
|
19
|
+
*/
|
|
20
|
+
callback: (updatedContent: BuilderContent) => void,
|
|
21
|
+
/**
|
|
22
|
+
* Extra options for the listener.
|
|
23
|
+
*/
|
|
24
|
+
options?: {
|
|
25
|
+
/**
|
|
26
|
+
* List of hosts to allow editing content from.
|
|
27
|
+
*/
|
|
28
|
+
trustedHosts?: string[] | undefined;
|
|
29
|
+
}) => () => void;
|
|
30
|
+
/**
|
|
31
|
+
* Subscribes to the Builder editor and listens to `content` updates of a certain `model`.
|
|
32
|
+
* Sends the updated `content` to the `callback` function.
|
|
33
|
+
*/
|
|
34
|
+
export declare const subscribeToEditor: SubscribeToEditor;
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { isBrowser } from '../functions/is-browser.js';
|
|
2
|
+
import { isFromTrustedHost } from '../functions/is-from-trusted-host.js';
|
|
3
|
+
import { setupBrowserForEditing } from '../scripts/init-editing.js';
|
|
4
|
+
import { logger } from './logger.js';
|
|
5
|
+
export const createEditorListener = ({ model, trustedHosts, callbacks }) => {
|
|
6
|
+
return (event) => {
|
|
7
|
+
if (!isFromTrustedHost(trustedHosts, event)) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
const { data } = event;
|
|
11
|
+
if (data) {
|
|
12
|
+
switch (data.type) {
|
|
13
|
+
case 'builder.configureSdk':
|
|
14
|
+
{
|
|
15
|
+
callbacks.configureSdk(data.data);
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
case 'builder.triggerAnimation':
|
|
19
|
+
{
|
|
20
|
+
callbacks.animation(data.data);
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
case 'builder.contentUpdate':
|
|
24
|
+
{
|
|
25
|
+
const messageContent = data.data;
|
|
26
|
+
const key = messageContent.key || messageContent.alias || messageContent.entry || messageContent.modelName;
|
|
27
|
+
const contentData = messageContent.data;
|
|
28
|
+
if (key === model) {
|
|
29
|
+
callbacks.contentUpdate(contentData);
|
|
30
|
+
}
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Subscribes to the Builder editor and listens to `content` updates of a certain `model`.
|
|
39
|
+
* Sends the updated `content` to the `callback` function.
|
|
40
|
+
*/
|
|
41
|
+
export const subscribeToEditor = (model, callback, options) => {
|
|
42
|
+
if (!isBrowser) {
|
|
43
|
+
logger.warn('`subscribeToEditor` only works in the browser. It currently seems to be running on the server.');
|
|
44
|
+
return () => { };
|
|
45
|
+
}
|
|
46
|
+
setupBrowserForEditing();
|
|
47
|
+
const listener = createEditorListener({
|
|
48
|
+
callbacks: {
|
|
49
|
+
contentUpdate: callback,
|
|
50
|
+
animation: () => { },
|
|
51
|
+
configureSdk: () => { }
|
|
52
|
+
},
|
|
53
|
+
model,
|
|
54
|
+
trustedHosts: options?.trustedHosts
|
|
55
|
+
});
|
|
56
|
+
window.addEventListener('message', listener);
|
|
57
|
+
return () => {
|
|
58
|
+
window.removeEventListener('message', listener);
|
|
59
|
+
};
|
|
60
|
+
};
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export * from './index-helpers/top-of-file.js';
|
|
2
|
+
/**
|
|
3
|
+
* Component Prop types
|
|
4
|
+
*/
|
|
2
5
|
export type { ButtonProps } from './blocks/button/button.types.js';
|
|
3
6
|
export type { ColumnProps } from './blocks/columns/columns.types.js';
|
|
4
7
|
export type { FragmentProps } from './blocks/fragment/fragment.types.js';
|
|
@@ -9,6 +12,16 @@ export type { TextProps } from './blocks/text/text.types.js';
|
|
|
9
12
|
export type { VideoProps } from './blocks/video/video.types.js';
|
|
10
13
|
export type { BlocksProps } from './components/blocks/blocks.types.js';
|
|
11
14
|
export type { ContentVariantsPrps as ContentProps } from './components/content-variants/content-variants.types.js';
|
|
15
|
+
/**
|
|
16
|
+
* General Builder types
|
|
17
|
+
*/
|
|
18
|
+
export type { RegisteredComponent } from './context/types.js';
|
|
19
|
+
export type { BuilderBlock } from './types/builder-block.js';
|
|
20
|
+
export type { BuilderContent } from './types/builder-content.js';
|
|
21
|
+
export type { ComponentInfo } from './types/components.js';
|
|
22
|
+
/**
|
|
23
|
+
* Helper functions
|
|
24
|
+
*/
|
|
12
25
|
export { isEditing } from './functions/is-editing.js';
|
|
13
26
|
export { isPreviewing } from './functions/is-previewing.js';
|
|
14
27
|
export { createRegisterComponentMessage } from './functions/register-component.js';
|
|
@@ -16,9 +29,11 @@ export { register } from './functions/register.js';
|
|
|
16
29
|
export type { InsertMenuConfig, InsertMenuItem } from './functions/register.js';
|
|
17
30
|
export { setEditorSettings } from './functions/set-editor-settings.js';
|
|
18
31
|
export type { Settings } from './functions/set-editor-settings.js';
|
|
19
|
-
export { _processContentResult, fetchEntries, fetchOneEntry, getAllContent, getContent } from './functions/get-content/index.js';
|
|
20
32
|
export { getBuilderSearchParams } from './functions/get-builder-search-params/index.js';
|
|
21
33
|
export { track } from './functions/track/index.js';
|
|
22
|
-
export
|
|
23
|
-
|
|
34
|
+
export { subscribeToEditor } from './helpers/subscribe-to-editor.js';
|
|
35
|
+
/**
|
|
36
|
+
* Content fetching
|
|
37
|
+
*/
|
|
24
38
|
export { fetchBuilderProps } from './functions/fetch-builder-props.js';
|
|
39
|
+
export { _processContentResult, fetchEntries, fetchOneEntry, getAllContent, getContent } from './functions/get-content/index.js';
|
package/lib/node/server-index.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
export * from './index-helpers/top-of-file.js';
|
|
2
|
+
/**
|
|
3
|
+
* Helper functions
|
|
4
|
+
*/
|
|
2
5
|
export { isEditing } from './functions/is-editing.js';
|
|
3
6
|
export { isPreviewing } from './functions/is-previewing.js';
|
|
4
7
|
export { createRegisterComponentMessage } from './functions/register-component.js';
|
|
5
8
|
export { register } from './functions/register.js';
|
|
6
9
|
export { setEditorSettings } from './functions/set-editor-settings.js';
|
|
7
|
-
export { _processContentResult, fetchEntries, fetchOneEntry, getAllContent, getContent } from './functions/get-content/index.js';
|
|
8
10
|
export { getBuilderSearchParams } from './functions/get-builder-search-params/index.js';
|
|
9
11
|
export { track } from './functions/track/index.js';
|
|
12
|
+
export { subscribeToEditor } from './helpers/subscribe-to-editor.js';
|
|
13
|
+
/**
|
|
14
|
+
* Content fetching
|
|
15
|
+
*/
|
|
10
16
|
export { fetchBuilderProps } from './functions/fetch-builder-props.js';
|
|
17
|
+
export { _processContentResult, fetchEntries, fetchOneEntry, getAllContent, getContent } from './functions/get-content/index.js';
|
|
@@ -4,6 +4,23 @@ interface JSONObject {
|
|
|
4
4
|
}
|
|
5
5
|
interface JSONArray extends Array<JSONValue> {
|
|
6
6
|
}
|
|
7
|
+
export interface AnimationStep {
|
|
8
|
+
styles: {
|
|
9
|
+
[key: string]: string;
|
|
10
|
+
};
|
|
11
|
+
delay?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface BuilderAnimation {
|
|
14
|
+
elementId: string;
|
|
15
|
+
trigger: string;
|
|
16
|
+
steps: AnimationStep[];
|
|
17
|
+
duration: number;
|
|
18
|
+
delay?: number;
|
|
19
|
+
easing?: string;
|
|
20
|
+
id?: string;
|
|
21
|
+
repeat?: boolean;
|
|
22
|
+
thresholdPercent?: number;
|
|
23
|
+
}
|
|
7
24
|
/** @todo typedoc this */
|
|
8
25
|
export interface BuilderBlock {
|
|
9
26
|
'@type': '@builder.io/sdk:Element';
|
|
@@ -52,7 +69,7 @@ export interface BuilderBlock {
|
|
|
52
69
|
collection: string;
|
|
53
70
|
itemName?: string;
|
|
54
71
|
} | null;
|
|
55
|
-
animations?:
|
|
72
|
+
animations?: BuilderAnimation[];
|
|
56
73
|
style?: Partial<CSSStyleDeclaration>;
|
|
57
74
|
href?: string;
|
|
58
75
|
/**
|