@deot/docs-playground 1.0.10 → 1.1.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.
package/dist/index.cjs CHANGED
@@ -140,7 +140,7 @@ var PLAYGROUND_ICONS = {
140
140
  //#endregion
141
141
  //#region packages/playground/src/icon/icon.vue?vue&type=script&setup=true&lang.ts
142
142
  var _hoisted_1$7 = ["fill", "stroke"];
143
- var _hoisted_2$6 = ["d"];
143
+ var _hoisted_2$7 = ["d"];
144
144
  //#endregion
145
145
  //#region packages/playground/src/icon/icon.vue
146
146
  var icon_default = /* @__PURE__ */ (0, vue.defineComponent)({
@@ -171,7 +171,7 @@ var icon_default = /* @__PURE__ */ (0, vue.defineComponent)({
171
171
  "stroke-linecap": "round",
172
172
  "stroke-linejoin": "round",
173
173
  "aria-hidden": "true"
174
- }, [(0, vue.createElementVNode)("path", { d: icon.value.path }, null, 8, _hoisted_2$6)], 12, _hoisted_1$7);
174
+ }, [(0, vue.createElementVNode)("path", { d: icon.value.path }, null, 8, _hoisted_2$7)], 12, _hoisted_1$7);
175
175
  };
176
176
  }
177
177
  });
@@ -198,9 +198,9 @@ var ensureCodePreviewStyle = () => {
198
198
  //#endregion
199
199
  //#region packages/playground/src/core/code-preview/code-preview.vue?vue&type=script&setup=true&lang.ts
200
200
  var _hoisted_1$6 = { class: "docs-code-preview" };
201
- var _hoisted_2$5 = ["title"];
202
- var _hoisted_3$5 = { class: "docs-code-preview__code" };
203
- var _hoisted_4$5 = ["innerHTML"];
201
+ var _hoisted_2$6 = ["title"];
202
+ var _hoisted_3$6 = { class: "docs-code-preview__code" };
203
+ var _hoisted_4$6 = ["innerHTML"];
204
204
  //#endregion
205
205
  //#region packages/playground/src/core/code-preview/code-preview.vue
206
206
  var code_preview_default = /* @__PURE__ */ (0, vue.defineComponent)({
@@ -236,7 +236,7 @@ var code_preview_default = /* @__PURE__ */ (0, vue.defineComponent)({
236
236
  key: 0,
237
237
  class: "docs-code-preview__language",
238
238
  title: languageLabel.value
239
- }, (0, vue.toDisplayString)(languageLabel.value), 9, _hoisted_2$5)) : (0, vue.createCommentVNode)("v-if", true),
239
+ }, (0, vue.toDisplayString)(languageLabel.value), 9, _hoisted_2$6)) : (0, vue.createCommentVNode)("v-if", true),
240
240
  (0, vue.createVNode)((0, vue.unref)(_deot_vc.Clipboard), {
241
241
  class: "docs-code-preview__copy",
242
242
  value: __props.code,
@@ -253,53 +253,23 @@ var code_preview_default = /* @__PURE__ */ (0, vue.defineComponent)({
253
253
  "aria-label"
254
254
  ]),
255
255
  (0, vue.createCommentVNode)(" eslint-disable-next-line vue/no-v-html "),
256
- (0, vue.createElementVNode)("pre", _hoisted_3$5, [(0, vue.createElementVNode)("code", {
256
+ (0, vue.createElementVNode)("pre", _hoisted_3$6, [(0, vue.createElementVNode)("code", {
257
257
  class: "hljs",
258
258
  innerHTML: highlightedCode.value
259
- }, null, 8, _hoisted_4$5)])
259
+ }, null, 8, _hoisted_4$6)])
260
260
  ]);
261
261
  };
262
262
  }
263
263
  });
264
264
  //#endregion
265
- //#region packages/playground/src/utils.ts
266
- /**
267
- * 比较两组 playground 文件是否完全一致。
268
- * @param left 左侧文件表。
269
- * @param right 右侧文件表。
270
- * @returns 键集合与各文件内容是否都相同。
271
- */
272
- var filesEqual = (left, right) => {
273
- const leftKeys = Object.keys(left);
274
- const rightKeys = Object.keys(right);
275
- return leftKeys.length === rightKeys.length && leftKeys.every((key) => left[key] === right[key]);
276
- };
277
- /**
278
- * 视图切换条使用的文案键。
279
- * @param view 当前预览视图。
280
- * @returns locale 消息键。
281
- */
282
- var playgroundViewMessage = (view) => view === "runtime" ? "playground.runtime.preview" : "playground.runtime.files";
283
- //#endregion
284
265
  //#region packages/playground/src/core/files-preview/files-preview.vue?vue&type=script&setup=true&lang.ts
285
266
  var _hoisted_1$5 = { class: "docs-playground-files" };
