meno-core 1.0.52 → 1.0.53

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 (135) hide show
  1. package/build-astro.ts +183 -13
  2. package/build-next.ts +1361 -0
  3. package/build-static.ts +7 -5
  4. package/dist/bin/cli.js +2 -2
  5. package/dist/build-static.js +6 -6
  6. package/dist/chunks/{chunk-HNLUO36W.js → chunk-GZHGVVW3.js} +2 -2
  7. package/dist/chunks/chunk-GZHGVVW3.js.map +7 -0
  8. package/dist/chunks/{chunk-LPVETICS.js → chunk-H3GJ4H2U.js} +185 -1
  9. package/dist/chunks/chunk-H3GJ4H2U.js.map +7 -0
  10. package/dist/chunks/{chunk-CXCBV2M7.js → chunk-IGYR22T6.js} +76 -270
  11. package/dist/chunks/chunk-IGYR22T6.js.map +7 -0
  12. package/dist/chunks/{chunk-LHLHPYSP.js → chunk-JGP5A3Y5.js} +12 -11
  13. package/dist/chunks/chunk-JGP5A3Y5.js.map +7 -0
  14. package/dist/chunks/{chunk-7NIC4I3V.js → chunk-JGWFTO6P.js} +167 -21
  15. package/dist/chunks/chunk-JGWFTO6P.js.map +7 -0
  16. package/dist/chunks/{chunk-EDQSMAMP.js → chunk-O3NAGJP4.js} +85 -4
  17. package/dist/chunks/chunk-O3NAGJP4.js.map +7 -0
  18. package/dist/chunks/{chunk-H4JSCDNW.js → chunk-QB2LNO4W.js} +24 -1
  19. package/dist/chunks/chunk-QB2LNO4W.js.map +7 -0
  20. package/dist/chunks/{chunk-A725KYFK.js → chunk-R6XHAFBF.js} +561 -112
  21. package/dist/chunks/chunk-R6XHAFBF.js.map +7 -0
  22. package/dist/chunks/{chunk-J23ZX5AP.js → chunk-X754AHS5.js} +277 -1
  23. package/dist/chunks/chunk-X754AHS5.js.map +7 -0
  24. package/dist/chunks/{chunk-2QK6U5UK.js → chunk-YBLHKYFF.js} +12 -2
  25. package/dist/chunks/chunk-YBLHKYFF.js.map +7 -0
  26. package/dist/chunks/{constants-GWBAD66U.js → constants-STK2YBIW.js} +2 -2
  27. package/dist/entries/server-router.js +7 -7
  28. package/dist/lib/client/index.js +354 -59
  29. package/dist/lib/client/index.js.map +4 -4
  30. package/dist/lib/server/index.js +1458 -190
  31. package/dist/lib/server/index.js.map +4 -4
  32. package/dist/lib/shared/index.js +202 -34
  33. package/dist/lib/shared/index.js.map +4 -4
  34. package/dist/lib/test-utils/index.js +1 -1
  35. package/entries/client-router.tsx +5 -165
  36. package/lib/client/ErrorBoundary.test.tsx +27 -25
  37. package/lib/client/ErrorBoundary.tsx +34 -19
  38. package/lib/client/core/ComponentBuilder.ts +19 -2
  39. package/lib/client/core/builders/embedBuilder.ts +8 -4
  40. package/lib/client/core/builders/listBuilder.ts +23 -4
  41. package/lib/client/fontFamiliesService.test.ts +76 -0
  42. package/lib/client/fontFamiliesService.ts +69 -0
  43. package/lib/client/hmrCssReload.ts +160 -0
  44. package/lib/client/hooks/useColorVariables.ts +2 -0
  45. package/lib/client/index.ts +4 -0
  46. package/lib/client/meno-filter/ui.ts +2 -0
  47. package/lib/client/routing/RouteLoader.test.ts +2 -2
  48. package/lib/client/routing/RouteLoader.ts +8 -2
  49. package/lib/client/routing/Router.tsx +81 -15
  50. package/lib/client/scripts/ScriptExecutor.test.ts +143 -0
  51. package/lib/client/scripts/ScriptExecutor.ts +56 -2
  52. package/lib/client/styles/StyleInjector.ts +20 -5
  53. package/lib/client/styles/UtilityClassCollector.ts +7 -1
  54. package/lib/client/styles/cspNonce.test.ts +67 -0
  55. package/lib/client/styles/cspNonce.ts +63 -0
  56. package/lib/client/templateEngine.test.ts +80 -0
  57. package/lib/client/templateEngine.ts +5 -0
  58. package/lib/server/astro/cmsPageEmitter.ts +35 -5
  59. package/lib/server/astro/componentEmitter.ts +61 -5
  60. package/lib/server/astro/nodeToAstro.ts +149 -11
  61. package/lib/server/astro/normalizeOrphanTemplateProps.test.ts +264 -0
  62. package/lib/server/astro/normalizeOrphanTemplateProps.ts +184 -0
  63. package/lib/server/createServer.ts +11 -0
  64. package/lib/server/draftPageStore.ts +49 -0
  65. package/lib/server/fileWatcher.ts +62 -2
  66. package/lib/server/index.ts +13 -1
  67. package/lib/server/providers/fileSystemPageProvider.ts +8 -0
  68. package/lib/server/routes/api/components.ts +9 -4
  69. package/lib/server/routes/api/core-routes.ts +2 -2
  70. package/lib/server/routes/api/pages.ts +14 -22
  71. package/lib/server/routes/api/shared.ts +56 -0
  72. package/lib/server/routes/index.ts +90 -0
  73. package/lib/server/routes/pages.ts +13 -6
  74. package/lib/server/services/componentService.test.ts +199 -2
  75. package/lib/server/services/componentService.ts +354 -49
  76. package/lib/server/services/fileWatcherService.ts +4 -24
  77. package/lib/server/services/pageService.test.ts +23 -0
  78. package/lib/server/services/pageService.ts +124 -6
  79. package/lib/server/ssr/attributeBuilder.ts +8 -2
  80. package/lib/server/ssr/buildErrorOverlay.ts +1 -1
  81. package/lib/server/ssr/errorOverlay.test.ts +21 -2
  82. package/lib/server/ssr/errorOverlay.ts +38 -11
  83. package/lib/server/ssr/htmlGenerator.test.ts +53 -13
  84. package/lib/server/ssr/htmlGenerator.ts +71 -27
  85. package/lib/server/ssr/liveReloadIntegration.test.ts +123 -2
  86. package/lib/server/ssr/ssrRenderer.test.ts +67 -0
  87. package/lib/server/ssr/ssrRenderer.ts +94 -9
  88. package/lib/server/websocketManager.ts +0 -1
  89. package/lib/shared/componentRefs.ts +45 -0
  90. package/lib/shared/constants.ts +8 -0
  91. package/lib/shared/cssGeneration.ts +2 -0
  92. package/lib/shared/cssProperties.ts +184 -0
  93. package/lib/shared/expressionEvaluator.ts +54 -0
  94. package/lib/shared/fontCss.ts +101 -0
  95. package/lib/shared/fontLoader.ts +8 -86
  96. package/lib/shared/friendlyError.test.ts +87 -0
  97. package/lib/shared/friendlyError.ts +121 -0
  98. package/lib/shared/hrefRefs.test.ts +130 -0
  99. package/lib/shared/hrefRefs.ts +100 -0
  100. package/lib/shared/index.ts +52 -0
  101. package/lib/shared/inlineSvgStyleRules.test.ts +108 -0
  102. package/lib/shared/inlineSvgStyleRules.ts +134 -0
  103. package/lib/shared/interfaces/contentProvider.ts +13 -0
  104. package/lib/shared/itemTemplateUtils.test.ts +14 -0
  105. package/lib/shared/itemTemplateUtils.ts +4 -1
  106. package/lib/shared/registry/NodeTypeDefinition.ts +1 -1
  107. package/lib/shared/registry/nodeTypes/LinkNodeType.ts +1 -1
  108. package/lib/shared/slugTranslator.test.ts +24 -0
  109. package/lib/shared/slugTranslator.ts +24 -0
  110. package/lib/shared/styleNodeUtils.ts +4 -1
  111. package/lib/shared/tree/PathBuilder.test.ts +128 -1
  112. package/lib/shared/tree/PathBuilder.ts +83 -31
  113. package/lib/shared/types/comment.ts +99 -0
  114. package/lib/shared/types/index.ts +12 -0
  115. package/lib/shared/types/rendering.ts +8 -0
  116. package/lib/shared/utilityClassConfig.ts +4 -2
  117. package/lib/shared/utilityClassMapper.test.ts +24 -0
  118. package/lib/shared/validation/commentValidators.ts +69 -0
  119. package/lib/shared/validation/index.ts +1 -0
  120. package/lib/shared/viewportUnits.integration.test.ts +42 -0
  121. package/lib/shared/viewportUnits.test.ts +103 -0
  122. package/lib/shared/viewportUnits.ts +63 -0
  123. package/lib/test-utils/dom-setup.ts +6 -0
  124. package/package.json +1 -1
  125. package/dist/chunks/chunk-2QK6U5UK.js.map +0 -7
  126. package/dist/chunks/chunk-7NIC4I3V.js.map +0 -7
  127. package/dist/chunks/chunk-A725KYFK.js.map +0 -7
  128. package/dist/chunks/chunk-CXCBV2M7.js.map +0 -7
  129. package/dist/chunks/chunk-EDQSMAMP.js.map +0 -7
  130. package/dist/chunks/chunk-H4JSCDNW.js.map +0 -7
  131. package/dist/chunks/chunk-HNLUO36W.js.map +0 -7
  132. package/dist/chunks/chunk-J23ZX5AP.js.map +0 -7
  133. package/dist/chunks/chunk-LHLHPYSP.js.map +0 -7
  134. package/dist/chunks/chunk-LPVETICS.js.map +0 -7
  135. /package/dist/chunks/{constants-GWBAD66U.js.map → constants-STK2YBIW.js.map} +0 -0
