@tensorix/metahub 0.5.6 → 0.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +241 -28
- package/dist/cli.js.map +9 -7
- package/dist/core/sync/page-messages.d.ts +4 -0
- package/dist/core/sync/page-messages.d.ts.map +1 -1
- package/dist/core/sync/share-serve.d.ts.map +1 -1
- package/dist/core/sync/share-table-client.d.ts +7 -0
- package/dist/core/sync/share-table-client.d.ts.map +1 -0
- package/dist/core/sync/share-table.d.ts +11 -0
- package/dist/core/sync/share-table.d.ts.map +1 -0
- package/dist/core/sync/storage-s3-bun.d.ts +2 -1
- package/dist/core/sync/storage-s3-bun.d.ts.map +1 -1
- package/dist/db-worker.js +25 -25
- package/dist/edge-worker.js +4 -0
- package/dist/index.js +241 -28
- package/dist/index.js.map +9 -7
- package/dist/mh-runtime.js +2 -2
- package/dist/sw.js +1 -1
- package/dist/webui.js +127 -126
- package/package.json +1 -1
package/dist/edge-worker.js
CHANGED
|
@@ -1850,6 +1850,10 @@ var EN = {
|
|
|
1850
1850
|
"(空文档)": "(empty document)",
|
|
1851
1851
|
文档: "Document",
|
|
1852
1852
|
表格: "Table",
|
|
1853
|
+
记录: "Record",
|
|
1854
|
+
关闭: "Close",
|
|
1855
|
+
查看全文: "Read full text",
|
|
1856
|
+
"查看「{name}」全文": "Read full {name}",
|
|
1853
1857
|
编辑: "Edit",
|
|
1854
1858
|
编辑文档: "Edit document",
|
|
1855
1859
|
保存: "Save",
|
package/dist/index.js
CHANGED
|
@@ -9389,7 +9389,7 @@ var package_default;
|
|
|
9389
9389
|
var init_package = __esm(() => {
|
|
9390
9390
|
package_default = {
|
|
9391
9391
|
name: "@tensorix/metahub",
|
|
9392
|
-
version: "0.5.
|
|
9392
|
+
version: "0.5.8",
|
|
9393
9393
|
description: "Metahub core library and CLI",
|
|
9394
9394
|
license: "AGPL-3.0-only",
|
|
9395
9395
|
type: "module",
|
|
@@ -12038,7 +12038,7 @@ var init_storage_s3_sign = __esm(() => {
|
|
|
12038
12038
|
|
|
12039
12039
|
// src/core/sync/storage-s3-bun.ts
|
|
12040
12040
|
var {S3Client } = globalThis.Bun;
|
|
12041
|
-
function
|
|
12041
|
+
function makeBunStorageClient(config) {
|
|
12042
12042
|
const vhost = isVirtualHostedStyle(config);
|
|
12043
12043
|
const s3 = new S3Client({
|
|
12044
12044
|
accessKeyId: config.accessKeyId,
|
|
@@ -12082,7 +12082,7 @@ function makeClient(config) {
|
|
|
12082
12082
|
if (opts?.ifMatch) {
|
|
12083
12083
|
const res = await aws().fetch(objectUrl(key), {
|
|
12084
12084
|
method: "PUT",
|
|
12085
|
-
body,
|
|
12085
|
+
body: new Uint8Array(body).buffer,
|
|
12086
12086
|
headers: {
|
|
12087
12087
|
"if-match": opts.ifMatch,
|
|
12088
12088
|
...opts.contentType ? { "content-type": opts.contentType } : {}
|
|
@@ -12124,7 +12124,7 @@ var init_storage_s3_bun = __esm(() => {
|
|
|
12124
12124
|
init_errors();
|
|
12125
12125
|
init_storage();
|
|
12126
12126
|
init_storage_s3_sign();
|
|
12127
|
-
setStorageClientFactory(
|
|
12127
|
+
setStorageClientFactory(makeBunStorageClient);
|
|
12128
12128
|
setBucketCorsAdmin(putBucketCors);
|
|
12129
12129
|
});
|
|
12130
12130
|
|
|
@@ -13280,6 +13280,10 @@ var init_page_messages = __esm(() => {
|
|
|
13280
13280
|
"\uFF08\u7A7A\u6587\u6863\uFF09": "(empty document)",
|
|
13281
13281
|
\u{6587}\u{6863}: "Document",
|
|
13282
13282
|
\u{8868}\u{683c}: "Table",
|
|
13283
|
+
\u{8bb0}\u{5f55}: "Record",
|
|
13284
|
+
\u{5173}\u{95ed}: "Close",
|
|
13285
|
+
\u{67e5}\u{770b}\u{5168}\u{6587}: "Read full text",
|
|
13286
|
+
"\u67E5\u770B\u300C{name}\u300D\u5168\u6587": "Read full {name}",
|
|
13283
13287
|
\u{7f16}\u{8f91}: "Edit",
|
|
13284
13288
|
\u{7f16}\u{8f91}\u{6587}\u{6863}: "Edit document",
|
|
13285
13289
|
\u{4fdd}\u{5b58}: "Save",
|
|
@@ -14972,7 +14976,7 @@ function copyScript(locale = "zh-CN") {
|
|
|
14972
14976
|
var btn=document.getElementById('mh-copy');if(!btn)return;var L=${L};
|
|
14973
14977
|
var label=btn.querySelector('span');var timer=0;
|
|
14974
14978
|
function absolutize(root){root.querySelectorAll('img[src],a[href],video[src],audio[src]').forEach(function(el){var a=el.tagName==='A'?'href':'src';var v=el.getAttribute(a);if(v&&!/^(blob|data):/.test(v))el.setAttribute(a,new URL(v,location.href).href);});}
|
|
14975
|
-
function payload(){var src=document.getElementById('mh-src');var text=src?src.content.textContent:'';var body=document.querySelector('article.doc')||document.querySelector('.table-wrap');var html='';if(body){var c=body.cloneNode(true);absolutize(c);html=c.innerHTML;}return{text:text,html:html};}
|
|
14979
|
+
function payload(){var src=document.getElementById('mh-src');var text=src?src.content.textContent:'';var body=document.querySelector('article.doc')||document.querySelector('.table-wrap');var html='';if(body){var c=body.cloneNode(true);c.querySelectorAll('.share-cell-expand').forEach(function(el){el.remove();});c.querySelectorAll('.share-cell-value').forEach(function(el){el.removeAttribute('contenteditable');el.removeAttribute('class');el.removeAttribute('style');});c.querySelectorAll('.share-table').forEach(function(el){el.removeAttribute('data-ready');});absolutize(c);html=c.innerHTML;}return{text:text,html:html};}
|
|
14976
14980
|
function legacy(text){var ta=document.createElement('textarea');ta.value=text;ta.setAttribute('readonly','');ta.style.cssText='position:fixed;top:0;left:0;opacity:0';document.body.appendChild(ta);ta.select();var ok=false;try{ok=document.execCommand('copy');}catch(e){}ta.remove();return ok?Promise.resolve():Promise.reject(new Error('copy'));}
|
|
14977
14981
|
function write(p){var nc=navigator.clipboard;if(nc&&nc.write&&window.ClipboardItem){try{return nc.write([new ClipboardItem({'text/plain':new Blob([p.text],{type:'text/plain'}),'text/html':new Blob([p.html],{type:'text/html'})})]);}catch(e){}}if(nc&&nc.writeText)return nc.writeText(p.text);return legacy(p.text);}
|
|
14978
14982
|
function settle(cls,txt){clearTimeout(timer);btn.classList.remove('done','fail');void btn.offsetWidth;btn.classList.add(cls);if(label)label.textContent=txt;timer=setTimeout(function(){btn.classList.remove(cls);if(label)label.textContent=L.idle;},1600);}
|
|
@@ -14996,6 +15000,140 @@ var init_share_copy = __esm(() => {
|
|
|
14996
15000
|
init_page_messages();
|
|
14997
15001
|
});
|
|
14998
15002
|
|
|
15003
|
+
// src/core/sync/share-table-client.js
|
|
15004
|
+
function mountShareTable(labels) {
|
|
15005
|
+
const table = document.querySelector("table.share-table");
|
|
15006
|
+
const peek = document.querySelector(".share-text-peek");
|
|
15007
|
+
if (!table || !peek || typeof peek.showModal !== "function")
|
|
15008
|
+
return;
|
|
15009
|
+
const heading = peek.querySelector("h2");
|
|
15010
|
+
const record = peek.querySelector(".share-text-record");
|
|
15011
|
+
const body = peek.querySelector(".share-text-body");
|
|
15012
|
+
const feedback = peek.querySelector(".share-text-feedback");
|
|
15013
|
+
let restore = null;
|
|
15014
|
+
let selected = null;
|
|
15015
|
+
const select = (cell) => {
|
|
15016
|
+
selected?.classList.remove("is-selected");
|
|
15017
|
+
selected = cell;
|
|
15018
|
+
cell.classList.add("is-selected");
|
|
15019
|
+
};
|
|
15020
|
+
const measure = (value) => {
|
|
15021
|
+
const button = value.parentElement.querySelector(".share-cell-expand");
|
|
15022
|
+
button.hidden = !(value.scrollHeight > value.clientHeight + 1 || value.scrollWidth > value.clientWidth + 1);
|
|
15023
|
+
};
|
|
15024
|
+
table.dataset.ready = "";
|
|
15025
|
+
const values = Array.from(table.querySelectorAll(".share-cell-value"));
|
|
15026
|
+
const observer = typeof ResizeObserver !== "undefined" ? new ResizeObserver((entries) => {
|
|
15027
|
+
for (const entry of entries)
|
|
15028
|
+
measure(entry.target);
|
|
15029
|
+
}) : null;
|
|
15030
|
+
for (const value of values) {
|
|
15031
|
+
measure(value);
|
|
15032
|
+
observer?.observe(value);
|
|
15033
|
+
value.addEventListener("input", () => measure(value));
|
|
15034
|
+
value.addEventListener("blur", () => requestAnimationFrame(() => measure(value)));
|
|
15035
|
+
}
|
|
15036
|
+
document.fonts?.ready.then(() => values.forEach(measure));
|
|
15037
|
+
table.addEventListener("click", (event) => {
|
|
15038
|
+
const target = event.target;
|
|
15039
|
+
const cell = target.closest("td");
|
|
15040
|
+
if (!cell)
|
|
15041
|
+
return;
|
|
15042
|
+
select(cell);
|
|
15043
|
+
const button = target.closest(".share-cell-expand");
|
|
15044
|
+
if (!button)
|
|
15045
|
+
return;
|
|
15046
|
+
const column = Array.from(cell.parentElement.children).indexOf(cell);
|
|
15047
|
+
heading.textContent = table.querySelectorAll("thead th")[column].textContent;
|
|
15048
|
+
record.textContent = cell.parentElement.querySelector(".share-cell-value")?.textContent || labels.record;
|
|
15049
|
+
body.textContent = cell.querySelector(".share-cell-value").textContent;
|
|
15050
|
+
feedback.textContent = "";
|
|
15051
|
+
restore = button;
|
|
15052
|
+
peek.showModal();
|
|
15053
|
+
body.scrollTop = 0;
|
|
15054
|
+
});
|
|
15055
|
+
peek.querySelector(".share-text-close").addEventListener("click", () => peek.close());
|
|
15056
|
+
peek.addEventListener("click", (event) => {
|
|
15057
|
+
const rect = peek.getBoundingClientRect();
|
|
15058
|
+
if (event.target === peek && (event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom))
|
|
15059
|
+
peek.close();
|
|
15060
|
+
});
|
|
15061
|
+
peek.addEventListener("close", () => restore?.focus({ preventScroll: true }));
|
|
15062
|
+
peek.querySelector(".share-text-copy").addEventListener("click", async () => {
|
|
15063
|
+
const text = body.textContent ?? "";
|
|
15064
|
+
try {
|
|
15065
|
+
await navigator.clipboard.writeText(text);
|
|
15066
|
+
feedback.textContent = labels.copied;
|
|
15067
|
+
} catch {
|
|
15068
|
+
const input = document.createElement("textarea");
|
|
15069
|
+
input.value = text;
|
|
15070
|
+
input.readOnly = true;
|
|
15071
|
+
input.style.cssText = "position:fixed;opacity:0;top:0;left:0";
|
|
15072
|
+
peek.append(input);
|
|
15073
|
+
input.select();
|
|
15074
|
+
try {
|
|
15075
|
+
feedback.textContent = document.execCommand("copy") ? labels.copied : labels.failed;
|
|
15076
|
+
} catch {
|
|
15077
|
+
feedback.textContent = labels.failed;
|
|
15078
|
+
}
|
|
15079
|
+
input.remove();
|
|
15080
|
+
peek.querySelector(".share-text-copy").focus();
|
|
15081
|
+
}
|
|
15082
|
+
});
|
|
15083
|
+
}
|
|
15084
|
+
|
|
15085
|
+
// src/core/sync/share-table.ts
|
|
15086
|
+
function shareCellHtml(html, name, locale, editAttrs = "") {
|
|
15087
|
+
return `<td><div class="share-cell-value"${editAttrs ? ` ${editAttrs}` : ""}>${html}</div><button type="button" class="share-cell-expand" hidden aria-label="${escapeHtml(pm(locale, "\u67E5\u770B\u300C{name}\u300D\u5168\u6587", { name }))}" title="${escapeHtml(pm(locale, "\u67E5\u770B\u5168\u6587"))}">${expandIcon}</button></td>`;
|
|
15088
|
+
}
|
|
15089
|
+
function shareTableHtml(columns, rows, locale) {
|
|
15090
|
+
const widths = columns.map((p) => typeof p.width === "number" && Number.isFinite(p.width) ? Math.max(80, Math.min(640, p.width)) : 180);
|
|
15091
|
+
return `<div class="table-wrap"><table class="db share-table" style="width:${widths.reduce((a, b) => a + b, 0)}px"><colgroup>${widths.map((w) => `<col style="width:${w}px">`).join("")}</colgroup><thead><tr>${columns.map((p) => `<th scope="col" title="${escapeHtml(p.name)}">${escapeHtml(p.name)}</th>`).join("")}</tr></thead><tbody>${rows}</tbody></table></div>
|
|
15092
|
+
<dialog class="share-text-peek" aria-labelledby="share-text-heading">
|
|
15093
|
+
<div class="share-text-toolbar"><button type="button" class="share-text-close" aria-label="${escapeHtml(pm(locale, "\u5173\u95ED"))}" autofocus>${closeIcon}</button><button type="button" class="copy-btn share-text-copy">${escapeHtml(pm(locale, "\u590D\u5236\u5168\u6587"))}</button><span class="share-text-feedback" role="status"></span></div>
|
|
15094
|
+
<div class="share-text-heading"><h2 id="share-text-heading"></h2><p class="share-text-record"></p></div>
|
|
15095
|
+
<div class="share-text-body" tabindex="0"></div>
|
|
15096
|
+
</dialog>`;
|
|
15097
|
+
}
|
|
15098
|
+
function shareTableScript(locale) {
|
|
15099
|
+
return `(${mountShareTable.toString()})(${JSON.stringify({ copied: pm(locale, "\u5DF2\u590D\u5236"), failed: pm(locale, "\u590D\u5236\u5931\u8D25"), record: pm(locale, "\u8BB0\u5F55") })});`;
|
|
15100
|
+
}
|
|
15101
|
+
var expandIcon = '<svg viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M15 4v16"/></svg>', closeIcon = '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="m6 6 12 12M18 6 6 18"/></svg>', SHARE_TABLE_CSS = `
|
|
15102
|
+
#app:has(.share-table),.wrap:has(.share-table){max-width:1440px}
|
|
15103
|
+
.table-wrap:has(.share-table){max-width:100%;overflow:auto;overscroll-behavior-x:contain}
|
|
15104
|
+
table.share-table{table-layout:fixed;min-width:100%}
|
|
15105
|
+
table.share-table th{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:500;color:var(--muted)}
|
|
15106
|
+
table.share-table td{position:relative;vertical-align:top}
|
|
15107
|
+
.share-cell-value{min-width:0;white-space:pre-wrap;overflow-wrap:anywhere;line-height:1.55}
|
|
15108
|
+
.share-table[data-ready] .share-cell-value{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;overflow:hidden;max-height:4.65em}
|
|
15109
|
+
.share-table .tag{max-width:100%;overflow:hidden;text-overflow:ellipsis;vertical-align:middle;white-space:nowrap}
|
|
15110
|
+
.share-cell-expand{position:absolute;top:5px;right:5px;display:flex;align-items:center;justify-content:center;width:26px;height:26px;padding:0;border:1px solid var(--line);border-radius:5px;background:var(--bg);color:var(--fg);cursor:pointer;opacity:0;pointer-events:none}
|
|
15111
|
+
.share-cell-expand[hidden]{display:none}
|
|
15112
|
+
.share-cell-expand svg,.share-text-close svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}
|
|
15113
|
+
.share-table td:is(:hover,:focus-within,.is-selected) .share-cell-expand{opacity:1;pointer-events:auto}
|
|
15114
|
+
.share-table td.is-selected{box-shadow:inset 0 0 0 1.5px var(--accent);background:var(--accent-soft)}
|
|
15115
|
+
.share-cell-expand:hover,.share-text-close:hover{background:var(--card)}
|
|
15116
|
+
.share-cell-expand:focus-visible,.share-text-close:focus-visible,.share-text-body:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
|
|
15117
|
+
.share-table[data-ready] [contenteditable]:focus{display:block;-webkit-line-clamp:unset;max-height:min(320px,40vh);overflow:auto;outline:2px solid var(--accent);outline-offset:2px}
|
|
15118
|
+
.share-cell-value.saving{opacity:.5}.share-cell-value.saved{background:color-mix(in srgb,var(--success) 18%,transparent)}
|
|
15119
|
+
.share-text-peek{position:fixed;inset:0 0 0 auto;margin:0;padding:0;width:min(620px,100vw);max-width:100vw;height:100vh;height:100dvh;max-height:100dvh;border:0;border-inline-start:1px solid var(--line);background:var(--bg);color:var(--fg);font:inherit;overflow:hidden}
|
|
15120
|
+
.share-text-peek[open]{display:flex;flex-direction:column}
|
|
15121
|
+
.share-text-peek::backdrop{background:rgba(15,15,25,.3)}
|
|
15122
|
+
body:has(.share-text-peek[open]){overflow:hidden}
|
|
15123
|
+
.share-text-toolbar{display:flex;align-items:center;gap:12px;flex:none;padding:12px 20px;border-bottom:1px solid var(--line)}
|
|
15124
|
+
.share-text-close{display:flex;align-items:center;justify-content:center;width:32px;height:32px;margin-inline-end:auto;border:0;border-radius:5px;background:transparent;color:var(--muted);cursor:pointer}
|
|
15125
|
+
.share-text-feedback{font-size:13px;color:var(--muted)}.share-text-feedback:empty{display:none}
|
|
15126
|
+
.share-text-heading{flex:none;padding:24px 32px 16px;min-width:0}
|
|
15127
|
+
.share-text-heading h2{margin:0;font-size:20px;line-height:1.4;overflow-wrap:anywhere}
|
|
15128
|
+
.share-text-record{margin:6px 0 0;font-size:13px;color:var(--muted);display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;overflow-wrap:anywhere}
|
|
15129
|
+
.share-text-body{flex:1;min-height:0;overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable;padding:0 32px 40px;white-space:pre-wrap;overflow-wrap:anywhere;line-height:1.75;user-select:text}
|
|
15130
|
+
@media(max-width:600px){.share-text-peek{width:100vw}.share-text-toolbar{padding:10px 14px}.share-text-heading{padding:20px 20px 16px}.share-text-body{padding:0 20px 32px;font-size:16px}}
|
|
15131
|
+
@media(hover:none),(pointer:coarse){.share-cell-expand{opacity:1;pointer-events:auto;width:44px;height:44px;top:0;right:0}.share-table td:has(.share-cell-expand:not([hidden])) .share-cell-value{min-height:44px}.share-text-close{width:44px;height:44px}}
|
|
15132
|
+
`;
|
|
15133
|
+
var init_share_table = __esm(() => {
|
|
15134
|
+
init_page_messages();
|
|
15135
|
+
});
|
|
15136
|
+
|
|
14999
15137
|
// src/core/sync/share-serve.ts
|
|
15000
15138
|
function notFound() {
|
|
15001
15139
|
return new Response("not found", { status: 404 });
|
|
@@ -15162,19 +15300,18 @@ async function serveTable(ctx, req, share, sub, locale) {
|
|
|
15162
15300
|
}
|
|
15163
15301
|
const titlesFor = (p) => p.type === "relation" ? relTitles.get(p.config?.database ?? "") : undefined;
|
|
15164
15302
|
const editable = share.permission === "edit";
|
|
15165
|
-
const head = props.map((p) => `<th>${escapeHtml(p.name)}</th>`).join("");
|
|
15166
15303
|
const rows = records.map((r) => {
|
|
15167
15304
|
const tds = props.map((p) => {
|
|
15168
15305
|
const v = r.cells[p.id];
|
|
15169
15306
|
if (editable && editableType(p.type)) {
|
|
15170
|
-
return
|
|
15307
|
+
return shareCellHtml(escapeHtml(cellText(p, v)), p.name, locale, `contenteditable aria-label="${escapeHtml(p.name)}" data-rec="${escapeHtml(r.id)}" data-prop="${escapeHtml(p.id)}" data-type="${p.type}"`);
|
|
15171
15308
|
}
|
|
15172
|
-
return
|
|
15309
|
+
return shareCellHtml(cellHtml(p, v, titlesFor(p)), p.name, locale);
|
|
15173
15310
|
}).join("");
|
|
15174
15311
|
return `<tr>${tds}</tr>`;
|
|
15175
15312
|
}).join("");
|
|
15176
|
-
const inner =
|
|
15177
|
-
const script = editable ? tableEditScript(locale, share.slug) : "";
|
|
15313
|
+
const inner = shareTableHtml(props.map((p) => ({ name: p.name, width: p.config?.width })), rows, locale);
|
|
15314
|
+
const script = shareTableScript(locale) + (editable ? tableEditScript(locale, share.slug) : "");
|
|
15178
15315
|
const copySource = markdownTable(props.map((p) => p.name), records.map((r) => props.map((p) => cellText(p, r.cells[p.id], titlesFor(p)))));
|
|
15179
15316
|
return new Response(pageShell(dbRow.name || pm(locale, "\u8868\u683C"), inner, {
|
|
15180
15317
|
lang: locale,
|
|
@@ -15186,7 +15323,7 @@ async function serveTable(ctx, req, share, sub, locale) {
|
|
|
15186
15323
|
function tableEditScript(locale, slug) {
|
|
15187
15324
|
return `
|
|
15188
15325
|
const L=${JSON.stringify({ failed: pm(locale, "\u4FDD\u5B58\u5931\u8D25") })};
|
|
15189
|
-
document.querySelectorAll('
|
|
15326
|
+
document.querySelectorAll('.share-cell-value[contenteditable]').forEach(td=>{
|
|
15190
15327
|
let orig=td.textContent;
|
|
15191
15328
|
td.addEventListener('blur', async ()=>{
|
|
15192
15329
|
const val=td.textContent;
|
|
@@ -15412,6 +15549,7 @@ function pageShell(title, inner, opts) {
|
|
|
15412
15549
|
header.mh h1.title{font-size:22px;margin:0}
|
|
15413
15550
|
.edit-btn{background:var(--accent);color:var(--accent-fg);border:0;border-radius:7px;height:32px;padding:0 14px;cursor:pointer;font-size:13px;font-weight:500;font-family:inherit}
|
|
15414
15551
|
${COPY_CSS}
|
|
15552
|
+
${SHARE_TABLE_CSS}
|
|
15415
15553
|
.hint{color:var(--muted);font-size:13px;margin:0 0 14px}
|
|
15416
15554
|
article.doc h1,article.doc h2,article.doc h3{line-height:1.3;margin:1.4em 0 .5em}
|
|
15417
15555
|
article.doc h1{font-size:1.7em} article.doc h2{font-size:1.4em} article.doc h3{font-size:1.2em}
|
|
@@ -15471,6 +15609,7 @@ var init_share_serve = __esm(() => {
|
|
|
15471
15609
|
init_share_render();
|
|
15472
15610
|
init_share_copy();
|
|
15473
15611
|
init_page_messages();
|
|
15612
|
+
init_share_table();
|
|
15474
15613
|
HTML = { "content-type": "text/html; charset=utf-8" };
|
|
15475
15614
|
HASH_RE2 = /^[0-9a-f]{16,64}$/;
|
|
15476
15615
|
SHARE_SESSION_TTL_MS = 12 * 60 * 60 * 1000;
|
|
@@ -17073,9 +17212,30 @@ var styles_default = ` :root {
|
|
|
17073
17212
|
.theme-card.sel .tc-ico { background:var(--selected-icon-bg); color:var(--selected-icon-fg); }
|
|
17074
17213
|
.theme-card.sel .tc-check { opacity:1; transform:scale(1); }
|
|
17075
17214
|
@media (max-width:560px) { .theme-grid { grid-template-columns:1fr; } }
|
|
17076
|
-
.brand-
|
|
17077
|
-
.brand-
|
|
17078
|
-
.brand-
|
|
17215
|
+
.brand-appearance { container:brand-appearance / inline-size; border:1px solid var(--line); border-radius:var(--radius-lg); background:var(--bg); }
|
|
17216
|
+
.brand-controls { display:grid; grid-template-columns:64px minmax(0,1fr); align-items:center; gap:24px; padding:18px 24px; }
|
|
17217
|
+
.brand-preview { display:block; width:64px; height:64px; }
|
|
17218
|
+
.brand-options { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:24px; min-width:0; padding-left:24px; border-left:1px solid var(--line); }
|
|
17219
|
+
.brand-option-row { display:grid; align-content:center; gap:6px; min-width:0; }
|
|
17220
|
+
.brand-option-label { color:var(--fg-soft); font-size:var(--fs-ui); }
|
|
17221
|
+
.brand-segments { display:flex; gap:2px; padding:3px; border-radius:var(--radius); background:var(--surface-2); }
|
|
17222
|
+
.brand-segment { position:relative; flex:1; min-width:0; text-align:center; }
|
|
17223
|
+
.brand-segment input { position:absolute; inset:0; width:100%; height:100%; opacity:0; margin:0; cursor:pointer; }
|
|
17224
|
+
.brand-segment > span { display:flex; align-items:center; justify-content:center; min-height:32px; padding:4px 12px;
|
|
17225
|
+
border-radius:var(--radius-sm); color:var(--muted); font-size:var(--fs-ui); pointer-events:none;
|
|
17226
|
+
transition:background .14s,color .14s; }
|
|
17227
|
+
.brand-segment:hover > span { color:var(--fg); }
|
|
17228
|
+
.brand-segment input:checked + span { background:var(--bg); color:var(--accent); font-weight:600; }
|
|
17229
|
+
.brand-segment input:focus-visible + span { outline:2px solid var(--accent); outline-offset:2px; }
|
|
17230
|
+
@container brand-appearance (max-width:480px) {
|
|
17231
|
+
.brand-controls { grid-template-columns:48px minmax(0,1fr); gap:16px; padding:16px; }
|
|
17232
|
+
.brand-preview { width:48px; height:48px; }
|
|
17233
|
+
.brand-options { grid-template-columns:minmax(0,1fr); gap:10px; padding-left:16px; }
|
|
17234
|
+
.brand-option-row { gap:4px; }
|
|
17235
|
+
.brand-option-label { font-size:var(--fs-sm); }
|
|
17236
|
+
.brand-segment > span { padding:4px 8px; }
|
|
17237
|
+
}
|
|
17238
|
+
@media (pointer:coarse) { .brand-segment > span { min-height:44px; } }
|
|
17079
17239
|
.theme-card:disabled { opacity:.55; cursor:not-allowed; }
|
|
17080
17240
|
.theme-card:disabled:hover { transform:none; border-color:var(--line-strong); }
|
|
17081
17241
|
|
|
@@ -17823,10 +17983,9 @@ var styles_default = ` :root {
|
|
|
17823
17983
|
.proprow-v .x:disabled:hover { background:none; color:var(--muted); }
|
|
17824
17984
|
.tablewrap { border-top:1px solid var(--line); border-bottom:1px solid var(--line); }
|
|
17825
17985
|
.tablescroll { overflow-x:auto; }
|
|
17826
|
-
/*
|
|
17827
|
-
|
|
17828
|
-
|
|
17829
|
-
narrow, with the slack absorbed only by the trailing auto (filler) column. */
|
|
17986
|
+
/* The grid supplies a definite width (sum of its columns): max-content alone
|
|
17987
|
+
lets intrinsic long text override fixed layout in some engines. min-width
|
|
17988
|
+
fills the container, with slack absorbed by the trailing filler column. */
|
|
17830
17989
|
table.grid { border-collapse:collapse; table-layout:fixed; width:max-content; min-width:100%; }
|
|
17831
17990
|
table.grid th, table.grid td { border-right:1px solid var(--line); border-bottom:1px solid var(--line); padding:0; text-align:left; }
|
|
17832
17991
|
table.grid th:last-child, table.grid td:last-child { border-right:0; }
|
|
@@ -17836,6 +17995,7 @@ var styles_default = ` :root {
|
|
|
17836
17995
|
.colhead:hover { background:var(--hover); color:var(--fg-soft); }
|
|
17837
17996
|
.colhead .ti { color:var(--muted); display:flex; } .colhead .ti svg { width:14px; height:14px; }
|
|
17838
17997
|
.colhead .nm { flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
|
|
17998
|
+
.colhead, .colhead .nm { min-width:0; }
|
|
17839
17999
|
.colhead .sortmark { width:12px; height:12px; color:var(--accent); flex:none; }
|
|
17840
18000
|
.colhead .caret { width:12px; height:12px; color:var(--muted); flex:none; opacity:0; transition:opacity .12s; }
|
|
17841
18001
|
.colhead:hover .caret { opacity:1; }
|
|
@@ -17856,9 +18016,9 @@ var styles_default = ` :root {
|
|
|
17856
18016
|
table.grid td.filler { border-right:0; border-bottom:0; background:transparent; }
|
|
17857
18017
|
body.col-resizing { user-select:none; cursor:col-resize; }
|
|
17858
18018
|
table.grid .selcell { width:38px; min-width:38px; max-width:38px; text-align:center; }
|
|
17859
|
-
/* relative: anchors
|
|
18019
|
+
/* relative: anchors preview actions and the selection fill handle */
|
|
17860
18020
|
td.cell-td { position:relative; vertical-align:top; user-select:none; }
|
|
17861
|
-
|
|
18021
|
+
.celledit, .celledit * { user-select:text; }
|
|
17862
18022
|
.cell { padding:8px 11px; min-height:37px; cursor:text; word-break:break-word; display:flex; flex-wrap:wrap; gap:3px; align-items:center; }
|
|
17863
18023
|
/* hover/active tint goes on the <td> (always full row height) not the inner
|
|
17864
18024
|
.cell (only as tall as its content), so a taller sibling row never leaves a
|
|
@@ -17942,18 +18102,36 @@ var styles_default = ` :root {
|
|
|
17942
18102
|
.inlineedit { width:100%; border:0; outline:2px solid var(--accent); border-radius:0; padding:7px 9px; background:var(--bg); color:var(--fg); font:inherit; }
|
|
17943
18103
|
textarea.inlineedit { resize:none; overflow:hidden; line-height:1.45; display:block; }
|
|
17944
18104
|
.inlineedit.num { text-align:right; font-variant-numeric:tabular-nums; }
|
|
17945
|
-
/* Overlay cell editor:
|
|
17946
|
-
stays in flow so the row height never changes
|
|
18105
|
+
/* Overlay cell editor: portaled to body to escape the table scrollport.
|
|
18106
|
+
The display stays in flow so the row height never changes. Padding on the
|
|
17947
18107
|
input matches .cell (8px 11px) so the text doesn't shift on entering edit;
|
|
17948
18108
|
a multi-line text editor grows downward over the rows below. */
|
|
17949
|
-
.celledit { position:
|
|
18109
|
+
.celledit { position:fixed; z-index:60;
|
|
17950
18110
|
display:flex; align-items:stretch; background:var(--bg); border-radius:0;
|
|
17951
18111
|
box-shadow:inset 0 0 0 2px var(--accent), var(--shadow-md); }
|
|
17952
18112
|
.celledit .inlineedit { width:100%; min-width:0; border:0; outline:0; border-radius:inherit;
|
|
17953
18113
|
padding:8px 11px; background:transparent; }
|
|
17954
|
-
.celledit textarea.inlineedit { min-height:
|
|
18114
|
+
.celledit textarea.inlineedit { min-height:0; max-height:min(320px, 40vh, var(--cell-editor-max-height)); }
|
|
17955
18115
|
.cell.num { justify-content:flex-end; font-variant-numeric:tabular-nums; }
|
|
17956
18116
|
.cell .txt { white-space:pre-wrap; }
|
|
18117
|
+
/* Grid text is a preview; full text belongs in the record drawer. Never
|
|
18118
|
+
truncate stored values or let a long token determine the column width. */
|
|
18119
|
+
.cell-preview { width:100%; min-width:0; }
|
|
18120
|
+
.cell .cell-preview-text { display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:3;
|
|
18121
|
+
overflow:hidden; overflow-wrap:anywhere; line-height:1.55; max-height:4.65em; }
|
|
18122
|
+
table.grid.nowrap .cell .cell-preview-text { display:block; -webkit-line-clamp:unset; max-height:1.55em; }
|
|
18123
|
+
/* Overlay the action so revealing it never changes row height. Opacity keeps
|
|
18124
|
+
it keyboard reachable; focus-within reveals it before activation. */
|
|
18125
|
+
.cell-read-more { position:absolute; top:6px; right:6px; z-index:2; display:flex; align-items:center; justify-content:center;
|
|
18126
|
+
width:24px; height:24px; padding:0; border:1px solid var(--line); border-radius:var(--radius-sm);
|
|
18127
|
+
background:var(--bg); color:var(--fg-soft); cursor:pointer; opacity:0; pointer-events:none; }
|
|
18128
|
+
td.cell-td:is(:hover, .cellsel, :focus-within) .cell-read-more { opacity:1; pointer-events:auto; }
|
|
18129
|
+
.firstcell:has(.cell-read-more) .rowactions { display:none; }
|
|
18130
|
+
.cell-read-more svg { width:14px; height:14px; flex:none; }
|
|
18131
|
+
.cell-read-more:hover { background:var(--surface-2); color:var(--fg); border-color:var(--line-strong); }
|
|
18132
|
+
.cell-read-more:focus-visible, .peek-copy:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
|
|
18133
|
+
textarea.inlineedit { max-height:min(320px, 40vh); overflow-y:auto; overflow-wrap:anywhere; }
|
|
18134
|
+
table.grid .chip { max-width:100%; overflow:hidden; text-overflow:ellipsis; }
|
|
17957
18135
|
.cell-url { display:inline-flex; align-items:center; gap:4px; max-width:100%; min-width:0; color:var(--accent); text-decoration:none; }
|
|
17958
18136
|
.cell-url span { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
|
|
17959
18137
|
.cell-url svg { flex:none; width:12px; height:12px; opacity:0; transition:opacity .1s; }
|
|
@@ -18395,6 +18573,33 @@ var styles_default = ` :root {
|
|
|
18395
18573
|
.peek .proprow .k { cursor:pointer; }
|
|
18396
18574
|
.proprow .v { flex:1; padding:7px 8px; border-radius:var(--radius-sm); cursor:text; min-height:33px; display:flex; flex-wrap:wrap; gap:3px; align-items:center; }
|
|
18397
18575
|
.proprow .v:hover { background:var(--hover); }
|
|
18576
|
+
.peek h2, .proprow .v { min-width:0; overflow-wrap:anywhere; }
|
|
18577
|
+
.proprow .v .txt { white-space:pre-wrap; overflow-wrap:anywhere; max-width:100%; user-select:text; }
|
|
18578
|
+
.proprow .k { min-width:0; }
|
|
18579
|
+
.proprow .k > svg { flex:none; }
|
|
18580
|
+
.proprow .k > span { min-width:0; overflow-wrap:anywhere; }
|
|
18581
|
+
.proprow-long { flex-direction:column; gap:0; margin-block:18px; scroll-margin-top:8px; }
|
|
18582
|
+
.proprow-long .k { width:100%; }
|
|
18583
|
+
.proprow-long .v { width:100%; line-height:1.7; }
|
|
18584
|
+
.proprow:focus-visible { outline:2px solid var(--accent); outline-offset:3px; border-radius:var(--radius-sm); }
|
|
18585
|
+
.peek-copy { display:inline-flex; align-items:center; justify-content:center; flex:none; width:24px; height:24px;
|
|
18586
|
+
margin-inline-start:auto; border-radius:var(--radius-sm); color:var(--muted); cursor:pointer; }
|
|
18587
|
+
.peek-copy:hover { background:var(--hover-2); color:var(--fg); }
|
|
18588
|
+
@media (max-width:560px) {
|
|
18589
|
+
.peek-body { padding:20px 16px; }
|
|
18590
|
+
.peek .proprow { flex-direction:column; gap:0; margin-block:12px; }
|
|
18591
|
+
.peek .proprow .k, .peek .proprow .v { width:100%; }
|
|
18592
|
+
.peek .proprow .v { font-size:16px; }
|
|
18593
|
+
.peek textarea.inlineedit { font-size:16px; }
|
|
18594
|
+
}
|
|
18595
|
+
@media (pointer:coarse) {
|
|
18596
|
+
.cell:has(.cell-read-more) { min-height:44px; }
|
|
18597
|
+
.cell-read-more { width:44px; height:44px; top:0; right:0; }
|
|
18598
|
+
.peek-copy { width:44px; height:44px; }
|
|
18599
|
+
}
|
|
18600
|
+
@media (hover:none), (pointer:coarse) {
|
|
18601
|
+
.cell-read-more { opacity:1; pointer-events:auto; }
|
|
18602
|
+
}
|
|
18398
18603
|
.peek-divider { height:1px; background:var(--line); margin:22px 0 18px; }
|
|
18399
18604
|
.peek-hidden-toggle { display:flex; align-items:center; gap:6px; padding:7px 8px; margin:2px 0; border-radius:var(--radius-sm); color:var(--muted); font-size:13px; width:100%; text-align:left; }
|
|
18400
18605
|
.peek-hidden-toggle:hover { background:var(--hover); color:var(--fg-soft); }
|
|
@@ -18702,14 +18907,22 @@ var styles_default = ` :root {
|
|
|
18702
18907
|
.tmpl .tt { font-weight:600; font-size:var(--fs-ui); } .tmpl .td { font-size:var(--fs-xs); color:var(--muted); margin-top:2px; }
|
|
18703
18908
|
|
|
18704
18909
|
/* toast */
|
|
18705
|
-
.toasts { position:fixed; bottom:20px; left:20px; z-index:110; display:flex; flex-direction:column; gap:8px; }
|
|
18706
|
-
.toast { background:var(--fg); color:var(--bg); padding:10px 14px; border-radius:9px; font-size:13px; box-shadow:var(--shadow-lg);
|
|
18910
|
+
.toasts { position:fixed; bottom:20px; left:20px; max-width:calc(100vw - 40px); z-index:110; display:flex; flex-direction:column; gap:8px; }
|
|
18911
|
+
.toast { position:relative; box-sizing:border-box; touch-action:pan-y; user-select:none; transform:translateX(var(--toast-offset, 0px)); transition:transform .18s ease-out, opacity .16s ease; background:var(--fg); color:var(--bg); padding:10px 14px; border-radius:9px; font-size:13px; box-shadow:var(--shadow-lg);
|
|
18707
18912
|
display:flex; align-items:center; gap:8px; animation:slidein .2s ease; }
|
|
18708
18913
|
@keyframes slidein { from { opacity:0; transform:translateX(-12px); } }
|
|
18709
18914
|
.toast.error { background:var(--danger); color:var(--danger-fg); }
|
|
18710
18915
|
.toast.leaving { animation:toast-out .16s ease-in forwards; pointer-events:none; }
|
|
18711
18916
|
@keyframes toast-out { to { opacity:0; transform:translateX(-8px); } }
|
|
18712
|
-
.toast-msg { min-width:0; }
|
|
18917
|
+
.toast-msg { min-width:0; overflow-wrap:anywhere; }
|
|
18918
|
+
.toast > .ico, .toast-act { flex-shrink:0; }
|
|
18919
|
+
.toast.dragging { animation:none; transition:none; cursor:grabbing; }
|
|
18920
|
+
.toast.leaving.swipe-out { animation:none; transition:transform .16s ease-in, opacity .16s ease-in; }
|
|
18921
|
+
.toast-act:focus-visible { outline:2px solid currentColor; outline-offset:2px; }
|
|
18922
|
+
@media (prefers-reduced-motion:reduce) {
|
|
18923
|
+
.toast, .toast.dragging, .toast.leaving, .toast.leaving.swipe-out { animation:none; transition:none; transform:none; }
|
|
18924
|
+
.toast.leaving { opacity:0; }
|
|
18925
|
+
}
|
|
18713
18926
|
.toast-act { margin-left:4px; padding:3px 9px; border-radius:6px; font-weight:600; color:inherit; background:color-mix(in srgb, var(--bg) 16%, transparent); white-space:nowrap; }
|
|
18714
18927
|
.toast-act:hover { background:color-mix(in srgb, var(--bg) 28%, transparent); }
|
|
18715
18928
|
|
|
@@ -25344,4 +25557,4 @@ export {
|
|
|
25344
25557
|
writeTx
|
|
25345
25558
|
};
|
|
25346
25559
|
|
|
25347
|
-
//# debugId=
|
|
25560
|
+
//# debugId=049F5CBBC74592BC64756E2164756E21
|