@pipelex/mthds-form 0.9.0 → 0.10.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/README.md +3 -0
- package/dist/{chunk-S4CB423P.js → chunk-4JQAJT7C.js} +3 -3
- package/dist/{chunk-S4CB423P.js.map → chunk-4JQAJT7C.js.map} +1 -1
- package/dist/{chunk-YABRYTQ4.js → chunk-4KGQ65TQ.js} +3 -3
- package/dist/{chunk-YABRYTQ4.js.map → chunk-4KGQ65TQ.js.map} +1 -1
- package/dist/chunk-CAKQ5VFT.js +35 -0
- package/dist/chunk-CAKQ5VFT.js.map +1 -0
- package/dist/{chunk-25I6JDIK.js → chunk-FABY3DEY.js} +2 -2
- package/dist/chunk-FABY3DEY.js.map +1 -0
- package/dist/{chunk-KG4IYFWI.js → chunk-G6BWZUGV.js} +165 -46
- package/dist/chunk-G6BWZUGV.js.map +1 -0
- package/dist/{chunk-AZZAAGNX.js → chunk-TID7ZN63.js} +7 -3
- package/dist/chunk-TID7ZN63.js.map +1 -0
- package/dist/chunk-XCO6GTEC.js +38 -0
- package/dist/chunk-XCO6GTEC.js.map +1 -0
- package/dist/{chunk-KIEOLP2L.js → chunk-ZB4RYUKV.js} +4 -4
- package/dist/chunk-ZB4RYUKV.js.map +1 -0
- package/dist/core/derive.d.ts +1 -0
- package/dist/core/derive.js +2 -2
- package/dist/core/descriptor.d.ts +13 -2
- package/dist/core/descriptor.js +1 -1
- package/dist/core/file-formats.d.ts +34 -7
- package/dist/core/file-formats.js +1 -1
- package/dist/core/gating-fields.d.ts +1 -0
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.js +7 -6
- package/dist/core/narrow-file-formats.d.ts +50 -0
- package/dist/core/narrow-file-formats.js +4 -0
- package/dist/core/narrow-file-formats.js.map +1 -0
- package/dist/core/native-content.d.ts +20 -11
- package/dist/core/native-content.js +1 -1
- package/dist/core/readiness.d.ts +1 -0
- package/dist/core/stuff-files.d.ts +1 -0
- package/dist/core/stuff-files.js +2 -2
- package/dist/core/values.d.ts +1 -0
- package/dist/core/values.js +3 -3
- package/dist/generative/index.d.ts +105 -12
- package/dist/generative/index.js +79 -157
- package/dist/generative/index.js.map +1 -1
- package/dist/{ui-designer.mthds → layout-design.mthds} +177 -29
- package/dist/react/index.d.ts +66 -10
- package/dist/react/index.js +5 -5
- package/dist/styles.css +1 -1
- package/package.json +3 -3
- package/dist/chunk-25I6JDIK.js.map +0 -1
- package/dist/chunk-2JWRG53S.js +0 -33
- package/dist/chunk-2JWRG53S.js.map +0 -1
- package/dist/chunk-AZZAAGNX.js.map +0 -1
- package/dist/chunk-KG4IYFWI.js.map +0 -1
- package/dist/chunk-KIEOLP2L.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { collectStuffFiles } from './chunk-
|
|
2
|
-
import { viewableUrl, isNativeDateNode, isNativeHtmlNode, readHtmlContent, isNativeCompositeNode, readCompositeContent,
|
|
3
|
-
import { conceptCategory } from './chunk-
|
|
4
|
-
import { isAcceptedFile,
|
|
1
|
+
import { collectStuffFiles } from './chunk-4JQAJT7C.js';
|
|
2
|
+
import { viewableUrl, isNativeDateNode, isNativeHtmlNode, readHtmlContent, isNativeCompositeNode, readCompositeContent, isNativeValueNode, readDateContent, formatDateContent, readImageContent, readDataUrl, readDocumentContent } from './chunk-TID7ZN63.js';
|
|
3
|
+
import { conceptCategory } from './chunk-FABY3DEY.js';
|
|
4
|
+
import { acceptLabel, acceptMap, isAcceptedFile, formatOfFilename, DOCUMENT_FORMATS, IMAGE_FORMATS } from './chunk-XCO6GTEC.js';
|
|
5
5
|
import { isFilled } from './chunk-PM55AHRO.js';
|
|
6
6
|
import { toStoredDateValue, toDateInputValue } from './chunk-GKV77RAS.js';
|
|
7
7
|
import { ownProp } from './chunk-V3OV2XQT.js';
|
|
@@ -66,6 +66,39 @@ function humanizeFieldName(name) {
|
|
|
66
66
|
if (words === "") return name;
|
|
67
67
|
return words.charAt(0).toUpperCase() + words.slice(1);
|
|
68
68
|
}
|
|
69
|
+
function humanizeEnumValue(code) {
|
|
70
|
+
if (!ENUM_CODE.test(code)) return code;
|
|
71
|
+
const allCaps = code === code.toUpperCase() && code !== code.toLowerCase();
|
|
72
|
+
if (!allCaps) return humanizeFieldName(code);
|
|
73
|
+
return CODE_SEPARATOR.test(code) ? humanizeFieldName(code.toLowerCase()) : code;
|
|
74
|
+
}
|
|
75
|
+
var ENUM_CODE = /^\p{L}[\p{L}\p{N}_-]*$/u;
|
|
76
|
+
var CODE_SEPARATOR = /[_-]/;
|
|
77
|
+
function enumLabeler(options, presentation) {
|
|
78
|
+
if (presentation !== "app") return asWritten;
|
|
79
|
+
let labeler = APP_LABELERS.get(options);
|
|
80
|
+
if (labeler === void 0) {
|
|
81
|
+
labeler = wordsOrCodes(options);
|
|
82
|
+
APP_LABELERS.set(options, labeler);
|
|
83
|
+
}
|
|
84
|
+
return labeler;
|
|
85
|
+
}
|
|
86
|
+
function asWritten(value) {
|
|
87
|
+
return value;
|
|
88
|
+
}
|
|
89
|
+
function wordsOrCodes(options) {
|
|
90
|
+
const labels = /* @__PURE__ */ new Map();
|
|
91
|
+
const owners = /* @__PURE__ */ new Map();
|
|
92
|
+
for (const option of options) {
|
|
93
|
+
const label = humanizeEnumValue(option);
|
|
94
|
+
const owner = owners.get(label);
|
|
95
|
+
if (owner !== void 0 && owner !== option) return asWritten;
|
|
96
|
+
owners.set(label, option);
|
|
97
|
+
labels.set(option, label);
|
|
98
|
+
}
|
|
99
|
+
return (value) => labels.get(value) ?? value;
|
|
100
|
+
}
|
|
101
|
+
var APP_LABELERS = /* @__PURE__ */ new WeakMap();
|
|
69
102
|
function fieldLabel(title, name, presentation) {
|
|
70
103
|
if (title !== void 0) return title;
|
|
71
104
|
return presentation === "app" ? humanizeFieldName(name) : name;
|
|
@@ -170,8 +203,9 @@ var DEFAULT_FIELD_STRINGS = {
|
|
|
170
203
|
dropToUpload: "Drop to upload",
|
|
171
204
|
dropOrBrowse: "Drop a file or click to browse",
|
|
172
205
|
pasteUrlInstead: "paste a URL instead",
|
|
173
|
-
urlPlaceholder: "https://\u2026
|
|
174
|
-
|
|
206
|
+
urlPlaceholder: "https://\u2026",
|
|
207
|
+
fileUrlAria: (label) => label ? `Link to the file for ${label}` : "Link to the file",
|
|
208
|
+
uploadedFile: "Attached file",
|
|
175
209
|
encodedFileSummary: (format, bytes) => `${format} \xB7 ${formatBytes(bytes)}`,
|
|
176
210
|
preview: "Preview",
|
|
177
211
|
removeFileAria: "Remove file",
|
|
@@ -192,7 +226,7 @@ var DEFAULT_FIELD_STRINGS = {
|
|
|
192
226
|
resultViewGroup: "Result view",
|
|
193
227
|
yes: "Yes",
|
|
194
228
|
no: "No",
|
|
195
|
-
unsupportedFileType: (
|
|
229
|
+
unsupportedFileType: (formats) => `That file type is not supported. Accepted formats: ${formats}.`,
|
|
196
230
|
hideOptionalFields: "Hide optional fields",
|
|
197
231
|
hideOptionalInputs: "Hide optional inputs",
|
|
198
232
|
optionalFieldsCount: (count) => count === 1 ? "1 optional field" : `${count} optional fields`,
|
|
@@ -296,6 +330,11 @@ function encodedFileSummary(url, strings) {
|
|
|
296
330
|
var IMAGE_EXT_RE = /\.(jpg|jpeg|png|gif|webp|bmp|svg|avif)(\?|$)/i;
|
|
297
331
|
var PDF_EXT_RE = /\.pdf(\?|$)/i;
|
|
298
332
|
var DATA_URL_MIME_RE = /^data:([^;,]+)/i;
|
|
333
|
+
var WEB_URL_RE = /^\s*https?:\/\//i;
|
|
334
|
+
var URL_SCHEME_RE = /^\s*[a-z][a-z0-9+.-]*:/i;
|
|
335
|
+
function isReadableLink(url) {
|
|
336
|
+
return WEB_URL_RE.test(url) || !URL_SCHEME_RE.test(url);
|
|
337
|
+
}
|
|
299
338
|
function dataUrlMime(url) {
|
|
300
339
|
return DATA_URL_MIME_RE.exec(url)?.[1]?.toLowerCase();
|
|
301
340
|
}
|
|
@@ -318,8 +357,10 @@ function FileField({
|
|
|
318
357
|
category
|
|
319
358
|
}) {
|
|
320
359
|
const s = useFieldStrings();
|
|
360
|
+
const presentation = useFieldPresentation();
|
|
321
361
|
const domId = useFieldDomId(id);
|
|
322
362
|
const [showUrl, setShowUrl] = useState(false);
|
|
363
|
+
const [typedUrl, setTypedUrl] = useState(null);
|
|
323
364
|
const [previewOpen, setPreviewOpen] = useState(false);
|
|
324
365
|
const [localPreview, setLocalPreview] = useState(null);
|
|
325
366
|
const [resolved, setResolved] = useState(null);
|
|
@@ -331,9 +372,12 @@ function FileField({
|
|
|
331
372
|
}, []);
|
|
332
373
|
useEffect(() => () => setLocal(null), [setLocal]);
|
|
333
374
|
const [rejected, setRejected] = useState(null);
|
|
375
|
+
const formats = field.formats;
|
|
376
|
+
const hint = acceptLabel(formats);
|
|
377
|
+
const accept = useMemo(() => acceptMap(formats), [formats]);
|
|
334
378
|
const handleFile = useCallback(
|
|
335
379
|
(file) => {
|
|
336
|
-
if (!isAcceptedFile(
|
|
380
|
+
if (!isAcceptedFile(formats, file)) {
|
|
337
381
|
setRejected(file.name);
|
|
338
382
|
return;
|
|
339
383
|
}
|
|
@@ -341,7 +385,7 @@ function FileField({
|
|
|
341
385
|
setLocal({ objectUrl: URL.createObjectURL(file), type: file.type });
|
|
342
386
|
onDropFile(file);
|
|
343
387
|
},
|
|
344
|
-
[
|
|
388
|
+
[formats, setLocal, onDropFile]
|
|
345
389
|
);
|
|
346
390
|
const busy = disabled || uploading;
|
|
347
391
|
const { getRootProps, getInputProps, isDragActive } = useDropzone({
|
|
@@ -353,7 +397,7 @@ function FileField({
|
|
|
353
397
|
// entirely, and a browser reporting an empty `File.type` slips through
|
|
354
398
|
// react-dropzone's own matcher. `handleFile` is where the answer is
|
|
355
399
|
// decided; this is the affordance in front of it.
|
|
356
|
-
accept
|
|
400
|
+
accept,
|
|
357
401
|
// The tab stop belongs on the INPUT, not on this div - see the root element
|
|
358
402
|
// below. Without this, react-dropzone puts `tabIndex: 0` and its own key
|
|
359
403
|
// handlers on a `role="presentation"` div, and the element a keyboard or
|
|
@@ -414,6 +458,8 @@ function FileField({
|
|
|
414
458
|
const resolvedSrc = resolved && resolved.uri === storageUri ? viewableUrl(resolved.src) : void 0;
|
|
415
459
|
const previewSrc = (localIsCurrent ? localPreview?.objectUrl : void 0) ?? directSrc ?? resolvedSrc;
|
|
416
460
|
const previewPending = !previewSrc && !!storageUri && resolved?.uri !== storageUri;
|
|
461
|
+
const urlValue = value?.url ?? "";
|
|
462
|
+
const urlText = presentation === "studio" || isReadableLink(urlValue) || urlValue === typedUrl ? urlValue : "";
|
|
417
463
|
return /* @__PURE__ */ jsxs(
|
|
418
464
|
FieldShell,
|
|
419
465
|
{
|
|
@@ -431,6 +477,8 @@ function FileField({
|
|
|
431
477
|
FileChip,
|
|
432
478
|
{
|
|
433
479
|
value,
|
|
480
|
+
formats,
|
|
481
|
+
presentation,
|
|
434
482
|
disabled,
|
|
435
483
|
onClear: clear,
|
|
436
484
|
canPreview,
|
|
@@ -480,7 +528,7 @@ function FileField({
|
|
|
480
528
|
/* @__PURE__ */ jsx(Upload, { className: "h-5 w-5 text-muted-foreground", strokeWidth: 1.75 }),
|
|
481
529
|
/* @__PURE__ */ jsxs("div", { className: "space-y-0.5", children: [
|
|
482
530
|
/* @__PURE__ */ jsx("p", { className: "text-[13px] text-foreground", children: isDragActive ? s.dropToUpload : s.dropOrBrowse }),
|
|
483
|
-
|
|
531
|
+
hint && /* @__PURE__ */ jsx("p", { className: "font-mono text-[10.5px] text-muted-foreground", children: hint })
|
|
484
532
|
] })
|
|
485
533
|
] })
|
|
486
534
|
]
|
|
@@ -489,9 +537,8 @@ function FileField({
|
|
|
489
537
|
),
|
|
490
538
|
rejected && !busy && /* @__PURE__ */ jsxs("p", { role: "alert", className: "text-[12px] text-destructive", children: [
|
|
491
539
|
/* @__PURE__ */ jsx("span", { className: "font-mono", children: rejected }),
|
|
492
|
-
" \u2014",
|
|
493
|
-
|
|
494
|
-
s.unsupportedFileType(field.accept ?? "")
|
|
540
|
+
" \u2014 ",
|
|
541
|
+
s.unsupportedFileType(hint)
|
|
495
542
|
] }),
|
|
496
543
|
!showUrl ? /* @__PURE__ */ jsxs(
|
|
497
544
|
"button",
|
|
@@ -510,11 +557,13 @@ function FileField({
|
|
|
510
557
|
{
|
|
511
558
|
type: "text",
|
|
512
559
|
autoFocus: true,
|
|
513
|
-
value:
|
|
560
|
+
value: urlText,
|
|
514
561
|
disabled: busy,
|
|
562
|
+
"aria-label": s.fileUrlAria(fieldLabel(field.title, field.name, presentation)),
|
|
515
563
|
placeholder: s.urlPlaceholder,
|
|
516
564
|
onChange: (e) => {
|
|
517
565
|
setLocal(null);
|
|
566
|
+
setTypedUrl(e.target.value);
|
|
518
567
|
onChange(e.target.value ? { url: e.target.value } : void 0);
|
|
519
568
|
},
|
|
520
569
|
className: cn(fieldControlClass, "h-9 px-3 font-mono text-[12px]")
|
|
@@ -556,8 +605,17 @@ function PdfPreview({ src }) {
|
|
|
556
605
|
}
|
|
557
606
|
);
|
|
558
607
|
}
|
|
608
|
+
function fileChipSubtitle(url, filename, formats, presentation, strings) {
|
|
609
|
+
if (url === void 0) return void 0;
|
|
610
|
+
const summary = encodedFileSummary(url, strings);
|
|
611
|
+
if (summary !== void 0) return summary;
|
|
612
|
+
if (presentation === "studio" || isReadableLink(url)) return url;
|
|
613
|
+
return filename ? formatOfFilename(formats, filename)?.label : void 0;
|
|
614
|
+
}
|
|
559
615
|
function FileChip({
|
|
560
616
|
value,
|
|
617
|
+
formats,
|
|
618
|
+
presentation,
|
|
561
619
|
disabled,
|
|
562
620
|
onClear,
|
|
563
621
|
canPreview,
|
|
@@ -566,15 +624,16 @@ function FileChip({
|
|
|
566
624
|
}) {
|
|
567
625
|
const s = useFieldStrings();
|
|
568
626
|
const url = value?.url;
|
|
627
|
+
const filename = value?.filename;
|
|
569
628
|
const subtitle = useMemo(
|
|
570
|
-
() => url
|
|
571
|
-
[url, s]
|
|
629
|
+
() => fileChipSubtitle(url, filename, formats, presentation, s),
|
|
630
|
+
[url, filename, formats, presentation, s]
|
|
572
631
|
);
|
|
573
632
|
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 rounded-md border border-border bg-input px-3 py-2.5", children: [
|
|
574
633
|
/* @__PURE__ */ jsx("span", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-md bg-muted", children: /* @__PURE__ */ jsx(FileText, { className: "h-4 w-4 text-muted-foreground" }) }),
|
|
575
634
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
576
635
|
/* @__PURE__ */ jsx("p", { className: "truncate text-[13px] font-medium text-foreground", children: value?.filename ?? s.uploadedFile }),
|
|
577
|
-
/* @__PURE__ */ jsx("p", { className: "truncate font-mono text-[10.5px] text-muted-foreground", children: subtitle })
|
|
636
|
+
subtitle && /* @__PURE__ */ jsx("p", { className: "truncate font-mono text-[10.5px] text-muted-foreground", children: subtitle })
|
|
578
637
|
] }),
|
|
579
638
|
canPreview && /* @__PURE__ */ jsxs(
|
|
580
639
|
"button",
|
|
@@ -773,7 +832,9 @@ ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName;
|
|
|
773
832
|
var CLEAR_VALUE = "__none__";
|
|
774
833
|
function EnumField({ field, value, onChange, id, error, disabled }) {
|
|
775
834
|
const s = useFieldStrings();
|
|
776
|
-
const
|
|
835
|
+
const presentation = useFieldPresentation();
|
|
836
|
+
const labelOf = enumLabeler(field.options, presentation);
|
|
837
|
+
const isSegmented = field.options.length <= 4 && field.options.every((o) => labelOf(o).length <= 16);
|
|
777
838
|
const domId = useFieldDomId(id);
|
|
778
839
|
return /* @__PURE__ */ jsx(
|
|
779
840
|
FieldShell,
|
|
@@ -797,7 +858,7 @@ function EnumField({ field, value, onChange, id, error, disabled }) {
|
|
|
797
858
|
value: value ?? "",
|
|
798
859
|
onValueChange: (next) => onChange(next === "" ? void 0 : next),
|
|
799
860
|
disabled,
|
|
800
|
-
"aria-label": field.title
|
|
861
|
+
"aria-label": fieldLabel(field.title, field.name, presentation),
|
|
801
862
|
className: "flex flex-wrap justify-start gap-1.5",
|
|
802
863
|
children: field.options.map((option) => /* @__PURE__ */ jsxs(
|
|
803
864
|
ToggleGroupItem,
|
|
@@ -807,7 +868,7 @@ function EnumField({ field, value, onChange, id, error, disabled }) {
|
|
|
807
868
|
className: "h-9 min-w-0 gap-1.5 border-border bg-input px-3 text-[13px] text-muted-foreground hover:bg-muted hover:text-foreground data-[state=on]:border-primary/40 data-[state=on]:bg-primary/10 data-[state=on]:font-medium data-[state=on]:text-foreground",
|
|
808
869
|
children: [
|
|
809
870
|
value === option && /* @__PURE__ */ jsx(Check, { className: "size-3.5 text-primary", strokeWidth: 2.5, "aria-hidden": "true" }),
|
|
810
|
-
option
|
|
871
|
+
labelOf(option)
|
|
811
872
|
]
|
|
812
873
|
},
|
|
813
874
|
option
|
|
@@ -824,7 +885,7 @@ function EnumField({ field, value, onChange, id, error, disabled }) {
|
|
|
824
885
|
/* @__PURE__ */ jsx(SelectTrigger, { id: domId, "aria-invalid": !!error, className: "h-11", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: s.selectPlaceholder }) }),
|
|
825
886
|
/* @__PURE__ */ jsxs(SelectContent, { children: [
|
|
826
887
|
/* @__PURE__ */ jsx(SelectItem, { value: CLEAR_VALUE, children: s.selectPlaceholder }),
|
|
827
|
-
field.options.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option, children: option }, option))
|
|
888
|
+
field.options.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option, children: labelOf(option) }, option))
|
|
828
889
|
] })
|
|
829
890
|
]
|
|
830
891
|
}
|
|
@@ -1345,11 +1406,12 @@ function ResultEnvProvider({
|
|
|
1345
1406
|
resolveUrl,
|
|
1346
1407
|
resolveShareUrl,
|
|
1347
1408
|
proseImages,
|
|
1409
|
+
tableColumns,
|
|
1348
1410
|
children
|
|
1349
1411
|
}) {
|
|
1350
1412
|
const env = useMemo(
|
|
1351
|
-
() => ({ resolveUrl, resolveShareUrl, proseImages }),
|
|
1352
|
-
[resolveUrl, resolveShareUrl, proseImages]
|
|
1413
|
+
() => ({ resolveUrl, resolveShareUrl, proseImages, tableColumns }),
|
|
1414
|
+
[resolveUrl, resolveShareUrl, proseImages, tableColumns]
|
|
1353
1415
|
);
|
|
1354
1416
|
return /* @__PURE__ */ jsx(ResultEnvContext, { value: env, children });
|
|
1355
1417
|
}
|
|
@@ -1365,6 +1427,12 @@ function useResolveShareUrl() {
|
|
|
1365
1427
|
function useProseImages() {
|
|
1366
1428
|
return use(ResultEnvContext).proseImages ?? "link";
|
|
1367
1429
|
}
|
|
1430
|
+
var DEFAULT_TABLE_COLUMNS = 5;
|
|
1431
|
+
function useTableColumns() {
|
|
1432
|
+
const budget = use(ResultEnvContext).tableColumns;
|
|
1433
|
+
if (budget === void 0 || Number.isNaN(budget)) return DEFAULT_TABLE_COLUMNS;
|
|
1434
|
+
return Math.max(1, Math.floor(budget));
|
|
1435
|
+
}
|
|
1368
1436
|
var TooltipProvider = TooltipPrimitive.Provider;
|
|
1369
1437
|
var TooltipRoot = TooltipPrimitive.Root;
|
|
1370
1438
|
var TooltipTrigger = TooltipPrimitive.Trigger;
|
|
@@ -1811,6 +1879,18 @@ function DateValue({ value }) {
|
|
|
1811
1879
|
if (!content) return /* @__PURE__ */ jsx(Absent, {});
|
|
1812
1880
|
return /* @__PURE__ */ jsx("span", { className: "text-[13px] text-foreground", children: formatDateContent(content) });
|
|
1813
1881
|
}
|
|
1882
|
+
function EnumValue({
|
|
1883
|
+
field,
|
|
1884
|
+
value,
|
|
1885
|
+
compact
|
|
1886
|
+
}) {
|
|
1887
|
+
const presentation = useFieldPresentation();
|
|
1888
|
+
const shown = typeof value === "string" ? enumLabeler(field.options, presentation)(value) : value;
|
|
1889
|
+
return /* @__PURE__ */ jsx(Scalar, { value: shown, compact });
|
|
1890
|
+
}
|
|
1891
|
+
function cellTitle(column, cell, presentation) {
|
|
1892
|
+
return column.kind === "enum" && typeof cell === "string" ? enumLabeler(column.options, presentation)(cell) : String(cell);
|
|
1893
|
+
}
|
|
1814
1894
|
function fileLabel(url, filename, strings) {
|
|
1815
1895
|
if (filename) return filename;
|
|
1816
1896
|
const encoded = encodedFileSummary(url, strings);
|
|
@@ -1829,16 +1909,18 @@ function CopyButton({
|
|
|
1829
1909
|
title
|
|
1830
1910
|
}) {
|
|
1831
1911
|
const [copied, setCopied] = useState(false);
|
|
1912
|
+
useEffect(() => {
|
|
1913
|
+
if (!copied) return;
|
|
1914
|
+
const timer = window.setTimeout(() => setCopied(false), 1500);
|
|
1915
|
+
return () => window.clearTimeout(timer);
|
|
1916
|
+
}, [copied]);
|
|
1832
1917
|
if (typeof navigator === "undefined" || !navigator.clipboard) return null;
|
|
1833
1918
|
return /* @__PURE__ */ jsx(
|
|
1834
1919
|
"button",
|
|
1835
1920
|
{
|
|
1836
1921
|
type: "button",
|
|
1837
1922
|
onClick: () => {
|
|
1838
|
-
const done = () =>
|
|
1839
|
-
setCopied(true);
|
|
1840
|
-
window.setTimeout(() => setCopied(false), 1500);
|
|
1841
|
-
};
|
|
1923
|
+
const done = () => setCopied(true);
|
|
1842
1924
|
if (!provide) {
|
|
1843
1925
|
void navigator.clipboard.writeText(value ?? "").then(done);
|
|
1844
1926
|
return;
|
|
@@ -2118,6 +2200,8 @@ function LeafValue({
|
|
|
2118
2200
|
return /* @__PURE__ */ jsx(ImageValue, { value, compact });
|
|
2119
2201
|
case "object":
|
|
2120
2202
|
return compact ? /* @__PURE__ */ jsx(RecordSummary, { field, value }) : /* @__PURE__ */ jsx(Scalar, { value });
|
|
2203
|
+
case "enum":
|
|
2204
|
+
return /* @__PURE__ */ jsx(EnumValue, { field, value, compact });
|
|
2121
2205
|
default:
|
|
2122
2206
|
return /* @__PURE__ */ jsx(Scalar, { value, compact });
|
|
2123
2207
|
}
|
|
@@ -2126,7 +2210,7 @@ function RecordSummary({ field, value }) {
|
|
|
2126
2210
|
const s = useFieldStrings();
|
|
2127
2211
|
if (isNativeDateNode(field)) return /* @__PURE__ */ jsx(DateValue, { value });
|
|
2128
2212
|
if (!isRecord(value) || Object.keys(value).length === 0) return /* @__PURE__ */ jsx(Absent, {});
|
|
2129
|
-
const naming = isNativeHtmlNode(field) ? void 0 : field.fields
|
|
2213
|
+
const naming = isNativeHtmlNode(field) ? void 0 : recordNameField(field.fields) ?? field.fields.find((member) => member.kind === "prose");
|
|
2130
2214
|
if (naming === void 0) {
|
|
2131
2215
|
return /* @__PURE__ */ jsx("span", { className: "whitespace-nowrap text-[12.5px] text-muted-foreground", children: s.fieldsCount(field.fields.length) });
|
|
2132
2216
|
}
|
|
@@ -2199,8 +2283,10 @@ function fitsACellWhole(field) {
|
|
|
2199
2283
|
return true;
|
|
2200
2284
|
case "text":
|
|
2201
2285
|
return field.maxLength !== void 0 && field.maxLength <= CELL_LENGTH_LIMIT;
|
|
2286
|
+
case "object":
|
|
2287
|
+
return isNativeDateNode(field);
|
|
2202
2288
|
case "list":
|
|
2203
|
-
return fitsACellWhole(field.item);
|
|
2289
|
+
return isInlineColumn(field) && fitsACellWhole(field.item);
|
|
2204
2290
|
default:
|
|
2205
2291
|
return false;
|
|
2206
2292
|
}
|
|
@@ -2213,10 +2299,12 @@ function ObjectTable({
|
|
|
2213
2299
|
}) {
|
|
2214
2300
|
const s = useFieldStrings();
|
|
2215
2301
|
const presentation = useFieldPresentation();
|
|
2302
|
+
const budget = useTableColumns();
|
|
2216
2303
|
const scrollerRef = useRef(null);
|
|
2217
2304
|
const [expanded, setExpanded] = useState(() => /* @__PURE__ */ new Set());
|
|
2218
2305
|
const [viewportWidth, setViewportWidth] = useState();
|
|
2219
|
-
const
|
|
2306
|
+
const { shown, hidden, name } = chooseColumns(columns, budget);
|
|
2307
|
+
const canExpand = hidden > 0 || shown.some((column) => column !== name && !fitsACellWhole(column));
|
|
2220
2308
|
useEffect(() => {
|
|
2221
2309
|
const scroller = scrollerRef.current;
|
|
2222
2310
|
if (!scroller) return;
|
|
@@ -2261,7 +2349,7 @@ function ObjectTable({
|
|
|
2261
2349
|
children: /* @__PURE__ */ jsxs("table", { className: "w-full min-w-full border-collapse text-[13px]", children: [
|
|
2262
2350
|
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: "border-b border-border bg-muted text-left", children: [
|
|
2263
2351
|
canExpand && /* @__PURE__ */ jsx("th", { scope: "col", style: { width: EXPAND_COLUMN }, className: "px-1", children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: s.rowDetailsColumn }) }),
|
|
2264
|
-
|
|
2352
|
+
shown.map((column) => /* @__PURE__ */ jsx(
|
|
2265
2353
|
"th",
|
|
2266
2354
|
{
|
|
2267
2355
|
scope: "col",
|
|
@@ -2275,7 +2363,7 @@ function ObjectTable({
|
|
|
2275
2363
|
))
|
|
2276
2364
|
] }) }),
|
|
2277
2365
|
/* @__PURE__ */ jsx("tbody", { children: items.map((item, index) => {
|
|
2278
|
-
const isOpen = expanded.has(index);
|
|
2366
|
+
const isOpen = canExpand && expanded.has(index);
|
|
2279
2367
|
return /* @__PURE__ */ jsx(Fragment$1, { children: /* @__PURE__ */ jsxs("tr", { className: "border-b border-border/60 last:border-b-0", children: [
|
|
2280
2368
|
canExpand && /* @__PURE__ */ jsx("td", { className: "px-1 pt-px align-top", children: /* @__PURE__ */ jsx(
|
|
2281
2369
|
"button",
|
|
@@ -2288,7 +2376,7 @@ function ObjectTable({
|
|
|
2288
2376
|
children: isOpen ? /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": true, className: "size-3.5" }) : /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": true, className: "size-3.5" })
|
|
2289
2377
|
}
|
|
2290
2378
|
) }),
|
|
2291
|
-
isOpen ? /* @__PURE__ */ jsx("td", { colSpan:
|
|
2379
|
+
isOpen ? /* @__PURE__ */ jsx("td", { colSpan: shown.length, className: "bg-card/40 p-0", children: /* @__PURE__ */ jsx(
|
|
2292
2380
|
"div",
|
|
2293
2381
|
{
|
|
2294
2382
|
className: "sticky left-0 px-3.5 py-3",
|
|
@@ -2303,16 +2391,16 @@ function ObjectTable({
|
|
|
2303
2391
|
} : {},
|
|
2304
2392
|
children: /* @__PURE__ */ jsx(ResultField, { field: element, value: item, hideLabel: true })
|
|
2305
2393
|
}
|
|
2306
|
-
) }) :
|
|
2394
|
+
) }) : shown.map((column) => {
|
|
2307
2395
|
const cell = typeof item === "object" && item !== null ? ownProp(item, column.name) : void 0;
|
|
2308
2396
|
return /* @__PURE__ */ jsx("td", { className: "px-3 py-1.5 align-top", children: /* @__PURE__ */ jsx(
|
|
2309
2397
|
"div",
|
|
2310
2398
|
{
|
|
2311
2399
|
className: cn(
|
|
2312
2400
|
"max-w-[44ch]",
|
|
2313
|
-
column.kind === "list" && isInlineColumn(column) ? "min-w-[16ch]" : "truncate"
|
|
2401
|
+
column === name ? "max-w-none min-w-[16ch] wrap-anywhere [&>span]:whitespace-normal" : column.kind === "list" && isInlineColumn(column) ? "min-w-[16ch]" : "truncate"
|
|
2314
2402
|
),
|
|
2315
|
-
...typeof cell === "string" || typeof cell === "number" ? { title:
|
|
2403
|
+
...typeof cell === "string" || typeof cell === "number" ? { title: cellTitle(column, cell, presentation) } : {},
|
|
2316
2404
|
children: /* @__PURE__ */ jsx(LeafValue, { field: column, value: cell, compact: true })
|
|
2317
2405
|
}
|
|
2318
2406
|
) }, column.name);
|
|
@@ -2379,10 +2467,31 @@ function ImageGallery({ items }) {
|
|
|
2379
2467
|
function FileRows({ items, kind }) {
|
|
2380
2468
|
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)) });
|
|
2381
2469
|
}
|
|
2382
|
-
function
|
|
2470
|
+
function recordColumns(item) {
|
|
2383
2471
|
if (item.kind !== "object" || item.fields.length === 0) return void 0;
|
|
2384
2472
|
return item.fields;
|
|
2385
2473
|
}
|
|
2474
|
+
function recordNameField(fields) {
|
|
2475
|
+
return fields.find((member) => member.kind === "text");
|
|
2476
|
+
}
|
|
2477
|
+
function columnTier(field, name) {
|
|
2478
|
+
if (field === name) return 1;
|
|
2479
|
+
if (field.kind !== "list" && fitsACellWhole(field)) return 2;
|
|
2480
|
+
if (field.kind === "text" || field.kind === "list" && isInlineColumn(field)) return 3;
|
|
2481
|
+
return 4;
|
|
2482
|
+
}
|
|
2483
|
+
function chooseColumns(fields, budget) {
|
|
2484
|
+
const name = recordNameField(fields);
|
|
2485
|
+
if (fields.length <= budget) return { shown: fields, hidden: 0, ...name ? { name } : {} };
|
|
2486
|
+
const kept = new Set(
|
|
2487
|
+
fields.map((field, index) => ({ field, index, tier: columnTier(field, name) })).sort((a, b) => a.tier - b.tier || a.index - b.index).slice(0, budget).map(({ field }) => field)
|
|
2488
|
+
);
|
|
2489
|
+
return {
|
|
2490
|
+
shown: fields.filter((field) => kept.has(field)),
|
|
2491
|
+
hidden: fields.length - kept.size,
|
|
2492
|
+
...name ? { name } : {}
|
|
2493
|
+
};
|
|
2494
|
+
}
|
|
2386
2495
|
function ResultField({ field, value, depth = 0, hideLabel = false }) {
|
|
2387
2496
|
const s = useFieldStrings();
|
|
2388
2497
|
const unwrapped = unwrap(field, value);
|
|
@@ -2454,13 +2563,21 @@ function ResultField({ field, value, depth = 0, hideLabel = false }) {
|
|
|
2454
2563
|
}
|
|
2455
2564
|
case "list": {
|
|
2456
2565
|
const items = Array.isArray(unwrapped) ? unwrapped : [];
|
|
2457
|
-
const columns =
|
|
2566
|
+
const columns = recordColumns(field.item);
|
|
2458
2567
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
2459
2568
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-baseline gap-x-2", children: [
|
|
2460
2569
|
header,
|
|
2461
2570
|
/* @__PURE__ */ jsx("span", { className: "font-mono text-[10.5px] text-muted-foreground", children: s.itemsCount(items.length) })
|
|
2462
2571
|
] }),
|
|
2463
|
-
items.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-[13px] italic text-muted-foreground", children: s.noItemsYet }) :
|
|
2572
|
+
items.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-[13px] italic text-muted-foreground", children: s.noItemsYet }) : isNativeValueNode(field.item) ? (
|
|
2573
|
+
// A list of dates, pages or composites is a list of VALUES, each read
|
|
2574
|
+
// by its own arm - one per line. Their nodes are `object` (or, for a
|
|
2575
|
+
// composite, `unknown`), so the branches below would tabulate a
|
|
2576
|
+
// date's `date` and `time`, print a page's markup source down a
|
|
2577
|
+
// column named by it, and show a composite as JSON. The arm keyed by
|
|
2578
|
+
// concept is the one that knows what each entry is.
|
|
2579
|
+
/* @__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)) })
|
|
2580
|
+
) : columns ? (
|
|
2464
2581
|
// Same shape every row: the labels are column headers, not per-row
|
|
2465
2582
|
// labels. See `ObjectTable`.
|
|
2466
2583
|
/* @__PURE__ */ jsx(
|
|
@@ -2616,6 +2733,11 @@ function highlight(json) {
|
|
|
2616
2733
|
function JsonView({ value }) {
|
|
2617
2734
|
const s = useFieldStrings();
|
|
2618
2735
|
const [copied, setCopied] = useState(false);
|
|
2736
|
+
useEffect(() => {
|
|
2737
|
+
if (!copied) return;
|
|
2738
|
+
const timer = window.setTimeout(() => setCopied(false), 1500);
|
|
2739
|
+
return () => window.clearTimeout(timer);
|
|
2740
|
+
}, [copied]);
|
|
2619
2741
|
const text = value === null || value === void 0 ? void 0 : typeof value === "object" ? stringifyValue(value) : JSON.stringify(value);
|
|
2620
2742
|
if (text === void 0) {
|
|
2621
2743
|
return /* @__PURE__ */ jsx(Absent, {});
|
|
@@ -2626,10 +2748,7 @@ function JsonView({ value }) {
|
|
|
2626
2748
|
{
|
|
2627
2749
|
type: "button",
|
|
2628
2750
|
onClick: () => {
|
|
2629
|
-
void navigator.clipboard.writeText(text).then(() =>
|
|
2630
|
-
setCopied(true);
|
|
2631
|
-
window.setTimeout(() => setCopied(false), 1500);
|
|
2632
|
-
});
|
|
2751
|
+
void navigator.clipboard.writeText(text).then(() => setCopied(true));
|
|
2633
2752
|
},
|
|
2634
2753
|
"aria-label": s.copyJson,
|
|
2635
2754
|
className: "absolute right-2 top-2 rounded border border-border bg-card p-1 text-muted-foreground hover:text-foreground focus-visible:outline-solid focus-visible:outline-2 focus-visible:outline-offset-1",
|
|
@@ -2717,5 +2836,5 @@ function StuffViewer({
|
|
|
2717
2836
|
}
|
|
2718
2837
|
|
|
2719
2838
|
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, downloadStuff, fieldControlClass, humanizeFieldName, useFieldDomId, useFieldPresentation, useFieldStrings, useProseImages, useResolveShareUrl, useResolveUrl, useResolvedUrl };
|
|
2720
|
-
//# sourceMappingURL=chunk-
|
|
2721
|
-
//# sourceMappingURL=chunk-
|
|
2839
|
+
//# sourceMappingURL=chunk-G6BWZUGV.js.map
|
|
2840
|
+
//# sourceMappingURL=chunk-G6BWZUGV.js.map
|