286
- var _hoisted_2$4 = { class: "docs-playground-files__toolbar" };
287
- var _hoisted_3$4 = ["data-filename", "onClick"];
288
- var _hoisted_4$4 = {
267
+ var _hoisted_2$5 = { class: "docs-playground-files__tabs-row" };
268
+ var _hoisted_3$5 = ["data-filename", "onClick"];
269
+ var _hoisted_4$5 = {
289
270
  key: 0,
290
271
  class: "docs-playground-files__entry"
291
272
  };
292
- var _hoisted_5$4 = { class: "docs-playground-files__actions" };
293
- var _hoisted_6$3 = {
294
- key: 0,
295
- class: "docs-playground__views docs-playground__views--files"
296
- };
297
- var _hoisted_7$2 = [
298
- "title",
299
- "aria-label",
300
- "aria-pressed",
301
- "onClick"
302
- ];
303
273
  //#endregion
304
274
  //#region packages/playground/src/core/files-preview/files-preview.vue
305
275
  var files_preview_default = /* @__PURE__ */ (0, vue.defineComponent)({
@@ -311,28 +281,26 @@ var files_preview_default = /* @__PURE__ */ (0, vue.defineComponent)({
311
281
  activeView: {},
312
282
  activeFilename: {}
313
283
  },
314
- emits: ["active-change", "view-change"],
284
+ emits: ["active-change"],
315
285
  setup(__props, { emit: __emit }) {
316
286
  const props = __props;
317
287
  const { t } = (0, _deot_docs_locale.useLocale)();
318
- const getViewText = (view) => t(playgroundViewMessage(view));
319
288
  const emit = __emit;
320
289
  const filenames = (0, vue.computed)(() => Object.keys(props.files));
321
290
  const activeCode = (0, vue.computed)(() => props.files[props.activeFilename] || "");
322
291
  const handleActive = (filename) => {
323
292
  if (filename !== props.activeFilename) emit("active-change", filename);
324
293
  };
325
- const handleView = (view) => emit("view-change", view);
326
294
  return (_ctx, _cache) => {
327
- return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$5, [(0, vue.createElementVNode)("div", _hoisted_2$4, [(0, vue.createVNode)((0, vue.unref)(_deot_vc.Scroller), {
295
+ return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$5, [(0, vue.createElementVNode)("div", _hoisted_2$5, [(0, vue.createVNode)((0, vue.unref)(_deot_vc.Scroller), {
328
296
  class: "docs-playground-files__scroller",
329
297
  "auto-resize": true,
330
298
  native: false,
331
299
  "show-bar": true,
332
- height: "44",
300
+ height: "40",
333
301
  "content-class": "docs-playground-files__tabs",
334
- "content-style": "height: 44px; overflow: hidden;",
335
- "wrapper-style": "height: 44px; overflow-x: auto; overflow-y: hidden;"
302
+ "content-style": "height: 40px; overflow: hidden;",
303
+ "wrapper-style": "height: 40px; overflow-x: auto; overflow-y: hidden;"
336
304
  }, {
337
305
  default: (0, vue.withCtx)(() => [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(filenames.value, (filename) => {
338
306
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
@@ -341,20 +309,10 @@ var files_preview_default = /* @__PURE__ */ (0, vue.defineComponent)({
341
309
  class: (0, vue.normalizeClass)(["docs-playground-files__tab", { "is-active": filename === __props.activeFilename }]),
342
310
  "data-filename": filename,
343
311
  onClick: ($event) => handleActive(filename)
344
- }, [(0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(filename), 1), filename === __props.entry ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("small", _hoisted_4$4, (0, vue.toDisplayString)((0, vue.unref)(t)("playground.files.entry")), 1)) : (0, vue.createCommentVNode)("v-if", true)], 10, _hoisted_3$4);
312
+ }, [(0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(filename), 1), filename === __props.entry ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("small", _hoisted_4$5, (0, vue.toDisplayString)((0, vue.unref)(t)("playground.files.entry")), 1)) : (0, vue.createCommentVNode)("v-if", true)], 10, _hoisted_3$5);
345
313
  }), 128))]),
346
314
  _: 1
347
- }), (0, vue.createElementVNode)("div", _hoisted_5$4, [__props.views.length > 1 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_6$3, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.views, (item) => {
348
- return (0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
349
- key: item,
350
- type: "button",
351
- class: (0, vue.normalizeClass)(["docs-playground__view", { "is-active": item === __props.activeView }]),
352
- title: getViewText(item),
353
- "aria-label": getViewText(item),
354
- "aria-pressed": item === __props.activeView,
355
- onClick: ($event) => handleView(item)
356
- }, [(0, vue.createVNode)((0, vue.unref)(icon_default), { name: item }, null, 8, ["name"])], 10, _hoisted_7$2);
357
- }), 128))])) : (0, vue.createCommentVNode)("v-if", true)])]), (0, vue.createVNode)((0, vue.unref)(code_preview_default), {
315
+ })]), (0, vue.createVNode)((0, vue.unref)(code_preview_default), {
358
316
  class: "docs-playground-files__body",
359
317
  code: activeCode.value,
360
318
  filename: __props.activeFilename,
@@ -486,21 +444,21 @@ var Drag = class {
486
444
  //#endregion
487
445
  //#region packages/playground/src/editor/editor.vue?vue&type=script&setup=true&lang.ts
488
446
  var _hoisted_1$4 = { class: "docs-playground-editor" };
489
- var _hoisted_2$3 = ["title"];
490
- var _hoisted_3$3 = { class: "docs-playground-editor__files" };
491
- var _hoisted_4$3 = [
447
+ var _hoisted_2$4 = ["title"];
448
+ var _hoisted_3$4 = { class: "docs-playground-editor__files" };
449
+ var _hoisted_4$4 = [
492
450
  "data-filename",
493
451
  "onClick",
494
452
  "onDblclick"
495
453
  ];
496
- var _hoisted_5$3 = ["onKeydown"];
497
- var _hoisted_6$2 = ["title"];
498
- var _hoisted_7$1 = ["title", "aria-label"];
499
- var _hoisted_8$1 = ["title", "aria-label"];
500
- var _hoisted_9 = { class: "docs-playground-editor__actions" };
501
- var _hoisted_10 = ["title"];
502
- var _hoisted_11 = ["title", "disabled"];
503
- var _hoisted_12 = {
454
+ var _hoisted_5$4 = ["onKeydown"];
455
+ var _hoisted_6$3 = ["title"];
456
+ var _hoisted_7$3 = ["title", "aria-label"];
457
+ var _hoisted_8$2 = ["title", "aria-label"];
458
+ var _hoisted_9$2 = { class: "docs-playground-editor__actions" };
459
+ var _hoisted_10$1 = ["title"];
460
+ var _hoisted_11$1 = ["title", "disabled"];
461
+ var _hoisted_12$1 = {
504
462
  key: 0,
505
463
  class: "docs-playground-editor__error"
506
464
  };
@@ -752,8 +710,8 @@ var editor_default = /* @__PURE__ */ (0, vue.defineComponent)({
752
710
  title: (0, vue.unref)(t)("playground.common.close"),
753
711
  style: { "cursor": "pointer" },
754
712
  onClick: handleHide
755
- }, "✕", 8, _hoisted_2$3)], 512),
756
- (0, vue.createElementVNode)("div", _hoisted_3$3, [(0, vue.createVNode)((0, vue.unref)(_deot_vc.Scroller), {
713
+ }, "✕", 8, _hoisted_2$4)], 512),
714
+ (0, vue.createElementVNode)("div", _hoisted_3$4, [(0, vue.createVNode)((0, vue.unref)(_deot_vc.Scroller), {
757
715
  ref_key: "scroller",
758
716
  ref: scroller,
759
717
  class: "docs-playground-editor__scroller",
@@ -781,11 +739,11 @@ var editor_default = /* @__PURE__ */ (0, vue.defineComponent)({
781
739
  onDblclick: _cache[2] || (_cache[2] = (0, vue.withModifiers)(() => {}, ["stop"])),
782
740
  onBlur: handleRenameSubmit,
783
741
  onKeydown: [(0, vue.withKeys)((0, vue.withModifiers)(handleRenameSubmit, ["prevent"]), ["enter"]), (0, vue.withKeys)((0, vue.withModifiers)(handleRenameCancel, ["prevent"]), ["esc"])]
784
- }, null, 40, _hoisted_5$3)), [[vue.vModelText, filenameDraft.value]]) : ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 1 }, [
742
+ }, null, 40, _hoisted_5$4)), [[vue.vModelText, filenameDraft.value]]) : ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 1 }, [
785
743
  filename === currentEntry.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
786
744
  key: 0,
787
745
  title: (0, vue.unref)(t)("playground.editor.entry")
788
- }, "●", 8, _hoisted_6$2)) : (0, vue.createCommentVNode)("v-if", true),
746
+ }, "●", 8, _hoisted_6$3)) : (0, vue.createCommentVNode)("v-if", true),
789
747
  (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(filename), 1),
790
748
  filename === currentEntry.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
791
749
  key: 1,
@@ -794,7 +752,7 @@ var editor_default = /* @__PURE__ */ (0, vue.defineComponent)({
794
752
  title: (0, vue.unref)(t)("playground.editor.entryCannotDelete"),
795
753
  "aria-label": (0, vue.unref)(t)("playground.editor.entryCannotDelete"),
796
754
  disabled: ""
797
- }, null, 8, _hoisted_7$1)) : ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_deot_vc.Popconfirm), {
755
+ }, null, 8, _hoisted_7$3)) : ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_deot_vc.Popconfirm), {
798
756
  key: 2,
799
757
  class: "docs-playground-editor__delete",
800
758
  title: (0, vue.unref)(t)("playground.editor.confirmDelete", { filename }),
@@ -807,23 +765,23 @@ var editor_default = /* @__PURE__ */ (0, vue.defineComponent)({
807
765
  class: "docs-playground-editor__close",
808
766
  title: (0, vue.unref)(t)("playground.editor.deleteFile"),
809
767
  "aria-label": (0, vue.unref)(t)("playground.editor.confirmDelete", { filename })
810
- }, null, 8, _hoisted_8$1)]),
768
+ }, null, 8, _hoisted_8$2)]),
811
769
  _: 2
812
770
  }, 1032, ["title", "onOk"]))
813
- ], 64))], 42, _hoisted_4$3);
771
+ ], 64))], 42, _hoisted_4$4);
814
772
  }), 128))]),
815
773
  _: 1