@@ -2,6 +2,7 @@ import {
2
2
  evaluateTemplate,
3
3
  extractAttributesFromNode,
4
4
  hasTemplates,
5
+ inlineSvgStyleRules,
5
6
  isHtmlMapping,
6
7
  isLinkMapping,
7
8
  mergeNodeStyles,
@@ -12,12 +13,12 @@ import {
12
13
  resolveLinkMapping,
13
14
  resolveStyleMapping,
14
15
  skipEmptyTemplateAttributes
15
- } from "../../chunks/chunk-EDQSMAMP.js";
16
+ } from "../../chunks/chunk-O3NAGJP4.js";
16
17
  import {
17
18
  filterCSSProperties,
18
19
  logNetworkError,
19
20
  logRuntimeError
20
- } from "../../chunks/chunk-LPVETICS.js";
21
+ } from "../../chunks/chunk-H3GJ4H2U.js";
21
22
  import {
22
23
  BaseComponentRegistry,
23
24
  DEFAULT_PREFETCH_CONFIG,
@@ -55,11 +56,13 @@ import {
55
56
  resolveItemsTemplate,
56
57
  resolvePropsFromDefinition,
57
58
  responsiveStylesToClasses,
59
+ rewriteViewportUnits,
58
60
  setGlobalTemplateContext,
59
61
  singularize,
60
62
  sortClassesByPropertyOrder,
63
+ toFriendlyError,
61
64
  validatePageData
62
- } from "../../chunks/chunk-7NIC4I3V.js";
65
+ } from "../../chunks/chunk-JGWFTO6P.js";
63
66
  import {
64
67
  DEFAULT_BREAKPOINTS,
65
68
  DEFAULT_I18N_CONFIG,
@@ -84,7 +87,7 @@ import {
84
87
  NOT_FOUND_TIMEOUT_MS,
85
88
  RAW_HTML_PREFIX,
86
89
  init_constants
87
- } from "../../chunks/chunk-2QK6U5UK.js";
90
+ } from "../../chunks/chunk-YBLHKYFF.js";
88
91
  import "../../chunks/chunk-KSBZ2L7C.js";
89
92
 
90
93
  // lib/client/core/ComponentBuilder.ts
