@jbpark/live-editor 4.4.0 → 4.6.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 (77) hide show
  1. package/README.ko.md +4 -1
  2. package/README.md +7 -3
  3. package/dist/{boundary-B17cepvm.js → boundary-BLB80tyw.js} +8 -5
  4. package/dist/boundary-BLB80tyw.js.map +1 -0
  5. package/dist/cache-B0-XcIxJ.js.map +1 -1
  6. package/dist/{compile-DDfk5P25.js → compile-Dxas-D05.js} +3 -3
  7. package/dist/compile-Dxas-D05.js.map +1 -0
  8. package/dist/{constants-h1JAgOeW.js → constants-DU17Tdwo.js} +3 -3
  9. package/dist/constants-DU17Tdwo.js.map +1 -0
  10. package/dist/{context-DB5kW3qe.js → context-B8MzP7_p.js} +11 -5
  11. package/dist/context-B8MzP7_p.js.map +1 -0
  12. package/dist/{core-CRsAGpei.js → core-Bgfek364.js} +2 -2
  13. package/dist/core-Bgfek364.js.map +1 -0
  14. package/dist/{detect-typescript-CCj9ALXc.js → detect-typescript-Dr_oLniM.js} +2 -2
  15. package/dist/detect-typescript-Dr_oLniM.js.map +1 -0
  16. package/dist/dnd/index.d.ts +1 -1
  17. package/dist/dnd/index.js +1 -1
  18. package/dist/{dnd-BE5ZizqX.js → dnd-UoJILA75.js} +973 -885
  19. package/dist/dnd-UoJILA75.js.map +1 -0
  20. package/dist/{document-BDn_f08_.js → document-CGbe6bSV.js} +7739 -7736
  21. package/dist/document-CGbe6bSV.js.map +1 -0
  22. package/dist/editor/index.js +2 -2
  23. package/dist/{editor-DQ8Q--qR.js → editor-CMElfHer.js} +2 -2
  24. package/dist/editor-CMElfHer.js.map +1 -0
  25. package/dist/editor-caches-ClMvdcQF.js.map +1 -1
  26. package/dist/error/index.d.ts +1 -1
  27. package/dist/error/index.js +2 -2
  28. package/dist/{error-DWhxQEom.js → error-CN_GCnXB.js} +13 -6
  29. package/dist/error-CN_GCnXB.js.map +1 -0
  30. package/dist/{index-Dgh1JTX3.d.ts → index-C69Lv-jR.d.ts} +72 -69
  31. package/dist/{index-C4SGQ3Ci.d.ts → index-CRwEhJ7w.d.ts} +4 -1
  32. package/dist/{index-f7ijuNTa.d.ts → index-DKYUxi-E.d.ts} +115 -155
  33. package/dist/index-DrWtSKXu.d.ts +11 -0
  34. package/dist/index.d.ts +18 -18
  35. package/dist/index.js +12 -8
  36. package/dist/index.js.map +1 -1
  37. package/dist/{ast-dYb78955.js → items-B6OXxcLG.js} +588 -718
  38. package/dist/items-B6OXxcLG.js.map +1 -0
  39. package/dist/messages-CSrMI4Rm.js +133 -0
  40. package/dist/messages-CSrMI4Rm.js.map +1 -0
  41. package/dist/messages-IBPs4TkZ.d.ts +130 -0
  42. package/dist/preview/index.js +2 -2
  43. package/dist/{preview-BnaCEFsF.js → preview-CtyG5UbH.js} +6 -4
  44. package/dist/preview-CtyG5UbH.js.map +1 -0
  45. package/dist/provider/index.d.ts +3 -8
  46. package/dist/provider/index.js +3 -2
  47. package/dist/{sections-CBVMO8Jl.js → sections-BYWOBISr.js} +9 -4
  48. package/dist/sections-BYWOBISr.js.map +1 -0
  49. package/dist/states-Ci1AvoQ9.js.map +1 -1
  50. package/dist/style.css +505 -21
  51. package/dist/{use-dynamic-tailwind-Bcipc1hL.js → use-dynamic-tailwind-BP1toJkW.js} +66 -40
  52. package/dist/use-dynamic-tailwind-BP1toJkW.js.map +1 -0
  53. package/dist/utils/ast/index.d.ts +3 -2
  54. package/dist/utils/ast/index.js +150 -3
  55. package/dist/utils/ast/index.js.map +1 -0
  56. package/dist/utils/index.d.ts +30 -13
  57. package/dist/utils/index.js +26 -6
  58. package/dist/utils/index.js.map +1 -0
  59. package/dist/utils/tailwind/index.js.map +1 -1
  60. package/dist/validate-DB59Z_Nx.d.ts +100 -0
  61. package/dist/validate-iLo8IONY.js +64 -0
  62. package/dist/validate-iLo8IONY.js.map +1 -0
  63. package/package.json +3 -3
  64. package/dist/ast-dYb78955.js.map +0 -1
  65. package/dist/boundary-B17cepvm.js.map +0 -1
  66. package/dist/compile-DDfk5P25.js.map +0 -1
  67. package/dist/constants-h1JAgOeW.js.map +0 -1
  68. package/dist/context-DB5kW3qe.js.map +0 -1
  69. package/dist/core-CRsAGpei.js.map +0 -1
  70. package/dist/detect-typescript-CCj9ALXc.js.map +0 -1
  71. package/dist/dnd-BE5ZizqX.js.map +0 -1
  72. package/dist/document-BDn_f08_.js.map +0 -1
  73. package/dist/editor-DQ8Q--qR.js.map +0 -1
  74. package/dist/error-DWhxQEom.js.map +0 -1
  75. package/dist/preview-BnaCEFsF.js.map +0 -1
  76. package/dist/sections-CBVMO8Jl.js.map +0 -1
  77. package/dist/use-dynamic-tailwind-Bcipc1hL.js.map +0 -1
@@ -1,10 +1,25 @@
1
- import { n as compile, s as withScriptBlobs } from "./compile-DDfk5P25.js";
1
+ import { i as useLiveMessages } from "./messages-CSrMI4Rm.js";
2
+ import { n as compile, s as withScriptBlobs } from "./compile-Dxas-D05.js";
2
3
  import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
3
4
  import { jsx } from "react/jsx-runtime";
4
5
  import * as ui from "@jbpark/ui-kit";
5
6
  import { useEventListener, useMutationObserver, useResizeObserver } from "@jbpark/use-hooks";
6
7
  import { createPortal } from "react-dom";
7
8
  import * as utils from "@jbpark/ui-kit/utils";
9
+ //#region src/components/preview/use-stable-modules.ts
10
+ const sameModules = (a, b) => {
11
+ if (a === b) return true;
12
+ if (!a || !b) return false;
13
+ const keys = Object.keys(a);
14
+ return keys.length === Object.keys(b).length && keys.every((key) => Object.hasOwn(b, key) && Object.is(a[key], b[key]));
15
+ };
16
+ const useStableModules = (modules) => {
17
+ const [stable, setStable] = useState(modules);
18
+ if (sameModules(stable, modules)) return stable;
19
+ setStable(modules);
20
+ return modules;
21
+ };
22
+ //#endregion
8
23
  //#region src/components/frame/measure.ts
