vitepress-plugin-filelist 0.6.0 → 0.6.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 CHANGED
@@ -8,7 +8,7 @@
8
8
  - ✅ 勾选文件;选中文件夹会自动加载并选中其下所有层级的文件
9
9
  - 📦 批量打包 ZIP(基于 `client-zip`),带进度、可取消;Chrome / Edge 边下载边写入磁盘,不受大小限制;保留目录结构,不同目录的同名文件不会互相覆盖
10
10
  - 📄 大目录每个文件夹先显示 200 条,可“显示更多 / 全部显示”
11
- - ⬇️ 单文件下载(`fs/get` 的 `raw_url`,回退 `/d/`)
11
+ - ⬇️ 单文件下载(`fs/get` 的 `raw_url`,回退 `/d/`):交给浏览器下载;OpenList 自己的 `/p/`、`/d/` 链接在当前页直接下载、不打开新标签页,存储直链在新标签页打开
12
12
  - 👁️ 弹窗预览(不跳转):图片、音视频、文本、PDF;Office 等其它类型显示文件信息与下载
13
13
  - 🔐 目录密码输入,可选只读 token
14
14
  - 🔎 当前树过滤,按名称 / 大小 / 日期排序
@@ -134,7 +134,8 @@ interface FileListSource {
134
134
 
135
135
  - Chrome / Edge(含较新的 Android Chrome):点“下载 ZIP”先弹出系统“另存为”窗口,之后边下载边写入,内存占用很小,不受大小限制
136
136
  - Firefox、Safari、iPhone:浏览器只能先把文件放进内存再打包。按已选总大小判断:超过 `zipWarnSize` 先确认,超过 `zipMaxSize` 不打包并建议分批
137
- - 打包期间操作条显示进度(大小与文件数),可随时取消;勾选暂时锁定。任一文件失败会整体取消并提示文件名
137
+ - 打包期间操作条显示进度(大小与文件数),可随时取消;勾选暂时锁定。任一文件失败会整体取消,并弹窗说明是哪个文件、什么原因
138
+ - 同时取 4 个文件(顺序不变),减少每个文件的网络等待;进度每 100 ms 更新一次
138
139
  - ZIP 只存储不压缩(网盘文件多为已压缩格式),支持超过 4 GB(Zip64)
139
140
 
140
141
  ## 大目录
@@ -92,6 +92,11 @@ interface FileListLabels {
92
92
  unlockFolder: string;
93
93
  /** @deprecated Network failures now append `corsHint`. */
94
94
  networkHint: string;
95
+ /** Title of the dialog when a batch ZIP fails (the reason is the text). */
96
+ batchFailedTitle: string;
97
+ batchFailedHint: string;
98
+ /** Single file handed to the browser's download manager. `{name}` */
99
+ downloadStarted: string;
95
100
  /** Batch progress detail. `{done}` `{total}` sizes, `{files}` `{count}` file counts */
96
101
  batchProgress: string;
97
102
  /** Batch finished. `{name}` `{count}` `{size}` */
@@ -329,6 +329,7 @@ function createOpenListApi(base, token) {
329
329
  return url;
330
330
  },
331
331
  directUrl,
332
+ isAttachmentUrl: (url) => !!root && (url.startsWith(`${root}/p/`) || url.startsWith(`${root}/d/`)),
332
333
  clearCache(path) {
333
334
  if (!path) urls.clear();
334
335
  else for (const key of [...urls.keys()]) if (isWithin(key, path)) urls.delete(key);
@@ -517,6 +518,7 @@ function createDemoApi(delay = 220) {
517
518
  }),
518
519
  fileUrl: async () => "",
519
520
  directUrl: () => "",
521
+ isAttachmentUrl: () => false,
520
522
  clearCache: () => {}
521
523
  };
522
524
  }
@@ -594,12 +596,21 @@ const _sfc_main$3 = /*@__PURE__*/ defineComponent({
594
596
  }
595
597
  });
596
598
  // src/client/download.ts
