@deot/docs-playground 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -0
- package/dist/index.cjs +506 -52
- package/dist/index.d.ts +51 -1
- package/dist/index.js +503 -53
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -153,10 +153,10 @@ var icon_default = /* @__PURE__ */ defineComponent({
|
|
|
153
153
|
});
|
|
154
154
|
//#endregion
|
|
155
155
|
//#region packages/playground/src/core/code-preview/github.css?inline
|
|
156
|
-
var github_default = "pre code.hljs{display:block;padding:1em
|
|
156
|
+
var github_default = "pre code.hljs{display:block;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#005cc5}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-code,.hljs-comment,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{font-weight:700;color:#005cc5}.hljs-bullet{color:#735c0f}.hljs-emphasis{font-style:italic;color:#24292e}.hljs-strong{font-weight:700;color:#24292e}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0}[data-doc-theme=dark] .hljs,[data-vc-theme=dark] .hljs{color:#c9d1d9;background:#0d1117}[data-doc-theme=dark] .hljs-doctag,[data-doc-theme=dark] .hljs-keyword,[data-doc-theme=dark] .hljs-meta .hljs-keyword,[data-doc-theme=dark] .hljs-template-tag,[data-doc-theme=dark] .hljs-template-variable,[data-doc-theme=dark] .hljs-type,[data-doc-theme=dark] .hljs-variable.language_,[data-vc-theme=dark] .hljs-doctag,[data-vc-theme=dark] .hljs-keyword,[data-vc-theme=dark] .hljs-meta .hljs-keyword,[data-vc-theme=dark] .hljs-template-tag,[data-vc-theme=dark] .hljs-template-variable,[data-vc-theme=dark] .hljs-type,[data-vc-theme=dark] .hljs-variable.language_{color:#ff7b72}[data-doc-theme=dark] .hljs-title,[data-doc-theme=dark] .hljs-title.class_,[data-doc-theme=dark] .hljs-title.function_,[data-vc-theme=dark] .hljs-title,[data-vc-theme=dark] .hljs-title.class_,[data-vc-theme=dark] .hljs-title.function_{color:#d2a8ff}[data-doc-theme=dark] .hljs-attr,[data-doc-theme=dark] .hljs-literal,[data-doc-theme=dark] .hljs-number,[data-doc-theme=dark] .hljs-variable,[data-vc-theme=dark] .hljs-attr,[data-vc-theme=dark] .hljs-literal,[data-vc-theme=dark] .hljs-number,[data-vc-theme=dark] .hljs-variable{color:#79c0ff}[data-doc-theme=dark] .hljs-regexp,[data-doc-theme=dark] .hljs-string,[data-vc-theme=dark] .hljs-regexp,[data-vc-theme=dark] .hljs-string{color:#a5d6ff}[data-doc-theme=dark] .hljs-code,[data-doc-theme=dark] .hljs-comment,[data-vc-theme=dark] .hljs-code,[data-vc-theme=dark] .hljs-comment{color:#8b949e}[data-doc-theme=dark] .hljs-name,[data-doc-theme=dark] .hljs-selector-tag,[data-vc-theme=dark] .hljs-name,[data-vc-theme=dark] .hljs-selector-tag{color:#7ee787}";
|
|
157
157
|
//#endregion
|
|
158
158
|
//#region packages/playground/src/core/code-preview/code-preview.scss?inline
|
|
159
|
-
var code_preview_default$1 = ".docs-code-preview{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;min-height:0;overflow:hidden;background:var(--docs-background-color-soft,var(--vc-background-color,#f7f8fa));border-radius:8px}.docs-code-preview__language{z-index:1;min-width:28px;padding:0 8px;font-size:12px;line-height:18px;white-space:nowrap;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-transition:opacity .15s ease;transition:opacity .15s ease}.docs-code-preview__copy,.docs-code-preview__language{position:absolute;top:6px;right:12px;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;height:28px;color:var(--docs-foreground-color-mute,var(--vc-color-dark-extralight,#71717a));-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.docs-code-preview__copy{z-index:2;width:28px;padding:0;pointer-events:none;cursor:pointer;background:var(--docs-background-color-soft,var(--vc-background-color,#f7f8fa));border:1px solid var(--docs-border-color,var(--vc-color-light-deeper,#d4d4d8));border-radius:8px;opacity:0;-webkit-transition:opacity .15s ease,background-color .15s ease;transition:opacity .15s ease,background-color .15s ease}.docs-code-preview__copy:hover{background:var(--docs-background-color,var(--vc-background-color-light,#fff))}.docs-code-preview__copy:focus-visible{pointer-events:auto;opacity:1}.docs-code-preview:has(.docs-code-preview__copy:focus-visible) .docs-code-preview__language,.docs-code-preview:hover .docs-code-preview__language{opacity:0}.docs-code-preview:has(.docs-code-preview__copy:focus-visible) .docs-code-preview__copy,.docs-code-preview:hover .docs-code-preview__copy{pointer-events:auto;opacity:1}.docs-code-
|
|
159
|
+
var code_preview_default$1 = ".docs-code-preview{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;min-height:0;overflow:hidden;background:var(--docs-background-color-soft,var(--vc-background-color,#f7f8fa));border-radius:8px}.docs-code-preview__language{z-index:1;min-width:28px;padding:0 8px;font-size:12px;line-height:18px;white-space:nowrap;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-transition:opacity .15s ease;transition:opacity .15s ease}.docs-code-preview__copy,.docs-code-preview__language{position:absolute;top:6px;right:12px;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;height:28px;color:var(--docs-foreground-color-mute,var(--vc-color-dark-extralight,#71717a));-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.docs-code-preview__copy{z-index:2;width:28px;padding:0;pointer-events:none;cursor:pointer;background:var(--docs-background-color-soft,var(--vc-background-color,#f7f8fa));border:1px solid var(--docs-border-color,var(--vc-color-light-deeper,#d4d4d8));border-radius:8px;opacity:0;-webkit-transition:opacity .15s ease,background-color .15s ease;transition:opacity .15s ease,background-color .15s ease}.docs-code-preview__copy:hover{background:var(--docs-background-color,var(--vc-background-color-light,#fff))}.docs-code-preview__copy:focus-visible{pointer-events:auto;opacity:1}.docs-code-preview:has(.docs-code-preview__copy:focus-visible) .docs-code-preview__language,.docs-code-preview:hover .docs-code-preview__language{opacity:0}.docs-code-preview:has(.docs-code-preview__copy:focus-visible) .docs-code-preview__copy,.docs-code-preview:hover .docs-code-preview__copy{pointer-events:auto;opacity:1}.docs-code-preview__scroller{width:100%;height:100%;min-width:0;min-height:0;-webkit-box-flex:1;-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto}.docs-code-preview__code{width:-webkit-max-content;width:-moz-max-content;width:max-content;margin:0}.docs-code-preview__code,.docs-code-preview__code code.hljs{min-width:100%;min-height:100%;overflow:visible;background:var(--docs-background-color-soft,var(--vc-background-color,#f7f8fa))}.docs-code-preview__code code.hljs{display:block;padding:12px 96px 12px 24px;-webkit-box-sizing:border-box;box-sizing:border-box}";
|
|
160
160
|
//#endregion
|
|
161
161
|
//#region packages/playground/src/core/code-preview/style.ts
|
|
162
162
|
var CODE_PREVIEW_STYLE_ID = "docs-code-preview-style";
|
|
@@ -228,11 +228,19 @@ var code_preview_default = /* @__PURE__ */ defineComponent({
|
|
|
228
228
|
"title",
|
|
229
229
|
"aria-label"
|
|
230
230
|
]),
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
231
|
+
createVNode(unref(Scroller), {
|
|
232
|
+
class: "docs-code-preview__scroller",
|
|
233
|
+
"auto-resize": true,
|
|
234
|
+
native: false,
|
|
235
|
+
"show-bar": true,
|
|
236
|
+
height: "100%"
|
|
237
|
+
}, {
|
|
238
|
+
default: withCtx(() => [createCommentVNode(" eslint-disable-next-line vue/no-v-html "), createElementVNode("pre", _hoisted_3$6, [createElementVNode("code", {
|
|
239
|
+
class: "hljs",
|
|
240
|
+
innerHTML: highlightedCode.value
|
|
241
|
+
}, null, 8, _hoisted_4$6)])]),
|
|
242
|
+
_: 1
|
|
243
|
+
})
|
|
236
244
|
]);
|
|
237
245
|
};
|
|
238
246
|
}
|
|
@@ -825,19 +833,120 @@ var resolvePlaygroundTitleId = (title, explicitId = "", isOccupied) => {
|
|
|
825
833
|
while (isOccupied(`${base}-${index}`)) index += 1;
|
|
826
834
|
return `${base}-${index}`;
|
|
827
835
|
};
|
|
836
|
+
//#endregion
|
|
837
|
+
//#region packages/playground/src/core/preview-scroll.ts
|
|
838
|
+
/** iframe 包装成功后挂在 `html` 上,供样式与 auto-height 识别。 */
|
|
839
|
+
var PREVIEW_SCROLL_HTML_CLASS = "docs-playground-preview-scroll";
|
|
840
|
+
/** Scroller 内容节点 class,auto-height 优先测量该节点。 */
|
|
841
|
+
var PREVIEW_SCROLL_CONTENT_CLASS = "docs-playground-preview-scroll__content";
|
|
842
|
+
/** 重评时先清掉 html class,避免 `await import` 期间仍套用 `height:100%`。 */
|
|
843
|
+
var PREVIEW_SCROLL_RESET_CODE = `document.documentElement.classList.remove("${PREVIEW_SCROLL_HTML_CLASS}");`;
|
|
844
|
+
/** 动态探测 `@deot/vc`;失败时为空对象,不阻断 DocsLink / 预览挂载。 */
|
|
845
|
+
var PREVIEW_SCROLLER_IMPORT_CODE = "const __docsVc=await import(\"@deot/vc\").catch(()=>({}))";
|
|
846
|
+
/**
|
|
847
|
+
* Vue 的 `mount` 闭包的是 `createApp(root)` 时的根组件,改 `app._component` 不会生效。
|
|
848
|
+
* 因此劫持 `app.mount`:等全部 useCode 注册完后,再 `createApp` 包一层 Scroller。
|
|
849
|
+
* 前导分号避免接在 `app.component(...)` 后被 ASI 解析成调用返回值。
|
|
850
|
+
*/
|
|
851
|
+
var PREVIEW_SCROLLER_USE_CODE = [
|
|
852
|
+
";(()=>{",
|
|
853
|
+
PREVIEW_SCROLL_RESET_CODE,
|
|
854
|
+
"const __DocsScroller=__docsVc&&__docsVc.Scroller;",
|
|
855
|
+
"if(!__DocsScroller)return;",
|
|
856
|
+
"const UserApp=app._component;",
|
|
857
|
+
"app.mount=(container,...rest)=>{",
|
|
858
|
+
"const next=_createApp({",
|
|
859
|
+
"name:\"DocsPreviewRoot\",",
|
|
860
|
+
"setup(){return()=>__docsH(__DocsScroller,{",
|
|
861
|
+
"height:\"100%\",",
|
|
862
|
+
"native:false,",
|
|
863
|
+
"autoResize:true,",
|
|
864
|
+
"showBar:true,",
|
|
865
|
+
`contentClass:"${PREVIEW_SCROLL_CONTENT_CLASS}"`,
|
|
866
|
+
"},{default:()=>__docsH(UserApp)})}",
|
|
867
|
+
"});",
|
|
868
|
+
"next.config.errorHandler=app.config.errorHandler;",
|
|
869
|
+
"if(app._context&&next._context){",
|
|
870
|
+
"if(app._context.components)Object.assign(next._context.components,app._context.components);",
|
|
871
|
+
"if(app._context.directives)Object.assign(next._context.directives,app._context.directives);",
|
|
872
|
+
"Object.assign(next._context.provides,app._context.provides);",
|
|
873
|
+
"next._context.mixins.push(...app._context.mixins);",
|
|
874
|
+
"}",
|
|
875
|
+
"window.__app__=next;",
|
|
876
|
+
`document.documentElement.classList.add("${PREVIEW_SCROLL_HTML_CLASS}");`,
|
|
877
|
+
"return next.mount(container,...rest)",
|
|
878
|
+
"}",
|
|
879
|
+
"})()"
|
|
880
|
+
].join("");
|
|
881
|
+
var PREVIEW_SCROLLER_STYLE = [
|
|
882
|
+
`html.${PREVIEW_SCROLL_HTML_CLASS},`,
|
|
883
|
+
`html.${PREVIEW_SCROLL_HTML_CLASS} body,`,
|
|
884
|
+
`html.${PREVIEW_SCROLL_HTML_CLASS} #app{`,
|
|
885
|
+
"height:100%;min-height:100%;margin:0;overflow:hidden",
|
|
886
|
+
"}",
|
|
887
|
+
`html.${PREVIEW_SCROLL_HTML_CLASS} #app>.vc-scroller,`,
|
|
888
|
+
`html.${PREVIEW_SCROLL_HTML_CLASS} #app>.vc-scroller>.vc-scroller__wrapper{`,
|
|
889
|
+
"height:100%;max-height:100%;box-sizing:border-box",
|
|
890
|
+
"}"
|
|
891
|
+
].join("");
|
|
828
892
|
var resolveSandboxContainer = (sandbox) => sandbox?.container ? unref(sandbox.container) : null;
|
|
893
|
+
var resolveScrollContent = (iframeDocument) => {
|
|
894
|
+
if (!iframeDocument.documentElement.classList.contains("docs-playground-preview-scroll")) return null;
|
|
895
|
+
return iframeDocument.querySelector(`.${PREVIEW_SCROLL_CONTENT_CLASS}`);
|
|
896
|
+
};
|
|
829
897
|
var useSandboxAutoHeight = (sandboxRef) => {
|
|
830
898
|
const height = ref(24);
|
|
831
899
|
let container = null;
|
|
832
900
|
let iframe = null;
|
|
833
901
|
let containerObserver = null;
|
|
834
902
|
let contentObserver = null;
|
|
903
|
+
let scrollMountObserver = null;
|
|
904
|
+
let observedScrollNode = null;
|
|
835
905
|
let frameId = 0;
|
|
836
906
|
const cancelMeasure = () => {
|
|
837
907
|
if (!frameId) return;
|
|
838
908
|
cancelAnimationFrame(frameId);
|
|
839
909
|
frameId = 0;
|
|
840
910
|
};
|
|
911
|
+
const measureDocumentContent = (iframeWindow, iframeDocument) => {
|
|
912
|
+
const { body, documentElement } = iframeDocument;
|
|
913
|
+
const bodyStyle = iframeWindow.getComputedStyle(body);
|
|
914
|
+
const bodyMargins = (Number.parseFloat(bodyStyle.marginTop) || 0) + (Number.parseFloat(bodyStyle.marginBottom) || 0);
|
|
915
|
+
const rootTop = documentElement.getBoundingClientRect().top;
|
|
916
|
+
const bodyRect = body.getBoundingClientRect();
|
|
917
|
+
const collapsedTop = Math.max(0, bodyRect.top - rootTop);
|
|
918
|
+
let childrenBottom = 0;
|
|
919
|
+
for (const child of body.children) {
|
|
920
|
+
if (iframeWindow.getComputedStyle(child).position === "fixed") continue;
|
|
921
|
+
const rect = child.getBoundingClientRect();
|
|
922
|
+
const marginBottom = Number.parseFloat(iframeWindow.getComputedStyle(child).marginBottom) || 0;
|
|
923
|
+
childrenBottom = Math.max(childrenBottom, rect.bottom + marginBottom - rootTop);
|
|
924
|
+
}
|
|
925
|
+
const scrollHeight = Math.max(body.scrollHeight, documentElement.scrollHeight);
|
|
926
|
+
const overflowingHeight = scrollHeight > (iframe?.clientHeight || 0) + 1 ? scrollHeight : 0;
|
|
927
|
+
return Math.ceil(Math.max(body.offsetHeight + bodyMargins + collapsedTop, bodyRect.height + bodyMargins + collapsedTop, childrenBottom, overflowingHeight));
|
|
928
|
+
};
|
|
929
|
+
const measureScrollContent = (scrollContent) => {
|
|
930
|
+
const contentStyle = scrollContent.ownerDocument.defaultView?.getComputedStyle(scrollContent);
|
|
931
|
+
const margins = contentStyle ? (Number.parseFloat(contentStyle.marginTop) || 0) + (Number.parseFloat(contentStyle.marginBottom) || 0) : 0;
|
|
932
|
+
let childrenBottom = 0;
|
|
933
|
+
const rootTop = scrollContent.getBoundingClientRect().top;
|
|
934
|
+
for (const child of scrollContent.children) {
|
|
935
|
+
const rect = child.getBoundingClientRect();
|
|
936
|
+
const marginBottom = Number.parseFloat(scrollContent.ownerDocument.defaultView?.getComputedStyle(child).marginBottom || "0") || 0;
|
|
937
|
+
childrenBottom = Math.max(childrenBottom, rect.bottom + marginBottom - rootTop);
|
|
938
|
+
}
|
|
939
|
+
return Math.ceil(Math.max(scrollContent.scrollHeight + margins, scrollContent.offsetHeight + margins, childrenBottom + margins));
|
|
940
|
+
};
|
|
941
|
+
const isPendingPreviewApp = (iframeDocument) => {
|
|
942
|
+
const app = iframeDocument.getElementById("app");
|
|
943
|
+
return app ? app.childElementCount === 0 : !!iframe?.srcdoc;
|
|
944
|
+
};
|
|
945
|
+
const releaseBootstrapHeight = (target) => {
|
|
946
|
+
nextTick(() => {
|
|
947
|
+
if (iframe === target) target.style.height = "100%";
|
|
948
|
+
});
|
|
949
|
+
};
|
|
841
950
|
const measure = () => {
|
|
842
951
|
frameId = 0;
|
|
843
952
|
if (!iframe) return;
|
|
@@ -845,23 +954,12 @@ var useSandboxAutoHeight = (sandboxRef) => {
|
|
|
845
954
|
const iframeWindow = iframe.contentWindow;
|
|
846
955
|
const iframeDocument = iframe.contentDocument;
|
|
847
956
|
if (!iframeWindow || !iframeDocument?.body) return;
|
|
848
|
-
const
|
|
849
|
-
|
|
850
|
-
const
|
|
851
|
-
const rootTop = documentElement.getBoundingClientRect().top;
|
|
852
|
-
const bodyRect = body.getBoundingClientRect();
|
|
853
|
-
const collapsedTop = Math.max(0, bodyRect.top - rootTop);
|
|
854
|
-
let childrenBottom = 0;
|
|
855
|
-
for (const child of body.children) {
|
|
856
|
-
const rect = child.getBoundingClientRect();
|
|
857
|
-
const marginBottom = Number.parseFloat(iframeWindow.getComputedStyle(child).marginBottom) || 0;
|
|
858
|
-
childrenBottom = Math.max(childrenBottom, rect.bottom + marginBottom - rootTop);
|
|
859
|
-
}
|
|
860
|
-
const scrollHeight = Math.max(body.scrollHeight, documentElement.scrollHeight);
|
|
861
|
-
const overflowingHeight = scrollHeight > iframe.clientHeight + 1 ? scrollHeight : 0;
|
|
862
|
-
const contentHeight = Math.ceil(Math.max(body.offsetHeight + bodyMargins + collapsedTop, bodyRect.height + bodyMargins + collapsedTop, childrenBottom, overflowingHeight));
|
|
957
|
+
const scrollContent = resolveScrollContent(iframeDocument);
|
|
958
|
+
if (!scrollContent && isPendingPreviewApp(iframeDocument)) return;
|
|
959
|
+
const contentHeight = scrollContent ? measureScrollContent(scrollContent) : measureDocumentContent(iframeWindow, iframeDocument);
|
|
863
960
|
const nextHeight = Math.max(contentHeight, 24);
|
|
864
961
|
if (height.value !== nextHeight) height.value = nextHeight;
|
|
962
|
+
releaseBootstrapHeight(iframe);
|
|
865
963
|
} catch {
|
|
866
964
|
if (height.value !== 24) height.value = 24;
|
|
867
965
|
}
|
|
@@ -873,6 +971,9 @@ var useSandboxAutoHeight = (sandboxRef) => {
|
|
|
873
971
|
const disconnectContent = () => {
|
|
874
972
|
contentObserver?.disconnect();
|
|
875
973
|
contentObserver = null;
|
|
974
|
+
scrollMountObserver?.disconnect();
|
|
975
|
+
scrollMountObserver = null;
|
|
976
|
+
observedScrollNode = null;
|
|
876
977
|
cancelMeasure();
|
|
877
978
|
};
|
|
878
979
|
const observeContent = () => {
|
|
@@ -890,7 +991,28 @@ var useSandboxAutoHeight = (sandboxRef) => {
|
|
|
890
991
|
observer.observe(iframeDocument.documentElement);
|
|
891
992
|
observer.observe(iframeDocument.body);
|
|
892
993
|
contentObserver = observer;
|
|
893
|
-
|
|
994
|
+
const attachScrollContent = (node) => {
|
|
995
|
+
if (!node || !contentObserver) return false;
|
|
996
|
+
if (observedScrollNode === node) return true;
|
|
997
|
+
if (observedScrollNode) contentObserver.unobserve(observedScrollNode);
|
|
998
|
+
observedScrollNode = node;
|
|
999
|
+
contentObserver.observe(node);
|
|
1000
|
+
return true;
|
|
1001
|
+
};
|
|
1002
|
+
const syncScrollContent = () => {
|
|
1003
|
+
attachScrollContent(resolveScrollContent(iframeDocument));
|
|
1004
|
+
scheduleMeasure();
|
|
1005
|
+
};
|
|
1006
|
+
scrollMountObserver = new MutationObserver(syncScrollContent);
|
|
1007
|
+
scrollMountObserver.observe(iframeDocument.documentElement, {
|
|
1008
|
+
attributes: true,
|
|
1009
|
+
attributeFilter: ["class"]
|
|
1010
|
+
});
|
|
1011
|
+
scrollMountObserver.observe(iframeDocument.body, {
|
|
1012
|
+
childList: true,
|
|
1013
|
+
subtree: true
|
|
1014
|
+
});
|
|
1015
|
+
syncScrollContent();
|
|
894
1016
|
} catch {
|
|
895
1017
|
if (height.value !== 24) height.value = 24;
|
|
896
1018
|
}
|
|
@@ -906,7 +1028,7 @@ var useSandboxAutoHeight = (sandboxRef) => {
|
|
|
906
1028
|
return;
|
|
907
1029
|
}
|
|
908
1030
|
iframe.addEventListener("load", handleIframeLoad);
|
|
909
|
-
iframe.style.height =
|
|
1031
|
+
iframe.style.height = `${Math.max(window.innerHeight, 24)}px`;
|
|
910
1032
|
observeContent();
|
|
911
1033
|
};
|
|
912
1034
|
const syncIframe = () => setIframe(container?.querySelector("iframe") || null);
|
|
@@ -934,6 +1056,12 @@ var useSandboxAutoHeight = (sandboxRef) => {
|
|
|
934
1056
|
});
|
|
935
1057
|
return height;
|
|
936
1058
|
};
|
|
1059
|
+
var resolvePreviewBoxHeight = (contentHeight, verticalInset = 0, borderWidth = 1) => {
|
|
1060
|
+
const content = Number.isFinite(contentHeight) ? Math.max(0, contentHeight) : 0;
|
|
1061
|
+
const inset = Number.isFinite(verticalInset) ? Math.max(0, verticalInset) : 0;
|
|
1062
|
+
const border = Number.isFinite(borderWidth) ? Math.max(0, borderWidth) : 1;
|
|
1063
|
+
return content + inset * 2 + border * 2;
|
|
1064
|
+
};
|
|
937
1065
|
var CLIPPING_OVERFLOW = /* @__PURE__ */ new Set([
|
|
938
1066
|
"auto",
|
|
939
1067
|
"scroll",
|
|
@@ -1250,6 +1378,73 @@ var useSandboxTheme = (sandboxRef) => {
|
|
|
1250
1378
|
});
|
|
1251
1379
|
};
|
|
1252
1380
|
//#endregion
|
|
1381
|
+
//#region packages/playground/src/core/runtime/height-bridge.ts
|
|
1382
|
+
/**
|
|
1383
|
+
* 只接收本宿主当前 iframe 的高度请求,应用重评时切换会话。
|
|
1384
|
+
* @param sandbox 预览容器。
|
|
1385
|
+
* @param maxHeight 当前可用高度,普通预览默认不限制。
|
|
1386
|
+
* @returns 所有有效请求的最大高度。
|
|
1387
|
+
*/
|
|
1388
|
+
function usePreviewHeightBridge(sandbox, maxHeight = () => Infinity) {
|
|
1389
|
+
const height = ref(0);
|
|
1390
|
+
const requests = /* @__PURE__ */ new Map();
|
|
1391
|
+
let source = null;
|
|
1392
|
+
let session = "";
|
|
1393
|
+
let disposed = false;
|
|
1394
|
+
const sync = () => {
|
|
1395
|
+
height.value = Math.max(0, ...requests.values());
|
|
1396
|
+
};
|
|
1397
|
+
const reset = () => {
|
|
1398
|
+
requests.clear();
|
|
1399
|
+
session = "";
|
|
1400
|
+
source = null;
|
|
1401
|
+
sync();
|
|
1402
|
+
};
|
|
1403
|
+
const handleMessage = async (event) => {
|
|
1404
|
+
const iframe = resolveSandboxContainer(sandbox.value)?.querySelector("iframe");
|
|
1405
|
+
const data = event.data;
|
|
1406
|
+
if (!iframe?.contentWindow || event.source !== iframe.contentWindow || data?.action !== "docs:height" || typeof data.session !== "string") return;
|
|
1407
|
+
if (data.operation === "start") {
|
|
1408
|
+
reset();
|
|
1409
|
+
source = iframe.contentWindow;
|
|
1410
|
+
session = data.session;
|
|
1411
|
+
return;
|
|
1412
|
+
}
|
|
1413
|
+
if (source !== iframe.contentWindow || session !== data.session) return;
|
|
1414
|
+
if (data.operation === "stop") {
|
|
1415
|
+
reset();
|
|
1416
|
+
return;
|
|
1417
|
+
}
|
|
1418
|
+
if (!Number.isSafeInteger(data.id) || data.id <= 0) return;
|
|
1419
|
+
if (data.operation === "release") {
|
|
1420
|
+
requests.delete(data.id);
|
|
1421
|
+
sync();
|
|
1422
|
+
return;
|
|
1423
|
+
}
|
|
1424
|
+
if (data.operation !== "enable" || !Number.isFinite(data.height) || data.height <= 0) return;
|
|
1425
|
+
const accepted = data.height <= maxHeight();
|
|
1426
|
+
if (accepted) requests.set(data.id, data.height);
|
|
1427
|
+
sync();
|
|
1428
|
+
const receiver = source;
|
|
1429
|
+
await nextTick();
|
|
1430
|
+
if (disposed || source !== receiver || session !== data.session) return;
|
|
1431
|
+
receiver?.postMessage({
|
|
1432
|
+
action: "docs:height:applied",
|
|
1433
|
+
session,
|
|
1434
|
+
id: data.id,
|
|
1435
|
+
accepted
|
|
1436
|
+
}, "*");
|
|
1437
|
+
};
|
|
1438
|
+
watch(() => resolveSandboxContainer(sandbox.value), reset, { flush: "sync" });
|
|
1439
|
+
if (typeof window !== "undefined") window.addEventListener("message", handleMessage);
|
|
1440
|
+
onBeforeUnmount(() => {
|
|
1441
|
+
disposed = true;
|
|
1442
|
+
if (typeof window !== "undefined") window.removeEventListener("message", handleMessage);
|
|
1443
|
+
reset();
|
|
1444
|
+
});
|
|
1445
|
+
return height;
|
|
1446
|
+
}
|
|
1447
|
+
//#endregion
|
|
1253
1448
|
//#region packages/playground/src/core/runtime/toolbar.vue?vue&type=script&setup=true&lang.ts
|
|
1254
1449
|
var _hoisted_1$3 = { class: "docs-playground__tools" };
|
|
1255
1450
|
var _hoisted_2$3 = {
|
|
@@ -1494,7 +1689,9 @@ var BUILTIN_IMPORT_ASSETS = {
|
|
|
1494
1689
|
"@deot/helper": "@deot/helper/dist/index.js",
|
|
1495
1690
|
"normalize-wheel": "normalize-wheel-es/dist/index.mjs",
|
|
1496
1691
|
"photoswipe": "photoswipe/dist/photoswipe.esm.js",
|
|
1497
|
-
"photoswipe/lightbox": "photoswipe/dist/photoswipe-lightbox.esm.js"
|
|
1692
|
+
"photoswipe/lightbox": "photoswipe/dist/photoswipe-lightbox.esm.js",
|
|
1693
|
+
"vue": "vue/dist/vue.runtime.esm-browser.js",
|
|
1694
|
+
"vue/server-renderer": "vue/dist/server-renderer.esm-browser.js"
|
|
1498
1695
|
};
|
|
1499
1696
|
var normalizeCdnURL = (cdnURL = DEFAULT_CDN_URL) => {
|
|
1500
1697
|
return cdnURL.trim().replace(/\/+$/u, "") || "https://cdn.jsdelivr.net/npm";
|
|
@@ -1505,9 +1702,7 @@ var SASS_CDN_URL = jsdelivrEsmURL("sass/+esm");
|
|
|
1505
1702
|
var cdnAsset = (cdnURL, asset) => cdnJoin(normalizeCdnURL(cdnURL), asset);
|
|
1506
1703
|
var createBuiltinImports = (cdnURL = DEFAULT_CDN_URL) => ({
|
|
1507
1704
|
...Object.fromEntries(Object.entries(BUILTIN_IMPORT_ASSETS).map(([specifier, asset]) => [specifier, cdnAsset(cdnURL, asset)])),
|
|
1508
|
-
"lodash-es": jsdelivrEsmURL("lodash-es/+esm")
|
|
1509
|
-
"vue": "https://play.vuejs.org/vue.runtime.esm-browser.js",
|
|
1510
|
-
"vue/server-renderer": "https://play.vuejs.org/server-renderer.esm-browser.js"
|
|
1705
|
+
"lodash-es": jsdelivrEsmURL("lodash-es/+esm")
|
|
1511
1706
|
});
|
|
1512
1707
|
var createBuiltinStyles = (cdnURL = DEFAULT_CDN_URL) => Object.fromEntries(PREVIEW_STYLE_ASSETS.map((asset) => [asset, cdnAsset(cdnURL, asset)]));
|
|
1513
1708
|
//#endregion
|
|
@@ -1587,6 +1782,227 @@ var clearPlaygroundMaps = () => {
|
|
|
1587
1782
|
].forEach((store) => store.set());
|
|
1588
1783
|
};
|
|
1589
1784
|
//#endregion
|
|
1785
|
+
//#region packages/playground/src/preview-service.ts
|
|
1786
|
+
/** Preview iframe 内的高度服务;class 会被序列化到 iframe 执行。 */
|
|
1787
|
+
var PlaygroundService = class {
|
|
1788
|
+
target;
|
|
1789
|
+
vue;
|
|
1790
|
+
session;
|
|
1791
|
+
/* istanbul ignore next -- class 会被序列化到没有覆盖率运行时的 iframe。 */
|
|
1792
|
+
sequence = 0;
|
|
1793
|
+
/* istanbul ignore next -- class 会被序列化到没有覆盖率运行时的 iframe。 */
|
|
1794
|
+
disposed = false;
|
|
1795
|
+
manual;
|
|
1796
|
+
/* istanbul ignore next -- class 会被序列化到没有覆盖率运行时的 iframe。 */
|
|
1797
|
+
requests = /* @__PURE__ */ new Set();
|
|
1798
|
+
/* istanbul ignore next -- class 会被序列化到没有覆盖率运行时的 iframe。 */
|
|
1799
|
+
owners = /* @__PURE__ */ new Set();
|
|
1800
|
+
/**
|
|
1801
|
+
* @param target 当前预览窗口。
|
|
1802
|
+
* @param vue 与预览应用共用的 Vue 实例。
|
|
1803
|
+
*/
|
|
1804
|
+
/* istanbul ignore next -- class 会被序列化到没有覆盖率运行时的 iframe。 */
|
|
1805
|
+
constructor(target, vue) {
|
|
1806
|
+
this.target = target;
|
|
1807
|
+
this.vue = vue;
|
|
1808
|
+
this.session = `${Date.now()}-${Math.random()}`;
|
|
1809
|
+
this.dispose = this.dispose.bind(this);
|
|
1810
|
+
this.post("start");
|
|
1811
|
+
this.target.addEventListener("pagehide", this.dispose);
|
|
1812
|
+
}
|
|
1813
|
+
/**
|
|
1814
|
+
* 申请手动临时高度;新请求会替换上一个手动请求。
|
|
1815
|
+
* @param height iframe 最小高度。
|
|
1816
|
+
* @returns iframe 是否在超时前应用目标高度。
|
|
1817
|
+
*/
|
|
1818
|
+
enable(height) {
|
|
1819
|
+
this.validateHeight(height);
|
|
1820
|
+
this.manual?.release();
|
|
1821
|
+
this.manual = this.createRequest(height);
|
|
1822
|
+
return this.manual.ready;
|
|
1823
|
+
}
|
|
1824
|
+
/** 释放手动临时高度,不影响 `run` 创建的请求。 */
|
|
1825
|
+
disable() {
|
|
1826
|
+
this.manual?.release();
|
|
1827
|
+
this.manual = void 0;
|
|
1828
|
+
}
|
|
1829
|
+
/**
|
|
1830
|
+
* 创建等待高度后执行的事件处理函数。
|
|
1831
|
+
* @param height iframe 最小高度。
|
|
1832
|
+
* @param optionsOrHandler 可见状态配置,或最后一个 handler。
|
|
1833
|
+
* @param lastHandler 使用配置时的最后一个 handler。
|
|
1834
|
+
* @returns 保留 handler 参数和结果的异步事件处理函数。
|
|
1835
|
+
*/
|
|
1836
|
+
run(height, optionsOrHandler, lastHandler) {
|
|
1837
|
+
this.validateHeight(height);
|
|
1838
|
+
if (optionsOrHandler === void 0) return (visible) => {
|
|
1839
|
+
if (visible) return this.enable(height);
|
|
1840
|
+
this.disable();
|
|
1841
|
+
return Promise.resolve(void 0);
|
|
1842
|
+
};
|
|
1843
|
+
const visible = (typeof optionsOrHandler === "function" ? {} : optionsOrHandler).visible;
|
|
1844
|
+
if (visible !== void 0 && !this.vue.isRef(visible) && typeof visible !== "function") throw new TypeError("Playground visible must be a ref or getter");
|
|
1845
|
+
const handler = typeof optionsOrHandler === "function" ? optionsOrHandler : lastHandler ?? (this.vue.isRef(visible) ? () => {
|
|
1846
|
+
visible.value = true;
|
|
1847
|
+
} : void 0);
|
|
1848
|
+
if (typeof handler !== "function") throw new TypeError("Playground run requires a handler");
|
|
1849
|
+
let ownerDisposed = false;
|
|
1850
|
+
let current;
|
|
1851
|
+
let pending;
|
|
1852
|
+
const disposeOwner = () => {
|
|
1853
|
+
ownerDisposed = true;
|
|
1854
|
+
current?.release();
|
|
1855
|
+
this.owners.delete(disposeOwner);
|
|
1856
|
+
};
|
|
1857
|
+
this.owners.add(disposeOwner);
|
|
1858
|
+
if (this.vue.getCurrentScope()) this.vue.onScopeDispose(disposeOwner);
|
|
1859
|
+
return (...args) => {
|
|
1860
|
+
if (this.disposed || ownerDisposed) return Promise.resolve(void 0);
|
|
1861
|
+
if (pending) return pending;
|
|
1862
|
+
const request = current = this.createRequest(height);
|
|
1863
|
+
let executionFinished = false;
|
|
1864
|
+
const unlock = () => {
|
|
1865
|
+
if (executionFinished && request.released && current === request) {
|
|
1866
|
+
pending = void 0;
|
|
1867
|
+
current = void 0;
|
|
1868
|
+
}
|
|
1869
|
+
};
|
|
1870
|
+
request.closed.then(unlock);
|
|
1871
|
+
const execution = (async () => {
|
|
1872
|
+
try {
|
|
1873
|
+
if (!await request.ready || ownerDisposed || this.disposed) return void 0;
|
|
1874
|
+
if (visible) request.watch(visible);
|
|
1875
|
+
const result = await handler(...args);
|
|
1876
|
+
if (!visible || !this.vue.toValue(visible)) request.release();
|
|
1877
|
+
return result;
|
|
1878
|
+
} catch (error) {
|
|
1879
|
+
request.release();
|
|
1880
|
+
throw error;
|
|
1881
|
+
} finally {
|
|
1882
|
+
executionFinished = true;
|
|
1883
|
+
unlock();
|
|
1884
|
+
}
|
|
1885
|
+
})();
|
|
1886
|
+
pending = execution;
|
|
1887
|
+
return execution;
|
|
1888
|
+
};
|
|
1889
|
+
}
|
|
1890
|
+
/** 释放当前预览应用持有的全部高度和监听。 */
|
|
1891
|
+
/* istanbul ignore next -- 注入测试会从序列化后的 iframe class 调用该方法。 */
|
|
1892
|
+
dispose() {
|
|
1893
|
+
if (this.disposed) return;
|
|
1894
|
+
this.disposed = true;
|
|
1895
|
+
for (const disposeOwner of this.owners) disposeOwner();
|
|
1896
|
+
for (const request of this.requests) request.release();
|
|
1897
|
+
this.post("stop");
|
|
1898
|
+
this.target.removeEventListener("pagehide", this.dispose);
|
|
1899
|
+
if (this.target.$docsPlayground === this) delete this.target.$docsPlayground;
|
|
1900
|
+
}
|
|
1901
|
+
/** @param height iframe 最小高度。 */
|
|
1902
|
+
validateHeight(height) {
|
|
1903
|
+
if (!Number.isFinite(height) || height <= 0) throw new TypeError("Playground height must be a positive finite number");
|
|
1904
|
+
}
|
|
1905
|
+
/**
|
|
1906
|
+
* @param operation 请求操作。
|
|
1907
|
+
* @param id 请求标识。
|
|
1908
|
+
* @param height iframe 最小高度。
|
|
1909
|
+
*/
|
|
1910
|
+
/* istanbul ignore next -- 构造和销毁时会从序列化后的 iframe class 调用该方法。 */
|
|
1911
|
+
post(operation, id = 0, height = 0) {
|
|
1912
|
+
this.target.parent.postMessage({
|
|
1913
|
+
action: "docs:height",
|
|
1914
|
+
session: this.session,
|
|
1915
|
+
operation,
|
|
1916
|
+
id,
|
|
1917
|
+
height
|
|
1918
|
+
}, "*");
|
|
1919
|
+
}
|
|
1920
|
+
/**
|
|
1921
|
+
* @param height iframe 最小高度。
|
|
1922
|
+
* @returns 内部等待与释放句柄。
|
|
1923
|
+
*/
|
|
1924
|
+
createRequest(height) {
|
|
1925
|
+
this.validateHeight(height);
|
|
1926
|
+
const id = ++this.sequence;
|
|
1927
|
+
let released = false;
|
|
1928
|
+
let settled = false;
|
|
1929
|
+
let frame = 0;
|
|
1930
|
+
let timer = 0;
|
|
1931
|
+
let stopWatch;
|
|
1932
|
+
let resolveReady;
|
|
1933
|
+
let resolveClosed;
|
|
1934
|
+
const ready = new Promise((resolve) => {
|
|
1935
|
+
resolveReady = resolve;
|
|
1936
|
+
});
|
|
1937
|
+
const closed = new Promise((resolve) => {
|
|
1938
|
+
resolveClosed = resolve;
|
|
1939
|
+
});
|
|
1940
|
+
const stopWaiting = () => {
|
|
1941
|
+
this.target.cancelAnimationFrame(frame);
|
|
1942
|
+
if (timer) {
|
|
1943
|
+
this.target.clearTimeout(timer);
|
|
1944
|
+
timer = 0;
|
|
1945
|
+
}
|
|
1946
|
+
this.target.removeEventListener("message", onMessage);
|
|
1947
|
+
};
|
|
1948
|
+
const release = () => {
|
|
1949
|
+
if (released) return;
|
|
1950
|
+
released = true;
|
|
1951
|
+
stopWaiting();
|
|
1952
|
+
stopWatch?.();
|
|
1953
|
+
resolveReady(false);
|
|
1954
|
+
resolveClosed();
|
|
1955
|
+
this.requests.delete(request);
|
|
1956
|
+
this.post("release", id);
|
|
1957
|
+
};
|
|
1958
|
+
const check = () => {
|
|
1959
|
+
if (released) return;
|
|
1960
|
+
if (this.target.innerHeight >= height) {
|
|
1961
|
+
settled = true;
|
|
1962
|
+
stopWaiting();
|
|
1963
|
+
resolveReady(true);
|
|
1964
|
+
} else frame = this.target.requestAnimationFrame(check);
|
|
1965
|
+
};
|
|
1966
|
+
const onMessage = (event) => {
|
|
1967
|
+
const data = event.data;
|
|
1968
|
+
if (event.source !== this.target.parent || data?.action !== "docs:height:applied" || data.session !== this.session || data.id !== id || settled) return;
|
|
1969
|
+
if (!data.accepted) release();
|
|
1970
|
+
else check();
|
|
1971
|
+
};
|
|
1972
|
+
const request = {
|
|
1973
|
+
ready,
|
|
1974
|
+
closed,
|
|
1975
|
+
get released() {
|
|
1976
|
+
return released;
|
|
1977
|
+
},
|
|
1978
|
+
release,
|
|
1979
|
+
watch: (visible) => {
|
|
1980
|
+
stopWatch = this.vue.watch(() => this.vue.toValue(visible), (value) => {
|
|
1981
|
+
if (!value) release();
|
|
1982
|
+
}, { flush: "sync" });
|
|
1983
|
+
}
|
|
1984
|
+
};
|
|
1985
|
+
this.requests.add(request);
|
|
1986
|
+
if (this.disposed) release();
|
|
1987
|
+
else {
|
|
1988
|
+
this.target.addEventListener("message", onMessage);
|
|
1989
|
+
timer = this.target.setTimeout(() => {
|
|
1990
|
+
timer = 0;
|
|
1991
|
+
release();
|
|
1992
|
+
}, 2e3);
|
|
1993
|
+
this.post("enable", id, height);
|
|
1994
|
+
}
|
|
1995
|
+
return request;
|
|
1996
|
+
}
|
|
1997
|
+
};
|
|
1998
|
+
var PREVIEW_SERVICE_IMPORT_CODE = "import * as __docsPreviewVue from \"vue\"";
|
|
1999
|
+
var PREVIEW_SERVICE_USE_CODE = [
|
|
2000
|
+
`;const __docsPlayground=new (${PlaygroundService.toString()})(window,__docsPreviewVue);`,
|
|
2001
|
+
"app.provide(\"docs:playground\",__docsPlayground);",
|
|
2002
|
+
"window.$docsPlayground=__docsPlayground;",
|
|
2003
|
+
"app.mixin({beforeUnmount(){if(this===this.$root)__docsPlayground.dispose()}});"
|
|
2004
|
+
].join("");
|
|
2005
|
+
//#endregion
|
|
1590
2006
|
//#region packages/playground/src/core/scss.ts
|
|
1591
2007
|
var SCHEME = "docs-playground";
|
|
1592
2008
|
var STYLE_EXTS = [".scss", ".sass"];
|
|
@@ -1803,6 +2219,7 @@ var bindPlaygroundScss = (store) => {
|
|
|
1803
2219
|
//#region packages/playground/src/core/store.ts
|
|
1804
2220
|
var DOCS_LINK_IMPORT_CODE = "import { h as __docsH } from \"vue\"";
|
|
1805
2221
|
var DOCS_LINK_USE_CODE = [
|
|
2222
|
+
PREVIEW_SCROLL_RESET_CODE,
|
|
1806
2223
|
"app.component(\"DocsLink\",{",
|
|
1807
2224
|
"props:{to:{type:String,default:\"\"}},",
|
|
1808
2225
|
"setup(props,{slots}){return()=>__docsH(\"a\",{",
|
|
@@ -1819,26 +2236,32 @@ var escapeHtmlAttr = (value) => value.replace(/&/gu, "&").replace(/"/gu, "&q
|
|
|
1819
2236
|
* `--vc-background-color-light` 不同,否则会出现色带割裂。
|
|
1820
2237
|
*/
|
|
1821
2238
|
var PLAYGROUND_RUNTIME_CANVAS_BACKGROUND = "var(--vc-background-color-light, var(--docs-background-color, #fff))";
|
|
1822
|
-
var createRuntimePreviewOptions = (cdnURL = DEFAULT_CDN_URL) => {
|
|
2239
|
+
var createRuntimePreviewOptions = (cdnURL = DEFAULT_CDN_URL, options = {}) => {
|
|
2240
|
+
const previewScroller = options.previewScroller === true;
|
|
2241
|
+
const hrefs = Object.values({
|
|
2242
|
+
...createBuiltinStyles(cdnURL),
|
|
2243
|
+
...getPlaygroundSiteStyles(),
|
|
2244
|
+
...getPlaygroundStyleOverrides()
|
|
2245
|
+
});
|
|
2246
|
+
const styleBlocks = [
|
|
2247
|
+
`html,body{height:auto;min-height:0;background:${PLAYGROUND_RUNTIME_CANVAS_BACKGROUND}}`,
|
|
2248
|
+
"body{color:var(--vc-foreground-color,#080f20)}",
|
|
2249
|
+
...previewScroller ? [PREVIEW_SCROLLER_STYLE] : []
|
|
2250
|
+
];
|
|
1823
2251
|
return {
|
|
1824
2252
|
showRuntimeError: false,
|
|
1825
2253
|
showRuntimeWarning: false,
|
|
1826
2254
|
headHTML: [
|
|
1827
2255
|
SANDBOX_RUNTIME_ERROR_CAPTURE_HTML,
|
|
1828
2256
|
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">",
|
|
1829
|
-
...
|
|
1830
|
-
...createBuiltinStyles(cdnURL),
|
|
1831
|
-
...getPlaygroundSiteStyles(),
|
|
1832
|
-
...getPlaygroundStyleOverrides()
|
|
1833
|
-
}).map((href) => `<link rel="stylesheet" href="${escapeHtmlAttr(href)}">`),
|
|
2257
|
+
...hrefs.map((href) => `<link rel="stylesheet" href="${escapeHtmlAttr(href)}">`),
|
|
1834
2258
|
"<style>",
|
|
1835
|
-
|
|
1836
|
-
"body{color:var(--vc-foreground-color,#080f20)}",
|
|
2259
|
+
...styleBlocks,
|
|
1837
2260
|
"</style>"
|
|
1838
2261
|
].join("\n"),
|
|
1839
2262
|
customCode: {
|
|
1840
|
-
importCode: DOCS_LINK_IMPORT_CODE
|
|
1841
|
-
useCode: DOCS_LINK_USE_CODE
|
|
2263
|
+
importCode: `${DOCS_LINK_IMPORT_CODE}\n${PREVIEW_SERVICE_IMPORT_CODE}`,
|
|
2264
|
+
useCode: `${DOCS_LINK_USE_CODE}\n${PREVIEW_SERVICE_USE_CODE}`
|
|
1842
2265
|
}
|
|
1843
2266
|
};
|
|
1844
2267
|
};
|
|
@@ -1919,6 +2342,8 @@ var Alone = new Portal(/* @__PURE__ */ defineComponent({
|
|
|
1919
2342
|
const { t } = useLocale();
|
|
1920
2343
|
const currentViewport = ref(props.viewport);
|
|
1921
2344
|
const sandboxRef = ref(null);
|
|
2345
|
+
const availableHeight = () => Math.max(0, getWindowInnerSize().height - 40 - 44);
|
|
2346
|
+
const temporaryHeight = usePreviewHeightBridge(sandboxRef, availableHeight);
|
|
1922
2347
|
const sandboxKey = ref(0);
|
|
1923
2348
|
const layoutTick = ref(0);
|
|
1924
2349
|
const runtimeError = useSandboxRuntimeErrorGuard(sandboxRef);
|
|
@@ -1930,7 +2355,16 @@ var Alone = new Portal(/* @__PURE__ */ defineComponent({
|
|
|
1930
2355
|
});
|
|
1931
2356
|
const layout = computed(() => {
|
|
1932
2357
|
layoutTick.value;
|
|
1933
|
-
|
|
2358
|
+
const base = resolvePopupLayout(currentViewport.value);
|
|
2359
|
+
if (!temporaryHeight.value) return base;
|
|
2360
|
+
const canvasHeight = Math.min(availableHeight(), Math.max(base.canvasHeight, temporaryHeight.value));
|
|
2361
|
+
const shellHeight = Math.max(base.shellHeight, canvasHeight + 44);
|
|
2362
|
+
return {
|
|
2363
|
+
...base,
|
|
2364
|
+
canvasHeight,
|
|
2365
|
+
shellHeight,
|
|
2366
|
+
bodyHeight: shellHeight - 44
|
|
2367
|
+
};
|
|
1934
2368
|
});
|
|
1935
2369
|
const shellStyle = computed(() => ({
|
|
1936
2370
|
width: `${layout.value.shellWidth}px`,
|
|
@@ -2091,6 +2525,10 @@ var runtime_default = /* @__PURE__ */ defineComponent({
|
|
|
2091
2525
|
options: {},
|
|
2092
2526
|
previewInset: { default: 10 },
|
|
2093
2527
|
previewOptions: {},
|
|
2528
|
+
previewScroller: {
|
|
2529
|
+
type: Boolean,
|
|
2530
|
+
default: false
|
|
2531
|
+
},
|
|
2094
2532
|
styleless: {
|
|
2095
2533
|
type: Boolean,
|
|
2096
2534
|
default: false
|
|
@@ -2124,7 +2562,7 @@ var runtime_default = /* @__PURE__ */ defineComponent({
|
|
|
2124
2562
|
const emit = __emit;
|
|
2125
2563
|
const joinCode = (...values) => values.filter(Boolean).join("\n");
|
|
2126
2564
|
const mergePreviewOptions = (extraHeadHTML) => {
|
|
2127
|
-
const runtimePreviewOptions = createRuntimePreviewOptions(props.options.cdnURL);
|
|
2565
|
+
const runtimePreviewOptions = createRuntimePreviewOptions(props.options.cdnURL, { previewScroller: props.previewScroller });
|
|
2128
2566
|
return {
|
|
2129
2567
|
...runtimePreviewOptions,
|
|
2130
2568
|
...props.previewOptions,
|
|
@@ -2134,8 +2572,8 @@ var runtime_default = /* @__PURE__ */ defineComponent({
|
|
|
2134
2572
|
extraHeadHTML
|
|
2135
2573
|
].filter(Boolean).join("\n"),
|
|
2136
2574
|
customCode: {
|
|
2137
|
-
importCode: joinCode(runtimePreviewOptions.customCode?.importCode, props.previewOptions?.customCode?.importCode),
|
|
2138
|
-
useCode: joinCode(runtimePreviewOptions.customCode?.useCode, props.previewOptions?.customCode?.useCode)
|
|
2575
|
+
importCode: joinCode(runtimePreviewOptions.customCode?.importCode, props.previewOptions?.customCode?.importCode, props.previewScroller ? PREVIEW_SCROLL_RESET_CODE : void 0, props.previewScroller ? PREVIEW_SCROLLER_IMPORT_CODE : void 0),
|
|
2576
|
+
useCode: joinCode(runtimePreviewOptions.customCode?.useCode, props.previewOptions?.customCode?.useCode, props.previewScroller ? PREVIEW_SCROLLER_USE_CODE : void 0)
|
|
2139
2577
|
}
|
|
2140
2578
|
};
|
|
2141
2579
|
};
|
|
@@ -2151,6 +2589,7 @@ var runtime_default = /* @__PURE__ */ defineComponent({
|
|
|
2151
2589
|
const copyValue = computed(() => props.files[props.entry] || "");
|
|
2152
2590
|
const store = createRuntimeStore(props.files, props.entry, props.options);
|
|
2153
2591
|
const sandboxRef = ref(null);
|
|
2592
|
+
const temporaryHeight = usePreviewHeightBridge(sandboxRef);
|
|
2154
2593
|
const sandboxKey = ref(0);
|
|
2155
2594
|
const runtimeHeight = useSandboxAutoHeight(sandboxRef);
|
|
2156
2595
|
const runtimeError = useSandboxRuntimeErrorGuard(sandboxRef);
|
|
@@ -2178,13 +2617,21 @@ var runtime_default = /* @__PURE__ */ defineComponent({
|
|
|
2178
2617
|
const error = root.querySelector(".docs-playground__runtime-error");
|
|
2179
2618
|
return (header instanceof HTMLElement ? header.offsetHeight : 0) + (error instanceof HTMLElement ? error.offsetHeight : 0);
|
|
2180
2619
|
};
|
|
2620
|
+
const normalizedPreviewInset = computed(() => {
|
|
2621
|
+
const value = props.previewInset;
|
|
2622
|
+
if (typeof value === "number") return Number.isFinite(value) && value >= 0 ? [value, value] : [10, 10];
|
|
2623
|
+
if (Array.isArray(value) && value.length === 2 && value.every((item) => typeof item === "number" && Number.isFinite(item) && item >= 0)) return [value[0], value[1]];
|
|
2624
|
+
return [10, 10];
|
|
2625
|
+
});
|
|
2181
2626
|
const measureExpandedPreviewHeight = () => {
|
|
2182
2627
|
if (typeof window === "undefined") return runtimeHeight.value;
|
|
2183
2628
|
const chromeHeight = measurePreviewChromeHeight();
|
|
2629
|
+
const viewport = getVisibleViewportRect(runtimeRoot.value);
|
|
2630
|
+
const [vertical] = normalizedPreviewInset.value;
|
|
2184
2631
|
return resolveExpandedPreviewHeight(true, resolveRemainingPreviewHeight({
|
|
2185
|
-
viewportHeight:
|
|
2632
|
+
viewportHeight: viewport.height,
|
|
2186
2633
|
chromeHeight
|
|
2187
|
-
}));
|
|
2634
|
+
}) - vertical * 2 - 2);
|
|
2188
2635
|
};
|
|
2189
2636
|
const syncFrozenExpandedHeight = () => {
|
|
2190
2637
|
if (!previewExpanded.value || props.expandable !== true) return;
|
|
@@ -2196,13 +2643,14 @@ var runtime_default = /* @__PURE__ */ defineComponent({
|
|
|
2196
2643
|
}
|
|
2197
2644
|
const canExpandPreview = computed(() => !props.styleless && isPlaygroundExpandable(props.expandable));
|
|
2198
2645
|
const expandLabel = computed(() => t(previewExpanded.value ? "playground.runtime.collapsePreview" : "playground.runtime.expandPreview"));
|
|
2199
|
-
const
|
|
2646
|
+
const baseViewportHeight = computed(() => {
|
|
2200
2647
|
if (previewExpanded.value && props.expandable === true) return frozenExpandedHeight.value;
|
|
2201
2648
|
if (previewExpanded.value && isPlaygroundExpandable(props.expandable)) return resolveExpandedPreviewHeight(props.expandable, 0);
|
|
2202
2649
|
const fixedHeight = getViewportHeight(props.viewport);
|
|
2203
2650
|
if (fixedHeight) return fixedHeight;
|
|
2204
2651
|
return runtimeHeight.value;
|
|
2205
2652
|
});
|
|
2653
|
+
const desiredViewportHeight = computed(() => Math.max(baseViewportHeight.value, temporaryHeight.value));
|
|
2206
2654
|
const scrollExpandedPreviewIntoView = () => {
|
|
2207
2655
|
scrollPlaygroundToViewportStart(runtimeRoot.value);
|
|
2208
2656
|
};
|
|
@@ -2224,16 +2672,10 @@ var runtime_default = /* @__PURE__ */ defineComponent({
|
|
|
2224
2672
|
frozenExpandedHeight.value = 0;
|
|
2225
2673
|
}
|
|
2226
2674
|
});
|
|
2227
|
-
const normalizedPreviewInset = computed(() => {
|
|
2228
|
-
const value = props.previewInset;
|
|
2229
|
-
if (typeof value === "number") return Number.isFinite(value) && value >= 0 ? [value, value] : [10, 10];
|
|
2230
|
-
if (Array.isArray(value) && value.length === 2 && value.every((item) => typeof item === "number" && Number.isFinite(item) && item >= 0)) return [value[0], value[1]];
|
|
2231
|
-
return [10, 10];
|
|
2232
|
-
});
|
|
2233
2675
|
const previewStyle = computed(() => {
|
|
2234
2676
|
const [vertical, horizontal] = normalizedPreviewInset.value;
|
|
2235
2677
|
return {
|
|
2236
|
-
height: `${desiredViewportHeight.value
|
|
2678
|
+
height: `${resolvePreviewBoxHeight(desiredViewportHeight.value, vertical)}px`,
|
|
2237
2679
|
padding: vertical === horizontal ? `${vertical}px` : `${vertical}px ${horizontal}px`,
|
|
2238
2680
|
background: PLAYGROUND_RUNTIME_CANVAS_BACKGROUND
|
|
2239
2681
|
};
|
|
@@ -2446,6 +2888,10 @@ var playground_default = /* @__PURE__ */ defineComponent({
|
|
|
2446
2888
|
expandable: { type: [Boolean, Number] },
|
|
2447
2889
|
title: { default: "" },
|
|
2448
2890
|
id: { default: "" },
|
|
2891
|
+
previewScroller: {
|
|
2892
|
+
type: Boolean,
|
|
2893
|
+
default: false
|
|
2894
|
+
},
|
|
2449
2895
|
previewOptions: {},
|
|
2450
2896
|
locale: {}
|
|
2451
2897
|
},
|
|
@@ -2603,6 +3049,7 @@ var playground_default = /* @__PURE__ */ defineComponent({
|
|
|
2603
3049
|
options: __props.options,
|
|
2604
3050
|
"preview-options": __props.previewOptions,
|
|
2605
3051
|
"preview-inset": __props.previewInset,
|
|
3052
|
+
"preview-scroller": __props.previewScroller,
|
|
2606
3053
|
expandable: __props.expandable,
|
|
2607
3054
|
styleless: true,
|
|
2608
3055
|
title: __props.title,
|
|
@@ -2618,6 +3065,7 @@ var playground_default = /* @__PURE__ */ defineComponent({
|
|
|
2618
3065
|
"options",
|
|
2619
3066
|
"preview-options",
|
|
2620
3067
|
"preview-inset",
|
|
3068
|
+
"preview-scroller",
|
|
2621
3069
|
"expandable",
|
|
2622
3070
|
"title",
|
|
2623
3071
|
"id",
|
|
@@ -2670,6 +3118,7 @@ var playground_default = /* @__PURE__ */ defineComponent({
|
|
|
2670
3118
|
options: __props.options,
|
|
2671
3119
|
"preview-options": __props.previewOptions,
|
|
2672
3120
|
"preview-inset": __props.previewInset,
|
|
3121
|
+
"preview-scroller": __props.previewScroller,
|
|
2673
3122
|
expandable: __props.expandable,
|
|
2674
3123
|
"hide-chrome": true,
|
|
2675
3124
|
title: __props.title,
|
|
@@ -2687,6 +3136,7 @@ var playground_default = /* @__PURE__ */ defineComponent({
|
|
|
2687
3136
|
"options",
|
|
2688
3137
|
"preview-options",
|
|
2689
3138
|
"preview-inset",
|
|
3139
|
+
"preview-scroller",
|
|
2690
3140
|
"expandable",
|
|
2691
3141
|
"title",
|
|
2692
3142
|
"id",
|
|
@@ -2715,4 +3165,4 @@ var playground_default = /* @__PURE__ */ defineComponent({
|
|
|
2715
3165
|
}
|
|
2716
3166
|
});
|
|
2717
3167
|
//#endregion
|
|
2718
|
-
export { code_preview_default as CodePreview, DEFAULT_CDN_URL, Editor, playground_default as Playground, applyPlaygroundImportMapOverride, applyPlaygroundStyleOverride, clearPlaygroundMaps, createBuiltinImports, createBuiltinStyles, createRuntimePreviewOptions, getPlaygroundImportMapOverrides, getPlaygroundSiteModules, getPlaygroundSiteStyles, getPlaygroundStyleOverrides, highlightCode, highlightCodeByLanguage, isSafePlaygroundHref, normalizeCdnURL, registerVueHighlight, removePlaygroundImportMapOverride, removePlaygroundStyleOverride, resolveHighlightLanguage, resolvePlaygroundTitleId, setPlaygroundImportMapOverrides, setPlaygroundSiteModules, setPlaygroundSiteStyles, setPlaygroundStyleOverrides, slugifyPlaygroundTitle, vueHighlight };
|
|
3168
|
+
export { code_preview_default as CodePreview, DEFAULT_CDN_URL, Editor, PREVIEW_SCROLLER_USE_CODE, PREVIEW_SCROLL_CONTENT_CLASS, PREVIEW_SCROLL_HTML_CLASS, playground_default as Playground, PlaygroundService, applyPlaygroundImportMapOverride, applyPlaygroundStyleOverride, clearPlaygroundMaps, createBuiltinImports, createBuiltinStyles, createRuntimePreviewOptions, getPlaygroundImportMapOverrides, getPlaygroundSiteModules, getPlaygroundSiteStyles, getPlaygroundStyleOverrides, highlightCode, highlightCodeByLanguage, isSafePlaygroundHref, normalizeCdnURL, registerVueHighlight, removePlaygroundImportMapOverride, removePlaygroundStyleOverride, resolveHighlightLanguage, resolvePlaygroundTitleId, setPlaygroundImportMapOverrides, setPlaygroundSiteModules, setPlaygroundSiteStyles, setPlaygroundStyleOverrides, slugifyPlaygroundTitle, vueHighlight };
|