@dirwell/theme-crosswave 0.0.1 → 0.0.3
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 +13 -1
- package/dist/client.js +16 -16
- package/dist/index.d.mts +2 -1
- package/dist/index.mjs +136 -34
- package/dist/index.mjs.map +1 -1
- package/dist/{model-VZ01cfyg.d.mts → model-Bvw3-a6R.d.mts} +5 -3
- package/dist/model.d.mts +1 -1
- package/dist/source/Crosswave.vue +135 -11
- package/dist/source/shared/live-search.mjs +28 -0
- package/dist/source/shared/navigation.mjs +1 -0
- package/dist/styles.css +19 -1
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as ThemeAction, c as ThemeLabels, i as ThemePage, o as ThemeColumn, s as ThemeCustomization, t as FrameworkRenderer } from "./model-
|
|
1
|
+
import { a as ThemeAction, c as ThemeLabels, i as ThemePage, o as ThemeColumn, s as ThemeCustomization, t as FrameworkRenderer } from "./model-Bvw3-a6R.mjs";
|
|
2
2
|
import { ExplorerTheme, ListingEntry } from "@dirwell/core";
|
|
3
3
|
//#region src/icons.d.ts
|
|
4
4
|
type CrosswaveIcon = "all" | "folder" | "image" | "audio" | "video" | "document" | "other" | "link" | "back" | "search" | "pause" | "play" | "controller";
|
|
@@ -26,6 +26,7 @@ export interface CrosswaveThemeOptions extends ThemeCustomization {
|
|
|
26
26
|
readonly categories?: readonly CrosswaveCategory[];
|
|
27
27
|
readonly color?: "azure" | "violet" | "amber" | "rose" | "jade" | "graphite";
|
|
28
28
|
readonly gamepad?: boolean;
|
|
29
|
+
readonly archiveSearch?: boolean;
|
|
29
30
|
readonly backgroundMotion?: boolean;
|
|
30
31
|
}
|
|
31
32
|
export declare function createCrosswaveTheme(options?: CrosswaveThemeOptions, renderer?: FrameworkRenderer): ExplorerTheme;
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
3
|
import { copyJsonObject, escapeHtml, projectListingEntry } from "@dirwell/core";
|
|
4
|
-
import path from "node:path";
|
|
5
4
|
import mime from "mime";
|
|
6
5
|
import { computed, createSSRApp, nextTick, onBeforeUnmount, onMounted, ref, shallowRef, unref, watch, watchEffect } from "vue";
|
|
7
6
|
import { renderToString, ssrIncludeBooleanAttr, ssrInterpolate, ssrLooseContain, ssrLooseEqual, ssrRenderAttr, ssrRenderClass, ssrRenderDynamicAttr, ssrRenderList, ssrRenderSlot, ssrRenderStyle } from "vue/server-renderer";
|
|
@@ -11,20 +10,9 @@ import { ListingDataError, loadListing, parseListingEntries } from "@dirwell/cor
|
|
|
11
10
|
const pageAsset = (theme, directory, page = 1) => `${theme}-page-${createHash("sha256").update(directory).digest("hex").slice(0, 24)}-${page}.json`;
|
|
12
11
|
function folderDataHref(entry, context, theme) {
|
|
13
12
|
if (entry.exitsExplorer || entry.href === null || !(entry.kind === "directory" || entry.link?.targetKind === "directory")) return null;
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const target = new URL(entry.href, base);
|
|
18
|
-
const rootPath = root.pathname.endsWith("/") ? root.pathname : root.pathname.slice(0, root.pathname.lastIndexOf("/") + 1);
|
|
19
|
-
const directoryPath = target.pathname.endsWith("/") ? target.pathname : target.pathname.slice(0, target.pathname.lastIndexOf("/") + 1);
|
|
20
|
-
const logical = directoryPath.slice(rootPath.length).split("/").filter(Boolean).map(decodeURIComponent).join("/");
|
|
21
|
-
const filename = pageAsset(theme, logical);
|
|
22
|
-
if (context.pageDataHref !== void 0) return context.pageDataHref(theme, logical, 1);
|
|
23
|
-
if (context.mode === "mpa") return context.assetHref(filename);
|
|
24
|
-
const href = new URL(filename, new URL(directoryPath, target));
|
|
25
|
-
if (href.origin !== new URL(fake).origin) return href.href;
|
|
26
|
-
if (context.documentBaseHref === null && !entry.href.startsWith("/")) return path.posix.relative(context.directoryPath || ".", path.posix.join(logical, filename)).split("/").map((segment) => segment === ".." || segment === "." ? segment : encodeURIComponent(segment)).join("/");
|
|
27
|
-
return href.pathname;
|
|
13
|
+
const logical = context.directoryPathForEntry(entry.id);
|
|
14
|
+
if (logical === null) return null;
|
|
15
|
+
return context.pageDataHref?.(theme, logical, 1) ?? context.assetHrefForDirectory(logical, pageAsset(theme, logical));
|
|
28
16
|
}
|
|
29
17
|
function createThemePage(context, theme, title) {
|
|
30
18
|
const directoryPath = context.directory.current.relativePath;
|
|
@@ -33,20 +21,13 @@ function createThemePage(context, theme, title) {
|
|
|
33
21
|
mode: context.mode,
|
|
34
22
|
outputName: context.outputName,
|
|
35
23
|
assetHref: context.assetHref,
|
|
24
|
+
assetHrefForDirectory: context.assetHrefForDirectory,
|
|
25
|
+
directoryPathForEntry: context.directoryPathForEntry,
|
|
36
26
|
hrefForDirectory: context.hrefForDirectory,
|
|
37
27
|
documentBaseHref: context.documentBaseHref,
|
|
38
28
|
directoryPath
|
|
39
29
|
};
|
|
40
|
-
const dataForDirectory = (logicalPath) => context.hasPageForDirectory?.(logicalPath) === false ? null :
|
|
41
|
-
id: logicalPath,
|
|
42
|
-
name: logicalPath,
|
|
43
|
-
kind: "directory",
|
|
44
|
-
href: context.hrefForDirectory(logicalPath),
|
|
45
|
-
exitsExplorer: false,
|
|
46
|
-
size: 0,
|
|
47
|
-
modifiedAt: "",
|
|
48
|
-
link: null
|
|
49
|
-
}, safeContext, theme.name);
|
|
30
|
+
const dataForDirectory = (logicalPath) => context.hasPageForDirectory?.(logicalPath) === false ? null : context.pageDataHref?.(theme.name, logicalPath, 1) ?? context.assetHrefForDirectory(logicalPath, pageAsset(theme.name, logicalPath));
|
|
50
31
|
const entries = context.directory.entries.map((entry) => {
|
|
51
32
|
const record = projectListingEntry(entry, context);
|
|
52
33
|
return theme.entryData === void 0 ? record : {
|
|
@@ -68,6 +49,10 @@ function createThemePage(context, theme, title) {
|
|
|
68
49
|
manifestHref: context.listing?.manifestHref ?? null,
|
|
69
50
|
...context.listing ? { listingRevision: context.listing.revision } : {},
|
|
70
51
|
updatesHref: context.updatesHref ?? null,
|
|
52
|
+
...context.searchQueryHref ? {
|
|
53
|
+
searchQueryHref: context.searchQueryHref,
|
|
54
|
+
searchRefreshIntervalMs: context.searchRefreshIntervalMs
|
|
55
|
+
} : {},
|
|
71
56
|
total: context.listing?.page.total ?? entries.length,
|
|
72
57
|
entries,
|
|
73
58
|
sort: context.sort,
|
|
@@ -255,6 +240,34 @@ function entryCategories(entry, type, categories) {
|
|
|
255
240
|
return categories.filter((category) => category.match === "all" || folder && category.match === "folders" || !folder && category.match === "other" && !specific.length || specific.includes(category));
|
|
256
241
|
}
|
|
257
242
|
//#endregion
|
|
243
|
+
//#region ../shared-theme/src/live-search.ts
|
|
244
|
+
async function queryLiveArchive(href, query, signal) {
|
|
245
|
+
const url = new URL(href, document.baseURI);
|
|
246
|
+
if (url.origin !== location.origin) throw new Error("Unsafe search endpoint");
|
|
247
|
+
url.searchParams.set("q", query);
|
|
248
|
+
const response = await fetch(url, {
|
|
249
|
+
signal,
|
|
250
|
+
cache: "no-store"
|
|
251
|
+
});
|
|
252
|
+
if (!response.ok) throw new Error("Archive search unavailable");
|
|
253
|
+
const data = await response.json();
|
|
254
|
+
if (typeof data !== "object" || data === null || !("version" in data) || data.version !== 1 || !("results" in data) || !Array.isArray(data.results) || data.results.length > 1e4 || !("truncated" in data) || typeof data.truncated !== "boolean") throw new Error("Invalid archive results");
|
|
255
|
+
return {
|
|
256
|
+
records: data.results.map((entry) => {
|
|
257
|
+
if (typeof entry !== "object" || entry === null || !("name" in entry) || typeof entry.name !== "string" || !("path" in entry) || typeof entry.path !== "string" || !("kind" in entry) || !["file", "directory"].includes(String(entry.kind)) || !("href" in entry) || entry.href !== null && typeof entry.href !== "string") throw new Error("Invalid archive record");
|
|
258
|
+
const target = entry.href === null ? null : new URL(entry.href, url);
|
|
259
|
+
if (target && !["http:", "https:"].includes(target.protocol)) throw new Error("Unsafe archive link");
|
|
260
|
+
return {
|
|
261
|
+
name: entry.name,
|
|
262
|
+
path: entry.path,
|
|
263
|
+
href: target?.href ?? null,
|
|
264
|
+
exitsExplorer: entry.kind !== "directory"
|
|
265
|
+
};
|
|
266
|
+
}),
|
|
267
|
+
truncated: data.truncated
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
//#endregion
|
|
258
271
|
//#region ../shared-theme/src/customization.ts
|
|
259
272
|
/** Small serializable inputs shared by official themes; layout stays theme-owned. */
|
|
260
273
|
const defaultLabels = {
|
|
@@ -559,6 +572,7 @@ async function fetchThemePage(dataHref, pageHref, theme, signal, fresh = false,
|
|
|
559
572
|
if (data.ui !== void 0) resolveCustomization(data.ui);
|
|
560
573
|
const result = {
|
|
561
574
|
...data,
|
|
575
|
+
searchQueryHref: link(data.searchQueryHref ?? null),
|
|
562
576
|
updatesHref: link(data.updatesHref ?? null),
|
|
563
577
|
entries,
|
|
564
578
|
dataHref: source.href,
|
|
@@ -955,6 +969,71 @@ var App_server_default = {
|
|
|
955
969
|
setup(__props) {
|
|
956
970
|
const props = __props, model = shallowRef(restoreThemePage(props.model, Boolean(import.meta.hot))), entries = shallowRef(model.value.entries), ui = computed(() => resolveCustomization(model.value.ui));
|
|
957
971
|
const query = ref(""), category = ref(model.value.categories[0]?.id ?? null), selected = ref(null), ready = ref(false), busy = ref(false), error = ref(""), failure = ref(null), color = ref(props.model.color), paused = ref(!props.model.backgroundMotion), clock = ref(""), pad = ref(false), waveReady = ref(false), pendingUpdates = ref(null), canvas = ref(), search = ref(), listScroll = ref(), footerElement = ref(), scrollTop = ref(0), viewportHeight = ref(400), retryRequest = shallowRef(null), heights = shallowRef(/* @__PURE__ */ new Map());
|
|
972
|
+
const archiveOpen = ref(false), archiveQuery = ref(""), archiveRows = shallowRef([]), archiveStatus = ref(""), archiveFailed = ref(false), archiveTrigger = ref(), archiveDialog = ref(), archiveInput = ref();
|
|
973
|
+
let archiveAbort, archiveRequest = 0, archivePending = false, archiveDebouncing = false;
|
|
974
|
+
async function searchArchive() {
|
|
975
|
+
const token = ++archiveRequest;
|
|
976
|
+
archiveAbort?.abort();
|
|
977
|
+
const local = archiveAbort = new AbortController();
|
|
978
|
+
archiveFailed.value = false;
|
|
979
|
+
if (!archiveQuery.value.trim()) {
|
|
980
|
+
archiveRows.value = [];
|
|
981
|
+
archiveStatus.value = ui.value.labels.beginArchive;
|
|
982
|
+
return;
|
|
983
|
+
}
|
|
984
|
+
archiveStatus.value = ui.value.labels.searchingArchive;
|
|
985
|
+
archivePending = true;
|
|
986
|
+
try {
|
|
987
|
+
const result = await queryLiveArchive(model.value.searchQueryHref, archiveQuery.value.trim(), local.signal);
|
|
988
|
+
if (local.signal.aborted || token !== archiveRequest) return;
|
|
989
|
+
archiveRows.value = result.records;
|
|
990
|
+
archiveStatus.value = result.truncated ? label(ui.value, "truncatedResults", {
|
|
991
|
+
shown: result.records.length,
|
|
992
|
+
count: result.records.length + "+"
|
|
993
|
+
}) : label(ui.value, "archiveResults", { count: result.records.length });
|
|
994
|
+
} catch {
|
|
995
|
+
if (local.signal.aborted || token !== archiveRequest) return;
|
|
996
|
+
archiveRows.value = [];
|
|
997
|
+
archiveStatus.value = ui.value.labels.archiveError;
|
|
998
|
+
archiveFailed.value = true;
|
|
999
|
+
} finally {
|
|
1000
|
+
if (token === archiveRequest) archivePending = false;
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
watch([archiveOpen, archiveQuery], (_, __, cleanup) => {
|
|
1004
|
+
archiveAbort?.abort();
|
|
1005
|
+
archiveRequest++;
|
|
1006
|
+
archivePending = false;
|
|
1007
|
+
if (!archiveOpen.value) return;
|
|
1008
|
+
archiveDebouncing = true;
|
|
1009
|
+
const debounce = setTimeout(() => {
|
|
1010
|
+
archiveDebouncing = false;
|
|
1011
|
+
searchArchive();
|
|
1012
|
+
}, 300);
|
|
1013
|
+
cleanup(() => {
|
|
1014
|
+
clearTimeout(debounce);
|
|
1015
|
+
archiveDebouncing = false;
|
|
1016
|
+
});
|
|
1017
|
+
});
|
|
1018
|
+
watch(archiveOpen, async (open, _, cleanup) => {
|
|
1019
|
+
if (!open) {
|
|
1020
|
+
await nextTick();
|
|
1021
|
+
archiveTrigger.value?.focus();
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
1024
|
+
await nextTick();
|
|
1025
|
+
if (!archiveOpen.value) return;
|
|
1026
|
+
archiveDialog.value?.showModal();
|
|
1027
|
+
archiveInput.value?.focus();
|
|
1028
|
+
const timer = setInterval(() => {
|
|
1029
|
+
if (document.visibilityState === "visible" && archiveQuery.value.trim() && !archivePending && !archiveDebouncing) searchArchive();
|
|
1030
|
+
}, model.value.searchRefreshIntervalMs ?? 2e3);
|
|
1031
|
+
cleanup(() => {
|
|
1032
|
+
clearInterval(timer);
|
|
1033
|
+
archiveAbort?.abort();
|
|
1034
|
+
archiveRequest++;
|
|
1035
|
+
});
|
|
1036
|
+
});
|
|
958
1037
|
const complete = computed(() => entries.value.length === model.value.total), membership = (entry) => Array.isArray(entry.presentation?.categories) ? entry.presentation.categories : [];
|
|
959
1038
|
const rows = computed(() => entries.value.filter((entry) => membership(entry).includes(category.value) && `${entry.name} ${entry.link?.target ?? ""}`.toLocaleLowerCase().includes(query.value.trim().toLocaleLowerCase()))), active = computed(() => rows.value.find((entry) => entry.id === selected.value) ?? rows.value[0]), heading = computed(() => model.value.categories.find((item) => item.id === category.value)?.label ?? ui.value.labels.allFiles);
|
|
960
1039
|
const nodes = /* @__PURE__ */ new Map();
|
|
@@ -1037,9 +1116,6 @@ var App_server_default = {
|
|
|
1037
1116
|
if (listScroll.value) listScroll.value.scrollTop = 0;
|
|
1038
1117
|
});
|
|
1039
1118
|
let wave, gamepad, abort, navigation = 0, timer, lastPad = 0, pressed = /* @__PURE__ */ new Set(), disposed = false, padIdentity = null, motionQuery;
|
|
1040
|
-
function safeHref(entry) {
|
|
1041
|
-
return typeof location !== "undefined" && location.protocol === "file:" && directoryLike(entry) && !entry.exitsExplorer && entry.href?.endsWith("/") ? entry.href + "index.html" : entry.href;
|
|
1042
|
-
}
|
|
1043
1119
|
async function loadComplete() {
|
|
1044
1120
|
if (complete.value || !model.value.manifestHref || location.protocol === "file:") return;
|
|
1045
1121
|
const local = abort, token = navigation;
|
|
@@ -1156,6 +1232,7 @@ var App_server_default = {
|
|
|
1156
1232
|
}
|
|
1157
1233
|
}
|
|
1158
1234
|
function keyboard(event) {
|
|
1235
|
+
if (archiveOpen.value) return;
|
|
1159
1236
|
if (event.isComposing || event.altKey || event.ctrlKey || event.metaKey) return;
|
|
1160
1237
|
if (event.target?.closest?.("[data-dirwell-actions]")) return;
|
|
1161
1238
|
if (/INPUT|TEXTAREA|SELECT/.test(event.target?.tagName ?? "")) {
|
|
@@ -1186,6 +1263,7 @@ var App_server_default = {
|
|
|
1186
1263
|
}
|
|
1187
1264
|
}
|
|
1188
1265
|
function controller(value) {
|
|
1266
|
+
if (archiveOpen.value) return;
|
|
1189
1267
|
pad.value = !!value;
|
|
1190
1268
|
if (!value) {
|
|
1191
1269
|
pressed.clear();
|
|
@@ -1384,6 +1462,7 @@ var App_server_default = {
|
|
|
1384
1462
|
}
|
|
1385
1463
|
});
|
|
1386
1464
|
onBeforeUnmount(() => {
|
|
1465
|
+
archiveAbort?.abort();
|
|
1387
1466
|
disposed = true;
|
|
1388
1467
|
document.body.removeAttribute("data-cw-enhanced");
|
|
1389
1468
|
abort?.abort();
|
|
@@ -1418,7 +1497,10 @@ var App_server_default = {
|
|
|
1418
1497
|
ssrRenderList(model.value.categories, (item) => {
|
|
1419
1498
|
_push(`<button role="tab"${ssrRenderAttr("id", "cw-tab-" + item.id)} aria-controls="cw-panel"${ssrRenderAttr("aria-selected", category.value === item.id)}${ssrRenderAttr("tabindex", category.value === item.id ? 0 : -1)} class="${ssrRenderClass(["cw-category", { "cw-active": category.value === item.id }])}"${ssrIncludeBooleanAttr(!complete.value) ? " disabled" : ""}><span>${item.svg ?? ""}</span><span>${ssrInterpolate(item.label)}</span><small>${ssrInterpolate(entries.value.filter((entry) => membership(entry).includes(item.id)).length)}</small></button>`);
|
|
1420
1499
|
});
|
|
1421
|
-
_push(`<!--]--></div></nav><section class="cw-browser" id="cw-panel" role="tabpanel"${ssrRenderAttr("aria-labelledby", "cw-tab-" + category.value)}><div class="cw-list-head"><div class="cw-directory"><h2>${ssrInterpolate(heading.value)}</h2><span data-cw-count>${ssrInterpolate(unref(label)(ui.value, "items", { count: complete.value ? rows.value.length : entries.value.length }))}</span></div><label class="cw-search"><span>${ssrInterpolate(ui.value.labels.search)}</span><input type="search"${ssrRenderAttr("value", query.value)}${ssrIncludeBooleanAttr(!ready.value || !complete.value) ? " disabled" : ""}></label
|
|
1500
|
+
_push(`<!--]--></div></nav><section class="cw-browser" id="cw-panel" role="tabpanel"${ssrRenderAttr("aria-labelledby", "cw-tab-" + category.value)}><div class="cw-list-head"><div class="cw-directory"><h2>${ssrInterpolate(heading.value)}</h2><span data-cw-count>${ssrInterpolate(unref(label)(ui.value, "items", { count: complete.value ? rows.value.length : entries.value.length }))}</span></div><label class="cw-search"><span>${ssrInterpolate(ui.value.labels.search)}</span><input type="search"${ssrRenderAttr("value", query.value)}${ssrIncludeBooleanAttr(!ready.value || !complete.value) ? " disabled" : ""}></label>`);
|
|
1501
|
+
if (model.value.searchQueryHref) _push(`<button class="cw-archive-trigger"${ssrIncludeBooleanAttr(!ready.value) ? " disabled" : ""}>${ssrInterpolate(ui.value.labels.searchArchive)}</button>`);
|
|
1502
|
+
else _push(`<!---->`);
|
|
1503
|
+
_push(`</div><div class="cw-list-scroll"${ssrRenderAttr("data-virtual", virtual.value)}><ul class="cw-files">`);
|
|
1422
1504
|
if (model.value.parentHref) _push(`<li class="cw-row"><a${ssrRenderAttr("href", model.value.parentHref)} class="cw-entry">../</a></li>`);
|
|
1423
1505
|
else _push(`<!---->`);
|
|
1424
1506
|
if (start.value) _push(`<li aria-hidden="true" style="${ssrRenderStyle({ height: offsets.value[start.value] + "px" })}"></li>`);
|
|
@@ -1427,7 +1509,7 @@ var App_server_default = {
|
|
|
1427
1509
|
ssrRenderList(visibleRows.value, (entry, visibleIndex) => {
|
|
1428
1510
|
_push(`<li${ssrRenderAttr("aria-posinset", start.value + visibleIndex + 1)}${ssrRenderAttr("aria-setsize", rows.value.length)} class="${ssrRenderClass(["cw-row", { "cw-selected": active.value?.id === entry.id }])}" data-cw-entry${ssrRenderAttr("data-custom-columns", Boolean(model.value.ui?.columns))}${ssrRenderAttr("data-id", entry.id)}>`);
|
|
1429
1511
|
if (entry.href) {
|
|
1430
|
-
_push(`<a class="cw-entry"${ssrRenderAttr("href",
|
|
1512
|
+
_push(`<a class="cw-entry"${ssrRenderAttr("href", entry.href)}${ssrRenderAttr("target", entry.exitsExplorer ? "_blank" : void 0)}${ssrRenderAttr("rel", entry.exitsExplorer ? "noopener" : void 0)}>`);
|
|
1431
1513
|
ssrRenderSlot(_ctx.$slots, "row", {
|
|
1432
1514
|
model: model.value,
|
|
1433
1515
|
entry,
|
|
@@ -1472,7 +1554,7 @@ var App_server_default = {
|
|
|
1472
1554
|
_push(`<!--[-->`);
|
|
1473
1555
|
ssrRenderList(ui.value.actions, (action) => {
|
|
1474
1556
|
_push(`<!--[-->`);
|
|
1475
|
-
if (action === "download" && entry.href && !unref(directoryLike)(entry) && !entry.link?.unavailable) _push(`<a${ssrRenderAttr("href",
|
|
1557
|
+
if (action === "download" && entry.href && !unref(directoryLike)(entry) && !entry.link?.unavailable) _push(`<a${ssrRenderAttr("href", entry.href)} download>${ssrInterpolate(ui.value.labels.download)}</a>`);
|
|
1476
1558
|
else if (action !== "download") _push(`<button${ssrIncludeBooleanAttr(!ready.value || action === "copy-link" && !entry.href) ? " disabled" : ""}${ssrRenderAttr("aria-label", (action === "copy-link" ? ui.value.labels.copyLink : ui.value.labels.copyPath) + ": " + entry.name)}>${ssrInterpolate(action === "copy-link" ? ui.value.labels.copyLink : ui.value.labels.copyPath)}</button>`);
|
|
1477
1559
|
else _push(`<!---->`);
|
|
1478
1560
|
_push(`<!--]-->`);
|
|
@@ -1531,7 +1613,21 @@ var App_server_default = {
|
|
|
1531
1613
|
ssrRenderList(Object.keys(colors), (name) => {
|
|
1532
1614
|
_push(`<option${ssrRenderAttr("value", name)}${ssrIncludeBooleanAttr(Array.isArray(color.value) ? ssrLooseContain(color.value, name) : ssrLooseEqual(color.value, name)) ? " selected" : ""}>${ssrInterpolate(ui.value.labels[name])}</option>`);
|
|
1533
1615
|
});
|
|
1534
|
-
_push(`<!--]--></select></label><button class="cw-motion"${ssrIncludeBooleanAttr(!ready.value) ? " disabled" : ""}>${ssrInterpolate(paused.value ? ui.value.labels.resumeMotion : ui.value.labels.pauseMotion)}</button></footer
|
|
1616
|
+
_push(`<!--]--></select></label><button class="cw-motion"${ssrIncludeBooleanAttr(!ready.value) ? " disabled" : ""}>${ssrInterpolate(paused.value ? ui.value.labels.resumeMotion : ui.value.labels.pauseMotion)}</button></footer>`);
|
|
1617
|
+
if (archiveOpen.value) {
|
|
1618
|
+
_push(`<dialog class="cw-archive"${ssrRenderAttr("aria-label", ui.value.labels.searchArchive)}><h2>${ssrInterpolate(ui.value.labels.searchArchive)}</h2><input type="search"${ssrRenderAttr("value", archiveQuery.value)}${ssrRenderAttr("aria-label", ui.value.labels.archiveSearchInput)}><p role="status">${ssrInterpolate(archiveStatus.value)}</p>`);
|
|
1619
|
+
if (archiveFailed.value) _push(`<button>${ssrInterpolate(ui.value.labels.retry)}</button>`);
|
|
1620
|
+
else _push(`<!---->`);
|
|
1621
|
+
_push(`<ul><!--[-->`);
|
|
1622
|
+
ssrRenderList(archiveRows.value, (record) => {
|
|
1623
|
+
_push(`<li>`);
|
|
1624
|
+
if (record.href) _push(`<a${ssrRenderAttr("href", record.href)}${ssrRenderAttr("target", record.exitsExplorer ? "_blank" : void 0)}${ssrRenderAttr("rel", record.exitsExplorer ? "noopener" : void 0)}>${ssrInterpolate(record.path)}</a>`);
|
|
1625
|
+
else _push(`<span>${ssrInterpolate(record.path)}</span>`);
|
|
1626
|
+
_push(`</li>`);
|
|
1627
|
+
});
|
|
1628
|
+
_push(`<!--]--></ul><button>${ssrInterpolate(ui.value.labels.close)}</button></dialog>`);
|
|
1629
|
+
} else _push(`<!---->`);
|
|
1630
|
+
_push(`<!--]-->`);
|
|
1535
1631
|
};
|
|
1536
1632
|
}
|
|
1537
1633
|
};
|
|
@@ -1546,7 +1642,8 @@ function createCrosswaveTheme(options = {}, renderer) {
|
|
|
1546
1642
|
"categories",
|
|
1547
1643
|
"color",
|
|
1548
1644
|
"gamepad",
|
|
1549
|
-
"backgroundMotion"
|
|
1645
|
+
"backgroundMotion",
|
|
1646
|
+
"archiveSearch"
|
|
1550
1647
|
]);
|
|
1551
1648
|
if (options.title !== void 0 && (typeof options.title !== "string" || !options.title)) throw new TypeError("title must be a non-empty string");
|
|
1552
1649
|
if (options.color !== void 0 && ![
|
|
@@ -1557,7 +1654,11 @@ function createCrosswaveTheme(options = {}, renderer) {
|
|
|
1557
1654
|
"jade",
|
|
1558
1655
|
"graphite"
|
|
1559
1656
|
].includes(options.color)) throw new TypeError("Unsupported Crosswave color");
|
|
1560
|
-
for (const key of [
|
|
1657
|
+
for (const key of [
|
|
1658
|
+
"gamepad",
|
|
1659
|
+
"backgroundMotion",
|
|
1660
|
+
"archiveSearch"
|
|
1661
|
+
]) if (options[key] !== void 0 && typeof options[key] !== "boolean") throw new TypeError(`${key} must be a boolean`);
|
|
1561
1662
|
const ui = resolveCustomization(options);
|
|
1562
1663
|
const publishedUi = pickCustomization(options);
|
|
1563
1664
|
const categoryLabels = {
|
|
@@ -1592,6 +1693,7 @@ function createCrosswaveTheme(options = {}, renderer) {
|
|
|
1592
1693
|
const model = {
|
|
1593
1694
|
...createThemePage(context, theme, options.title ?? ui.brand.name ?? "Dirwell"),
|
|
1594
1695
|
...publishedUi === void 0 ? {} : { ui: publishedUi },
|
|
1696
|
+
searchQueryHref: options.archiveSearch === false ? null : context.searchQueryHref ?? null,
|
|
1595
1697
|
categories: categories.map(({ id, label, svg }) => ({
|
|
1596
1698
|
id,
|
|
1597
1699
|
label,
|