@quartz-community/bases-page 0.2.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/CHANGELOG.md +27 -0
- package/LICENSE +21 -0
- package/README.md +315 -0
- package/dist/BasesBody-B4CEJjEp.d.ts +6 -0
- package/dist/chunk-2AUMER56.js +44 -0
- package/dist/chunk-2AUMER56.js.map +1 -0
- package/dist/chunk-4HXXKSJ4.js +929 -0
- package/dist/chunk-4HXXKSJ4.js.map +1 -0
- package/dist/chunk-TDUJOYTU.js +42 -0
- package/dist/chunk-TDUJOYTU.js.map +1 -0
- package/dist/chunk-X2AZ5GOJ.js +1931 -0
- package/dist/chunk-X2AZ5GOJ.js.map +1 -0
- package/dist/compiler/index.d.ts +146 -0
- package/dist/compiler/index.js +7 -0
- package/dist/compiler/index.js.map +1 -0
- package/dist/components/index.d.ts +13 -0
- package/dist/components/index.js +9 -0
- package/dist/components/index.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +18703 -0
- package/dist/index.js.map +1 -0
- package/dist/registry.d.ts +48 -0
- package/dist/registry.js +7 -0
- package/dist/registry.js.map +1 -0
- package/dist/types.d.ts +181 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +143 -0
|
@@ -0,0 +1,929 @@
|
|
|
1
|
+
import { createRequire } from 'module';
|
|
2
|
+
import { viewRegistry, registerCustomViews } from './chunk-2AUMER56.js';
|
|
3
|
+
import { u, evaluate, evaluateFilter, resolvePropertyValue, S, transformLink, slugifyPath } from './chunk-X2AZ5GOJ.js';
|
|
4
|
+
|
|
5
|
+
createRequire(import.meta.url);
|
|
6
|
+
|
|
7
|
+
// src/components/ViewSelector.tsx
|
|
8
|
+
function ViewSelector({ views, activeIndex }) {
|
|
9
|
+
if (views.length <= 1) return null;
|
|
10
|
+
return /* @__PURE__ */ u("div", { class: "bases-view-tabs", role: "tablist", children: views.map((view, index) => /* @__PURE__ */ u(
|
|
11
|
+
"button",
|
|
12
|
+
{
|
|
13
|
+
type: "button",
|
|
14
|
+
class: index === activeIndex ? "is-active" : "",
|
|
15
|
+
"data-view-index": index,
|
|
16
|
+
children: view.name ?? view.type
|
|
17
|
+
}
|
|
18
|
+
)) });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// src/resolver.ts
|
|
22
|
+
function normalizeStringArray(values) {
|
|
23
|
+
if (!Array.isArray(values)) return [];
|
|
24
|
+
return values.filter((value) => typeof value === "string");
|
|
25
|
+
}
|
|
26
|
+
function getFilePath(fileData, slug) {
|
|
27
|
+
if (typeof fileData.relativePath === "string") return fileData.relativePath;
|
|
28
|
+
if (typeof fileData.filePath === "string") return fileData.filePath;
|
|
29
|
+
return slug ? `${slug}.md` : "";
|
|
30
|
+
}
|
|
31
|
+
function getFileName(path) {
|
|
32
|
+
const lastSlash = path.lastIndexOf("/");
|
|
33
|
+
return lastSlash >= 0 ? path.slice(lastSlash + 1) : path;
|
|
34
|
+
}
|
|
35
|
+
function getBaseName(path) {
|
|
36
|
+
const fileName = getFileName(path);
|
|
37
|
+
const dot = fileName.lastIndexOf(".");
|
|
38
|
+
return dot > 0 ? fileName.slice(0, dot) : fileName;
|
|
39
|
+
}
|
|
40
|
+
function toDate(value) {
|
|
41
|
+
if (value instanceof Date && !Number.isNaN(value.getTime())) return value;
|
|
42
|
+
if (typeof value === "string") {
|
|
43
|
+
const parsed = Date.parse(value);
|
|
44
|
+
if (!Number.isNaN(parsed)) return new Date(parsed);
|
|
45
|
+
}
|
|
46
|
+
return void 0;
|
|
47
|
+
}
|
|
48
|
+
function buildFileProperties(fileData, slug, frontmatter) {
|
|
49
|
+
const filePath = getFilePath(fileData, slug);
|
|
50
|
+
const baseName = filePath ? getBaseName(filePath) : getBaseName(slug);
|
|
51
|
+
const name = baseName || slug.split("/").pop() || "Untitled";
|
|
52
|
+
const basename = baseName || slug.split("/").pop() || "Untitled";
|
|
53
|
+
const lastSlash = filePath.lastIndexOf("/");
|
|
54
|
+
const folder = lastSlash >= 0 ? filePath.slice(0, lastSlash) : "";
|
|
55
|
+
const lastDot = filePath.lastIndexOf(".");
|
|
56
|
+
const ext = lastDot >= 0 ? filePath.slice(lastDot + 1) : "";
|
|
57
|
+
const tags = normalizeStringArray(frontmatter.tags);
|
|
58
|
+
const links = normalizeStringArray(fileData.links ?? fileData.outgoingLinks);
|
|
59
|
+
const embeds = normalizeStringArray(fileData.embeds);
|
|
60
|
+
const dates = fileData.dates;
|
|
61
|
+
const ctime = toDate(dates?.created);
|
|
62
|
+
const mtime = toDate(dates?.modified);
|
|
63
|
+
return {
|
|
64
|
+
name,
|
|
65
|
+
basename,
|
|
66
|
+
path: filePath,
|
|
67
|
+
folder,
|
|
68
|
+
ext,
|
|
69
|
+
tags,
|
|
70
|
+
links,
|
|
71
|
+
embeds,
|
|
72
|
+
created: ctime?.toISOString(),
|
|
73
|
+
modified: mtime?.toISOString(),
|
|
74
|
+
ctime,
|
|
75
|
+
mtime
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function compareSort(a, b) {
|
|
79
|
+
if (a === b) return 0;
|
|
80
|
+
if (a === void 0 || a === null) return 1;
|
|
81
|
+
if (b === void 0 || b === null) return -1;
|
|
82
|
+
if (typeof a === "number" && typeof b === "number") return a - b;
|
|
83
|
+
const dateA = typeof a === "string" ? Date.parse(a) : NaN;
|
|
84
|
+
const dateB = typeof b === "string" ? Date.parse(b) : NaN;
|
|
85
|
+
if (!Number.isNaN(dateA) && !Number.isNaN(dateB)) return dateA - dateB;
|
|
86
|
+
return String(a).localeCompare(String(b));
|
|
87
|
+
}
|
|
88
|
+
function buildSortKeys(view) {
|
|
89
|
+
if (view?.sort && view.sort.length > 0) return view.sort;
|
|
90
|
+
if (view?.groupBy?.property) {
|
|
91
|
+
return [{ property: view.groupBy.property, direction: view.groupBy.direction ?? "ASC" }];
|
|
92
|
+
}
|
|
93
|
+
if (view?.order && view.order.length > 0) {
|
|
94
|
+
return view.order.map((property) => ({ property, direction: "ASC" }));
|
|
95
|
+
}
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
function sortEntries(entries, view) {
|
|
99
|
+
const sortKeys = buildSortKeys(view);
|
|
100
|
+
if (sortKeys.length === 0) return entries;
|
|
101
|
+
return [...entries].sort((left, right) => {
|
|
102
|
+
for (const key of sortKeys) {
|
|
103
|
+
const sign = key.direction === "DESC" ? -1 : 1;
|
|
104
|
+
const leftValue = resolvePropertyValue(key.property, {
|
|
105
|
+
note: left.properties,
|
|
106
|
+
file: left.fileProperties,
|
|
107
|
+
formula: left.formulaValues
|
|
108
|
+
});
|
|
109
|
+
const rightValue = resolvePropertyValue(key.property, {
|
|
110
|
+
note: right.properties,
|
|
111
|
+
file: right.fileProperties,
|
|
112
|
+
formula: right.formulaValues
|
|
113
|
+
});
|
|
114
|
+
const cmp = compareSort(leftValue, rightValue);
|
|
115
|
+
if (cmp !== 0) return sign * cmp;
|
|
116
|
+
}
|
|
117
|
+
return 0;
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
function resolveBasesEntries(basesData, allFiles, view, selfContext) {
|
|
121
|
+
const entries = [];
|
|
122
|
+
const formulas = basesData.formulas ?? {};
|
|
123
|
+
const fileLookup = /* @__PURE__ */ new Map();
|
|
124
|
+
for (const fd of allFiles) {
|
|
125
|
+
if (fd.unlisted === true) continue;
|
|
126
|
+
const fdSlug = typeof fd.slug === "string" ? fd.slug : "";
|
|
127
|
+
if (!fdSlug) continue;
|
|
128
|
+
const fdPath = getFilePath(fd, fdSlug);
|
|
129
|
+
const fm = fd.frontmatter ?? {};
|
|
130
|
+
const fp = buildFileProperties(fd, fdSlug, fm);
|
|
131
|
+
const fileValue = { ...fp, properties: fm };
|
|
132
|
+
fileLookup.set(fdPath, fileValue);
|
|
133
|
+
const withoutExt = fdPath.replace(/\.md$/, "");
|
|
134
|
+
if (withoutExt !== fdPath) fileLookup.set(withoutExt, fileValue);
|
|
135
|
+
if (fdSlug && !fileLookup.has(fdSlug)) {
|
|
136
|
+
fileLookup.set(fdSlug, fileValue);
|
|
137
|
+
}
|
|
138
|
+
const base = getBaseName(fdPath);
|
|
139
|
+
if (base && !fileLookup.has(base)) {
|
|
140
|
+
fileLookup.set(base, fileValue);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
for (const fileData of allFiles) {
|
|
144
|
+
if (fileData.unlisted === true) continue;
|
|
145
|
+
const slug = typeof fileData.slug === "string" ? fileData.slug : "";
|
|
146
|
+
if (!slug) continue;
|
|
147
|
+
const filePath = typeof fileData.filePath === "string" ? fileData.filePath : "";
|
|
148
|
+
if (filePath.endsWith(".base") || slug.endsWith(".base")) continue;
|
|
149
|
+
const frontmatter = fileData.frontmatter ?? {};
|
|
150
|
+
const fileProperties = buildFileProperties(fileData, slug, frontmatter);
|
|
151
|
+
const context = {
|
|
152
|
+
note: frontmatter,
|
|
153
|
+
file: { ...fileProperties, properties: frontmatter },
|
|
154
|
+
formula: {},
|
|
155
|
+
self: selfContext,
|
|
156
|
+
_fileLookup: fileLookup
|
|
157
|
+
};
|
|
158
|
+
for (const [name, expr] of Object.entries(formulas)) {
|
|
159
|
+
context.formula[name] = evaluate(expr, context);
|
|
160
|
+
}
|
|
161
|
+
if (!evaluateFilter(basesData.filters, context)) continue;
|
|
162
|
+
if (view?.filters && !evaluateFilter(view.filters, context)) continue;
|
|
163
|
+
const title = typeof frontmatter.title === "string" ? frontmatter.title : fileProperties.basename || slug.split("/").pop() || "Untitled";
|
|
164
|
+
entries.push({
|
|
165
|
+
slug,
|
|
166
|
+
title,
|
|
167
|
+
properties: frontmatter,
|
|
168
|
+
fileProperties,
|
|
169
|
+
formulaValues: context.formula
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
const total = entries.length;
|
|
173
|
+
const sorted = sortEntries(entries, view);
|
|
174
|
+
const limited = view?.limit ? sorted.slice(0, view.limit) : sorted;
|
|
175
|
+
return { entries: limited, total };
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// src/i18n/locales/en-US.ts
|
|
179
|
+
var en_US_default = {
|
|
180
|
+
components: {
|
|
181
|
+
bases: {
|
|
182
|
+
title: "Base",
|
|
183
|
+
noData: "No data found.",
|
|
184
|
+
noViews: "No views defined.",
|
|
185
|
+
mapPlaceholder: "Map view is not available in static builds.",
|
|
186
|
+
allNotes: "All notes",
|
|
187
|
+
allEntries: "All entries",
|
|
188
|
+
galleryView: "Gallery",
|
|
189
|
+
boardView: "Board",
|
|
190
|
+
noImage: "No image available",
|
|
191
|
+
uncategorized: "Uncategorized",
|
|
192
|
+
showingCount: "Showing {count} of {total} entries"
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
// src/i18n/index.ts
|
|
198
|
+
var locales = {
|
|
199
|
+
"en-US": en_US_default
|
|
200
|
+
};
|
|
201
|
+
function i18n(locale) {
|
|
202
|
+
return locales[locale] || en_US_default;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// src/components/shared/links.tsx
|
|
206
|
+
var WIKILINK_RE = /\[\[([^\]|]+)(?:\|([^\]]+))?\]\]/g;
|
|
207
|
+
var MDLINK_RE = /\[([^\]]*)\]\(([^)]+)\)/g;
|
|
208
|
+
var URL_RE = /https?:\/\/[^\s<>]+/g;
|
|
209
|
+
function renderTextWithLinks(text, ctx) {
|
|
210
|
+
const segments = [];
|
|
211
|
+
const transformOpts = {
|
|
212
|
+
strategy: ctx.linkResolution,
|
|
213
|
+
allSlugs: ctx.allSlugs
|
|
214
|
+
};
|
|
215
|
+
for (const match of text.matchAll(WIKILINK_RE)) {
|
|
216
|
+
const target = match[1] ?? "";
|
|
217
|
+
const display = match[2] ?? target;
|
|
218
|
+
const href = transformLink(ctx.slug, target, transformOpts);
|
|
219
|
+
segments.push({
|
|
220
|
+
start: match.index ?? 0,
|
|
221
|
+
end: (match.index ?? 0) + match[0].length,
|
|
222
|
+
node: /* @__PURE__ */ u("a", { href, class: "internal internal-link", children: display })
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
for (const match of text.matchAll(MDLINK_RE)) {
|
|
226
|
+
const start = match.index ?? 0;
|
|
227
|
+
const end = start + match[0].length;
|
|
228
|
+
const overlaps = segments.some((segment) => start < segment.end && end > segment.start);
|
|
229
|
+
if (overlaps) continue;
|
|
230
|
+
const display = match[1] ?? "";
|
|
231
|
+
const href = match[2] ?? "";
|
|
232
|
+
const isExternal = href.startsWith("http://") || href.startsWith("https://");
|
|
233
|
+
const resolvedHref = isExternal ? href : String(transformLink(ctx.slug, href, transformOpts));
|
|
234
|
+
segments.push({
|
|
235
|
+
start,
|
|
236
|
+
end,
|
|
237
|
+
node: /* @__PURE__ */ u(
|
|
238
|
+
"a",
|
|
239
|
+
{
|
|
240
|
+
href: resolvedHref,
|
|
241
|
+
class: isExternal ? "external external-link" : "internal internal-link",
|
|
242
|
+
...isExternal ? { target: "_blank", rel: "noopener noreferrer" } : {},
|
|
243
|
+
children: display || href
|
|
244
|
+
}
|
|
245
|
+
)
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
for (const match of text.matchAll(URL_RE)) {
|
|
249
|
+
const start = match.index ?? 0;
|
|
250
|
+
const end = start + match[0].length;
|
|
251
|
+
const overlaps = segments.some((segment) => start < segment.end && end > segment.start);
|
|
252
|
+
if (overlaps) continue;
|
|
253
|
+
segments.push({
|
|
254
|
+
start,
|
|
255
|
+
end,
|
|
256
|
+
node: /* @__PURE__ */ u("a", { href: match[0], class: "external external-link", target: "_blank", rel: "noopener noreferrer", children: match[0] })
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
if (segments.length === 0) return [text];
|
|
260
|
+
segments.sort((a, b) => a.start - b.start);
|
|
261
|
+
const result = [];
|
|
262
|
+
let cursor = 0;
|
|
263
|
+
for (const segment of segments) {
|
|
264
|
+
if (segment.start > cursor) {
|
|
265
|
+
result.push(text.slice(cursor, segment.start));
|
|
266
|
+
}
|
|
267
|
+
result.push(segment.node);
|
|
268
|
+
cursor = segment.end;
|
|
269
|
+
}
|
|
270
|
+
if (cursor < text.length) {
|
|
271
|
+
result.push(text.slice(cursor));
|
|
272
|
+
}
|
|
273
|
+
return result;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// src/components/shared/cell.tsx
|
|
277
|
+
function isFileValue(value) {
|
|
278
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
279
|
+
const record = value;
|
|
280
|
+
return typeof record.name === "string" && typeof record.basename === "string" && typeof record.path === "string" && typeof record.folder === "string" && typeof record.ext === "string";
|
|
281
|
+
}
|
|
282
|
+
function formatValue(value) {
|
|
283
|
+
if (value === void 0 || value === null) return "";
|
|
284
|
+
if (Array.isArray(value)) return value.map((item) => String(item)).join(", ");
|
|
285
|
+
if (typeof value === "object") return JSON.stringify(value);
|
|
286
|
+
return String(value);
|
|
287
|
+
}
|
|
288
|
+
function renderCellValue(value, ctx) {
|
|
289
|
+
if (value === null || value === void 0) {
|
|
290
|
+
return /* @__PURE__ */ u("span", { class: "bases-empty", children: "\u2014" });
|
|
291
|
+
}
|
|
292
|
+
if (typeof value === "boolean") {
|
|
293
|
+
return /* @__PURE__ */ u("input", { type: "checkbox", checked: value, disabled: true });
|
|
294
|
+
}
|
|
295
|
+
if (typeof value === "number") {
|
|
296
|
+
return /* @__PURE__ */ u("span", { class: "bases-number", children: value });
|
|
297
|
+
}
|
|
298
|
+
if (typeof value === "string") {
|
|
299
|
+
const parts = renderTextWithLinks(value, ctx);
|
|
300
|
+
return /* @__PURE__ */ u("span", { class: "bases-text", children: parts });
|
|
301
|
+
}
|
|
302
|
+
if (Array.isArray(value)) {
|
|
303
|
+
const items = value.map((item, index) => /* @__PURE__ */ u(S, { children: [
|
|
304
|
+
index > 0 && /* @__PURE__ */ u("span", { class: "bases-separator", children: ", " }),
|
|
305
|
+
renderCellValue(item, ctx)
|
|
306
|
+
] }));
|
|
307
|
+
return /* @__PURE__ */ u("span", { class: "bases-list", children: items });
|
|
308
|
+
}
|
|
309
|
+
if (typeof value === "object") {
|
|
310
|
+
if (isFileValue(value)) {
|
|
311
|
+
const href = transformLink(
|
|
312
|
+
ctx.slug,
|
|
313
|
+
slugifyPath(value.path.replace(/\.md$/, "")),
|
|
314
|
+
{
|
|
315
|
+
strategy: ctx.linkResolution,
|
|
316
|
+
allSlugs: ctx.allSlugs
|
|
317
|
+
}
|
|
318
|
+
);
|
|
319
|
+
return /* @__PURE__ */ u("a", { href, class: "internal internal-link", children: value.basename });
|
|
320
|
+
}
|
|
321
|
+
return /* @__PURE__ */ u("code", { children: JSON.stringify(value) });
|
|
322
|
+
}
|
|
323
|
+
return String(value);
|
|
324
|
+
}
|
|
325
|
+
function isEmptyValue(value) {
|
|
326
|
+
if (value === void 0 || value === null || value === "") return true;
|
|
327
|
+
if (Array.isArray(value)) return value.length === 0;
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
function getColumnLabel(column, basesData) {
|
|
331
|
+
const config = basesData.properties?.[column];
|
|
332
|
+
if (config?.displayName) return config.displayName;
|
|
333
|
+
const segment = column.split(".").pop() ?? column;
|
|
334
|
+
return segment.split("_").map((part) => part ? part.charAt(0).toUpperCase() + part.slice(1) : part).join(" ");
|
|
335
|
+
}
|
|
336
|
+
function getColumns(view, basesData, entries) {
|
|
337
|
+
if (view.order && view.order.length > 0) return view.order;
|
|
338
|
+
const columns = /* @__PURE__ */ new Set();
|
|
339
|
+
columns.add("file.name");
|
|
340
|
+
const propertyKeys = basesData.properties ? Object.keys(basesData.properties) : [];
|
|
341
|
+
if (propertyKeys.length > 0) {
|
|
342
|
+
propertyKeys.forEach((key) => {
|
|
343
|
+
columns.add(key);
|
|
344
|
+
});
|
|
345
|
+
} else if (entries.length > 0) {
|
|
346
|
+
const firstEntry = entries[0];
|
|
347
|
+
if (firstEntry) {
|
|
348
|
+
Object.keys(firstEntry.properties).forEach((key) => {
|
|
349
|
+
columns.add(key);
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return Array.from(columns);
|
|
354
|
+
}
|
|
355
|
+
function getNestedValue(value, path) {
|
|
356
|
+
let current = value;
|
|
357
|
+
for (const segment of path) {
|
|
358
|
+
if (segment === "") continue;
|
|
359
|
+
if (Array.isArray(current)) {
|
|
360
|
+
const index = Number(segment);
|
|
361
|
+
if (Number.isNaN(index)) return void 0;
|
|
362
|
+
current = current[index];
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
365
|
+
if (current && typeof current === "object") {
|
|
366
|
+
const record = current;
|
|
367
|
+
current = record[segment];
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
370
|
+
return void 0;
|
|
371
|
+
}
|
|
372
|
+
return current;
|
|
373
|
+
}
|
|
374
|
+
function resolveEntryPropertyValue(column, entry) {
|
|
375
|
+
if (column.startsWith("note.")) {
|
|
376
|
+
return getNestedValue(entry.properties, column.slice(5).split("."));
|
|
377
|
+
}
|
|
378
|
+
if (column.startsWith("file.")) {
|
|
379
|
+
return getNestedValue(entry.fileProperties, column.slice(5).split("."));
|
|
380
|
+
}
|
|
381
|
+
if (column.startsWith("formula.")) {
|
|
382
|
+
return getNestedValue(entry.formulaValues, column.slice(8).split("."));
|
|
383
|
+
}
|
|
384
|
+
return getNestedValue(entry.properties, column.split("."));
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// src/components/views/board.tsx
|
|
388
|
+
function formatMessage(template, values) {
|
|
389
|
+
return Object.entries(values).reduce(
|
|
390
|
+
(text, [key, value]) => text.replace(`{${key}}`, String(value)),
|
|
391
|
+
template
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
var BoardView = ({
|
|
395
|
+
entries,
|
|
396
|
+
view,
|
|
397
|
+
basesData,
|
|
398
|
+
total,
|
|
399
|
+
locale,
|
|
400
|
+
slug,
|
|
401
|
+
allSlugs,
|
|
402
|
+
linkResolution
|
|
403
|
+
}) => {
|
|
404
|
+
const localeStrings = i18n(locale).components.bases;
|
|
405
|
+
const groupProperty = view.groupBy?.property ?? view.boardProperty;
|
|
406
|
+
const columns = getColumns(view, basesData, entries).filter((column) => column !== groupProperty);
|
|
407
|
+
const groups = /* @__PURE__ */ new Map();
|
|
408
|
+
const emptyLabel = groupProperty ? localeStrings.uncategorized : localeStrings.allEntries;
|
|
409
|
+
const transformOpts = { strategy: linkResolution, allSlugs };
|
|
410
|
+
for (const entry of entries) {
|
|
411
|
+
const rawValue = groupProperty ? resolveEntryPropertyValue(groupProperty, entry) : void 0;
|
|
412
|
+
const label = isEmptyValue(rawValue) ? emptyLabel : formatValue(rawValue);
|
|
413
|
+
const key = label || emptyLabel;
|
|
414
|
+
const existing = groups.get(key);
|
|
415
|
+
if (existing) {
|
|
416
|
+
existing.entries.push(entry);
|
|
417
|
+
} else {
|
|
418
|
+
groups.set(key, { label: key, entries: [entry] });
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
if (groups.size === 0) {
|
|
422
|
+
groups.set(localeStrings.allEntries, { label: localeStrings.allEntries, entries });
|
|
423
|
+
}
|
|
424
|
+
return /* @__PURE__ */ u("div", { class: "bases-board-wrapper", children: [
|
|
425
|
+
/* @__PURE__ */ u("div", { class: "bases-view-meta", children: formatMessage(localeStrings.showingCount, {
|
|
426
|
+
count: entries.length,
|
|
427
|
+
total
|
|
428
|
+
}) }),
|
|
429
|
+
/* @__PURE__ */ u("div", { class: "bases-board", children: Array.from(groups.values()).map((group) => /* @__PURE__ */ u("div", { class: "bases-board-column", children: [
|
|
430
|
+
/* @__PURE__ */ u("div", { class: "bases-board-column-header", children: [
|
|
431
|
+
/* @__PURE__ */ u("span", { children: group.label }),
|
|
432
|
+
/* @__PURE__ */ u("span", { class: "bases-board-count", children: group.entries.length })
|
|
433
|
+
] }),
|
|
434
|
+
/* @__PURE__ */ u("div", { class: "bases-board-column-body", children: group.entries.map((entry) => {
|
|
435
|
+
const ctx = { slug, allSlugs, linkResolution };
|
|
436
|
+
return /* @__PURE__ */ u("div", { class: "bases-board-card", children: [
|
|
437
|
+
/* @__PURE__ */ u(
|
|
438
|
+
"a",
|
|
439
|
+
{
|
|
440
|
+
href: transformLink(slug, entry.slug, transformOpts),
|
|
441
|
+
class: "internal internal-link",
|
|
442
|
+
"data-slug": entry.slug,
|
|
443
|
+
children: entry.title
|
|
444
|
+
}
|
|
445
|
+
),
|
|
446
|
+
columns.length > 0 && /* @__PURE__ */ u("div", { class: "bases-board-card-meta", children: columns.map((column) => {
|
|
447
|
+
const value = resolveEntryPropertyValue(column, entry);
|
|
448
|
+
if (isEmptyValue(value)) return null;
|
|
449
|
+
return /* @__PURE__ */ u("div", { class: "bases-board-card-row", children: [
|
|
450
|
+
/* @__PURE__ */ u("span", { class: "bases-board-card-label", children: getColumnLabel(column, basesData) }),
|
|
451
|
+
/* @__PURE__ */ u("span", { class: "bases-board-card-value", children: renderCellValue(value, ctx) })
|
|
452
|
+
] });
|
|
453
|
+
}) })
|
|
454
|
+
] });
|
|
455
|
+
}) })
|
|
456
|
+
] })) })
|
|
457
|
+
] });
|
|
458
|
+
};
|
|
459
|
+
var boardViewRegistration = {
|
|
460
|
+
id: "board",
|
|
461
|
+
name: "Board",
|
|
462
|
+
icon: "columns",
|
|
463
|
+
render: BoardView
|
|
464
|
+
};
|
|
465
|
+
|
|
466
|
+
// src/components/views/cards.tsx
|
|
467
|
+
function formatMessage2(template, values) {
|
|
468
|
+
return Object.entries(values).reduce(
|
|
469
|
+
(text, [key, value]) => text.replace(`{${key}}`, String(value)),
|
|
470
|
+
template
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
var HEX_COLOR_RE = /^#(?:[0-9a-f]{3}){1,2}$/i;
|
|
474
|
+
var WIKILINK_RE2 = /^\[\[(.+?)(?:\|.*)?\]\]$/;
|
|
475
|
+
function resolveImageSrc(raw, opts) {
|
|
476
|
+
if (!raw) return { src: "", isColor: false };
|
|
477
|
+
if (HEX_COLOR_RE.test(raw)) {
|
|
478
|
+
return { src: raw, isColor: true };
|
|
479
|
+
}
|
|
480
|
+
const wikiMatch = WIKILINK_RE2.exec(raw);
|
|
481
|
+
if (wikiMatch?.[1]) {
|
|
482
|
+
const target = wikiMatch[1].trim();
|
|
483
|
+
const resolved = transformLink(opts.slug, target, {
|
|
484
|
+
strategy: opts.linkResolution,
|
|
485
|
+
allSlugs: opts.allSlugs
|
|
486
|
+
});
|
|
487
|
+
return { src: String(resolved), isColor: false };
|
|
488
|
+
}
|
|
489
|
+
return { src: raw, isColor: false };
|
|
490
|
+
}
|
|
491
|
+
var CardsView = ({
|
|
492
|
+
entries,
|
|
493
|
+
view,
|
|
494
|
+
basesData,
|
|
495
|
+
total,
|
|
496
|
+
locale,
|
|
497
|
+
slug,
|
|
498
|
+
allSlugs,
|
|
499
|
+
linkResolution
|
|
500
|
+
}) => {
|
|
501
|
+
const imageProperty = typeof view.image === "string" ? view.image : void 0;
|
|
502
|
+
const cardMetaColumns = view.order && view.order.length > 0 ? view.order.filter((column) => column !== imageProperty && column !== "file.name") : [];
|
|
503
|
+
const localeStrings = i18n(locale).components.bases;
|
|
504
|
+
const cardSize = view.cardSize;
|
|
505
|
+
const aspectRatio = view.imageAspectRatio ?? view.cardAspect;
|
|
506
|
+
const imageFit = view.imageFit === "contain" ? "contain" : "cover";
|
|
507
|
+
const gridStyle = typeof cardSize === "number" && cardSize > 0 ? { gridTemplateColumns: `repeat(auto-fit, minmax(${cardSize}px, 1fr))` } : void 0;
|
|
508
|
+
const imageOpts = { slug, allSlugs, linkResolution };
|
|
509
|
+
const transformOpts = { strategy: linkResolution, allSlugs };
|
|
510
|
+
return /* @__PURE__ */ u("div", { class: "bases-cards-wrapper", children: [
|
|
511
|
+
/* @__PURE__ */ u("div", { class: "bases-view-meta", children: formatMessage2(localeStrings.showingCount, {
|
|
512
|
+
count: entries.length,
|
|
513
|
+
total
|
|
514
|
+
}) }),
|
|
515
|
+
/* @__PURE__ */ u("div", { class: "bases-cards", style: gridStyle, children: entries.map((entry) => {
|
|
516
|
+
const ctx = { slug, allSlugs, linkResolution };
|
|
517
|
+
const imageValue = imageProperty ? resolveEntryPropertyValue(imageProperty, entry) : void 0;
|
|
518
|
+
const rawImage = imageValue ? String(imageValue) : "";
|
|
519
|
+
const { src: imageSrc, isColor } = resolveImageSrc(rawImage, imageOpts);
|
|
520
|
+
const imageAspect = typeof aspectRatio === "number" && aspectRatio > 0 ? { aspectRatio: String(aspectRatio) } : void 0;
|
|
521
|
+
const href = transformLink(slug, entry.slug, transformOpts);
|
|
522
|
+
return /* @__PURE__ */ u("a", { href, class: "internal internal-link bases-card", "data-slug": entry.slug, children: [
|
|
523
|
+
imageSrc && !isColor && /* @__PURE__ */ u("div", { class: "bases-card-image", style: imageAspect, children: /* @__PURE__ */ u(
|
|
524
|
+
"img",
|
|
525
|
+
{
|
|
526
|
+
src: imageSrc,
|
|
527
|
+
alt: entry.title,
|
|
528
|
+
loading: "lazy",
|
|
529
|
+
style: { objectFit: imageFit }
|
|
530
|
+
}
|
|
531
|
+
) }),
|
|
532
|
+
imageSrc && isColor && /* @__PURE__ */ u(
|
|
533
|
+
"div",
|
|
534
|
+
{
|
|
535
|
+
class: "bases-card-image bases-card-color",
|
|
536
|
+
style: { ...imageAspect, backgroundColor: imageSrc }
|
|
537
|
+
}
|
|
538
|
+
),
|
|
539
|
+
/* @__PURE__ */ u("div", { class: "bases-card-body", children: [
|
|
540
|
+
/* @__PURE__ */ u("span", { class: "bases-card-title", children: entry.title }),
|
|
541
|
+
/* @__PURE__ */ u("div", { class: "bases-card-meta", children: cardMetaColumns.map((column) => {
|
|
542
|
+
const value = resolveEntryPropertyValue(column, entry);
|
|
543
|
+
if (isEmptyValue(value)) return null;
|
|
544
|
+
return /* @__PURE__ */ u("div", { class: "bases-card-row", children: [
|
|
545
|
+
/* @__PURE__ */ u("span", { class: "bases-card-label", children: getColumnLabel(column, basesData) }),
|
|
546
|
+
/* @__PURE__ */ u("span", { class: "bases-card-value", children: renderCellValue(value, ctx) })
|
|
547
|
+
] });
|
|
548
|
+
}) })
|
|
549
|
+
] })
|
|
550
|
+
] });
|
|
551
|
+
}) })
|
|
552
|
+
] });
|
|
553
|
+
};
|
|
554
|
+
var cardsViewRegistration = {
|
|
555
|
+
id: "cards",
|
|
556
|
+
name: "Cards",
|
|
557
|
+
icon: "layout-grid",
|
|
558
|
+
render: CardsView
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
// src/components/views/gallery.tsx
|
|
562
|
+
function formatMessage3(template, values) {
|
|
563
|
+
return Object.entries(values).reduce(
|
|
564
|
+
(text, [key, value]) => text.replace(`{${key}}`, String(value)),
|
|
565
|
+
template
|
|
566
|
+
);
|
|
567
|
+
}
|
|
568
|
+
var GalleryView = ({
|
|
569
|
+
entries,
|
|
570
|
+
view,
|
|
571
|
+
total,
|
|
572
|
+
locale,
|
|
573
|
+
slug,
|
|
574
|
+
allSlugs,
|
|
575
|
+
linkResolution
|
|
576
|
+
}) => {
|
|
577
|
+
const imageProperty = typeof view.image === "string" ? view.image : void 0;
|
|
578
|
+
const localeStrings = i18n(locale).components.bases;
|
|
579
|
+
const columns = typeof view.cardSize === "number" && view.cardSize > 0 ? Math.round(view.cardSize) : 3;
|
|
580
|
+
const gridStyle = { gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))` };
|
|
581
|
+
const imageOpts = { slug, allSlugs, linkResolution };
|
|
582
|
+
const transformOpts = { strategy: linkResolution, allSlugs };
|
|
583
|
+
return /* @__PURE__ */ u("div", { class: "bases-gallery-wrapper", children: [
|
|
584
|
+
/* @__PURE__ */ u("div", { class: "bases-view-meta", children: formatMessage3(localeStrings.showingCount, {
|
|
585
|
+
count: entries.length,
|
|
586
|
+
total
|
|
587
|
+
}) }),
|
|
588
|
+
/* @__PURE__ */ u("div", { class: "bases-gallery", style: gridStyle, children: entries.map((entry) => {
|
|
589
|
+
const imageValue = imageProperty ? resolveEntryPropertyValue(imageProperty, entry) : void 0;
|
|
590
|
+
const rawImage = imageValue ? String(imageValue) : "";
|
|
591
|
+
const { src: imageSrc, isColor } = resolveImageSrc(rawImage, imageOpts);
|
|
592
|
+
return /* @__PURE__ */ u("div", { class: "bases-gallery-item", children: [
|
|
593
|
+
/* @__PURE__ */ u("div", { class: "bases-gallery-image", children: imageSrc && !isColor ? /* @__PURE__ */ u("img", { src: imageSrc, alt: entry.title, loading: "lazy" }) : imageSrc && isColor ? /* @__PURE__ */ u("span", { class: "bases-gallery-placeholder", style: { background: imageSrc } }) : /* @__PURE__ */ u(
|
|
594
|
+
"span",
|
|
595
|
+
{
|
|
596
|
+
class: "bases-gallery-placeholder",
|
|
597
|
+
role: "img",
|
|
598
|
+
"aria-label": localeStrings.noImage
|
|
599
|
+
}
|
|
600
|
+
) }),
|
|
601
|
+
/* @__PURE__ */ u("div", { class: "bases-gallery-title", children: /* @__PURE__ */ u(
|
|
602
|
+
"a",
|
|
603
|
+
{
|
|
604
|
+
href: transformLink(slug, entry.slug, transformOpts),
|
|
605
|
+
class: "internal internal-link",
|
|
606
|
+
"data-slug": entry.slug,
|
|
607
|
+
children: entry.title
|
|
608
|
+
}
|
|
609
|
+
) })
|
|
610
|
+
] });
|
|
611
|
+
}) })
|
|
612
|
+
] });
|
|
613
|
+
};
|
|
614
|
+
var galleryViewRegistration = {
|
|
615
|
+
id: "gallery",
|
|
616
|
+
name: "Gallery",
|
|
617
|
+
icon: "image",
|
|
618
|
+
render: GalleryView
|
|
619
|
+
};
|
|
620
|
+
|
|
621
|
+
// src/components/views/list.tsx
|
|
622
|
+
function formatMessage4(template, values) {
|
|
623
|
+
return Object.entries(values).reduce(
|
|
624
|
+
(text, [key, value]) => text.replace(`{${key}}`, String(value)),
|
|
625
|
+
template
|
|
626
|
+
);
|
|
627
|
+
}
|
|
628
|
+
var ListView = ({
|
|
629
|
+
entries,
|
|
630
|
+
view,
|
|
631
|
+
basesData,
|
|
632
|
+
total,
|
|
633
|
+
locale,
|
|
634
|
+
slug,
|
|
635
|
+
allSlugs,
|
|
636
|
+
linkResolution
|
|
637
|
+
}) => {
|
|
638
|
+
const columns = getColumns(view, basesData, entries);
|
|
639
|
+
const localeStrings = i18n(locale).components.bases;
|
|
640
|
+
const transformOpts = { strategy: linkResolution, allSlugs };
|
|
641
|
+
return /* @__PURE__ */ u("div", { class: "bases-list-wrapper", children: [
|
|
642
|
+
/* @__PURE__ */ u("div", { class: "bases-view-meta", children: formatMessage4(localeStrings.showingCount, {
|
|
643
|
+
count: entries.length,
|
|
644
|
+
total
|
|
645
|
+
}) }),
|
|
646
|
+
/* @__PURE__ */ u("div", { class: "bases-list-group", children: /* @__PURE__ */ u("div", { class: "bases-list-group-list", children: entries.map((entry) => {
|
|
647
|
+
const ctx = { slug, allSlugs, linkResolution };
|
|
648
|
+
const primaryColumn = columns[0] ?? "file.name";
|
|
649
|
+
const secondaryColumns = columns.slice(1);
|
|
650
|
+
const primaryValue = primaryColumn === "file.name" ? /* @__PURE__ */ u(
|
|
651
|
+
"a",
|
|
652
|
+
{
|
|
653
|
+
href: transformLink(slug, entry.slug, transformOpts),
|
|
654
|
+
class: "internal internal-link",
|
|
655
|
+
"data-slug": entry.slug,
|
|
656
|
+
children: entry.title
|
|
657
|
+
}
|
|
658
|
+
) : renderCellValue(resolveEntryPropertyValue(primaryColumn, entry), ctx);
|
|
659
|
+
const secondaryItems = [];
|
|
660
|
+
for (const column of secondaryColumns) {
|
|
661
|
+
const value = resolveEntryPropertyValue(column, entry);
|
|
662
|
+
if (isEmptyValue(value)) continue;
|
|
663
|
+
secondaryItems.push(
|
|
664
|
+
/* @__PURE__ */ u("span", { class: "bases-list-property", children: /* @__PURE__ */ u("span", { class: "bases-rendered-value", children: renderCellValue(value, ctx) }) })
|
|
665
|
+
);
|
|
666
|
+
}
|
|
667
|
+
return /* @__PURE__ */ u("div", { class: "bases-list-item", children: /* @__PURE__ */ u("div", { class: "bases-list-item-properties", children: [
|
|
668
|
+
/* @__PURE__ */ u("span", { class: "bases-list-property", children: [
|
|
669
|
+
/* @__PURE__ */ u("span", { class: "list-bullet", children: "-" }),
|
|
670
|
+
/* @__PURE__ */ u("span", { class: "bases-rendered-value", children: primaryValue })
|
|
671
|
+
] }),
|
|
672
|
+
secondaryItems.map((item) => /* @__PURE__ */ u(S, { children: [
|
|
673
|
+
/* @__PURE__ */ u("span", { class: "bases-list-separator", children: ", " }),
|
|
674
|
+
item
|
|
675
|
+
] }))
|
|
676
|
+
] }) });
|
|
677
|
+
}) }) })
|
|
678
|
+
] });
|
|
679
|
+
};
|
|
680
|
+
var listViewRegistration = {
|
|
681
|
+
id: "list",
|
|
682
|
+
name: "List",
|
|
683
|
+
icon: "list",
|
|
684
|
+
render: ListView
|
|
685
|
+
};
|
|
686
|
+
|
|
687
|
+
// src/components/shared/summary.tsx
|
|
688
|
+
function computeSummary(values, summary) {
|
|
689
|
+
const nonEmpty = values.filter((value) => value !== void 0 && value !== null && value !== "");
|
|
690
|
+
if (summary === "Empty") return String(values.length - nonEmpty.length);
|
|
691
|
+
if (summary === "Filled") return String(nonEmpty.length);
|
|
692
|
+
if (summary === "Checked") return String(values.filter((value) => value === true).length);
|
|
693
|
+
if (summary === "Unchecked") return String(values.filter((value) => value === false).length);
|
|
694
|
+
if (summary === "Unique") return String(new Set(values.map((value) => String(value))).size);
|
|
695
|
+
const numeric = nonEmpty.map((value) => typeof value === "number" ? value : Number(value)).filter((value) => !Number.isNaN(value));
|
|
696
|
+
if (numeric.length === 0) return summary;
|
|
697
|
+
if (summary === "Sum") return String(numeric.reduce((acc, value) => acc + value, 0));
|
|
698
|
+
if (summary === "Average")
|
|
699
|
+
return String(numeric.reduce((acc, value) => acc + value, 0) / numeric.length);
|
|
700
|
+
if (summary === "Min") return String(Math.min(...numeric));
|
|
701
|
+
if (summary === "Max") return String(Math.max(...numeric));
|
|
702
|
+
if (summary === "Range") return String(Math.max(...numeric) - Math.min(...numeric));
|
|
703
|
+
if (summary === "Median") {
|
|
704
|
+
const sorted = [...numeric].sort((a, b) => a - b);
|
|
705
|
+
const mid = Math.floor(sorted.length / 2);
|
|
706
|
+
const upper = sorted[mid] ?? 0;
|
|
707
|
+
const lower = sorted[mid - 1] ?? upper;
|
|
708
|
+
const median = sorted.length % 2 === 0 ? (lower + upper) / 2 : upper;
|
|
709
|
+
return String(median);
|
|
710
|
+
}
|
|
711
|
+
if (summary === "Stddev") {
|
|
712
|
+
const mean = numeric.reduce((acc, value) => acc + value, 0) / numeric.length;
|
|
713
|
+
const variance = numeric.reduce((acc, value) => acc + Math.pow(value - mean, 2), 0) / numeric.length;
|
|
714
|
+
return String(Math.sqrt(variance));
|
|
715
|
+
}
|
|
716
|
+
return summary;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// src/components/views/table.tsx
|
|
720
|
+
function formatMessage5(template, values) {
|
|
721
|
+
return Object.entries(values).reduce(
|
|
722
|
+
(text, [key, value]) => text.replace(`{${key}}`, String(value)),
|
|
723
|
+
template
|
|
724
|
+
);
|
|
725
|
+
}
|
|
726
|
+
function groupEntries(entries, groupProperty, emptyLabel) {
|
|
727
|
+
if (!groupProperty) return null;
|
|
728
|
+
const groups = /* @__PURE__ */ new Map();
|
|
729
|
+
for (const entry of entries) {
|
|
730
|
+
const rawValue = resolveEntryPropertyValue(groupProperty, entry);
|
|
731
|
+
const label = isEmptyValue(rawValue) ? emptyLabel : formatValue(rawValue);
|
|
732
|
+
const key = label || emptyLabel;
|
|
733
|
+
const existing = groups.get(key);
|
|
734
|
+
if (existing) {
|
|
735
|
+
existing.push(entry);
|
|
736
|
+
} else {
|
|
737
|
+
groups.set(key, [entry]);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
return groups.size > 0 ? groups : null;
|
|
741
|
+
}
|
|
742
|
+
function renderRow(entry, columns, view, slug, allSlugs, linkResolution) {
|
|
743
|
+
const transformOpts = { strategy: linkResolution, allSlugs };
|
|
744
|
+
const ctx = { slug, allSlugs, linkResolution };
|
|
745
|
+
return /* @__PURE__ */ u("tr", { children: columns.map((column) => {
|
|
746
|
+
const value = resolveEntryPropertyValue(column, entry);
|
|
747
|
+
const display = formatValue(value);
|
|
748
|
+
const isPrimary = column === "file.name" || column === "title";
|
|
749
|
+
const columnWidth = view.columnSize?.[column];
|
|
750
|
+
const style = columnWidth ? { width: `${columnWidth}px`, minWidth: `${columnWidth}px` } : void 0;
|
|
751
|
+
return /* @__PURE__ */ u("td", { "data-value": display, style, children: isPrimary ? /* @__PURE__ */ u(
|
|
752
|
+
"a",
|
|
753
|
+
{
|
|
754
|
+
href: transformLink(slug, entry.slug, transformOpts),
|
|
755
|
+
class: "internal internal-link",
|
|
756
|
+
"data-slug": entry.slug,
|
|
757
|
+
children: display || entry.title
|
|
758
|
+
}
|
|
759
|
+
) : renderCellValue(value, ctx) });
|
|
760
|
+
}) });
|
|
761
|
+
}
|
|
762
|
+
var TableView = ({
|
|
763
|
+
entries,
|
|
764
|
+
view,
|
|
765
|
+
basesData,
|
|
766
|
+
total,
|
|
767
|
+
locale,
|
|
768
|
+
slug,
|
|
769
|
+
allSlugs,
|
|
770
|
+
linkResolution
|
|
771
|
+
}) => {
|
|
772
|
+
const columns = getColumns(view, basesData, entries);
|
|
773
|
+
const summaries = view.summaries ?? {};
|
|
774
|
+
const hasSummary = Object.keys(summaries).length > 0;
|
|
775
|
+
const localeStrings = i18n(locale).components.bases;
|
|
776
|
+
const groupProperty = view.groupBy?.property;
|
|
777
|
+
const groupPropertyLabel = groupProperty ? getColumnLabel(groupProperty, basesData) : "";
|
|
778
|
+
const groups = groupEntries(entries, groupProperty, localeStrings.uncategorized);
|
|
779
|
+
return /* @__PURE__ */ u("div", { class: "bases-table-wrapper", children: [
|
|
780
|
+
/* @__PURE__ */ u("div", { class: "bases-view-meta", children: formatMessage5(localeStrings.showingCount, {
|
|
781
|
+
count: entries.length,
|
|
782
|
+
total
|
|
783
|
+
}) }),
|
|
784
|
+
/* @__PURE__ */ u("table", { class: "bases-table", "data-view-type": "table", children: [
|
|
785
|
+
/* @__PURE__ */ u("thead", { children: /* @__PURE__ */ u("tr", { children: columns.map((column) => {
|
|
786
|
+
const columnWidth = view.columnSize?.[column];
|
|
787
|
+
const style = columnWidth ? { width: `${columnWidth}px`, minWidth: `${columnWidth}px` } : void 0;
|
|
788
|
+
return /* @__PURE__ */ u("th", { "data-column": column, "data-sortable": "true", style, children: [
|
|
789
|
+
/* @__PURE__ */ u("span", { class: "bases-table-header", children: getColumnLabel(column, basesData) }),
|
|
790
|
+
/* @__PURE__ */ u("span", { class: "bases-table-header-sort", "aria-hidden": "true" })
|
|
791
|
+
] });
|
|
792
|
+
}) }) }),
|
|
793
|
+
/* @__PURE__ */ u("tbody", { children: groups ? Array.from(groups.entries()).map(([label, groupEntries2]) => /* @__PURE__ */ u(S, { children: [
|
|
794
|
+
/* @__PURE__ */ u("tr", { class: "bases-table-group-header", children: /* @__PURE__ */ u("td", { colSpan: columns.length, children: [
|
|
795
|
+
groupPropertyLabel && /* @__PURE__ */ u("span", { class: "bases-table-group-property", children: [
|
|
796
|
+
groupPropertyLabel,
|
|
797
|
+
" "
|
|
798
|
+
] }),
|
|
799
|
+
/* @__PURE__ */ u("span", { class: "bases-table-group-label", children: label }),
|
|
800
|
+
/* @__PURE__ */ u("span", { class: "bases-table-group-count", children: groupEntries2.length })
|
|
801
|
+
] }) }),
|
|
802
|
+
groupEntries2.map(
|
|
803
|
+
(entry) => renderRow(entry, columns, view, slug, allSlugs, linkResolution)
|
|
804
|
+
)
|
|
805
|
+
] })) : entries.map(
|
|
806
|
+
(entry) => renderRow(entry, columns, view, slug, allSlugs, linkResolution)
|
|
807
|
+
) }),
|
|
808
|
+
hasSummary && /* @__PURE__ */ u("tfoot", { children: /* @__PURE__ */ u("tr", { class: "bases-summary-row", children: columns.map((column) => {
|
|
809
|
+
const summary = summaries[column];
|
|
810
|
+
if (!summary) return /* @__PURE__ */ u("td", {});
|
|
811
|
+
const values = entries.map((entry) => resolveEntryPropertyValue(column, entry));
|
|
812
|
+
return /* @__PURE__ */ u("td", { children: computeSummary(values, summary) });
|
|
813
|
+
}) }) })
|
|
814
|
+
] })
|
|
815
|
+
] });
|
|
816
|
+
};
|
|
817
|
+
var tableViewRegistration = {
|
|
818
|
+
id: "table",
|
|
819
|
+
name: "Table",
|
|
820
|
+
icon: "table",
|
|
821
|
+
render: TableView
|
|
822
|
+
};
|
|
823
|
+
|
|
824
|
+
// src/components/views/index.ts
|
|
825
|
+
function registerBuiltinViews() {
|
|
826
|
+
viewRegistry.register(tableViewRegistration);
|
|
827
|
+
viewRegistry.register(listViewRegistration);
|
|
828
|
+
viewRegistry.register(cardsViewRegistration);
|
|
829
|
+
viewRegistry.register(galleryViewRegistration);
|
|
830
|
+
viewRegistry.register(boardViewRegistration);
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
// src/components/styles/bases.scss
|
|
834
|
+
var bases_default = ".bases-page {\n width: 100%;\n max-width: 100%;\n display: flex;\n flex-direction: column;\n gap: 16px;\n overflow: hidden;\n}\n\n.bases-view-tabs {\n display: flex;\n gap: 8px;\n flex-wrap: wrap;\n}\n.bases-view-tabs button {\n border: 1px solid var(--lightgray);\n background: var(--light);\n color: var(--darkgray);\n padding: 6px 12px;\n border-radius: 999px;\n cursor: pointer;\n font-size: 0.9rem;\n}\n.bases-view-tabs button.is-active {\n background: var(--secondary);\n color: var(--light);\n border-color: var(--secondary);\n}\n\n.bases-view-container {\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.bases-view {\n display: none;\n}\n.bases-view.is-active {\n display: block;\n}\n\n.bases-view-meta {\n font-size: 0.85rem;\n color: var(--gray);\n margin-bottom: 8px;\n}\n\n.bases-table-wrapper {\n width: 100%;\n overflow-x: auto;\n}\n\n.bases-table {\n width: 100%;\n border-collapse: collapse;\n border: 1px solid var(--lightgray);\n border-radius: 8px;\n overflow: hidden;\n}\n.bases-table th,\n.bases-table td {\n padding: 10px 12px;\n text-align: left;\n border-bottom: 1px solid var(--lightgray);\n font-size: 0.9rem;\n}\n.bases-table thead th {\n position: sticky;\n top: 0;\n background: var(--light);\n color: var(--dark);\n font-weight: 600;\n cursor: pointer;\n}\n.bases-table td .bases-empty {\n padding: 0;\n border: 0;\n background: none;\n color: var(--gray);\n display: inline;\n}\n.bases-table td code {\n font-size: 0.85em;\n padding: 0.1rem 0.3rem;\n border-radius: 3px;\n background: var(--highlight);\n word-break: break-all;\n}\n.bases-table td .bases-list {\n flex-direction: row;\n flex-wrap: wrap;\n gap: 4px;\n}\n.bases-table td input[type=checkbox] {\n margin-inline: 0;\n}\n\n.bases-table-header-sort {\n position: absolute;\n right: 8px;\n top: calc(50% - 4px);\n display: inline-block;\n width: 8px;\n height: 8px;\n margin-left: 6px;\n border-right: 2px solid transparent;\n border-bottom: 2px solid transparent;\n}\n\nth.is-sorted-asc .bases-table-header-sort {\n border-right-color: var(--darkgray);\n border-bottom-color: var(--darkgray);\n transform: rotate(-45deg);\n}\n\nth.is-sorted-desc .bases-table-header-sort {\n border-right-color: var(--darkgray);\n border-bottom-color: var(--darkgray);\n transform: rotate(135deg);\n}\n\n.bases-summary-row td {\n background: var(--light);\n font-weight: 600;\n color: var(--darkgray);\n}\n\n.bases-table-group-header td {\n background: var(--lightgray);\n font-weight: 600;\n padding: 8px 12px;\n border-bottom: 2px solid var(--gray);\n}\n\n.bases-table-group-property {\n color: var(--gray);\n font-weight: 400;\n}\n\n.bases-table-group-label {\n margin-right: 8px;\n}\n\n.bases-table-group-count {\n background: var(--light);\n color: var(--darkgray);\n border-radius: 999px;\n padding: 2px 8px;\n font-size: 0.75rem;\n font-weight: 400;\n}\n\n.bases-separator {\n color: var(--gray);\n}\n\n.bases-number {\n font-variant-numeric: tabular-nums;\n}\n\n.bases-list {\n display: inline-flex;\n flex-wrap: wrap;\n gap: 4px;\n}\n\n.bases-list-group {\n width: 100%;\n}\n\n.bases-list-group-list {\n display: flex;\n flex-direction: column;\n}\n\n.bases-list-item {\n padding: 2px 0;\n}\n\n.bases-list-item-properties {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: 0;\n}\n\n.bases-list-property {\n display: inline-flex;\n align-items: baseline;\n gap: 4px;\n}\n\n.list-bullet {\n color: var(--darkgray);\n user-select: none;\n}\n\n.bases-list-separator {\n color: var(--gray);\n margin-right: 4px;\n}\n\n.bases-rendered-value {\n display: inline;\n}\n\n.bases-cards {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));\n gap: 16px;\n}\n\n.bases-card {\n border: 1px solid var(--lightgray);\n border-radius: 12px;\n overflow: hidden;\n background: var(--light);\n display: flex;\n flex-direction: column;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n color: inherit;\n text-decoration: none;\n transition: box-shadow 0.15s ease;\n}\n.bases-card:hover {\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.14);\n}\n\n.bases-card-image {\n overflow: hidden;\n background: var(--lightgray);\n}\n.bases-card-image img {\n width: 100%;\n height: 100%;\n display: block;\n object-fit: cover;\n}\n\n.bases-card-color {\n min-height: 60px;\n}\n\n.bases-card-title {\n font-weight: 600;\n color: var(--dark);\n}\n\n.bases-card-body {\n padding: 12px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.bases-card-meta {\n display: grid;\n gap: 4px;\n}\n\n.bases-card-row {\n display: flex;\n justify-content: space-between;\n font-size: 0.8rem;\n color: var(--darkgray);\n}\n\n.bases-card-label {\n color: var(--gray);\n}\n\n.bases-map-placeholder {\n padding: 24px;\n border: 1px dashed var(--lightgray);\n border-radius: 12px;\n background: var(--light);\n}\n\n.bases-map-message {\n color: var(--darkgray);\n margin-top: 12px;\n}\n\n.bases-empty {\n padding: 24px;\n text-align: center;\n color: var(--darkgray);\n border: 1px dashed var(--lightgray);\n border-radius: 12px;\n background: var(--light);\n}\n\n.bases-gallery {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));\n gap: 16px;\n}\n\n.bases-gallery-item {\n position: relative;\n border-radius: 12px;\n overflow: hidden;\n border: 1px solid var(--lightgray);\n background: var(--light);\n}\n\n.bases-gallery-image {\n aspect-ratio: 4/3;\n overflow: hidden;\n background: var(--lightgray);\n}\n\n.bases-gallery-image img,\n.bases-gallery-placeholder {\n width: 100%;\n height: 100%;\n display: block;\n object-fit: cover;\n}\n\n.bases-gallery-placeholder {\n background: linear-gradient(135deg, var(--lightgray), var(--highlight));\n}\n\n.bases-gallery-title {\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n padding: 10px 12px;\n background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.65) 100%);\n color: var(--light);\n font-weight: 600;\n}\n\n.bases-gallery-title a {\n color: inherit;\n}\n\n.bases-board {\n display: flex;\n gap: 16px;\n overflow-x: auto;\n padding-bottom: 4px;\n}\n\n.bases-board-column {\n min-width: min(250px, 80vw);\n flex-shrink: 0;\n border: 1px solid var(--lightgray);\n border-radius: 12px;\n background: var(--light);\n display: flex;\n flex-direction: column;\n}\n\n.bases-board-column-header {\n position: sticky;\n top: 0;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 10px 12px;\n font-weight: 600;\n background: var(--light);\n border-bottom: 1px solid var(--lightgray);\n border-radius: 12px 12px 0 0;\n z-index: 1;\n}\n\n.bases-board-count {\n background: var(--lightgray);\n color: var(--darkgray);\n border-radius: 999px;\n padding: 2px 8px;\n font-size: 0.75rem;\n}\n\n.bases-board-column-body {\n padding: 8px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.bases-board-card {\n border: 1px solid var(--lightgray);\n border-radius: 10px;\n background: var(--light);\n padding: 10px 12px;\n display: flex;\n flex-direction: column;\n gap: 6px;\n box-shadow: 0 1px 6px rgba(0, 0, 0, 0.08);\n}\n\n.bases-board-card-meta {\n display: grid;\n gap: 4px;\n font-size: 0.8rem;\n color: var(--darkgray);\n}\n\n.bases-board-card-row {\n display: flex;\n justify-content: space-between;\n gap: 8px;\n}\n\n.bases-board-card-label {\n color: var(--gray);\n}";
|
|
835
|
+
|
|
836
|
+
// src/components/scripts/bases.inline.ts
|
|
837
|
+
var bases_inline_default = `function f(e,s){let n=e.querySelectorAll(".bases-view-tabs button"),r=e.querySelectorAll(".bases-view");n.forEach(t=>{t.classList.toggle("is-active",t.dataset.viewIndex===String(s))}),r.forEach(t=>{t.classList.toggle("is-active",t.dataset.viewIndex===String(s))})}function p(e,s){let n=Number(e),r=Number(s);return!Number.isNaN(n)&&!Number.isNaN(r)?n-r:String(e).localeCompare(String(s))}function h(e,s,n){return e.length===0||(e.sort((r,t)=>{let i=r.children[s],o=t.children[s],c=i?.dataset?.value??i?.textContent??"",a=o?.dataset?.value??o?.textContent??"";return p(c,a)}),n==="desc"&&e.reverse()),e}function v(e,s,n){let r=e.querySelector("tbody");if(!r)return;let t=Array.from(r.querySelectorAll("tr"));if(n==="none"){let o=e._originalOrder;o&&o.forEach(c=>r.appendChild(c));return}if(e._originalOrder||(e._originalOrder=Array.from(t)),t.some(o=>o.classList.contains("bases-table-group-header"))){let o=[],c=null;for(let a of t)a.classList.contains("bases-table-group-header")?(c={header:a,rows:[]},o.push(c)):c?c.rows.push(a):(c={header:null,rows:[a]},o.push(c));for(let a of o)h(a.rows,s,n);for(let a of o)a.header&&r.appendChild(a.header),a.rows.forEach(l=>r.appendChild(l))}else h(t,s,n),t.forEach(o=>r.appendChild(o))}function b(e,s){e.querySelectorAll(".bases-table").forEach(r=>{let t=r.querySelectorAll("th[data-sortable='true']");t.forEach((i,o)=>{let c=()=>{let a=i.dataset.sortDirection||"none",l=a==="asc"?"desc":a==="desc"?"none":"asc";t.forEach(u=>{u!==i&&(u.dataset.sortDirection="none"),u.classList.remove("is-sorted-asc","is-sorted-desc")}),i.dataset.sortDirection=l,i.classList.toggle("is-sorted-asc",l==="asc"),i.classList.toggle("is-sorted-desc",l==="desc"),v(r,o,l)};i.addEventListener("click",c),s.push(()=>i.removeEventListener("click",c))})})}function g(e,s){let n=e.querySelectorAll(".bases-view-tabs button");if(n.length===0)return;let r=parseInt(e.dataset.initialView||"0",10);f(e,Number.isNaN(r)?0:r),n.forEach(t=>{let i=()=>{let o=parseInt(t.dataset.viewIndex||"0",10);f(e,Number.isNaN(o)?0:o)};t.addEventListener("click",i),s.push(()=>t.removeEventListener("click",i))})}function d(){let e=document.querySelectorAll(".bases-page");if(e.length===0)return;let s=[];e.forEach(n=>{g(n,s),b(n,s)}),window.addCleanup&&window.addCleanup(()=>{s.forEach(n=>{n()})})}document.addEventListener("nav",()=>{d()});document.addEventListener("render",()=>{d()});d();
|
|
838
|
+
`;
|
|
839
|
+
|
|
840
|
+
// src/components/BasesBody.tsx
|
|
841
|
+
var builtinViewsRegistered = false;
|
|
842
|
+
var BasesBody_default = ((opts) => {
|
|
843
|
+
const Component = (props) => {
|
|
844
|
+
const locale = props.cfg?.locale ?? "en-US";
|
|
845
|
+
const localeStrings = i18n(locale).components.bases;
|
|
846
|
+
const fileData = props.fileData;
|
|
847
|
+
const basesData = fileData.basesData;
|
|
848
|
+
const basesOptions = fileData.basesOptions ?? opts;
|
|
849
|
+
const basesSelfContext = fileData.basesSelfContext;
|
|
850
|
+
const slug = props.fileData.slug ?? "";
|
|
851
|
+
const rawSlugs = props.ctx?.allSlugs ?? [];
|
|
852
|
+
const baseSlugs = new Set(rawSlugs.filter((s) => s.endsWith(".base")));
|
|
853
|
+
const baseAliases = new Set([...baseSlugs].map((s) => s.replace(/\.base$/, "")));
|
|
854
|
+
const allSlugs = rawSlugs.filter((s) => !baseSlugs.has(s) && !baseAliases.has(s));
|
|
855
|
+
const linkResolution = basesOptions?.linkResolution ?? "shortest";
|
|
856
|
+
if (!basesData) {
|
|
857
|
+
return /* @__PURE__ */ u("div", { class: "bases-page bases-empty", children: localeStrings.noData });
|
|
858
|
+
}
|
|
859
|
+
const views = basesData.views ?? [];
|
|
860
|
+
if (views.length === 0) {
|
|
861
|
+
return /* @__PURE__ */ u("div", { class: "bases-page bases-empty", children: localeStrings.noViews });
|
|
862
|
+
}
|
|
863
|
+
const preferredType = basesOptions?.defaultViewType ?? "table";
|
|
864
|
+
const initialIndex = Math.max(
|
|
865
|
+
0,
|
|
866
|
+
views.findIndex((view) => view.type === preferredType)
|
|
867
|
+
);
|
|
868
|
+
if (!builtinViewsRegistered) {
|
|
869
|
+
registerBuiltinViews();
|
|
870
|
+
builtinViewsRegistered = true;
|
|
871
|
+
}
|
|
872
|
+
if (basesOptions?.customViews) {
|
|
873
|
+
registerCustomViews(basesOptions.customViews);
|
|
874
|
+
}
|
|
875
|
+
const activeTypes = new Set(views.map((v) => v.type));
|
|
876
|
+
const viewCssChunks = [];
|
|
877
|
+
for (const typeId of activeTypes) {
|
|
878
|
+
const reg = viewRegistry.get(typeId);
|
|
879
|
+
if (reg?.css) viewCssChunks.push(reg.css);
|
|
880
|
+
}
|
|
881
|
+
return /* @__PURE__ */ u("div", { class: "bases-page", "data-initial-view": initialIndex, children: [
|
|
882
|
+
viewCssChunks.length > 0 && /* @__PURE__ */ u("style", { dangerouslySetInnerHTML: { __html: viewCssChunks.join("\n") } }),
|
|
883
|
+
/* @__PURE__ */ u(ViewSelector, { views, activeIndex: initialIndex, locale }),
|
|
884
|
+
/* @__PURE__ */ u("div", { class: "bases-view-container", children: views.map((view, index) => {
|
|
885
|
+
const { entries, total } = resolveBasesEntries(
|
|
886
|
+
basesData,
|
|
887
|
+
props.allFiles,
|
|
888
|
+
view,
|
|
889
|
+
basesSelfContext
|
|
890
|
+
);
|
|
891
|
+
const registration = viewRegistry.get(view.type);
|
|
892
|
+
const Renderer = registration?.render;
|
|
893
|
+
return /* @__PURE__ */ u(
|
|
894
|
+
"div",
|
|
895
|
+
{
|
|
896
|
+
class: `bases-view ${index === initialIndex ? "is-active" : ""}`,
|
|
897
|
+
"data-view-index": index,
|
|
898
|
+
"data-view-type": view.type,
|
|
899
|
+
children: entries.length === 0 ? /* @__PURE__ */ u("div", { class: "bases-empty", children: localeStrings.noData }) : Renderer ? /* @__PURE__ */ u(
|
|
900
|
+
Renderer,
|
|
901
|
+
{
|
|
902
|
+
entries,
|
|
903
|
+
view,
|
|
904
|
+
basesData,
|
|
905
|
+
total,
|
|
906
|
+
locale,
|
|
907
|
+
slug,
|
|
908
|
+
allSlugs,
|
|
909
|
+
linkResolution,
|
|
910
|
+
options: registration.options
|
|
911
|
+
}
|
|
912
|
+
) : /* @__PURE__ */ u("div", { class: "bases-empty", children: [
|
|
913
|
+
"Unknown view type: ",
|
|
914
|
+
view.type
|
|
915
|
+
] })
|
|
916
|
+
}
|
|
917
|
+
);
|
|
918
|
+
}) })
|
|
919
|
+
] });
|
|
920
|
+
};
|
|
921
|
+
Component.css = bases_default;
|
|
922
|
+
const viewScripts = viewRegistry.getAll().map((reg) => reg.afterDOMLoaded).filter((s) => typeof s === "string" && s.length > 0);
|
|
923
|
+
Component.afterDOMLoaded = [bases_inline_default, ...viewScripts];
|
|
924
|
+
return Component;
|
|
925
|
+
});
|
|
926
|
+
|
|
927
|
+
export { BasesBody_default, ViewSelector, i18n, registerBuiltinViews, resolveBasesEntries };
|
|
928
|
+
//# sourceMappingURL=chunk-4HXXKSJ4.js.map
|
|
929
|
+
//# sourceMappingURL=chunk-4HXXKSJ4.js.map
|