@pipelex/mthds-form 0.11.0 → 0.12.1
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/{chunk-E2IVBAW3.js → chunk-2D4NEFUH.js} +293 -104
- package/dist/chunk-2D4NEFUH.js.map +1 -0
- package/dist/chunk-7KQXGG6J.js +127 -0
- package/dist/chunk-7KQXGG6J.js.map +1 -0
- package/dist/{chunk-TID7ZN63.js → chunk-CM4KVG53.js} +13 -10
- package/dist/chunk-CM4KVG53.js.map +1 -0
- package/dist/{chunk-4JQAJT7C.js → chunk-RRTI7AIR.js} +25 -38
- package/dist/chunk-RRTI7AIR.js.map +1 -0
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.js +3 -2
- package/dist/core/native-content.d.ts +6 -1
- package/dist/core/native-content.js +1 -1
- package/dist/core/save-plan.d.ts +145 -0
- package/dist/core/save-plan.js +6 -0
- package/dist/core/save-plan.js.map +1 -0
- package/dist/core/stuff-files.d.ts +26 -3
- package/dist/core/stuff-files.js +2 -2
- package/dist/generative/index.js +7 -5
- package/dist/generative/index.js.map +1 -1
- package/dist/react/index.d.ts +177 -108
- package/dist/react/index.js +4 -3
- package/package.json +1 -1
- package/dist/chunk-4JQAJT7C.js.map +0 -1
- package/dist/chunk-E2IVBAW3.js.map +0 -1
- package/dist/chunk-TID7ZN63.js.map +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { planStuffSave, planFileSave } from './chunk-7KQXGG6J.js';
|
|
2
|
+
import { readStuffFile } from './chunk-RRTI7AIR.js';
|
|
3
|
+
import { viewableUrl, isNativeDateNode, isNativeHtmlNode, readHtmlContent, isNativeCompositeNode, readCompositeContent, isNativeValueNode, readDateContent, formatDateContent, readImageContent, readDataUrl, readDocumentContent } from './chunk-CM4KVG53.js';
|
|
3
4
|
import { conceptCategory } from './chunk-FABY3DEY.js';
|
|
4
5
|
import { acceptLabel, acceptMap, isAcceptedFile, formatOfFilename, DOCUMENT_FORMATS, IMAGE_FORMATS } from './chunk-XCO6GTEC.js';
|
|
5
6
|
import { isFilled } from './chunk-PM55AHRO.js';
|
|
@@ -7,7 +8,7 @@ import { toStoredDateValue, toDateInputValue } from './chunk-GKV77RAS.js';
|
|
|
7
8
|
import { ownProp } from './chunk-V3OV2XQT.js';
|
|
8
9
|
import { clsx } from 'clsx';
|
|
9
10
|
import { twMerge } from 'tailwind-merge';
|
|
10
|
-
import { ChevronDown, ChevronUp, Check, List, Braces, ListChecks, ToggleLeft, Hash, Image, FileText, CalendarDays, Type, Loader2, ImageOff, Upload, Link2, EyeOff, Eye, X, Minus, Plus, Trash2, Copy, Download, ChevronRight } from 'lucide-react';
|
|
11
|
+
import { ChevronDown, ChevronUp, Check, List, Braces, ListChecks, ToggleLeft, Hash, Image, FileText, CalendarDays, Type, Loader2, ImageOff, Upload, Link2, EyeOff, Eye, X, Minus, Plus, Trash2, Copy, Download, ChevronRight, TriangleAlert } from 'lucide-react';
|
|
11
12
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
12
13
|
import * as React2 from 'react';
|
|
13
14
|
import { createContext, use, useId, useMemo, useContext, useState, useRef, useCallback, useEffect, Fragment as Fragment$1, useLayoutEffect } from 'react';
|
|
@@ -221,6 +222,9 @@ var DEFAULT_FIELD_STRINGS = {
|
|
|
221
222
|
copyText: "Copy the text",
|
|
222
223
|
download: "Download",
|
|
223
224
|
downloading: "Downloading\u2026",
|
|
225
|
+
downloadIncomplete: (names) => `${names.length === 1 ? "One file" : `${names.length} files`} could not be saved: ${names.join(", ")}`,
|
|
226
|
+
downloadFile: (name) => `Download ${name}`,
|
|
227
|
+
downloadFileFailed: "The file could not be saved",
|
|
224
228
|
viewRendered: "Result",
|
|
225
229
|
viewJson: "JSON",
|
|
226
230
|
copyJson: "Copy the JSON",
|
|
@@ -1504,20 +1508,84 @@ function FieldRenderer({ field, value, onChange, id, error, env }) {
|
|
|
1504
1508
|
);
|
|
1505
1509
|
}
|
|
1506
1510
|
}
|
|
1511
|
+
|
|
1512
|
+
// src/react/absolute-url.ts
|
|
1513
|
+
function absoluteUrl(url) {
|
|
1514
|
+
const gated = viewableUrl(url);
|
|
1515
|
+
if (!gated?.startsWith("/") || typeof document === "undefined") return url;
|
|
1516
|
+
try {
|
|
1517
|
+
return new URL(gated, document.baseURI).href;
|
|
1518
|
+
} catch {
|
|
1519
|
+
return url;
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
// src/react/save-in-browser.ts
|
|
1524
|
+
function saveBlob(blob, filename) {
|
|
1525
|
+
const href = URL.createObjectURL(blob);
|
|
1526
|
+
const anchor = document.createElement("a");
|
|
1527
|
+
anchor.href = href;
|
|
1528
|
+
anchor.download = filename;
|
|
1529
|
+
document.body.appendChild(anchor);
|
|
1530
|
+
anchor.click();
|
|
1531
|
+
anchor.remove();
|
|
1532
|
+
setTimeout(() => URL.revokeObjectURL(href), 0);
|
|
1533
|
+
}
|
|
1534
|
+
function blobType(mimeType) {
|
|
1535
|
+
return /^(text\/|application\/json)/.test(mimeType) && !/charset=/i.test(mimeType) ? `${mimeType};charset=utf-8` : mimeType;
|
|
1536
|
+
}
|
|
1537
|
+
async function saveInBrowser(files) {
|
|
1538
|
+
const failed = [];
|
|
1539
|
+
for (const file of files) {
|
|
1540
|
+
try {
|
|
1541
|
+
if (file.text !== void 0) {
|
|
1542
|
+
saveBlob(new Blob([file.text], { type: blobType(file.mimeType) }), file.name);
|
|
1543
|
+
continue;
|
|
1544
|
+
}
|
|
1545
|
+
const response = await fetch(file.url);
|
|
1546
|
+
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
1547
|
+
saveBlob(await response.blob(), file.name);
|
|
1548
|
+
} catch (error) {
|
|
1549
|
+
failed.push({ file, reason: error instanceof Error ? error.message : String(error) });
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
return { failed };
|
|
1553
|
+
}
|
|
1507
1554
|
var ResultEnvContext = createContext({});
|
|
1508
1555
|
function ResultEnvProvider({
|
|
1509
1556
|
resolveUrl,
|
|
1510
1557
|
resolveShareUrl,
|
|
1511
1558
|
proseImages,
|
|
1512
1559
|
tableColumns,
|
|
1560
|
+
saveFiles,
|
|
1561
|
+
downloads,
|
|
1513
1562
|
children
|
|
1514
1563
|
}) {
|
|
1515
1564
|
const env = useMemo(
|
|
1516
|
-
() => ({ resolveUrl, resolveShareUrl, proseImages, tableColumns }),
|
|
1517
|
-
[resolveUrl, resolveShareUrl, proseImages, tableColumns]
|
|
1565
|
+
() => ({ resolveUrl, resolveShareUrl, proseImages, tableColumns, saveFiles, downloads }),
|
|
1566
|
+
[resolveUrl, resolveShareUrl, proseImages, tableColumns, saveFiles, downloads]
|
|
1518
1567
|
);
|
|
1519
1568
|
return /* @__PURE__ */ jsx(ResultEnvContext, { value: env, children });
|
|
1520
1569
|
}
|
|
1570
|
+
function DownloadDisplayOverride({
|
|
1571
|
+
downloads,
|
|
1572
|
+
children
|
|
1573
|
+
}) {
|
|
1574
|
+
const env = use(ResultEnvContext);
|
|
1575
|
+
const result = downloads?.result;
|
|
1576
|
+
const files = downloads?.files;
|
|
1577
|
+
const merged = useMemo(
|
|
1578
|
+
() => result === void 0 && files === void 0 ? env : {
|
|
1579
|
+
...env,
|
|
1580
|
+
downloads: {
|
|
1581
|
+
result: result ?? env.downloads?.result,
|
|
1582
|
+
files: files ?? env.downloads?.files
|
|
1583
|
+
}
|
|
1584
|
+
},
|
|
1585
|
+
[env, result, files]
|
|
1586
|
+
);
|
|
1587
|
+
return /* @__PURE__ */ jsx(ResultEnvContext, { value: merged, children });
|
|
1588
|
+
}
|
|
1521
1589
|
function useResolvedUrl(url) {
|
|
1522
1590
|
return use(ResultEnvContext).resolveUrl?.(url) ?? url;
|
|
1523
1591
|
}
|
|
@@ -1527,6 +1595,32 @@ function useResolveUrl() {
|
|
|
1527
1595
|
function useResolveShareUrl() {
|
|
1528
1596
|
return use(ResultEnvContext).resolveShareUrl;
|
|
1529
1597
|
}
|
|
1598
|
+
function useSaveFiles() {
|
|
1599
|
+
const save = use(ResultEnvContext).saveFiles ?? saveInBrowser;
|
|
1600
|
+
return useCallback((files) => deliver(save, files), [save]);
|
|
1601
|
+
}
|
|
1602
|
+
async function deliver(save, files) {
|
|
1603
|
+
const handed = files.map(
|
|
1604
|
+
(file) => file.url === void 0 ? file : { ...file, url: absoluteUrl(file.url) }
|
|
1605
|
+
);
|
|
1606
|
+
try {
|
|
1607
|
+
const result = await save(handed);
|
|
1608
|
+
if (Array.isArray(result?.failed)) return { failed: result.failed };
|
|
1609
|
+
return {
|
|
1610
|
+
failed: handed.map((file) => ({ file, reason: "The save function reported no result" }))
|
|
1611
|
+
};
|
|
1612
|
+
} catch (error) {
|
|
1613
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
1614
|
+
return { failed: handed.map((file) => ({ file, reason })) };
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
function useResultDownloadShown() {
|
|
1618
|
+
return use(ResultEnvContext).downloads?.result ?? true;
|
|
1619
|
+
}
|
|
1620
|
+
function useFileDownloadShown(kind) {
|
|
1621
|
+
const files = use(ResultEnvContext).downloads?.files ?? true;
|
|
1622
|
+
return typeof files === "boolean" ? files : files.includes(kind);
|
|
1623
|
+
}
|
|
1530
1624
|
function useProseImages() {
|
|
1531
1625
|
return use(ResultEnvContext).proseImages ?? "link";
|
|
1532
1626
|
}
|
|
@@ -1536,6 +1630,27 @@ function useTableColumns() {
|
|
|
1536
1630
|
if (budget === void 0 || Number.isNaN(budget)) return DEFAULT_TABLE_COLUMNS;
|
|
1537
1631
|
return Math.max(1, Math.floor(budget));
|
|
1538
1632
|
}
|
|
1633
|
+
var ResultLocationContext = createContext(void 0);
|
|
1634
|
+
function useResultLocation() {
|
|
1635
|
+
return use(ResultLocationContext);
|
|
1636
|
+
}
|
|
1637
|
+
function ResultRoot({
|
|
1638
|
+
baseName,
|
|
1639
|
+
path,
|
|
1640
|
+
children
|
|
1641
|
+
}) {
|
|
1642
|
+
const key = path.join("\0");
|
|
1643
|
+
const location = useMemo(() => ({ baseName, path: key.split("\0") }), [baseName, key]);
|
|
1644
|
+
return /* @__PURE__ */ jsx(ResultLocationContext, { value: location, children });
|
|
1645
|
+
}
|
|
1646
|
+
function ResultAt({ segment, children }) {
|
|
1647
|
+
const parent = use(ResultLocationContext);
|
|
1648
|
+
const location = useMemo(
|
|
1649
|
+
() => parent ? { baseName: parent.baseName, path: [...parent.path, segment] } : void 0,
|
|
1650
|
+
[parent, segment]
|
|
1651
|
+
);
|
|
1652
|
+
return /* @__PURE__ */ jsx(ResultLocationContext, { value: location, children });
|
|
1653
|
+
}
|
|
1539
1654
|
var TooltipProvider = TooltipPrimitive.Provider;
|
|
1540
1655
|
var TooltipRoot = TooltipPrimitive.Root;
|
|
1541
1656
|
var TooltipTrigger = TooltipPrimitive.Trigger;
|
|
@@ -2058,15 +2173,12 @@ function CopyUrlButton({ url, storageUrl }) {
|
|
|
2058
2173
|
};
|
|
2059
2174
|
return /* @__PURE__ */ jsx(CopyButton, { provide, label: s.copyUrl, title: url });
|
|
2060
2175
|
}
|
|
2061
|
-
function absoluteUrl(url) {
|
|
2062
|
-
if (!/^\/(?!\/)/.test(url) || typeof window === "undefined") return url;
|
|
2063
|
-
return `${window.location.origin}${url}`;
|
|
2064
|
-
}
|
|
2065
2176
|
function FileRef({
|
|
2066
2177
|
url,
|
|
2067
2178
|
storageUrl,
|
|
2068
2179
|
mimeType,
|
|
2069
|
-
filename
|
|
2180
|
+
filename,
|
|
2181
|
+
file
|
|
2070
2182
|
}) {
|
|
2071
2183
|
const s = useFieldStrings();
|
|
2072
2184
|
const encoded = encodedFileSummary(url, s);
|
|
@@ -2093,7 +2205,80 @@ function FileRef({
|
|
|
2093
2205
|
children: label
|
|
2094
2206
|
}
|
|
2095
2207
|
),
|
|
2096
|
-
/* @__PURE__ */ jsx(
|
|
2208
|
+
/* @__PURE__ */ jsx(FileActions, { copy: { url, ...storageUrl ? { storageUrl } : {} }, file })
|
|
2209
|
+
] });
|
|
2210
|
+
}
|
|
2211
|
+
function FileActions({
|
|
2212
|
+
copy,
|
|
2213
|
+
file
|
|
2214
|
+
}) {
|
|
2215
|
+
return /* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-0.5", children: [
|
|
2216
|
+
copy && /* @__PURE__ */ jsx(
|
|
2217
|
+
CopyUrlButton,
|
|
2218
|
+
{
|
|
2219
|
+
url: copy.url,
|
|
2220
|
+
...copy.storageUrl ? { storageUrl: copy.storageUrl } : {}
|
|
2221
|
+
}
|
|
2222
|
+
),
|
|
2223
|
+
file && /* @__PURE__ */ jsx(FileDownloadButton, { file })
|
|
2224
|
+
] });
|
|
2225
|
+
}
|
|
2226
|
+
function useStuffFile(kind, value) {
|
|
2227
|
+
const location = useResultLocation();
|
|
2228
|
+
return location ? readStuffFile(kind, value, location.path.join(".")) : void 0;
|
|
2229
|
+
}
|
|
2230
|
+
function FileDownloadButton({ file }) {
|
|
2231
|
+
const s = useFieldStrings();
|
|
2232
|
+
const location = useResultLocation();
|
|
2233
|
+
const resolve = useResolveUrl();
|
|
2234
|
+
const save = useSaveFiles();
|
|
2235
|
+
const shown = useFileDownloadShown(file.kind);
|
|
2236
|
+
const statusId = useId();
|
|
2237
|
+
const [attempt, setAttempt] = useState(null);
|
|
2238
|
+
useEffect(() => {
|
|
2239
|
+
if (attempt?.state !== "saved") return;
|
|
2240
|
+
const timer = window.setTimeout(
|
|
2241
|
+
() => setAttempt((current) => current === attempt ? null : current),
|
|
2242
|
+
1500
|
|
2243
|
+
);
|
|
2244
|
+
return () => window.clearTimeout(timer);
|
|
2245
|
+
}, [attempt]);
|
|
2246
|
+
if (!shown || !location) return null;
|
|
2247
|
+
const planned = planFileSave(file, {
|
|
2248
|
+
baseName: location.baseName,
|
|
2249
|
+
...resolve ? { resolveUrl: resolve } : {}
|
|
2250
|
+
});
|
|
2251
|
+
if (!planned) return null;
|
|
2252
|
+
const identity = `${planned.name}
|
|
2253
|
+
${planned.url ?? planned.text}`;
|
|
2254
|
+
const state = attempt?.identity === identity ? attempt.state : "idle";
|
|
2255
|
+
const failed = state === "failed";
|
|
2256
|
+
const label = s.downloadFile(planned.name);
|
|
2257
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2258
|
+
/* @__PURE__ */ jsx(
|
|
2259
|
+
"button",
|
|
2260
|
+
{
|
|
2261
|
+
type: "button",
|
|
2262
|
+
onClick: () => {
|
|
2263
|
+
const started = { identity, state: "saving" };
|
|
2264
|
+
setAttempt(started);
|
|
2265
|
+
void save([planned]).then((result) => {
|
|
2266
|
+
const settled = result.failed.length > 0 ? "failed" : "saved";
|
|
2267
|
+
setAttempt((current) => current === started ? { identity, state: settled } : current);
|
|
2268
|
+
});
|
|
2269
|
+
},
|
|
2270
|
+
disabled: state === "saving",
|
|
2271
|
+
"aria-label": label,
|
|
2272
|
+
title: failed ? s.downloadFileFailed : label,
|
|
2273
|
+
...failed ? { "aria-describedby": statusId } : {},
|
|
2274
|
+
className: cn(
|
|
2275
|
+
"shrink-0 rounded p-0.5 hover:bg-card focus-visible:outline-solid focus-visible:outline-2 focus-visible:outline-offset-1 disabled:opacity-60",
|
|
2276
|
+
failed ? "text-destructive" : "text-muted-foreground hover:text-foreground"
|
|
2277
|
+
),
|
|
2278
|
+
children: state === "saving" ? /* @__PURE__ */ jsx(Loader2, { "aria-hidden": true, className: "size-3.5 animate-spin" }) : state === "saved" ? /* @__PURE__ */ jsx(Check, { "aria-hidden": true, className: "size-3.5" }) : failed ? /* @__PURE__ */ jsx(TriangleAlert, { "aria-hidden": true, className: "size-3.5" }) : /* @__PURE__ */ jsx(Download, { "aria-hidden": true, className: "size-3.5" })
|
|
2279
|
+
}
|
|
2280
|
+
),
|
|
2281
|
+
/* @__PURE__ */ jsx("span", { id: statusId, role: "status", className: "sr-only", children: failed ? s.downloadFileFailed : "" })
|
|
2097
2282
|
] });
|
|
2098
2283
|
}
|
|
2099
2284
|
function paintable(content, resolve) {
|
|
@@ -2135,6 +2320,7 @@ function DocumentValue({ value }) {
|
|
|
2135
2320
|
const s = useFieldStrings();
|
|
2136
2321
|
const resolve = useResolveUrl();
|
|
2137
2322
|
const [open, setOpen] = useState(false);
|
|
2323
|
+
const file = useStuffFile("document", value);
|
|
2138
2324
|
const content = readDocumentContent(value);
|
|
2139
2325
|
if (!content) return /* @__PURE__ */ jsx(Absent, {});
|
|
2140
2326
|
const name = content.title ?? content.filename ?? fileLabel(content.url, content.filename, s);
|
|
@@ -2150,7 +2336,8 @@ function DocumentValue({ value }) {
|
|
|
2150
2336
|
url: paintableUrl(content, resolve) ?? content.url,
|
|
2151
2337
|
storageUrl: content.url,
|
|
2152
2338
|
mimeType: content.mimeType,
|
|
2153
|
-
...content.filename ? { filename: content.filename } : {}
|
|
2339
|
+
...content.filename ? { filename: content.filename } : {},
|
|
2340
|
+
file
|
|
2154
2341
|
}
|
|
2155
2342
|
),
|
|
2156
2343
|
content.snippet && /* @__PURE__ */ jsx("p", { className: "line-clamp-2 text-[12px] leading-relaxed text-muted-foreground", children: content.snippet })
|
|
@@ -2180,6 +2367,7 @@ function ImageValue({
|
|
|
2180
2367
|
}) {
|
|
2181
2368
|
const s = useFieldStrings();
|
|
2182
2369
|
const resolve = useResolveUrl();
|
|
2370
|
+
const file = useStuffFile("image", value);
|
|
2183
2371
|
const content = readImageContent(value);
|
|
2184
2372
|
if (!content) return /* @__PURE__ */ jsx(Absent, {});
|
|
2185
2373
|
const src = paintableUrl(content, resolve);
|
|
@@ -2230,7 +2418,8 @@ function ImageValue({
|
|
|
2230
2418
|
{
|
|
2231
2419
|
url: content.url,
|
|
2232
2420
|
mimeType: content.mimeType,
|
|
2233
|
-
...content.filename ? { filename: content.filename } : {}
|
|
2421
|
+
...content.filename ? { filename: content.filename } : {},
|
|
2422
|
+
file
|
|
2234
2423
|
}
|
|
2235
2424
|
) })
|
|
2236
2425
|
] })
|
|
@@ -2255,7 +2444,8 @@ function ImageValue({
|
|
|
2255
2444
|
{
|
|
2256
2445
|
url: content.url,
|
|
2257
2446
|
mimeType: content.mimeType,
|
|
2258
|
-
...content.filename ? { filename: content.filename } : {}
|
|
2447
|
+
...content.filename ? { filename: content.filename } : {},
|
|
2448
|
+
file
|
|
2259
2449
|
}
|
|
2260
2450
|
),
|
|
2261
2451
|
src && !compact && /* @__PURE__ */ jsx("div", { className: inGallery ? "px-2.5" : void 0, children: /* @__PURE__ */ jsx(
|
|
@@ -2264,7 +2454,8 @@ function ImageValue({
|
|
|
2264
2454
|
url: src,
|
|
2265
2455
|
storageUrl: content.url,
|
|
2266
2456
|
mimeType: content.mimeType,
|
|
2267
|
-
...content.filename ? { filename: content.filename } : {}
|
|
2457
|
+
...content.filename ? { filename: content.filename } : {},
|
|
2458
|
+
file
|
|
2268
2459
|
}
|
|
2269
2460
|
) }),
|
|
2270
2461
|
content.caption && /* @__PURE__ */ jsx(
|
|
@@ -2467,7 +2658,7 @@ function ObjectTable({
|
|
|
2467
2658
|
] }) }),
|
|
2468
2659
|
/* @__PURE__ */ jsx("tbody", { children: items.map((item, index) => {
|
|
2469
2660
|
const isOpen = canExpand && expanded.has(index);
|
|
2470
|
-
return /* @__PURE__ */ jsx(
|
|
2661
|
+
return /* @__PURE__ */ jsx(ResultAt, { segment: String(index), children: /* @__PURE__ */ jsxs("tr", { className: "border-b border-border/60 last:border-b-0", children: [
|
|
2471
2662
|
canExpand && /* @__PURE__ */ jsx("td", { className: "px-1 pt-px align-top", children: /* @__PURE__ */ jsx(
|
|
2472
2663
|
"button",
|
|
2473
2664
|
{
|
|
@@ -2504,7 +2695,7 @@ function ObjectTable({
|
|
|
2504
2695
|
column === name ? "max-w-none min-w-[16ch] wrap-anywhere [&>span]:whitespace-normal" : column.kind === "list" && isInlineColumn(column) ? "min-w-[16ch]" : "truncate"
|
|
2505
2696
|
),
|
|
2506
2697
|
...typeof cell === "string" || typeof cell === "number" ? { title: cellTitle(column, cell, presentation) } : {},
|
|
2507
|
-
children: /* @__PURE__ */ jsx(LeafValue, { field: column, value: cell, compact: true })
|
|
2698
|
+
children: /* @__PURE__ */ jsx(ResultAt, { segment: column.name, children: /* @__PURE__ */ jsx(LeafValue, { field: column, value: cell, compact: true }) })
|
|
2508
2699
|
}
|
|
2509
2700
|
) }, column.name);
|
|
2510
2701
|
})
|
|
@@ -2565,10 +2756,10 @@ function ImageGallery({ items }) {
|
|
|
2565
2756
|
return content ? !!(viewableUrl(content.publicUrl) ?? viewableUrl(content.url)) : false;
|
|
2566
2757
|
});
|
|
2567
2758
|
if (!anyViewable) return /* @__PURE__ */ jsx(FileRows, { items, kind: "image" });
|
|
2568
|
-
return /* @__PURE__ */ jsx("div", { className: "grid grid-cols-[repeat(auto-fill,minmax(140px,1fr))] gap-2", children: items.map((item, index) => /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-lg border border-border bg-card/40", children: /* @__PURE__ */ jsx(ImageValue, { value: item, inGallery: true }) }, index)) });
|
|
2759
|
+
return /* @__PURE__ */ jsx("div", { className: "grid grid-cols-[repeat(auto-fill,minmax(140px,1fr))] gap-2", children: items.map((item, index) => /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-lg border border-border bg-card/40", children: /* @__PURE__ */ jsx(ResultAt, { segment: String(index), children: /* @__PURE__ */ jsx(ImageValue, { value: item, inGallery: true }) }) }, index)) });
|
|
2569
2760
|
}
|
|
2570
2761
|
function FileRows({ items, kind }) {
|
|
2571
|
-
return /* @__PURE__ */ jsx("div", { className: "divide-y divide-border overflow-hidden rounded-lg border border-border", children: items.map((item, index) => /* @__PURE__ */ jsx("div", { className: "bg-card/40 px-3.5 py-2", children: kind === "document" ? /* @__PURE__ */ jsx(DocumentValue, { value: item }) : /* @__PURE__ */ jsx(ImageValue, { value: item, inRow: true }) }, index)) });
|
|
2762
|
+
return /* @__PURE__ */ jsx("div", { className: "divide-y divide-border overflow-hidden rounded-lg border border-border", children: items.map((item, index) => /* @__PURE__ */ jsx("div", { className: "bg-card/40 px-3.5 py-2", children: /* @__PURE__ */ jsx(ResultAt, { segment: String(index), children: kind === "document" ? /* @__PURE__ */ jsx(DocumentValue, { value: item }) : /* @__PURE__ */ jsx(ImageValue, { value: item, inRow: true }) }) }, index)) });
|
|
2572
2763
|
}
|
|
2573
2764
|
function recordColumns(item) {
|
|
2574
2765
|
if (item.kind !== "object" || item.fields.length === 0) return void 0;
|
|
@@ -2595,9 +2786,16 @@ function chooseColumns(fields, budget) {
|
|
|
2595
2786
|
...name ? { name } : {}
|
|
2596
2787
|
};
|
|
2597
2788
|
}
|
|
2598
|
-
function ResultField(
|
|
2789
|
+
function ResultField(props) {
|
|
2790
|
+
const location = useResultLocation();
|
|
2791
|
+
if (location) return /* @__PURE__ */ jsx(ResultNode, { ...props });
|
|
2792
|
+
return /* @__PURE__ */ jsx(ResultRoot, { baseName: props.field.name, path: [props.field.name], children: /* @__PURE__ */ jsx(ResultNode, { ...props }) });
|
|
2793
|
+
}
|
|
2794
|
+
function ResultNode({ field, value, depth = 0, hideLabel = false }) {
|
|
2599
2795
|
const s = useFieldStrings();
|
|
2600
2796
|
const unwrapped = unwrap(field, value);
|
|
2797
|
+
const pageDownloadShown = useFileDownloadShown("markup");
|
|
2798
|
+
const location = useResultLocation();
|
|
2601
2799
|
const header = hideLabel ? null : /* @__PURE__ */ jsx(Label2, { field, describe: true });
|
|
2602
2800
|
const copyText = (field.kind === "text" || field.kind === "prose") && typeof unwrapped === "string" && unwrapped !== "" ? unwrapped : void 0;
|
|
2603
2801
|
if (isNativeDateNode(field)) {
|
|
@@ -2608,8 +2806,12 @@ function ResultField({ field, value, depth = 0, hideLabel = false }) {
|
|
|
2608
2806
|
}
|
|
2609
2807
|
if (isNativeHtmlNode(field)) {
|
|
2610
2808
|
const content = readHtmlContent(unwrapped);
|
|
2809
|
+
const page = pageDownloadShown && location ? readStuffFile("markup", unwrapped, location.path.join(".")) : void 0;
|
|
2611
2810
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
2612
|
-
|
|
2811
|
+
page ? /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
|
|
2812
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: header }),
|
|
2813
|
+
/* @__PURE__ */ jsx(FileActions, { file: page })
|
|
2814
|
+
] }) : header,
|
|
2613
2815
|
content ? /* @__PURE__ */ jsx(HtmlPreview, { content }) : /* @__PURE__ */ jsx(Absent, {})
|
|
2614
2816
|
] });
|
|
2615
2817
|
}
|
|
@@ -2657,7 +2859,7 @@ function ResultField({ field, value, depth = 0, hideLabel = false }) {
|
|
|
2657
2859
|
isInlineColumn(child) ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
2658
2860
|
/* @__PURE__ */ jsx("div", { className: "min-w-0", children: /* @__PURE__ */ jsx(Label2, { field: child, describe: true }) }),
|
|
2659
2861
|
/* @__PURE__ */ jsx("div", { className: "flex min-w-0 justify-end **:data-chips:justify-end", children: /* @__PURE__ */ jsx("div", { className: "min-w-0 text-left wrap-break-word", children: /* @__PURE__ */ jsx(LeafValue, { field: child, value: memberValue(child) }) }) })
|
|
2660
|
-
] }, child.name) : /* @__PURE__ */ jsx("div", { className: "col-span-2 min-w-0", children: /* @__PURE__ */ jsx(ResultField, { field: child, value: memberValue(child), depth: depth + 1 }) }, child.name)
|
|
2862
|
+
] }, child.name) : /* @__PURE__ */ jsx("div", { className: "col-span-2 min-w-0", children: /* @__PURE__ */ jsx(ResultAt, { segment: child.name, children: /* @__PURE__ */ jsx(ResultField, { field: child, value: memberValue(child), depth: depth + 1 }) }) }, child.name)
|
|
2661
2863
|
)
|
|
2662
2864
|
)
|
|
2663
2865
|
}
|
|
@@ -2679,7 +2881,7 @@ function ResultField({ field, value, depth = 0, hideLabel = false }) {
|
|
|
2679
2881
|
// date's `date` and `time`, print a page's markup source down a
|
|
2680
2882
|
// column named by it, and show a composite as JSON. The arm keyed by
|
|
2681
2883
|
// concept is the one that knows what each entry is.
|
|
2682
|
-
/* @__PURE__ */ jsx("div", { className: "divide-y divide-border/60 overflow-hidden rounded-lg border border-border", children: items.map((item, index) => /* @__PURE__ */ jsx("div", { className: "bg-card/40 px-3 py-1.5", children: /* @__PURE__ */ jsx(ResultField, { field: field.item, value: item, depth: depth + 1, hideLabel: true }) }, index)) })
|
|
2884
|
+
/* @__PURE__ */ jsx("div", { className: "divide-y divide-border/60 overflow-hidden rounded-lg border border-border", children: items.map((item, index) => /* @__PURE__ */ jsx("div", { className: "bg-card/40 px-3 py-1.5", children: /* @__PURE__ */ jsx(ResultAt, { segment: String(index), children: /* @__PURE__ */ jsx(ResultField, { field: field.item, value: item, depth: depth + 1, hideLabel: true }) }) }, index)) })
|
|
2683
2885
|
) : columns ? (
|
|
2684
2886
|
// Same shape every row: the labels are column headers, not per-row
|
|
2685
2887
|
// labels. See `ObjectTable`.
|
|
@@ -2714,7 +2916,7 @@ function ResultField({ field, value, depth = 0, hideLabel = false }) {
|
|
|
2714
2916
|
className: "space-y-2 rounded-lg border border-border bg-card/40 px-3.5 py-3",
|
|
2715
2917
|
children: [
|
|
2716
2918
|
/* @__PURE__ */ jsx("span", { className: "font-mono text-[10px] text-muted-foreground", children: index + 1 }),
|
|
2717
|
-
/* @__PURE__ */ jsx(ResultField, { field: field.item, value: item, depth: depth + 1, hideLabel: true })
|
|
2919
|
+
/* @__PURE__ */ jsx(ResultAt, { segment: String(index), children: /* @__PURE__ */ jsx(ResultField, { field: field.item, value: item, depth: depth + 1, hideLabel: true }) })
|
|
2718
2920
|
]
|
|
2719
2921
|
},
|
|
2720
2922
|
index
|
|
@@ -2741,67 +2943,6 @@ function ResultField({ field, value, depth = 0, hideLabel = false }) {
|
|
|
2741
2943
|
}
|
|
2742
2944
|
return null;
|
|
2743
2945
|
}
|
|
2744
|
-
|
|
2745
|
-
// src/react/download-stuff.ts
|
|
2746
|
-
function saveBlob(blob, filename) {
|
|
2747
|
-
const href = URL.createObjectURL(blob);
|
|
2748
|
-
const anchor = document.createElement("a");
|
|
2749
|
-
anchor.href = href;
|
|
2750
|
-
anchor.download = filename;
|
|
2751
|
-
document.body.appendChild(anchor);
|
|
2752
|
-
anchor.click();
|
|
2753
|
-
anchor.remove();
|
|
2754
|
-
setTimeout(() => URL.revokeObjectURL(href), 0);
|
|
2755
|
-
}
|
|
2756
|
-
function mimeForExtension(extension) {
|
|
2757
|
-
return extension === "html" ? "text/html;charset=utf-8" : "text/plain;charset=utf-8";
|
|
2758
|
-
}
|
|
2759
|
-
function extensionOf(url, filename) {
|
|
2760
|
-
const named = filename?.match(/\.([A-Za-z0-9]{1,8})$/)?.[1];
|
|
2761
|
-
if (named) return named.toLowerCase();
|
|
2762
|
-
const path = url.split(/[?#]/)[0] ?? url;
|
|
2763
|
-
const match = path.match(/\.([A-Za-z0-9]{1,8})$/)?.[1];
|
|
2764
|
-
return match ? match.toLowerCase() : "";
|
|
2765
|
-
}
|
|
2766
|
-
function fileNameFor(file, base) {
|
|
2767
|
-
if (file.filename) return file.filename;
|
|
2768
|
-
const extension = file.extension ?? extensionOf(file.url ?? "", file.filename);
|
|
2769
|
-
const stem = `${base}-${file.path.replace(/\./g, "-")}`;
|
|
2770
|
-
return extension ? `${stem}.${extension}` : stem;
|
|
2771
|
-
}
|
|
2772
|
-
async function downloadStuff({
|
|
2773
|
-
field,
|
|
2774
|
-
value,
|
|
2775
|
-
baseName,
|
|
2776
|
-
resolveUrl
|
|
2777
|
-
}) {
|
|
2778
|
-
const files = collectStuffFiles(field, value);
|
|
2779
|
-
const isBareFile = files.length === 1 && files[0]?.path === field.name;
|
|
2780
|
-
let deliveredAFile = false;
|
|
2781
|
-
for (const file of files) {
|
|
2782
|
-
const name = fileNameFor(file, baseName);
|
|
2783
|
-
if (file.text !== void 0) {
|
|
2784
|
-
saveBlob(new Blob([file.text], { type: mimeForExtension(file.extension) }), name);
|
|
2785
|
-
deliveredAFile = true;
|
|
2786
|
-
continue;
|
|
2787
|
-
}
|
|
2788
|
-
const href = viewableUrl(resolveUrl?.(file.url ?? "")) ?? viewableUrl(file.publicUrl) ?? viewableUrl(file.url);
|
|
2789
|
-
if (!href) continue;
|
|
2790
|
-
try {
|
|
2791
|
-
const response = await fetch(href);
|
|
2792
|
-
if (!response.ok) throw new Error(String(response.status));
|
|
2793
|
-
saveBlob(await response.blob(), name);
|
|
2794
|
-
} catch {
|
|
2795
|
-
window.open(href, "_blank", "noopener");
|
|
2796
|
-
}
|
|
2797
|
-
deliveredAFile = true;
|
|
2798
|
-
}
|
|
2799
|
-
if (isBareFile && deliveredAFile) return;
|
|
2800
|
-
saveBlob(
|
|
2801
|
-
new Blob([JSON.stringify(value, null, 2)], { type: "application/json;charset=utf-8" }),
|
|
2802
|
-
`${baseName}.json`
|
|
2803
|
-
);
|
|
2804
|
-
}
|
|
2805
2946
|
var JSON_TOKEN_RE = /("(?:\\.|[^"\\])*"\s*:)|("(?:\\.|[^"\\])*")|(\b(?:true|false|null)\b|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)/g;
|
|
2806
2947
|
function highlight(json) {
|
|
2807
2948
|
const out = [];
|
|
@@ -2861,33 +3002,73 @@ function JsonView({ value }) {
|
|
|
2861
3002
|
/* @__PURE__ */ jsx("pre", { className: "overflow-x-auto rounded-lg border border-border bg-card/40 px-3.5 py-3 pr-12 font-mono text-[12px] leading-relaxed", children: highlight(text) })
|
|
2862
3003
|
] });
|
|
2863
3004
|
}
|
|
2864
|
-
function
|
|
3005
|
+
function isShownResult(attempt, field, baseName, value) {
|
|
3006
|
+
if (attempt.field === field && attempt.baseName === baseName && attempt.value === value) {
|
|
3007
|
+
return true;
|
|
3008
|
+
}
|
|
3009
|
+
return attempt.key !== void 0 && attempt.key === resultKey(field, baseName, value);
|
|
3010
|
+
}
|
|
3011
|
+
function resultKey(field, baseName, value) {
|
|
3012
|
+
try {
|
|
3013
|
+
return JSON.stringify(
|
|
3014
|
+
[baseName, field, value],
|
|
3015
|
+
(_key, member) => typeof member === "bigint" ? `${member}n` : member
|
|
3016
|
+
);
|
|
3017
|
+
} catch {
|
|
3018
|
+
return void 0;
|
|
3019
|
+
}
|
|
3020
|
+
}
|
|
3021
|
+
function StuffViewer({ downloads, ...props }) {
|
|
3022
|
+
return /* @__PURE__ */ jsx(DownloadDisplayOverride, { downloads, children: /* @__PURE__ */ jsx(StuffPanel, { ...props }) });
|
|
3023
|
+
}
|
|
3024
|
+
function StuffPanel({
|
|
2865
3025
|
field,
|
|
2866
3026
|
value,
|
|
2867
3027
|
name,
|
|
2868
3028
|
defaultView = "rendered",
|
|
2869
3029
|
downloadBaseName,
|
|
2870
|
-
hideDownload = false,
|
|
2871
3030
|
className
|
|
2872
3031
|
}) {
|
|
2873
3032
|
const s = useFieldStrings();
|
|
2874
3033
|
const named = name ? { ...field, name } : field;
|
|
3034
|
+
const baseName = downloadBaseName ?? named.name ?? "result";
|
|
2875
3035
|
const [view, setView] = useState(defaultView);
|
|
2876
|
-
const [saving, setSaving] = useState(
|
|
3036
|
+
const [saving, setSaving] = useState(null);
|
|
3037
|
+
const [missed, setMissed] = useState(null);
|
|
3038
|
+
const latest = useRef(null);
|
|
3039
|
+
const savingShown = saving !== null && isShownResult(saving, field, baseName, value);
|
|
3040
|
+
const missedShown = missed && isShownResult(missed.attempt, field, baseName, value) ? missed.names : [];
|
|
2877
3041
|
const resolveUrl = useResolveUrl();
|
|
3042
|
+
const save = useSaveFiles();
|
|
3043
|
+
const downloadShown = useResultDownloadShown();
|
|
2878
3044
|
const handleDownload = useCallback(async () => {
|
|
2879
|
-
|
|
3045
|
+
const attempt = {
|
|
3046
|
+
field,
|
|
3047
|
+
baseName,
|
|
3048
|
+
value,
|
|
3049
|
+
key: resultKey(field, baseName, value)
|
|
3050
|
+
};
|
|
3051
|
+
latest.current = attempt;
|
|
3052
|
+
setSaving(attempt);
|
|
3053
|
+
setMissed(null);
|
|
2880
3054
|
try {
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
3055
|
+
const plan = planStuffSave(field, value, {
|
|
3056
|
+
baseName,
|
|
3057
|
+
...resolveUrl ? { resolveUrl } : {}
|
|
3058
|
+
});
|
|
3059
|
+
const { failed } = await save(plan.files);
|
|
3060
|
+
if (latest.current !== attempt) return;
|
|
3061
|
+
setMissed({
|
|
3062
|
+
attempt,
|
|
3063
|
+
names: [
|
|
3064
|
+
...plan.unavailable.map((file) => file.name),
|
|
3065
|
+
...failed.map((failure) => failure.file.name)
|
|
3066
|
+
]
|
|
2886
3067
|
});
|
|
2887
3068
|
} finally {
|
|
2888
|
-
setSaving(
|
|
3069
|
+
setSaving((current) => current === attempt ? null : current);
|
|
2889
3070
|
}
|
|
2890
|
-
}, [field,
|
|
3071
|
+
}, [field, value, baseName, resolveUrl, save]);
|
|
2891
3072
|
const views = [
|
|
2892
3073
|
{ id: "rendered", label: s.viewRendered },
|
|
2893
3074
|
{ id: "json", label: s.viewJson }
|
|
@@ -2896,17 +3077,17 @@ function StuffViewer({
|
|
|
2896
3077
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-start justify-between gap-x-4 gap-y-1", children: [
|
|
2897
3078
|
/* @__PURE__ */ jsx("div", { className: "min-w-0 space-y-1", children: /* @__PURE__ */ jsx(ResultHeader, { field: named }) }),
|
|
2898
3079
|
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
2899
|
-
|
|
3080
|
+
downloadShown && /* @__PURE__ */ jsxs(
|
|
2900
3081
|
"button",
|
|
2901
3082
|
{
|
|
2902
3083
|
type: "button",
|
|
2903
3084
|
onClick: () => void handleDownload(),
|
|
2904
|
-
disabled:
|
|
3085
|
+
disabled: savingShown,
|
|
2905
3086
|
"aria-label": s.download,
|
|
2906
3087
|
className: "inline-flex items-center gap-1.5 rounded-md border border-border px-2 py-1 text-[12px] text-muted-foreground hover:text-foreground focus-visible:outline-solid focus-visible:outline-2 focus-visible:outline-offset-1 disabled:opacity-60",
|
|
2907
3088
|
children: [
|
|
2908
|
-
|
|
2909
|
-
|
|
3089
|
+
savingShown ? /* @__PURE__ */ jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ jsx(Download, { className: "h-3.5 w-3.5" }),
|
|
3090
|
+
savingShown ? s.downloading : s.download
|
|
2910
3091
|
]
|
|
2911
3092
|
}
|
|
2912
3093
|
),
|
|
@@ -2934,10 +3115,18 @@ function StuffViewer({
|
|
|
2934
3115
|
)
|
|
2935
3116
|
] })
|
|
2936
3117
|
] }),
|
|
2937
|
-
|
|
3118
|
+
downloadShown && /* @__PURE__ */ jsx(
|
|
3119
|
+
"p",
|
|
3120
|
+
{
|
|
3121
|
+
role: "status",
|
|
3122
|
+
className: cn("text-[12px] text-destructive", missedShown.length === 0 && "sr-only"),
|
|
3123
|
+
children: missedShown.length > 0 ? s.downloadIncomplete(missedShown) : ""
|
|
3124
|
+
}
|
|
3125
|
+
),
|
|
3126
|
+
view === "json" ? /* @__PURE__ */ jsx(JsonView, { value }) : /* @__PURE__ */ jsx(ResultRoot, { baseName, path: [field.name], children: /* @__PURE__ */ jsx(ResultField, { field, value, hideLabel: true }) })
|
|
2938
3127
|
] });
|
|
2939
3128
|
}
|
|
2940
3129
|
|
|
2941
|
-
export { BooleanField, ConceptPill, DEFAULT_FIELD_STRINGS, DateField, DocumentField, EnumField, FieldDomIdProvider, FieldPresentationProvider, FieldRenderer, FieldShell, FieldStringsProvider, HtmlPreview, ImageField, JsonView, ListField, Markdown, NumberField, ObjectField, OptionalToggle, ProseField, ResultEnvProvider, ResultField, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, StuffViewer, Switch, TextField, ToggleGroup, ToggleGroupItem, UnknownField, cn,
|
|
2942
|
-
//# sourceMappingURL=chunk-
|
|
2943
|
-
//# sourceMappingURL=chunk-
|
|
3130
|
+
export { BooleanField, ConceptPill, DEFAULT_FIELD_STRINGS, DateField, DocumentField, EnumField, FieldDomIdProvider, FieldPresentationProvider, FieldRenderer, FieldShell, FieldStringsProvider, HtmlPreview, ImageField, JsonView, ListField, Markdown, NumberField, ObjectField, OptionalToggle, ProseField, ResultEnvProvider, ResultField, ResultRoot, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, StuffViewer, Switch, TextField, ToggleGroup, ToggleGroupItem, UnknownField, cn, fieldControlClass, humanizeFieldName, saveInBrowser, useFieldDomId, useFieldPresentation, useFieldStrings, useProseImages, useResolveShareUrl, useResolveUrl, useResolvedUrl };
|
|
3131
|
+
//# sourceMappingURL=chunk-2D4NEFUH.js.map
|
|
3132
|
+
//# sourceMappingURL=chunk-2D4NEFUH.js.map
|