816
- }, 512), (0, vue.createElementVNode)("div", _hoisted_9, [(0, vue.createElementVNode)("button", {
774
+ }, 512), (0, vue.createElementVNode)("div", _hoisted_9$2, [(0, vue.createElementVNode)("button", {
817
775
  type: "button",
818
776
  title: (0, vue.unref)(t)("playground.editor.createFile"),
819
777
  onClick: handleCreate
820
- }, "+", 8, _hoisted_10), (0, vue.createElementVNode)("button", {
778
+ }, "+", 8, _hoisted_10$1), (0, vue.createElementVNode)("button", {
821
779
  type: "button",
822
780
  title: (0, vue.unref)(t)("playground.editor.setEntry"),
823
781
  disabled: activeFilename.value === currentEntry.value,
824
782
  onClick: handleEntry
825
- }, (0, vue.toDisplayString)((0, vue.unref)(t)("playground.editor.setEntry")), 9, _hoisted_11)])]),
826
- codeErrorText.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_12, (0, vue.toDisplayString)(codeErrorText.value), 1)) : (0, vue.createCommentVNode)("v-if", true),
783
+ }, (0, vue.toDisplayString)((0, vue.unref)(t)("playground.editor.setEntry")), 9, _hoisted_11$1)])]),
784
+ codeErrorText.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_12$1, (0, vue.toDisplayString)(codeErrorText.value), 1)) : (0, vue.createCommentVNode)("v-if", true),
827
785
  (0, vue.createVNode)((0, vue.unref)(_deot_vc.Scroller), {
828
786
  ref_key: "editorScroller",
829
787
  ref: editorScroller,
@@ -850,6 +808,50 @@ var editor_default = /* @__PURE__ */ (0, vue.defineComponent)({
850
808
  //#endregion
851
809
  //#region packages/playground/src/editor/index.ts
852
810
  var Editor = new _deot_vc.Portal(editor_default, { aliveRegExp: { className: /(PORTAL_TAG_DISABLE)/ } });
811
+ //#endregion
812
+ //#region packages/playground/src/utils.ts
813
+ /**
814
+ * 比较两组 playground 文件是否完全一致。
815
+ * @param left 左侧文件表。
816
+ * @param right 右侧文件表。
817
+ * @returns 键集合与各文件内容是否都相同。
818
+ */
819
+ var filesEqual = (left, right) => {
820
+ const leftKeys = Object.keys(left);
821
+ const rightKeys = Object.keys(right);
822
+ return leftKeys.length === rightKeys.length && leftKeys.every((key) => left[key] === right[key]);
823
+ };
824
+ /**
825
+ * 视图切换条使用的文案键。
826
+ * @param view 当前预览视图。
827
+ * @returns locale 消息键。
828
+ */
829
+ var playgroundViewMessage = (view) => view === "runtime" ? "playground.runtime.preview" : "playground.runtime.files";
830
+ /**
831
+ * 与 markdown-it-anchor 默认 `slugify` 对齐,用于标题锚点 id。
832
+ * @param title 标题文本。
833
+ * @returns 可用作元素 id / hash 的字符串;空标题返回空串。
834
+ */
835
+ var slugifyPlaygroundTitle = (title) => {
836
+ const normalized = String(title).trim().toLowerCase().replace(/\s+/g, "-");
837
+ return normalized ? encodeURIComponent(normalized) : "";
838
+ };
839
+ /**
840
+ * 解析标题锚点 id:显式 id 优先,否则从标题 slugify;必要时避开已占用 id。
841
+ * @param title 标题文本。
842
+ * @param explicitId 可选显式 id。
843
+ * @param isOccupied 返回该 id 是否已被其他元素占用。
844
+ * @returns 锚点 id;无标题时为空串。
845
+ */
846
+ var resolvePlaygroundTitleId = (title, explicitId = "", isOccupied) => {
847
+ if (!String(title).trim()) return "";
848
+ const base = String(explicitId).trim() || slugifyPlaygroundTitle(title);
849
+ if (!base) return "";
850
+ if (!isOccupied || !isOccupied(base)) return base;
851
+ let index = 1;
852
+ while (isOccupied(`${base}-${index}`)) index += 1;
853
+ return `${base}-${index}`;
854
+ };
853
855
  var resolveSandboxContainer = (sandbox) => sandbox?.container ? (0, vue.unref)(sandbox.container) : null;
854
856
  var useSandboxAutoHeight = (sandboxRef) => {
855
857
  const height = (0, vue.ref)(24);
@@ -972,14 +974,14 @@ var SCROLLABLE_OVERFLOW = /* @__PURE__ */ new Set([
972
974
  ]);
973
975
  var getWindowInnerHeight = () => typeof window === "undefined" ? 0 : window.innerHeight;
974
976
  var getPlaygroundHost = (el) => el?.closest(".docs-playground") ?? el;
975
- var isPlaygroundExpandEnabled = (expand) => {
976
- if (expand === true) return true;
977
- return typeof expand === "number" && Number.isFinite(expand) && expand > 0;
977
+ var isPlaygroundExpandable = (value) => {
978
+ if (value === true) return true;
979
+ return typeof value === "number" && Number.isFinite(value) && value > 0;
978
980
  };
979
981
  var resolveRemainingPreviewHeight = ({ viewportHeight, chromeHeight, gap = 16 }) => Math.max(0, Math.round((Number.isFinite(viewportHeight) ? viewportHeight : 0) - (Number.isFinite(chromeHeight) ? Math.max(0, chromeHeight) : 0) - (Number.isFinite(gap) ? gap : 16)));
980
- var resolveExpandedPreviewHeight = (expand, availableHeight) => {
981
- if (expand === true) return Math.max(24, Math.round(Number.isFinite(availableHeight) ? availableHeight : 0));
982
- return Math.max(24, Math.round(expand));
982
+ var resolveExpandedPreviewHeight = (expandable, availableHeight) => {
983
+ if (expandable === true) return Math.max(24, Math.round(Number.isFinite(availableHeight) ? availableHeight : 0));
984
+ return Math.max(24, Math.round(expandable));
983
985
  };
984
986
  var getVisibleViewportRect = (el) => {
985
987
  const viewportHeight = getWindowInnerHeight();
@@ -1127,6 +1129,13 @@ var formatViewportLabel = (viewport, autoLabel = "Auto") => {
1127
1129
  if (viewport === "auto") return autoLabel;
1128
1130
  return Array.isArray(viewport) ? `${viewport[0]} × ${viewport[1]}px` : `${viewport}px`;
1129
1131
  };
1132
+ var resolvePopupScreenInset = (gap = 40) => {
1133
+ const safeGap = Number.isFinite(gap) ? Math.max(0, gap) : 40;
1134
+ return {
1135
+ x: safeGap * 2,
1136
+ y: safeGap
1137
+ };
1138
+ };
1130
1139
  var getWindowInnerSize = () => {
1131
1140
  if (typeof window === "undefined") return {
1132
1141
  width: 0,
@@ -1138,9 +1147,9 @@ var getWindowInnerSize = () => {
1138
1147
  };
1139
1148
  };
1140
1149
  var resolvePopupRequestedSize = (viewport, screen = getWindowInnerSize(), gap = 40) => {
1141
- const safeGap = Number.isFinite(gap) ? Math.max(0, gap) : 40;
1142
- const maxWidth = Math.max(0, Math.round((Number.isFinite(screen.width) ? screen.width : 0) - safeGap));
1143
- const maxHeight = Math.max(0, Math.round((Number.isFinite(screen.height) ? screen.height : 0) - safeGap));
1150
+ const inset = resolvePopupScreenInset(gap);
1151
+ const maxWidth = Math.max(0, Math.round((Number.isFinite(screen.width) ? screen.width : 0) - inset.x));
1152
+ const maxHeight = Math.max(0, Math.round((Number.isFinite(screen.height) ? screen.height : 0) - inset.y));
1144
1153
  const viewportWidth = getViewportWidth(viewport);
1145
1154
  const viewportHeight = getViewportHeight(viewport);
1146
1155
  return {
@@ -1151,11 +1160,11 @@ var resolvePopupRequestedSize = (viewport, screen = getWindowInnerSize(), gap =
1151
1160
  };
1152
1161
  };
1153
1162
  /**
1154
- * 壳层封顶到 `screen - gap`。未设 viewport 边时,画布铺满工具栏以下区域;
1155
- * 请求尺寸大于可用区域时由 Scroller 处理溢出。
1163
+ * 壳层封顶到 `screen.width - gap * 2`、`screen.height - gap`。
1164
+ * 未设 viewport 边时,画布铺满工具栏以下区域;请求尺寸大于可用区域时由 Scroller 处理溢出。
1156
1165
  * @param viewport 当前 playground 视口配置。
1157
- * @param screen 屏幕可用宽高,默认取 `window.inner*`.
1158
- * @param gap 相对屏幕边缘的留白。
1166
+ * @param screen 屏幕可用宽高,默认取 `window.inner*`。
1167
+ * @param gap 相对屏幕上下边缘的留白;左右为该值的 2 倍。
1159
1168
  * @returns 壳层、内容区与画布尺寸,以及是否需要滚动。
1160
1169
  */
1161
1170
  var resolvePopupLayout = (viewport, screen = getWindowInnerSize(), gap = 40) => {
@@ -1270,23 +1279,56 @@ var useSandboxTheme = (sandboxRef) => {
1270
1279
  //#endregion
1271
1280
  //#region packages/playground/src/core/runtime/toolbar.vue?vue&type=script&setup=true&lang.ts
1272
1281
  var _hoisted_1$3 = { class: "docs-playground__tools" };
1273
- var _hoisted_2$2 = ["title", "aria-label"];
1274
- var _hoisted_3$2 = [
1282
+ var _hoisted_2$3 = {
1283
+ key: 0,
1284
+ class: "docs-playground__tool-group"
1285
+ };
1286
+ var _hoisted_3$3 = [
1275
1287
  "title",
1276
1288
  "aria-label",
1277
1289
  "aria-expanded"
1278
1290
  ];
1279
- var _hoisted_4$2 = ["title", "aria-label"];
1280
- var _hoisted_5$2 = ["title", "aria-label"];
1281
- var _hoisted_6$1 = ["title", "aria-label"];
1291
+ var _hoisted_4$3 = {
1292
+ key: 1,
1293
+ class: "docs-playground__tool-divider",
1294
+ "aria-hidden": "true"
1295
+ };
1296
+ var _hoisted_5$3 = ["title", "aria-label"];
1297
+ var _hoisted_6$2 = ["title", "aria-label"];
1298
+ var _hoisted_7$2 = ["title", "aria-label"];
1299
+ var _hoisted_8$1 = {
1300
+ key: 3,
1301
+ class: "docs-playground__tool-divider",
1302
+ "aria-hidden": "true"
1303
+ };
1304
+ var _hoisted_9$1 = ["aria-label"];
1305
+ var _hoisted_10 = [
1306
+ "title",
1307
+ "aria-label",
1308
+ "aria-selected",
1309
+ "aria-pressed",
1310
+ "onClick"
1311
+ ];
1312
+ var _hoisted_11 = {
1313
+ key: 2,
1314
+ class: "docs-playground__tool-divider",
1315
+ "aria-hidden": "true"
1316
+ };
1317
+ var _hoisted_12 = ["title", "aria-label"];
1282
1318
  //#endregion
1283
1319
  //#region packages/playground/src/core/runtime/toolbar.vue
1284
1320
  var toolbar_default = /* @__PURE__ */ (0, vue.defineComponent)({
1285
1321
  __name: "toolbar",
1286
1322
  props: {
1287
- copyValue: {},
1323
+ copyValue: { default: "" },
1288
1324
  viewport: { default: "auto" },
1289
1325
  viewportOptions: { default: () => ["auto", 375] },
1326
+ views: { default: () => [] },
1327
+ activeView: { default: "runtime" },
1328
+ showRuntimeActions: {
1329
+ type: Boolean,
1330
+ default: true
1331
+ },
1290
1332
  showOpenPopup: {
1291
1333
  type: Boolean,
1292
1334
  default: false
@@ -1301,14 +1343,20 @@ var toolbar_default = /* @__PURE__ */ (0, vue.defineComponent)({
1301
1343
  "edit",
1302
1344
  "open-popup",
1303
1345
  "close-popup",
1304
- "viewport-change"
1346
+ "viewport-change",
1347
+ "view-change"
1305
1348
  ],
1306
1349
  setup(__props, { emit: __emit }) {
1307
1350
  const props = __props;
1308
1351
  const emit = __emit;
1309
1352
  const { t } = (0, _deot_docs_locale.useLocale)();
1353
+ const VIEW_ORDER = ["runtime", "files"];
1310
1354
  const viewportMenuVisible = (0, vue.ref)(false);
1355
+ const orderedViews = (0, vue.computed)(() => VIEW_ORDER.filter((view) => props.views.includes(view)));
1356
+ const showViews = (0, vue.computed)(() => orderedViews.value.length > 1);
1311
1357
  const viewportLabel = (0, vue.computed)(() => formatViewportLabel(props.viewport, t("playground.runtime.auto")));
1358
+ const getViewAriaLabel = (view) => t(playgroundViewMessage(view));
1359
+ const getViewLabel = (view) => view === "runtime" ? t("playground.runtime.previewLabel") : t("playground.runtime.codeLabel");
1312
1360
  const handleViewport = (index) => {
1313
1361
  const viewport = props.viewportOptions[index];
1314
1362
  if (viewport && !viewportEquals(viewport, props.viewport)) emit("viewport-change", viewport);
@@ -1316,95 +1364,120 @@ var toolbar_default = /* @__PURE__ */ (0, vue.defineComponent)({
1316
1364
  (0, vue.watch)(() => props.viewportOptions.length, (length) => {
1317
1365
  if (length <= 1) viewportMenuVisible.value = false;
1318
1366
  });
1367
+ (0, vue.watch)(() => props.showRuntimeActions, (enabled) => {
1368
+ if (!enabled) viewportMenuVisible.value = false;
1369
+ });
1319
1370
  return (_ctx, _cache) => {
1320
1371
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$3, [
1321
- (0, vue.createElementVNode)("button", {
1322
- type: "button",
1323
- class: "docs-playground__tool docs-playground__refresh",
1324
- "data-action": "refresh",
1325
- title: (0, vue.unref)(t)("playground.runtime.refresh"),
1326
- "aria-label": (0, vue.unref)(t)("playground.runtime.refresh"),
1327
- onClick: _cache[0] || (_cache[0] = ($event) => emit("refresh"))
1328
- }, [(0, vue.createVNode)((0, vue.unref)(icon_default), { name: "refresh" })], 8, _hoisted_2$2),
1329
- __props.viewportOptions.length > 1 ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_deot_vc.Dropdown), {
1330
- key: 0,
1331
- modelValue: viewportMenuVisible.value,
1332
- "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => viewportMenuVisible.value = $event),
1333
- class: "docs-playground__viewport-menu",
1334
- portal: true,
1335
- trigger: "click",
1336
- placement: "bottom-right"
1337
- }, {
1338
- content: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_deot_vc.DropdownMenu), {
1339
- class: "docs-playground__viewport-options",
1340
- role: "menu",
1341
- "aria-label": (0, vue.unref)(t)("playground.runtime.viewportMenu")
1372
+ __props.showRuntimeActions ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [
1373
+ __props.viewportOptions.length > 1 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2$3, [(0, vue.createVNode)((0, vue.unref)(_deot_vc.Dropdown), {
1374
+ modelValue: viewportMenuVisible.value,
1375
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => viewportMenuVisible.value = $event),
1376
+ class: "docs-playground__viewport-menu",
1377
+ portal: true,
1378
+ trigger: "click",
1379
+ placement: "bottom-right"
1342
1380
  }, {
1343
- default: (0, vue.withCtx)(() => [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.viewportOptions, (item, index) => {
1344
- return (0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_deot_vc.DropdownItem), {
1345
- key: (0, vue.unref)(getViewportKey)(item),
1346
- class: "docs-playground__viewport-option",
1347
- value: index,
1348
- selected: (0, vue.unref)(viewportEquals)(item, __props.viewport),
1349
- role: "menuitemradio",
1350
- "aria-checked": (0, vue.unref)(viewportEquals)(item, __props.viewport),
1351
- onClick: ($event) => handleViewport(index)
1352
- }, {
1353
- default: (0, vue.withCtx)(() => [(0, vue.createTextVNode)((0, vue.toDisplayString)((0, vue.unref)(formatViewportLabel)(item, (0, vue.unref)(t)("playground.runtime.auto"))), 1)]),
1354
- _: 2
1355
- }, 1032, [
1356
- "value",
1357
- "selected",
1358
- "aria-checked",
1359
- "onClick"
1360
- ]);
1361
- }), 128))]),
1381
+ content: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_deot_vc.DropdownMenu), {
1382
+ class: "docs-playground__viewport-options",
1383
+ role: "menu",
1384
+ "aria-label": (0, vue.unref)(t)("playground.runtime.viewportMenu")
1385
+ }, {
1386
+ default: (0, vue.withCtx)(() => [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.viewportOptions, (item, index) => {
1387
+ return (0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_deot_vc.DropdownItem), {
1388
+ key: (0, vue.unref)(getViewportKey)(item),
1389
+ class: "docs-playground__viewport-option",
1390
+ value: index,
1391
+ selected: (0, vue.unref)(viewportEquals)(item, __props.viewport),
1392
+ role: "menuitemradio",
1393
+ "aria-checked": (0, vue.unref)(viewportEquals)(item, __props.viewport),
1394
+ onClick: ($event) => handleViewport(index)
1395
+ }, {
1396
+ default: (0, vue.withCtx)(() => [(0, vue.createTextVNode)((0, vue.toDisplayString)((0, vue.unref)(formatViewportLabel)(item, (0, vue.unref)(t)("playground.runtime.auto"))), 1)]),
1397
+ _: 2
1398
+ }, 1032, [
1399
+ "value",
1400
+ "selected",
1401
+ "aria-checked",
1402
+ "onClick"
1403
+ ]);
1404
+ }), 128))]),
1405
+ _: 1
1406
+ }, 8, ["aria-label"])]),
1407
+ default: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("button", {
1408
+ type: "button",
1409
+ class: (0, vue.normalizeClass)(["docs-playground__tool docs-playground__viewport-trigger", { "is-active": __props.viewport !== "auto" }]),
1410
+ title: (0, vue.unref)(t)("playground.runtime.viewport", { value: viewportLabel.value }),
1411
+ "aria-label": (0, vue.unref)(t)("playground.runtime.viewport", { value: viewportLabel.value }),
1412
+ "aria-expanded": viewportMenuVisible.value,
1413
+ "aria-haspopup": "menu"
1414
+ }, [(0, vue.createVNode)((0, vue.unref)(icon_default), { name: "viewport" })], 10, _hoisted_3$3)]),
1362
1415
  _: 1
1363
- }, 8, ["aria-label"])]),
1364
- default: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("button", {
1416
+ }, 8, ["modelValue"])])) : (0, vue.createCommentVNode)("v-if", true),
1417
+ __props.viewportOptions.length > 1 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_4$3)) : (0, vue.createCommentVNode)("v-if", true),
1418
+ (0, vue.createElementVNode)("button", {
1365
1419
  type: "button",
1366
- class: (0, vue.normalizeClass)(["docs-playground__tool docs-playground__viewport-trigger", { "is-active": __props.viewport !== "auto" }]),
1367
- title: (0, vue.unref)(t)("playground.runtime.viewport", { value: viewportLabel.value }),
1368
- "aria-label": (0, vue.unref)(t)("playground.runtime.viewport", { value: viewportLabel.value }),
1369
- "aria-expanded": viewportMenuVisible.value,
1370
- "aria-haspopup": "menu"
1371
- }, [(0, vue.createVNode)((0, vue.unref)(icon_default), { name: "viewport" })], 10, _hoisted_3$2)]),
1372
- _: 1
1373
- }, 8, ["modelValue"])) : (0, vue.createCommentVNode)("v-if", true),
1374
- (0, vue.createVNode)((0, vue.unref)(_deot_vc.Clipboard), {
1375
- class: "docs-playground__tool",
1376
- value: __props.copyValue,
1377
- tag: "button",
1378
- type: "button",
1379
- title: (0, vue.unref)(t)("playground.common.copy"),
1380
- "aria-label": (0, vue.unref)(t)("playground.common.copy")
1381
- }, {
1382
- default: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(icon_default), { name: "copy" })]),
1383
- _: 1
1384
- }, 8, [
1385
- "value",
1386
- "title",
1387
- "aria-label"
1388
- ]),
1389
- (0, vue.createElementVNode)("button", {
1390
- type: "button",
1391
- class: "docs-playground__tool docs-playground__editor",
1392
- "data-action": "edit",
1393
- title: (0, vue.unref)(t)("playground.runtime.editFiles"),
1394
- "aria-label": (0, vue.unref)(t)("playground.runtime.editFiles"),
1395
- onClick: _cache[2] || (_cache[2] = ($event) => emit("edit"))
1396
- }, [(0, vue.createVNode)((0, vue.unref)(icon_default), { name: "editor" })], 8, _hoisted_4$2),
1397
- __props.showOpenPopup ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
1420
+ class: "docs-playground__tool docs-playground__refresh",
1421
+ "data-action": "refresh",
1422
+ title: (0, vue.unref)(t)("playground.runtime.refresh"),
1423
+ "aria-label": (0, vue.unref)(t)("playground.runtime.refresh"),
1424
+ onClick: _cache[1] || (_cache[1] = ($event) => emit("refresh"))
1425
+ }, [(0, vue.createVNode)((0, vue.unref)(icon_default), { name: "refresh" })], 8, _hoisted_5$3),
1426
+ (0, vue.createElementVNode)("button", {
1427
+ type: "button",
1428
+ class: "docs-playground__tool docs-playground__editor",
1429
+ "data-action": "edit",
1430
+ title: (0, vue.unref)(t)("playground.runtime.editFiles"),
1431
+ "aria-label": (0, vue.unref)(t)("playground.runtime.editFiles"),
1432
+ onClick: _cache[2] || (_cache[2] = ($event) => emit("edit"))
1433
+ }, [(0, vue.createVNode)((0, vue.unref)(icon_default), { name: "editor" })], 8, _hoisted_6$2),
1434
+ __props.showOpenPopup ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
1435
+ key: 2,
1436
+ type: "button",
1437
+ class: "docs-playground__tool docs-playground__popup",
1438
+ "data-action": "open-popup",
1439
+ title: (0, vue.unref)(t)("playground.runtime.openPopup"),
1440
+ "aria-label": (0, vue.unref)(t)("playground.runtime.openPopup"),
1441
+ onClick: _cache[3] || (_cache[3] = ($event) => emit("open-popup"))
1442
+ }, [(0, vue.createVNode)((0, vue.unref)(icon_default), { name: "popup" })], 8, _hoisted_7$2)) : (0, vue.createCommentVNode)("v-if", true),
1443
+ (0, vue.createVNode)((0, vue.unref)(_deot_vc.Clipboard), {
1444
+ class: "docs-playground__tool",
1445
+ value: __props.copyValue,
1446
+ tag: "button",
1447
+ type: "button",
1448
+ title: (0, vue.unref)(t)("playground.common.copy"),
1449
+ "aria-label": (0, vue.unref)(t)("playground.common.copy")
1450
+ }, {
1451
+ default: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(icon_default), { name: "copy" })]),
1452
+ _: 1
1453
+ }, 8, [
1454
+ "value",
1455
+ "title",
1456
+ "aria-label"
1457
+ ]),
1458
+ showViews.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_8$1)) : (0, vue.createCommentVNode)("v-if", true)
1459
+ ], 64)) : (0, vue.createCommentVNode)("v-if", true),
1460
+ showViews.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
1398
1461
  key: 1,
