@valbuild/shared 0.150.8 → 0.150.11
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/CHANGELOG.md +30 -0
- package/client/dist/valbuild-shared-client.cjs.dev.js +16 -2
- package/client/dist/valbuild-shared-client.cjs.prod.js +16 -2
- package/client/dist/valbuild-shared-client.esm.js +2 -2
- package/dist/{acquireTypes-dd976839.cjs.prod.js → acquireTypes-6250a305.cjs.prod.js} +46 -46
- package/dist/{acquireTypes-6e2f7961.esm.js → acquireTypes-c2227b23.esm.js} +2 -2
- package/dist/{acquireTypes-84a4077a.cjs.dev.js → acquireTypes-c9e757a1.cjs.dev.js} +46 -46
- package/dist/{slicedToArray-22567815.esm.js → createForOfIteratorHelper-9b80f1a2.esm.js} +136 -106
- package/dist/{slicedToArray-d99b4e2e.cjs.prod.js → createForOfIteratorHelper-9ca2078d.cjs.prod.js} +142 -111
- package/dist/{slicedToArray-c8a29f6b.cjs.dev.js → createForOfIteratorHelper-f2d7ac6d.cjs.dev.js} +142 -111
- package/dist/declarations/src/client/index.d.ts +2 -0
- package/dist/declarations/src/internal/ApiRoutes.d.ts +23 -0
- package/dist/declarations/src/internal/index.d.ts +2 -0
- package/dist/declarations/src/internal/pageInspection.d.ts +117 -0
- package/dist/declarations/src/internal/quickPreview.d.ts +91 -0
- package/dist/declarations/src/internal/valCanvasProtocol.d.ts +53 -0
- package/dist/declarations/src/publish/buildProposal.d.ts +16 -1
- package/dist/declarations/src/publish/buildQuickPreview.d.ts +46 -0
- package/dist/declarations/src/publish/index.d.ts +3 -2
- package/dist/declarations/src/publish/runStudioDeploy.d.ts +10 -0
- package/dist/getSitemapTree-5354ce90.cjs.prod.js +1421 -0
- package/dist/getSitemapTree-97b3166f.esm.js +1381 -0
- package/dist/getSitemapTree-d934ff9c.cjs.dev.js +1421 -0
- package/dist/{proposalProject-689c24cc.esm.js → proposalProject-5da177d5.esm.js} +1 -2
- package/dist/{proposalProject-926f2c68.cjs.dev.js → proposalProject-76caa377.cjs.prod.js} +2 -3
- package/dist/{proposalProject-fab0c026.cjs.prod.js → proposalProject-81fee08f.cjs.dev.js} +2 -3
- package/dist/{protocol-7ddc1a71.esm.js → protocol-55cfa3cf.esm.js} +1 -1
- package/dist/{protocol-4e2a455b.cjs.prod.js → protocol-b1055ef0.cjs.prod.js} +6 -6
- package/dist/{protocol-ac1c3ec7.cjs.dev.js → protocol-d0efb8cd.cjs.dev.js} +6 -6
- package/dist/wrapNativeSuper-639b12b7.esm.js +107 -0
- package/dist/wrapNativeSuper-8673414f.cjs.prod.js +113 -0
- package/dist/wrapNativeSuper-933f991e.cjs.dev.js +113 -0
- package/internal/dist/valbuild-shared-internal.cjs.dev.js +72 -34
- package/internal/dist/valbuild-shared-internal.cjs.prod.js +72 -34
- package/internal/dist/valbuild-shared-internal.esm.js +30 -7
- package/package.json +2 -2
- package/publish/dist/valbuild-shared-publish.cjs.dev.js +589 -237
- package/publish/dist/valbuild-shared-publish.cjs.prod.js +589 -237
- package/publish/dist/valbuild-shared-publish.esm.js +504 -155
- package/typecheck/dist/valbuild-shared-typecheck.cjs.dev.js +34 -34
- package/typecheck/dist/valbuild-shared-typecheck.cjs.prod.js +34 -34
- package/typecheck/dist/valbuild-shared-typecheck.esm.js +5 -5
- package/typecheck/testing/dist/valbuild-shared-typecheck-testing.cjs.dev.js +7 -7
- package/typecheck/testing/dist/valbuild-shared-typecheck-testing.cjs.prod.js +7 -7
- package/typecheck/testing/dist/valbuild-shared-typecheck-testing.esm.js +3 -3
- package/dist/createForOfIteratorHelper-666a6d17.esm.js +0 -137
- package/dist/createForOfIteratorHelper-87a33eff.cjs.dev.js +0 -145
- package/dist/createForOfIteratorHelper-fef4fa7d.cjs.prod.js +0 -145
- package/dist/getSitemapTree-873f7266.cjs.prod.js +0 -743
- package/dist/getSitemapTree-b6161fd8.esm.js +0 -717
- package/dist/getSitemapTree-be70d9fc.cjs.dev.js +0 -743
|
@@ -1,743 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var createForOfIteratorHelper = require('./createForOfIteratorHelper-fef4fa7d.cjs.prod.js');
|
|
4
|
-
var core = require('@valbuild/core');
|
|
5
|
-
|
|
6
|
-
var VAL_CONFIG_SESSION_STORAGE_KEY = "val-config";
|
|
7
|
-
var VAL_THEME_SESSION_STORAGE_KEY = "val-theme";
|
|
8
|
-
var VAL_AI_SESSION_STORAGE_KEY = "val-ai-session";
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* The protocol between the studio's canvas and the page inside it.
|
|
12
|
-
*
|
|
13
|
-
* The canvas shows the running site in a frame. That frame is a different
|
|
14
|
-
* document — the customer's app, rendered by their components — so the studio
|
|
15
|
-
* cannot reach into it, and it cannot reach out. Everything they say to each
|
|
16
|
-
* other goes through `postMessage`, and this is the vocabulary.
|
|
17
|
-
*
|
|
18
|
-
* It lives in `shared` because both halves have to agree on it: the page half
|
|
19
|
-
* ships in `@valbuild/next`, the studio half in `@valbuild/ui`, and a message
|
|
20
|
-
* shape defined twice is a message shape that will differ once.
|
|
21
|
-
*
|
|
22
|
-
* ## Why a query parameter turns it on
|
|
23
|
-
*
|
|
24
|
-
* The frame has to render the page as Val sees it — draft content, with
|
|
25
|
-
* `data-val-path` on every element Val tracks — while *not* showing Val's own
|
|
26
|
-
* overlay, because the studio is already the UI. Nothing about the cookies can
|
|
27
|
-
* express that: they are per-origin, and the studio and the page share an
|
|
28
|
-
* origin, so a cookie would change the customer's own tabs too. A parameter on
|
|
29
|
-
* the frame's URL is scoped to exactly the one document that needs it.
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
/** Marks a page load as the studio's canvas frame. */
|
|
33
|
-
var VAL_CANVAS_PARAM = "val_canvas";
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Every message is tagged with this, and the tag is checked on receipt.
|
|
37
|
-
*
|
|
38
|
-
* A window receives messages from anything that has a handle on it —
|
|
39
|
-
* extensions, embeds, other frames — and `event.data` is whatever they chose to
|
|
40
|
-
* send. Checking a discriminator before reading anything else is what keeps a
|
|
41
|
-
* stray message from being read as a canvas instruction.
|
|
42
|
-
*/
|
|
43
|
-
var VAL_CANVAS_MESSAGE = "val-canvas";
|
|
44
|
-
|
|
45
|
-
/** One element on the page that Val has a path for. */
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* The colours Val outlines the page's content in, when nobody has said
|
|
49
|
-
* otherwise.
|
|
50
|
-
*
|
|
51
|
-
* They mirror `--bg-page-selection` and `--bg-page-selection-soft` in
|
|
52
|
-
* `packages/ui/spa/index.css`, and they are literals here because the page the
|
|
53
|
-
* bridge runs in has none of Val's stylesheet — no `:host`, no tokens, nothing
|
|
54
|
-
* to inherit. A CSS custom property genuinely cannot reach across that
|
|
55
|
-
* boundary, which is why the colours are SENT (see the `theme` message below)
|
|
56
|
-
* rather than derived.
|
|
57
|
-
*
|
|
58
|
-
* They live beside the protocol rather than with the theme code on purpose:
|
|
59
|
-
* `@valbuild/shared/client` is what the bridge imports, and it exists to keep
|
|
60
|
-
* production bundles small (see the docblock on that entrypoint). Two strings
|
|
61
|
-
* cost nothing; the accent generator that produces the non-default values is
|
|
62
|
-
* ~350 lines of colour maths that no visitor to a Val site should download.
|
|
63
|
-
*
|
|
64
|
-
* `canvasSelectionDefaults.test.ts` holds them equal to the stylesheet.
|
|
65
|
-
*/
|
|
66
|
-
var DEFAULT_CANVAS_SELECTION = "#079455";
|
|
67
|
-
var DEFAULT_CANVAS_SELECTION_SOFT = "rgba(7, 148, 85, 0.4)";
|
|
68
|
-
|
|
69
|
-
/** What the page tells the studio. */
|
|
70
|
-
|
|
71
|
-
/** What the studio tells the page. */
|
|
72
|
-
|
|
73
|
-
/** Narrow an unknown `event.data` to a message from the page. */
|
|
74
|
-
function isValCanvasPageMessage(data) {
|
|
75
|
-
if (createForOfIteratorHelper._typeof(data) !== "object" || data === null) return false;
|
|
76
|
-
var message = data;
|
|
77
|
-
if (message.val !== VAL_CANVAS_MESSAGE) return false;
|
|
78
|
-
return message.type === "ready" || message.type === "elements" || message.type === "clicked" || message.type === "pinch" || message.type === "zoom" || message.type === "refreshing" || message.type === "elementPickingStopped" || message.type === "elementPicked" && isPickedElement(data.element);
|
|
79
|
-
}
|
|
80
|
-
function isPickedElement(value) {
|
|
81
|
-
if (createForOfIteratorHelper._typeof(value) !== "object" || value === null) return false;
|
|
82
|
-
var element = value;
|
|
83
|
-
return typeof element.tag === "string" && typeof element.text === "string" && typeof element.selector === "string" && Array.isArray(element.classes) && element.classes.every(function (item) {
|
|
84
|
-
return typeof item === "string";
|
|
85
|
-
}) && (element.valPath === undefined || typeof element.valPath === "string");
|
|
86
|
-
}
|
|
87
|
-
var PICK_MODIFIERS = ["alt", "meta", "shift", "ctrl"];
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Whether a value is a colour a `theme` message may carry.
|
|
91
|
-
*
|
|
92
|
-
* A whitelist rather than an escape, and the reason is where these two strings
|
|
93
|
-
* end up: the bridge writes them into a `<style>` element in the CUSTOMER's
|
|
94
|
-
* document with `dangerouslySetInnerHTML`, so a value containing `</style>` is
|
|
95
|
-
* a script tag away from running in someone else's page. A page can be
|
|
96
|
-
* `postMessage`d by any window holding a handle on it, and this guard is the
|
|
97
|
-
* only thing between such a message and that sink.
|
|
98
|
-
*
|
|
99
|
-
* The two shapes are exactly what `themeCustomProperties` produces — a hex, and
|
|
100
|
-
* the `rgba()` it derives the soft outline as. Narrowing the contract is easier
|
|
101
|
-
* to keep true than sanitising an open one, and a forged message that passes
|
|
102
|
-
* this can do no more than pick a different colour.
|
|
103
|
-
*/
|
|
104
|
-
var CANVAS_SELECTION_COLOR = /^(?:#[0-9a-f]{3,8}|rgba?\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*(?:,\s*(?:0|1|0?\.\d+)\s*)?\))$/i;
|
|
105
|
-
function isCanvasSelectionColor(value) {
|
|
106
|
-
return typeof value === "string" && CANVAS_SELECTION_COLOR.test(value);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/** Narrow an unknown `event.data` to a message from the studio. */
|
|
110
|
-
function isValCanvasStudioMessage(data) {
|
|
111
|
-
if (createForOfIteratorHelper._typeof(data) !== "object" || data === null) return false;
|
|
112
|
-
var message = data;
|
|
113
|
-
if (message.val !== VAL_CANVAS_MESSAGE) return false;
|
|
114
|
-
if (message.type === "theme") {
|
|
115
|
-
// Checked here and not in the bridge: a rejected message is never applied
|
|
116
|
-
// at all, and there is one guard rather than one per framework binding.
|
|
117
|
-
return isCanvasSelectionColor(message.selection) && isCanvasSelectionColor(message.selectionSoft);
|
|
118
|
-
}
|
|
119
|
-
if (message.type === "pickElements") {
|
|
120
|
-
var pick = data;
|
|
121
|
-
return typeof pick.enabled === "boolean" && typeof pick.active === "boolean" && typeof pick.keepPicked === "boolean" && PICK_MODIFIERS.includes(pick.modifier);
|
|
122
|
-
}
|
|
123
|
-
return message.type === "rescan" || message.type === "highlight" || message.type === "setPicking" || message.type === "sourceUpdate" || message.type === "sourcesSynced";
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Whether this document is showing in the studio's canvas frame.
|
|
128
|
-
*
|
|
129
|
-
* The parameter marks the document the studio LOADED, and that is not always
|
|
130
|
-
* the document the frame ends up holding. A frame navigates on its own: a site
|
|
131
|
-
* with a login of its own redirects a signed-out canvas to its sign-in page,
|
|
132
|
-
* and the sign-in sends it back to wherever the site chooses. Each of those is
|
|
133
|
-
* a new document without the parameter, and it used to render Val's whole
|
|
134
|
-
* overlay inside the canvas — a studio in the studio, which never told the
|
|
135
|
-
* canvas it was there, so the canvas never went live again until reloaded.
|
|
136
|
-
*
|
|
137
|
-
* So where the frame SITS answers too: a document whose parent is the studio
|
|
138
|
-
* is in the canvas, whatever its own address says. `parentPathname` is that
|
|
139
|
-
* parent's path: `null` for a top-level document, and for a parent on another
|
|
140
|
-
* origin, whose `location` cannot be read and which is not the studio anyway.
|
|
141
|
-
*/
|
|
142
|
-
function isValCanvasFrame(search) {
|
|
143
|
-
var parentPathname = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
144
|
-
if (parentPathname !== null && isValStudioPathname(parentPathname)) {
|
|
145
|
-
return true;
|
|
146
|
-
}
|
|
147
|
-
try {
|
|
148
|
-
return new URLSearchParams(search).get(VAL_CANVAS_PARAM) !== null;
|
|
149
|
-
} catch (_unused) {
|
|
150
|
-
return false;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/** Whether a path is the studio's own route, where the canvas lives. */
|
|
155
|
-
function isValStudioPathname(pathname) {
|
|
156
|
-
return pathname === "/val" || pathname.startsWith("/val/");
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/** Add the canvas marker to a page URL. */
|
|
160
|
-
function withValCanvasParam(url) {
|
|
161
|
-
var separator = url.includes("?") ? "&" : "?";
|
|
162
|
-
return "".concat(url).concat(separator).concat(VAL_CANVAS_PARAM, "=1");
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Pointing at anything on a page, as Lovable's picker does: hover outlines
|
|
167
|
-
* the element under the pointer, a click picks it, and the assistant is told
|
|
168
|
-
* which (valbuild/home `docs/design-tab.md`).
|
|
169
|
-
*
|
|
170
|
-
* ANY element, not only what Val marks. The design tab changes code, and the
|
|
171
|
-
* thing a person wants changed is as often a wrapper, a gap or a button as a
|
|
172
|
-
* field -- so a field's path is extra information when there is one
|
|
173
|
-
* (`valPath`), never the condition for picking.
|
|
174
|
-
*
|
|
175
|
-
* Picking is on while a MODIFIER is held, so the page stays a page: links
|
|
176
|
-
* follow, menus open, and nothing has to be switched back off. `active`
|
|
177
|
-
* turns it on without one, for a Select button or a touch screen.
|
|
178
|
-
*
|
|
179
|
-
* Plain DOM, nothing of React's or the Studio's, and in `shared` because
|
|
180
|
-
* both halves need it: the canvas bridge (`@valbuild/next`,
|
|
181
|
-
* `@valbuild/tanstack`) runs it inside the proposal's page, which is another
|
|
182
|
-
* origin than the design tab and the only place the page's elements can be
|
|
183
|
-
* reached; the Studio's stories run it on a page of their own. Only the
|
|
184
|
-
* `PickedElement` crosses the frame (`valCanvasProtocol.ts`).
|
|
185
|
-
*/
|
|
186
|
-
|
|
187
|
-
var TEXT_LENGTH = 80;
|
|
188
|
-
var CLASSES = 6;
|
|
189
|
-
function describeElement(element, root) {
|
|
190
|
-
var _element$textContent, _element$closest$getA, _element$closest;
|
|
191
|
-
var text = ((_element$textContent = element.textContent) !== null && _element$textContent !== void 0 ? _element$textContent : "").replace(/\s+/g, " ").trim();
|
|
192
|
-
var valPath = (_element$closest$getA = (_element$closest = element.closest("[data-val-path]")) === null || _element$closest === void 0 ? void 0 : _element$closest.getAttribute("data-val-path")) !== null && _element$closest$getA !== void 0 ? _element$closest$getA : undefined;
|
|
193
|
-
return createForOfIteratorHelper._objectSpread2({
|
|
194
|
-
tag: element.tagName.toLowerCase(),
|
|
195
|
-
text: text.length > TEXT_LENGTH ? "".concat(text.slice(0, TEXT_LENGTH - 1), "\u2026") : text,
|
|
196
|
-
classes: Array.from(element.classList).slice(0, CLASSES),
|
|
197
|
-
selector: selectorOf(element, root)
|
|
198
|
-
}, valPath !== undefined ? {
|
|
199
|
-
valPath: valPath
|
|
200
|
-
} : {});
|
|
201
|
-
}
|
|
202
|
-
function selectorOf(element, root) {
|
|
203
|
-
var parts = [];
|
|
204
|
-
var at = element;
|
|
205
|
-
while (at !== null && at !== root) {
|
|
206
|
-
var tag = at.tagName.toLowerCase();
|
|
207
|
-
if (at.id !== "") {
|
|
208
|
-
parts.unshift("".concat(tag, "#").concat(at.id));
|
|
209
|
-
break;
|
|
210
|
-
}
|
|
211
|
-
var parent = at.parentElement;
|
|
212
|
-
var same = parent === null ? [] : Array.from(parent.children).filter(function (sibling) {
|
|
213
|
-
var _at;
|
|
214
|
-
return sibling.tagName === ((_at = at) === null || _at === void 0 ? void 0 : _at.tagName);
|
|
215
|
-
});
|
|
216
|
-
parts.unshift(same.length > 1 ? "".concat(tag, ":nth-of-type(").concat(same.indexOf(at) + 1, ")") : tag);
|
|
217
|
-
at = parent;
|
|
218
|
-
}
|
|
219
|
-
return parts.join(" > ");
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/** What a person is told to hold, on their own keyboard. */
|
|
223
|
-
function modifierLabel(modifier, mac) {
|
|
224
|
-
switch (modifier) {
|
|
225
|
-
case "alt":
|
|
226
|
-
return mac ? "⌥" : "Alt";
|
|
227
|
-
case "meta":
|
|
228
|
-
return mac ? "⌘" : "Win";
|
|
229
|
-
case "shift":
|
|
230
|
-
return mac ? "⇧" : "Shift";
|
|
231
|
-
case "ctrl":
|
|
232
|
-
return mac ? "⌃" : "Ctrl";
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
function held(event, modifier) {
|
|
236
|
-
switch (modifier) {
|
|
237
|
-
case "alt":
|
|
238
|
-
return event.altKey;
|
|
239
|
-
case "meta":
|
|
240
|
-
return event.metaKey;
|
|
241
|
-
case "shift":
|
|
242
|
-
return event.shiftKey;
|
|
243
|
-
case "ctrl":
|
|
244
|
-
return event.ctrlKey;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* Listens on `root` (capturing, so the page's own handlers never see a pick)
|
|
249
|
-
* and returns what stops it.
|
|
250
|
-
*/
|
|
251
|
-
function attachElementPicker(root, options) {
|
|
252
|
-
var win = root.ownerDocument.defaultView;
|
|
253
|
-
var last = null;
|
|
254
|
-
var picking = function picking(event) {
|
|
255
|
-
return options.active() || held(event, options.modifier);
|
|
256
|
-
};
|
|
257
|
-
var target = function target(event) {
|
|
258
|
-
return event.target instanceof Element && root.contains(event.target) ? event.target : null;
|
|
259
|
-
};
|
|
260
|
-
var onMove = function onMove(event) {
|
|
261
|
-
last = {
|
|
262
|
-
x: event.clientX,
|
|
263
|
-
y: event.clientY
|
|
264
|
-
};
|
|
265
|
-
options.onHover(picking(event) ? target(event) : null);
|
|
266
|
-
};
|
|
267
|
-
var onClick = function onClick(event) {
|
|
268
|
-
if (!picking(event)) return;
|
|
269
|
-
var element = target(event);
|
|
270
|
-
if (element === null) return;
|
|
271
|
-
event.preventDefault();
|
|
272
|
-
event.stopPropagation();
|
|
273
|
-
options.onPick(element);
|
|
274
|
-
};
|
|
275
|
-
// Pressing the modifier with the pointer still: outline what is under it
|
|
276
|
-
// now, rather than after the next move.
|
|
277
|
-
var onKey = function onKey(event) {
|
|
278
|
-
if (!picking(event)) {
|
|
279
|
-
options.onHover(null);
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
if (last === null) return;
|
|
283
|
-
var under = root.ownerDocument.elementFromPoint(last.x, last.y);
|
|
284
|
-
options.onHover(under !== null && root.contains(under) ? under : null);
|
|
285
|
-
};
|
|
286
|
-
var onLeave = function onLeave() {
|
|
287
|
-
last = null;
|
|
288
|
-
options.onHover(null);
|
|
289
|
-
};
|
|
290
|
-
root.addEventListener("mousemove", onMove, true);
|
|
291
|
-
root.addEventListener("click", onClick, true);
|
|
292
|
-
root.addEventListener("mouseleave", onLeave);
|
|
293
|
-
win === null || win === void 0 || win.addEventListener("keydown", onKey, true);
|
|
294
|
-
win === null || win === void 0 || win.addEventListener("keyup", onKey, true);
|
|
295
|
-
return function () {
|
|
296
|
-
root.removeEventListener("mousemove", onMove, true);
|
|
297
|
-
root.removeEventListener("click", onClick, true);
|
|
298
|
-
root.removeEventListener("mouseleave", onLeave);
|
|
299
|
-
win === null || win === void 0 || win.removeEventListener("keydown", onKey, true);
|
|
300
|
-
win === null || win === void 0 || win.removeEventListener("keyup", onKey, true);
|
|
301
|
-
};
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* The outlines over the page while picking: the element under the pointer,
|
|
306
|
-
* named, and the one picked.
|
|
307
|
-
*
|
|
308
|
-
* Boxes `position: fixed` on top of everything, with `pointer-events: none`,
|
|
309
|
-
* appended to the page's body -- not outlines on the elements themselves.
|
|
310
|
-
* The canvas's field outlines are a stylesheet so they cannot disturb the
|
|
311
|
-
* page's layout (`ValCanvasBridge`); a fixed box is out of the flow, so it
|
|
312
|
-
* cannot either, and it is the one way to put a NAME beside any element, which
|
|
313
|
-
* a selector cannot reach.
|
|
314
|
-
*
|
|
315
|
-
* In a shadow root of one host element: the bridge re-measures the page on
|
|
316
|
-
* every `style` change under `body`, and a box that follows the pointer
|
|
317
|
-
* changes its style every frame. Inside a shadow root those changes are not
|
|
318
|
-
* the page's, so the host's one insertion is all the bridge sees.
|
|
319
|
-
*/
|
|
320
|
-
|
|
321
|
-
var TOP = "2147483647";
|
|
322
|
-
function createPickerOverlay(doc, initialColor) {
|
|
323
|
-
var color = initialColor;
|
|
324
|
-
var shown = {
|
|
325
|
-
hover: null,
|
|
326
|
-
picked: null
|
|
327
|
-
};
|
|
328
|
-
var host = doc.createElement("div");
|
|
329
|
-
host.setAttribute("data-val-picker", "");
|
|
330
|
-
var shadow = host.attachShadow({
|
|
331
|
-
mode: "open"
|
|
332
|
-
});
|
|
333
|
-
doc.body.appendChild(host);
|
|
334
|
-
var box = function box(kind) {
|
|
335
|
-
var el = doc.createElement("div");
|
|
336
|
-
el.setAttribute("data-kind", kind);
|
|
337
|
-
Object.assign(el.style, {
|
|
338
|
-
position: "fixed",
|
|
339
|
-
pointerEvents: "none",
|
|
340
|
-
zIndex: TOP,
|
|
341
|
-
boxSizing: "border-box",
|
|
342
|
-
display: "none"
|
|
343
|
-
});
|
|
344
|
-
shadow.appendChild(el);
|
|
345
|
-
return el;
|
|
346
|
-
};
|
|
347
|
-
var boxes = {
|
|
348
|
-
hover: box("hover"),
|
|
349
|
-
picked: box("picked")
|
|
350
|
-
};
|
|
351
|
-
var label = doc.createElement("span");
|
|
352
|
-
Object.assign(label.style, {
|
|
353
|
-
position: "absolute",
|
|
354
|
-
left: "-2px",
|
|
355
|
-
padding: "1px 4px",
|
|
356
|
-
borderRadius: "2px",
|
|
357
|
-
font: "500 10px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
358
|
-
color: "#fff",
|
|
359
|
-
whiteSpace: "nowrap"
|
|
360
|
-
});
|
|
361
|
-
boxes.hover.appendChild(label);
|
|
362
|
-
// The pointer says it is picking, and a link under it is not a link.
|
|
363
|
-
var cursor = doc.createElement("style");
|
|
364
|
-
cursor.textContent = "[data-val-picking] * { cursor: crosshair !important; }";
|
|
365
|
-
doc.head.appendChild(cursor);
|
|
366
|
-
var place = function place(kind) {
|
|
367
|
-
var element = shown[kind];
|
|
368
|
-
var el = boxes[kind];
|
|
369
|
-
if (element === null || !element.isConnected) {
|
|
370
|
-
el.style.display = "none";
|
|
371
|
-
return;
|
|
372
|
-
}
|
|
373
|
-
var rect = element.getBoundingClientRect();
|
|
374
|
-
Object.assign(el.style, {
|
|
375
|
-
display: "block",
|
|
376
|
-
top: "".concat(rect.top - 2, "px"),
|
|
377
|
-
left: "".concat(rect.left - 2, "px"),
|
|
378
|
-
width: "".concat(rect.width + 4, "px"),
|
|
379
|
-
height: "".concat(rect.height + 4, "px"),
|
|
380
|
-
border: "2px ".concat(kind === "hover" ? "solid" : "dashed", " ").concat(color)
|
|
381
|
-
});
|
|
382
|
-
if (kind === "hover") {
|
|
383
|
-
label.textContent = elementLabel(element);
|
|
384
|
-
label.style.background = color;
|
|
385
|
-
// Above the box, unless that is off the top of the window.
|
|
386
|
-
if (rect.top >= 18) {
|
|
387
|
-
label.style.top = "";
|
|
388
|
-
label.style.bottom = "100%";
|
|
389
|
-
} else {
|
|
390
|
-
label.style.bottom = "";
|
|
391
|
-
label.style.top = "100%";
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
};
|
|
395
|
-
var frame = null;
|
|
396
|
-
var win = doc.defaultView;
|
|
397
|
-
var reposition = function reposition() {
|
|
398
|
-
if (frame !== null || win === null) return;
|
|
399
|
-
frame = win.requestAnimationFrame(function () {
|
|
400
|
-
frame = null;
|
|
401
|
-
place("hover");
|
|
402
|
-
place("picked");
|
|
403
|
-
});
|
|
404
|
-
};
|
|
405
|
-
win === null || win === void 0 || win.addEventListener("scroll", reposition, true);
|
|
406
|
-
win === null || win === void 0 || win.addEventListener("resize", reposition);
|
|
407
|
-
return {
|
|
408
|
-
show: function show(kind, element) {
|
|
409
|
-
shown[kind] = element;
|
|
410
|
-
if (kind === "hover") {
|
|
411
|
-
if (element !== null) {
|
|
412
|
-
doc.documentElement.setAttribute("data-val-picking", "");
|
|
413
|
-
} else {
|
|
414
|
-
doc.documentElement.removeAttribute("data-val-picking");
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
place(kind);
|
|
418
|
-
},
|
|
419
|
-
setColor: function setColor(next) {
|
|
420
|
-
color = next;
|
|
421
|
-
place("hover");
|
|
422
|
-
place("picked");
|
|
423
|
-
},
|
|
424
|
-
destroy: function destroy() {
|
|
425
|
-
if (frame !== null) win === null || win === void 0 || win.cancelAnimationFrame(frame);
|
|
426
|
-
win === null || win === void 0 || win.removeEventListener("scroll", reposition, true);
|
|
427
|
-
win === null || win === void 0 || win.removeEventListener("resize", reposition);
|
|
428
|
-
host.remove();
|
|
429
|
-
cursor.remove();
|
|
430
|
-
doc.documentElement.removeAttribute("data-val-picking");
|
|
431
|
-
}
|
|
432
|
-
};
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
/** `h2.mb-6.text-2xl`: what the hover box is named. */
|
|
436
|
-
function elementLabel(element) {
|
|
437
|
-
var classes = Array.from(element.classList).slice(0, 2);
|
|
438
|
-
return [element.tagName.toLowerCase()].concat(createForOfIteratorHelper._toConsumableArray(classes)).join(".");
|
|
439
|
-
}
|
|
440
|
-
/**
|
|
441
|
-
* Picking on a page, whole: the listeners, the outlines, and Esc to stop
|
|
442
|
-
* picking without the modifier. What a canvas bridge mounts.
|
|
443
|
-
*/
|
|
444
|
-
function startElementPicking(root, options) {
|
|
445
|
-
var _doc$defaultView;
|
|
446
|
-
var doc = root.ownerDocument;
|
|
447
|
-
var overlay = createPickerOverlay(doc, options.color);
|
|
448
|
-
var detach = attachElementPicker(root, {
|
|
449
|
-
modifier: options.modifier,
|
|
450
|
-
active: options.active,
|
|
451
|
-
onHover: function onHover(element) {
|
|
452
|
-
return overlay.show("hover", element);
|
|
453
|
-
},
|
|
454
|
-
onPick: function onPick(element) {
|
|
455
|
-
overlay.show("hover", null);
|
|
456
|
-
overlay.show("picked", element);
|
|
457
|
-
options.onPick(describeElement(element, root));
|
|
458
|
-
}
|
|
459
|
-
});
|
|
460
|
-
var onKey = function onKey(event) {
|
|
461
|
-
if (event.key === "Escape" && options.active()) options.onStop();
|
|
462
|
-
};
|
|
463
|
-
(_doc$defaultView = doc.defaultView) === null || _doc$defaultView === void 0 || _doc$defaultView.addEventListener("keydown", onKey);
|
|
464
|
-
return {
|
|
465
|
-
clearPicked: function clearPicked() {
|
|
466
|
-
return overlay.show("picked", null);
|
|
467
|
-
},
|
|
468
|
-
setColor: overlay.setColor,
|
|
469
|
-
stop: function stop() {
|
|
470
|
-
var _doc$defaultView2;
|
|
471
|
-
(_doc$defaultView2 = doc.defaultView) === null || _doc$defaultView2 === void 0 || _doc$defaultView2.removeEventListener("keydown", onKey);
|
|
472
|
-
detach();
|
|
473
|
-
overlay.destroy();
|
|
474
|
-
}
|
|
475
|
-
};
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
function parseRoutePattern(pattern) {
|
|
479
|
-
if (pattern === "" || pattern === "/") {
|
|
480
|
-
return [];
|
|
481
|
-
}
|
|
482
|
-
var p = pattern.startsWith("/") ? pattern.slice(1) : pattern;
|
|
483
|
-
return p.split("/").map(function (part) {
|
|
484
|
-
var isOptionalParam = part.startsWith("[[") && part.endsWith("]]");
|
|
485
|
-
var isNonOptionalParam = part.startsWith("[") && part.endsWith("]");
|
|
486
|
-
var nameStart = isOptionalParam ? 2 : isNonOptionalParam ? 1 : 0;
|
|
487
|
-
var nameEnd = part.indexOf("]", nameStart);
|
|
488
|
-
var isArrayParam = part.slice(nameStart, nameStart + 3) === "...";
|
|
489
|
-
var paramName = part.slice(nameStart + (isArrayParam ? 3 : 0), nameEnd);
|
|
490
|
-
if (isOptionalParam || isNonOptionalParam) {
|
|
491
|
-
if (isArrayParam) {
|
|
492
|
-
return {
|
|
493
|
-
type: "array-param",
|
|
494
|
-
paramName: paramName,
|
|
495
|
-
optional: isOptionalParam
|
|
496
|
-
};
|
|
497
|
-
} else {
|
|
498
|
-
return {
|
|
499
|
-
type: "string-param",
|
|
500
|
-
paramName: paramName,
|
|
501
|
-
optional: isOptionalParam
|
|
502
|
-
};
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
return {
|
|
506
|
-
type: "literal",
|
|
507
|
-
name: part
|
|
508
|
-
};
|
|
509
|
-
});
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
/**
|
|
513
|
-
* A parsed pattern written back as segments: the inverse of
|
|
514
|
-
* {@link parseRoutePattern}, in the vocabulary core's `matchRoutePattern`
|
|
515
|
-
* reads.
|
|
516
|
-
*/
|
|
517
|
-
function formatRoutePattern(pattern) {
|
|
518
|
-
return pattern.map(function (part) {
|
|
519
|
-
if (part.type === "literal") {
|
|
520
|
-
return part.name;
|
|
521
|
-
}
|
|
522
|
-
var inner = part.type === "string-param" ? part.paramName : "...".concat(part.paramName);
|
|
523
|
-
return part.optional ? "[[".concat(inner, "]]") : "[".concat(inner, "]");
|
|
524
|
-
});
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
function getNextAppRouterSourceFolder(moduleFilePath) {
|
|
528
|
-
if (moduleFilePath.startsWith("/app")) {
|
|
529
|
-
return "/app";
|
|
530
|
-
} else if (moduleFilePath.startsWith("/src/app")) {
|
|
531
|
-
return "/src/app";
|
|
532
|
-
}
|
|
533
|
-
return null;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
/**
|
|
537
|
-
* The folder a TanStack Router app keeps its route files in.
|
|
538
|
-
*
|
|
539
|
-
* The same question as above for the other convention: `routes/` at the project
|
|
540
|
-
* root, or under `src/`. A Val module for a route lives beside the route file
|
|
541
|
-
* and is named the same way, so this is the prefix to strip before reading the
|
|
542
|
-
* route pattern out of the rest.
|
|
543
|
-
*/
|
|
544
|
-
function getTanStackRouterSourceFolder(moduleFilePath) {
|
|
545
|
-
if (moduleFilePath.startsWith("/routes/")) {
|
|
546
|
-
return "/routes";
|
|
547
|
-
} else if (moduleFilePath.startsWith("/src/routes/")) {
|
|
548
|
-
return "/src/routes";
|
|
549
|
-
}
|
|
550
|
-
return null;
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
/**
|
|
554
|
-
* The route folder of whichever page router this module belongs to.
|
|
555
|
-
*
|
|
556
|
-
* The two conventions have disjoint prefixes — `app/` versus `routes/` — so a
|
|
557
|
-
* module file path answers this on its own, which is what the Studio needs: it
|
|
558
|
-
* walks every schema in the project and has no framework to ask.
|
|
559
|
-
*/
|
|
560
|
-
function getPageRouterSourceFolder(moduleFilePath) {
|
|
561
|
-
var _getNextAppRouterSour;
|
|
562
|
-
return (_getNextAppRouterSour = getNextAppRouterSourceFolder(moduleFilePath)) !== null && _getNextAppRouterSour !== void 0 ? _getNextAppRouterSour : getTanStackRouterSourceFolder(moduleFilePath);
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
/**
|
|
566
|
-
* Whether a route folder is a TanStack Router one.
|
|
567
|
-
*
|
|
568
|
-
* Exported so the pattern derivation and the source-folder detection cannot
|
|
569
|
-
* drift apart about what `/src/routes` means.
|
|
570
|
-
*/
|
|
571
|
-
function isTanStackRoutesFolder(srcFolder) {
|
|
572
|
-
return srcFolder === "/routes" || srcFolder === "/src/routes";
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
// Strictly speaking this should be in the framework packages but it's shared,
|
|
576
|
-
// because we want to use it in the ui package. We want to resolve that somehow.
|
|
577
|
-
//
|
|
578
|
-
// It is one function for both page routers because the tree it builds is made
|
|
579
|
-
// of URL paths, which is the same thing in either: only `srcFolder` and the
|
|
580
|
-
// pattern derivation differ, and both of those are arguments (or the one call
|
|
581
|
-
// below).
|
|
582
|
-
function getPageRouterSitemapTree(srcFolder, paths) {
|
|
583
|
-
var root = {
|
|
584
|
-
type: "node",
|
|
585
|
-
name: "/",
|
|
586
|
-
children: []
|
|
587
|
-
};
|
|
588
|
-
var _iterator = createForOfIteratorHelper._createForOfIteratorHelper(paths),
|
|
589
|
-
_step;
|
|
590
|
-
try {
|
|
591
|
-
var _loop = function _loop() {
|
|
592
|
-
var path = _step.value;
|
|
593
|
-
var urlPath = path.urlPath,
|
|
594
|
-
moduleFilePathS = path.moduleFilePath;
|
|
595
|
-
var moduleFilePath = moduleFilePathS;
|
|
596
|
-
if (!urlPath.startsWith("/")) {
|
|
597
|
-
core.Internal.log.error("urlPath must start with /: ".concat(urlPath));
|
|
598
|
-
return 0; // continue
|
|
599
|
-
}
|
|
600
|
-
var pattern = getPatternFromModuleFilePath(moduleFilePath, srcFolder);
|
|
601
|
-
if (urlPath === "/") {
|
|
602
|
-
var fullPath = "/";
|
|
603
|
-
root.pattern = getPatternFromModuleFilePath(moduleFilePath, srcFolder);
|
|
604
|
-
root.page = {
|
|
605
|
-
fullPath: fullPath
|
|
606
|
-
};
|
|
607
|
-
root.sourcePath = core.Internal.joinModuleFilePathAndModulePath(moduleFilePath, "\"".concat(fullPath, "\""));
|
|
608
|
-
root.moduleFilePath = moduleFilePath;
|
|
609
|
-
return 0; // continue
|
|
610
|
-
}
|
|
611
|
-
var pathParts = urlPath.split("/").slice(1).filter(Boolean);
|
|
612
|
-
var currentNode = root;
|
|
613
|
-
pathParts.forEach(function (part, index) {
|
|
614
|
-
var hasChildren = index < pathParts.length - 1;
|
|
615
|
-
var isLast = index === pathParts.length - 1;
|
|
616
|
-
var fullPath = "/" + pathParts.slice(0, index + 1).join("/");
|
|
617
|
-
var sourcePath = core.Internal.joinModuleFilePathAndModulePath(moduleFilePath, "\"".concat(fullPath, "\""));
|
|
618
|
-
var node = hasChildren ? createForOfIteratorHelper._objectSpread2(createForOfIteratorHelper._objectSpread2({
|
|
619
|
-
type: "node",
|
|
620
|
-
name: part,
|
|
621
|
-
pattern: pattern,
|
|
622
|
-
moduleFilePath: moduleFilePath
|
|
623
|
-
}, isLast ? {
|
|
624
|
-
page: {
|
|
625
|
-
fullPath: fullPath
|
|
626
|
-
},
|
|
627
|
-
sourcePath: sourcePath
|
|
628
|
-
} : {}), {}, {
|
|
629
|
-
children: []
|
|
630
|
-
}) : {
|
|
631
|
-
type: "leaf",
|
|
632
|
-
name: part,
|
|
633
|
-
pattern: pattern,
|
|
634
|
-
fullPath: fullPath,
|
|
635
|
-
moduleFilePath: moduleFilePath,
|
|
636
|
-
sourcePath: sourcePath,
|
|
637
|
-
children: []
|
|
638
|
-
};
|
|
639
|
-
var existingNodeIndex = currentNode.children.findIndex(function (node) {
|
|
640
|
-
return node.name === part;
|
|
641
|
-
});
|
|
642
|
-
if (existingNodeIndex === -1) {
|
|
643
|
-
currentNode.children.push(node);
|
|
644
|
-
if (currentNode.type === "node") {
|
|
645
|
-
currentNode.isLinear = true;
|
|
646
|
-
if (currentNode.children.length > 1) {
|
|
647
|
-
delete currentNode.isLinear;
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
currentNode = node;
|
|
651
|
-
} else {
|
|
652
|
-
var existingNode = currentNode.children[existingNodeIndex];
|
|
653
|
-
if (existingNode.type === "leaf" && hasChildren) {
|
|
654
|
-
var _sourcePath = existingNode.sourcePath;
|
|
655
|
-
// convert leaf to node
|
|
656
|
-
currentNode.children[existingNodeIndex] = {
|
|
657
|
-
type: "node",
|
|
658
|
-
name: part,
|
|
659
|
-
pattern: pattern,
|
|
660
|
-
page: {
|
|
661
|
-
fullPath: fullPath
|
|
662
|
-
},
|
|
663
|
-
sourcePath: _sourcePath,
|
|
664
|
-
children: existingNode.children,
|
|
665
|
-
moduleFilePath: moduleFilePath
|
|
666
|
-
};
|
|
667
|
-
currentNode = currentNode.children[existingNodeIndex];
|
|
668
|
-
} else if (existingNode.type === "node" && isLast) {
|
|
669
|
-
// add page, source path and module file path
|
|
670
|
-
existingNode.page = {
|
|
671
|
-
fullPath: fullPath
|
|
672
|
-
};
|
|
673
|
-
existingNode.sourcePath = sourcePath;
|
|
674
|
-
existingNode.moduleFilePath = moduleFilePath;
|
|
675
|
-
existingNode.pattern = pattern;
|
|
676
|
-
} else {
|
|
677
|
-
currentNode = currentNode.children[existingNodeIndex];
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
});
|
|
681
|
-
},
|
|
682
|
-
_ret;
|
|
683
|
-
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
684
|
-
_ret = _loop();
|
|
685
|
-
if (_ret === 0) continue;
|
|
686
|
-
}
|
|
687
|
-
} catch (err) {
|
|
688
|
-
_iterator.e(err);
|
|
689
|
-
} finally {
|
|
690
|
-
_iterator.f();
|
|
691
|
-
}
|
|
692
|
-
return root;
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
/**
|
|
696
|
-
* The route pattern a page-router module serves, e.g. `/blogs/[blog]`.
|
|
697
|
-
*
|
|
698
|
-
* Written in Next's vocabulary for both routers on purpose: the pattern is read
|
|
699
|
-
* by `parseRoutePattern`, the sitemap and the Studio's key inputs, none of which
|
|
700
|
-
* should have to know which framework the project uses. The TanStack branch
|
|
701
|
-
* translates that framework's conventions into it; see
|
|
702
|
-
* `tanStackSegmentsOfRoutePath` in `@valbuild/core` for the rules.
|
|
703
|
-
*/
|
|
704
|
-
function getPatternFromModuleFilePath(moduleFilePath, srcFolder) {
|
|
705
|
-
if (isTanStackRoutesFolder(srcFolder)) {
|
|
706
|
-
var routePath = moduleFilePath.slice(srcFolder.length).replace(/\.val\.[tj]sx?$/, "");
|
|
707
|
-
var segments = core.tanStackSegmentsOfRoutePath(routePath);
|
|
708
|
-
// "" rather than "/" for the root, so it matches what the Next branch
|
|
709
|
-
// returns for `/app/page.val.ts` — `parseRoutePattern` reads both as [].
|
|
710
|
-
return segments.length === 0 ? "" : "/".concat(segments.join("/"));
|
|
711
|
-
}
|
|
712
|
-
return moduleFilePath.replace(srcFolder, "")
|
|
713
|
-
// TODO: hacky!
|
|
714
|
-
// remove route groups
|
|
715
|
-
.replace(/\/\([^/]+\)/g, "") // not sure we want to do this?
|
|
716
|
-
.replace("/page.val.ts", "").replace("/page.val.js", "");
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
exports.DEFAULT_CANVAS_SELECTION = DEFAULT_CANVAS_SELECTION;
|
|
720
|
-
exports.DEFAULT_CANVAS_SELECTION_SOFT = DEFAULT_CANVAS_SELECTION_SOFT;
|
|
721
|
-
exports.VAL_AI_SESSION_STORAGE_KEY = VAL_AI_SESSION_STORAGE_KEY;
|
|
722
|
-
exports.VAL_CANVAS_MESSAGE = VAL_CANVAS_MESSAGE;
|
|
723
|
-
exports.VAL_CANVAS_PARAM = VAL_CANVAS_PARAM;
|
|
724
|
-
exports.VAL_CONFIG_SESSION_STORAGE_KEY = VAL_CONFIG_SESSION_STORAGE_KEY;
|
|
725
|
-
exports.VAL_THEME_SESSION_STORAGE_KEY = VAL_THEME_SESSION_STORAGE_KEY;
|
|
726
|
-
exports.attachElementPicker = attachElementPicker;
|
|
727
|
-
exports.createPickerOverlay = createPickerOverlay;
|
|
728
|
-
exports.describeElement = describeElement;
|
|
729
|
-
exports.elementLabel = elementLabel;
|
|
730
|
-
exports.formatRoutePattern = formatRoutePattern;
|
|
731
|
-
exports.getNextAppRouterSourceFolder = getNextAppRouterSourceFolder;
|
|
732
|
-
exports.getPageRouterSitemapTree = getPageRouterSitemapTree;
|
|
733
|
-
exports.getPageRouterSourceFolder = getPageRouterSourceFolder;
|
|
734
|
-
exports.getPatternFromModuleFilePath = getPatternFromModuleFilePath;
|
|
735
|
-
exports.getTanStackRouterSourceFolder = getTanStackRouterSourceFolder;
|
|
736
|
-
exports.isTanStackRoutesFolder = isTanStackRoutesFolder;
|
|
737
|
-
exports.isValCanvasFrame = isValCanvasFrame;
|
|
738
|
-
exports.isValCanvasPageMessage = isValCanvasPageMessage;
|
|
739
|
-
exports.isValCanvasStudioMessage = isValCanvasStudioMessage;
|
|
740
|
-
exports.modifierLabel = modifierLabel;
|
|
741
|
-
exports.parseRoutePattern = parseRoutePattern;
|
|
742
|
-
exports.startElementPicking = startElementPicking;
|
|
743
|
-
exports.withValCanvasParam = withValCanvasParam;
|