@@ -129,6 +132,9 @@ var ErrorBoundary = class extends Component {
129
132
  if (fallback) {
130
133
  return fallback(error, errorInfo);
131
134
  }
135
+ const friendly = toFriendlyError(error);
136
+ const friendlyMessage = friendly.friendlyMessage.replace(/`/g, "");
137
+ const friendlyHint = friendly.hint?.replace(/`/g, "");
132
138
  if (level === "page") {
133
139
  return h(
134
140
  "div",
@@ -157,7 +163,7 @@ var ErrorBoundary = class extends Component {
157
163
  fontSize: "24px",
158
164
  fontWeight: "600"
159
165
  }
160
- }, "\u26A0\uFE0F Page Rendering Error"),
166
+ }, `\u26A0\uFE0F ${friendly.title}`),
161
167
  h("p", {
162
168
  style: {
163
169
  margin: "0 0 16px 0",
@@ -165,21 +171,8 @@ var ErrorBoundary = class extends Component {
165
171
  fontSize: "16px",
166
172
  lineHeight: "1.5"
167
173
  }
168
- }, "An error occurred while rendering this page. Please check your JSON configuration."),
169
- h("div", {
170
- style: {
171
- background: "#fff",
172
- border: "1px solid #ddd",
173
- borderRadius: "4px",
174
- padding: "16px",
175
- marginBottom: "16px",
176
- fontFamily: "monospace",
177
- fontSize: "14px",
178
- color: "#c00",
179
- overflowX: "auto"
180
- }
181
- }, error.message),
182
- process.env.NODE_ENV === "development" && errorInfo?.componentStack && h(
174
+ }, friendlyHint ? `${friendlyMessage} ${friendlyHint}` : friendlyMessage),
175
+ h(
183
176
  "details",
184
177
  {
185
178
  style: {
@@ -194,8 +187,21 @@ var ErrorBoundary = class extends Component {
194
187
  fontWeight: "600",
195
188
  marginBottom: "8px"
196
189
  }
197
- }, "Stack Trace"),
198
- h("pre", {
190
+ }, "Technical details"),
191
+ h("div", {
192
+ style: {
193
+ background: "#fff",
194
+ border: "1px solid #ddd",
195
+ borderRadius: "4px",
196
+ padding: "16px",
197
+ margin: "8px 0",
198
+ fontFamily: "monospace",
199
+ fontSize: "14px",
200
+ color: "#c00",
201
+ overflowX: "auto"
202
+ }
203
+ }, error.message),
204
+ process.env.NODE_ENV === "development" && errorInfo?.componentStack && h("pre", {
199
205
  style: {
200
206
  background: "#f5f5f5",
201
207
  border: "1px solid #ddd",
@@ -256,10 +262,18 @@ var ErrorBoundary = class extends Component {
256
262
  color: "#c00",
257
263
  fontSize: "14px"
258
264
  }
259
- }, `Component Error${componentName ? `: ${componentName}` : ""}`)
265
+ }, `${friendly.title}${componentName ? ` (${componentName})` : ""}`)
260
266
  ),