1399
- type: "button",
1400
- class: "docs-playground__tool docs-playground__popup",
1401
- "data-action": "open-popup",
1402
- title: (0, vue.unref)(t)("playground.runtime.openPopup"),
1403
- "aria-label": (0, vue.unref)(t)("playground.runtime.openPopup"),
1404
- onClick: _cache[3] || (_cache[3] = ($event) => emit("open-popup"))
1405
- }, [(0, vue.createVNode)((0, vue.unref)(icon_default), { name: "popup" })], 8, _hoisted_5$2)) : (0, vue.createCommentVNode)("v-if", true),
1462
+ class: "docs-playground__views",
1463
+ role: "tablist",
1464
+ "aria-label": (0, vue.unref)(t)("playground.runtime.views")
1465
+ }, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(orderedViews.value, (item) => {
1466
+ return (0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
1467
+ key: item,
1468
+ type: "button",
1469
+ class: (0, vue.normalizeClass)(["docs-playground__view", { "is-active": item === __props.activeView }]),
1470
+ role: "tab",
1471
+ title: getViewAriaLabel(item),
1472
+ "aria-label": getViewAriaLabel(item),
1473
+ "aria-selected": item === __props.activeView,
1474
+ "aria-pressed": item === __props.activeView,
1475
+ onClick: ($event) => emit("view-change", item)
1476
+ }, (0, vue.toDisplayString)(getViewLabel(item)), 11, _hoisted_10);
1477
+ }), 128))], 8, _hoisted_9$1)) : (0, vue.createCommentVNode)("v-if", true),
1478
+ __props.showClose && (__props.showRuntimeActions || showViews.value) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_11)) : (0, vue.createCommentVNode)("v-if", true),
1406
1479
  __props.showClose ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
