@jxsuite/studio 2.4.2 → 3.0.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.
Files changed (82) hide show
  1. package/dist/chunks/{cf-settings-g5fbf2zp.js → cf-settings-zj2cj1ar.js} +6 -3
  2. package/dist/chunks/{content-source-k9724vcv.js → content-source-7fy9qrm0.js} +10 -9
  3. package/dist/chunks/{convert-to-repeater-k10dvcc7.js → convert-to-repeater-6vvx96n2.js} +9 -8
  4. package/dist/chunks/{extension-sections-0ada0xcw.js → extension-sections-kwzvpemr.js} +13 -12
  5. package/dist/chunks/{files-yew27sn9.js → files-xcybanxe.js} +14 -13
  6. package/dist/chunks/{format-host-wewba4nq.js → format-host-8fr3545e.js} +2 -2
  7. package/dist/chunks/{git-panel-2dh1aw50.js → git-panel-g01d93vc.js} +9 -8
  8. package/dist/chunks/{layers-panel-qnsghwwd.js → layers-panel-27essgkc.js} +12 -11
  9. package/dist/chunks/{publish-panel-a0pdft5w.js → publish-panel-09sy2bab.js} +8 -7
  10. package/dist/chunks/{quick-search-9avyc4pc.js → quick-search-sefb61v8.js} +15 -14
  11. package/dist/chunks/{right-panel-kcnhtc5j.js → right-panel-9r32jd5j.js} +11 -10
  12. package/dist/chunks/{studio-aweyr4v1.js → studio-2x9zbxmx.js} +2 -2
  13. package/dist/chunks/{studio-ef8t53vc.js → studio-3dkcd4c5.js} +3 -3
  14. package/dist/chunks/{studio-hb7c46jy.js → studio-5efrtn1m.js} +9 -7
  15. package/dist/chunks/{studio-v1va0vhd.js → studio-6z5eyjwn.js} +24 -25
  16. package/dist/chunks/{studio-ke244pam.js → studio-7p35254k.js} +33 -11
  17. package/dist/chunks/{studio-f5yyvqxv.js → studio-8ezdegcx.js} +13 -11
  18. package/dist/chunks/{studio-cz2j1c0g.js → studio-a0yp7syn.js} +55 -18
  19. package/dist/chunks/{studio-26sv44br.js → studio-dc8s8heb.js} +34 -23
  20. package/dist/chunks/{studio-jnakhg87.js → studio-g5gdqnyd.js} +4 -4
  21. package/dist/chunks/{studio-rqemfhz6.js → studio-hcxzyk3x.js} +2 -2
  22. package/dist/chunks/{studio-ws6ef6js.js → studio-hj2se583.js} +12 -10
  23. package/dist/chunks/{studio-pyrw8h0w.js → studio-j595e748.js} +407 -167
  24. package/dist/chunks/{studio-dgj7gq44.js → studio-k4jvjcfx.js} +4 -4
  25. package/dist/chunks/studio-kfpek536.js +28 -0
  26. package/dist/chunks/{studio-sccge2wf.js → studio-p5dja96s.js} +2 -2
  27. package/dist/chunks/{studio-0b6fs05q.js → studio-pkp61mh8.js} +5 -5
  28. package/dist/chunks/studio-qpfq7xhm.js +1802 -0
  29. package/dist/chunks/{studio-ra7ar50f.js → studio-r5xbtctf.js} +51 -1565
  30. package/dist/chunks/{studio-v2c5pmjj.js → studio-rh1cnamv.js} +17 -15
  31. package/dist/chunks/{studio-28xc8ws4.js → studio-ry1vz5sv.js} +10 -8
  32. package/dist/chunks/{studio-hyn3vhwr.js → studio-xntfdy1x.js} +5 -5
  33. package/dist/iframe-entry.js +344 -26
  34. package/dist/studio.js +374 -248
  35. package/package.json +9 -9
  36. package/src/browse/library-layouts.ts +3 -3
  37. package/src/browse/library-pane.ts +2 -2
  38. package/src/browse/library-preview.ts +19 -3
  39. package/src/canvas/asset-refs.ts +119 -0
  40. package/src/canvas/asset-resolve.ts +256 -0
  41. package/src/canvas/canvas-live-render.ts +23 -15
  42. package/src/canvas/iframe-entry.ts +1 -0
  43. package/src/canvas/iframe-host.ts +4 -0
  44. package/src/canvas/iframe-protocol.ts +9 -0
  45. package/src/canvas/iframe-render.ts +28 -10
  46. package/src/canvas/site-style-css.ts +2 -6
  47. package/src/editor/file-drop-action.ts +2 -1
  48. package/src/files/files.ts +2 -2
  49. package/src/files/media-paths.ts +37 -14
  50. package/src/files/media-upload.ts +47 -6
  51. package/src/grid/grid-idle.ts +45 -0
  52. package/src/grid/grid-view.ts +21 -0
  53. package/src/grid/schema-columns.ts +2 -1
  54. package/src/grid/sources/content-source.ts +24 -3
  55. package/src/new-project/import-tab.ts +3 -2
  56. package/src/panels/ai-chat/composer.ts +30 -13
  57. package/src/panels/frontmatter-fields.ts +6 -2
  58. package/src/panels/properties-panel.ts +8 -2
  59. package/src/panels/seo-modal.ts +5 -6
  60. package/src/panels/signals-panel.ts +2 -1
  61. package/src/platforms/cloud.ts +75 -5
  62. package/src/platforms/devserver.ts +5 -1
  63. package/src/services/ai-models.ts +101 -11
  64. package/src/services/ai-settings.ts +69 -71
  65. package/src/services/cf-settings.ts +19 -37
  66. package/src/services/document-assistant.ts +4 -3
  67. package/src/services/idle.ts +6 -1
  68. package/src/services/settings/definitions.ts +164 -0
  69. package/src/services/settings/kernel.ts +335 -0
  70. package/src/services/settings/write-queue.ts +116 -0
  71. package/src/settings/preferences-accounts.ts +6 -19
  72. package/src/settings/preferences-keymap.ts +8 -18
  73. package/src/settings/schema-field-ui.ts +2 -2
  74. package/src/shell.ts +6 -14
  75. package/src/studio.ts +32 -1
  76. package/src/types.ts +61 -3
  77. package/src/ui/ai-credentials-form.ts +52 -27
  78. package/src/ui/media-picker.ts +6 -11
  79. package/src/utils/studio-utils.ts +45 -3
  80. package/dist/chunks/studio-a7pzveq1.js +0 -110
  81. package/src/canvas/content-assets.ts +0 -263
  82. package/src/services/settings-store.ts +0 -99