261
267
  h("div", {
262
268
  style: {
269
+ fontSize: "13px",
270
+ color: "#666",
271
+ lineHeight: "1.5"
272
+ }
273
+ }, friendlyHint ? `${friendlyMessage} ${friendlyHint}` : friendlyMessage),
274
+ process.env.NODE_ENV === "development" && h("div", {
275
+ style: {
276
+ marginTop: "8px",
263
277
  fontSize: "12px",
264
278
  color: "#666",
265
279
  fontFamily: "monospace",
@@ -467,6 +481,29 @@ async function initializeBreakpoints(forceRefresh = false) {
467
481
  }
468
482
  var initializeConfig = initializeBreakpoints;
469
483
 
484
+ // lib/client/styles/cspNonce.ts
485
+ var cached;
486
+ function getCspNonce() {
487
+ if (cached !== void 0) return cached;
488
+ if (typeof document === "undefined") {
489
+ cached = null;
490
+ return cached;
491
+ }
492
+ try {
493
+ const meta = document.querySelector('meta[name="csp-nonce"]');
494
+ cached = meta?.getAttribute("content") ?? null;
495
+ } catch {
496
+ cached = null;
497
+ }
498
+ return cached;
499
+ }
500
+ function applyNonce(el) {
501
+ const n = getCspNonce();
502
+ if (n) {
503
+ el.nonce = n;
504
+ }
505
+ }
506
+
470
507
  // lib/client/styles/UtilityClassCollector.ts
471
508
  function buildResponsivePrefixMap(breakpoints) {
472
509
  const breakpointValues = getBreakpointValues(breakpoints);
@@ -531,6 +568,7 @@ var UtilityClassCollectorImpl = class {
531
568
  if (document.head) {
532
569
  this.styleEl = document.createElement("style");
533
570
  this.styleEl.id = "utility-css";
571
+ applyNonce(this.styleEl);
534
572
  document.head.appendChild(this.styleEl);
535
573
  }
536
574
  return this.styleEl;
@@ -554,7 +592,7 @@ var UtilityClassCollectorImpl = class {
554
592
  if (this.injectedRules.has(name)) continue;
555
593
  const css = generateSingleClassCSS(name, breakpointConfig2, responsiveScalesConfig2, remConversionConfig2);
556
594
  if (css) {
557
- this.injectedRules.set(name, css);
595
+ this.injectedRules.set(name, rewriteViewportUnits(css));
558
596
  hasNew = true;
559
597
  }
560
598
  }
@@ -706,8 +744,8 @@ function hasCMSTemplate(text) {
706
744
  import { createElement as h2 } from "react";
707
745
  import DOMPurify from "isomorphic-dompurify";
708
746
  var SANITIZE_CONFIG = {
709
- ALLOWED_TAGS: ["svg", "path", "circle", "rect", "line", "polyline", "polygon", "g", "text", "tspan", "image", "defs", "use", "linearGradient", "radialGradient", "stop", "clipPath", "mask", "pattern", "marker", "symbol", "a", "div", "span", "p", "br", "button", "img", "iframe", "video", "audio", "source", "canvas", "b", "i", "u", "strong", "em", "sub", "sup", "mark", "s", "small", "del", "ins", "q", "abbr", "code", "pre", "blockquote", "ul", "ol", "li", "h1", "h2", "h3", "h4", "h5", "h6", "style", "animate", "animateTransform", "animateMotion", "set"],
710
- ALLOWED_ATTR: ["class", "id", "style", "width", "height", "viewBox", "xmlns", "fill", "stroke", "stroke-width", "stroke-linecap", "stroke-linejoin", "stroke-dasharray", "stroke-dashoffset", "d", "cx", "cy", "r", "x", "y", "x1", "y1", "x2", "y2", "points", "href", "src", "alt", "target", "rel", "data-*", "aria-*", "transform", "opacity", "fill-opacity", "stroke-opacity", "font-size", "font-family", "text-anchor", "dominant-baseline", "offset", "stop-color", "stop-opacity", "frameborder", "allowfullscreen", "allow", "title", "attributeName", "values", "dur", "begin", "end", "repeatCount", "repeatDur", "keyTimes", "keySplines", "calcMode", "from", "to", "by", "additive", "accumulate", "type", "rotate", "keyPoints", "path"],
747
+ ALLOWED_TAGS: ["svg", "path", "circle", "rect", "line", "polyline", "polygon", "g", "text", "tspan", "image", "defs", "use", "linearGradient", "radialGradient", "stop", "clipPath", "mask", "pattern", "marker", "symbol", "a", "div", "span", "p", "br", "button", "img", "iframe", "video", "audio", "source", "canvas", "b", "i", "u", "strong", "em", "sub", "sup", "mark", "s", "small", "del", "ins", "q", "abbr", "code", "pre", "blockquote", "ul", "ol", "li", "h1", "h2", "h3", "h4", "h5", "h6", "style", "animate", "animateTransform", "animateMotion", "set", "filter", "feGaussianBlur", "feOffset", "feMerge", "feMergeNode", "feColorMatrix", "feComposite", "feFlood", "feMorphology", "feBlend", "feDropShadow", "feTurbulence", "feDisplacementMap", "foreignObject"],
748
+ ALLOWED_ATTR: ["class", "id", "style", "width", "height", "viewBox", "xmlns", "xmlns:xlink", "xlink:href", "fill", "stroke", "stroke-width", "stroke-linecap", "stroke-linejoin", "stroke-dasharray", "stroke-dashoffset", "d", "cx", "cy", "r", "x", "y", "x1", "y1", "x2", "y2", "points", "href", "src", "alt", "target", "rel", "data-*", "aria-*", "transform", "opacity", "fill-opacity", "fill-rule", "clip-rule", "clip-path", "clipPathUnits", "mask", "mask-type", "maskUnits", "maskContentUnits", "patternUnits", "patternContentUnits", "patternTransform", "gradientUnits", "gradientTransform", "spreadMethod", "preserveAspectRatio", "marker-start", "marker-mid", "marker-end", "markerUnits", "markerWidth", "markerHeight", "refX", "refY", "orient", "paint-order", "vector-effect", "filter", "filterUnits", "primitiveUnits", "in", "in2", "result", "stdDeviation", "flood-color", "flood-opacity", "stroke-opacity", "font-size", "font-family", "font-weight", "font-style", "text-anchor", "dominant-baseline", "offset", "stop-color", "stop-opacity", "frameborder", "allowfullscreen", "allow", "title", "attributeName", "values", "dur", "begin", "end", "repeatCount", "repeatDur", "keyTimes", "keySplines", "calcMode", "from", "to", "by", "additive", "accumulate", "type", "rotate", "keyPoints", "path"],
711
749
  KEEP_CONTENT: true
712
750
  };
713
751
  function buildEmbed(node, ctx, deps) {
@@ -723,7 +761,7 @@ function buildEmbed(node, ctx, deps) {
723
761
  const effectiveLocale = ctx.cmsLocale || ctx.locale;
724
762
  htmlContent = processCMSTemplate(htmlContent, ctx.cmsContext, effectiveLocale);
725
763
  }
726
- const sanitizedHtml = DOMPurify.sanitize(htmlContent, SANITIZE_CONFIG);
764
+ const sanitizedHtml = inlineSvgStyleRules(DOMPurify.sanitize(htmlContent, SANITIZE_CONFIG));
727
765
  const effectiveParentComponentName = deps.getEffectiveParentComponentName(componentContext, parentComponentName);
728
766
  const extractedAttributes = extractAttributesFromNode(node);
729
767
  const embedProps = {
@@ -1229,6 +1267,15 @@ function buildList(node, children, ctx, deps) {
1229
1267
  containerProps["data-list"] = "true";
1230
1268
  containerProps["data-source"] = source || (sourceIsResolved ? "resolved" : "");
1231
1269
  }
1270
+ if (cmsItemIndexPath && cmsItemIndexPath.length > 0) {
1271
+ containerProps["data-cms-item-index"] = cmsItemIndexPath.join(".");
1272
+ if (cmsListPaths && cmsListPaths.length === cmsItemIndexPath.length) {
1273
+ containerProps["data-cms-context"] = JSON.stringify({
1274
+ itemIndexPath: cmsItemIndexPath,
1275
+ listPaths: cmsListPaths
1276
+ });
1277
+ }
1278
+ }
1232
1279
  if (Object.keys(extractedAttributes).length > 0) {
1233
1280
  Object.assign(containerProps, extractedAttributes);
1234
1281
  }
@@ -1330,17 +1377,19 @@ function buildList(node, children, ctx, deps) {
1330
1377
  templateContext: itemTemplateContext,
1331
1378
  componentResolvedProps
1332
1379
  });
1380
+ const cmsItem = item;
1381
+ const itemKey = cmsItem?._id ?? cmsItem?._filename ?? index;
1333
1382
  if (itemChildren === null) continue;
1334
1383
  if (Array.isArray(itemChildren)) {
1335
1384
  for (const child of itemChildren) {
1336
1385
  if (typeof child === "object" && child !== null && "key" in child) {
1337
- renderedItems.push({ ...child, key: `${child.key}-item-${index}` });
1386
+ renderedItems.push({ ...child, key: `${child.key}-item-${itemKey}` });
1338
1387
  } else {
1339
1388
  renderedItems.push(child);
1340
1389
  }
1341
1390
  }
1342
1391
  } else if (typeof itemChildren === "object" && itemChildren !== null && "key" in itemChildren) {
1343
- renderedItems.push({ ...itemChildren, key: `${itemChildren.key}-item-${index}` });
1392
+ renderedItems.push({ ...itemChildren, key: `${itemChildren.key}-item-${itemKey}` });
1344
1393
  } else {
1345
1394
  renderedItems.push(itemChildren);
1346
1395
  }
@@ -1679,18 +1728,18 @@ var ComponentBuilder = class {
1679
1728
  * Get cached utility classes for a style object
1680
1729
  */
1681
1730
  getCachedStyleClasses(style) {
1682
- let cached = this.styleClassCache.get(style);
1683
- if (!cached) {
1731
+ let cached2 = this.styleClassCache.get(style);
1732
+ if (!cached2) {
1684
1733
  const scales = getCachedResponsiveScalesConfig();
1685
1734
  const fluidActive = scales?.enabled === true && scales?.mode === "fluid";
1686
- cached = responsiveStylesToClasses(
1735
+ cached2 = responsiveStylesToClasses(
1687
1736
  style,
1688
1737
  { fluidActive, responsiveScales: scales ?? void 0 }
1689
1738
  );
1690
- this.styleClassCache.set(style, cached);
1739
+ this.styleClassCache.set(style, cached2);
1691
1740
  }
1692
- UtilityClassCollector.collect(cached);
1693
- return cached;
1741
+ UtilityClassCollector.collect(cached2);
1742
+ return cached2;
1694
1743
  }
1695
1744
  /**
1696
1745
  * Helper function to create onClick handlers from JSON-defined onClick values
@@ -1861,6 +1910,9 @@ var ComponentBuilder = class {
1861
1910
  componentResolvedProps = null
1862
1911
  } = options;
1863
1912
  if (!node) return null;
1913
+ if (typeof node === "object" && node._code === true) {
1914
+ return null;
1915
+ }
1864
1916
  if (isI18nValue(node)) {
1865
1917
  const i18nResolveConfig = i18nConfig ?? DEFAULT_I18N_CONFIG;
1866
1918
  const i18nEffectiveLocale = locale || i18nResolveConfig.defaultLocale;
@@ -2267,7 +2319,12 @@ var ComponentBuilder = class {
2267
2319
  itemContext = null,
2268
2320
  cmsItemIndexPath = null,
2269
2321
  cmsListPaths = null,
2270
- templateContext = null
2322
+ templateContext = null,
2323
+ // The host (outer) component's resolved props. Forwarded to
2324
+ // `processStructure` as `parentProps` so a `{{x}}` in this
2325
+ // component's structure falls back to the host's `x` when this
2326
+ // component's interface doesn't declare it.
2327
+ componentResolvedProps: parentResolvedProps = null
2271
2328
  } = options;
2272
2329
  const componentDef = this.componentRegistry.get(componentName);
2273
2330
  if (!componentDef) return null;
@@ -2298,7 +2355,11 @@ var ComponentBuilder = class {
2298
2355
  const markedChildren = typedChildren ? markAsSlotContent(typedChildren) : void 0;
2299
2356
  const processedStructure = processStructure(
2300
2357
  structuredComponentDef.structure,
2301
- { props: resolvedProps, componentDef: structuredComponentDef },
2358
+ {
2359
+ props: resolvedProps,
2360
+ componentDef: structuredComponentDef,
2361
+ parentProps: parentResolvedProps ?? void 0
2362
+ },
2302
2363
  viewportWidth,
2303
2364
  markedChildren
2304
2365
  );
@@ -2523,7 +2584,7 @@ var RouteLoader = class {
2523
2584
  */
2524
2585
  async loadGlobalComponents(signal) {
2525
2586
  try {
2526
- const fetchOptions = { cache: "no-store" };
2587
+ const fetchOptions = { cache: "default" };
2527
2588
  if (signal) {
2528
2589
  fetchOptions.signal = signal;
2529
2590
  }
@@ -2586,10 +2647,10 @@ var RouteLoader = class {
2586
2647
  if (this.config.onLocaleDetected && !this.isCancelled) {
2587
2648
  this.config.onLocaleDetected(locale);
2588
2649
  }
2589
- const cached = this.prefetchService?.getFromCache(pathWithoutLocale);
2590
- if (cached) {
2650
+ const cached2 = this.prefetchService?.getFromCache(pathWithoutLocale);
2651
+ if (cached2) {
2591
2652
  let tree2 = null;
2592
- const parsed2 = cached.data;
2653
+ const parsed2 = cached2.data;
2593
2654
  if (parsed2.components) {
2594
2655
  this.config.componentRegistry.merge(parsed2.components);
2595
2656
  tree2 = parsed2.root || parsed2;
@@ -2606,7 +2667,7 @@ var RouteLoader = class {
2606
2667
  return tree2;
2607
2668
  }
2608
2669
  const response = await fetch(`${API_ROUTES.PAGE_CONTENT}?page=${encodeURIComponent(pathWithoutLocale)}`, {
2609
- cache: "no-store",
2670
+ cache: "default",
2610
2671
  signal: abortController.signal
2611
2672
  });
2612
2673
  if (abortController.signal.aborted || this.isCancelled) {
@@ -3235,15 +3296,17 @@ ${originalCSS}`);
3235
3296
  }
3236
3297
  }
3237
3298
  if (processedCSSBlocks.length === 0) return;
3238
- const combinedCSS = processedCSSBlocks.join("\n\n");
3299
+ const combinedCSS = rewriteViewportUnits(processedCSSBlocks.join("\n\n"));
3239
3300
  const hash = simpleHash(combinedCSS);
3240
- if (hash === this.previousComponentCSSHash) return;
3301
+ const existing = typeof document !== "undefined" ? document.getElementById(this.styleId) : null;
3302
+ if (hash === this.previousComponentCSSHash && existing) return;
3241
3303
  this.previousComponentCSSHash = hash;
3242
3304
  if (document.head) {
3243
- let styleTag = document.getElementById(this.styleId);
3305
+ let styleTag = existing;
3244
3306
  if (!styleTag) {
3245
3307
  styleTag = document.createElement("style");
3246
3308
  styleTag.id = this.styleId;
3309
+ applyNonce(styleTag);
3247
3310
  document.head.appendChild(styleTag);
3248
3311
  }
3249
3312
  styleTag.textContent = combinedCSS;
@@ -3261,13 +3324,16 @@ ${originalCSS}`);
3261
3324
  const breakpointConfig2 = getCachedBreakpointConfig() || DEFAULT_BREAKPOINTS;
3262
3325
  const remConversionConfig2 = getCachedRemConversionConfig() || void 0;
3263
3326
  const responsiveScalesConfig2 = getCachedResponsiveScalesConfig() || void 0;
3264
- const interactiveCSS = generateAllInteractiveCSS(interactiveStylesMap, breakpointConfig2, remConversionConfig2, responsiveScalesConfig2);
3327
+ const interactiveCSS = rewriteViewportUnits(
3328
+ generateAllInteractiveCSS(interactiveStylesMap, breakpointConfig2, remConversionConfig2, responsiveScalesConfig2)
3329
+ );
3265
3330
  if (!interactiveCSS) return;
3266
3331
  if (document.head) {
3267
3332
  let styleTag = document.getElementById(interactiveStyleId);
3268
3333
  if (!styleTag) {
3269
3334
  styleTag = document.createElement("style");
3270
3335
  styleTag.id = interactiveStyleId;
3336
+ applyNonce(styleTag);
3271
3337
  document.head.appendChild(styleTag);
3272
3338
  }
3273
3339
  styleTag.textContent = interactiveCSS;
@@ -3308,9 +3374,33 @@ function generateDestructure(defineVars, interfaceDef) {
3308
3374
  var ScriptExecutor = class {
3309
3375
  componentRegistry;
3310
3376
  elementRegistry;
3377
+ // Tracks which (element, componentName) pairs have already had their user
3378
+ // JS executed. Prevents stacking side effects (IntersectionObservers,
3379
+ // event listeners, intervals) when execute() is re-called on the same
3380
+ // DOM nodes after a structural commit. WeakMap stays out of the DOM and
3381
+ // GCs cleanly when React unmounts elements.
3382
+ boundElements = /* @__PURE__ */ new WeakMap();
3311
3383
  constructor(config) {
3312
3384
  this.componentRegistry = config.componentRegistry;
3313
3385
  this.elementRegistry = config.elementRegistry;
3386
+ if (typeof window !== "undefined") {
3387
+ window.__menoShouldBind = (el, name) => this.shouldBind(el, name);
3388
+ }
3389
+ }
3390
+ /**
3391
+ * Check whether (element, componentName) has already been bound this
3392
+ * session. Records the bind on first call. Returns `true` if the caller
3393
+ * should run the user JS, `false` if it should skip.
3394
+ */
3395
+ shouldBind(el, componentName) {
3396
+ let names = this.boundElements.get(el);
3397
+ if (names && names.has(componentName)) return false;
3398
+ if (!names) {
3399
+ names = /* @__PURE__ */ new Set();
3400
+ this.boundElements.set(el, names);
3401
+ }
3402
+ names.add(componentName);
3403
+ return true;
3314
3404
  }
3315
3405
  /**
3316
3406
  * Execute JavaScript code via new Function() with error isolation
@@ -3350,6 +3440,10 @@ var ScriptExecutor = class {
3350
3440
  if (!props) {
3351
3441
  return;
3352
3442
  }
3443
+ const instanceEl = this.elementRegistry.get(rootPath);
3444
+ if (instanceEl && !this.shouldBind(instanceEl, componentName)) {
3445
+ return;
3446
+ }
3353
3447
  try {
3354
3448
  const processedJS = processCodeTemplates(originalJS, props);
3355
3449
  this.executeWrappedJS(processedJS, `${componentName} (instance: ${rootPath})`);
@@ -3375,10 +3469,20 @@ var ScriptExecutor = class {
3375
3469
  // Component: ${componentName} (defineVars)
3376
3470
  try {
3377
3471
  var elements = document.querySelectorAll('[data-component~="${componentName}"]');
3472
+ var shouldBind = (typeof window !== 'undefined' && typeof window.__menoShouldBind === 'function')
3473
+ ? window.__menoShouldBind
3474
+ : null;
3378
3475
  elements.forEach(function(el) {
3476
+ // Skip elements already bound for this component. When the host
3477
+ // hook is absent (direct <script> use, test harness), bind
3478
+ // unconditionally \u2014 preserves legacy "runs once at page load"
3479
+ // semantics for non-runtime contexts.
3480
+ if (shouldBind && !shouldBind(el, ${JSON.stringify(componentName)})) {
3481
+ return;
3482
+ }
3379
3483
  var propsStr = el.getAttribute('data-props');
3380
3484
  var allProps = propsStr ? JSON.parse(propsStr) : {};
3381
- var props = allProps["${componentName}"] || {};
3485
+ var props = allProps[${JSON.stringify(componentName)}] || {};
3382
3486
  (function(el, props) {
3383
3487
  ${destructure}
3384
3488
  ${js}
@@ -3478,7 +3582,12 @@ var ScriptExecutor = class {
3478
3582
  }
3479
3583
  /**
3480
3584
  * Re-execute JavaScript for a specific element instance (used for editor reactivity)
3481
- * Updates data-props attribute and re-runs the component JS for that element
3585
+ * Updates data-props attribute and re-runs the component JS for that element.
3586
+ *
3587
+ * NOTE: This path intentionally bypasses the per-element bind dedup
3588
+ * (`boundElements` / `shouldBind`). It exists so live prop edits in the
3589
+ * editor can re-run the user JS on demand with new prop values — the
3590
+ * caller is signaling "re-bind this element now," not "bind once."
3482
3591
  * @param componentName - Component name
3483
3592
  * @param element - The DOM element to re-execute for
3484
3593
  * @param newProps - New props to inject
@@ -3858,6 +3967,7 @@ function Router(props = {}) {
3858
3967
  const [cmsTemplatePath, setCmsTemplatePath] = useState2(null);
3859
3968
  const lastCommitTimestampRef = useRef2(0);
3860
3969
  const COMMIT_GRACE_MS = 1e3;
3970
+ const lastCommitStructureChangedRef = useRef2(true);
3861
3971
  const ssrCmsHandledRef = useRef2(false);
3862
3972
  const initialLoadDoneRef = useRef2(false);
3863
3973
  const routeLoader = useRef2(new RouteLoader({
@@ -3934,29 +4044,51 @@ function Router(props = {}) {
3934
4044
  useEffect2(() => {
3935
4045
  if (typeof window === "undefined") return;
3936
4046
  const handleMessage = (event) => {
3937
- if (event.data?.type === IFRAME_MESSAGE_TYPES.CSS_VARIABLE_UPDATE) {
3938
- const { name, value } = event.data;
3939
- document.documentElement.style.setProperty(name, value);
4047
+ if (event.data?.type === IFRAME_MESSAGE_TYPES.CSS_VARIABLE_UPDATE || event.data?.type === IFRAME_MESSAGE_TYPES.CSS_VARIABLE_SCOPED_UPDATE) {
4048
+ const { name, value, media, maxWidth } = event.data;
4049
+ const styleId = "meno-scrub-preview";
4050
+ let styleTag = document.getElementById(styleId);
4051
+ if (!styleTag) {
4052
+ styleTag = document.createElement("style");
4053
+ styleTag.id = styleId;
4054
+ applyNonce(styleTag);
4055
+ document.head.appendChild(styleTag);
4056
+ }
4057
+ const mediaExpr = media ?? (typeof maxWidth === "number" ? `(max-width: ${maxWidth}px)` : null);
4058
+ styleTag.textContent = mediaExpr ? `@media ${mediaExpr} { :root { ${name}: ${value}; } }` : `:root { ${name}: ${value}; }`;
4059
+ return;
4060
+ }
4061
+ if (event.data?.type === IFRAME_MESSAGE_TYPES.CSS_VARIABLE_SCOPED_CLEAR) {
4062
+ document.getElementById("meno-scrub-preview")?.remove();
3940
4063
  return;
3941
4064
  }
3942
4065
  if (event.data?.type === IFRAME_MESSAGE_TYPES.INTERACTIVE_CSS_UPDATE) {
3943
4066
  const css = event.data.css;
3944
4067
  const styleId = "interactive-styles";
3945
- const existingStyle = document.getElementById(styleId);
3946
- if (existingStyle) {
3947
- existingStyle.remove();
3948
- }
3949
- if (css && document.head) {
3950
- const styleTag = document.createElement("style");
4068
+ if (!css) return;
4069
+ if (!document.head) return;
4070
+ const rewritten = rewriteViewportUnits(css);
4071
+ let styleTag = document.getElementById(styleId);
4072
+ if (!styleTag) {
4073
+ styleTag = document.createElement("style");
3951
4074
  styleTag.id = styleId;
3952
- styleTag.textContent = css;
4075
+ applyNonce(styleTag);
3953
4076
  document.head.appendChild(styleTag);
3954
4077
  }
4078
+ styleTag.textContent = rewritten;
3955
4079
  }
3956
4080
  };
3957
4081
  window.addEventListener("message", handleMessage);
3958
4082
  return () => window.removeEventListener("message", handleMessage);
3959
4083
  }, []);
4084
+ useEffect2(() => {
4085
+ if (typeof window === "undefined") return;
4086
+ const clearScrubPreview = () => {
4087
+ document.getElementById("meno-scrub-preview")?.remove();
4088
+ };
4089
+ document.addEventListener("hmr-variables-update", clearScrubPreview);
4090
+ return () => document.removeEventListener("hmr-variables-update", clearScrubPreview);
4091
+ }, []);
3960
4092
  useEffect2(() => {
3961
4093
  if (typeof window === "undefined") return;
3962
4094
  const handleMessage = (event) => {
@@ -3969,6 +4101,7 @@ function Router(props = {}) {
3969
4101
  setPreviewComponentTree(null);
3970
4102
  } else if (event.data?.type === IFRAME_MESSAGE_TYPES.PAGE_DATA_COMMITTED) {
3971
4103
  lastCommitTimestampRef.current = Date.now();
4104
+ lastCommitStructureChangedRef.current = event.data.structureChanged !== false;
3972
4105
  const pageData = event.data.pageData;
3973
4106
  if (pageData?.root) {
3974
4107
  setComponentTree(pageData.root);
@@ -3977,6 +4110,7 @@ function Router(props = {}) {
3977
4110
  }
3978
4111
  } else if (event.data?.type === IFRAME_MESSAGE_TYPES.COMPONENT_DEFINITION_COMMITTED) {
3979
4112
  lastCommitTimestampRef.current = Date.now();
4113
+ lastCommitStructureChangedRef.current = event.data.structureChanged !== false;
3980
4114
  const { componentName, definition } = event.data;
3981
4115
  if (componentName && definition) {
3982
4116
  services.componentRegistry.register(componentName, definition);
@@ -4012,7 +4146,9 @@ function Router(props = {}) {
4012
4146
  styles: registryData
4013
4147
  }, "*");
4014
4148
  }
4015
- if (!disableScripts) {
4149
+ const shouldRunScripts = !disableScripts && lastCommitStructureChangedRef.current;
4150
+ lastCommitStructureChangedRef.current = true;
4151
+ if (shouldRunScripts) {
4016
4152
  const timeoutId = setTimeout(() => {
4017
4153
  services.scriptExecutor.execute();
4018
4154
  }, 100);
@@ -4429,6 +4565,7 @@ ${vars}
4429
4565
  if (!themeStyleTag) {
4430
4566
  themeStyleTag = document.createElement("style");
4431
4567
  themeStyleTag.id = "hmr-theme-variables";
4568
+ applyNonce(themeStyleTag);
4432
4569
  const mainStyle = document.querySelector("style");
4433
4570
  if (mainStyle && mainStyle.nextSibling) {
4434
4571
  document.head.insertBefore(themeStyleTag, mainStyle.nextSibling);
@@ -4646,6 +4783,159 @@ function mergeStyles(...styles) {
4646
4783
  }, {});
4647
4784
  }
4648
4785
 
4786
+ // lib/client/hmrCssReload.ts
4787
+ async function injectUpdatedThemeCSS2() {
4788
+ try {
4789
+ const themesResponse = await fetch("/api/themes");
4790
+ if (!themesResponse.ok) return;
4791
+ const themesData = await themesResponse.json();
4792
+ const themeColors = {};
4793
+ for (const theme of themesData.themes) {
4794
+ const colorResponse = await fetch(
4795
+ `/api/colors?theme=${encodeURIComponent(theme.name)}`
4796
+ );
4797
+ if (colorResponse.ok) {
4798
+ themeColors[theme.name] = (await colorResponse.json()).colors;
4799
+ }
4800
+ }
4801
+ const defaultResponse = await fetch("/api/colors");
4802
+ if (defaultResponse.ok) {
4803
+ themeColors["default"] = (await defaultResponse.json()).colors;
4804
+ }
4805
+ let css = "";
4806
+ if (themeColors["default"]) {
4807
+ const vars = Object.entries(themeColors["default"]).map(([name, value]) => ` --${name}: ${value};`).join("\n");
4808
+ css += `:root {
4809
+ ${vars}
4810
+ }
4811
+
4812
+ `;
4813
+ }
4814
+ for (const theme of themesData.themes) {
4815
+ if (themeColors[theme.name]) {
4816
+ const vars = Object.entries(themeColors[theme.name]).map(([name, value]) => ` --${name}: ${value};`).join("\n");
4817
+ css += `[theme="${theme.name}"] {
4818
+ ${vars}
4819
+ }
4820
+
4821
+ `;
4822
+ }
4823
+ }
4824
+ let styleTag = document.getElementById("hmr-theme-variables");
4825
+ if (!styleTag) {
4826
+ styleTag = document.createElement("style");
4827
+ styleTag.id = "hmr-theme-variables";
4828
+ applyNonce(styleTag);
4829
+ document.head.appendChild(styleTag);
4830
+ }
4831
+ styleTag.textContent = css;
4832
+ } catch {
4833
+ }
4834
+ }
4835
+ async function injectUpdatedVariablesCSS() {
4836
+ try {
4837
+ const response = await fetch("/api/variables-css");
4838
+ if (!response.ok) return;
4839
+ const css = await response.text();
4840
+ let styleTag = document.getElementById("hmr-css-variables");
4841
+ if (!styleTag) {
4842
+ styleTag = document.createElement("style");
4843
+ styleTag.id = "hmr-css-variables";
4844
+ applyNonce(styleTag);
4845
+ document.head.appendChild(styleTag);
4846
+ }
4847
+ styleTag.textContent = css;
4848
+ } catch {
4849
+ }
4850
+ }
4851
+ async function injectUpdatedFontsCSS() {
4852
+ try {
4853
+ const response = await fetch("/api/fonts-css");
4854
+ if (!response.ok) return;
4855
+ const css = await response.text();
4856
+ let styleTag = document.getElementById("hmr-fonts-css");
4857
+ if (!styleTag) {
4858
+ styleTag = document.createElement("style");
4859
+ styleTag.id = "hmr-fonts-css";
4860
+ applyNonce(styleTag);
4861
+ document.head.appendChild(styleTag);
4862
+ }
4863
+ styleTag.textContent = css;
4864
+ } catch {
4865
+ }
4866
+ }
4867
+ function setupCssHmrListeners() {
4868
+ if (typeof window === "undefined") return;
4869
+ if (!window.__hmrColorsInitialized) {
4870
+ window.__hmrColorsInitialized = true;
4871
+ document.addEventListener("hmr-colors-update", () => {
4872
+ void injectUpdatedThemeCSS2();
4873
+ });
4874
+ }
4875
+ if (!window.__hmrVariablesCSSInitialized) {
4876
+ window.__hmrVariablesCSSInitialized = true;
4877
+ document.addEventListener("hmr-variables-update", () => {
4878
+ void injectUpdatedVariablesCSS();
4879
+ });
4880
+ }
4881
+ if (!window.__hmrFontsCSSInitialized) {
4882
+ window.__hmrFontsCSSInitialized = true;
4883
+ document.addEventListener("hmr-fonts-update", () => {
4884
+ void injectUpdatedFontsCSS();
4885
+ });
4886
+ }
4887
+ if (!window.__hmrLibrariesInitialized) {
4888
+ window.__hmrLibrariesInitialized = true;
4889
+ document.addEventListener("hmr-libraries-update", () => {
4890
+ location.reload();
4891
+ });
4892
+ }
4893
+ }
4894
+
4895
+ // lib/client/fontFamiliesService.ts
4896
+ function extractFamilyFromPath(path) {
4897
+ const filename = path.split("/").pop() || "Font";
4898
+ const name = filename.replace(/\.(ttf|woff2?|otf)$/i, "");
4899
+ return name.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
4900
+ }
4901
+ function extractFamilies(fonts) {
4902
+ if (!Array.isArray(fonts)) return [];
4903
+ const set = /* @__PURE__ */ new Set();
4904
+ for (const font of fonts) {
4905
+ const path = font.path || font.src;
4906
+ const family = font.family || (path ? extractFamilyFromPath(path) : null);
4907
+ if (family) set.add(family);
4908
+ }
4909
+ return [...set];
4910
+ }
4911
+ var cachedFamilies = null;
4912
+ var inFlight = null;
4913
+ async function fetchFontFamilies() {
4914
+ if (cachedFamilies) return cachedFamilies;
4915
+ if (inFlight) return inFlight;
4916
+ inFlight = fetch("/api/config").then((res) => res.ok ? res.json() : { fonts: [] }).then((config) => {
4917
+ cachedFamilies = extractFamilies(config.fonts);
4918
+ return cachedFamilies;
4919
+ }).catch(() => {
4920
+ cachedFamilies = [];
4921
+ return cachedFamilies;
4922
+ }).finally(() => {
4923
+ inFlight = null;
4924
+ });
4925
+ return inFlight;
4926
+ }
4927
+ function getCachedFontFamilies() {
4928
+ return cachedFamilies || [];
4929
+ }
4930
+ function invalidateFontFamilies() {
4931
+ cachedFamilies = null;
4932
+ inFlight = null;
4933
+ }
4934
+ async function initializeFontFamilies(forceRefresh = false) {
4935
+ if (forceRefresh) invalidateFontFamilies();
4936
+ await fetchFontFamilies();
4937
+ }
4938
+
4649
4939
  // lib/client/hooks/usePropertyAutocomplete.ts
4650
4940
  import { useState as useState5, useRef as useRef4 } from "react";
4651
4941
  function usePropertyAutocomplete(initialProperty = "") {
@@ -4775,8 +5065,10 @@ export {
4775
5065
  detectSSRContent,
4776
5066
  elementRegistry,
4777
5067
  evaluateTemplate,
5068
+ fetchFontFamilies,
4778
5069
  fetchI18nConfig,
4779
5070
  getCachedBreakpointConfig,
5071
+ getCachedFontFamilies,
4780
5072
  getCachedRemConversionConfig,
4781
5073
  getCachedResponsiveScalesConfig,
4782
5074
  getColorVariableSuggestions,
@@ -4789,6 +5081,8 @@ export {
4789
5081
  hasTemplates,
4790
5082
  initializeBreakpoints,
4791
5083
  initializeConfig,
5084
+ initializeFontFamilies,
5085
+ invalidateFontFamilies,
4792
5086
  invalidateI18nConfig,
4793
5087
  isColorVariableValue,
4794
5088
  isHtmlMapping,
@@ -4811,6 +5105,7 @@ export {
4811
5105
  resolveStyleMapping,
4812
5106
  setElementRegistry,
4813
5107
  setI18nConfig,
5108
+ setupCssHmrListeners,
4814
5109
  useColorVariables,
4815
5110
  usePropertyAutocomplete,
4816
5111
  useTheme,