597
- /** Open a file URL; OpenList serves `/p/` and `/d/` as attachments, so this downloads. */
598
- function openUrl(url) {
599
+ /**
600
+ * Hand a file URL to the browser's own download manager.
601
+ *
602
+ * `sameTab` is for links known to answer as attachments (OpenList `/p/`, `/d/`):
603
+ * the browser downloads and the page stays put, with no tab flashing open.
604
+ * Other links (a storage provider's direct URL may display inline) open in a
605
+ * new tab so the document page is never replaced. `download` also keeps a
606
+ * same-origin link out of the VitePress router and names the file.
607
+ */
608
+ function openUrl(url, options) {
599
609
  const anchor = document.createElement("a");
600
610
  anchor.href = url;
601
- anchor.target = "_blank";
611
+ anchor.download = options.name;
602
612
  anchor.rel = "noopener";
613
+ if (!options.sameTab) anchor.target = "_blank";
603
614
  document.body.appendChild(anchor);
604
615
  anchor.click();
605
616
  anchor.remove();
@@ -641,10 +652,14 @@ async function pickZipFile(name) {
641
652
  }
642
653
  }
643
654
  /**
644
- * The ZIP as a stream: files are fetched one after another and passed through
655
+ * The ZIP as a stream: files are fetched a few at a time and passed through
645
656
  * as they arrive, stored without compression (most shared files are already
646
657
  * compressed). Clashing entry names get ` (2)`, ` (3)`...
647
658
  */
659
+ /** Files fetched at once: hides per-file latency, stays under the browser's 6 per host. */
660
+ const CONCURRENCY = 4;
661
+ /** Progress updates at most this often (ms), so the bar does not re-render per chunk. */
662
+ const PROGRESS_INTERVAL = 100;
648
663
  async function zipStream(files, options) {
649
664
  const { makeZip } = await import("client-zip");
650
665
  const progress = {
@@ -653,12 +668,28 @@ async function zipStream(files, options) {
653
668
  files: 0,
654
669
  totalFiles: files.length
655
670
  };
656
- const report = () => options.onProgress({ ...progress });
657
- report();
671
+ let reportedAt = 0;
672
+ const report = (force = false) => {
673
+ const now = Date.now();
674
+ if (!force && now - reportedAt < PROGRESS_INTERVAL) return;
675
+ reportedAt = now;
676
+ options.onProgress({ ...progress });
677
+ };
678
+ report(true);
658
679
  async function* entries() {
659
680
  const used = /* @__PURE__ */ new Set();
681
+ const ahead = [];
682
+ let started = 0;
683
+ const startNext = () => {
684
+ const file = files[started++];
685
+ const response = options.urlOf(file).then((url) => fetch(url, { signal: options.signal }));
686
+ response.catch(() => {});
687
+ ahead.push(response);
688
+ };
689
+ while (started < files.length && ahead.length < CONCURRENCY) startNext();
660
690
  for (const file of files) {
661
- const response = await fetch(await options.urlOf(file), { signal: options.signal });
691
+ const response = await ahead.shift();
692
+ if (started < files.length) startNext();
662
693
  if (!response.ok || !response.body) throw new Error(`${file.name}:HTTP ${response.status}`);
663
694
  const counted = response.body.pipeThrough(new TransformStream({
664
695
  transform(chunk, controller) {
@@ -668,7 +699,7 @@ async function zipStream(files, options) {
668
699
  },
669
700
  flush() {
670
701
  progress.files += 1;
671
- report();
702
+ report(progress.files === progress.totalFiles);
672
703
  }
673
704
  }));
674
705
  const modified = new Date(file.modified);
@@ -868,6 +899,9 @@ const fileListLocales = {
868
899
  forgetPassword: "忘记",
869
900
  unlockFolder: "输入 {name} 的密码",
870
901
  networkHint: "可能被跨域拦截:请检查 OpenList 的 cors.allow_origins,或 OpenList-Worker 的 ALLOW_URLS。",
902
+ batchFailedTitle: "打包失败",
903
+ batchFailedHint: "可以减少勾选的文件后重试。",
904
+ downloadStarted: "已交给浏览器下载:{name}",
871
905
  batchProgress: "{done} / {total} · {files} / {count} 个文件",
872
906
  batchDone: "已打包 {name}({count} 个文件,{size})",
873
907
  batchCanceled: "已取消下载",
@@ -945,6 +979,9 @@ const fileListLocales = {
945
979
  forgetPassword: "Forget",
946
980
  unlockFolder: "Enter the password for {name}",
947
981
  networkHint: "Possibly blocked by CORS: check cors.allow_origins in OpenList, or ALLOW_URLS in OpenList-Worker.",
982
+ batchFailedTitle: "Could not create the ZIP",
983
+ batchFailedHint: "Try again with fewer files selected.",
984
+ downloadStarted: "Downloading {name} in your browser",
948
985
  batchProgress: "{done} / {total} · {files} / {count} files",
949
986
  batchDone: "Saved {name} ({count} files, {size})",
950
987
  batchCanceled: "Download cancelled",
@@ -2244,7 +2281,12 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
2244
2281
  return;
2245
2282
  }
2246
2283
  try {
2247
- openUrl(await fileUrlOf(node));
2284
+ const url = await fileUrlOf(node);
2285
+ openUrl(url, {
2286
+ sameTab: api.value.isAttachmentUrl(url),
2287
+ name: node.name
2288
+ });
2289
+ showToast(t("downloadStarted", { name: node.name }));
2248
2290
  } catch (error) {
2249
2291
  showToast(t("downloadFailed", { message: errorText(error) }));
2250
2292
  }
@@ -2260,9 +2302,28 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
2260
2302
  max: bytes(props.zipMaxSize, touch ? 1024 : 2048)
2261
2303
  };
2262
2304
  }
2305
+ /** A ZIP question or notice: over the warning size, over the limit, or failed. */
2263
2306
  const zipNotice = ref(null);
2264
2307
  /** Only desktop browsers get “use Chrome or Edge”; on iPhone every browser is Safari. */
2265
2308
  const zipTip = computed(() => typeof window !== "undefined" && !window.matchMedia?.("(pointer: coarse)").matches ? t("zipStreamTip") : "");
2309
+ const zipDialog = computed(() => {
2310
+ const notice = zipNotice.value;
2311
+ if (!notice) return null;
2312
+ if (notice.kind === "failed") return {
2313
+ title: t("batchFailedTitle"),
2314
+ text: notice.message,
2315
+ tip: t("batchFailedHint"),
2316
+ cancel: t("gotIt")
2317
+ };
2318
+ const warn = notice.kind === "warn";
2319
+ return {
2320
+ title: t(warn ? "zipWarnTitle" : "zipBlockTitle", { size: formatSize(notice.size) }),
2321
+ text: t(warn ? "zipWarnText" : "zipBlockText", { limit: formatSize(notice.limit) }),
2322
+ tip: zipTip.value,
2323
+ confirm: warn ? t("zipContinue") : void 0,
2324
+ cancel: warn ? t("cancel") : t("gotIt")
2325
+ };
2326
+ });
2266
2327
  function zipName() {
2267
2328
  return zipFileName(props.title || t("defaultZip"));
2268
2329
  }
@@ -2331,7 +2392,11 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
2331
2392
  }));
2332
2393
  selected.value = /* @__PURE__ */ new Set();
2333
2394
  } catch (error) {
2334
- showToast(controller.signal.aborted ? t("batchCanceled") : t("batchFailed", { message: errorText(error) }));
2395
+ if (controller.signal.aborted) showToast(t("batchCanceled"));
2396
+ else zipNotice.value = {
2397
+ kind: "failed",
2398
+ message: errorText(error)
2399
+ };
2335
2400
  } finally {
2336
2401
  zipAbort = null;
2337
2402
  batchBusy.value = false;
@@ -2779,12 +2844,12 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
2779
2844
  createElementVNode("div", _hoisted_73, [createElementVNode("span", null, toDisplayString(t("loaded", { count: allFiles.value.length })) + " · " + toDisplayString(t("totalSize", { size: unref(formatSize)(unref(totalSize)(allFiles.value)) })), 1)]),
2780
2845
  toast.value ? (openBlock(), createElementBlock("div", _hoisted_74, toDisplayString(toast.value), 1)) : createCommentVNode("v-if", true),
2781
2846
  createVNode(_sfc_main$3, {
2782
- open: !!zipNotice.value,
2783
- title: zipNotice.value ? t(zipNotice.value.kind === "warn" ? "zipWarnTitle" : "zipBlockTitle", { size: unref(formatSize)(zipNotice.value.size) }) : "",
2784
- text: zipNotice.value ? t(zipNotice.value.kind === "warn" ? "zipWarnText" : "zipBlockText", { limit: unref(formatSize)(zipNotice.value.limit) }) : "",
2785
- tip: zipTip.value,
2786
- "confirm-label": zipNotice.value?.kind === "warn" ? t("zipContinue") : void 0,
2787
- "cancel-label": zipNotice.value?.kind === "warn" ? t("cancel") : t("gotIt"),
2847
+ open: !!zipDialog.value,
2848
+ title: zipDialog.value?.title ?? "",
2849
+ text: zipDialog.value?.text ?? "",
2850
+ tip: zipDialog.value?.tip,
2851
+ "confirm-label": zipDialog.value?.confirm,
2852
+ "cancel-label": zipDialog.value?.cancel ?? "",
2788
2853
  onConfirm: confirmZip,
2789
2854
  onClose: _cache[4] || (_cache[4] = ($event) => zipNotice.value = null)
2790
2855
  }, null, 8, [
@@ -92,6 +92,11 @@ interface FileListLabels {
92
92
  unlockFolder: string;
93
93
  /** @deprecated Network failures now append `corsHint`. */
94
94
  networkHint: string;
95
+ /** Title of the dialog when a batch ZIP fails (the reason is the text). */
96
+ batchFailedTitle: string;
97
+ batchFailedHint: string;
98
+ /** Single file handed to the browser's download manager. `{name}` */
99
+ downloadStarted: string;
95
100
  /** Batch progress detail. `{done}` `{total}` sizes, `{files}` `{count}` file counts */
96
101
  batchProgress: string;
97
102
  /** Batch finished. `{name}` `{count}` `{size}` */
@@ -329,6 +329,7 @@ function createOpenListApi(base, token) {
329
329
  return url;
330
330
  },
331
331
  directUrl,
332
+ isAttachmentUrl: (url) => !!root && (url.startsWith(`${root}/p/`) || url.startsWith(`${root}/d/`)),
332
333
  clearCache(path) {
333
334
  if (!path) urls.clear();
334
335
  else for (const key of [...urls.keys()]) if (isWithin(key, path)) urls.delete(key);
@@ -517,6 +518,7 @@ function createDemoApi(delay = 220) {
517
518
  }),
518
519
  fileUrl: async () => "",
519
520
  directUrl: () => "",
521
+ isAttachmentUrl: () => false,
520
522
  clearCache: () => {}
521
523
  };
522
524
  }
@@ -575,12 +577,21 @@ _sfc_main$3.setup = (props, ctx) => {
575
577
  return _sfc_setup$3 ? _sfc_setup$3(props, ctx) : void 0;
576
578
  };
577
579
  // src/client/download.ts
578
- /** Open a file URL; OpenList serves `/p/` and `/d/` as attachments, so this downloads. */
579
- function openUrl(url) {
580
+ /**
581
+ * Hand a file URL to the browser's own download manager.
582
+ *
583
+ * `sameTab` is for links known to answer as attachments (OpenList `/p/`, `/d/`):
584
+ * the browser downloads and the page stays put, with no tab flashing open.
585
+ * Other links (a storage provider's direct URL may display inline) open in a
586
+ * new tab so the document page is never replaced. `download` also keeps a
587
+ * same-origin link out of the VitePress router and names the file.
588
+ */
589
+ function openUrl(url, options) {
580
590
  const anchor = document.createElement("a");
581
591
  anchor.href = url;
582
- anchor.target = "_blank";
592
+ anchor.download = options.name;
583
593
  anchor.rel = "noopener";
594
+ if (!options.sameTab) anchor.target = "_blank";
584
595
  document.body.appendChild(anchor);
585
596
  anchor.click();
586
597
  anchor.remove();
@@ -600,10 +611,14 @@ function zipFileName(title) {
600
611
  return `${title.replace(/[\\/:*?"<>|]/g, "_")}.zip`;
601
612
  }
602
613
  /**
603
- * The ZIP as a stream: files are fetched one after another and passed through
614
+ * The ZIP as a stream: files are fetched a few at a time and passed through
604
615
  * as they arrive, stored without compression (most shared files are already
605
616
  * compressed). Clashing entry names get ` (2)`, ` (3)`...
606
617
  */
618
+ /** Files fetched at once: hides per-file latency, stays under the browser's 6 per host. */
619
+ const CONCURRENCY = 4;
620
+ /** Progress updates at most this often (ms), so the bar does not re-render per chunk. */
621
+ const PROGRESS_INTERVAL = 100;
607
622
  async function zipStream(files, options) {
608
623
  const { makeZip } = await import("client-zip");
609
624
  const progress = {
@@ -612,12 +627,28 @@ async function zipStream(files, options) {
612
627
  files: 0,
613
628
  totalFiles: files.length
614
629
  };
615
- const report = () => options.onProgress({ ...progress });
616
- report();
630
+ let reportedAt = 0;
631
+ const report = (force = false) => {
632
+ const now = Date.now();
633
+ if (!force && now - reportedAt < PROGRESS_INTERVAL) return;
634
+ reportedAt = now;
635
+ options.onProgress({ ...progress });
636
+ };
637
+ report(true);
617
638
  async function* entries() {
618
639
  const used = /* @__PURE__ */ new Set();
640
+ const ahead = [];
641
+ let started = 0;
642
+ const startNext = () => {
643
+ const file = files[started++];
644
+ const response = options.urlOf(file).then((url) => fetch(url, { signal: options.signal }));
645
+ response.catch(() => {});
646
+ ahead.push(response);
647
+ };
648
+ while (started < files.length && ahead.length < CONCURRENCY) startNext();
619
649
  for (const file of files) {
620
- const response = await fetch(await options.urlOf(file), { signal: options.signal });
650
+ const response = await ahead.shift();
651
+ if (started < files.length) startNext();
621
652
  if (!response.ok || !response.body) throw new Error(`${file.name}:HTTP ${response.status}`);
622
653
  const counted = response.body.pipeThrough(new TransformStream({
623
654
  transform(chunk, controller) {
@@ -627,7 +658,7 @@ async function zipStream(files, options) {
627
658
  },
628
659
  flush() {
629
660
  progress.files += 1;
630
- report();
661
+ report(progress.files === progress.totalFiles);
631
662
  }
632
663
  }));
633
664
  const modified = new Date(file.modified);
@@ -821,6 +852,9 @@ const fileListLocales = {
821
852
  forgetPassword: "忘记",
822
853
  unlockFolder: "输入 {name} 的密码",
823
854
  networkHint: "可能被跨域拦截:请检查 OpenList 的 cors.allow_origins,或 OpenList-Worker 的 ALLOW_URLS。",
855
+ batchFailedTitle: "打包失败",
856
+ batchFailedHint: "可以减少勾选的文件后重试。",
857
+ downloadStarted: "已交给浏览器下载:{name}",
824
858
  batchProgress: "{done} / {total} · {files} / {count} 个文件",
825
859
  batchDone: "已打包 {name}({count} 个文件,{size})",
826
860
  batchCanceled: "已取消下载",
@@ -898,6 +932,9 @@ const fileListLocales = {
898
932
  forgetPassword: "Forget",
899
933
  unlockFolder: "Enter the password for {name}",
900
934
  networkHint: "Possibly blocked by CORS: check cors.allow_origins in OpenList, or ALLOW_URLS in OpenList-Worker.",
935
+ batchFailedTitle: "Could not create the ZIP",
936
+ batchFailedHint: "Try again with fewer files selected.",
937
+ downloadStarted: "Downloading {name} in your browser",
901
938
  batchProgress: "{done} / {total} · {files} / {count} files",
902
939
  batchDone: "Saved {name} ({count} files, {size})",
903
940
  batchCanceled: "Download cancelled",
@@ -1707,14 +1744,38 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
1707
1744
  return;
1708
1745
  }
1709
1746
  try {
1710
- openUrl(await fileUrlOf(node));
1747
+ const url = await fileUrlOf(node);
1748
+ openUrl(url, {
1749
+ sameTab: api.value.isAttachmentUrl(url),
1750
+ name: node.name
1751
+ });
1752
+ showToast(t("downloadStarted", { name: node.name }));
1711
1753
  } catch (error) {
1712
1754
  showToast(t("downloadFailed", { message: errorText(error) }));
1713
1755
  }
1714
1756
  }
1757
+ /** A ZIP question or notice: over the warning size, over the limit, or failed. */
1715
1758
  const zipNotice = ref(null);
1716
1759
  /** Only desktop browsers get “use Chrome or Edge”; on iPhone every browser is Safari. */
1717
1760
  const zipTip = computed(() => typeof window !== "undefined" && !window.matchMedia?.("(pointer: coarse)").matches ? t("zipStreamTip") : "");
1761
+ const zipDialog = computed(() => {
1762
+ const notice = zipNotice.value;
1763
+ if (!notice) return null;
1764
+ if (notice.kind === "failed") return {
1765
+ title: t("batchFailedTitle"),
1766
+ text: notice.message,
1767
+ tip: t("batchFailedHint"),
1768
+ cancel: t("gotIt")
1769
+ };
1770
+ const warn = notice.kind === "warn";
1771
+ return {
1772
+ title: t(warn ? "zipWarnTitle" : "zipBlockTitle", { size: formatSize(notice.size) }),
1773
+ text: t(warn ? "zipWarnText" : "zipBlockText", { limit: formatSize(notice.limit) }),
1774
+ tip: zipTip.value,
1775
+ confirm: warn ? t("zipContinue") : void 0,
1776
+ cancel: warn ? t("cancel") : t("gotIt")
1777
+ };
1778
+ });
1718
1779
  function zipName() {
1719
1780
  return zipFileName(props.title || t("defaultZip"));
1720
1781
  }
@@ -1745,7 +1806,11 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
1745
1806
  }));
1746
1807
  selected.value = /* @__PURE__ */ new Set();
1747
1808
  } catch (error) {
1748
- showToast(controller.signal.aborted ? t("batchCanceled") : t("batchFailed", { message: errorText(error) }));
1809
+ if (controller.signal.aborted) showToast(t("batchCanceled"));
1810
+ else zipNotice.value = {
1811
+ kind: "failed",
1812
+ message: errorText(error)
1813
+ };
1749
1814
  } finally {
1750
1815
  zipAbort = null;
1751
1816
  batchBusy.value = false;
@@ -2042,12 +2107,12 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
2042
2107
  if (toast.value) _push(`<div class="fl-toast" role="status">${ssrInterpolate(toast.value)}</div>`);
2043
2108
  else _push(`<!---->`);
2044
2109
  _push(ssrRenderComponent(_sfc_main$3, {
2045
- open: !!zipNotice.value,
2046
- title: zipNotice.value ? t(zipNotice.value.kind === "warn" ? "zipWarnTitle" : "zipBlockTitle", { size: unref(formatSize)(zipNotice.value.size) }) : "",
2047
- text: zipNotice.value ? t(zipNotice.value.kind === "warn" ? "zipWarnText" : "zipBlockText", { limit: unref(formatSize)(zipNotice.value.limit) }) : "",
2048
- tip: zipTip.value,
2049
- "confirm-label": zipNotice.value?.kind === "warn" ? t("zipContinue") : void 0,
2050
- "cancel-label": zipNotice.value?.kind === "warn" ? t("cancel") : t("gotIt"),
2110
+ open: !!zipDialog.value,
2111
+ title: zipDialog.value?.title ?? "",
2112
+ text: zipDialog.value?.text ?? "",
2113
+ tip: zipDialog.value?.tip,
2114
+ "confirm-label": zipDialog.value?.confirm,
2115
+ "cancel-label": zipDialog.value?.cancel ?? "",
2051
2116
  onConfirm: confirmZip,
2052
2117
  onClose: ($event) => zipNotice.value = null
2053
2118
  }, null, _parent));
@@ -787,11 +787,13 @@
787
787
  }
788
788
 
789
789
  .fl-toast {
790
- position: absolute;
791
- bottom: 14px;
790
+ /* the viewport, not the card: a long list would push the card's bottom off screen */
791
+ position: fixed;
792
+ bottom: calc(24px + env(safe-area-inset-bottom));
792
793
  left: 50%;
793
- z-index: 5;
794
- max-width: 92%;
794
+ z-index: 100;
795
+ box-sizing: border-box;
796
+ max-width: min(560px, calc(100vw - 32px));
795
797
  padding: 7px 14px;
796
798
  overflow: hidden;
797
799
  font-size: 13px;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vitepress-plugin-filelist",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "packageManager": "pnpm@11.25.0",
5
5
  "type": "module",
6
6
  "description": "OpenList file browser for VitePress: tree view, batch ZIP download, i18n, password and token support.",