@valbuild/shared 0.150.10 → 0.150.12

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.
Files changed (51) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/client/dist/valbuild-shared-client.cjs.dev.js +16 -2
  3. package/client/dist/valbuild-shared-client.cjs.prod.js +16 -2
  4. package/client/dist/valbuild-shared-client.esm.js +2 -2
  5. package/dist/{acquireTypes-dd976839.cjs.prod.js → acquireTypes-6250a305.cjs.prod.js} +46 -46
  6. package/dist/{acquireTypes-6e2f7961.esm.js → acquireTypes-c2227b23.esm.js} +2 -2
  7. package/dist/{acquireTypes-84a4077a.cjs.dev.js → acquireTypes-c9e757a1.cjs.dev.js} +46 -46
  8. package/dist/{slicedToArray-22567815.esm.js → createForOfIteratorHelper-9b80f1a2.esm.js} +136 -106
  9. package/dist/{slicedToArray-d99b4e2e.cjs.prod.js → createForOfIteratorHelper-9ca2078d.cjs.prod.js} +142 -111
  10. package/dist/{slicedToArray-c8a29f6b.cjs.dev.js → createForOfIteratorHelper-f2d7ac6d.cjs.dev.js} +142 -111
  11. package/dist/declarations/src/client/index.d.ts +2 -0
  12. package/dist/declarations/src/internal/ApiRoutes.d.ts +35 -0
  13. package/dist/declarations/src/internal/index.d.ts +2 -0
  14. package/dist/declarations/src/internal/pageInspection.d.ts +117 -0
  15. package/dist/declarations/src/internal/quickPreview.d.ts +91 -0
  16. package/dist/declarations/src/internal/valCanvasProtocol.d.ts +53 -0
  17. package/dist/declarations/src/publish/buildProposal.d.ts +16 -1
  18. package/dist/declarations/src/publish/buildQuickPreview.d.ts +46 -0
  19. package/dist/declarations/src/publish/index.d.ts +3 -2
  20. package/dist/declarations/src/publish/runStudioDeploy.d.ts +10 -0
  21. package/dist/getSitemapTree-5354ce90.cjs.prod.js +1421 -0
  22. package/dist/getSitemapTree-97b3166f.esm.js +1381 -0
  23. package/dist/getSitemapTree-d934ff9c.cjs.dev.js +1421 -0
  24. package/dist/{proposalProject-689c24cc.esm.js → proposalProject-5da177d5.esm.js} +1 -2
  25. package/dist/{proposalProject-926f2c68.cjs.dev.js → proposalProject-76caa377.cjs.prod.js} +2 -3
  26. package/dist/{proposalProject-fab0c026.cjs.prod.js → proposalProject-81fee08f.cjs.dev.js} +2 -3
  27. package/dist/{protocol-7ddc1a71.esm.js → protocol-55cfa3cf.esm.js} +1 -1
  28. package/dist/{protocol-4e2a455b.cjs.prod.js → protocol-b1055ef0.cjs.prod.js} +6 -6
  29. package/dist/{protocol-ac1c3ec7.cjs.dev.js → protocol-d0efb8cd.cjs.dev.js} +6 -6
  30. package/dist/wrapNativeSuper-639b12b7.esm.js +107 -0
  31. package/dist/wrapNativeSuper-8673414f.cjs.prod.js +113 -0
  32. package/dist/wrapNativeSuper-933f991e.cjs.dev.js +113 -0
  33. package/internal/dist/valbuild-shared-internal.cjs.dev.js +94 -34
  34. package/internal/dist/valbuild-shared-internal.cjs.prod.js +94 -34
  35. package/internal/dist/valbuild-shared-internal.esm.js +52 -6
  36. package/package.json +2 -2
  37. package/publish/dist/valbuild-shared-publish.cjs.dev.js +589 -237
  38. package/publish/dist/valbuild-shared-publish.cjs.prod.js +589 -237
  39. package/publish/dist/valbuild-shared-publish.esm.js +504 -155
  40. package/typecheck/dist/valbuild-shared-typecheck.cjs.dev.js +34 -34
  41. package/typecheck/dist/valbuild-shared-typecheck.cjs.prod.js +34 -34
  42. package/typecheck/dist/valbuild-shared-typecheck.esm.js +5 -5
  43. package/typecheck/testing/dist/valbuild-shared-typecheck-testing.cjs.dev.js +7 -7
  44. package/typecheck/testing/dist/valbuild-shared-typecheck-testing.cjs.prod.js +7 -7
  45. package/typecheck/testing/dist/valbuild-shared-typecheck-testing.esm.js +3 -3
  46. package/dist/createForOfIteratorHelper-666a6d17.esm.js +0 -137
  47. package/dist/createForOfIteratorHelper-87a33eff.cjs.dev.js +0 -145
  48. package/dist/createForOfIteratorHelper-fef4fa7d.cjs.prod.js +0 -145
  49. package/dist/getSitemapTree-873f7266.cjs.prod.js +0 -743
  50. package/dist/getSitemapTree-b6161fd8.esm.js +0 -717
  51. 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;