@@ -2084,6 +2084,188 @@ function evaluateOperand(operand, state, event, iterCtx) {
2084
2084
  return resolveOperand(operand, state, event, iterCtx);
2085
2085
  }
2086
2086
 
2087
+ // ../schema/src/asset-paths.ts
2088
+ function normalizeDir(value) {
2089
+ const forward = value.replaceAll("\\", "/");
2090
+ return forward.length > 1 && forward.endsWith("/") ? forward.slice(0, -1) : forward;
2091
+ }
2092
+ function normalizeAssetPrefix(prefix) {
2093
+ const forward = normalizeDir(prefix);
2094
+ return forward.startsWith("/") ? forward : `/${forward}`;
2095
+ }
2096
+ function bySpecificity(mounts, key) {
2097
+ return [...mounts].toSorted((a, b) => b[key].length - a[key].length);
2098
+ }
2099
+ function isUnder(path, dir) {
2100
+ return path === dir || path.startsWith(`${dir}/`);
2101
+ }
2102
+ function assetUrlFor(mounts, absolutePath) {
2103
+ const path = normalizeDir(absolutePath);
2104
+ for (const mount of bySpecificity(mounts, "dir")) {
2105
+ const dir = normalizeDir(mount.dir);
2106
+ if (!isUnder(path, dir) || path === dir) {
2107
+ continue;
2108
+ }
2109
+ const rest = path.slice(dir.length + 1);
2110
+ const encoded = rest.split("/").map((segment) => encodeURIComponent(segment)).join("/");
2111
+ return `${normalizeAssetPrefix(mount.urlPrefix)}/${encoded}`;
2112
+ }
2113
+ return null;
2114
+ }
2115
+ function resolveAssetUrl(mounts, url) {
2116
+ const pathname = url.split("#")[0].split("?")[0];
2117
+ if (!pathname.startsWith("/")) {
2118
+ return null;
2119
+ }
2120
+ let decoded;
2121
+ try {
2122
+ decoded = decodeURIComponent(pathname);
2123
+ } catch {
2124
+ return null;
2125
+ }
2126
+ if (/%2e|%2f/i.test(decoded)) {
2127
+ return null;
2128
+ }
2129
+ for (const mount of bySpecificity(mounts, "urlPrefix")) {
2130
+ const prefix = normalizeAssetPrefix(mount.urlPrefix);
2131
+ if (!decoded.startsWith(`${prefix}/`)) {
2132
+ continue;
2133
+ }
2134
+ const rest = decoded.slice(prefix.length + 1);
2135
+ const segments = rest.split("/");
2136
+ if (segments.some((s) => s === "" || s === "." || s === "..")) {
2137
+ return null;
2138
+ }
2139
+ return `${normalizeDir(mount.dir)}/${segments.join("/")}`;
2140
+ }
2141
+ return null;
2142
+ }
2143
+ var URL_TERMINATOR = String.raw`"'\s<>()\\`;
2144
+ var PUBLIC_DIR = "public";
2145
+ function splitRefSuffix(value) {
2146
+ const cut = value.search(/[#?]/);
2147
+ return cut === -1 ? { path: value, suffix: "" } : { path: value.slice(0, cut), suffix: value.slice(cut) };
2148
+ }
2149
+ function isNonRelativeRef(value) {
2150
+ return value === "" || value.startsWith("/") || value.startsWith("#") || value.includes("${") || /^[a-z][\w+.-]*:/i.test(value);
2151
+ }
2152
+ function normalizeProjectPath(path) {
2153
+ return path.replaceAll("\\", "/").replace(/^\.\//, "").replace(/^\/+/, "").replace(/\/+$/, "");
2154
+ }
2155
+ function joinProjectPath(dir, ref2) {
2156
+ const base = dir === "" || dir === "." ? [] : normalizeProjectPath(dir).split("/");
2157
+ const out = base.filter((segment) => segment !== "" && segment !== ".");
2158
+ for (const segment of ref2.replaceAll("\\", "/").split("/")) {
2159
+ if (segment === "" || segment === ".") {
2160
+ continue;
2161
+ }
2162
+ if (segment === "..") {
2163
+ if (out.length === 0) {
2164
+ return null;
2165
+ }
2166
+ out.pop();
2167
+ continue;
2168
+ }
2169
+ out.push(segment);
2170
+ }
2171
+ return out.join("/");
2172
+ }
2173
+ function projectPathsForSiteUrl(url, mounts, lanes) {
2174
+ const { path } = splitRefSuffix(url);
2175
+ if (!path.startsWith("/")) {
2176
+ return [];
2177
+ }
2178
+ let decoded;
2179
+ try {
2180
+ decoded = decodeURIComponent(path);
2181
+ } catch {
2182
+ return [];
2183
+ }
2184
+ if (/%2e|%2f/i.test(decoded)) {
2185
+ return [];
2186
+ }
2187
+ const rest = decoded.replace(/^\/+/, "");
2188
+ if (rest === "" || rest.split("/").some((segment) => segment === "." || segment === "..")) {
2189
+ return [];
2190
+ }
2191
+ const out = [];
2192
+ for (const lane of lanes) {
2193
+ if (lane === "mounts") {
2194
+ const mounted = resolveAssetUrl(mounts, path);
2195
+ if (mounted !== null && !mounted.startsWith("/") && !/^[A-Za-z]:/.test(mounted)) {
2196
+ out.push(normalizeProjectPath(mounted));
2197
+ }
2198
+ continue;
2199
+ }
2200
+ out.push(lane === "root" ? rest : `${PUBLIC_DIR}/${rest}`);
2201
+ }
2202
+ return [...new Set(out)];
2203
+ }
2204
+ function projectPathForRef(value, documentDir, mounts, lanes) {
2205
+ const { path } = splitRefSuffix(value);
2206
+ if (path === "") {
2207
+ return null;
2208
+ }
2209
+ if (isNonRelativeRef(value)) {
2210
+ return path.startsWith("/") ? projectPathsForSiteUrl(path, mounts, lanes)[0] ?? null : null;
2211
+ }
2212
+ if (path.endsWith("/")) {
2213
+ return null;
2214
+ }
2215
+ let decoded;
2216
+ try {
2217
+ decoded = decodeURIComponent(path);
2218
+ } catch {
2219
+ return null;
2220
+ }
2221
+ const joined = joinProjectPath(documentDir, decoded);
2222
+ if (joined === null || joined === "" || joined === normalizeProjectPath(documentDir)) {
2223
+ return null;
2224
+ }
2225
+ return joined;
2226
+ }
2227
+ function encodeProjectPath(path) {
2228
+ return path.split("/").map((segment) => encodeURIComponent(segment)).join("/");
2229
+ }
2230
+ function parseSrcset(value) {
2231
+ const out = [];
2232
+ let i = 0;
2233
+ while (i < value.length) {
2234
+ while (i < value.length && (/\s/.test(value[i]) || value[i] === ",")) {
2235
+ i += 1;
2236
+ }
2237
+ if (i >= value.length) {
2238
+ break;
2239
+ }
2240
+ const start = i;
2241
+ while (i < value.length && !/\s/.test(value[i])) {
2242
+ i += 1;
2243
+ }
2244
+ let url = value.slice(start, i);
2245
+ if (url.endsWith(",")) {
2246
+ out.push({ descriptor: "", url: url.replace(/,+$/, "") });
2247
+ continue;
2248
+ }
2249
+ while (i < value.length && /\s/.test(value[i])) {
2250
+ i += 1;
2251
+ }
2252
+ const descStart = i;
2253
+ while (i < value.length && value[i] !== ",") {
2254
+ i += 1;
2255
+ }
2256
+ const descriptor = value.slice(descStart, i).trim();
2257
+ i += 1;
2258
+ url = url.replace(/,+$/, "");
2259
+ if (url !== "") {
2260
+ out.push({ descriptor, url });
2261
+ }
2262
+ }
2263
+ return out;
2264
+ }
2265
+ function formatSrcset(candidates) {
2266
+ return candidates.map(({ url, descriptor }) => descriptor ? `${url} ${descriptor}` : url).join(", ");
2267
+ }
2268
+
2087
2269
  // ../runtime/src/statements.ts
2088
2270
  function statementKind(statement) {
2089
2271
  if ("operator" in statement) {
@@ -2287,6 +2469,52 @@ function canvasAttrName(el, key) {
2287
2469
  }
2288
2470
  return key;
2289
2471
  }
2472
+ var _canvasAssetResolver = null;
2473
+ function setCanvasAssetResolver(fn) {
2474
+ _canvasAssetResolver = fn;
2475
+ }
2476
+ var ASSET_KEYS = new Set(["src", "poster", "data"]);
2477
+ var SRCSET_KEYS = new Set(["srcset", "imagesrcset"]);
2478
+ var HREF_ASSET_TAGS = new Set(["LINK"]);
2479
+ function isAssetKey(tagName, key) {
2480
+ return ASSET_KEYS.has(key) || key === "href" && HREF_ASSET_TAGS.has(tagName);
2481
+ }
2482
+ function canvasAssetValue(tagName, key, value) {
2483
+ if (!_canvasAssetResolver || value === "") {
2484
+ return value;
2485
+ }
2486
+ const name = key.toLowerCase();
2487
+ if (SRCSET_KEYS.has(name)) {
2488
+ const candidates = parseSrcset(value);
2489
+ let changed = false;
2490
+ const next = candidates.map((candidate) => {
2491
+ const resolved = _canvasAssetResolver?.(candidate.url, name) ?? null;
2492
+ if (resolved === null || resolved === candidate.url) {
2493
+ return candidate;
2494
+ }
2495
+ changed = true;
2496
+ return { descriptor: candidate.descriptor, url: resolved };
2497
+ });
2498
+ return changed ? formatSrcset(next) : value;
2499
+ }
2500
+ if (!isAssetKey(tagName, name)) {
2501
+ return value;
2502
+ }
2503
+ return _canvasAssetResolver(value, name) ?? value;
2504
+ }
2505
+ var CSS_URL_RE = /\burl\(\s*(?<q>["']?)(?<u>[^"')]*)\k<q>\s*\)/g;
2506
+ function canvasStyleUrls(value) {
2507
+ if (!_canvasAssetResolver || !value.includes("url(")) {
2508
+ return value;
2509
+ }
2510
+ return value.replaceAll(CSS_URL_RE, (whole, quote, url) => {
2511
+ const resolved = url === "" ? null : _canvasAssetResolver?.(url, "url()") ?? null;
2512
+ return resolved === null ? whole : `url(${quote}${resolved}${quote})`;
2513
+ });
2514
+ }
2515
+ function canvasStyleValue(value) {
2516
+ return transposeCanvasUnits(canvasStyleUrls(value));
2517
+ }
2290
2518
  var _stampPropBindings = false;
2291
2519
  function setStampPropBindings(on) {
2292
2520
  _stampPropBindings = on;
@@ -2563,6 +2791,17 @@ var RESERVED_KEYS = new Set([
2563
2791
  "observedAttributes"
2564
2792
  ]);
2565
2793
  var warnedRefChildren = new Set;
2794
+ var SVG_NS = "http://www.w3.org/2000/svg";
2795
+ var MATHML_NS = "http://www.w3.org/1998/Math/MathML";
2796
+ function elementNamespace(tagName, inherited) {
2797
+ if (tagName === "svg") {
2798
+ return SVG_NS;
2799
+ }
2800
+ if (tagName === "math") {
2801
+ return MATHML_NS;
2802
+ }
2803
+ return inherited ?? null;
2804
+ }
2566
2805
  function renderNode(def2, state, options) {
2567
2806
  const path = options?._path ?? [];
2568
2807
  if (typeof def2 === "string" || typeof def2 === "number" || typeof def2 === "boolean") {
@@ -2605,7 +2844,9 @@ function renderNode(def2, state, options) {
2605
2844
  if (def2.$switch) {
2606
2845
  return renderSwitch(def2, localState, options);
2607
2846
  }
2608
- const el = document.createElement(tagName);
2847
+ const ns = elementNamespace(tagName, options?._ns);
2848
+ const childNs = tagName === "foreignObject" ? null : ns;
2849
+ const el = ns ? document.createElementNS(ns, tagName) : document.createElement(tagName);
2609
2850
  if (options?.onNodeCreated) {
2610
2851
  options.onNodeCreated(el, path, def2, localState);
2611
2852
  }
@@ -2614,12 +2855,12 @@ function renderNode(def2, state, options) {
2614
2855
  applyAttributes(el, def2.attributes ?? {}, localState);
2615
2856
  const kids = def2.children;
2616
2857
  if (isMappedArray(kids)) {
2617
- const arrOpts = options ? { ...options, _path: [...path, "children"] } : undefined;
2858
+ const arrOpts = options || childNs ? { ...options, _ns: childNs, _path: [...path, "children"] } : undefined;
2618
2859
  renderMappedArrayInto(el, kids, localState, arrOpts);
2619
2860
  } else if (Array.isArray(kids)) {
2620
2861
  for (let i = 0;i < kids.length; i++) {
2621
2862
  const child = kids[i];
2622
- const childOpts = options ? { ...options, _path: [...path, "children", i] } : undefined;
2863
+ const childOpts = options || childNs ? { ...options, _ns: childNs, _path: [...path, "children", i] } : undefined;
2623
2864
  if (isMappedArray(child)) {
2624
2865
  renderMappedArrayInto(el, child, localState, childOpts);
2625
2866
  } else {
@@ -2678,6 +2919,15 @@ function bindProperty(el, key, val, state) {
2678
2919
  if (boundProp) {
2679
2920
  el.dataset.jxBoundProp = boundProp;
2680
2921
  }
2922
+ const asAsset = (resolved) => typeof resolved === "string" ? canvasAssetValue(el.tagName, key, resolved) : resolved;
2923
+ const write = (resolved) => {
2924
+ const node = el;
2925
+ if (key === "className" && !(node instanceof HTMLElement)) {
2926
+ node.setAttribute("class", resolved == null ? "" : String(resolved));
2927
+ return;
2928
+ }
2929
+ target[key] = resolved;
2930
+ };
2681
2931
  if (isRefObj(val)) {
2682
2932
  const refVal = val;
2683
2933
  if (key === "id") {
@@ -2685,17 +2935,17 @@ function bindProperty(el, key, val, state) {
2685
2935
  return;
2686
2936
  }
2687
2937
  effect(() => {
2688
- target[key] = resolveRef(refVal.$ref, state);
2938
+ write(asAsset(resolveRef(refVal.$ref, state)));
2689
2939
  });
2690
2940
  return;
2691
2941
  }
2692
2942
  if (isTemplateString(val)) {
2693
2943
  effect(() => {
2694
- target[key] = evaluateTemplate(val, state);
2944
+ write(asAsset(evaluateTemplate(val, state)));
2695
2945
  });
2696
2946
  return;
2697
2947
  }
2698
- target[key] = val;
2948
+ write(asAsset(val));
2699
2949
  }
2700
2950
  function applyStyle(el, styleDef, mediaQueries = {}, state = {}) {
2701
2951
  const nested = {};
@@ -2730,19 +2980,19 @@ function applyStyle(el, styleDef, mediaQueries = {}, state = {}) {
2730
2980
  if (prop.startsWith("--")) {
2731
2981
  if (isTemplateString(val)) {
2732
2982
  effect(() => {
2733
- el.style.setProperty(prop, transposeCanvasUnits(evaluateTemplate(val, state)));
2983
+ el.style.setProperty(prop, canvasStyleValue(evaluateTemplate(val, state)));
2734
2984
  });
2735
2985
  } else {
2736
- el.style.setProperty(prop, transposeCanvasUnits(scalar));
2986
+ el.style.setProperty(prop, canvasStyleValue(scalar));
2737
2987
  }
2738
2988
  } else if (isTemplateString(val)) {
2739
2989
  effect(() => {
2740
- el.style[prop] = transposeCanvasUnits(evaluateTemplate(val, state));
2990
+ el.style[prop] = canvasStyleValue(evaluateTemplate(val, state));
2741
2991
  });
2742
2992
  } else if (mediaOverriddenProps.has(prop)) {
2743
2993
  baseDecls[prop] = scalar;
2744
2994
  } else {
2745
- el.style[prop] = transposeCanvasUnits(scalar);
2995
+ el.style[prop] = canvasStyleValue(scalar);
2746
2996
  }
2747
2997
  }
2748
2998
  const hasNested = Object.keys(nested).length > 0;
@@ -2801,7 +3051,7 @@ function applyStyle(el, styleDef, mediaQueries = {}, state = {}) {
2801
3051
  if (key === "@--") {
2802
3052
  continue;
2803
3053
  }
2804
- const query = key.startsWith("@--") ? mediaQueries[key.slice(1)] ?? key.slice(1) : key.startsWith("@(") ? key.slice(1) : null;
3054
+ const query = resolveAtQuery(key, mediaQueries);
2805
3055
  const atRule = query === null ? key : `@media ${query}`;
2806
3056
  const scope = `[data-jx="${uid}"]`;
2807
3057
  const scheme = query === null ? null : pureSchemeOf(query);
@@ -2837,12 +3087,15 @@ function reapplyStyle(el, styleDef, mediaQueries = {}, state = {}) {
2837
3087
  function applyAttributes(el, attrs, state) {
2838
3088
  for (const [k, v] of Object.entries(attrs)) {
2839
3089
  const attr = canvasAttrName(el, k);
3090
+ const write = (resolved) => {
3091
+ el.setAttribute(attr, canvasAssetValue(el.tagName, k, String(resolved ?? "")));
3092
+ };
2840
3093
  if (isRefObj(v)) {
2841
- effect(() => el.setAttribute(attr, String(resolveRef(v.$ref, state) ?? "")));
3094
+ effect(() => write(resolveRef(v.$ref, state)));
2842
3095
  } else if (isTemplateString(v)) {
2843
- effect(() => el.setAttribute(attr, String(evaluateTemplate(v, state))));
3096
+ effect(() => write(evaluateTemplate(v, state)));
2844
3097
  } else {
2845
- el.setAttribute(attr, String(v));
3098
+ write(v);
2846
3099
  }
2847
3100
  }
2848
3101
  }
@@ -3515,7 +3768,18 @@ function camelToKebab(s) {
3515
3768
  return s.replaceAll(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
3516
3769
  }
3517
3770
  function toCSSText(rules) {
3518
- return Object.entries(rules).filter(([k, v]) => !isNestedSelector(k) && (v === null || typeof v !== "object")).map(([p, v]) => `${camelToKebab(p)}: ${transposeCanvasUnits(String(v))}`).join("; ");
3771
+ return Object.entries(rules).filter(([k, v]) => !isNestedSelector(k) && (v === null || typeof v !== "object")).map(([p, v]) => `${camelToKebab(p)}: ${canvasStyleValue(String(v))}`).join("; ");
3772
+ }
3773
+ var MEDIA_TYPES = new Set(["all", "print", "screen", "speech"]);
3774
+ function resolveAtQuery(atKey, mediaQueries) {
3775
+ if (atKey.startsWith("@--")) {
3776
+ return mediaQueries[atKey.slice(1)] ?? atKey.slice(1);
3777
+ }
3778
+ if (atKey.startsWith("@(")) {
3779
+ const inner = atKey.slice(2, -1).trim();
3780
+ return MEDIA_TYPES.has(inner.toLowerCase()) ? inner : atKey.slice(1);
3781
+ }
3782
+ return null;
3519
3783
  }
3520
3784
  var COLOR_SCHEME_ATTR = "data-color-scheme";
3521
3785
  function pureSchemeOf(query) {
@@ -3666,6 +3930,9 @@ async function defineElement(source, baseUrl) {
3666
3930
  }
3667
3931
  applyStyle(this, def2.style ?? {}, state["$media"] ?? {}, state);
3668
3932
  applyAttributes(this, def2.attributes ?? {}, state);
3933
+ if (!Array.isArray(def2.children) && def2.textContent !== undefined) {
3934
+ bindProperty(this, "textContent", def2.textContent, state);
3935
+ }
3669
3936
  const children = Array.isArray(def2.children) ? def2.children : [];
3670
3937
  for (const childDef of children) {
3671
3938
  this.append(renderNode(childDef, state));
@@ -3712,19 +3979,21 @@ function renderCustomElementWithProps(def2, state, options, path) {
3712
3979
  if (refusePrivateProp(key, "$props")) {
3713
3980
  continue;
3714
3981
  }
3982
+ const write = (resolved) => {
3983
+ el[key] = typeof resolved === "string" ? canvasAssetValue(el.tagName, key, resolved) : resolved;
3984
+ };
3715
3985
  if (isRefObj(val)) {
3716
3986
  const refVal = val;
3717
- const resolved = resolveRef(refVal.$ref, state);
3718
- el[key] = resolved;
3987
+ write(resolveRef(refVal.$ref, state));
3719
3988
  effect(() => {
3720
- el[key] = resolveRef(refVal.$ref, state);
3989
+ write(resolveRef(refVal.$ref, state));
3721
3990
  });
3722
3991
  } else if (isTemplateString(val)) {
3723
3992
  effect(() => {
3724
- el[key] = evaluateTemplate(val, state);
3993
+ write(evaluateTemplate(val, state));
3725
3994
  });
3726
3995
  } else {
3727
- el[key] = val;
3996
+ write(val);
3728
3997
  }
3729
3998
  }
3730
3999
  applyStyle(el, def2.style ?? {}, state["$media"] ?? {}, state);
@@ -3769,6 +4038,47 @@ function distributeSlots(host, slottedChildren) {
3769
4038
  }
3770
4039
  }
3771
4040
 
4041
+ // src/canvas/asset-resolve.ts
4042
+ function resolveAssetRef(value, ctx) {
4043
+ if (!ctx || value === "") {
4044
+ return null;
4045
+ }
4046
+ if (ctx.space === "repo") {
4047
+ if (!ctx.fileBaseUrl) {
4048
+ return null;
4049
+ }
4050
+ const path = projectPathForRef(value, ctx.documentDir, ctx.mounts, ctx.lanes);
4051
+ if (path === null) {
4052
+ return null;
4053
+ }
4054
+ const { suffix } = splitRefSuffix(value);
4055
+ return `${ctx.fileBaseUrl}${encodeProjectPath(path)}${suffix}`;
4056
+ }
4057
+ const [mount] = ctx.mounts;
4058
+ return mount ? mountedRefFor(value, ctx.documentDir, mount) : null;
4059
+ }
4060
+ function mountedRefFor(value, entryDir, mount) {
4061
+ if (isNonRelativeRef(value)) {
4062
+ return null;
4063
+ }
4064
+ const { path: bare, suffix } = splitRefSuffix(value);
4065
+ let decoded;
4066
+ try {
4067
+ decoded = decodeURIComponent(bare);
4068
+ } catch {
4069
+ return null;
4070
+ }
4071
+ const target = joinProjectPath(entryDir, decoded);
4072
+ if (target === null) {
4073
+ return null;
4074
+ }
4075
+ const url = assetUrlFor([mount], target);
4076
+ if (!url) {
4077
+ return null;
4078
+ }
4079
+ return `${url}${suffix}`;
4080
+ }
4081
+
3772
4082
  // src/canvas/path-mapping.ts
3773
4083
  function wrapsPageContent(path, prefix) {
3774
4084
  if (!prefix) {
@@ -3853,7 +4163,7 @@ function buildSiteStyleCSS(siteStyle, mediaQueries, transpose) {
3853
4163
  rules.push(`body { ${bodyCSS} }`);
3854
4164
  }
3855
4165
  for (const [atKey, block] of condBlocks) {
3856
- const query = atKey.startsWith("@--") ? mediaQueries[atKey.slice(1)] ?? atKey.slice(1) : atKey.startsWith("@(") ? atKey.slice(1) : null;
4166
+ const query = resolveAtQuery(atKey, mediaQueries);
3857
4167
  if (query === null) {
3858
4168
  continue;
3859
4169
  }
@@ -4157,7 +4467,7 @@ function applySiteStyle(siteStyle, mediaQueries = {}) {
4157
4467
  existing?.remove();
4158
4468
  return;
4159
4469
  }
4160
- const css = buildSiteStyleCSS(siteStyle, mediaQueries, transposeCanvasUnits);
4470
+ const css = buildSiteStyleCSS(siteStyle, mediaQueries, canvasStyleValue);
4161
4471
  if (existing) {
4162
4472
  existing.textContent = css;
4163
4473
  return;
@@ -4174,7 +4484,7 @@ function applyPreviewColorScheme(doc, scheme) {
4174
4484
  delete doc.documentElement.dataset.colorScheme;
4175
4485
  }
4176
4486
  }
4177
- function injectHead(doc) {
4487
+ function injectHead(doc, assets = null) {
4178
4488
  const head = doc.$head;
4179
4489
  if (!Array.isArray(head)) {
4180
4490
  return;
@@ -4190,9 +4500,14 @@ function injectHead(doc) {
4190
4500
  const attrs = { ...entry.attributes };
4191
4501
  for (const key of ["href", "src"]) {
4192
4502
  const val = attrs[key];
4193
- if (typeof val === "string" && !val.startsWith("/") && !val.startsWith(".") && !val.startsWith("http")) {
4503
+ if (typeof val !== "string" || val === "") {
4504
+ continue;
4505
+ }
4506
+ if (!val.startsWith("/") && !val.startsWith(".") && !val.startsWith("http")) {
4194
4507
  attrs[key] = `/node_modules/${val}`;
4508
+ continue;
4195
4509
  }
4510
+ attrs[key] = resolveAssetRef(val, assets) ?? val;
4196
4511
  }
4197
4512
  const sel = `${tag}${attrs.href ? `[href="${String(attrs.href)}"]` : ""}${attrs.src ? `[src="${String(attrs.src)}"]` : ""}`;
4198
4513
  if (sel !== tag && document.head.querySelector(sel)) {
@@ -4269,13 +4584,15 @@ function installCanvasImageRetry(root, maxAttempts = 3) {
4269
4584
  return () => root.removeEventListener("error", onError, true);
4270
4585
  }
4271
4586
  async function renderResolvedDocument(opts) {
4587
+ const assets = opts.assets ?? null;
4588
+ setCanvasAssetResolver(assets ? (value) => resolveAssetRef(value, assets) : null);
4272
4589
  setSkipServerFunctions(opts.mode !== "preview");
4273
4590
  setSkipAutoRequests(opts.mode !== "preview" && !opts.allowAutoRequests);
4274
4591
  setCanvasViewportTranspose(true);
4275
4592
  setCanvasDelinkAnchors(opts.mode !== "preview");
4276
4593
  setStampPropBindings(opts.mode === "design" || opts.mode === "edit");
4277
4594
  applySiteStyle(opts.siteStyle, opts.doc.$media ?? {});
4278
- injectHead(opts.doc);
4595
+ injectHead(opts.doc, assets);
4279
4596
  syncEditModeCss(opts.container.ownerDocument, opts.mode);
4280
4597
  syncPreviewShell(opts.container.ownerDocument, opts.mode);
4281
4598
  syncStylebookCss(opts.container.ownerDocument, opts.mode);
@@ -8165,6 +8482,7 @@ function startCanvasIframe(opts) {
8165
8482
  stopDataScopeWatch = null;
8166
8483
  handle?.dispose();
8167
8484
  handle = await renderResolvedDocument({
8485
+ assets: msg.assets ?? null,
8168
8486
  container,
8169
8487
  doc: msg.doc,
8170
8488
  docBase: msg.docBase,
@@ -8262,5 +8580,5 @@ export {
8262
8580
  startCanvasIframe
8263
8581
  };
8264
8582
 
8265
- //# debugId=2229405F4A023FB664756E2164756E21
8583
+ //# debugId=39CA18389F1F06A664756E2164756E21
8266
8584
  //# sourceMappingURL=iframe-entry.js.map