@valbuild/next 0.101.1 → 0.103.0
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 +50 -1
- package/client/dist/valbuild-next-client.cjs.dev.js +25 -2
- package/client/dist/valbuild-next-client.cjs.prod.js +25 -2
- package/client/dist/valbuild-next-client.esm.js +25 -2
- package/dist/ValApp-90c4171d.cjs.js +7 -0
- package/dist/{ValApp-bb207e96.cjs.prod.js → ValApp-90c4171d.cjs.prod.js} +8 -6
- package/dist/{ValApp-1992d8b3.cjs.dev.js → ValApp-c1c3ef55.cjs.dev.js} +8 -6
- package/dist/{ValApp-8912fc8b.esm.js → ValApp-e17eb734.esm.js} +5 -3
- package/dist/ValCanvasBridge-96f67a41.cjs.dev.js +395 -0
- package/dist/ValCanvasBridge-d8713d9d.esm.js +387 -0
- package/dist/ValCanvasBridge-f75509c6.cjs.js +7 -0
- package/dist/ValCanvasBridge-f75509c6.cjs.prod.js +395 -0
- package/dist/{ValNextProvider-7302b8af.esm.js → ValNextProvider-3209948c.esm.js} +282 -43
- package/dist/{ValNextProvider-03a9f8fd.cjs.dev.js → ValNextProvider-3d8ebfec.cjs.dev.js} +297 -58
- package/dist/ValNextProvider-3fdf8756.cjs.js +7 -0
- package/dist/{ValNextProvider-6103cb74.cjs.prod.js → ValNextProvider-3fdf8756.cjs.prod.js} +297 -58
- package/dist/ValOverlayContext-1d019b95.cjs.js +7 -0
- package/dist/{ValOverlayContext-f7f45bc7.cjs.prod.js → ValOverlayContext-1d019b95.cjs.prod.js} +8 -2
- package/dist/{ValOverlayContext-c6f27a6d.cjs.dev.js → ValOverlayContext-ca3b6ebd.cjs.dev.js} +8 -2
- package/dist/{ValOverlayContext-3c37e5a7.esm.js → ValOverlayContext-f63e0fc9.esm.js} +8 -2
- package/dist/declarations/src/ValApp.d.ts +1 -1
- package/dist/declarations/src/ValImage.d.ts +1 -1
- package/dist/declarations/src/ValProvider.d.ts +1 -1
- package/dist/declarations/src/external_exempt_from_val_quickjs.d.ts +7 -5
- package/dist/fallbackColors-5ead2c26.esm.js +58 -0
- package/dist/{cssUtils-9c11102f.cjs.dev.js → fallbackColors-9a2ac53a.cjs.dev.js} +30 -0
- package/dist/{cssUtils-d97a757c.cjs.prod.js → fallbackColors-d4a5b0da.cjs.prod.js} +30 -0
- package/dist/valbuild-next.cjs.dev.js +8 -13
- package/dist/valbuild-next.cjs.prod.js +8 -13
- package/dist/valbuild-next.esm.js +9 -10
- package/package.json +13 -13
- package/dist/ValApp-bb207e96.cjs.js +0 -7
- package/dist/ValNextProvider-6103cb74.cjs.js +0 -7
- package/dist/ValOverlayContext-f7f45bc7.cjs.js +0 -7
- package/dist/cssUtils-b5651c03.esm.js +0 -32
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var slicedToArray = require('./slicedToArray-ce613de6.cjs.prod.js');
|
|
7
|
+
var React = require('react');
|
|
8
|
+
var core = require('@valbuild/core');
|
|
9
|
+
var internal = require('@valbuild/shared/internal');
|
|
10
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
11
|
+
require('./unsupportedIterableToArray-0d2087a2.cjs.prod.js');
|
|
12
|
+
|
|
13
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
|
14
|
+
|
|
15
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
16
|
+
|
|
17
|
+
var SELECTION = "#079455";
|
|
18
|
+
var SELECTION_SOFT = "rgba(7, 148, 85, 0.4)";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* How often the page is re-measured even when nothing said it changed.
|
|
22
|
+
*
|
|
23
|
+
* A backstop, not the mechanism — the observers below carry the responsive
|
|
24
|
+
* case. Slow enough to be free, fast enough that a field which appeared late is
|
|
25
|
+
* in the list before anyone goes looking for it.
|
|
26
|
+
*/
|
|
27
|
+
var RESCAN_INTERVAL_MS = 5000;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The page's half of the canvas protocol.
|
|
31
|
+
*
|
|
32
|
+
* Mounted only in the studio's canvas frame. Its job is to tell the studio
|
|
33
|
+
* where Val's content is on the page, and to do the two things the studio can
|
|
34
|
+
* ask of a document it cannot touch: outline an element, and treat a click as a
|
|
35
|
+
* pick rather than as a click.
|
|
36
|
+
*
|
|
37
|
+
* Nothing here is visible on the customer's own site — this component is not
|
|
38
|
+
* mounted there at all.
|
|
39
|
+
*/
|
|
40
|
+
function ValCanvasBridge(_ref) {
|
|
41
|
+
var draftMode = _ref.draftMode,
|
|
42
|
+
isRefreshing = _ref.isRefreshing;
|
|
43
|
+
var _React$useState = React__default["default"].useState(false),
|
|
44
|
+
_React$useState2 = slicedToArray._slicedToArray(_React$useState, 2),
|
|
45
|
+
picking = _React$useState2[0],
|
|
46
|
+
setPicking = _React$useState2[1];
|
|
47
|
+
var _React$useState3 = React__default["default"].useState(null),
|
|
48
|
+
_React$useState4 = slicedToArray._slicedToArray(_React$useState3, 2),
|
|
49
|
+
highlighted = _React$useState4[0],
|
|
50
|
+
setHighlighted = _React$useState4[1];
|
|
51
|
+
// Kept in a ref as well, because the capture-phase click listener below is
|
|
52
|
+
// installed once and would otherwise close over the first value forever.
|
|
53
|
+
var pickingRef = React__default["default"].useRef(false);
|
|
54
|
+
pickingRef.current = picking;
|
|
55
|
+
var post = React__default["default"].useCallback(function (message) {
|
|
56
|
+
// `*` as the target origin: the studio and the page share an origin today,
|
|
57
|
+
// but the frame does not know the parent's origin for certain and naming
|
|
58
|
+
// the wrong one silently drops the message. Nothing sent here is
|
|
59
|
+
// sensitive — it is the positions of elements on a page the parent is
|
|
60
|
+
// already displaying.
|
|
61
|
+
window.parent.postMessage(message, "*");
|
|
62
|
+
}, []);
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The last payload posted, as a string.
|
|
66
|
+
*
|
|
67
|
+
* The periodic scan below runs whether or not anything moved, and an
|
|
68
|
+
* unchanged payload costs the studio a re-render of the fields column for
|
|
69
|
+
* nothing. Compared as a string because the comparison has to be by value —
|
|
70
|
+
* every scan builds fresh objects.
|
|
71
|
+
*/
|
|
72
|
+
var lastPosted = React__default["default"].useRef(null);
|
|
73
|
+
|
|
74
|
+
/** Every element Val tagged, with where it is on the page. */
|
|
75
|
+
var scan = React__default["default"].useCallback(function () {
|
|
76
|
+
var elements = [];
|
|
77
|
+
var scrollX = window.scrollX;
|
|
78
|
+
var scrollY = window.scrollY;
|
|
79
|
+
document.querySelectorAll("[data-val-path]").forEach(function (el) {
|
|
80
|
+
if (!(el instanceof HTMLElement) && !(el instanceof SVGElement)) return;
|
|
81
|
+
var attribute = el.getAttribute("data-val-path");
|
|
82
|
+
if (!attribute) return;
|
|
83
|
+
/**
|
|
84
|
+
* A `<source>` has no box of its own, so its `<video>`/`<picture>` parent
|
|
85
|
+
* is measured instead — the same substitution the overlay makes, and for
|
|
86
|
+
* the same reason: an element with a zero-size rect cannot be pointed at.
|
|
87
|
+
*/
|
|
88
|
+
var measured = el;
|
|
89
|
+
if (el.tagName === "SOURCE") {
|
|
90
|
+
var parent = el.parentElement;
|
|
91
|
+
if (parent && (parent.tagName === "VIDEO" || parent.tagName === "PICTURE")) {
|
|
92
|
+
measured = parent;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
var rect = measured.getBoundingClientRect();
|
|
96
|
+
if (rect.width === 0 && rect.height === 0) return;
|
|
97
|
+
elements.push({
|
|
98
|
+
// Split by the same helper the rest of Val uses, so the studio gets
|
|
99
|
+
// the paths back in exactly the form it holds them in.
|
|
100
|
+
paths: core.Internal.splitJoinedSourcePaths(attribute),
|
|
101
|
+
// Page coordinates, not viewport: the studio scales and offsets the
|
|
102
|
+
// whole document, so a viewport-relative box would be wrong the moment
|
|
103
|
+
// the frame scrolled.
|
|
104
|
+
rect: {
|
|
105
|
+
top: rect.top + scrollY,
|
|
106
|
+
left: rect.left + scrollX,
|
|
107
|
+
width: rect.width,
|
|
108
|
+
height: rect.height
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
var message = {
|
|
113
|
+
val: internal.VAL_CANVAS_MESSAGE,
|
|
114
|
+
type: "elements",
|
|
115
|
+
elements: elements,
|
|
116
|
+
pageSize: {
|
|
117
|
+
width: document.documentElement.scrollWidth,
|
|
118
|
+
height: document.documentElement.scrollHeight
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
var serialized = JSON.stringify(message);
|
|
122
|
+
if (serialized === lastPosted.current) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
lastPosted.current = serialized;
|
|
126
|
+
post(message);
|
|
127
|
+
}, [post]);
|
|
128
|
+
|
|
129
|
+
// Relayed as it changes, not polled: the studio only has to know the two
|
|
130
|
+
// edges, and a message per render would be a message per keystroke.
|
|
131
|
+
React__default["default"].useEffect(function () {
|
|
132
|
+
post({
|
|
133
|
+
val: internal.VAL_CANVAS_MESSAGE,
|
|
134
|
+
type: "refreshing",
|
|
135
|
+
pending: isRefreshing === true
|
|
136
|
+
});
|
|
137
|
+
}, [post, isRefreshing]);
|
|
138
|
+
|
|
139
|
+
// Announce the frame, and say whether it is actually showing draft content.
|
|
140
|
+
React__default["default"].useEffect(function () {
|
|
141
|
+
post({
|
|
142
|
+
val: internal.VAL_CANVAS_MESSAGE,
|
|
143
|
+
type: "ready",
|
|
144
|
+
draftMode: draftMode,
|
|
145
|
+
url: window.location.href
|
|
146
|
+
});
|
|
147
|
+
}, [post, draftMode]);
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Re-scan whenever the page could have moved.
|
|
151
|
+
*
|
|
152
|
+
* Coalesced into one animation frame: a layout change fires mutation,
|
|
153
|
+
* resize and scroll events together, and scanning three times produces three
|
|
154
|
+
* identical messages.
|
|
155
|
+
*/
|
|
156
|
+
React__default["default"].useEffect(function () {
|
|
157
|
+
var frame = null;
|
|
158
|
+
var schedule = function schedule() {
|
|
159
|
+
if (frame !== null) return;
|
|
160
|
+
frame = requestAnimationFrame(function () {
|
|
161
|
+
frame = null;
|
|
162
|
+
scan();
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
schedule();
|
|
166
|
+
var mutations = new MutationObserver(schedule);
|
|
167
|
+
mutations.observe(document.body, {
|
|
168
|
+
subtree: true,
|
|
169
|
+
childList: true,
|
|
170
|
+
attributes: true,
|
|
171
|
+
attributeFilter: ["data-val-path", "class", "style"]
|
|
172
|
+
});
|
|
173
|
+
var resizes = new ResizeObserver(schedule);
|
|
174
|
+
resizes.observe(document.documentElement);
|
|
175
|
+
window.addEventListener("scroll", schedule, {
|
|
176
|
+
passive: true
|
|
177
|
+
});
|
|
178
|
+
window.addEventListener("resize", schedule);
|
|
179
|
+
// Images and fonts land after the first paint and move everything below
|
|
180
|
+
// them, so the boxes measured before `load` are stale by definition.
|
|
181
|
+
window.addEventListener("load", schedule);
|
|
182
|
+
return function () {
|
|
183
|
+
if (frame !== null) cancelAnimationFrame(frame);
|
|
184
|
+
mutations.disconnect();
|
|
185
|
+
resizes.disconnect();
|
|
186
|
+
window.removeEventListener("scroll", schedule);
|
|
187
|
+
window.removeEventListener("resize", schedule);
|
|
188
|
+
window.removeEventListener("load", schedule);
|
|
189
|
+
};
|
|
190
|
+
}, [scan]);
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* And re-scan every few seconds regardless.
|
|
194
|
+
*
|
|
195
|
+
* The event-driven scan above is not enough in practice, and the way it fails
|
|
196
|
+
* is confusing rather than obviously broken: the fields column shows some of
|
|
197
|
+
* what is on the page and not the rest, until you happen to edit one of the
|
|
198
|
+
* missing ones and they appear. Anything that tags content after the observers
|
|
199
|
+
* are set up but produces no mutation they watch — a streamed-in server
|
|
200
|
+
* component, an element that measured zero because its image had not decoded,
|
|
201
|
+
* content revealed by something outside `data-val-path`, `class` and `style` —
|
|
202
|
+
* is invisible until the next unrelated change. A slow poll costs nothing and
|
|
203
|
+
* closes all of those at once, without having to guess which one it was.
|
|
204
|
+
*
|
|
205
|
+
* Idle-scheduled, and never on the frame's critical path. A scan is a
|
|
206
|
+
* `querySelectorAll` plus a forced layout per tagged element, which is exactly
|
|
207
|
+
* the kind of work that should wait for a gap rather than take one — and this
|
|
208
|
+
* runs inside the customer's own page, where Val is a guest. Skipped entirely
|
|
209
|
+
* while the frame is hidden, where the boxes cannot have moved and nobody is
|
|
210
|
+
* looking at them.
|
|
211
|
+
*/
|
|
212
|
+
React__default["default"].useEffect(function () {
|
|
213
|
+
var idle = null;
|
|
214
|
+
var runWhenIdle = function runWhenIdle() {
|
|
215
|
+
if (document.hidden || idle !== null) return;
|
|
216
|
+
// `requestIdleCallback` where it exists, a timeout where it does not
|
|
217
|
+
// (Safari). The timeout option matters: without it a busy page can defer
|
|
218
|
+
// an idle callback indefinitely, which is the one outcome worse than
|
|
219
|
+
// scanning at a bad moment.
|
|
220
|
+
if (typeof window.requestIdleCallback === "function") {
|
|
221
|
+
idle = window.requestIdleCallback(function () {
|
|
222
|
+
idle = null;
|
|
223
|
+
scan();
|
|
224
|
+
}, {
|
|
225
|
+
timeout: 1000
|
|
226
|
+
});
|
|
227
|
+
} else {
|
|
228
|
+
idle = window.setTimeout(function () {
|
|
229
|
+
idle = null;
|
|
230
|
+
scan();
|
|
231
|
+
}, 0);
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
var interval = window.setInterval(runWhenIdle, RESCAN_INTERVAL_MS);
|
|
235
|
+
return function () {
|
|
236
|
+
window.clearInterval(interval);
|
|
237
|
+
if (idle === null) return;
|
|
238
|
+
if (typeof window.cancelIdleCallback === "function") {
|
|
239
|
+
window.cancelIdleCallback(idle);
|
|
240
|
+
} else {
|
|
241
|
+
window.clearTimeout(idle);
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
}, [scan]);
|
|
245
|
+
|
|
246
|
+
// What the studio asks for.
|
|
247
|
+
React__default["default"].useEffect(function () {
|
|
248
|
+
var listener = function listener(event) {
|
|
249
|
+
if (!internal.isValCanvasStudioMessage(event.data)) return;
|
|
250
|
+
var message = event.data;
|
|
251
|
+
if (message.type === "rescan") {
|
|
252
|
+
scan();
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
if (message.type === "setPicking") {
|
|
256
|
+
setPicking(message.picking);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
if (message.type === "sourceUpdate") {
|
|
260
|
+
/**
|
|
261
|
+
* Handed straight to the listener the page already has.
|
|
262
|
+
*
|
|
263
|
+
* `ValNextProvider` listens for this event on its own window to make an
|
|
264
|
+
* inline edit visible behind the overlay; the only thing different here
|
|
265
|
+
* is that the edit was made in another window. Re-dispatching rather
|
|
266
|
+
* than reaching into the store keeps one path into the page — including
|
|
267
|
+
* the `router.refresh()` it throttles behind it, which is what brings a
|
|
268
|
+
* server component's own re-read across.
|
|
269
|
+
*/
|
|
270
|
+
window.dispatchEvent(new CustomEvent("val-event", {
|
|
271
|
+
detail: {
|
|
272
|
+
type: "source-update",
|
|
273
|
+
moduleFilePath: message.moduleFilePath,
|
|
274
|
+
source: message.source
|
|
275
|
+
}
|
|
276
|
+
}));
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
if (message.type === "sourcesSynced") {
|
|
280
|
+
// Relayed the same way and for the same reason as `sourceUpdate`: the
|
|
281
|
+
// page is listening on its own window, and the studio is in another.
|
|
282
|
+
window.dispatchEvent(new CustomEvent("val-event", {
|
|
283
|
+
detail: {
|
|
284
|
+
type: "sources-synced"
|
|
285
|
+
}
|
|
286
|
+
}));
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
setHighlighted(message.path);
|
|
290
|
+
if (message.path !== null && message.scrollIntoView) {
|
|
291
|
+
var target = findByPath(message.path);
|
|
292
|
+
target === null || target === void 0 || target.scrollIntoView({
|
|
293
|
+
block: "center",
|
|
294
|
+
behavior: "smooth"
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
window.addEventListener("message", listener);
|
|
299
|
+
return function () {
|
|
300
|
+
return window.removeEventListener("message", listener);
|
|
301
|
+
};
|
|
302
|
+
}, [scan]);
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Picking.
|
|
306
|
+
*
|
|
307
|
+
* Capture phase, and the event is stopped: the point of picking mode is that
|
|
308
|
+
* a click means "this one" rather than what the page would do with it, and a
|
|
309
|
+
* link that navigates has taken the canvas somewhere else before the studio
|
|
310
|
+
* hears anything.
|
|
311
|
+
*/
|
|
312
|
+
React__default["default"].useEffect(function () {
|
|
313
|
+
var onClick = function onClick(event) {
|
|
314
|
+
if (!pickingRef.current) return;
|
|
315
|
+
var target = event.target;
|
|
316
|
+
if (!(target instanceof Element)) return;
|
|
317
|
+
var tagged = target.closest("[data-val-path]");
|
|
318
|
+
var attribute = tagged === null || tagged === void 0 ? void 0 : tagged.getAttribute("data-val-path");
|
|
319
|
+
if (!attribute) return;
|
|
320
|
+
event.preventDefault();
|
|
321
|
+
event.stopPropagation();
|
|
322
|
+
post({
|
|
323
|
+
val: internal.VAL_CANVAS_MESSAGE,
|
|
324
|
+
type: "clicked",
|
|
325
|
+
paths: core.Internal.splitJoinedSourcePaths(attribute)
|
|
326
|
+
});
|
|
327
|
+
};
|
|
328
|
+
document.addEventListener("click", onClick, {
|
|
329
|
+
capture: true
|
|
330
|
+
});
|
|
331
|
+
return function () {
|
|
332
|
+
return document.removeEventListener("click", onClick, {
|
|
333
|
+
capture: true
|
|
334
|
+
});
|
|
335
|
+
};
|
|
336
|
+
}, [post]);
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* The outlines, as a stylesheet rather than as injected elements.
|
|
340
|
+
*
|
|
341
|
+
* A style rule cannot disturb the page's layout, which an absolutely
|
|
342
|
+
* positioned box on top of it eventually would — and the whole value of
|
|
343
|
+
* showing the real page is that it is laid out the way the customer built
|
|
344
|
+
* it. `outline` rather than `border` for the same reason: outlines do not
|
|
345
|
+
* take up space.
|
|
346
|
+
*/
|
|
347
|
+
return /*#__PURE__*/jsxRuntime.jsx("style", {
|
|
348
|
+
// The attribute selector is built from the path, so it is escaped as a
|
|
349
|
+
// CSS string. A path contains quotes (`?p="/"`) and would otherwise
|
|
350
|
+
// close the selector early.
|
|
351
|
+
dangerouslySetInnerHTML: {
|
|
352
|
+
__html: [picking ? "[data-val-path] { outline: 1px solid ".concat(SELECTION_SOFT, "; outline-offset: 1px; cursor: pointer; }\n[data-val-path]:hover { outline: 2px solid ").concat(SELECTION, "; }") : "", highlighted ? highlightRule(highlighted) : ""].filter(Boolean).join("\n")
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* A rule that outlines exactly the elements carrying `path`.
|
|
359
|
+
*
|
|
360
|
+
* The attribute holds a comma-separated list, so this cannot be one `=`
|
|
361
|
+
* comparison; and it cannot be a `*=` substring test either, because a path is
|
|
362
|
+
* a prefix of every path below it. `?p="/blogs/blog1"` is contained in
|
|
363
|
+
* `?p="/blogs/blog1"."title"`, so a substring test on the route would outline
|
|
364
|
+
* every field on the page — which is what it did.
|
|
365
|
+
*
|
|
366
|
+
* Four selectors instead: the whole attribute, the first item, the last item,
|
|
367
|
+
* and one in the middle. Between them they match the path as a complete list
|
|
368
|
+
* item and nothing else.
|
|
369
|
+
*/
|
|
370
|
+
function highlightRule(path) {
|
|
371
|
+
var value = JSON.stringify(path);
|
|
372
|
+
var inner = JSON.stringify(",".concat(path, ","));
|
|
373
|
+
var first = JSON.stringify("".concat(path, ","));
|
|
374
|
+
var last = JSON.stringify(",".concat(path));
|
|
375
|
+
var selectors = ["[data-val-path=".concat(value, "]"), "[data-val-path^=".concat(first, "]"), "[data-val-path$=".concat(last, "]"), "[data-val-path*=".concat(inner, "]")].join(",\n");
|
|
376
|
+
return "".concat(selectors, " { outline: 2px solid ").concat(SELECTION, "; outline-offset: 1px; }");
|
|
377
|
+
}
|
|
378
|
+
function findByPath(path) {
|
|
379
|
+
var elements = document.querySelectorAll("[data-val-path]");
|
|
380
|
+
for (var _i = 0, _Array$from = Array.from(elements); _i < _Array$from.length; _i++) {
|
|
381
|
+
var el = _Array$from[_i];
|
|
382
|
+
var attribute = el.getAttribute("data-val-path");
|
|
383
|
+
if (!attribute) continue;
|
|
384
|
+
// Compared as strings: the split returns branded `SourcePath`s and what
|
|
385
|
+
// came back over `postMessage` is a plain string, which is the same value.
|
|
386
|
+
if (core.Internal.splitJoinedSourcePaths(attribute).some(function (candidate) {
|
|
387
|
+
return candidate === path;
|
|
388
|
+
})) {
|
|
389
|
+
return el;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
return null;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
exports.ValCanvasBridge = ValCanvasBridge;
|