9
24
  const verticalInsets = (style) => [
10
25
  style.marginTop,
@@ -20,18 +35,9 @@ const computeProbeHeight = (scrollContainerClientHeight, wrapperInsets) => {
20
35
  };
21
36
  const isVisuallyHidden = (computed, isAnimating = false) => computed.visibility === "hidden" || computed.opacity === "0" && !isAnimating;
22
37
  const isAnimationActive = (playState) => playState === "running" || playState === "paused";
23
- const parseTranslateY = (transform) => {
24
- if (!transform || transform === "none") return 0;
25
- const translateYMatch = transform.match(/translateY\(\s*([+-]?\d*\.?\d+)/);
26
- if (translateYMatch?.[1]) return parseFloat(translateYMatch[1]);
27
- const translateMatch = transform.match(/translate\([^,]+,\s*([+-]?\d*\.?\d+)/);
28
- if (translateMatch?.[1]) return parseFloat(translateMatch[1]);
29
- const matrixMatch = transform.match(/matrix\(\s*[^,]+,\s*[^,]+,\s*[^,]+,\s*[^,]+,\s*[^,]+,\s*([+-]?\d*\.?\d+)/);
30
- return matrixMatch?.[1] ? parseFloat(matrixMatch[1]) : 0;
31
- };
32
- const estimatePositionedElementHeight = (offsetHeight, transform, probeHeight) => {
33
- const offsetY = parseTranslateY(transform);
34
- return Math.min(offsetY + offsetHeight, probeHeight);
38
+ const positionedElementBottom = (top, bottom, probeHeight) => {
39
+ if (bottom <= 0 || top >= probeHeight) return null;
40
+ return Math.min(bottom, probeHeight);
35
41
  };
36
42
  //#endregion
37
43
  //#region src/components/frame/style-sync.ts
@@ -325,6 +331,8 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
325
331
  let contentHeight = 0;
326
332
  const freezeTransitions = probeHeight !== lastProbeHeightRef.current;
327
333
  lastProbeHeightRef.current = probeHeight;
334
+ const previousHeight = iframe.style.height;
335
+ iframe.style.height = `${probeHeight}px`;
328
336
  withMeasurementOverrides(doc, freezeTransitions, () => {
329
337
  ensureContainerStyle(doc, probeHeight);
330
338
  rewriteInlineViewportUnits(mountNode);
@@ -334,12 +342,13 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
334
342
  const isAnimating = style.opacity === "0" && hasActiveAnimation(el);
335
343
  if (isVisuallyHidden(style, isAnimating)) return;
336
344
  if ((style.position === "fixed" || style.position === "absolute") && el.offsetHeight > 0) {
337
- const estimatedHeight = estimatePositionedElementHeight(el.offsetHeight, style.transform, probeHeight);
338
- contentHeight = Math.max(contentHeight, estimatedHeight);
345
+ const rect = el.getBoundingClientRect();
346
+ const bottom = positionedElementBottom(rect.top, rect.bottom, probeHeight);
347
+ if (bottom !== null) contentHeight = Math.max(contentHeight, bottom);
339
348
  }
340
349
  });
341
350
  });
342
- if (contentHeight > 0) iframe.style.height = `${Math.ceil(contentHeight)}px`;
351
+ iframe.style.height = contentHeight > 0 ? `${Math.ceil(contentHeight)}px` : previousHeight;
343
352
  trackScriptAnimations(doc, win);
344
353
  }, [
345
354
  shouldAutoHeight,
@@ -432,12 +441,39 @@ const IFrame = ({ title = "Live Preview", sandbox, style = {}, scripts = EMPTY_S
432
441
  };
433
442
  //#endregion
434
443
  //#region src/components/frame/shadow.tsx
444
+ const OVERLAY_LAYER_ATTR = "data-live-editor-overlay-layer";
445
+ const OVERLAY_LAYER_STYLE = `[${OVERLAY_LAYER_ATTR}] > * { pointer-events: auto; }`;
446
+ const createFrameNodes = () => {
447
+ const wrapper = document.createElement("div");
448
+ wrapper.style.display = "grid";
449
+ wrapper.style.gridTemplateColumns = "minmax(0, 1fr)";
450
+ wrapper.style.minHeight = "100%";
451
+ wrapper.style.isolation = "isolate";
452
+ const renderTarget = document.createElement("div");
453
+ renderTarget.style.gridArea = "1 / 1";
454
+ const overlayLayer = document.createElement("div");
455
+ overlayLayer.setAttribute(OVERLAY_LAYER_ATTR, "");
456
+ overlayLayer.style.gridArea = "1 / 1";
457
+ overlayLayer.style.zIndex = "1";
458
+ overlayLayer.style.contain = "layout";
459
+ overlayLayer.style.pointerEvents = "none";
460
+ const style = document.createElement("style");
461
+ style.textContent = OVERLAY_LAYER_STYLE;
462
+ wrapper.append(style, renderTarget, overlayLayer);
463
+ return {
464
+ wrapper,
465
+ renderTarget
466
+ };
467
+ };
468
+ const overlayLayerOf = (renderTarget) => {
469
+ const layer = renderTarget.nextElementSibling;
470
+ return layer instanceof HTMLElement && layer.hasAttribute(OVERLAY_LAYER_ATTR) ? layer : null;
471
+ };
435
472
  const Shadow = ({ syncStyle = false, children }) => {
436
473
  const hostRef = useRef(null);
437
474
  const shadowRootRef = useRef(null);
438
475
  const renderTargetRef = useRef(null);
439
476
  const [renderTarget, setRenderTarget] = useState(null);
440
- const [hostContainer, setHostContainer] = useState(null);
441
477
  const styleManagerRef = useRef(createStyleSyncManager());
442
478
  const applyStyle = useCallback(() => {
443
479
  const shadowRoot = shadowRootRef.current;
@@ -460,8 +496,6 @@ const Shadow = ({ syncStyle = false, children }) => {
460
496
  });
461
497
  useLayoutEffect(() => {
462
498
  if (!hostRef.current) return;
463
- const container = hostRef.current.closest("[data-frame-container]");
464
- setHostContainer(container);
465
499
  let shadowRoot = shadowRootRef.current;
466
500
  if (!shadowRoot) {
467
501
  shadowRoot = hostRef.current.shadowRoot || hostRef.current.attachShadow({ mode: "open" });
@@ -469,8 +503,9 @@ const Shadow = ({ syncStyle = false, children }) => {
469
503
  }
470
504
  let target = renderTargetRef.current;
471
505
  if (!target) {
472
- target = document.createElement("div");
473
- shadowRoot.appendChild(target);
506
+ const nodes = createFrameNodes();
507
+ shadowRoot.appendChild(nodes.wrapper);
508
+ target = nodes.renderTarget;
474
509
  renderTargetRef.current = target;
475
510
  setRenderTarget(target);
476
511
  }
@@ -482,7 +517,7 @@ const Shadow = ({ syncStyle = false, children }) => {
482
517
  return /* @__PURE__ */ jsx("div", {
483
518
  ref: hostRef,
484
519
  style: { display: "contents" },
485
- children: renderTarget && createPortal(children(hostContainer), renderTarget)
520
+ children: renderTarget && createPortal(children(overlayLayerOf(renderTarget)), renderTarget)
486
521
  });
487
522
  };
488
523
  //#endregion
@@ -499,20 +534,6 @@ const Frame = ({ mode, children, ...restProps }) => {
499
534
  });
500
535
  };
501
536
  //#endregion
502
- //#region src/components/preview/use-stable-modules.ts
503
- const sameModules = (a, b) => {
504
- if (a === b) return true;
505
- if (!a || !b) return false;
506
- const keys = Object.keys(a);
507
- return keys.length === Object.keys(b).length && keys.every((key) => Object.hasOwn(b, key) && Object.is(a[key], b[key]));
508
- };
509
- const useStableModules = (modules) => {
510
- const [stable, setStable] = useState(modules);
511
- if (sameModules(stable, modules)) return stable;
512
- setStable(modules);
513
- return modules;
514
- };
515
- //#endregion
516
537
  //#region src/components/preview/base-modules.ts
517
538
  const baseModules = {
518
539
  "ui-kit": ui,
@@ -522,6 +543,7 @@ const baseModules = {
522
543
  //#region src/components/preview/use-compiled-module.ts
523
544
  const useCompiledModule = (code, _modules) => {
524
545
  const modules = useStableModules(_modules);
546
+ const { unknown } = useLiveMessages().errors;
525
547
  const mergedModules = useMemo(() => ({
526
548
  ...baseModules,
527
549
  ...modules
@@ -533,10 +555,14 @@ const useCompiledModule = (code, _modules) => {
533
555
  } catch (e) {
534
556
  return {
535
557
  exports: {},
536
- error: e instanceof Error ? e.message : "Module transformation error"
558
+ error: e instanceof Error ? e.message : unknown
537
559
  };
538
560
  }
539
- }, [code, mergedModules]);
561
+ }, [
562
+ code,
563
+ mergedModules,
564
+ unknown
565
+ ]);
540
566
  };
541
567
  //#endregion
542
568
  //#region src/components/preview/use-dynamic-tailwind.ts
@@ -566,6 +592,6 @@ const useDynamicTailwind = (code, enabled) => {
566
592
  };
567
593
  };
568
594
  //#endregion
569
- export { Frame as a, useStableModules as i, useCompiledModule as n, baseModules as r, useDynamicTailwind as t };
595
+ export { useStableModules as a, Frame as i, useCompiledModule as n, baseModules as r, useDynamicTailwind as t };
570
596
 
571
- //# sourceMappingURL=use-dynamic-tailwind-Bcipc1hL.js.map
597
+ //# sourceMappingURL=use-dynamic-tailwind-BP1toJkW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-dynamic-tailwind-BP1toJkW.js","names":[],"sources":["../src/components/preview/use-stable-modules.ts","../src/components/frame/measure.ts","../src/components/frame/style-sync.ts","../src/components/frame/viewport-units.ts","../src/components/frame/iframe.tsx","../src/components/frame/shadow.tsx","../src/components/frame/frame.tsx","../src/components/preview/base-modules.ts","../src/components/preview/use-compiled-module.ts","../src/components/preview/use-dynamic-tailwind.ts"],"sourcesContent":["import { useState } from 'react';\n\ntype Modules = Record<string, unknown> | undefined;\n\n// Same keys, each value the same object. A module is compared by identity,\n// never deeply: a module replaced with a changed object has to recompile\n// (#329). This is also how the compilation cache tells modules apart.\nconst sameModules = (a: Modules, b: Modules): boolean => {\n if (a === b) {\n return true;\n }\n\n if (!a || !b) {\n return false;\n }\n\n const keys = Object.keys(a);\n\n return (\n keys.length === Object.keys(b).length &&\n keys.every(key => Object.hasOwn(b, key) && Object.is(a[key], b[key]))\n );\n};\n\n// Keeps the previous `modules` object while its entries are the same, since\n// hosts usually pass a new inline object every render, which would recompile\n// every section (#397).\nexport const useStableModules = <T extends Modules>(modules: T): T => {\n const [stable, setStable] = useState(modules);\n\n if (sameModules(stable, modules)) {\n return stable;\n }\n\n // Adjusted during render, so the changed modules are used in this render\n // rather than one render late.\n setStable(modules);\n\n return modules;\n};\n","// The calculations behind `iframe.tsx`'s `autoHeight`, kept free of the DOM\n// so they can be unit-tested. The DOM reads stay in `iframe.tsx`, which needs\n// a real browser to test.\n\n// The probe height when there's no `[data-frame-container]` scroll\n// container, as when `Frame` is used without `Live.Dnd`. A common mobile\n// viewport height.\nexport const FALLBACK_PROBE_HEIGHT = 812;\n\n// The vertical space an element takes around its content: margin, border\n// and padding, top and bottom. Margin counts (#440), or a `100vh` section in\n// a wrapper with a margin would overflow the container by that margin. A\n// margin that collapses through a parent is counted twice, which errs toward\n// a smaller probe that fits.\nexport const verticalInsets = (\n style: Pick<\n CSSStyleDeclaration,\n | 'marginTop'\n | 'marginBottom'\n | 'borderTopWidth'\n | 'borderBottomWidth'\n | 'paddingTop'\n | 'paddingBottom'\n >,\n): number =>\n [\n style.marginTop,\n style.marginBottom,\n style.borderTopWidth,\n style.borderBottomWidth,\n style.paddingTop,\n style.paddingBottom,\n ].reduce((sum, value) => sum + (parseFloat(value) || 0), 0);\n\n// The height the preview's `cq*` units resolve against: the scroll\n// container's `clientHeight` minus `wrapperInsets`, the space everything\n// between the iframe and the container takes (`verticalInsets`). `null`\n// while the container isn't laid out yet: skip the pass rather than guess a\n// height that nothing would correct later.\nexport const computeProbeHeight = (\n scrollContainerClientHeight: number,\n wrapperInsets: number,\n): number | null => {\n const usable = scrollContainerClientHeight - wrapperInsets;\n\n return usable > 0 ? usable : null;\n};\n\n// Whether an element is hidden but still takes height: `visibility: hidden`\n// or `opacity: 0` (`display: none` already reads 0), such as a closed bottom\n// sheet. A transparent element that `isAnimating` is a fade-in starting, so\n// it's measured (#374). `visibility: hidden` stays hidden even while\n// animating.\nexport const isVisuallyHidden = (\n computed: {\n visibility: string;\n opacity: string;\n },\n isAnimating = false,\n): boolean =>\n computed.visibility === 'hidden' ||\n (computed.opacity === '0' && !isAnimating);\n\n// The `playState`s that mean the element is still changing. Not just\n// `!== 'idle'`: a finished fade-out with `fill-mode: forwards` stays\n// `finished` at `opacity: 0` and is hidden for good. `paused` counts, since\n// a paused fade-in stopped part-way.\nexport const isAnimationActive = (playState: string): boolean =>\n playState === 'running' || playState === 'paused';\n\n// How far down a fixed or absolute element reaches, from its viewport `top`\n// and `bottom` read while the viewport is `probeHeight` tall: its bottom\n// edge, capped at `probeHeight` so one element placed past the viewport can't\n// stretch the whole preview. `null` for an element entirely outside the\n// viewport, such as a closed drawer moved off-screen, which shows nothing.\nexport const positionedElementBottom = (\n top: number,\n bottom: number,\n probeHeight: number,\n): number | null => {\n if (bottom <= 0 || top >= probeHeight) {\n return null;\n }\n\n return Math.min(bottom, probeHeight);\n};\n","const SYNCED_STYLE_ATTR = 'data-live-editor-synced-style';\n\ntype SourceStyle = HTMLLinkElement | HTMLStyleElement;\ntype SyncedStyle = HTMLLinkElement | HTMLStyleElement;\n\nexport interface StyleSyncManager {\n clones: Map<SourceStyle, SyncedStyle>;\n}\n\nexport const createStyleSyncManager = (): StyleSyncManager => ({\n clones: new Map(),\n});\n\nconst isDocument = (target: Document | ShadowRoot): target is Document =>\n target.nodeType === Node.DOCUMENT_NODE;\n\nconst sourceStyles = (document: Document): SourceStyle[] =>\n Array.from(\n document.head.querySelectorAll<HTMLLinkElement | HTMLStyleElement>(\n 'link[rel=\"stylesheet\"], style',\n ),\n );\n\nconst copyAttributes = (\n source: SourceStyle,\n clone: SyncedStyle,\n transformStyle: (content: string) => string,\n) => {\n Array.from(clone.attributes).forEach(attribute => {\n if (\n attribute.name !== SYNCED_STYLE_ATTR &&\n !source.hasAttribute(attribute.name)\n ) {\n clone.removeAttribute(attribute.name);\n }\n });\n\n Array.from(source.attributes).forEach(attribute => {\n clone.setAttribute(attribute.name, attribute.value);\n });\n\n if (source.tagName === 'LINK' && clone.tagName === 'LINK') {\n (clone as HTMLLinkElement).disabled = (source as HTMLLinkElement).disabled;\n }\n\n clone.textContent =\n source.tagName === 'STYLE'\n ? transformStyle(source.textContent || '')\n : source.textContent;\n};\n\nconst createClone = (\n source: SourceStyle,\n target: Document | ShadowRoot,\n transformStyle: (content: string) => string,\n): SyncedStyle => {\n const ownerDocument = isDocument(target) ? target : target.ownerDocument;\n const clone = ownerDocument.createElement(\n source.tagName.toLowerCase(),\n ) as SyncedStyle;\n\n clone.setAttribute(SYNCED_STYLE_ATTR, '');\n copyAttributes(source, clone, transformStyle);\n\n return clone;\n};\n\nconst targetContainer = (target: Document | ShadowRoot) =>\n isDocument(target) ? target.head : target;\n\nconst isSyncedStyle = (node: Node): node is SyncedStyle => {\n const element = node as Element;\n\n return (\n (element.tagName === 'LINK' || element.tagName === 'STYLE') &&\n element.hasAttribute(SYNCED_STYLE_ATTR)\n );\n};\n\nconst removeClone = (clone: SyncedStyle) => {\n clone.remove();\n};\n\n// `anchor`, when given, is an element the synced block has to stay in front\n// of. Without it, a first sync appends the block after whatever the target\n// already holds, so a rule the target added for itself could end up before\n// the host's copies and lose to them on order (#441).\nexport const reconcileStyles = (\n sourceDocument: Document,\n target: Document | ShadowRoot,\n manager: StyleSyncManager,\n enabled: boolean,\n transformStyle: (content: string) => string = content => content,\n anchor: Node | null = null,\n) => {\n if (!enabled) {\n manager.clones.forEach(removeClone);\n manager.clones.clear();\n\n return;\n }\n\n const sources = sourceStyles(sourceDocument);\n const sourceSet = new Set(sources);\n const container = targetContainer(target);\n\n manager.clones.forEach((clone, source) => {\n if (!sourceSet.has(source)) {\n removeClone(clone);\n manager.clones.delete(source);\n }\n });\n\n let previous: SyncedStyle | null = null;\n\n sources.forEach(source => {\n let clone = manager.clones.get(source);\n\n if (!clone) {\n clone = createClone(source, target, transformStyle);\n manager.clones.set(source, clone);\n } else {\n copyAttributes(source, clone, transformStyle);\n }\n\n const nextSibling = previous\n ? previous.nextSibling\n : (Array.from(container.childNodes).find(isSyncedStyle) ??\n (anchor?.parentNode === container ? anchor : null));\n\n if (clone !== nextSibling) {\n container.insertBefore(clone, nextSibling);\n }\n\n previous = clone;\n });\n};\n\n// What a root-attribute sync has written onto the target, so a later pass\n// removes exactly that and never what the target set for itself.\nexport interface RootAttributeSync {\n attributes: Set<string>;\n classes: Set<string>;\n}\n\nexport const createRootAttributeSync = (): RootAttributeSync => ({\n attributes: new Set(),\n classes: new Set(),\n});\n\nconst isMirroredAttribute = (name: string) => name.startsWith('data-');\n\n// Mirrors the host `<html>`'s classes and `data-*` attributes onto an iframe's\n// `<html>`. A theme is usually switched there (`.dark`, `data-theme=\"dark\"`),\n// and copying the host's stylesheets alone doesn't help an iframe: its\n// selectors look for those on an ancestor, and the iframe document has a root\n// of its own. A shadow root needs none of this, since it sits under the host's\n// `<html>` already (#497).\n//\n// Classes are synced token by token, so a class the preview put on its own\n// root survives. Other attributes (`style`, `lang`, `dir`, ...) are left\n// alone: the frame relies on its own root for sizing and layout.\nexport const reconcileRootAttributes = (\n source: Element,\n target: Element,\n sync: RootAttributeSync,\n enabled: boolean,\n) => {\n const attributes = enabled\n ? Array.from(source.attributes).filter(({ name }) =>\n isMirroredAttribute(name),\n )\n : [];\n const classes = enabled ? Array.from(source.classList) : [];\n const attributeNames = new Set(attributes.map(({ name }) => name));\n const classNames = new Set(classes);\n\n sync.attributes.forEach(name => {\n if (!attributeNames.has(name)) {\n target.removeAttribute(name);\n }\n });\n attributes.forEach(({ name, value }) => {\n if (target.getAttribute(name) !== value) {\n target.setAttribute(name, value);\n }\n });\n\n sync.classes.forEach(name => {\n if (!classNames.has(name)) {\n target.classList.remove(name);\n }\n });\n classes.forEach(name => target.classList.add(name));\n\n if (!target.classList.length) {\n target.removeAttribute('class');\n }\n\n sync.attributes = attributeNames;\n sync.classes = classNames;\n};\n","// Rewrites viewport units to container units for `autoHeight` (#132). The\n// iframe measures its content against a fixed-height size container\n// (`html { container-type: size; height: <probe>px }`), but a size container\n// doesn't change what `vh` resolves against, so `vh`, `svh`, `lvh`, `dvh`,\n// `vmin` and `vmax` become `cqh`, `cqmin` and `cqmax`. `vw` and `vi` are left\n// alone: they depend on width, which the measurement doesn't touch.\nconst UNIT_MAP: Record<string, string> = {\n vh: 'cqh',\n svh: 'cqh',\n lvh: 'cqh',\n dvh: 'cqh',\n vmin: 'cqmin',\n vmax: 'cqmax',\n};\n\n// Longest-unit-first so `svh`/`lvh`/`dvh` aren't shadowed by a shorter\n// alternative matching a prefix of them first.\nconst UNITS_PATTERN = Object.keys(UNIT_MAP)\n .sort((a, b) => b.length - a.length)\n .join('|');\n\n// A CSS dimension token: optional sign, then digits with an optional\n// fractional part on either side of the decimal point (`100`, `50.5`,\n// `-10`, `.5` all match; a bare `-` or `.` alone does not).\nconst NUMBER_PATTERN = '-?(?:\\\\d+\\\\.?\\\\d*|\\\\.\\\\d+)';\n\n// The number must not follow a letter, digit, `_`, `.` or `-`, so\n// `url(a5vh.png)`, `.a5vh{}` and `.hero-100vh{}` stay as they are: those\n// digits belong to a name. A real negative value (`margin-top: -10vh`) still\n// matches, since a space comes before its `-`. `--my-vh` never matches:\n// there's no number before `vh`.\nconst VIEWPORT_UNIT_RE = new RegExp(\n `(?<![\\\\w.-])(${NUMBER_PATTERN})(${UNITS_PATTERN})(?![a-zA-Z0-9_-])`,\n 'gi',\n);\n\n// Rewrites `vh`, `svh`, `lvh`, `dvh`, `vmin` and `vmax` to `cqh`, `cqmin` and\n// `cqmax` wherever they appear as a dimension, including inside `calc()` and\n// `var()` fallbacks. `vw` stays (see `UNIT_MAP`). A plain text replacement,\n// so a value in a CSS string such as `content: \"100vh\"` is rewritten too,\n// which doesn't affect layout.\nexport const convertViewportUnits = (css: string): string =>\n css.replace(\n VIEWPORT_UNIT_RE,\n (_match, number: string, unit: string) =>\n number + UNIT_MAP[unit.toLowerCase()],\n );\n\n// Rewrites viewport units in the two places `convertViewportUnits` doesn't\n// see: inline `style` attributes (which panel edits produce) and `<style>`\n// elements the preview renders itself. Without this, their `vh` would\n// resolve against the iframe's own height again (#132). Call it from\n// `updateHeight` after the container style is applied, before reading any\n// height.\n//\n// Idempotent: converted values no longer match the selectors, and a node is\n// written only when its text changes. A write would trigger the\n// MutationObserver in `iframe.tsx` again and loop.\nexport const rewriteInlineViewportUnits = (root: HTMLElement): void => {\n // `vh` as a substring already covers `svh`/`lvh`/`dvh`; `vmin`/`vmax` need\n // their own terms. Case-insensitive so `100VH` inline is caught too.\n const inlineTargets = root.querySelectorAll<HTMLElement>(\n '[style*=\"vh\" i], [style*=\"vmin\" i], [style*=\"vmax\" i]',\n );\n\n inlineTargets.forEach(el => {\n const current = el.getAttribute('style');\n\n if (current == null) {\n return;\n }\n\n const converted = convertViewportUnits(current);\n\n if (converted !== current) {\n el.setAttribute('style', converted);\n }\n });\n\n root.querySelectorAll<HTMLStyleElement>('style').forEach(styleEl => {\n const current = styleEl.textContent;\n\n if (!current) {\n return;\n }\n\n const converted = convertViewportUnits(current);\n\n if (converted !== current) {\n styleEl.textContent = converted;\n }\n });\n};\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { ReactNode } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport {\n useEventListener,\n useMutationObserver,\n useResizeObserver,\n} from '@jbpark/use-hooks';\n\nimport { withScriptBlobs } from '~/utils/scripts';\n\nimport {\n FALLBACK_PROBE_HEIGHT,\n computeProbeHeight,\n isAnimationActive,\n isVisuallyHidden,\n positionedElementBottom,\n verticalInsets,\n} from './measure';\nimport {\n createRootAttributeSync,\n createStyleSyncManager,\n reconcileRootAttributes,\n reconcileStyles,\n} from './style-sync';\nimport {\n convertViewportUnits,\n rewriteInlineViewportUnits,\n} from './viewport-units';\n\n// The style that makes `<html>` a size container, found again by this id.\n// Scoped to `html`, so it only affects how `cq*` units resolve.\nconst CONTAINER_STYLE_ID = 'autoheight-container';\n\nexport interface Props {\n title?: string;\n /** Forwarded to the iframe's `sandbox` attribute for DOM/CSS isolation only — not a security boundary, since preview code executes in the host window's realm (see `compileModule` in `~/utils`). */\n sandbox?: string;\n style?: React.CSSProperties;\n scripts?: string[];\n styles?: string[];\n stylesheets?: string[];\n autoHeight?: boolean;\n syncStyle?: boolean;\n children: (container: HTMLElement) => ReactNode;\n onLoaded?: () => void;\n}\n\nconst EMPTY_STRING_ARRAY: string[] = [];\n\n// `getAnimations()` mixes CSS animations, CSS transitions and script\n// animations (`element.animate()`). Only the first two fire a bubbling event\n// when they end, so they're told apart. Both constructors are checked first,\n// since jsdom has neither.\nconst isCssAnimation = (\n win: Window & typeof globalThis,\n animation: Animation,\n): boolean =>\n typeof win.CSSAnimation === 'function' &&\n animation instanceof win.CSSAnimation;\n\nconst isCssTransition = (\n win: Window & typeof globalThis,\n animation: Animation,\n): boolean =>\n typeof win.CSSTransition === 'function' &&\n animation instanceof win.CSSTransition;\n\n// Whether the element is animating, which tells a passing `opacity: 0` (the\n// start of a fade-in, so measure it) from a lasting one (a closed overlay, so\n// skip it). Transitions count too: a measurement pass doesn't always freeze\n// them, so a fade-in can read `opacity: 0` with a transition running. Without\n// `getAnimations()` (jsdom, old browsers) this is false, which under-measures\n// a fading-in overlay rather than counting a closed one.\nconst hasActiveAnimation = (el: HTMLElement): boolean =>\n typeof el.getAnimations === 'function' &&\n el.getAnimations().some(animation => isAnimationActive(animation.playState));\n\n// An animation that repeats forever never resolves `finished`, so it gets no\n// handler. It's always animating, so `hasActiveAnimation` keeps it measured\n// anyway.\nconst neverFinishes = (animation: Animation): boolean => {\n const timing = animation.effect?.getComputedTiming();\n\n return timing?.iterations === Infinity || timing?.duration === Infinity;\n};\n\n// A style that is off (`media=\"not all\"`) except while a measurement runs.\n// It guards against two things:\n//\n// - Transitions: a transition on what the measurement changes would animate\n// the new probe height, and the read would catch a value part-way there.\n// Only on a pass that changes the probe height (`freezeTransitions`).\n// - Scrollbars: a new probe height can show or hide a scrollbar for that\n// pass, which narrows the content where scrollbars take space (Windows)\n// and changes the height. Only the scrollbar is hidden; scrolling still\n// works.\n//\n// One element that is never added or removed, so toggling it doesn't trigger\n// the MutationObserver that watches the content.\nconst MEASUREMENT_OVERRIDE_STYLE_ID = 'autoheight-measurement-overrides';\n\nconst SCROLLBAR_OVERRIDE_RULES = [\n 'html, body { scrollbar-width: none !important; }',\n 'html::-webkit-scrollbar, body::-webkit-scrollbar { display: none !important; }',\n];\n\nconst FREEZE_TRANSITIONS_RULE =\n '*, *::before, *::after { transition: none !important; }';\n\n// Measures with the overrides above on. `freezeTransitions` is off unless\n// the pass changes the probe height: `transition: none` cancels a running\n// transition rather than pausing it, and the element jumps to its end state\n// for good. A pass that leaves the probe height alone changes nothing, so it\n// leaves the preview's transitions alone.\nconst withMeasurementOverrides = (\n doc: Document,\n freezeTransitions: boolean,\n measure: () => void,\n) => {\n let styleEl = doc.getElementById(\n MEASUREMENT_OVERRIDE_STYLE_ID,\n ) as HTMLStyleElement | null;\n\n if (!styleEl) {\n styleEl = doc.createElement('style');\n styleEl.id = MEASUREMENT_OVERRIDE_STYLE_ID;\n styleEl.media = 'not all';\n doc.head?.appendChild(styleEl);\n }\n\n const text = (\n freezeTransitions\n ? [FREEZE_TRANSITIONS_RULE, ...SCROLLBAR_OVERRIDE_RULES]\n : SCROLLBAR_OVERRIDE_RULES\n ).join('\\n');\n\n if (styleEl.textContent !== text) {\n styleEl.textContent = text;\n }\n\n styleEl.media = 'all';\n measure();\n styleEl.media = 'not all';\n};\n\nconst IFrame = ({\n title = 'Live Preview',\n sandbox,\n style = {},\n scripts = EMPTY_STRING_ARRAY,\n styles = EMPTY_STRING_ARRAY,\n stylesheets = EMPTY_STRING_ARRAY,\n autoHeight = false,\n syncStyle = false,\n children,\n onLoaded,\n ...props\n}: Props) => {\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const [mountNode, setMountNode] = useState<HTMLElement | null>(null);\n // The script srcs already added to this iframe's document, so a src added\n // to `scripts` later still loads.\n const loadedScriptsRef = useRef<Set<string>>(new Set());\n // The document those scripts went into. Moving the iframe, as reordering\n // canvas sections does, reloads it with a new document that has none\n // (#507).\n const loadedScriptsDocRef = useRef<Document | null>(null);\n const prevStyleCountRef = useRef(0);\n const prevStylesheetCountRef = useRef(0);\n // Animations that already have a re-measure handler, so a long one gets only\n // one. Weak, so it never keeps an animation or its element alive.\n const trackedAnimationsRef = useRef(new WeakSet<Animation>());\n // Lets those handlers call the current `updateHeight` without it depending\n // on itself.\n const updateHeightRef = useRef<(() => void) | null>(null);\n // The probe height the container style was last built for. A pass that\n // leaves it unchanged changes nothing, so it can measure without freezing\n // transitions.\n const lastProbeHeightRef = useRef<number | undefined>(undefined);\n const shouldAutoHeight = autoHeight && style.height == null;\n\n const styleManagerRef = useRef(createStyleSyncManager());\n const rootAttributeSyncRef = useRef(createRootAttributeSync());\n\n const applyStyle = useCallback(() => {\n const doc = iframeRef.current?.contentDocument;\n\n if (!doc) {\n return;\n }\n\n // The container style goes after every copied host style. Both use\n // `!important`, so a host `html { height: 100% !important }` copied in after\n // it would win and fold the frame to a pixel (#441).\n reconcileStyles(\n document,\n doc,\n styleManagerRef.current,\n syncStyle,\n convertViewportUnits,\n doc.getElementById(CONTAINER_STYLE_ID),\n );\n // The host's theme class or attribute, which the copied styles select on\n // (#497).\n reconcileRootAttributes(\n document.documentElement,\n doc.documentElement,\n rootAttributeSyncRef.current,\n syncStyle,\n );\n }, [syncStyle]);\n\n const applyStyleTimeoutRef = useRef<number>(undefined);\n\n // Debounced, since a stylesheet swap fires several head mutations in a\n // row.\n const debouncedApplyStyle = useCallback(() => {\n clearTimeout(applyStyleTimeoutRef.current);\n applyStyleTimeoutRef.current = window.setTimeout(applyStyle, 50);\n }, [applyStyle]);\n\n useEffect(() => {\n return () => clearTimeout(applyStyleTimeoutRef.current);\n }, []);\n\n useMutationObserver(document.head, debouncedApplyStyle, {\n enabled: syncStyle,\n childList: true,\n subtree: true,\n attributes: true,\n });\n\n // A theme switch only changes the host's `<html>` attributes, which the head\n // observer above doesn't see.\n useMutationObserver(document.documentElement, debouncedApplyStyle, {\n enabled: syncStyle,\n attributes: true,\n });\n\n useEffect(() => {\n const $iframe = iframeRef.current;\n\n if (!$iframe) {\n return;\n }\n\n const onLoad = () => {\n const doc = $iframe.contentDocument;\n\n if (!doc) {\n return;\n }\n\n if (loadedScriptsDocRef.current !== doc) {\n loadedScriptsDocRef.current = doc;\n loadedScriptsRef.current = new Set();\n }\n\n doc.body.style.overflowX = 'hidden';\n doc.body.style.margin = '0';\n\n let node = doc.getElementById('iframe-root');\n\n if (!node) {\n node = doc.createElement('div');\n node.id = 'iframe-root';\n doc.body.appendChild(node);\n }\n\n setMountNode(node);\n\n applyStyle();\n\n const pendingScripts = scripts.filter(\n src => !loadedScriptsRef.current.has(src),\n );\n\n if (pendingScripts.length) {\n pendingScripts.forEach(src => loadedScriptsRef.current.add(src));\n\n withScriptBlobs(pendingScripts, blobUrls => {\n if (!doc.head) {\n return;\n }\n\n const fragment = doc.createDocumentFragment();\n blobUrls.forEach(blobUrl => {\n const script = doc.createElement('script');\n script.src = blobUrl;\n fragment.appendChild(script);\n });\n doc.head.appendChild(fragment);\n });\n }\n\n onLoaded?.();\n };\n\n $iframe.addEventListener('load', onLoad);\n\n if ($iframe.contentDocument?.readyState === 'complete') {\n onLoad();\n }\n\n return () => {\n $iframe.removeEventListener('load', onLoad);\n };\n }, [scripts, onLoaded, applyStyle]);\n\n useEffect(() => {\n const doc = iframeRef.current?.contentDocument;\n\n if (!doc?.head) {\n return;\n }\n\n styles.forEach((css, index) => {\n const styleId = `injected-style-${index}`;\n let styleEl = doc.getElementById(styleId) as HTMLStyleElement | null;\n\n if (!styleEl) {\n styleEl = doc.createElement('style');\n styleEl.id = styleId;\n doc.head.appendChild(styleEl);\n }\n\n // The main source of `vh` units in a preview: compiled component CSS,\n // such as Tailwind's `h-screen`. See `ensureContainerStyle` for why they're\n // converted.\n const convertedCss = convertViewportUnits(css);\n\n if (styleEl.textContent !== convertedCss) {\n styleEl.textContent = convertedCss;\n }\n });\n\n // Remove what's left from a longer `styles` or `stylesheets` array.\n for (\n let index = styles.length;\n index < prevStyleCountRef.current;\n index++\n ) {\n doc.getElementById(`injected-style-${index}`)?.remove();\n }\n prevStyleCountRef.current = styles.length;\n\n stylesheets.forEach((href, index) => {\n const linkId = `injected-stylesheet-${index}`;\n let linkEl = doc.getElementById(linkId) as HTMLLinkElement | null;\n\n if (!linkEl) {\n linkEl = doc.createElement('link');\n linkEl.id = linkId;\n linkEl.rel = 'stylesheet';\n doc.head.appendChild(linkEl);\n }\n\n if (linkEl.href !== href) {\n linkEl.href = href;\n }\n });\n\n for (\n let index = stylesheets.length;\n index < prevStylesheetCountRef.current;\n index++\n ) {\n doc.getElementById(`injected-stylesheet-${index}`)?.remove();\n }\n prevStylesheetCountRef.current = stylesheets.length;\n }, [styles, stylesheets]);\n\n // Hides the iframe document's scrollbar while `autoHeight` sizes it.\n // Rounding can leave the document a fraction taller than the iframe, which\n // would draw a scrollbar in every section. Unlike the measurement override,\n // this stays on. Scrolling still works if the content ever outgrows it.\n const HIDE_SCROLLBAR_STYLE_ID = 'autoheight-hide-scrollbar';\n\n // Makes `<html>` a size container with a fixed height, `probeHeight`, the\n // scroll container's available height. Viewport units are rewritten to `cq*`\n // units (`convertViewportUnits`), so they resolve against this height\n // instead of the iframe's own. Against the iframe's own height, `100vh`\n // content would grow the iframe, which grows the content again, and never\n // settle (#132).\n const ensureContainerStyle = (doc: Document, probeHeight: number) => {\n let styleEl = doc.getElementById(\n CONTAINER_STYLE_ID,\n ) as HTMLStyleElement | null;\n\n if (!styleEl) {\n styleEl = doc.createElement('style');\n styleEl.id = CONTAINER_STYLE_ID;\n doc.head?.appendChild(styleEl);\n }\n\n const text = `html { container-type: size !important; height: ${probeHeight}px !important; }`;\n\n // Written only when it differs, so a pass with the same probe height\n // changes nothing in the document (see `freezeTransitions`).\n if (styleEl.textContent !== text) {\n styleEl.textContent = text;\n }\n };\n\n // Script animations fire no event when they end, so each gets one\n // re-measure when its `finished` promise settles. CSS animations and\n // transitions are skipped: their end events already bubble to the mount node.\n // A cancelled animation rejects `finished` and snaps the element back, which\n // also changes the height, so both outcomes re-measure.\n const trackScriptAnimations = useCallback(\n (doc: Document, win: Window & typeof globalThis) => {\n if (typeof doc.getAnimations !== 'function') {\n return;\n }\n\n doc.getAnimations().forEach(animation => {\n if (\n trackedAnimationsRef.current.has(animation) ||\n !isAnimationActive(animation.playState) ||\n isCssAnimation(win, animation) ||\n isCssTransition(win, animation) ||\n neverFinishes(animation)\n ) {\n return;\n }\n\n trackedAnimationsRef.current.add(animation);\n\n animation.finished\n .catch(() => undefined)\n .then(() => updateHeightRef.current?.());\n });\n },\n [],\n );\n\n // There is no \"skip when `scrollHeight` and the probe height are unchanged\"\n // check, though setting the iframe's height can trigger the ResizeObserver\n // again. Opening or closing a fixed or absolute overlay often leaves\n // `scrollHeight` unchanged, so such a check would skip exactly the updates\n // the full-subtree walk is for.\n const updateHeight = useCallback(() => {\n if (!shouldAutoHeight || !mountNode || !iframeRef.current) {\n return;\n }\n\n const iframe = iframeRef.current;\n const doc = iframe.contentDocument;\n const win = doc?.defaultView;\n\n if (!doc || !win) {\n return;\n }\n\n const scrollParent = iframe.closest<HTMLElement>('[data-frame-container]');\n\n let probeHeight: number;\n\n if (!scrollParent) {\n // No scroll container (`Frame` used without `Live.Dnd`): use a fixed\n // default. See `FALLBACK_PROBE_HEIGHT`.\n probeHeight = FALLBACK_PROBE_HEIGHT;\n } else {\n // From the iframe up to the scroll container: the iframe's and each\n // wrapper's margin, border and padding take space, and the scroll container\n // adds only its padding, since `clientHeight` leaves out its border and\n // margin (#440).\n const scrollParentStyle = win.getComputedStyle(scrollParent);\n let wrapperInsets =\n (parseFloat(scrollParentStyle.paddingTop) || 0) +\n (parseFloat(scrollParentStyle.paddingBottom) || 0);\n let node: HTMLElement | null = iframe;\n\n while (node && node !== scrollParent) {\n wrapperInsets += verticalInsets(win.getComputedStyle(node));\n node = node.parentElement;\n }\n\n const computed = computeProbeHeight(\n scrollParent.clientHeight,\n wrapperInsets,\n );\n\n if (computed === null) {\n // Layout isn't ready yet: skip this pass. The observers call this again\n // once it settles.\n return;\n }\n\n probeHeight = computed;\n }\n\n let contentHeight = 0;\n\n // Only the first pass and a pass that moves the probe height change the\n // container, so only they freeze transitions.\n const freezeTransitions = probeHeight !== lastProbeHeightRef.current;\n\n lastProbeHeightRef.current = probeHeight;\n\n // Sizes the iframe's viewport to the probe height for the reads below, so\n // a fixed element's percentage `height` or `top` resolves against what the\n // section shows, not against the iframe's current height, which is itself\n // what is being measured (#565). The final height replaces it before the\n // next paint.\n const previousHeight = iframe.style.height;\n\n iframe.style.height = `${probeHeight}px`;\n\n withMeasurementOverrides(doc, freezeTransitions, () => {\n ensureContainerStyle(doc, probeHeight);\n\n // Rewrite viewport units in inline `style` attributes and in-preview\n // `<style>` tags, which the container style can't reach, so they resolve\n // against the probe height too. After `ensureContainerStyle` and before the\n // reads below. It's idempotent, so the observer pass its own rewrites trigger\n // changes nothing.\n rewriteInlineViewportUnits(mountNode);\n\n // No need to fold the iframe to 0px first: `cq*` content is sized against\n // the fixed probe height, so a direct read is stable (#132).\n contentHeight = mountNode.scrollHeight;\n\n // Every descendant, so an overlay nested deep in the tree counts too.\n const descendants = mountNode.querySelectorAll<HTMLElement>('*');\n\n descendants.forEach(el => {\n const style = win.getComputedStyle(el);\n\n // `visibility: hidden` and `opacity: 0` elements, such as a closed bottom\n // sheet, still have an `offsetHeight`, so they're skipped here\n // (`display: none` already reads 0). Animations are checked only for a fully\n // transparent element, to tell a fade-in apart from a hidden one.\n const isAnimating = style.opacity === '0' && hasActiveAnimation(el);\n\n if (isVisuallyHidden(style, isAnimating)) {\n return;\n }\n\n if (\n (style.position === 'fixed' || style.position === 'absolute') &&\n el.offsetHeight > 0\n ) {\n const rect = el.getBoundingClientRect();\n const bottom = positionedElementBottom(\n rect.top,\n rect.bottom,\n probeHeight,\n );\n\n if (bottom !== null) {\n contentHeight = Math.max(contentHeight, bottom);\n }\n }\n });\n });\n\n iframe.style.height =\n contentHeight > 0 ? `${Math.ceil(contentHeight)}px` : previousHeight;\n\n // After the measurement window, which can cancel transitions, so this sees\n // the document's real animations.\n trackScriptAnimations(doc, win);\n }, [shouldAutoHeight, mountNode, trackScriptAnimations]);\n\n useEffect(() => {\n updateHeightRef.current = updateHeight;\n }, [updateHeight]);\n\n // Removes the container style when `autoHeight` turns off or a height is\n // given, so `cq*` content goes back to sizing against the viewport.\n useEffect(() => {\n if (shouldAutoHeight) {\n return;\n }\n\n iframeRef.current?.contentDocument\n ?.getElementById(CONTAINER_STYLE_ID)\n ?.remove();\n }, [shouldAutoHeight]);\n\n // A fixed-height iframe scrolls its own document. A copied host\n // `body { overflow: hidden }` would stop that, so an inline value overrides\n // it. With `autoHeight` there's nothing to scroll, so the body is left\n // alone.\n useEffect(() => {\n const body = iframeRef.current?.contentDocument?.body;\n\n if (!body || !mountNode) {\n return;\n }\n\n if (shouldAutoHeight) {\n body.style.removeProperty('overflow-y');\n } else {\n body.style.setProperty('overflow-y', 'auto');\n }\n }, [shouldAutoHeight, mountNode]);\n\n // Depends on `mountNode` so it runs again once the iframe's document\n // exists.\n useEffect(() => {\n const doc = iframeRef.current?.contentDocument;\n\n if (!doc?.head) {\n return;\n }\n\n const existing = doc.getElementById(HIDE_SCROLLBAR_STYLE_ID);\n\n if (!shouldAutoHeight) {\n existing?.remove();\n return;\n }\n\n if (existing) {\n return;\n }\n\n const styleEl = doc.createElement('style');\n styleEl.id = HIDE_SCROLLBAR_STYLE_ID;\n styleEl.textContent = [\n 'html, body { scrollbar-width: none !important; }',\n 'html::-webkit-scrollbar, body::-webkit-scrollbar { display: none !important; }',\n ].join('\\n');\n doc.head.appendChild(styleEl);\n }, [shouldAutoHeight, mountNode]);\n\n useEffect(() => {\n updateHeight();\n }, [updateHeight]);\n\n const [resizeRef, resizeSize] = useResizeObserver<HTMLElement>();\n\n // Attached by hand, since `mountNode` is created by the portal, not\n // rendered here. Only used as a trigger: `updateHeight`'s own walk measures\n // more accurately than the mount node's size.\n useEffect(() => {\n if (!shouldAutoHeight || !mountNode) {\n return;\n }\n\n resizeRef(mountNode);\n return () => resizeRef(null);\n }, [shouldAutoHeight, mountNode, resizeRef]);\n\n useEffect(() => {\n updateHeight();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [resizeSize]);\n\n useMutationObserver(mountNode, updateHeight, {\n enabled: shouldAutoHeight,\n childList: true,\n subtree: true,\n attributes: true,\n characterData: true,\n });\n\n // Re-measure when an animation or transition ends or is cancelled, which\n // neither observer sees. A fixed or absolute element read part-way through a\n // fade would otherwise keep its height until something else changed (#374).\n // All four events bubble, so one listener each on the mount node covers\n // every descendant.\n //\n // The mount node is wrapped in a ref that changes only with the node, and\n // `enabled` waits until it exists.\n const mountNodeRef = useMemo(() => ({ current: mountNode }), [mountNode]);\n const settleListenerEnabled = shouldAutoHeight && mountNode !== null;\n\n useEventListener('animationend', updateHeight, {\n target: mountNodeRef,\n enabled: settleListenerEnabled,\n });\n\n useEventListener('animationcancel', updateHeight, {\n target: mountNodeRef,\n enabled: settleListenerEnabled,\n });\n\n useEventListener('transitionend', updateHeight, {\n target: mountNodeRef,\n enabled: settleListenerEnabled,\n });\n\n useEventListener('transitioncancel', updateHeight, {\n target: mountNodeRef,\n enabled: settleListenerEnabled,\n });\n\n const content = mountNode\n ? createPortal(children(mountNode), mountNode)\n : null;\n\n return (\n <iframe\n ref={iframeRef}\n style={{\n // An iframe is inline by default and leaves a gap below it for text\n // descenders, which added up across canvas sections (#439).\n display: 'block',\n width: '100%',\n height: '100%',\n border: 'none',\n ...style,\n }}\n title={title}\n sandbox={sandbox}\n {...props}\n >\n {content}\n </iframe>\n );\n};\n\nexport default IFrame;\n","import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\nimport type { ReactNode } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { useMutationObserver } from '@jbpark/use-hooks';\n\nimport { createStyleSyncManager, reconcileStyles } from './style-sync';\n\ninterface Props {\n // Copies the host page's stylesheets and `<style>` tags into the shadow\n // root, like `iframe.tsx`'s option of the same name. This brings the host's\n // compiled CSS, its own utilities and theme included. `dynamicTailwind`\n // covers what the host's build never saw, such as a class typed at runtime.\n syncStyle?: boolean;\n // Receives the overlay layer, the `container` to portal a modal or drawer\n // into so it opens inside the preview.\n children: (overlayLayer: HTMLElement | null) => ReactNode;\n}\n\nconst OVERLAY_LAYER_ATTR = 'data-live-editor-overlay-layer';\n\n// The layer lets clicks through to the preview under it. What is portaled\n// into it takes them again.\nconst OVERLAY_LAYER_STYLE = `[${OVERLAY_LAYER_ATTR}] > * { pointer-events: auto; }`;\n\n// The render target and the overlay layer in one grid cell, so the layer\n// covers exactly the preview's box. `min-height: 100%` stretches that box to\n// a parent with a set height, such as `Live.Preview`'s, so an overlay isn't\n// squeezed into short content. The wrapper isn't positioned, so it doesn't\n// change what an `absolute` element in the preview is placed against.\n// `isolation` keeps the layer's stacking inside the preview.\nconst createFrameNodes = () => {\n const wrapper = document.createElement('div');\n\n wrapper.style.display = 'grid';\n wrapper.style.gridTemplateColumns = 'minmax(0, 1fr)';\n wrapper.style.minHeight = '100%';\n wrapper.style.isolation = 'isolate';\n\n const renderTarget = document.createElement('div');\n\n renderTarget.style.gridArea = '1 / 1';\n\n // `contain: layout` makes the layer the containing block of the fixed\n // elements inside it, so an overlay covers the preview and not the page.\n const overlayLayer = document.createElement('div');\n\n overlayLayer.setAttribute(OVERLAY_LAYER_ATTR, '');\n overlayLayer.style.gridArea = '1 / 1';\n overlayLayer.style.zIndex = '1';\n overlayLayer.style.contain = 'layout';\n overlayLayer.style.pointerEvents = 'none';\n\n const style = document.createElement('style');\n\n style.textContent = OVERLAY_LAYER_STYLE;\n wrapper.append(style, renderTarget, overlayLayer);\n\n return { wrapper, renderTarget };\n};\n\n// The overlay layer `createFrameNodes` put next to `renderTarget`.\nconst overlayLayerOf = (renderTarget: HTMLElement) => {\n const layer = renderTarget.nextElementSibling;\n\n return layer instanceof HTMLElement && layer.hasAttribute(OVERLAY_LAYER_ATTR)\n ? layer\n : null;\n};\n\nconst Shadow = ({ syncStyle = false, children }: Props) => {\n const hostRef = useRef<HTMLDivElement>(null);\n const shadowRootRef = useRef<ShadowRoot | null>(null);\n const renderTargetRef = useRef<HTMLDivElement | null>(null);\n const [renderTarget, setRenderTarget] = useState<HTMLDivElement | null>(null);\n\n // Added next to the portal target, not inside it: React owns that subtree\n // and would remove anything added there.\n const styleManagerRef = useRef(createStyleSyncManager());\n\n const applyStyle = useCallback(() => {\n const shadowRoot = shadowRootRef.current;\n\n if (!shadowRoot) {\n return;\n }\n\n reconcileStyles(document, shadowRoot, styleManagerRef.current, syncStyle);\n }, [syncStyle]);\n\n const applyStyleTimeoutRef = useRef<number>(undefined);\n\n // Debounced, since a stylesheet swap fires several head mutations in a\n // row, as in `iframe.tsx`.\n const debouncedApplyStyle = useCallback(() => {\n clearTimeout(applyStyleTimeoutRef.current);\n applyStyleTimeoutRef.current = window.setTimeout(applyStyle, 50);\n }, [applyStyle]);\n\n useEffect(() => {\n return () => clearTimeout(applyStyleTimeoutRef.current);\n }, []);\n\n useMutationObserver(document.head, debouncedApplyStyle, {\n enabled: syncStyle,\n childList: true,\n subtree: true,\n attributes: true,\n });\n\n useLayoutEffect(() => {\n if (!hostRef.current) {\n return;\n }\n\n let shadowRoot = shadowRootRef.current;\n\n if (!shadowRoot) {\n shadowRoot =\n hostRef.current.shadowRoot ||\n hostRef.current.attachShadow({ mode: 'open' });\n shadowRootRef.current = shadowRoot;\n }\n\n let target = renderTargetRef.current;\n\n if (!target) {\n const nodes = createFrameNodes();\n\n shadowRoot.appendChild(nodes.wrapper);\n target = nodes.renderTarget;\n renderTargetRef.current = target;\n setRenderTarget(target);\n }\n\n applyStyle();\n // `click`, `pointerdown` and `pointerup` already cross the shadow boundary\n // (`composed: true`), so they aren't dispatched again here, which made\n // listeners outside see them twice (#92). `event.composedPath()[0]` gives\n // the element inside.\n }, [applyStyle]);\n\n useLayoutEffect(() => {\n if (renderTargetRef.current && !renderTarget) {\n setRenderTarget(renderTargetRef.current);\n }\n }, [renderTarget]);\n\n return (\n <div ref={hostRef} style={{ display: 'contents' }}>\n {renderTarget &&\n createPortal(children(overlayLayerOf(renderTarget)), renderTarget)}\n </div>\n );\n};\n\nexport default Shadow;\n","import { type ReactNode } from 'react';\n\nimport IFrame, { type Props as IframeProps } from './iframe';\nimport Shadow from './shadow';\n\nexport interface FrameProps extends Omit<IframeProps, 'children'> {\n mode?: 'iframe' | 'shadow';\n}\n\ninterface Props extends FrameProps {\n children: (container: HTMLElement) => ReactNode;\n}\n\nconst Frame = ({ mode, children, ...restProps }: Props) => {\n if (!mode) {\n return children(document.body);\n }\n\n if (mode === 'shadow') {\n return (\n <Shadow syncStyle={restProps.syncStyle}>\n {container => children(container || document.body)}\n </Shadow>\n );\n }\n\n return <IFrame {...restProps}>{children}</IFrame>;\n};\n\nexport default Frame;\n","import * as ui from '@jbpark/ui-kit';\nimport * as utils from '@jbpark/ui-kit/utils';\n\n// What every preview can import without the host passing it\n// (`import * as ui from 'ui-kit'`). Kept here, not in `~/utils`, because\n// loading ui-kit reaches its stylesheets, which would make `./utils`\n// unloadable in Node (#372).\nexport const baseModules = {\n 'ui-kit': ui,\n 'ui-kit/utils': utils,\n};\n","import { useMemo } from 'react';\n\nimport { useLiveMessages } from '~/components/context/messages';\nimport type { Module } from '~/types';\nimport { compile } from '~/utils/compile';\n\nimport { baseModules } from './base-modules';\nimport { useStableModules } from './use-stable-modules';\n\n// Compiles code into a component, for `Live.Preview` and each canvas\n// section, so both handle errors the same way (#246). `null` for empty code,\n// so a caller can tell \"nothing to render\" from a failed compile, which\n// comes back as a module with `error`.\nexport const useCompiledModule = (\n code: string,\n _modules?: Record<string, unknown>,\n): Module | null => {\n // An inline `modules` object from `Live.Preview`'s host is new each\n // render; only a changed entry should recompile (#397).\n const modules = useStableModules(_modules);\n const { unknown } = useLiveMessages().errors;\n\n const mergedModules = useMemo(\n () => ({ ...baseModules, ...modules }),\n [modules],\n );\n\n return useMemo(() => {\n if (!code) {\n return null;\n }\n\n try {\n return compile(code, mergedModules);\n } catch (e) {\n return {\n exports: {},\n error: e instanceof Error ? e.message : unknown,\n };\n }\n }, [code, mergedModules, unknown]);\n};\n","import { useCallback, useEffect, useState } from 'react';\n\n// Compiles the Tailwind classes in the rendered DOM into CSS for a `<style>`\n// tag, for `Live.Preview` and each canvas section. Reading the DOM, not the\n// source, finds the classes imported components add too.\n//\n// The element is held in state through a callback ref: in shadow mode it\n// appears a commit later, and an effect reading a plain ref would miss it.\n// The compiler and theme load on first use, since they're large (#332).\nexport const useDynamicTailwind = (code: string, enabled: boolean) => {\n const [css, setCss] = useState('');\n const [element, setElement] = useState<HTMLDivElement | null>(null);\n\n const ref = useCallback((node: HTMLDivElement | null) => {\n setElement(node);\n }, []);\n\n useEffect(() => {\n if (!code || !enabled || !element) {\n return;\n }\n\n let cancelled = false;\n\n import('~/utils/tailwind')\n .then(({ generateTailwindCSSFromDOM }) =>\n generateTailwindCSSFromDOM(element),\n )\n .then(next => {\n if (!cancelled) {\n setCss(next);\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [code, enabled, element]);\n\n return { ref, css };\n};\n"],"mappings":";;;;;;;;;AAOA,MAAM,eAAe,GAAY,MAAwB;CACvD,IAAI,MAAM,GACR,OAAO;CAGT,IAAI,CAAC,KAAK,CAAC,GACT,OAAO;CAGT,MAAM,OAAO,OAAO,KAAK,CAAC;CAE1B,OACE,KAAK,WAAW,OAAO,KAAK,CAAC,CAAC,CAAC,UAC/B,KAAK,OAAM,QAAO,OAAO,OAAO,GAAG,GAAG,KAAK,OAAO,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC;AAExE;AAKA,MAAa,oBAAuC,YAAkB;CACpE,MAAM,CAAC,QAAQ,aAAa,SAAS,OAAO;CAE5C,IAAI,YAAY,QAAQ,OAAO,GAC7B,OAAO;CAKT,UAAU,OAAO;CAEjB,OAAO;AACT;;;ACzBA,MAAa,kBACX,UAUA;CACE,MAAM;CACN,MAAM;CACN,MAAM;CACN,MAAM;CACN,MAAM;CACN,MAAM;AACR,CAAC,CAAC,QAAQ,KAAK,UAAU,OAAO,WAAW,KAAK,KAAK,IAAI,CAAC;AAO5D,MAAa,sBACX,6BACA,kBACkB;CAClB,MAAM,SAAS,8BAA8B;CAE7C,OAAO,SAAS,IAAI,SAAS;AAC/B;AAOA,MAAa,oBACX,UAIA,cAAc,UAEd,SAAS,eAAe,YACvB,SAAS,YAAY,OAAO,CAAC;AAMhC,MAAa,qBAAqB,cAChC,cAAc,aAAa,cAAc;AAO3C,MAAa,2BACX,KACA,QACA,gBACkB;CAClB,IAAI,UAAU,KAAK,OAAO,aACxB,OAAO;CAGT,OAAO,KAAK,IAAI,QAAQ,WAAW;AACrC;;;ACrFA,MAAM,oBAAoB;AAS1B,MAAa,gCAAkD,EAC7D,wBAAQ,IAAI,IAAI,EAClB;AAEA,MAAM,cAAc,WAClB,OAAO,aAAa,KAAK;AAE3B,MAAM,gBAAgB,aACpB,MAAM,KACJ,SAAS,KAAK,iBACZ,iCACF,CACF;AAEF,MAAM,kBACJ,QACA,OACA,mBACG;CACH,MAAM,KAAK,MAAM,UAAU,CAAC,CAAC,SAAQ,cAAa;EAChD,IACE,UAAU,SAAS,qBACnB,CAAC,OAAO,aAAa,UAAU,IAAI,GAEnC,MAAM,gBAAgB,UAAU,IAAI;CAExC,CAAC;CAED,MAAM,KAAK,OAAO,UAAU,CAAC,CAAC,SAAQ,cAAa;EACjD,MAAM,aAAa,UAAU,MAAM,UAAU,KAAK;CACpD,CAAC;CAED,IAAI,OAAO,YAAY,UAAU,MAAM,YAAY,QACjD,MAA2B,WAAY,OAA2B;CAGpE,MAAM,cACJ,OAAO,YAAY,UACf,eAAe,OAAO,eAAe,EAAE,IACvC,OAAO;AACf;AAEA,MAAM,eACJ,QACA,QACA,mBACgB;CAEhB,MAAM,SADgB,WAAW,MAAM,IAAI,SAAS,OAAO,cAAA,CAC/B,cAC1B,OAAO,QAAQ,YAAY,CAC7B;CAEA,MAAM,aAAa,mBAAmB,EAAE;CACxC,eAAe,QAAQ,OAAO,cAAc;CAE5C,OAAO;AACT;AAEA,MAAM,mBAAmB,WACvB,WAAW,MAAM,IAAI,OAAO,OAAO;AAErC,MAAM,iBAAiB,SAAoC;CACzD,MAAM,UAAU;CAEhB,QACG,QAAQ,YAAY,UAAU,QAAQ,YAAY,YACnD,QAAQ,aAAa,iBAAiB;AAE1C;AAEA,MAAM,eAAe,UAAuB;CAC1C,MAAM,OAAO;AACf;AAMA,MAAa,mBACX,gBACA,QACA,SACA,SACA,kBAA8C,YAAW,SACzD,SAAsB,SACnB;CACH,IAAI,CAAC,SAAS;EACZ,QAAQ,OAAO,QAAQ,WAAW;EAClC,QAAQ,OAAO,MAAM;EAErB;CACF;CAEA,MAAM,UAAU,aAAa,cAAc;CAC3C,MAAM,YAAY,IAAI,IAAI,OAAO;CACjC,MAAM,YAAY,gBAAgB,MAAM;CAExC,QAAQ,OAAO,SAAS,OAAO,WAAW;EACxC,IAAI,CAAC,UAAU,IAAI,MAAM,GAAG;GAC1B,YAAY,KAAK;GACjB,QAAQ,OAAO,OAAO,MAAM;EAC9B;CACF,CAAC;CAED,IAAI,WAA+B;CAEnC,QAAQ,SAAQ,WAAU;EACxB,IAAI,QAAQ,QAAQ,OAAO,IAAI,MAAM;EAErC,IAAI,CAAC,OAAO;GACV,QAAQ,YAAY,QAAQ,QAAQ,cAAc;GAClD,QAAQ,OAAO,IAAI,QAAQ,KAAK;EAClC,OACE,eAAe,QAAQ,OAAO,cAAc;EAG9C,MAAM,cAAc,WAChB,SAAS,cACR,MAAM,KAAK,UAAU,UAAU,CAAC,CAAC,KAAK,aAAa,MACnD,QAAQ,eAAe,YAAY,SAAS;EAEjD,IAAI,UAAU,aACZ,UAAU,aAAa,OAAO,WAAW;EAG3C,WAAW;CACb,CAAC;AACH;AASA,MAAa,iCAAoD;CAC/D,4BAAY,IAAI,IAAI;CACpB,yBAAS,IAAI,IAAI;AACnB;AAEA,MAAM,uBAAuB,SAAiB,KAAK,WAAW,OAAO;AAYrE,MAAa,2BACX,QACA,QACA,MACA,YACG;CACH,MAAM,aAAa,UACf,MAAM,KAAK,OAAO,UAAU,CAAC,CAAC,QAAQ,EAAE,WACtC,oBAAoB,IAAI,CAC1B,IACA,CAAC;CACL,MAAM,UAAU,UAAU,MAAM,KAAK,OAAO,SAAS,IAAI,CAAC;CAC1D,MAAM,iBAAiB,IAAI,IAAI,WAAW,KAAK,EAAE,WAAW,IAAI,CAAC;CACjE,MAAM,aAAa,IAAI,IAAI,OAAO;CAElC,KAAK,WAAW,SAAQ,SAAQ;EAC9B,IAAI,CAAC,eAAe,IAAI,IAAI,GAC1B,OAAO,gBAAgB,IAAI;CAE/B,CAAC;CACD,WAAW,SAAS,EAAE,MAAM,YAAY;EACtC,IAAI,OAAO,aAAa,IAAI,MAAM,OAChC,OAAO,aAAa,MAAM,KAAK;CAEnC,CAAC;CAED,KAAK,QAAQ,SAAQ,SAAQ;EAC3B,IAAI,CAAC,WAAW,IAAI,IAAI,GACtB,OAAO,UAAU,OAAO,IAAI;CAEhC,CAAC;CACD,QAAQ,SAAQ,SAAQ,OAAO,UAAU,IAAI,IAAI,CAAC;CAElD,IAAI,CAAC,OAAO,UAAU,QACpB,OAAO,gBAAgB,OAAO;CAGhC,KAAK,aAAa;CAClB,KAAK,UAAU;AACjB;;;ACnMA,MAAM,WAAmC;CACvC,IAAI;CACJ,KAAK;CACL,KAAK;CACL,KAAK;CACL,MAAM;CACN,MAAM;AACR;AAIA,MAAM,gBAAgB,OAAO,KAAK,QAAQ,CAAC,CACxC,MAAM,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,CACnC,KAAK,GAAG;AAYX,MAAM,mBAAmB,IAAI,OAC3B,4CAAmC,cAAc,qBACjD,IACF;AAOA,MAAa,wBAAwB,QACnC,IAAI,QACF,mBACC,QAAQ,QAAgB,SACvB,SAAS,SAAS,KAAK,YAAY,EACvC;AAYF,MAAa,8BAA8B,SAA4B;CAOrE,KAJ2B,iBACzB,6DAGU,CAAC,CAAC,SAAQ,OAAM;EAC1B,MAAM,UAAU,GAAG,aAAa,OAAO;EAEvC,IAAI,WAAW,MACb;EAGF,MAAM,YAAY,qBAAqB,OAAO;EAE9C,IAAI,cAAc,SAChB,GAAG,aAAa,SAAS,SAAS;CAEtC,CAAC;CAED,KAAK,iBAAmC,OAAO,CAAC,CAAC,SAAQ,YAAW;EAClE,MAAM,UAAU,QAAQ;EAExB,IAAI,CAAC,SACH;EAGF,MAAM,YAAY,qBAAqB,OAAO;EAE9C,IAAI,cAAc,SAChB,QAAQ,cAAc;CAE1B,CAAC;AACH;;;AC3DA,MAAM,qBAAqB;AAgB3B,MAAM,qBAA+B,CAAC;AAMtC,MAAM,kBACJ,KACA,cAEA,OAAO,IAAI,iBAAiB,cAC5B,qBAAqB,IAAI;AAE3B,MAAM,mBACJ,KACA,cAEA,OAAO,IAAI,kBAAkB,cAC7B,qBAAqB,IAAI;AAQ3B,MAAM,sBAAsB,OAC1B,OAAO,GAAG,kBAAkB,cAC5B,GAAG,cAAc,CAAC,CAAC,MAAK,cAAa,kBAAkB,UAAU,SAAS,CAAC;AAK7E,MAAM,iBAAiB,cAAkC;CACvD,MAAM,SAAS,UAAU,QAAQ,kBAAkB;CAEnD,OAAO,QAAQ,eAAe,YAAY,QAAQ,aAAa;AACjE;AAeA,MAAM,gCAAgC;AAEtC,MAAM,2BAA2B,CAC/B,oDACA,gFACF;AAEA,MAAM,0BACJ;AAOF,MAAM,4BACJ,KACA,mBACA,YACG;CACH,IAAI,UAAU,IAAI,eAChB,6BACF;CAEA,IAAI,CAAC,SAAS;EACZ,UAAU,IAAI,cAAc,OAAO;EACnC,QAAQ,KAAK;EACb,QAAQ,QAAQ;EAChB,IAAI,MAAM,YAAY,OAAO;CAC/B;CAEA,MAAM,QACJ,oBACI,CAAC,yBAAyB,GAAG,wBAAwB,IACrD,yBAAA,CACJ,KAAK,IAAI;CAEX,IAAI,QAAQ,gBAAgB,MAC1B,QAAQ,cAAc;CAGxB,QAAQ,QAAQ;CAChB,QAAQ;CACR,QAAQ,QAAQ;AAClB;AAEA,MAAM,UAAU,EACd,QAAQ,gBACR,SACA,QAAQ,CAAC,GACT,UAAU,oBACV,SAAS,oBACT,cAAc,oBACd,aAAa,OACb,YAAY,OACZ,UACA,UACA,GAAG,YACQ;CACX,MAAM,YAAY,OAA0B,IAAI;CAChD,MAAM,CAAC,WAAW,gBAAgB,SAA6B,IAAI;CAGnE,MAAM,mBAAmB,uBAAoB,IAAI,IAAI,CAAC;CAItD,MAAM,sBAAsB,OAAwB,IAAI;CACxD,MAAM,oBAAoB,OAAO,CAAC;CAClC,MAAM,yBAAyB,OAAO,CAAC;CAGvC,MAAM,uBAAuB,uBAAO,IAAI,QAAmB,CAAC;CAG5D,MAAM,kBAAkB,OAA4B,IAAI;CAIxD,MAAM,qBAAqB,OAA2B,KAAA,CAAS;CAC/D,MAAM,mBAAmB,cAAc,MAAM,UAAU;CAEvD,MAAM,kBAAkB,OAAO,uBAAuB,CAAC;CACvD,MAAM,uBAAuB,OAAO,wBAAwB,CAAC;CAE7D,MAAM,aAAa,kBAAkB;EACnC,MAAM,MAAM,UAAU,SAAS;EAE/B,IAAI,CAAC,KACH;EAMF,gBACE,UACA,KACA,gBAAgB,SAChB,WACA,sBACA,IAAI,eAAe,kBAAkB,CACvC;EAGA,wBACE,SAAS,iBACT,IAAI,iBACJ,qBAAqB,SACrB,SACF;CACF,GAAG,CAAC,SAAS,CAAC;CAEd,MAAM,uBAAuB,OAAe,KAAA,CAAS;CAIrD,MAAM,sBAAsB,kBAAkB;EAC5C,aAAa,qBAAqB,OAAO;EACzC,qBAAqB,UAAU,OAAO,WAAW,YAAY,EAAE;CACjE,GAAG,CAAC,UAAU,CAAC;CAEf,gBAAgB;EACd,aAAa,aAAa,qBAAqB,OAAO;CACxD,GAAG,CAAC,CAAC;CAEL,oBAAoB,SAAS,MAAM,qBAAqB;EACtD,SAAS;EACT,WAAW;EACX,SAAS;EACT,YAAY;CACd,CAAC;CAID,oBAAoB,SAAS,iBAAiB,qBAAqB;EACjE,SAAS;EACT,YAAY;CACd,CAAC;CAED,gBAAgB;EACd,MAAM,UAAU,UAAU;EAE1B,IAAI,CAAC,SACH;EAGF,MAAM,eAAe;GACnB,MAAM,MAAM,QAAQ;GAEpB,IAAI,CAAC,KACH;GAGF,IAAI,oBAAoB,YAAY,KAAK;IACvC,oBAAoB,UAAU;IAC9B,iBAAiB,0BAAU,IAAI,IAAI;GACrC;GAEA,IAAI,KAAK,MAAM,YAAY;GAC3B,IAAI,KAAK,MAAM,SAAS;GAExB,IAAI,OAAO,IAAI,eAAe,aAAa;GAE3C,IAAI,CAAC,MAAM;IACT,OAAO,IAAI,cAAc,KAAK;IAC9B,KAAK,KAAK;IACV,IAAI,KAAK,YAAY,IAAI;GAC3B;GAEA,aAAa,IAAI;GAEjB,WAAW;GAEX,MAAM,iBAAiB,QAAQ,QAC7B,QAAO,CAAC,iBAAiB,QAAQ,IAAI,GAAG,CAC1C;GAEA,IAAI,eAAe,QAAQ;IACzB,eAAe,SAAQ,QAAO,iBAAiB,QAAQ,IAAI,GAAG,CAAC;IAE/D,gBAAgB,iBAAgB,aAAY;KAC1C,IAAI,CAAC,IAAI,MACP;KAGF,MAAM,WAAW,IAAI,uBAAuB;KAC5C,SAAS,SAAQ,YAAW;MAC1B,MAAM,SAAS,IAAI,cAAc,QAAQ;MACzC,OAAO,MAAM;MACb,SAAS,YAAY,MAAM;KAC7B,CAAC;KACD,IAAI,KAAK,YAAY,QAAQ;IAC/B,CAAC;GACH;GAEA,WAAW;EACb;EAEA,QAAQ,iBAAiB,QAAQ,MAAM;EAEvC,IAAI,QAAQ,iBAAiB,eAAe,YAC1C,OAAO;EAGT,aAAa;GACX,QAAQ,oBAAoB,QAAQ,MAAM;EAC5C;CACF,GAAG;EAAC;EAAS;EAAU;CAAU,CAAC;CAElC,gBAAgB;EACd,MAAM,MAAM,UAAU,SAAS;EAE/B,IAAI,CAAC,KAAK,MACR;EAGF,OAAO,SAAS,KAAK,UAAU;GAC7B,MAAM,UAAU,kBAAkB;GAClC,IAAI,UAAU,IAAI,eAAe,OAAO;GAExC,IAAI,CAAC,SAAS;IACZ,UAAU,IAAI,cAAc,OAAO;IACnC,QAAQ,KAAK;IACb,IAAI,KAAK,YAAY,OAAO;GAC9B;GAKA,MAAM,eAAe,qBAAqB,GAAG;GAE7C,IAAI,QAAQ,gBAAgB,cAC1B,QAAQ,cAAc;EAE1B,CAAC;EAGD,KACE,IAAI,QAAQ,OAAO,QACnB,QAAQ,kBAAkB,SAC1B,SAEA,IAAI,eAAe,kBAAkB,OAAO,CAAC,EAAE,OAAO;EAExD,kBAAkB,UAAU,OAAO;EAEnC,YAAY,SAAS,MAAM,UAAU;GACnC,MAAM,SAAS,uBAAuB;GACtC,IAAI,SAAS,IAAI,eAAe,MAAM;GAEtC,IAAI,CAAC,QAAQ;IACX,SAAS,IAAI,cAAc,MAAM;IACjC,OAAO,KAAK;IACZ,OAAO,MAAM;IACb,IAAI,KAAK,YAAY,MAAM;GAC7B;GAEA,IAAI,OAAO,SAAS,MAClB,OAAO,OAAO;EAElB,CAAC;EAED,KACE,IAAI,QAAQ,YAAY,QACxB,QAAQ,uBAAuB,SAC/B,SAEA,IAAI,eAAe,uBAAuB,OAAO,CAAC,EAAE,OAAO;EAE7D,uBAAuB,UAAU,YAAY;CAC/C,GAAG,CAAC,QAAQ,WAAW,CAAC;CAMxB,MAAM,0BAA0B;CAQhC,MAAM,wBAAwB,KAAe,gBAAwB;EACnE,IAAI,UAAU,IAAI,eAChB,kBACF;EAEA,IAAI,CAAC,SAAS;GACZ,UAAU,IAAI,cAAc,OAAO;GACnC,QAAQ,KAAK;GACb,IAAI,MAAM,YAAY,OAAO;EAC/B;EAEA,MAAM,OAAO,mDAAmD,YAAY;EAI5E,IAAI,QAAQ,gBAAgB,MAC1B,QAAQ,cAAc;CAE1B;CAOA,MAAM,wBAAwB,aAC3B,KAAe,QAAoC;EAClD,IAAI,OAAO,IAAI,kBAAkB,YAC/B;EAGF,IAAI,cAAc,CAAC,CAAC,SAAQ,cAAa;GACvC,IACE,qBAAqB,QAAQ,IAAI,SAAS,KAC1C,CAAC,kBAAkB,UAAU,SAAS,KACtC,eAAe,KAAK,SAAS,KAC7B,gBAAgB,KAAK,SAAS,KAC9B,cAAc,SAAS,GAEvB;GAGF,qBAAqB,QAAQ,IAAI,SAAS;GAE1C,UAAU,SACP,YAAY,KAAA,CAAS,CAAC,CACtB,WAAW,gBAAgB,UAAU,CAAC;EAC3C,CAAC;CACH,GACA,CAAC,CACH;CAOA,MAAM,eAAe,kBAAkB;EACrC,IAAI,CAAC,oBAAoB,CAAC,aAAa,CAAC,UAAU,SAChD;EAGF,MAAM,SAAS,UAAU;EACzB,MAAM,MAAM,OAAO;EACnB,MAAM,MAAM,KAAK;EAEjB,IAAI,CAAC,OAAO,CAAC,KACX;EAGF,MAAM,eAAe,OAAO,QAAqB,wBAAwB;EAEzE,IAAI;EAEJ,IAAI,CAAC,cAGH,cAAA;OACK;GAKL,MAAM,oBAAoB,IAAI,iBAAiB,YAAY;GAC3D,IAAI,iBACD,WAAW,kBAAkB,UAAU,KAAK,MAC5C,WAAW,kBAAkB,aAAa,KAAK;GAClD,IAAI,OAA2B;GAE/B,OAAO,QAAQ,SAAS,cAAc;IACpC,iBAAiB,eAAe,IAAI,iBAAiB,IAAI,CAAC;IAC1D,OAAO,KAAK;GACd;GAEA,MAAM,WAAW,mBACf,aAAa,cACb,aACF;GAEA,IAAI,aAAa,MAGf;GAGF,cAAc;EAChB;EAEA,IAAI,gBAAgB;EAIpB,MAAM,oBAAoB,gBAAgB,mBAAmB;EAE7D,mBAAmB,UAAU;EAO7B,MAAM,iBAAiB,OAAO,MAAM;EAEpC,OAAO,MAAM,SAAS,GAAG,YAAY;EAErC,yBAAyB,KAAK,yBAAyB;GACrD,qBAAqB,KAAK,WAAW;GAOrC,2BAA2B,SAAS;GAIpC,gBAAgB,UAAU;GAK1B,UAF8B,iBAA8B,GAElD,CAAC,CAAC,SAAQ,OAAM;IACxB,MAAM,QAAQ,IAAI,iBAAiB,EAAE;IAMrC,MAAM,cAAc,MAAM,YAAY,OAAO,mBAAmB,EAAE;IAElE,IAAI,iBAAiB,OAAO,WAAW,GACrC;IAGF,KACG,MAAM,aAAa,WAAW,MAAM,aAAa,eAClD,GAAG,eAAe,GAClB;KACA,MAAM,OAAO,GAAG,sBAAsB;KACtC,MAAM,SAAS,wBACb,KAAK,KACL,KAAK,QACL,WACF;KAEA,IAAI,WAAW,MACb,gBAAgB,KAAK,IAAI,eAAe,MAAM;IAElD;GACF,CAAC;EACH,CAAC;EAED,OAAO,MAAM,SACX,gBAAgB,IAAI,GAAG,KAAK,KAAK,aAAa,EAAE,MAAM;EAIxD,sBAAsB,KAAK,GAAG;CAChC,GAAG;EAAC;EAAkB;EAAW;CAAqB,CAAC;CAEvD,gBAAgB;EACd,gBAAgB,UAAU;CAC5B,GAAG,CAAC,YAAY,CAAC;CAIjB,gBAAgB;EACd,IAAI,kBACF;EAGF,UAAU,SAAS,iBACf,eAAe,kBAAkB,CAAC,EAClC,OAAO;CACb,GAAG,CAAC,gBAAgB,CAAC;CAMrB,gBAAgB;EACd,MAAM,OAAO,UAAU,SAAS,iBAAiB;EAEjD,IAAI,CAAC,QAAQ,CAAC,WACZ;EAGF,IAAI,kBACF,KAAK,MAAM,eAAe,YAAY;OAEtC,KAAK,MAAM,YAAY,cAAc,MAAM;CAE/C,GAAG,CAAC,kBAAkB,SAAS,CAAC;CAIhC,gBAAgB;EACd,MAAM,MAAM,UAAU,SAAS;EAE/B,IAAI,CAAC,KAAK,MACR;EAGF,MAAM,WAAW,IAAI,eAAe,uBAAuB;EAE3D,IAAI,CAAC,kBAAkB;GACrB,UAAU,OAAO;GACjB;EACF;EAEA,IAAI,UACF;EAGF,MAAM,UAAU,IAAI,cAAc,OAAO;EACzC,QAAQ,KAAK;EACb,QAAQ,cAAc,CACpB,oDACA,gFACF,CAAC,CAAC,KAAK,IAAI;EACX,IAAI,KAAK,YAAY,OAAO;CAC9B,GAAG,CAAC,kBAAkB,SAAS,CAAC;CAEhC,gBAAgB;EACd,aAAa;CACf,GAAG,CAAC,YAAY,CAAC;CAEjB,MAAM,CAAC,WAAW,cAAc,kBAA+B;CAK/D,gBAAgB;EACd,IAAI,CAAC,oBAAoB,CAAC,WACxB;EAGF,UAAU,SAAS;EACnB,aAAa,UAAU,IAAI;CAC7B,GAAG;EAAC;EAAkB;EAAW;CAAS,CAAC;CAE3C,gBAAgB;EACd,aAAa;CAEf,GAAG,CAAC,UAAU,CAAC;CAEf,oBAAoB,WAAW,cAAc;EAC3C,SAAS;EACT,WAAW;EACX,SAAS;EACT,YAAY;EACZ,eAAe;CACjB,CAAC;CAUD,MAAM,eAAe,eAAe,EAAE,SAAS,UAAU,IAAI,CAAC,SAAS,CAAC;CACxE,MAAM,wBAAwB,oBAAoB,cAAc;CAEhE,iBAAiB,gBAAgB,cAAc;EAC7C,QAAQ;EACR,SAAS;CACX,CAAC;CAED,iBAAiB,mBAAmB,cAAc;EAChD,QAAQ;EACR,SAAS;CACX,CAAC;CAED,iBAAiB,iBAAiB,cAAc;EAC9C,QAAQ;EACR,SAAS;CACX,CAAC;CAED,iBAAiB,oBAAoB,cAAc;EACjD,QAAQ;EACR,SAAS;CACX,CAAC;CAED,MAAM,UAAU,YACZ,aAAa,SAAS,SAAS,GAAG,SAAS,IAC3C;CAEJ,OACE,oBAAC,UAAD;EACE,KAAK;EACL,OAAO;GAGL,SAAS;GACT,OAAO;GACP,QAAQ;GACR,QAAQ;GACR,GAAG;EACL;EACO;EACE;EACT,GAAI;EAEH,UAAA;CACK,CAAA;AAEZ;;;AClrBA,MAAM,qBAAqB;AAI3B,MAAM,sBAAsB,IAAI,mBAAmB;AAQnD,MAAM,yBAAyB;CAC7B,MAAM,UAAU,SAAS,cAAc,KAAK;CAE5C,QAAQ,MAAM,UAAU;CACxB,QAAQ,MAAM,sBAAsB;CACpC,QAAQ,MAAM,YAAY;CAC1B,QAAQ,MAAM,YAAY;CAE1B,MAAM,eAAe,SAAS,cAAc,KAAK;CAEjD,aAAa,MAAM,WAAW;CAI9B,MAAM,eAAe,SAAS,cAAc,KAAK;CAEjD,aAAa,aAAa,oBAAoB,EAAE;CAChD,aAAa,MAAM,WAAW;CAC9B,aAAa,MAAM,SAAS;CAC5B,aAAa,MAAM,UAAU;CAC7B,aAAa,MAAM,gBAAgB;CAEnC,MAAM,QAAQ,SAAS,cAAc,OAAO;CAE5C,MAAM,cAAc;CACpB,QAAQ,OAAO,OAAO,cAAc,YAAY;CAEhD,OAAO;EAAE;EAAS;CAAa;AACjC;AAGA,MAAM,kBAAkB,iBAA8B;CACpD,MAAM,QAAQ,aAAa;CAE3B,OAAO,iBAAiB,eAAe,MAAM,aAAa,kBAAkB,IACxE,QACA;AACN;AAEA,MAAM,UAAU,EAAE,YAAY,OAAO,eAAsB;CACzD,MAAM,UAAU,OAAuB,IAAI;CAC3C,MAAM,gBAAgB,OAA0B,IAAI;CACpD,MAAM,kBAAkB,OAA8B,IAAI;CAC1D,MAAM,CAAC,cAAc,mBAAmB,SAAgC,IAAI;CAI5E,MAAM,kBAAkB,OAAO,uBAAuB,CAAC;CAEvD,MAAM,aAAa,kBAAkB;EACnC,MAAM,aAAa,cAAc;EAEjC,IAAI,CAAC,YACH;EAGF,gBAAgB,UAAU,YAAY,gBAAgB,SAAS,SAAS;CAC1E,GAAG,CAAC,SAAS,CAAC;CAEd,MAAM,uBAAuB,OAAe,KAAA,CAAS;CAIrD,MAAM,sBAAsB,kBAAkB;EAC5C,aAAa,qBAAqB,OAAO;EACzC,qBAAqB,UAAU,OAAO,WAAW,YAAY,EAAE;CACjE,GAAG,CAAC,UAAU,CAAC;CAEf,gBAAgB;EACd,aAAa,aAAa,qBAAqB,OAAO;CACxD,GAAG,CAAC,CAAC;CAEL,oBAAoB,SAAS,MAAM,qBAAqB;EACtD,SAAS;EACT,WAAW;EACX,SAAS;EACT,YAAY;CACd,CAAC;CAED,sBAAsB;EACpB,IAAI,CAAC,QAAQ,SACX;EAGF,IAAI,aAAa,cAAc;EAE/B,IAAI,CAAC,YAAY;GACf,aACE,QAAQ,QAAQ,cAChB,QAAQ,QAAQ,aAAa,EAAE,MAAM,OAAO,CAAC;GAC/C,cAAc,UAAU;EAC1B;EAEA,IAAI,SAAS,gBAAgB;EAE7B,IAAI,CAAC,QAAQ;GACX,MAAM,QAAQ,iBAAiB;GAE/B,WAAW,YAAY,MAAM,OAAO;GACpC,SAAS,MAAM;GACf,gBAAgB,UAAU;GAC1B,gBAAgB,MAAM;EACxB;EAEA,WAAW;CAKb,GAAG,CAAC,UAAU,CAAC;CAEf,sBAAsB;EACpB,IAAI,gBAAgB,WAAW,CAAC,cAC9B,gBAAgB,gBAAgB,OAAO;CAE3C,GAAG,CAAC,YAAY,CAAC;CAEjB,OACE,oBAAC,OAAD;EAAK,KAAK;EAAS,OAAO,EAAE,SAAS,WAAW;EAC7C,UAAA,gBACC,aAAa,SAAS,eAAe,YAAY,CAAC,GAAG,YAAY;CAChE,CAAA;AAET;;;ACnJA,MAAM,SAAS,EAAE,MAAM,UAAU,GAAG,gBAAuB;CACzD,IAAI,CAAC,MACH,OAAO,SAAS,SAAS,IAAI;CAG/B,IAAI,SAAS,UACX,OACE,oBAAC,QAAD;EAAQ,WAAW,UAAU;EAC1B,WAAA,cAAa,SAAS,aAAa,SAAS,IAAI;CAC3C,CAAA;CAIZ,OAAO,oBAAC,QAAD;EAAQ,GAAI;EAAY;CAAiB,CAAA;AAClD;;;ACpBA,MAAa,cAAc;CACzB,UAAU;CACV,gBAAgB;AAClB;;;ACGA,MAAa,qBACX,MACA,aACkB;CAGlB,MAAM,UAAU,iBAAiB,QAAQ;CACzC,MAAM,EAAE,YAAY,gBAAgB,CAAC,CAAC;CAEtC,MAAM,gBAAgB,eACb;EAAE,GAAG;EAAa,GAAG;CAAQ,IACpC,CAAC,OAAO,CACV;CAEA,OAAO,cAAc;EACnB,IAAI,CAAC,MACH,OAAO;EAGT,IAAI;GACF,OAAO,QAAQ,MAAM,aAAa;EACpC,SAAS,GAAG;GACV,OAAO;IACL,SAAS,CAAC;IACV,OAAO,aAAa,QAAQ,EAAE,UAAU;GAC1C;EACF;CACF,GAAG;EAAC;EAAM;EAAe;CAAO,CAAC;AACnC;;;AChCA,MAAa,sBAAsB,MAAc,YAAqB;CACpE,MAAM,CAAC,KAAK,UAAU,SAAS,EAAE;CACjC,MAAM,CAAC,SAAS,cAAc,SAAgC,IAAI;CAElE,MAAM,MAAM,aAAa,SAAgC;EACvD,WAAW,IAAI;CACjB,GAAG,CAAC,CAAC;CAEL,gBAAgB;EACd,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,SACxB;EAGF,IAAI,YAAY;EAEhB,OAAO,4BAAmB,CACvB,MAAM,EAAE,iCACP,2BAA2B,OAAO,CACpC,CAAC,CACA,MAAK,SAAQ;GACZ,IAAI,CAAC,WACH,OAAO,IAAI;EAEf,CAAC;EAEH,aAAa;GACX,YAAY;EACd;CACF,GAAG;EAAC;EAAM;EAAS;CAAO,CAAC;CAE3B,OAAO;EAAE;EAAK;CAAI;AACpB"}
@@ -1,3 +1,4 @@
1
- import { $ as BindingFieldSpec, A as EditablePathSegment, B as parseValue, C as moveArrayItem, D as updateArrayItemProperty, E as removeArrayItems, F as createNodeFromValue, G as getRegistryBindings, H as findEditableChildren, I as extractNodeValue, J as parseBinding, K as getStructuredValue, L as extractObjectProperties, M as EditableValueEntry, N as arrayExpressionToCode, O as updateArrayItemValue, P as canLosslesslyEvaluateSource, Q as BindingComponentName, R as flattenEditableValue, S as duplicateArrayItems, T as parseItems, U as getCurrentValue, V as setEditableValue, W as getKeyBindings, X as readNodeBindings, Y as parseBindingExpression, Z as resolveBindings, _ as clearExtractCache, a as replaceIds, at as BindingRenderLeaf, b as ItemKind, c as ChildrenEdit, ct as BindingWidget, d as UpdateEntry, dt as ExtractedNodeValue, et as BindingItem, f as UpdateFailure, ft as NodeValueType, g as updateAll, h as update, i as fillIds, it as BindingRegistry, j as EditablePrimitive, k as generateCode, l as getChildrenSignatures, lt as DataAttrNode, m as bulkUpdate, n as validateBindingValue, nt as BindingOption, o as canStructurallyEditArray, ot as BindingRenderMap, p as UpdateResult, q as isComponentTagName, r as clone, rt as BindingOptions, s as ChildrenAction, st as BindingType, t as ValidationResult, tt as BindingKeyMap, u as UpdateAllResult, ut as EditableNodeValueType, v as extract, w as moveArrayItems, x as appendArrayItem, y as ArrayItem, z as parseArrayExpression } from "../../index-f7ijuNTa.js";
1
+ import { _ as BindingWidget, a as validateBindingValue, c as BindingItem, d as BindingOptions, f as BindingRegistry, g as BindingType, h as BindingSchema, i as defaultValidationMessages, l as BindingKeyMap, m as BindingRenderMap, n as ValidationOptions, o as BindingComponentName, p as BindingRenderLeaf, r as ValidationResult, s as BindingFieldSpec, t as ValidationMessages, u as BindingOption, v as DataAttrNode } from "../../validate-DB59Z_Nx.js";
2
2
  import { a as SectionOptions, c as createSectionPreviewCache, d as generateSectionPreview, f as generateSectionPreviews, g as replaceDocumentSections, h as parseDocument, i as DocumentTree, l as fillSectionIds, m as inspectDocument, n as DocumentOptions, o as SectionPreviewCache, p as getSections, r as DocumentProblem, s as clearDocumentParseCache, t as DocumentInspection, u as generateDocumentCode } from "../../document-Ct4jW78J.js";
3
- export { type ArrayItem, type BindingComponentName, type BindingFieldSpec, type BindingItem, type BindingKeyMap, type BindingOption, type BindingOptions, type BindingRegistry, type BindingRenderLeaf, type BindingRenderMap, type BindingType, type BindingWidget, type ChildrenAction, type ChildrenEdit, type DataAttrNode, type DocumentInspection, type DocumentOptions, type DocumentProblem, type DocumentTree, type EditableNodeValueType, type EditablePathSegment, type EditablePrimitive, type EditableValueEntry, type ExtractedNodeValue, type ItemKind, type NodeValueType, type SectionOptions, type SectionPreviewCache, type UpdateAllResult, type UpdateEntry, type UpdateFailure, type UpdateResult, type ValidationResult, appendArrayItem, arrayExpressionToCode, bulkUpdate, canLosslesslyEvaluateSource, canStructurallyEditArray, clearDocumentParseCache, clearExtractCache, clone, createNodeFromValue, createSectionPreviewCache, duplicateArrayItems, extract, extractNodeValue, extractObjectProperties, fillIds, fillSectionIds, findEditableChildren, flattenEditableValue, generateCode, generateDocumentCode, generateSectionPreview, generateSectionPreviews, getChildrenSignatures, getCurrentValue, getKeyBindings, getRegistryBindings, getSections, getStructuredValue, inspectDocument, isComponentTagName, moveArrayItem, moveArrayItems, parseArrayExpression, parseBinding, parseBindingExpression, parseDocument, parseItems, parseValue, readNodeBindings, removeArrayItems, replaceDocumentSections, replaceIds, resolveBindings, setEditableValue, update, updateAll, updateArrayItemProperty, updateArrayItemValue, validateBindingValue };
3
+ import { A as removeArrayItems, B as UpdateFailure, C as moveArrayItem, D as parseBindingExpression, E as parseBinding, F as ChildrenAction, G as parseValue, H as bulkUpdate, I as ChildrenEdit, J as EditableValueEntry, K as EditablePathSegment, L as getChildrenSignatures, M as resolveBindings, N as updateArrayItemProperty, O as parseItems, P as updateArrayItemValue, Q as extract, R as UpdateAllResult, S as isComponentTagName, T as parseArrayExpression, U as update, V as UpdateResult, W as updateAll, X as setEditableValue, Y as flattenEditableValue, Z as findEditableChildren, _ as generateCode, a as NodeValueType, b as getRegistryBindings, c as canLosslesslyEvaluateSource, d as clone, f as createNodeFromValue, g as fillIds, h as extractObjectProperties, i as ItemKind, j as replaceIds, k as readNodeBindings, l as canStructurallyEditArray, m as extractNodeValue, n as EditableNodeValueType, o as appendArrayItem, p as duplicateArrayItems, q as EditablePrimitive, r as ExtractedNodeValue, s as arrayExpressionToCode, t as ArrayItem, u as clearExtractCache, v as getCurrentValue, w as moveArrayItems, x as getStructuredValue, y as getKeyBindings, z as UpdateEntry } from "../../index-DKYUxi-E.js";
4
+ export { ArrayItem, type BindingComponentName, type BindingFieldSpec, type BindingItem, type BindingKeyMap, type BindingOption, type BindingOptions, type BindingRegistry, type BindingRenderLeaf, type BindingRenderMap, type BindingSchema, type BindingType, type BindingWidget, type ChildrenAction, type ChildrenEdit, type DataAttrNode, type DocumentInspection, type DocumentOptions, type DocumentProblem, type DocumentTree, EditableNodeValueType, type EditablePathSegment, type EditablePrimitive, type EditableValueEntry, ExtractedNodeValue, ItemKind, NodeValueType, type SectionOptions, type SectionPreviewCache, type UpdateAllResult, type UpdateEntry, type UpdateFailure, type UpdateResult, type ValidationMessages, type ValidationOptions, type ValidationResult, appendArrayItem, arrayExpressionToCode, bulkUpdate, canLosslesslyEvaluateSource, canStructurallyEditArray, clearDocumentParseCache, clearExtractCache, clone, createNodeFromValue, createSectionPreviewCache, defaultValidationMessages, duplicateArrayItems, extract, extractNodeValue, extractObjectProperties, fillIds, fillSectionIds, findEditableChildren, flattenEditableValue, generateCode, generateDocumentCode, generateSectionPreview, generateSectionPreviews, getChildrenSignatures, getCurrentValue, getKeyBindings, getRegistryBindings, getSections, getStructuredValue, inspectDocument, isComponentTagName, moveArrayItem, moveArrayItems, parseArrayExpression, parseBinding, parseBindingExpression, parseDocument, parseItems, parseValue, readNodeBindings, removeArrayItems, replaceDocumentSections, replaceIds, resolveBindings, setEditableValue, update, updateAll, updateArrayItemProperty, updateArrayItemValue, validateBindingValue };
@@ -1,3 +1,150 @@
1
- import { a as generateSectionPreview, c as inspectDocument, f as clone, h as replaceIds, i as generateDocumentCode, l as parseDocument, n as createSectionPreviewCache, o as generateSectionPreviews, p as fillIds, r as fillSectionIds, s as getSections, t as clearDocumentParseCache, u as replaceDocumentSections, y as generateCode } from "../../document-BDn_f08_.js";
2
- import { A as createNodeFromValue, C as isComponentTagName, D as resolveBindings, E as readNodeBindings, F as parseValue, I as setEditableValue, M as extractObjectProperties, N as flattenEditableValue, O as arrayExpressionToCode, P as parseArrayExpression, S as getStructuredValue, T as parseBindingExpression, a as getChildrenSignatures, b as getKeyBindings, c as appendArrayItem, d as moveArrayItems, f as parseItems, g as canStructurallyEditArray, h as updateArrayItemValue, i as updateAll, j as extractNodeValue, k as canLosslesslyEvaluateSource, l as duplicateArrayItems, m as updateArrayItemProperty, n as bulkUpdate, o as clearExtractCache, p as removeArrayItems, r as update, s as extract, t as validateBindingValue, u as moveArrayItem, v as findEditableChildren, w as parseBinding, x as getRegistryBindings, y as getCurrentValue } from "../../ast-dYb78955.js";
3
- export { appendArrayItem, arrayExpressionToCode, bulkUpdate, canLosslesslyEvaluateSource, canStructurallyEditArray, clearDocumentParseCache, clearExtractCache, clone, createNodeFromValue, createSectionPreviewCache, duplicateArrayItems, extract, extractNodeValue, extractObjectProperties, fillIds, fillSectionIds, findEditableChildren, flattenEditableValue, generateCode, generateDocumentCode, generateSectionPreview, generateSectionPreviews, getChildrenSignatures, getCurrentValue, getKeyBindings, getRegistryBindings, getSections, getStructuredValue, inspectDocument, isComponentTagName, moveArrayItem, moveArrayItems, parseArrayExpression, parseBinding, parseBindingExpression, parseDocument, parseItems, parseValue, readNodeBindings, removeArrayItems, replaceDocumentSections, replaceIds, resolveBindings, setEditableValue, update, updateAll, updateArrayItemProperty, updateArrayItemValue, validateBindingValue };
1
+ import { C as require_lib, S as require_lib$1, _ as generateCode$1, a as generateSectionPreview, c as inspectDocument, f as clone$1, h as replaceIds$1, i as generateDocumentCode, l as parseDocument, n as createSectionPreviewCache, o as generateSectionPreviews, p as fillIds$1, r as fillSectionIds, s as getSections, t as clearDocumentParseCache, u as replaceDocumentSections, w as __toESM } from "../../document-CGbe6bSV.js";
2
+ import { n as validateBindingValue, t as defaultValidationMessages } from "../../validate-iLo8IONY.js";
3
+ import { A as extractNodeValue$1, C as getStructuredValue$1, D as readNodeBindings$1, E as parseBindingExpression$1, M as parseArrayExpression$1, N as parseValue, O as resolveBindings$1, P as unwrapExpression, S as getRegistryBindings$1, T as parseBinding$1, _ as clearExtractCache$1, a as parseItems$1, b as getCurrentValue$1, c as updateArrayItemValue$1, d as update, f as updateAll, h as getChildrenSignatures, i as moveArrayItems$1, j as extractObjectProperties$1, k as canLosslesslyEvaluateSource$1, l as canStructurallyEditArray$1, m as createNodeFromValue$1, n as duplicateArrayItems$1, o as removeArrayItems$1, p as arrayExpressionToCode$1, r as moveArrayItem$1, s as updateArrayItemProperty$1, t as appendArrayItem$1, u as bulkUpdate, v as extract, w as isComponentTagName$1, x as getKeyBindings$1, y as findEditableChildren } from "../../items-B6OXxcLG.js";
4
+ //#region src/utils/ast/editable-value.ts
5
+ var import_lib = require_lib();
6
+ var import_lib$1 = /* @__PURE__ */ __toESM(require_lib$1(), 1);
7
+ const MAX_FLATTEN_DEPTH = 20;
8
+ const isEditablePrimitive = (value) => typeof value === "string" || typeof value === "number" || typeof value === "boolean";
9
+ const flattenEditableValue = (value) => {
10
+ const parsed = parseValue(value);
11
+ if (typeof parsed !== "object" || parsed === null || Object.keys(parsed).length === 0) return null;
12
+ const entries = [];
13
+ const walk = (node, path, depth) => {
14
+ if (depth > MAX_FLATTEN_DEPTH) return;
15
+ if (isEditablePrimitive(node)) {
16
+ entries.push({
17
+ path,
18
+ value: node
19
+ });
20
+ return;
21
+ }
22
+ if (Array.isArray(node)) {
23
+ node.forEach((item, index) => walk(item, [...path, index], depth + 1));
24
+ return;
25
+ }
26
+ if (typeof node === "object" && node !== null) Object.entries(node).forEach(([key, item]) => walk(item, [...path, key], depth + 1));
27
+ };
28
+ walk(parsed, [], 0);
29
+ return entries.length ? entries : null;
30
+ };
31
+ const findEditableLeaf = (root, path) => {
32
+ let node = unwrapExpression(root);
33
+ for (const segment of path) {
34
+ if (import_lib$1.isArrayExpression(node)) {
35
+ if (typeof segment !== "number") return null;
36
+ const elements = node.elements.slice(0, segment + 1);
37
+ const element = node.elements[segment];
38
+ if (!element || elements.some((item) => import_lib$1.isSpreadElement(item))) return null;
39
+ node = unwrapExpression(element);
40
+ continue;
41
+ }
42
+ if (import_lib$1.isObjectExpression(node)) {
43
+ const key = String(segment);
44
+ const matches = (property) => import_lib$1.isObjectProperty(property) && !property.computed && (import_lib$1.isIdentifier(property.key) && property.key.name === key || import_lib$1.isStringLiteral(property.key) && property.key.value === key || import_lib$1.isNumericLiteral(property.key) && String(property.key.value) === key);
45
+ let index = node.properties.length - 1;
46
+ while (index >= 0 && !matches(node.properties[index])) index--;
47
+ const property = node.properties[index];
48
+ if (!property || !import_lib$1.isObjectProperty(property) || node.properties.slice(index + 1).some((item) => import_lib$1.isSpreadElement(item))) return null;
49
+ node = unwrapExpression(property.value);
50
+ continue;
51
+ }
52
+ return null;
53
+ }
54
+ return node;
55
+ };
56
+ const isEditableLeaf = (node) => import_lib$1.isStringLiteral(node) || import_lib$1.isNumericLiteral(node) || import_lib$1.isBooleanLiteral(node) || import_lib$1.isUnaryExpression(node) && node.operator === "-" && import_lib$1.isNumericLiteral(node.argument) || import_lib$1.isTemplateLiteral(node) && node.expressions.length === 0 || import_lib$1.isJSXElement(node) || import_lib$1.isJSXFragment(node);
57
+ const quoteString = (text, quote) => {
58
+ if (quote === "`") return `\`${text.replace(/[\\`]|\$\{/g, (match) => `\\${match}`)}\``;
59
+ const escaped = JSON.stringify(text).slice(1, -1);
60
+ return quote === "\"" ? `"${escaped}"` : `'${escaped.replace(/\\"/g, "\"").replace(/'/g, "\\'")}'`;
61
+ };
62
+ const isJSXSource = (text) => {
63
+ try {
64
+ const expression = (0, import_lib.parseExpression)(text, { plugins: ["jsx"] });
65
+ return import_lib$1.isJSXElement(expression) || import_lib$1.isJSXFragment(expression);
66
+ } catch {
67
+ return false;
68
+ }
69
+ };
70
+ const leafSource = (value, leaf, next) => {
71
+ if (typeof next !== "string") return String(next);
72
+ if ((import_lib$1.isJSXElement(leaf) || import_lib$1.isJSXFragment(leaf)) && isJSXSource(next)) return next.trim();
73
+ const quote = import_lib$1.isStringLiteral(leaf) || import_lib$1.isTemplateLiteral(leaf) ? value[leaf.start] : "'";
74
+ return quoteString(next, quote);
75
+ };
76
+ const setEditableValue = (value, path, next) => {
77
+ if (!path.length) return value;
78
+ let leaf;
79
+ try {
80
+ leaf = findEditableLeaf((0, import_lib.parseExpression)(value, { plugins: ["jsx", "typescript"] }), path);
81
+ } catch {
82
+ return value;
83
+ }
84
+ if (!leaf || !isEditableLeaf(leaf) || leaf.start == null || leaf.end == null) return value;
85
+ return `${value.slice(0, leaf.start)}${leafSource(value, leaf, next)}${value.slice(leaf.end)}`;
86
+ };
87
+ //#endregion
88
+ //#region src/utils/ast/index.ts
89
+ /** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */
90
+ const appendArrayItem = appendArrayItem$1;
91
+ /** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */
92
+ const duplicateArrayItems = duplicateArrayItems$1;
93
+ /** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */
94
+ const moveArrayItem = moveArrayItem$1;
95
+ /** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */
96
+ const moveArrayItems = moveArrayItems$1;
97
+ /** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */
98
+ const parseItems = parseItems$1;
99
+ /** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */
100
+ const removeArrayItems = removeArrayItems$1;
101
+ /** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */
102
+ const updateArrayItemProperty = updateArrayItemProperty$1;
103
+ /** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */
104
+ const updateArrayItemValue = updateArrayItemValue$1;
105
+ /** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */
106
+ const parseArrayExpression = parseArrayExpression$1;
107
+ /** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */
108
+ const arrayExpressionToCode = arrayExpressionToCode$1;
109
+ /** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */
110
+ const canStructurallyEditArray = canStructurallyEditArray$1;
111
+ /** @deprecated Internal. Read values through `extract` or `PanelBinding.value`. Removed in the next major. */
112
+ const extractNodeValue = extractNodeValue$1;
113
+ /** @deprecated Internal. Read values through `extract` or `PanelBinding.value`. Removed in the next major. */
114
+ const extractObjectProperties = extractObjectProperties$1;
115
+ /** @deprecated Internal. Write values through `update` or `PanelBinding.onChange`. Removed in the next major. */
116
+ const createNodeFromValue = createNodeFromValue$1;
117
+ /** @deprecated Internal. Check `PanelBinding.canEditValue` instead. Removed in the next major. */
118
+ const canLosslesslyEvaluateSource = canLosslesslyEvaluateSource$1;
119
+ /** @deprecated Internal. Read values through `extract` or `PanelBinding.value`. Removed in the next major. */
120
+ const getCurrentValue = getCurrentValue$1;
121
+ /** @deprecated Internal. Read values through `extract` or `PanelBinding.value`. Removed in the next major. */
122
+ const getStructuredValue = getStructuredValue$1;
123
+ /** @deprecated Internal. Read bindings through `extract` or `useDndPanel().bindings`. Removed in the next major. */
124
+ const parseBinding = parseBinding$1;
125
+ /** @deprecated Internal. Read bindings through `extract` or `useDndPanel().bindings`. Removed in the next major. */
126
+ const parseBindingExpression = parseBindingExpression$1;
127
+ /** @deprecated Internal. Read bindings through `extract` or `useDndPanel().bindings`. Removed in the next major. */
128
+ const readNodeBindings = readNodeBindings$1;
129
+ /** @deprecated Internal. Read bindings through `extract` or `useDndPanel().bindings`. Removed in the next major. */
130
+ const resolveBindings = resolveBindings$1;
131
+ /** @deprecated Internal. Read bindings through `extract` or `useDndPanel().bindings`. Removed in the next major. */
132
+ const getKeyBindings = getKeyBindings$1;
133
+ /** @deprecated Internal. Read bindings through `extract` or `useDndPanel().bindings`. Removed in the next major. */
134
+ const getRegistryBindings = getRegistryBindings$1;
135
+ /** @deprecated Internal. Removed in the next major. */
136
+ const isComponentTagName = isComponentTagName$1;
137
+ /** @deprecated Internal. Removed in the next major. */
138
+ const fillIds = fillIds$1;
139
+ /** @deprecated Internal. Removed in the next major. */
140
+ const replaceIds = replaceIds$1;
141
+ /** @deprecated Internal. Removed in the next major. */
142
+ const clone = clone$1;
143
+ /** @deprecated Internal. Removed in the next major. */
144
+ const generateCode = generateCode$1;
145
+ /** @deprecated Internal. Use `clearEditorCaches` from `./utils`. Removed in the next major. */
146
+ const clearExtractCache = clearExtractCache$1;
147
+ //#endregion
148
+ export { appendArrayItem, arrayExpressionToCode, bulkUpdate, canLosslesslyEvaluateSource, canStructurallyEditArray, clearDocumentParseCache, clearExtractCache, clone, createNodeFromValue, createSectionPreviewCache, defaultValidationMessages, duplicateArrayItems, extract, extractNodeValue, extractObjectProperties, fillIds, fillSectionIds, findEditableChildren, flattenEditableValue, generateCode, generateDocumentCode, generateSectionPreview, generateSectionPreviews, getChildrenSignatures, getCurrentValue, getKeyBindings, getRegistryBindings, getSections, getStructuredValue, inspectDocument, isComponentTagName, moveArrayItem, moveArrayItems, parseArrayExpression, parseBinding, parseBindingExpression, parseDocument, parseItems, parseValue, readNodeBindings, removeArrayItems, replaceDocumentSections, replaceIds, resolveBindings, setEditableValue, update, updateAll, updateArrayItemProperty, updateArrayItemValue, validateBindingValue };
149
+
150
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["t","parseExpression","_appendArrayItem","_duplicateArrayItems","_moveArrayItem","_moveArrayItems","_parseItems","_removeArrayItems","_updateArrayItemProperty","_updateArrayItemValue","_parseArrayExpression","_arrayExpressionToCode","_canStructurallyEditArray","_extractNodeValue","_extractObjectProperties","_createNodeFromValue","_canLosslesslyEvaluateSource","_getCurrentValue","_getStructuredValue","_parseBinding","_parseBindingExpression","_readNodeBindings","_resolveBindings","_getKeyBindings","_getRegistryBindings","_isComponentTagName","_fillIds","_replaceIds","_clone","_generateCode","_clearExtractCache"],"sources":["../../../src/utils/ast/editable-value.ts","../../../src/utils/ast/index.ts"],"sourcesContent":["import { parseExpression } from '@babel/parser';\nimport * as t from '@babel/types';\n\nimport { parseValue, unwrapExpression } from './value';\n\n// The editable leaves of an object or array value: listing them with their\n// paths, and replacing one while keeping the rest of the source as written.\n\nexport type EditablePathSegment = string | number;\n\nexport type EditablePrimitive = string | number | boolean;\n\nexport interface EditableValueEntry {\n path: EditablePathSegment[];\n value: EditablePrimitive;\n}\n\nconst MAX_FLATTEN_DEPTH = 20;\n\nconst isEditablePrimitive = (value: unknown): value is EditablePrimitive =>\n typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean';\n\n// Lists the editable leaves of an object or array value, with their paths.\n// It follows the value's own shape, so it works without a `render` map\n// (#225), as for `style` or an `items` array of `{ key, children }`. Strings,\n// numbers and booleans are leaves, whatever a string contains. Deeply nested\n// values stop at a fixed depth, and anything deeper is left out.\nexport const flattenEditableValue = (\n value: string,\n): EditableValueEntry[] | null => {\n const parsed = parseValue(value);\n\n if (\n typeof parsed !== 'object' ||\n parsed === null ||\n Object.keys(parsed).length === 0\n ) {\n return null;\n }\n\n const entries: EditableValueEntry[] = [];\n\n const walk = (node: unknown, path: EditablePathSegment[], depth: number) => {\n if (depth > MAX_FLATTEN_DEPTH) {\n return;\n }\n\n if (isEditablePrimitive(node)) {\n entries.push({ path, value: node });\n return;\n }\n\n if (Array.isArray(node)) {\n node.forEach((item, index) => walk(item, [...path, index], depth + 1));\n return;\n }\n\n if (typeof node === 'object' && node !== null) {\n Object.entries(node).forEach(([key, item]) =>\n walk(item, [...path, key], depth + 1),\n );\n }\n\n // `null`, `undefined`, functions and symbols have no editable form and\n // are left out.\n };\n\n walk(parsed, [], 0);\n\n return entries.length ? entries : null;\n};\n\n// Finds the node `flattenEditableValue` reported at `path`, walking the\n// same literal structure `evaluateLiteral` reads. Returns null for anything\n// it can't point at with certainty: a missing key or index, a step through\n// something that isn't an object or array, or a spread that could replace\n// the entry at runtime.\nconst findEditableLeaf = (\n root: t.Node,\n path: EditablePathSegment[],\n): t.Node | null => {\n let node = unwrapExpression(root);\n\n for (const segment of path) {\n if (t.isArrayExpression(node)) {\n if (typeof segment !== 'number') {\n return null;\n }\n\n const elements = node.elements.slice(0, segment + 1);\n const element = node.elements[segment];\n\n if (!element || elements.some(item => t.isSpreadElement(item))) {\n return null;\n }\n\n node = unwrapExpression(element);\n continue;\n }\n\n if (t.isObjectExpression(node)) {\n const key = String(segment);\n const matches = (property: t.ObjectExpression['properties'][number]) =>\n t.isObjectProperty(property) &&\n !property.computed &&\n ((t.isIdentifier(property.key) && property.key.name === key) ||\n (t.isStringLiteral(property.key) && property.key.value === key) ||\n (t.isNumericLiteral(property.key) &&\n String(property.key.value) === key));\n // The last match is the one a duplicate key leaves in effect, and the\n // one `evaluateLiteral` reports.\n let index = node.properties.length - 1;\n\n while (index >= 0 && !matches(node.properties[index]!)) {\n index--;\n }\n\n const property = node.properties[index];\n\n if (\n !property ||\n !t.isObjectProperty(property) ||\n node.properties.slice(index + 1).some(item => t.isSpreadElement(item))\n ) {\n return null;\n }\n\n node = unwrapExpression(property.value);\n continue;\n }\n\n return null;\n }\n\n return node;\n};\n\nconst isEditableLeaf = (node: t.Node): boolean =>\n t.isStringLiteral(node) ||\n t.isNumericLiteral(node) ||\n t.isBooleanLiteral(node) ||\n (t.isUnaryExpression(node) &&\n node.operator === '-' &&\n t.isNumericLiteral(node.argument)) ||\n (t.isTemplateLiteral(node) && node.expressions.length === 0) ||\n t.isJSXElement(node) ||\n t.isJSXFragment(node);\n\nconst quoteString = (text: string, quote: string): string => {\n if (quote === '`') {\n return `\\`${text.replace(/[\\\\`]|\\$\\{/g, match => `\\\\${match}`)}\\``;\n }\n\n const escaped = JSON.stringify(text).slice(1, -1);\n\n return quote === '\"'\n ? `\"${escaped}\"`\n : `'${escaped.replace(/\\\\\"/g, '\"').replace(/'/g, \"\\\\'\")}'`;\n};\n\nconst isJSXSource = (text: string): boolean => {\n try {\n const expression = parseExpression(text, { plugins: ['jsx'] });\n\n return t.isJSXElement(expression) || t.isJSXFragment(expression);\n } catch {\n return false;\n }\n};\n\n// Source text for `next` in place of `leaf`, keeping the leaf's own form\n// where it has one: a string keeps its quotes, and a JSX leaf, which\n// `flattenEditableValue` reports as its source text, stays JSX when the\n// edited text still is.\nconst leafSource = (\n value: string,\n leaf: t.Node,\n next: EditablePrimitive,\n): string => {\n if (typeof next !== 'string') {\n return String(next);\n }\n\n if ((t.isJSXElement(leaf) || t.isJSXFragment(leaf)) && isJSXSource(next)) {\n return next.trim();\n }\n\n const quote =\n t.isStringLiteral(leaf) || t.isTemplateLiteral(leaf)\n ? value[leaf.start!]!\n : \"'\";\n\n return quoteString(next, quote);\n};\n\n// Replaces the leaf at `path` (as `flattenEditableValue` reports it) and\n// returns `value` with only that leaf's source changed, so formatting,\n// comments, JSX, functions and references stay (#427). The result is a\n// string for `PanelBinding.onChange`. A path it can't find, or a `value`\n// that doesn't parse, returns `value` unchanged. It never adds a key or\n// grows an array.\nexport const setEditableValue = (\n value: string,\n path: EditablePathSegment[],\n next: EditablePrimitive,\n): string => {\n if (!path.length) {\n return value;\n }\n\n let leaf: t.Node | null;\n\n try {\n leaf = findEditableLeaf(\n parseExpression(value, { plugins: ['jsx', 'typescript'] }),\n path,\n );\n } catch {\n return value;\n }\n\n if (\n !leaf ||\n !isEditableLeaf(leaf) ||\n leaf.start == null ||\n leaf.end == null\n ) {\n return value;\n }\n\n return `${value.slice(0, leaf.start)}${leafSource(value, leaf, next)}${value.slice(leaf.end)}`;\n};\n","// The public `./utils/ast` entry: reading a section's bindings (`extract`),\n// committing edits (`update`, `updateAll`), validating and flattening\n// values, and the types those take and return. Library code imports from\n// the module files, not from here, so the deprecated names below can leave\n// this barrel without touching their callers (#522).\nimport { canStructurallyEditArray as _canStructurallyEditArray } from './array-source';\nimport { getCurrentValue as _getCurrentValue } from './binding';\nimport { getStructuredValue as _getStructuredValue } from './binding';\nimport { parseBinding as _parseBinding } from './binding';\nimport { parseBindingExpression as _parseBindingExpression } from './binding';\nimport { readNodeBindings as _readNodeBindings } from './binding';\nimport { resolveBindings as _resolveBindings } from './binding';\nimport { getKeyBindings as _getKeyBindings } from './binding';\nimport { getRegistryBindings as _getRegistryBindings } from './binding';\nimport { isComponentTagName as _isComponentTagName } from './binding';\nimport { clearExtractCache as _clearExtractCache } from './extract';\nimport { generateCode as _generateCode } from './helpers';\nimport { appendArrayItem as _appendArrayItem } from './items';\nimport { duplicateArrayItems as _duplicateArrayItems } from './items';\nimport { moveArrayItem as _moveArrayItem } from './items';\nimport { moveArrayItems as _moveArrayItems } from './items';\nimport { parseItems as _parseItems } from './items';\nimport { removeArrayItems as _removeArrayItems } from './items';\nimport { updateArrayItemProperty as _updateArrayItemProperty } from './items';\nimport { updateArrayItemValue as _updateArrayItemValue } from './items';\nimport type { ArrayItem as _ArrayItem } from './items';\nimport type { ItemKind as _ItemKind } from './items';\nimport { fillIds as _fillIds } from './tree';\nimport { replaceIds as _replaceIds } from './tree';\nimport { clone as _clone } from './tree';\nimport type { ExtractedNodeValue as _ExtractedNodeValue } from './types';\nimport type { NodeValueType as _NodeValueType } from './types';\nimport type { EditableNodeValueType as _EditableNodeValueType } from './types';\nimport { parseArrayExpression as _parseArrayExpression } from './value';\nimport { extractNodeValue as _extractNodeValue } from './value';\nimport { extractObjectProperties as _extractObjectProperties } from './value';\nimport { canLosslesslyEvaluateSource as _canLosslesslyEvaluateSource } from './value';\nimport { arrayExpressionToCode as _arrayExpressionToCode } from './value-expression';\nimport { createNodeFromValue as _createNodeFromValue } from './value-expression';\n\nexport type {\n BindingFieldSpec,\n BindingItem,\n BindingOption,\n BindingRenderLeaf,\n BindingComponentName,\n BindingKeyMap,\n BindingOptions,\n BindingRegistry,\n BindingRenderMap,\n BindingSchema,\n BindingType,\n BindingWidget,\n DataAttrNode,\n} from './types';\nexport { findEditableChildren } from './binding';\nexport type {\n EditablePathSegment,\n EditablePrimitive,\n EditableValueEntry,\n} from './editable-value';\nexport { parseValue } from './value';\nexport { flattenEditableValue, setEditableValue } from './editable-value';\nexport { extract } from './extract';\nexport type {\n DocumentOptions,\n DocumentProblem,\n SectionOptions,\n} from './document';\nexport { bulkUpdate, update, updateAll } from './update';\nexport type {\n UpdateAllResult,\n UpdateEntry,\n UpdateFailure,\n UpdateResult,\n} from './update';\nexport { getChildrenSignatures } from './children';\nexport type { ChildrenAction, ChildrenEdit } from './children';\nexport type {\n ValidationMessages,\n ValidationOptions,\n ValidationResult,\n} from './validate';\nexport { defaultValidationMessages, validateBindingValue } from './validate';\n\n// Internal helpers, deprecated. Each still works, and leaves this entry in\n// the next major (#522). Most are `const` aliases, so their\n// `@deprecated` reaches the built declarations. The document layer stays a\n// plain re-export: as an alias here, its Babel AST types move this entry's\n// declarations into the chunk that also pulls in React, and\n// `check-package-types.mjs` fails. A re-export's JSDoc doesn't survive the\n// declaration bundle, so those are announced in the docs and changeset only.\n\n// Array-literal editing: the engine behind `useDndItems`.\n/** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */\nexport const appendArrayItem = _appendArrayItem;\n/** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */\nexport const duplicateArrayItems = _duplicateArrayItems;\n/** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */\nexport const moveArrayItem = _moveArrayItem;\n/** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */\nexport const moveArrayItems = _moveArrayItems;\n/** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */\nexport const parseItems = _parseItems;\n/** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */\nexport const removeArrayItems = _removeArrayItems;\n/** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */\nexport const updateArrayItemProperty = _updateArrayItemProperty;\n/** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */\nexport const updateArrayItemValue = _updateArrayItemValue;\n/** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */\nexport const parseArrayExpression = _parseArrayExpression;\n/** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */\nexport const arrayExpressionToCode = _arrayExpressionToCode;\n/** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */\nexport const canStructurallyEditArray = _canStructurallyEditArray;\n/** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */\nexport type ArrayItem = _ArrayItem;\n/** @deprecated Internal. Use `useDndItems` from `./dnd`. Removed in the next major. */\nexport type ItemKind = _ItemKind;\n\n// Value plumbing behind `extract`, `update` and `PanelBinding.value`.\n/** @deprecated Internal. Read values through `extract` or `PanelBinding.value`. Removed in the next major. */\nexport const extractNodeValue = _extractNodeValue;\n/** @deprecated Internal. Read values through `extract` or `PanelBinding.value`. Removed in the next major. */\nexport const extractObjectProperties = _extractObjectProperties;\n/** @deprecated Internal. Write values through `update` or `PanelBinding.onChange`. Removed in the next major. */\nexport const createNodeFromValue = _createNodeFromValue;\n/** @deprecated Internal. Check `PanelBinding.canEditValue` instead. Removed in the next major. */\nexport const canLosslesslyEvaluateSource = _canLosslesslyEvaluateSource;\n/** @deprecated Internal. Read values through `extract` or `PanelBinding.value`. Removed in the next major. */\nexport const getCurrentValue = _getCurrentValue;\n/** @deprecated Internal. Read values through `extract` or `PanelBinding.value`. Removed in the next major. */\nexport const getStructuredValue = _getStructuredValue;\n/** @deprecated Internal. Removed in the next major. */\nexport type ExtractedNodeValue = _ExtractedNodeValue;\n/** @deprecated Internal. Removed in the next major. */\nexport type NodeValueType = _NodeValueType;\n/** @deprecated Internal. Removed in the next major. */\nexport type EditableNodeValueType = _EditableNodeValueType;\n\n// Binding resolution behind `extract(source, { bindings, bindingKeys })`.\n/** @deprecated Internal. Read bindings through `extract` or `useDndPanel().bindings`. Removed in the next major. */\nexport const parseBinding = _parseBinding;\n/** @deprecated Internal. Read bindings through `extract` or `useDndPanel().bindings`. Removed in the next major. */\nexport const parseBindingExpression = _parseBindingExpression;\n/** @deprecated Internal. Read bindings through `extract` or `useDndPanel().bindings`. Removed in the next major. */\nexport const readNodeBindings = _readNodeBindings;\n/** @deprecated Internal. Read bindings through `extract` or `useDndPanel().bindings`. Removed in the next major. */\nexport const resolveBindings = _resolveBindings;\n/** @deprecated Internal. Read bindings through `extract` or `useDndPanel().bindings`. Removed in the next major. */\nexport const getKeyBindings = _getKeyBindings;\n/** @deprecated Internal. Read bindings through `extract` or `useDndPanel().bindings`. Removed in the next major. */\nexport const getRegistryBindings = _getRegistryBindings;\n/** @deprecated Internal. Removed in the next major. */\nexport const isComponentTagName = _isComponentTagName;\n\n// The document layer under `./utils` and `Live.Dnd`.\nexport {\n /** @deprecated Internal. Use `extractSections` from `./utils`. Removed in the next major. */\n parseDocument,\n /** @deprecated Internal. Use `extractSections` from `./utils`. Removed in the next major. */\n getSections,\n /** @deprecated Internal. Use `replaceSections` from `./utils`. Removed in the next major. */\n replaceDocumentSections,\n /** @deprecated Internal. Use `checkDocument` from `./utils`. Removed in the next major. */\n inspectDocument,\n /** @deprecated Internal. Removed in the next major. */\n generateDocumentCode,\n /** @deprecated Internal. Removed in the next major. */\n fillSectionIds,\n /** @deprecated Internal. Removed in the next major. */\n generateSectionPreview,\n /** @deprecated Internal. Removed in the next major. */\n generateSectionPreviews,\n /** @deprecated Internal. Removed in the next major. */\n createSectionPreviewCache,\n} from './document';\nexport type {\n /** @deprecated Internal. Use `checkDocument` from `./utils`. Removed in the next major. */\n DocumentInspection,\n /** @deprecated Internal. Removed in the next major. */\n DocumentTree,\n /** @deprecated Internal. Removed in the next major. */\n SectionPreviewCache,\n} from './document';\n\n// Ids, code generation and caches.\n/** @deprecated Internal. Removed in the next major. */\nexport const fillIds = _fillIds;\n/** @deprecated Internal. Removed in the next major. */\nexport const replaceIds = _replaceIds;\n/** @deprecated Internal. Removed in the next major. */\nexport const clone = _clone;\n/** @deprecated Internal. Removed in the next major. */\nexport const generateCode = _generateCode;\n/** @deprecated Internal. Use `clearEditorCaches` from `./utils`. Removed in the next major. */\nexport const clearExtractCache = _clearExtractCache;\nexport {\n /** @deprecated Internal. Use `clearEditorCaches` from `./utils`. Removed in the next major. */\n clearDocumentParseCache,\n} from './document';\n"],"mappings":"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"}