1407
- key: 2,
1480
+ key: 3,
1408
1481
  type: "button",
1409
1482
  class: "docs-playground__tool docs-playground__popup-close",
1410
1483
  "data-action": "close-popup",
@@ -1414,7 +1487,7 @@ var toolbar_default = /* @__PURE__ */ (0, vue.defineComponent)({
1414
1487
  }, [..._cache[5] || (_cache[5] = [(0, vue.createElementVNode)("span", {
1415
1488
  class: "docs-playground__popup-close-mark",
1416
1489
  "aria-hidden": "true"
1417
- }, "✕", -1)])], 8, _hoisted_6$1)) : (0, vue.createCommentVNode)("v-if", true)
1490
+ }, "✕", -1)])], 8, _hoisted_12)) : (0, vue.createCommentVNode)("v-if", true)
1418
1491
  ]);
1419
1492
  };
1420
1493
  }
@@ -1835,14 +1908,16 @@ var createRuntimeStore = (files, entry, options) => {
1835
1908
  //#endregion
1836
1909
  //#region packages/playground/src/core/runtime/alone/wrapper.vue?vue&type=script&setup=true&lang.ts
1837
1910
  var _hoisted_1$2 = ["aria-label"];
1838
- var _hoisted_2$1 = { class: "docs-playground-popup__frame" };
1839
- var _hoisted_3$1 = { class: "docs-playground-popup__header" };
1840
- var _hoisted_4$1 = {
1911
+ var _hoisted_2$2 = { class: "docs-playground-popup__frame" };
1912
+ var _hoisted_3$2 = { class: "docs-playground-popup__header" };
1913
+ var _hoisted_4$2 = ["title"];
1914
+ var _hoisted_5$2 = { class: "docs-playground__title-text" };
1915
+ var _hoisted_6$1 = {
1841
1916
  key: 0,
1842
1917
  class: "docs-playground__runtime-error",
1843
1918
  role: "alert"
1844
1919
  };
1845
- var _hoisted_5$1 = { class: "docs-playground-popup__body" };
1920
+ var _hoisted_7$1 = { class: "docs-playground-popup__body" };
1846
1921
  //#endregion
1847
1922
  //#region packages/playground/src/core/runtime/alone/wrapper.vue
1848
1923
  var wrapper_default = /* @__PURE__ */ (0, vue.defineComponent)({
@@ -1850,6 +1925,7 @@ var wrapper_default = /* @__PURE__ */ (0, vue.defineComponent)({
1850
1925
  props: {
1851
1926
  store: {},
1852
1927
  copyValue: {},
1928
+ title: { default: "" },
1853
1929
  viewport: { default: "auto" },
1854
1930
  viewportOptions: { default: () => ["auto", 375] },
1855
1931
  previewOptions: {},
@@ -1950,8 +2026,12 @@ var wrapper_default = /* @__PURE__ */ (0, vue.defineComponent)({
1950
2026
  }), (0, vue.createElementVNode)("div", {
1951
2027
  class: "docs-playground-popup__shell",
1952
2028
  style: (0, vue.normalizeStyle)(shellStyle.value)
1953
- }, [(0, vue.createElementVNode)("div", _hoisted_2$1, [
1954
- (0, vue.createElementVNode)("div", _hoisted_3$1, [(0, vue.createVNode)(toolbar_default, {
2029
+ }, [(0, vue.createElementVNode)("div", _hoisted_2$2, [
2030
+ (0, vue.createElementVNode)("div", _hoisted_3$2, [__props.title.trim() ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
2031
+ key: 0,
2032
+ class: "docs-playground__title",
2033
+ title: __props.title.trim()
2034
+ }, [(0, vue.createElementVNode)("span", _hoisted_5$2, (0, vue.toDisplayString)(__props.title.trim()), 1)], 8, _hoisted_4$2)) : (0, vue.createCommentVNode)("v-if", true), (0, vue.createVNode)(toolbar_default, {
1955
2035
  "copy-value": __props.copyValue,
1956
2036
  viewport: currentViewport.value,
1957
2037
  "viewport-options": __props.viewportOptions,
@@ -1965,8 +2045,8 @@ var wrapper_default = /* @__PURE__ */ (0, vue.defineComponent)({
1965
2045
  "viewport",
1966
2046
  "viewport-options"
1967
2047
  ])]),
1968
- errorText.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("pre", _hoisted_4$1, (0, vue.toDisplayString)(errorText.value), 1)) : (0, vue.createCommentVNode)("v-if", true),
1969
- (0, vue.createElementVNode)("div", _hoisted_5$1, [(0, vue.createVNode)((0, vue.unref)(_deot_vc.Scroller), {
2048
+ errorText.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("pre", _hoisted_6$1, (0, vue.toDisplayString)(errorText.value), 1)) : (0, vue.createCommentVNode)("v-if", true),
2049
+ (0, vue.createElementVNode)("div", _hoisted_7$1, [(0, vue.createVNode)((0, vue.unref)(_deot_vc.Scroller), {
1970
2050
  class: "docs-playground-popup__scroller",
1971
2051
  "content-class": "docs-playground-popup__scroller-content",
1972
2052
  "auto-resize": true,
@@ -2006,29 +2086,25 @@ var Alone = new _deot_vc.Portal(wrapper_default, {
2006
2086
  //#endregion
2007
2087
  //#region packages/playground/src/core/runtime/runtime.vue?vue&type=script&setup=true&lang.ts
2008
2088
  var _hoisted_1$1 = { class: "docs-playground-runtime-host" };
2009
- var _hoisted_2 = {
2089
+ var _hoisted_2$1 = {
2010
2090
  key: 0,
2011
2091
  class: "docs-playground__runtime-error",
2012
2092
  role: "alert"
2013
2093
  };
2014
- var _hoisted_3 = { class: "docs-playground__header" };
2015
- var _hoisted_4 = {
2094
+ var _hoisted_3$1 = {
2016
2095
  key: 0,
2017
- class: "docs-playground__views"
2096
+ class: "docs-playground__header"
2018
2097
  };
2019
- var _hoisted_5 = [
2020
- "title",
2021
- "aria-label",
2022
- "aria-pressed",
2023
- "onClick"
2024
- ];
2025
- var _hoisted_6 = {
2026
- key: 0,
2098
+ var _hoisted_4$1 = ["id", "title"];
2099
+ var _hoisted_5$1 = ["href"];
2100
+ var _hoisted_6 = { class: "docs-playground__title-text" };
2101
+ var _hoisted_7 = {
2102
+ key: 1,
2027
2103
  class: "docs-playground__runtime-error",
2028
2104
  role: "alert"
2029
2105
  };
2030
- var _hoisted_7 = { class: "docs-playground-runtime__viewport-stage" };
2031
- var _hoisted_8 = [
2106
+ var _hoisted_8 = { class: "docs-playground-runtime__viewport-stage" };
2107
+ var _hoisted_9 = [
2032
2108
  "aria-expanded",
2033
2109
  "title",
2034
2110
  "aria-label"
@@ -2049,7 +2125,13 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
2049
2125
  type: Boolean,
2050
2126
  default: false
2051
2127
  },
2052
- expand: { type: [Boolean, Number] },
2128
+ hideChrome: {
2129
+ type: Boolean,
2130
+ default: false
2131
+ },
2132
+ expandable: { type: [Boolean, Number] },
2133
+ title: { default: "" },
2134
+ id: { default: "" },
2053
2135
  viewport: { default: "auto" },
2054
2136
  viewportOptions: { default: () => ["auto", 375] }
2055
2137
  },
@@ -2059,10 +2141,16 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
2059
2141
  "viewport-change",
2060
2142
  "navigate"
2061
2143
  ],
2062
- setup(__props, { emit: __emit }) {
2144
+ setup(__props, { expose: __expose, emit: __emit }) {
2063
2145
  const props = __props;
2064
2146
  const { locale, t } = (0, _deot_docs_locale.useLocale)();
2065
- const getViewText = (view) => t(playgroundViewMessage(view));
2147
+ const displayTitle = (0, vue.computed)(() => props.title.trim());
2148
+ const titleEl = (0, vue.ref)(null);
2149
+ const titleId = (0, vue.computed)(() => resolvePlaygroundTitleId(displayTitle.value, props.id, (candidate) => {
2150
+ if (typeof document === "undefined") return false;
2151
+ const existing = document.getElementById(candidate);
2152
+ return !!existing && existing !== titleEl.value;
2153
+ }));
2066
2154
  const emit = __emit;
2067
2155
  const joinCode = (...values) => values.filter(Boolean).join("\n");
2068
2156
  const mergePreviewOptions = (extraHeadHTML) => {
@@ -2111,12 +2199,12 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
2111
2199
  };
2112
2200
  const runtimeRoot = (0, vue.ref)(null);
2113
2201
  const previewExpanded = (0, vue.ref)(false);
2114
- /** `expand: true` 时在展开瞬间冻结,避免滚动重算高度造成抖动。 */
2202
+ /** `expandable: true` 时在展开瞬间冻结,避免滚动重算高度造成抖动。 */
2115
2203
  const frozenExpandedHeight = (0, vue.ref)(0);
2116
2204
  const measurePreviewChromeHeight = () => {
2117
2205
  const root = runtimeRoot.value;
2118
2206
  if (!root) return 0;
2119
- const header = root.querySelector(".docs-playground__header");
2207
+ const header = (root.closest(".docs-playground") ?? root).querySelector(".docs-playground__header");
2120
2208
  const error = root.querySelector(".docs-playground__runtime-error");
2121
2209
  return (header instanceof HTMLElement ? header.offsetHeight : 0) + (error instanceof HTMLElement ? error.offsetHeight : 0);
2122
2210
  };
@@ -2129,18 +2217,18 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
2129
2217
  }));
2130
2218
  };
2131
2219
  const syncFrozenExpandedHeight = () => {
2132
- if (!previewExpanded.value || props.expand !== true) return;
2220
+ if (!previewExpanded.value || props.expandable !== true) return;
2133
2221
  frozenExpandedHeight.value = measureExpandedPreviewHeight();
2134
2222
  };
2135
2223
  if (typeof window !== "undefined") {
2136
2224
  window.addEventListener("message", handleBridgeMessage);
2137
2225
  window.addEventListener("resize", syncFrozenExpandedHeight);
2138
2226
  }
2139
- const canExpandPreview = (0, vue.computed)(() => !props.styleless && isPlaygroundExpandEnabled(props.expand));
2227
+ const canExpandPreview = (0, vue.computed)(() => !props.styleless && isPlaygroundExpandable(props.expandable));
2140
2228
  const expandLabel = (0, vue.computed)(() => t(previewExpanded.value ? "playground.runtime.collapsePreview" : "playground.runtime.expandPreview"));
2141
2229
  const desiredViewportHeight = (0, vue.computed)(() => {
2142
- if (previewExpanded.value && props.expand === true) return frozenExpandedHeight.value;
2143
- if (previewExpanded.value && isPlaygroundExpandEnabled(props.expand)) return resolveExpandedPreviewHeight(props.expand, 0);
2230
+ if (previewExpanded.value && props.expandable === true) return frozenExpandedHeight.value;
2231
+ if (previewExpanded.value && isPlaygroundExpandable(props.expandable)) return resolveExpandedPreviewHeight(props.expandable, 0);
2144
2232
  const fixedHeight = getViewportHeight(props.viewport);
2145
2233
  if (fixedHeight) return fixedHeight;
2146
2234
  return runtimeHeight.value;
@@ -2151,7 +2239,7 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
2151
2239
  const handleTogglePreviewExpand = () => {
2152
2240
  if (!canExpandPreview.value) return;
2153
2241
  if (!previewExpanded.value) {
2154
- if (props.expand === true) frozenExpandedHeight.value = measureExpandedPreviewHeight();
2242
+ if (props.expandable === true) frozenExpandedHeight.value = measureExpandedPreviewHeight();
2155
2243
  else frozenExpandedHeight.value = 0;
2156
2244
  previewExpanded.value = true;
2157
2245
  (0, vue.nextTick)(scrollExpandedPreviewIntoView);
@@ -2240,6 +2328,7 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
2240
2328
  Alone.popup({
2241
2329
  store,
2242
2330
  copyValue: copyValue.value,
2331
+ title: props.title,
2243
2332
  viewport: props.viewport,
2244
2333
  viewportOptions: props.viewportOptions,
2245
2334
  previewOptions: popupPreviewOptions.value,
@@ -2249,7 +2338,6 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
2249
2338
  onNavigate: (to) => emit("navigate", to)
2250
2339
  });
2251
2340
  };
2252
- const handleView = (view) => emit("view-change", view);
2253
2341
  const handleViewportChange = (viewport) => {
2254
2342
  emit("viewport-change", viewport);
2255
2343
  };
@@ -2274,6 +2362,11 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
2274
2362
  window.removeEventListener("resize", syncFrozenExpandedHeight);
2275
2363
  handleClosePopup();
2276
2364
  });
2365
+ __expose({
2366
+ refresh: handleInlineRefresh,
2367
+ edit: handleEditor,
2368
+ openPopup: handleOpenPopup
2369
+ });
2277
2370
  return (_ctx, _cache) => {
2278
2371
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$1, [__props.styleless ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
2279
2372
  key: 0,
@@ -2281,7 +2374,7 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
2281
2374
  ref: runtimeRoot,
2282
2375
  class: "docs-playground-runtime--styleless",
2283
2376
  style: (0, vue.normalizeStyle)(stylelessStyle.value)
2284
- }, [errorText.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("pre", _hoisted_2, (0, vue.toDisplayString)(errorText.value), 1)) : (0, vue.createCommentVNode)("v-if", true), (0, vue.createElementVNode)("div", {
2377
+ }, [errorText.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("pre", _hoisted_2$1, (0, vue.toDisplayString)(errorText.value), 1)) : (0, vue.createCommentVNode)("v-if", true), (0, vue.createElementVNode)("div", {
2285
2378
  class: "docs-playground-runtime__viewport",
2286
2379
  style: (0, vue.normalizeStyle)(viewportStyle.value)
2287
2380
  }, [(0, vue.createVNode)((0, vue.unref)(_vue_repl.Sandbox), {
@@ -2296,7 +2389,18 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
2296
2389
  ref: runtimeRoot,
2297
2390
  class: "docs-playground-runtime"
2298
2391
  }, [
2299
- (0, vue.createElementVNode)("div", _hoisted_3, [(0, vue.createVNode)(toolbar_default, {
2392
+ !__props.hideChrome ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_3$1, [displayTitle.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
2393
+ key: 0,
2394
+ ref_key: "titleEl",
2395
+ ref: titleEl,
2396
+ class: "docs-playground__title",
2397
+ id: titleId.value,
2398
+ tabindex: "-1",
2399
+ title: displayTitle.value
2400
+ }, [(0, vue.createElementVNode)("a", {
2401
+ class: "docs-playground__title-anchor",
2402
+ href: `#${titleId.value}`
2403
+ }, "#", 8, _hoisted_5$1), (0, vue.createElementVNode)("span", _hoisted_6, (0, vue.toDisplayString)(displayTitle.value), 1)], 8, _hoisted_4$1)) : (0, vue.createCommentVNode)("v-if", true), (0, vue.createVNode)(toolbar_default, {
2300
2404
  "copy-value": copyValue.value,
2301
2405
  viewport: __props.viewport,
2302
2406
  "viewport-options": __props.viewportOptions,
@@ -2309,22 +2413,12 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
2309
2413
  "copy-value",
2310
2414
  "viewport",
2311
2415
  "viewport-options"
2312
- ]), __props.views.length > 1 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_4, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.views, (item) => {
2313
- return (0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
2314
- key: item,
2315
- type: "button",
2316
- class: (0, vue.normalizeClass)(["docs-playground__view", { "is-active": item === __props.activeView }]),
2317
- title: getViewText(item),
2318
- "aria-label": getViewText(item),
2319
- "aria-pressed": item === __props.activeView,
2320
- onClick: ($event) => handleView(item)
2321
- }, [(0, vue.createVNode)((0, vue.unref)(icon_default), { name: item }, null, 8, ["name"])], 10, _hoisted_5);
2322
- }), 128))])) : (0, vue.createCommentVNode)("v-if", true)]),
2323
- errorText.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("pre", _hoisted_6, (0, vue.toDisplayString)(errorText.value), 1)) : (0, vue.createCommentVNode)("v-if", true),
2416
+ ])])) : (0, vue.createCommentVNode)("v-if", true),
2417
+ errorText.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("pre", _hoisted_7, (0, vue.toDisplayString)(errorText.value), 1)) : (0, vue.createCommentVNode)("v-if", true),
2324
2418
  (0, vue.createElementVNode)("section", {
2325
2419
  class: (0, vue.normalizeClass)(["docs-playground__preview", { "is-expanded": previewExpanded.value }]),
2326
2420
  style: (0, vue.normalizeStyle)(previewStyle.value)
2327
- }, [(0, vue.createElementVNode)("div", _hoisted_7, [(0, vue.createElementVNode)("div", {
2421
+ }, [(0, vue.createElementVNode)("div", _hoisted_8, [(0, vue.createElementVNode)("div", {
2328
2422
  class: "docs-playground-runtime__viewport",
2329
2423
  style: (0, vue.normalizeStyle)(viewportStyle.value)
2330
2424
  }, [((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_vue_repl.Sandbox), {
@@ -2344,7 +2438,7 @@ var runtime_default = /* @__PURE__ */ (0, vue.defineComponent)({
2344
2438
  title: expandLabel.value,
2345
2439
  "aria-label": expandLabel.value,
2346
2440
  onClick: handleTogglePreviewExpand
2347
- }, [(0, vue.createVNode)((0, vue.unref)(icon_default), { name: "expand" })], 10, _hoisted_8)) : (0, vue.createCommentVNode)("v-if", true)], 6)
2441
+ }, [(0, vue.createVNode)((0, vue.unref)(icon_default), { name: "expand" })], 10, _hoisted_9)) : (0, vue.createCommentVNode)("v-if", true)], 6)
2348
2442
  ], 512))]);
2349
2443
  };
2350
2444
  }
@@ -2355,6 +2449,13 @@ var _hoisted_1 = {
2355
2449
  key: 0,
2356
2450
  class: "docs-playground__error"
2357
2451
  };
2452
+ var _hoisted_2 = {
2453
+ key: 0,
2454
+ class: "docs-playground__header"
2455
+ };
2456
+ var _hoisted_3 = ["id", "title"];
2457
+ var _hoisted_4 = ["href"];
2458
+ var _hoisted_5 = { class: "docs-playground__title-text" };
2358
2459
  //#endregion
2359
2460
  //#region packages/playground/src/playground.vue
2360
2461
  var playground_default = /* @__PURE__ */ (0, vue.defineComponent)({
@@ -2372,7 +2473,9 @@ var playground_default = /* @__PURE__ */ (0, vue.defineComponent)({
2372
2473
  },
2373
2474
  options: { default: () => ({}) },
2374
2475
  previewInset: { default: 0 },
2375
- expand: { type: [Boolean, Number] },
2476
+ expandable: { type: [Boolean, Number] },
2477
+ title: { default: "" },
2478
+ id: { default: "" },
2376
2479
  previewOptions: {},
2377
2480
  locale: {}
2378
2481
  },
@@ -2396,6 +2499,8 @@ var playground_default = /* @__PURE__ */ (0, vue.defineComponent)({
2396
2499
  const sourceFiles = (0, vue.ref)(initialFiles);
2397
2500
  const currentEntry = (0, vue.ref)(initialEntry);
2398
2501
  const fileActiveFilename = (0, vue.ref)(initialEntry);
2502
+ const runtimeRef = (0, vue.ref)(null);
2503
+ const titleEl = (0, vue.ref)(null);
2399
2504
  const normalizeViews = (views) => {
2400
2505
  const normalized = [];
2401
2506
  for (const view of views) {
@@ -2406,12 +2511,25 @@ var playground_default = /* @__PURE__ */ (0, vue.defineComponent)({
2406
2511
  return normalized.length ? normalized : ["runtime"];
2407
2512
  };
2408
2513
  const normalizedViews = (0, vue.computed)(() => normalizeViews(props.views));
2514
+ const hasRuntimeView = (0, vue.computed)(() => normalizedViews.value.includes("runtime"));
2515
+ const hasFilesView = (0, vue.computed)(() => normalizedViews.value.includes("files"));
2409
2516
  const activeView = (0, vue.ref)(normalizedViews.value[0]);
2410
2517
  const runtimeActivated = (0, vue.ref)(props.styleless || activeView.value === "runtime");
2411
2518
  const normalizedViewportOptions = (0, vue.computed)(() => normalizeViewportOptions(props.viewportOptions));
2412
2519
  const activeViewport = (0, vue.ref)(resolveInitialViewport(props.viewport, normalizedViewportOptions.value));
2413
2520
  const selectableViewportOptions = (0, vue.computed)(() => includeActiveViewport(normalizedViewportOptions.value, activeViewport.value));
2414
2521
  const error = (0, vue.ref)(props.entry && initialFiles[props.entry] === void 0 ? t("playground.validation.entryMissing", { filename: props.entry }) : "");
2522
+ const displayTitle = (0, vue.computed)(() => props.title.trim());
2523
+ const titleId = (0, vue.computed)(() => resolvePlaygroundTitleId(displayTitle.value, props.id, (candidate) => {
2524
+ if (typeof document === "undefined") return false;
2525
+ const existing = document.getElementById(candidate);
2526
+ return !!existing && existing !== titleEl.value;
2527
+ }));
2528
+ const copyValue = (0, vue.computed)(() => sourceFiles.value[currentEntry.value] || "");
2529
+ /** runtime / 双视图始终有顶栏;files-only 仅有标题时渲染。 */
2530
+ const showHeader = (0, vue.computed)(() => hasRuntimeView.value || !!displayTitle.value);
2531
+ const showToolbar = (0, vue.computed)(() => hasRuntimeView.value);
2532
+ const showRuntimeActions = (0, vue.computed)(() => activeView.value === "runtime");
2415
2533
  (0, vue.watch)(locale, () => {
2416
2534
  if (props.entry && sourceFiles.value[props.entry] === void 0) error.value = t("playground.validation.entryMissing", { filename: props.entry });
2417
2535
  });
@@ -2425,6 +2543,15 @@ var playground_default = /* @__PURE__ */ (0, vue.defineComponent)({
2425
2543
  activeViewport.value = cloneViewport(viewport);
2426
2544
  emit("update:viewport", cloneViewport(viewport));
2427
2545
  };
2546
+ const handleRefresh = () => {
2547
+ runtimeRef.value?.refresh();
2548
+ };
2549
+ const handleEdit = () => {
2550
+ runtimeRef.value?.edit();
2551
+ };
2552
+ const handleOpenPopup = () => {
2553
+ runtimeRef.value?.openPopup();
2554
+ };
2428
2555
  const handleFileActive = (filename) => {
2429
2556
  if (sourceFiles.value[filename] !== void 0) fileActiveFilename.value = filename;
2430
2557
  };
@@ -2506,8 +2633,10 @@ var playground_default = /* @__PURE__ */ (0, vue.defineComponent)({
2506
2633
  options: __props.options,
2507
2634
  "preview-options": __props.previewOptions,
2508
2635
  "preview-inset": __props.previewInset,
2509
- expand: __props.expand,
2636
+ expandable: __props.expandable,
2510
2637
  styleless: true,
2638
+ title: __props.title,
2639
+ id: __props.id,
2511
2640
  viewport: activeViewport.value,
2512
2641
  "viewport-options": selectableViewportOptions.value,
2513
2642
  onFilesChange: handleFilesChange,
@@ -2519,29 +2648,68 @@ var playground_default = /* @__PURE__ */ (0, vue.defineComponent)({
2519
2648
  "options",
2520
2649
  "preview-options",
2521
2650
  "preview-inset",
2522
- "expand",
2651
+ "expandable",
2652
+ "title",
2653
+ "id",
2523
2654
  "viewport",
2524
2655
  "viewport-options"
2525
2656
  ])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
2526
2657
  key: 1,
2527
2658
  class: (0, vue.normalizeClass)(["docs-playground", { "docs-playground--files": activeView.value === "files" }])
2528
- }, [
2529
- error.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1, (0, vue.toDisplayString)(error.value), 1)) : (0, vue.createCommentVNode)("v-if", true),
2530
- runtimeActivated.value && normalizedViews.value.includes("runtime") ? (0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(runtime_default), {
2659
+ }, [error.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1, (0, vue.toDisplayString)(error.value), 1)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 1 }, [
2660
+ showHeader.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2, [displayTitle.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
2661
+ key: 0,
2662
+ ref_key: "titleEl",
2663
+ ref: titleEl,
2664
+ class: "docs-playground__title",
2665
+ id: titleId.value,
2666
+ tabindex: "-1",
2667
+ title: displayTitle.value
2668
+ }, [(0, vue.createElementVNode)("a", {
2669
+ class: "docs-playground__title-anchor",
2670
+ href: `#${titleId.value}`
2671
+ }, "#", 8, _hoisted_4), (0, vue.createElementVNode)("span", _hoisted_5, (0, vue.toDisplayString)(displayTitle.value), 1)], 8, _hoisted_3)) : (0, vue.createCommentVNode)("v-if", true), showToolbar.value ? ((0, vue.openBlock)(), (0, vue.createBlock)(toolbar_default, {
2531
2672
  key: 1,
2673
+ "copy-value": copyValue.value,
2674
+ viewport: activeViewport.value,
2675
+ "viewport-options": selectableViewportOptions.value,
2676
+ views: normalizedViews.value,
2677
+ "active-view": activeView.value,
2678
+ "show-runtime-actions": showRuntimeActions.value,
2679
+ "show-open-popup": hasRuntimeView.value,
2680
+ onRefresh: handleRefresh,
2681
+ onEdit: handleEdit,
2682
+ onOpenPopup: handleOpenPopup,
2683
+ onViewportChange: handleViewport,
2684
+ onViewChange: handleView
2685
+ }, null, 8, [
2686
+ "copy-value",
2687
+ "viewport",
2688
+ "viewport-options",
2689
+ "views",
2690
+ "active-view",
2691
+ "show-runtime-actions",
2692
+ "show-open-popup"
2693
+ ])) : (0, vue.createCommentVNode)("v-if", true)])) : (0, vue.createCommentVNode)("v-if", true),
2694
+ runtimeActivated.value && hasRuntimeView.value ? (0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(runtime_default), {
2695
+ key: 1,
2696
+ ref_key: "runtimeRef",
2697
+ ref: runtimeRef,
2532
2698
  files: sourceFiles.value,
2533
2699
  entry: currentEntry.value,
2534
2700
  options: __props.options,
2535
2701
  "preview-options": __props.previewOptions,
2536
2702
  "preview-inset": __props.previewInset,
2537
- expand: __props.expand,
2703
+ expandable: __props.expandable,
2704
+ "hide-chrome": true,
2705
+ title: __props.title,
2706
+ id: __props.id,
2538
2707
  "active-view": activeView.value,
2539
2708
  views: normalizedViews.value,
2540
2709
  viewport: activeViewport.value,
2541
2710
  "viewport-options": selectableViewportOptions.value,
2542
2711
  onFilesChange: handleFilesChange,
2543
2712
  onNavigate: _cache[1] || (_cache[1] = ($event) => emit("navigate", $event)),
2544
- onViewChange: handleView,
2545
2713
  onViewportChange: handleViewport
2546
2714
  }, null, 8, [
2547
2715
  "files",
@@ -2549,29 +2717,30 @@ var playground_default = /* @__PURE__ */ (0, vue.defineComponent)({
2549
2717
  "options",
2550
2718
  "preview-options",
2551
2719
  "preview-inset",
2552
- "expand",
2720
+ "expandable",
2721
+ "title",
2722
+ "id",
2553
2723
  "active-view",
2554
2724
  "views",
2555
2725
  "viewport",
2556
2726
  "viewport-options"
2557
- ])), [[vue.vShow, !error.value && activeView.value === "runtime"]]) : (0, vue.createCommentVNode)("v-if", true),
2558
- normalizedViews.value.includes("files") ? (0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(files_preview_default), {
2727
+ ])), [[vue.vShow, activeView.value === "runtime"]]) : (0, vue.createCommentVNode)("v-if", true),
2728
+ hasFilesView.value ? (0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(files_preview_default), {
2559
2729
  key: 2,
2560
2730
  files: sourceFiles.value,
2561
2731
  entry: currentEntry.value,
2562
2732
  "active-filename": fileActiveFilename.value,
2563
2733
  "active-view": activeView.value,
2564
2734
  views: normalizedViews.value,
2565
- onActiveChange: handleFileActive,
2566
- onViewChange: handleView
2735
+ onActiveChange: handleFileActive
2567
2736
  }, null, 8, [
2568
2737
  "files",
2569
2738
  "entry",
2570
2739
  "active-filename",
2571
2740
  "active-view",
2572
2741
  "views"
2573
- ])), [[vue.vShow, !error.value && activeView.value === "files"]]) : (0, vue.createCommentVNode)("v-if", true)
2574
- ], 2));
2742
+ ])), [[vue.vShow, activeView.value === "files"]]) : (0, vue.createCommentVNode)("v-if", true)
2743
+ ], 64))], 2));
2575
2744
  };
2576
2745
  }
2577
2746
  });
@@ -2598,8 +2767,10 @@ exports.registerVueHighlight = registerVueHighlight;
2598
2767
  exports.removePlaygroundImportMapOverride = removePlaygroundImportMapOverride;
2599
2768
  exports.removePlaygroundStyleOverride = removePlaygroundStyleOverride;
2600
2769
  exports.resolveHighlightLanguage = resolveHighlightLanguage;
2770
+ exports.resolvePlaygroundTitleId = resolvePlaygroundTitleId;
2601
2771
  exports.setPlaygroundImportMapOverrides = setPlaygroundImportMapOverrides;
2602
2772
  exports.setPlaygroundSiteModules = setPlaygroundSiteModules;
2603
2773
  exports.setPlaygroundSiteStyles = setPlaygroundSiteStyles;
2604
2774
  exports.setPlaygroundStyleOverrides = setPlaygroundStyleOverrides;
2775
+ exports.slugifyPlaygroundTitle = slugifyPlaygroundTitle;
2605
2776
  exports.vueHighlight = vueHighlight;