@dirwell/theme-crosswave 0.0.0-stage → 0.0.1-alpha
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/LICENSE +21 -0
- package/README.md +16 -2
- package/dist/THIRD_PARTY_NOTICES.txt +166 -0
- package/dist/client.js +231 -0
- package/dist/component.css +0 -0
- package/dist/index.d.mts +34 -0
- package/dist/index.mjs +972 -0
- package/dist/index.mjs.map +1 -0
- package/dist/model-D4-K54I9.d.mts +53 -0
- package/dist/model.d.mts +2 -0
- package/dist/model.mjs +1 -0
- package/dist/source/Crosswave.vue +569 -0
- package/dist/source/component.d.mts +4 -0
- package/dist/source/shared/icons.mjs +12 -0
- package/dist/source/shared/navigation.mjs +294 -0
- package/dist/source/shared/records.mjs +60 -0
- package/dist/source/wave.mjs +132 -0
- package/dist/styles.css +23 -0
- package/package.json +49 -3
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
// ../core/src/json.ts
|
|
2
|
+
function copyJsonObject(value) {
|
|
3
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4
|
+
const copy = (input, depth) => {
|
|
5
|
+
if (depth > 32) throw new TypeError("Presentation data is too deeply nested");
|
|
6
|
+
if (input === null || typeof input === "string" || typeof input === "boolean") return input;
|
|
7
|
+
if (typeof input === "number" && Number.isFinite(input)) return input;
|
|
8
|
+
if (typeof input !== "object" || input === null || seen.has(input))
|
|
9
|
+
throw new TypeError("Presentation data must be finite, acyclic JSON");
|
|
10
|
+
seen.add(input);
|
|
11
|
+
try {
|
|
12
|
+
if (Array.isArray(input)) return input.map((item) => copy(item, depth + 1));
|
|
13
|
+
if (Object.getPrototypeOf(input) !== Object.prototype && Object.getPrototypeOf(input) !== null)
|
|
14
|
+
throw new TypeError("Presentation data must use plain objects");
|
|
15
|
+
return Object.fromEntries(
|
|
16
|
+
Object.entries(input).map(([key, item]) => [key, copy(item, depth + 1)])
|
|
17
|
+
);
|
|
18
|
+
} finally {
|
|
19
|
+
seen.delete(input);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
23
|
+
throw new TypeError("Presentation data must be an object");
|
|
24
|
+
const result = copy(value, 0);
|
|
25
|
+
if (typeof result !== "object" || result === null || Array.isArray(result))
|
|
26
|
+
throw new TypeError("Presentation data must be an object");
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// ../core/src/client.ts
|
|
31
|
+
var ListingDataError = class extends Error {
|
|
32
|
+
name = "ListingDataError";
|
|
33
|
+
};
|
|
34
|
+
var StaleListingError = class extends ListingDataError {
|
|
35
|
+
};
|
|
36
|
+
var object = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
37
|
+
var count = (value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
38
|
+
var kind = (value) => typeof value === "string" && ["directory", "file", "symlink", "other"].includes(value);
|
|
39
|
+
function string(value, name) {
|
|
40
|
+
if (typeof value !== "string") throw new ListingDataError(`Invalid ${name}`);
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
function boolean(value, name) {
|
|
44
|
+
if (typeof value !== "boolean") throw new ListingDataError(`Invalid ${name}`);
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
function href(value, base) {
|
|
48
|
+
if (value === null) return null;
|
|
49
|
+
const result = new URL(string(value, "href"), base);
|
|
50
|
+
if (!["http:", "https:"].includes(result.protocol))
|
|
51
|
+
throw new ListingDataError("Unsupported listing link protocol");
|
|
52
|
+
return result.href;
|
|
53
|
+
}
|
|
54
|
+
function entry(value, base) {
|
|
55
|
+
if (!object(value) || !kind(value.kind) || typeof value.size !== "number" || !Number.isFinite(value.size) || value.size < 0)
|
|
56
|
+
throw new ListingDataError("Invalid listing entry");
|
|
57
|
+
let link = null;
|
|
58
|
+
if (value.link !== null) {
|
|
59
|
+
if (!object(value.link)) throw new ListingDataError("Invalid link metadata");
|
|
60
|
+
const targetKind = value.link.targetKind;
|
|
61
|
+
if (targetKind !== null && (!kind(targetKind) || targetKind === "symlink"))
|
|
62
|
+
throw new ListingDataError("Invalid target kind");
|
|
63
|
+
const targetSize = value.link.targetSize;
|
|
64
|
+
if (targetSize !== null && (typeof targetSize !== "number" || !Number.isFinite(targetSize) || targetSize < 0))
|
|
65
|
+
throw new ListingDataError("Invalid target size");
|
|
66
|
+
link = {
|
|
67
|
+
target: string(value.link.target, "target"),
|
|
68
|
+
targetKind,
|
|
69
|
+
targetSize,
|
|
70
|
+
unavailable: boolean(value.link.unavailable, "unavailable"),
|
|
71
|
+
cycle: boolean(value.link.cycle, "cycle")
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
...value.presentation === void 0 ? {} : { presentation: copyJsonObject(value.presentation) },
|
|
76
|
+
id: string(value.id, "id"),
|
|
77
|
+
name: string(value.name, "name"),
|
|
78
|
+
kind: value.kind,
|
|
79
|
+
href: href(value.href, base),
|
|
80
|
+
exitsExplorer: boolean(value.exitsExplorer, "exitsExplorer"),
|
|
81
|
+
size: value.size,
|
|
82
|
+
modifiedAt: string(value.modifiedAt, "modifiedAt"),
|
|
83
|
+
link
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function manifest(value) {
|
|
87
|
+
if (!object(value) || value.version !== 1 || !count(value.total) || !Array.isArray(value.blocks) || !object(value.sort))
|
|
88
|
+
throw new ListingDataError("Invalid listing manifest");
|
|
89
|
+
const sort = value.sort;
|
|
90
|
+
if (typeof sort.field !== "string" || !["name", "size", "modified"].includes(sort.field) || typeof sort.direction !== "string" || !["asc", "desc"].includes(sort.direction) || typeof sort.nameMode !== "string" || !["locale", "natural", "unicode"].includes(sort.nameMode) || typeof sort.directoriesFirst !== "boolean")
|
|
91
|
+
throw new ListingDataError("Invalid listing order");
|
|
92
|
+
const field = sort.field === "size" ? "size" : sort.field === "modified" ? "modified" : "name";
|
|
93
|
+
const direction = sort.direction === "desc" ? "desc" : "asc";
|
|
94
|
+
const nameMode = sort.nameMode === "unicode" ? "unicode" : sort.nameMode === "locale" ? "locale" : "natural";
|
|
95
|
+
const blocks = value.blocks.map((item) => {
|
|
96
|
+
if (!object(item) || !count(item.offset) || !count(item.count))
|
|
97
|
+
throw new ListingDataError("Invalid block descriptor");
|
|
98
|
+
return { href: string(item.href, "block href"), offset: item.offset, count: item.count };
|
|
99
|
+
});
|
|
100
|
+
if (blocks.length === 0) throw new ListingDataError("Missing blocks");
|
|
101
|
+
return {
|
|
102
|
+
version: 1,
|
|
103
|
+
revision: string(value.revision, "revision"),
|
|
104
|
+
directory: string(value.directory, "directory"),
|
|
105
|
+
hrefBase: string(value.hrefBase, "href base"),
|
|
106
|
+
total: value.total,
|
|
107
|
+
sort: { field, direction, nameMode, directoriesFirst: sort.directoriesFirst },
|
|
108
|
+
blocks
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
async function loadListing(manifestUrl, options = {}) {
|
|
112
|
+
const request = options.fetch ?? fetch;
|
|
113
|
+
const maxEntries = options.maxEntries ?? 1e5;
|
|
114
|
+
if (!count(maxEntries)) throw new ListingDataError("Invalid entry limit");
|
|
115
|
+
const source = new URL(manifestUrl);
|
|
116
|
+
if (!["http:", "https:"].includes(source.protocol))
|
|
117
|
+
throw new ListingDataError("Listing loading requires HTTP(S); use native file navigation");
|
|
118
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
119
|
+
try {
|
|
120
|
+
const init = {
|
|
121
|
+
...options.signal === void 0 ? {} : { signal: options.signal },
|
|
122
|
+
cache: attempt === 0 ? options.cache ?? "default" : "reload"
|
|
123
|
+
};
|
|
124
|
+
const response = await request(source, init);
|
|
125
|
+
if (!response.ok) throw new ListingDataError(`Manifest request failed: ${response.status}`);
|
|
126
|
+
const current = manifest(await response.json());
|
|
127
|
+
if (current.total > maxEntries)
|
|
128
|
+
throw new ListingDataError("Listing exceeds the configured entry limit");
|
|
129
|
+
const base = new URL(current.hrefBase, source);
|
|
130
|
+
if (!["http:", "https:"].includes(base.protocol))
|
|
131
|
+
throw new ListingDataError("Unsupported href base protocol");
|
|
132
|
+
const entries = [];
|
|
133
|
+
const ids = /* @__PURE__ */ new Set();
|
|
134
|
+
for (const descriptor of current.blocks) {
|
|
135
|
+
if (descriptor.offset !== entries.length || descriptor.count + entries.length > current.total)
|
|
136
|
+
throw new ListingDataError("Invalid block coverage");
|
|
137
|
+
const blockUrl = new URL(descriptor.href, source);
|
|
138
|
+
if (blockUrl.origin !== source.origin || !["http:", "https:"].includes(blockUrl.protocol))
|
|
139
|
+
throw new ListingDataError("Block leaves the manifest origin");
|
|
140
|
+
const blockResponse = await request(blockUrl, init);
|
|
141
|
+
if (blockResponse.status === 404 || blockResponse.status === 410)
|
|
142
|
+
throw new StaleListingError("Block no longer available");
|
|
143
|
+
if (!blockResponse.ok)
|
|
144
|
+
throw new ListingDataError(`Block request failed: ${blockResponse.status}`);
|
|
145
|
+
const data = await blockResponse.json();
|
|
146
|
+
if (!object(data) || data.version !== 1 || data.revision !== current.revision)
|
|
147
|
+
throw new StaleListingError("Listing revision changed");
|
|
148
|
+
if (data.offset !== descriptor.offset || data.total !== current.total || !Array.isArray(data.entries) || data.entries.length !== descriptor.count)
|
|
149
|
+
throw new ListingDataError("Invalid block envelope");
|
|
150
|
+
for (const raw of data.entries) {
|
|
151
|
+
const record = entry(raw, base);
|
|
152
|
+
if (ids.has(record.id)) throw new ListingDataError("Duplicate entry ID");
|
|
153
|
+
ids.add(record.id);
|
|
154
|
+
entries.push(record);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (entries.length !== current.total) throw new ListingDataError("Incomplete listing");
|
|
158
|
+
return { manifest: current, entries };
|
|
159
|
+
} catch (error) {
|
|
160
|
+
if (options.signal?.aborted || !(error instanceof StaleListingError) || attempt === 1)
|
|
161
|
+
throw error;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
throw new ListingDataError("Listing unavailable");
|
|
165
|
+
}
|
|
166
|
+
function parseListingEntries(value, baseHref, maxEntries = 1e5) {
|
|
167
|
+
if (!Array.isArray(value) || value.length > maxEntries)
|
|
168
|
+
throw new ListingDataError("Invalid page slice");
|
|
169
|
+
const base = new URL(baseHref), ids = /* @__PURE__ */ new Set();
|
|
170
|
+
const result = value.map((raw) => entry(raw, base));
|
|
171
|
+
for (const record of result) {
|
|
172
|
+
if (ids.has(record.id)) throw new ListingDataError("Duplicate entry ID");
|
|
173
|
+
ids.add(record.id);
|
|
174
|
+
}
|
|
175
|
+
return result;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ../shared-theme/src/navigation.ts
|
|
179
|
+
async function fetchThemePage(dataHref, pageHref, theme, signal, fresh = false, attempt = 0) {
|
|
180
|
+
const source = new URL(dataHref, document.baseURI);
|
|
181
|
+
if (source.origin !== location.origin)
|
|
182
|
+
throw new ListingDataError("Folder leaves the theme origin");
|
|
183
|
+
const response = await fetch(source, { signal, cache: fresh ? "no-store" : "default" });
|
|
184
|
+
if (!response.ok) throw new ListingDataError("Unavailable folder");
|
|
185
|
+
const value = await response.json();
|
|
186
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
187
|
+
throw new ListingDataError("Invalid folder snapshot");
|
|
188
|
+
const data = value;
|
|
189
|
+
if (data.version !== 1 || data.theme !== theme || typeof data.title !== "string" || typeof data.path !== "string" || !Number.isSafeInteger(data.total) || Number(data.total) < 0 || !Array.isArray(data.breadcrumbs))
|
|
190
|
+
throw new ListingDataError("Unsupported folder snapshot");
|
|
191
|
+
if (data.metadataHead !== void 0 && typeof data.metadataHead !== "string")
|
|
192
|
+
throw new ListingDataError("Invalid folder metadata");
|
|
193
|
+
const base = document.querySelector("base")?.href ?? pageHref;
|
|
194
|
+
const link = (raw) => {
|
|
195
|
+
if (raw === null) return null;
|
|
196
|
+
if (typeof raw !== "string") throw new ListingDataError("Invalid folder link");
|
|
197
|
+
const url = new URL(raw, base);
|
|
198
|
+
if (!["http:", "https:"].includes(url.protocol) || url.origin !== location.origin)
|
|
199
|
+
throw new ListingDataError("Unsupported folder link");
|
|
200
|
+
return url.href;
|
|
201
|
+
};
|
|
202
|
+
const entries = parseListingEntries(data.entries, base).map((entry2) => ({
|
|
203
|
+
...entry2,
|
|
204
|
+
...entry2.presentation ? {
|
|
205
|
+
presentation: {
|
|
206
|
+
...entry2.presentation,
|
|
207
|
+
folderDataHref: link(entry2.presentation.folderDataHref ?? null)
|
|
208
|
+
}
|
|
209
|
+
} : {}
|
|
210
|
+
}));
|
|
211
|
+
if (entries.length > Number(data.total)) throw new ListingDataError("Invalid folder count");
|
|
212
|
+
const result = {
|
|
213
|
+
...data,
|
|
214
|
+
updatesHref: link(data.updatesHref ?? null),
|
|
215
|
+
entries,
|
|
216
|
+
dataHref: source.href,
|
|
217
|
+
manifestHref: link(data.manifestHref),
|
|
218
|
+
rootHref: link(data.rootHref),
|
|
219
|
+
rootDataHref: link(data.rootDataHref),
|
|
220
|
+
parentHref: link(data.parentHref),
|
|
221
|
+
parentDataHref: link(data.parentDataHref),
|
|
222
|
+
breadcrumbs: data.breadcrumbs.map((raw) => {
|
|
223
|
+
if (typeof raw !== "object" || raw === null || !("name" in raw) || !("href" in raw) || !("dataHref" in raw) || typeof raw.name !== "string")
|
|
224
|
+
throw new ListingDataError("Invalid breadcrumb");
|
|
225
|
+
return { name: raw.name, href: link(raw.href), dataHref: link(raw.dataHref) };
|
|
226
|
+
})
|
|
227
|
+
};
|
|
228
|
+
if (fresh && result.manifestHref) {
|
|
229
|
+
const loaded = await loadListing(result.manifestHref, { signal, cache: "no-store" });
|
|
230
|
+
if (loaded.manifest.total !== data.total || data.listingRevision !== void 0 && loaded.manifest.revision !== data.listingRevision) {
|
|
231
|
+
if (attempt < 2) return fetchThemePage(dataHref, pageHref, theme, signal, true, attempt + 1);
|
|
232
|
+
throw new ListingDataError("Folder changed while refreshing");
|
|
233
|
+
}
|
|
234
|
+
result.entries = [...loaded.entries];
|
|
235
|
+
}
|
|
236
|
+
return result;
|
|
237
|
+
}
|
|
238
|
+
var hotModels = /* @__PURE__ */ new WeakMap();
|
|
239
|
+
function restoreThemePage(initial, hot) {
|
|
240
|
+
if (!hot || typeof document === "undefined") return initial;
|
|
241
|
+
const root = document.querySelector("[data-dirwell-theme]");
|
|
242
|
+
if (!root) return initial;
|
|
243
|
+
const snapshot = hotModels.get(root) ?? initial;
|
|
244
|
+
hotModels.set(root, snapshot);
|
|
245
|
+
return snapshot;
|
|
246
|
+
}
|
|
247
|
+
function applyThemeMetadata(page, pageHref) {
|
|
248
|
+
const root = document.querySelector("[data-dirwell-theme]");
|
|
249
|
+
if (root && hotModels.has(root)) hotModels.set(root, page);
|
|
250
|
+
document.title = typeof page.title === "string" ? page.title : "";
|
|
251
|
+
const template = document.createElement("template");
|
|
252
|
+
template.innerHTML = typeof page.metadataHead === "string" ? page.metadataHead : "";
|
|
253
|
+
document.head.querySelectorAll("[data-dirwell-metadata]").forEach((element) => element.remove());
|
|
254
|
+
const base = document.querySelector("base")?.href ?? pageHref;
|
|
255
|
+
const url = (value) => {
|
|
256
|
+
try {
|
|
257
|
+
const target = new URL(value, base);
|
|
258
|
+
return ["http:", "https:"].includes(target.protocol) ? target.href : null;
|
|
259
|
+
} catch {
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
for (const element of template.content.children) {
|
|
264
|
+
if (!element.hasAttribute("data-dirwell-metadata")) continue;
|
|
265
|
+
let next;
|
|
266
|
+
if (element.tagName === "META") {
|
|
267
|
+
const attribute = element.hasAttribute("property") ? "property" : "name";
|
|
268
|
+
const key = element.getAttribute(attribute) ?? "";
|
|
269
|
+
if (!/^(?:description|og:[a-z_:]+|twitter:[a-z_:]+)$/i.test(key)) continue;
|
|
270
|
+
let content = element.getAttribute("content") ?? "";
|
|
271
|
+
if (["og:image", "og:url", "twitter:image"].includes(key)) {
|
|
272
|
+
const resolved = url(content);
|
|
273
|
+
if (resolved === null) continue;
|
|
274
|
+
content = resolved;
|
|
275
|
+
}
|
|
276
|
+
next = document.createElement("meta");
|
|
277
|
+
next.setAttribute(attribute, key);
|
|
278
|
+
next.setAttribute("content", content);
|
|
279
|
+
} else if (element.tagName === "LINK" && element.getAttribute("rel") === "canonical") {
|
|
280
|
+
const href2 = url(element.getAttribute("href") ?? "");
|
|
281
|
+
if (href2 === null) continue;
|
|
282
|
+
next = document.createElement("link");
|
|
283
|
+
next.setAttribute("rel", "canonical");
|
|
284
|
+
next.setAttribute("href", href2);
|
|
285
|
+
} else continue;
|
|
286
|
+
next.setAttribute("data-dirwell-metadata", "");
|
|
287
|
+
document.head.append(next);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
export {
|
|
291
|
+
applyThemeMetadata,
|
|
292
|
+
fetchThemePage,
|
|
293
|
+
restoreThemePage
|
|
294
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// ../shared-theme/src/records.ts
|
|
2
|
+
var directoryLike = (entry) => entry.kind === "directory" || entry.link?.targetKind === "directory";
|
|
3
|
+
var entryType = (entry) => entry.kind === "symlink" ? "link" : directoryLike(entry) ? "directory" : "file";
|
|
4
|
+
function fuzzy(query, value) {
|
|
5
|
+
let score = 0, start = 0, last = -2;
|
|
6
|
+
for (const character of query.trim().toLocaleLowerCase()) {
|
|
7
|
+
const index = value.toLocaleLowerCase().indexOf(character, start);
|
|
8
|
+
if (index < 0) return null;
|
|
9
|
+
if (index === last + 1) score += 8;
|
|
10
|
+
if (index === 0 || /[\s/_.-]/.test(value[index - 1] ?? "")) score += 5;
|
|
11
|
+
score += Math.max(0, 4 - index * 0.05);
|
|
12
|
+
last = index;
|
|
13
|
+
start = index + 1;
|
|
14
|
+
}
|
|
15
|
+
return score - value.length * 0.01;
|
|
16
|
+
}
|
|
17
|
+
function visibleRecords(entries, query, types, sort) {
|
|
18
|
+
return entries.map((entry) => ({ entry, score: fuzzy(query, `${entry.name} ${entry.link?.target ?? ""}`) })).filter((item) => types.includes(entryType(item.entry)) && item.score !== null).sort((left, right) => {
|
|
19
|
+
if (query.trim() && left.score !== right.score) return (right.score ?? 0) - (left.score ?? 0);
|
|
20
|
+
const a = left.entry, b = right.entry;
|
|
21
|
+
if (sort.directoriesFirst && directoryLike(a) !== directoryLike(b))
|
|
22
|
+
return directoryLike(a) ? -1 : 1;
|
|
23
|
+
const name = () => sort.nameMode === "unicode" ? compareUnicode(a.name, b.name) : a.name.localeCompare(b.name, void 0, {
|
|
24
|
+
numeric: sort.nameMode === "natural",
|
|
25
|
+
sensitivity: "base"
|
|
26
|
+
});
|
|
27
|
+
const primary = (sort.field === "name" ? name() : sort.field === "size" ? (a.kind === "directory" ? 0 : a.size) - (b.kind === "directory" ? 0 : b.size) : a.modifiedAt.localeCompare(b.modifiedAt)) || name();
|
|
28
|
+
return (sort.direction === "asc" ? primary : -primary) || compareUnicode(a.id, b.id);
|
|
29
|
+
}).map((item) => item.entry);
|
|
30
|
+
}
|
|
31
|
+
function compareUnicode(left, right) {
|
|
32
|
+
const a = [...left], b = [...right];
|
|
33
|
+
for (let i = 0; i < Math.min(a.length, b.length); i++) {
|
|
34
|
+
const delta = (a[i]?.codePointAt(0) ?? 0) - (b[i]?.codePointAt(0) ?? 0);
|
|
35
|
+
if (delta) return delta;
|
|
36
|
+
}
|
|
37
|
+
return a.length - b.length;
|
|
38
|
+
}
|
|
39
|
+
function size(bytes) {
|
|
40
|
+
const units = ["B", "KiB", "MiB", "GiB", "TiB"];
|
|
41
|
+
let value = bytes, index = 0;
|
|
42
|
+
while (value >= 1024 && index < 4) {
|
|
43
|
+
value /= 1024;
|
|
44
|
+
index++;
|
|
45
|
+
}
|
|
46
|
+
return `${value.toFixed(index === 0 || value >= 100 ? 0 : 1)} ${units[index]}`;
|
|
47
|
+
}
|
|
48
|
+
function modified(value, local = false) {
|
|
49
|
+
const date = new Date(value);
|
|
50
|
+
if (Number.isNaN(date.getTime())) return "Unknown";
|
|
51
|
+
return local ? date.toLocaleString(void 0, { dateStyle: "short", timeStyle: "short" }) : `${date.toISOString().slice(0, 16).replace("T", " ")} UTC`;
|
|
52
|
+
}
|
|
53
|
+
export {
|
|
54
|
+
directoryLike,
|
|
55
|
+
entryType,
|
|
56
|
+
fuzzy,
|
|
57
|
+
modified,
|
|
58
|
+
size,
|
|
59
|
+
visibleRecords
|
|
60
|
+
};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
export function createWave(canvas, colors, root, moving, onReady) {
|
|
2
|
+
let gl;
|
|
3
|
+
try {
|
|
4
|
+
gl = canvas.getContext("webgl", {
|
|
5
|
+
alpha: false,
|
|
6
|
+
antialias: false,
|
|
7
|
+
powerPreference: "low-power",
|
|
8
|
+
});
|
|
9
|
+
} catch {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
if (!gl) return null;
|
|
13
|
+
const vertex = "attribute vec2 p;void main(){gl_Position=vec4(p,0.,1.);}";
|
|
14
|
+
const fragment = `precision highp float;uniform vec2 resolution;uniform float time;uniform vec3 tint;
|
|
15
|
+
void main(){vec2 uv=gl_FragCoord.xy/resolution;float x=uv.x;float y=uv.y;float t=time;
|
|
16
|
+
vec3 ground=mix(tint*.22,tint,clamp(y*.85+x*.1,0.,1.));ground+=vec3(.035)*pow(max(0.,1.-distance(uv,vec2(.2,.9))),3.);
|
|
17
|
+
float light=0.;for(int i=0;i<3;i++){float k=float(i);float center=.40+.07*sin(x*4.2+t*.17+k*.8)+.035*cos(x*7.1-t*.11+k*1.4)+k*.024;
|
|
18
|
+
float breadth=.012+.037*(.5+.5*sin(x*2.7+t*.09+k));float d=y-center;float sheet=exp(-pow(d/breadth,2.));float edge=exp(-abs(d-breadth*.65)*430.);
|
|
19
|
+
float fold=exp(-abs(d+breadth*.35)*170.);float taper=pow(sin(clamp(x,0.,1.)*3.14159),.6);light+=(sheet*.07+edge*.23+fold*.09)*taper;}
|
|
20
|
+
ground+=mix(vec3(.6,.8,1.),vec3(1.),.75)*min(light,.12);gl_FragColor=vec4(ground,1.);}`;
|
|
21
|
+
const shader = (type, source) => {
|
|
22
|
+
const s = gl.createShader(type);
|
|
23
|
+
if (!s) return null;
|
|
24
|
+
gl.shaderSource(s, source);
|
|
25
|
+
gl.compileShader(s);
|
|
26
|
+
if (!gl.getShaderParameter(s, gl.COMPILE_STATUS)) {
|
|
27
|
+
gl.deleteShader(s);
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
return s;
|
|
31
|
+
};
|
|
32
|
+
const vs = shader(gl.VERTEX_SHADER, vertex),
|
|
33
|
+
fs = shader(gl.FRAGMENT_SHADER, fragment);
|
|
34
|
+
if (!vs || !fs) {
|
|
35
|
+
if (vs) gl.deleteShader(vs);
|
|
36
|
+
if (fs) gl.deleteShader(fs);
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
const program = gl.createProgram();
|
|
40
|
+
if (!program) return null;
|
|
41
|
+
gl.attachShader(program, vs);
|
|
42
|
+
gl.attachShader(program, fs);
|
|
43
|
+
gl.linkProgram(program);
|
|
44
|
+
gl.deleteShader(vs);
|
|
45
|
+
gl.deleteShader(fs);
|
|
46
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
47
|
+
gl.deleteProgram(program);
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
const buffer = gl.createBuffer();
|
|
51
|
+
if (!buffer) {
|
|
52
|
+
gl.deleteProgram(program);
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
56
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);
|
|
57
|
+
gl.useProgram(program);
|
|
58
|
+
const p = gl.getAttribLocation(program, "p");
|
|
59
|
+
gl.enableVertexAttribArray(p);
|
|
60
|
+
gl.vertexAttribPointer(p, 2, gl.FLOAT, false, 0, 0);
|
|
61
|
+
const r = gl.getUniformLocation(program, "resolution"),
|
|
62
|
+
t = gl.getUniformLocation(program, "time"),
|
|
63
|
+
c = gl.getUniformLocation(program, "tint");
|
|
64
|
+
let frame = 0,
|
|
65
|
+
last = 0,
|
|
66
|
+
lost = false,
|
|
67
|
+
frozenTime = 17;
|
|
68
|
+
const draw = (now) => {
|
|
69
|
+
if (lost) return;
|
|
70
|
+
const ratio = Math.min(devicePixelRatio || 1, 1.5, 1600 / innerWidth, 1000 / innerHeight),
|
|
71
|
+
width = Math.round(innerWidth * ratio),
|
|
72
|
+
height = Math.round(innerHeight * ratio);
|
|
73
|
+
if (canvas.width !== width || canvas.height !== height) {
|
|
74
|
+
canvas.width = width;
|
|
75
|
+
canvas.height = height;
|
|
76
|
+
gl.viewport(0, 0, width, height);
|
|
77
|
+
}
|
|
78
|
+
if (moving()) frozenTime = (Date.now() % 86400000) / 1000;
|
|
79
|
+
gl.uniform2f(r, width, height);
|
|
80
|
+
gl.uniform1f(t, frozenTime);
|
|
81
|
+
gl.uniform3fv(c, colors[root.dataset.cwColor] ?? colors.azure);
|
|
82
|
+
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
83
|
+
onReady(true);
|
|
84
|
+
last = now;
|
|
85
|
+
};
|
|
86
|
+
const tick = (now) => {
|
|
87
|
+
frame = 0;
|
|
88
|
+
if (!moving() || lost) return;
|
|
89
|
+
if (now - last >= 33) draw(now);
|
|
90
|
+
frame = requestAnimationFrame(tick);
|
|
91
|
+
};
|
|
92
|
+
const stop = () => {
|
|
93
|
+
cancelAnimationFrame(frame);
|
|
94
|
+
frame = 0;
|
|
95
|
+
};
|
|
96
|
+
const sync = () => {
|
|
97
|
+
stop();
|
|
98
|
+
if (lost) return;
|
|
99
|
+
draw(0);
|
|
100
|
+
if (moving()) frame = requestAnimationFrame(tick);
|
|
101
|
+
};
|
|
102
|
+
const contextLost = (event) => {
|
|
103
|
+
event.preventDefault();
|
|
104
|
+
lost = true;
|
|
105
|
+
stop();
|
|
106
|
+
onReady(false);
|
|
107
|
+
};
|
|
108
|
+
canvas.addEventListener("webglcontextlost", contextLost);
|
|
109
|
+
const contextRestored = () => {
|
|
110
|
+
onReady(false);
|
|
111
|
+
lost = true;
|
|
112
|
+
};
|
|
113
|
+
canvas.addEventListener("webglcontextrestored", contextRestored);
|
|
114
|
+
const resized = () => draw(0);
|
|
115
|
+
addEventListener("resize", resized);
|
|
116
|
+
return {
|
|
117
|
+
dispose() {
|
|
118
|
+
stop();
|
|
119
|
+
removeEventListener("resize", resized);
|
|
120
|
+
canvas.removeEventListener("webglcontextlost", contextLost);
|
|
121
|
+
canvas.removeEventListener("webglcontextrestored", contextRestored);
|
|
122
|
+
gl.deleteBuffer(buffer);
|
|
123
|
+
gl.deleteProgram(program);
|
|
124
|
+
},
|
|
125
|
+
draw,
|
|
126
|
+
sync,
|
|
127
|
+
stop,
|
|
128
|
+
get available() {
|
|
129
|
+
return !lost;
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}
|
package/dist/styles.css
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
|
|
2
|
+
:root{color-scheme:dark;--cw-top:#2b4f85;--cw-bottom:#091a3a;--cw-text:#f7fbff;--cw-muted:#edf4fc;--cw-focus:#fff;--cw-ease:cubic-bezier(.16,1,.3,1);font-family:"Segoe UI",Helvetica,Arial,sans-serif;font-synthesis:none}
|
|
3
|
+
:root[data-cw-color=violet]{--cw-top:#5c407d;--cw-bottom:#241532;--cw-muted:#edf4fc}:root[data-cw-color=amber]{--cw-top:#704d1a;--cw-bottom:#30200b;--cw-muted:#edf4fc}:root[data-cw-color=rose]{--cw-top:#704055;--cw-bottom:#351b29;--cw-muted:#edf4fc}:root[data-cw-color=jade]{--cw-top:#215e52;--cw-bottom:#0b2a28;--cw-muted:#edf4fc}:root[data-cw-color=graphite]{--cw-top:#424d61;--cw-bottom:#181d28;--cw-muted:#edf4fc}
|
|
4
|
+
*{box-sizing:border-box}[hidden]{display:none!important}html{scroll-padding-bottom:110px;min-height:100%;background:var(--cw-bottom)}body{margin:0;color:var(--cw-text);background:var(--cw-bottom);min-height:100svh;font-size:16px;line-height:1.5}::selection{background:#d0e4fc;color:#132848}a{color:inherit;text-decoration:none}button,input,select{font:inherit;color:inherit}button,select{cursor:pointer}button{border:0}a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible{outline:2px solid var(--cw-focus);outline-offset:6px;border-radius:3px}svg{display:block;width:24px;height:24px;flex:none}.cw-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.cw-skip{position:fixed;left:24px;top:16px;padding:12px 18px;background:#fff;color:#142e53;z-index:20;transform:translateY(-150%)}.cw-skip:focus{transform:none}
|
|
5
|
+
.cw-background{position:fixed;inset:0;z-index:0;pointer-events:none;background:radial-gradient(ellipse at 28% 4%,#c0d7ff12,transparent 68%),linear-gradient(165deg,var(--cw-top),var(--cw-bottom));view-transition-name:cw-background;overflow:hidden}.cw-background canvas{width:100%;height:100%;display:block}.cw-fallback-wave{position:absolute;inset:0;width:100%;height:100%;fill:none;stroke:#d5e8ff;stroke-width:18;opacity:.06;filter:blur(3px)}.cw-background[data-ready] .cw-fallback-wave{display:none}
|
|
6
|
+
.cw-top,.cw-stage,.cw-bottom,.cw-noscript{position:relative;z-index:1}.cw-top{display:flex;align-items:center;gap:32px;padding:30px 48px 20px;min-height:92px;view-transition-name:cw-header}.cw-brand{font-size:20px;font-weight:500;letter-spacing:-.02em;white-space:nowrap}.cw-brand>a:hover{text-decoration:underline;text-underline-offset:5px}.cw-location{display:flex;gap:12px;align-items:center;min-width:0;flex-wrap:wrap;font-size:13px;color:var(--cw-muted)}.cw-location a:hover{text-decoration:underline;text-underline-offset:5px}.cw-separator{opacity:.6}.cw-clock{margin-left:auto;white-space:nowrap;font-variant-numeric:tabular-nums;font-size:14px;color:var(--cw-muted)}
|
|
7
|
+
.cw-stage{max-width:1500px;margin:28px auto 110px;padding:0 72px;display:grid;grid-template-columns:minmax(0,1.55fr) minmax(220px,1fr);column-gap:80px}.cw-rail{grid-column:1/-1;margin:0 -12px 22px;overflow-x:auto;padding:12px 12px 24px;scrollbar-width:none}.cw-rail::-webkit-scrollbar{display:none}.cw-categories{padding-left:104px;padding-right:calc(100vw - 200px);display:flex;gap:32px;min-width:max-content;align-items:flex-start}.cw-category{position:relative;display:flex;flex-direction:column;align-items:center;gap:12px;min-width:94px;min-height:96px;background:none;padding:10px 4px;color:var(--cw-muted);transition:color .2s,transform .3s var(--cw-ease);flex:none}.cw-category svg{width:40px;height:40px;filter:drop-shadow(0 3px 2px #07182a55)}.cw-category span{font-size:14px;white-space:nowrap}.cw-category small{font-size:10px;position:absolute;right:8px;top:0;color:var(--cw-muted)}.cw-category:hover{color:#fff;transform:translateY(-3px)}.cw-category.cw-active{color:#fff;transform:scale(1.1)}.cw-category.cw-active:after{content:"";position:absolute;left:calc(50% - 12px);bottom:-8px;width:24px;height:2px;background:#e6f2ff;box-shadow:0 3px 10px #bddaff55}
|
|
8
|
+
.cw-browser{padding-left:104px;min-width:0;view-transition-name:cw-browser}.cw-list-head{display:flex;align-items:center;justify-content:space-between;gap:24px;min-height:58px;margin:0 0 12px;padding:0 4px}.cw-directory{display:flex;align-items:center;gap:16px;min-width:0}.cw-directory h2{font-size:17px;font-weight:400;margin:0;white-space:nowrap}.cw-directory>[data-cw-count]{font-size:12px;color:var(--cw-muted);white-space:nowrap}.cw-parent,.cw-parent-placeholder{width:34px;height:44px;display:flex;align-items:center;justify-content:center;flex:none}.cw-parent:hover{background:#ffffff12;border-radius:5px}.cw-search{display:flex;align-items:center;gap:8px;border-bottom:1px solid #d5e7ff55;min-width:140px;width:220px;padding:6px 0}.cw-search svg{width:17px;height:17px;color:var(--cw-muted)}.cw-search input{background:none;border:0;min-width:0;width:100%;outline-offset:3px;font-size:13px;caret-color:#fff}.cw-search input::placeholder{color:var(--cw-muted);opacity:1}.cw-search button{background:none;font-size:11px;padding:6px 0}.cw-search input::-webkit-search-cancel-button{display:none}
|
|
9
|
+
.cw-list-scroll{max-height:calc(100svh - 365px);min-height:220px;overflow-y:auto;overflow-x:hidden;scrollbar-width:thin;scrollbar-color:#d6e8fa66 transparent;padding:14px 12px 24px 8px;scroll-padding-block:20px;overscroll-behavior:contain}.cw-list-scroll::-webkit-scrollbar{width:5px}.cw-list-scroll::-webkit-scrollbar-thumb{background:#d6e8fa66;border-radius:4px}.cw-files{list-style:none;padding:0;margin:0}.cw-row{margin:0;min-height:76px;padding:0}.cw-entry{display:flex;align-items:center;gap:25px;padding:14px 18px;min-height:76px;transition:background .2s,opacity .2s,transform .3s var(--cw-ease);border-radius:7px}.cw-entry-icon{display:flex;width:42px;min-width:42px;align-items:center;justify-content:center;transition:transform .3s var(--cw-ease);filter:drop-shadow(0 3px 2px #08192c66)}.cw-entry-icon svg{width:34px;height:34px}.cw-entry-label{min-width:0;display:block}.cw-name{display:block;font-size:18px;font-weight:400;line-height:1.4;overflow-wrap:anywhere;text-shadow:0 2px 3px #07192b66}.cw-row-meta{display:block;font-size:11px;color:var(--cw-muted);margin-top:3px}.cw-row-date{display:none;font-size:11px;color:var(--cw-muted);margin-top:4px}.cw-target{display:block;font-size:11px;color:var(--cw-muted);overflow-wrap:anywhere;margin-top:4px}.cw-row.cw-selected .cw-entry{background:linear-gradient(90deg,#f4f9ff08,#f4f9ff04);transform:translateX(5px)}.cw-row.cw-selected .cw-entry-icon{transform:scale(1.22)}.cw-row.cw-selected .cw-name{color:#fff}.cw-row:hover .cw-entry{background:#eef7ff08}.cw-unavailable{color:var(--cw-muted)}.cw-notice{position:fixed;bottom:calc(var(--cw-footer-height,82px) + 8px);left:48px;right:24px;z-index:3;margin:0;background:var(--cw-bottom);border-radius:4px;font-size:12px;color:var(--cw-muted);padding:12px 24px;max-width:52ch}.cw-empty{padding:36px 28px;color:var(--cw-muted);font-size:15px}.cw-detail{min-width:0;align-self:center;padding:20px 0 28px;view-transition-name:cw-detail}.cw-detail-symbol{margin-bottom:28px;filter:drop-shadow(0 12px 12px #04152e44)}.cw-detail-symbol svg{width:110px;height:110px;stroke-width:.8;opacity:.9}.cw-detail h2{font-size:25px;font-weight:300;margin:0 0 7px;overflow-wrap:anywhere;line-height:1.3;letter-spacing:-.015em}.cw-detail>p{font-size:12px;color:var(--cw-muted);margin:0 0 25px}.cw-detail dl{margin:0;font-size:12px}.cw-detail dl>div{display:grid;grid-template-columns:70px minmax(0,1fr);gap:10px;margin-bottom:10px}.cw-detail dt{color:var(--cw-muted)}.cw-detail dd{margin:0;overflow-wrap:anywhere}.cw-open{display:inline-flex;margin-top:24px;min-height:44px;align-items:center;font-size:14px;border-bottom:1px solid #e8f1ff88;gap:12px}.cw-open:hover{border-bottom-color:#fff}.cw-open:after{content:"";display:block;width:7px;height:7px;border-top:1px solid currentColor;border-right:1px solid currentColor;transform:rotate(45deg)}
|
|
10
|
+
.cw-bottom{display:flex;align-items:center;justify-content:space-between;gap:24px;padding:22px 48px;position:fixed;bottom:0;left:0;right:0;background:linear-gradient(0deg,var(--cw-bottom),transparent);min-height:82px}.cw-credits{display:flex;align-items:center;gap:6px;margin:0;font-size:12px;font-weight:400;letter-spacing:normal;color:var(--cw-muted)}.cw-credits a{display:inline-flex;align-items:center;min-height:24px;padding-inline:2px;text-decoration:underline;text-underline-offset:4px;text-decoration-color:#edf4fc66}.cw-credits a:hover{text-decoration-color:currentColor}.cw-key-help{display:flex;gap:20px;flex-wrap:wrap;font-size:11px;color:var(--cw-muted)}kbd{font:inherit;color:#fff;margin-right:5px}.cw-appearance{display:flex;align-items:center;gap:16px;flex:none}.cw-appearance select{background:#0b193b70;border:1px solid #d7e9ff33;padding:7px 24px 7px 10px;border-radius:4px;max-width:116px;font-size:12px;min-height:36px}.cw-appearance button{display:flex;align-items:center;gap:8px;background:transparent;font-size:12px;min-height:40px;padding:6px 0}.cw-appearance button svg{width:16px;height:16px}.cw-controller{display:flex;align-items:center;gap:8px;font-size:11px;color:var(--cw-muted)}.cw-controller svg{width:22px;height:22px}.cw-noscript{padding:0 48px 24px;color:var(--cw-muted);font-size:13px}
|
|
11
|
+
body:not([data-cw-enhanced]) .cw-browser{padding-left:0}body:not([data-cw-enhanced]) .cw-stage{display:block;margin-top:20px}body:not([data-cw-enhanced]) .cw-list-scroll{max-height:none;min-height:0}body:not([data-cw-enhanced]) .cw-parent-placeholder{display:none}body:not([data-cw-enhanced]) .cw-bottom{display:none}
|
|
12
|
+
.cw-navigation-notice{position:fixed;z-index:5;left:48px;right:24px;bottom:calc(var(--cw-footer-height,82px) + 8px);background:var(--cw-bottom);color:var(--cw-text);padding:12px 16px;border-radius:4px;font-size:13px;display:flex;align-items:center;gap:16px;flex-wrap:wrap}.cw-navigation-notice[hidden]{display:none}.cw-navigation-notice button,.cw-navigation-notice a{background:none;min-height:44px;padding:6px 12px;border:1px solid var(--cw-muted);border-radius:4px}.cw-transition-layer *{animation:none!important;transition:none!important}.cw-transition-layer [data-cw-status]{display:none}
|
|
13
|
+
@view-transition{navigation:auto}::view-transition-old(root),::view-transition-new(root){animation:none}::view-transition-old(cw-background),::view-transition-new(cw-background){animation-duration:420ms}::view-transition-old(cw-browser),::view-transition-old(cw-detail){animation:cw-out 180ms ease-in both}::view-transition-new(cw-browser),::view-transition-new(cw-detail){animation:cw-in 420ms var(--cw-ease) both}::view-transition-old(cw-header),::view-transition-new(cw-header){animation-duration:240ms}@keyframes cw-out{to{opacity:0;transform:translateX(-22px);filter:blur(3px)}}@keyframes cw-in{from{opacity:0;transform:translateX(32px);filter:blur(5px)}}:root[data-cw-transitions=false]::view-transition-group(*){animation-duration:0s}:root[data-cw-transitions=false]::view-transition-old(*),:root[data-cw-transitions=false]::view-transition-new(*){animation:none}.cw-category-changing .cw-files{animation:cw-category-in 260ms var(--cw-ease)}@keyframes cw-category-in{from{opacity:.35;transform:translateX(12px)}}
|
|
14
|
+
@media(min-width:1500px){.cw-stage{margin-top:55px}.cw-categories{gap:48px}.cw-category{min-width:112px}.cw-list-scroll{max-height:calc(100svh - 405px)}}
|
|
15
|
+
@media(max-width:1000px){.cw-top{padding:24px 30px;gap:22px}.cw-stage{padding:0 36px;column-gap:35px}.cw-categories{padding-left:44px;gap:20px}.cw-browser{padding-left:44px}.cw-category{min-width:82px}.cw-list-head{flex-wrap:wrap;gap:8px}.cw-search{margin-left:52px;width:calc(100% - 52px)}.cw-list-scroll{max-height:calc(100svh - 390px)}.cw-bottom{padding:20px 30px}.cw-key-help{gap:12px}.cw-detail h2{font-size:21px}.cw-clock{font-size:12px}}
|
|
16
|
+
@media(max-width:680px){.cw-top{padding:22px 20px 12px;flex-wrap:wrap;gap:16px;min-height:104px}.cw-brand{font-size:18px}.cw-clock{order:1;font-size:11px}.cw-location{order:2;width:100%;font-size:12px;gap:8px}.cw-stage{padding:0 16px;margin:12px auto 100px;display:block}.cw-rail{margin:0 -8px 8px;padding:12px 8px 20px}.cw-categories{padding-left:0;gap:14px}.cw-browser{padding-left:0}.cw-category{min-width:76px;min-height:83px;padding:10px 2px;gap:10px}.cw-category svg{width:33px;height:33px}.cw-category span{font-size:12px}.cw-category small{right:5px}.cw-list-head{padding:0 12px;margin-bottom:8px}.cw-directory{gap:12px}.cw-directory h2{font-size:16px}.cw-search{margin-left:46px;width:calc(100% - 46px);min-height:44px}.cw-search input,.cw-search button{min-height:44px}.cw-list-scroll{max-height:none;min-height:150px;padding:8px 2px 18px}.cw-entry{gap:20px;padding:14px 12px;min-height:78px}.cw-entry-icon{width:36px;min-width:36px}.cw-entry-icon svg{width:29px;height:29px}.cw-name{font-size:17px}.cw-detail{display:none!important}.cw-row-date{display:block}.cw-bottom{padding:16px 20px;min-height:76px;gap:12px}.cw-key-help{display:none!important}.cw-appearance{width:100%;justify-content:space-between}.cw-appearance select,.cw-appearance button{min-height:44px}.cw-controller{position:absolute;bottom:calc(var(--cw-footer-height,76px) + 4px);right:20px;background:var(--cw-bottom);padding:6px 9px;border-radius:4px;max-width:calc(100% - 40px)}.cw-notice{left:20px;right:20px;bottom:calc(var(--cw-footer-height,82px) + 8px)}.cw-noscript{padding:0 24px 24px}}
|
|
17
|
+
@media(max-height:520px){.cw-stage{grid-template-columns:minmax(0,1fr)}.cw-detail{display:none!important}.cw-row-date{display:block}.cw-top{flex-wrap:nowrap}.cw-location{order:0;width:auto}.cw-clock{display:none!important}.cw-top{min-height:58px;padding-top:10px;padding-bottom:8px}.cw-stage{margin-top:0;margin-bottom:70px}.cw-rail{margin-bottom:0;padding-bottom:12px}.cw-category{min-height:68px;gap:4px;padding-top:4px}.cw-category svg{width:28px;height:28px}.cw-list-scroll{max-height:calc(100svh - 235px);min-height:80px}.cw-list-head{min-height:36px;margin-bottom:0}.cw-detail-symbol{margin-bottom:10px}.cw-detail-symbol svg{width:60px;height:60px}.cw-detail>p{margin-bottom:12px}.cw-bottom{min-height:60px;padding-block:8px}.cw-key-help{display:none!important}.cw-list-head{flex-wrap:nowrap}.cw-search{margin-left:0;width:170px}.cw-detail dl>div{margin-bottom:4px}}
|
|
18
|
+
@media(prefers-reduced-motion:reduce){*,*:before,*:after{scroll-behavior:auto!important;animation:none!important;transition:none!important}::view-transition-group(*),::view-transition-old(*),::view-transition-new(*){animation:none!important}.cw-row.cw-selected .cw-entry,.cw-category.cw-active,.cw-category:hover{transform:none}}
|
|
19
|
+
|
|
20
|
+
.cw-directory{flex-wrap:wrap;gap:.35rem}.cw-list-head h2{font-size:17px;font-weight:400;margin:0}.cw-list-head [data-cw-count]{font-size:12px;color:var(--cw-muted)}
|
|
21
|
+
.cw-motion{display:flex;align-items:center;background:transparent;border:1px solid #d7e9ff33;border-radius:4px;font-size:12px;min-height:44px;padding:6px 12px;white-space:nowrap}
|
|
22
|
+
.cw-appearance{min-width:0}.cw-appearance select{max-width:116px}
|
|
23
|
+
@media(max-width:680px){.cw-bottom{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:12px}.cw-appearance{width:auto;justify-content:flex-start;gap:12px}.cw-motion{max-width:140px;white-space:normal}.cw-list-head{align-items:start}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,52 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dirwell/theme-crosswave",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.0.1-alpha",
|
|
4
|
+
"description": "Vue-owned media navigation with VueUse gamepad support.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/vp-tw/dirwell.git",
|
|
9
|
+
"directory": "packages/theme-crosswave"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"README.md",
|
|
14
|
+
"LICENSE"
|
|
15
|
+
],
|
|
16
|
+
"type": "module",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/index.d.mts",
|
|
20
|
+
"import": "./dist/index.mjs"
|
|
21
|
+
},
|
|
22
|
+
"./source": {
|
|
23
|
+
"types": "./dist/source/component.d.mts",
|
|
24
|
+
"default": "./dist/source/Crosswave.vue"
|
|
25
|
+
},
|
|
26
|
+
"./model": {
|
|
27
|
+
"types": "./dist/model.d.mts",
|
|
28
|
+
"import": "./dist/model.mjs"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public",
|
|
33
|
+
"provenance": true,
|
|
34
|
+
"tag": "alpha"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@dirwell/core": "0.0.1-alpha",
|
|
38
|
+
"@vue/server-renderer": "3.5.43",
|
|
39
|
+
"@vueuse/core": "15.0.0",
|
|
40
|
+
"mime": "4.1.0",
|
|
41
|
+
"vue": "3.5.43"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@vue/compiler-sfc": "3.5.43"
|
|
45
|
+
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=22.12.0"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"build": "node ../../scripts/build-framework-theme.mjs theme-crosswave"
|
|
51
|
+
}
|
|
6
52
|
}
|