@pipelex/mthds-form 0.18.0 → 0.20.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-KLCV736G.js → chunk-4DPYGNJ3.js} +3 -3
- package/dist/{chunk-KLCV736G.js.map → chunk-4DPYGNJ3.js.map} +1 -1
- package/dist/{chunk-YY3JI6VI.js → chunk-CSLDIWB6.js} +1455 -112
- package/dist/chunk-CSLDIWB6.js.map +1 -0
- package/dist/{chunk-HQMXXK5X.js → chunk-E6BIXJ6C.js} +3 -3
- package/dist/{chunk-HQMXXK5X.js.map → chunk-E6BIXJ6C.js.map} +1 -1
- package/dist/chunk-EQJBM3NS.js +41 -0
- package/dist/chunk-EQJBM3NS.js.map +1 -0
- package/dist/{chunk-HVWE3TTC.js → chunk-ZB4RYUKV.js} +3 -3
- package/dist/{chunk-HVWE3TTC.js.map → chunk-ZB4RYUKV.js.map} +1 -1
- package/dist/{chunk-PQ3ZX5MJ.js → chunk-ZX52CQJ4.js} +17 -5
- package/dist/chunk-ZX52CQJ4.js.map +1 -0
- package/dist/core/derive.js +2 -2
- package/dist/core/gate.js +2 -2
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.js +13 -12
- package/dist/core/sources.d.ts +161 -0
- package/dist/core/sources.js +3 -0
- package/dist/core/sources.js.map +1 -0
- package/dist/core/values.d.ts +25 -1
- package/dist/core/values.js +4 -4
- package/dist/core/wire-format.d.ts +11 -1
- package/dist/core/wire-format.js +1 -1
- package/dist/{field-renderer-C5Onx6qB.d.ts → field-renderer-B3g16qZT.d.ts} +9 -0
- package/dist/generative/index.d.ts +2 -1
- package/dist/generative/index.js +8 -7
- package/dist/generative/index.js.map +1 -1
- package/dist/react/index.d.ts +248 -6
- package/dist/react/index.js +8 -7
- package/dist/styles.css +1 -1
- package/package.json +5 -2
- package/dist/chunk-PQ3ZX5MJ.js.map +0 -1
- package/dist/chunk-YY3JI6VI.js.map +0 -1
|
@@ -1,26 +1,30 @@
|
|
|
1
1
|
import { planFileSave, planStuffSave, splitFileName, typedFileStem } from './chunk-ICUEHNEH.js';
|
|
2
2
|
import { seedInputs, closeOptionalStructures, openOptionalStructures } from './chunk-VH5CDQDR.js';
|
|
3
|
+
import { sourceFileValue, roomForChosenFiles, addChosenFiles, chosenFilesAdded } from './chunk-EQJBM3NS.js';
|
|
3
4
|
import { readStuffFile } from './chunk-RRTI7AIR.js';
|
|
4
|
-
import { setValueAtPath, apiInputsFromRunValues } from './chunk-
|
|
5
|
-
import { shownAsOptional, isFoldedOptional, anyOptionalStructureOpen, isOptionalStructure, computeReadiness, optionalStructureOpen, mustBeFilled, fieldFilled, isFilled } from './chunk-XO5OENNF.js';
|
|
5
|
+
import { setValueAtPath, apiInputsFromRunValues, sameRunValues, runValuesFromInputs } from './chunk-ZX52CQJ4.js';
|
|
6
6
|
import { viewableUrl, isNativeDateNode, isNativeHtmlNode, readHtmlContent, isNativeCompositeNode, readCompositeContent, isNativeValueNode, readDateContent, formatDateContent, readImageContent, readDataUrl, readDocumentContent } from './chunk-CM4KVG53.js';
|
|
7
|
-
import { buildRunFields } from './chunk-
|
|
8
|
-
import { ownProp } from './chunk-V3OV2XQT.js';
|
|
7
|
+
import { buildRunFields } from './chunk-ZB4RYUKV.js';
|
|
9
8
|
import { conceptCategory } from './chunk-FABY3DEY.js';
|
|
10
|
-
import { acceptLabel, acceptMap, isAcceptedFile, formatOfFilename, DOCUMENT_FORMATS, IMAGE_FORMATS } from './chunk-XCO6GTEC.js';
|
|
9
|
+
import { acceptLabel, acceptMap, isAcceptedFile, normalizeMimeType, formatOfFilename, DOCUMENT_FORMATS, IMAGE_FORMATS } from './chunk-XCO6GTEC.js';
|
|
10
|
+
import { shownAsOptional, isFoldedOptional, anyOptionalStructureOpen, isOptionalStructure, computeReadiness, optionalStructureOpen, mustBeFilled, fieldFilled, isFilled } from './chunk-XO5OENNF.js';
|
|
11
|
+
import { ownProp } from './chunk-V3OV2XQT.js';
|
|
11
12
|
import { toStoredDateValue, toDateInputValue } from './chunk-GKV77RAS.js';
|
|
12
13
|
import { clsx } from 'clsx';
|
|
13
14
|
import { twMerge } from 'tailwind-merge';
|
|
14
|
-
import { ChevronDown, ChevronUp, Check, List, Braces, ListChecks, ToggleLeft, Hash, Image as Image$1, FileText, CalendarDays, Type, Loader2, ImageOff, Upload, Link2, EyeOff, Eye,
|
|
15
|
+
import { ChevronDown, ChevronUp, Check, List, Braces, ListChecks, ToggleLeft, Hash, Image as Image$1, FileText, CalendarDays, Type, Folder, Search, X, ImageIcon, Loader2, ImageOff, Upload, Link2, EyeOff, Eye, Minus, Plus, Trash2, Sparkles, MoreHorizontal, TriangleAlert, FileDown, Copy, Download, ChevronRight } from 'lucide-react';
|
|
15
16
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
16
|
-
import * as
|
|
17
|
-
import { createContext, use, useId, useMemo, useContext, useState, useRef,
|
|
17
|
+
import * as React5 from 'react';
|
|
18
|
+
import { createContext, use, useId, useMemo, useContext, useState, useEffect, useRef, useLayoutEffect, useCallback, Fragment as Fragment$1 } from 'react';
|
|
18
19
|
import * as SwitchPrimitives from '@radix-ui/react-switch';
|
|
19
20
|
import { useDropzone } from 'react-dropzone';
|
|
20
|
-
import * as
|
|
21
|
+
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
21
22
|
import * as ToggleGroupPrimitive from '@radix-ui/react-toggle-group';
|
|
22
23
|
import * as TogglePrimitive from '@radix-ui/react-toggle';
|
|
23
24
|
import { cva } from 'class-variance-authority';
|
|
25
|
+
import * as SelectPrimitive from '@radix-ui/react-select';
|
|
26
|
+
import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog';
|
|
27
|
+
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
24
28
|
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
25
29
|
import { marked } from 'marked';
|
|
26
30
|
|
|
@@ -107,7 +111,7 @@ function fieldLabel(title, name, presentation) {
|
|
|
107
111
|
if (title !== void 0) return title;
|
|
108
112
|
return presentation === "app" ? humanizeFieldName(name) : name;
|
|
109
113
|
}
|
|
110
|
-
var Switch =
|
|
114
|
+
var Switch = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
111
115
|
SwitchPrimitives.Root,
|
|
112
116
|
{
|
|
113
117
|
className: cn(
|
|
@@ -186,12 +190,38 @@ function BooleanField({ field, value, onChange, id, disabled }) {
|
|
|
186
190
|
);
|
|
187
191
|
}
|
|
188
192
|
|
|
193
|
+
// src/react/locales/calendar.ts
|
|
194
|
+
function dayNumber(date) {
|
|
195
|
+
return Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()) / 864e5;
|
|
196
|
+
}
|
|
197
|
+
function calendarDaysBefore(date, now = /* @__PURE__ */ new Date()) {
|
|
198
|
+
return dayNumber(now) - dayNumber(date);
|
|
199
|
+
}
|
|
200
|
+
function inCurrentYear(date, now = /* @__PURE__ */ new Date()) {
|
|
201
|
+
return date.getFullYear() === now.getFullYear();
|
|
202
|
+
}
|
|
203
|
+
|
|
189
204
|
// src/react/locales/en.ts
|
|
190
205
|
function formatBytes(bytes) {
|
|
191
206
|
if (bytes < 1024) return bytes === 1 ? "1 byte" : `${bytes} bytes`;
|
|
192
207
|
if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
|
|
193
208
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
194
209
|
}
|
|
210
|
+
var AND = new Intl.ListFormat("en-GB", { type: "conjunction" });
|
|
211
|
+
var OR = new Intl.ListFormat("en-GB", { type: "disjunction" });
|
|
212
|
+
var TIME = new Intl.DateTimeFormat("en-GB", { hour: "2-digit", minute: "2-digit" });
|
|
213
|
+
var DAY = new Intl.DateTimeFormat("en-GB", { day: "numeric", month: "short" });
|
|
214
|
+
var DAY_YEAR = new Intl.DateTimeFormat("en-GB", {
|
|
215
|
+
day: "numeric",
|
|
216
|
+
month: "short",
|
|
217
|
+
year: "numeric"
|
|
218
|
+
});
|
|
219
|
+
function formatFileDate(date) {
|
|
220
|
+
const days = calendarDaysBefore(date);
|
|
221
|
+
if (days === 0) return `Today, ${TIME.format(date)}`;
|
|
222
|
+
if (days === 1) return "Yesterday";
|
|
223
|
+
return inCurrentYear(date) ? DAY.format(date) : DAY_YEAR.format(date);
|
|
224
|
+
}
|
|
195
225
|
var EN_FIELD_STRINGS = {
|
|
196
226
|
optionalBadge: "optional",
|
|
197
227
|
selectPlaceholder: "Select\u2026",
|
|
@@ -252,7 +282,61 @@ var EN_FIELD_STRINGS = {
|
|
|
252
282
|
optionalInputsCount: (count) => count === 1 ? "1 optional input" : `${count} optional inputs`,
|
|
253
283
|
requiredField: "Required",
|
|
254
284
|
incompleteField: "Incomplete: fill in its required fields",
|
|
255
|
-
uploadFailed: "This file could not be uploaded. Try again."
|
|
285
|
+
uploadFailed: "This file could not be uploaded. Try again.",
|
|
286
|
+
chooseFromSource: "Choose from your team's files",
|
|
287
|
+
chooseFromSourceAria: (label) => label ? `Choose from your team's files for ${label}` : "Choose from your team's files",
|
|
288
|
+
filePickerTitle: "Your team's files",
|
|
289
|
+
filePickerTakes: (formats) => `Showing ${AND.format(formats)} files, which this input takes`,
|
|
290
|
+
filePickerSearch: "Search files",
|
|
291
|
+
filePickerSearchPlaceholder: "Search by name",
|
|
292
|
+
filePickerScope: "Whose files",
|
|
293
|
+
filePickerMine: "Mine",
|
|
294
|
+
filePickerEveryone: "Everyone",
|
|
295
|
+
filePickerUse: (count, name) => {
|
|
296
|
+
if (count === 0) return "Choose a file";
|
|
297
|
+
if (count === 1 && name) return `Use ${name}`;
|
|
298
|
+
return count === 1 ? "Use 1 file" : `Use ${count} files`;
|
|
299
|
+
},
|
|
300
|
+
filePickerLoading: "Loading your files\u2026",
|
|
301
|
+
filePickerFailed: "Couldn't load your files.",
|
|
302
|
+
filePickerNoMatch: "No files match.",
|
|
303
|
+
filePickerClearSearch: "Clear search",
|
|
304
|
+
filePickerNoneTeam: (formats) => `Your team has no ${OR.format(formats)} files yet.`,
|
|
305
|
+
filePickerNoneMine: (formats) => `You haven't added or made any ${OR.format(formats)} files yet.`,
|
|
306
|
+
filePickerShowEveryone: "Show everyone's",
|
|
307
|
+
filePickerUpload: "Upload a file",
|
|
308
|
+
filePickerShown: (count) => count === 1 ? "1 file" : `${count} files`,
|
|
309
|
+
testFile: "Test file",
|
|
310
|
+
fileSize: formatBytes,
|
|
311
|
+
fileDate: formatFileDate,
|
|
312
|
+
fillWithExample: "Fill with an example",
|
|
313
|
+
examplesTitle: "Examples",
|
|
314
|
+
examplesHint: "Choosing one fills the form. Nothing runs until you run it.",
|
|
315
|
+
examplesLoading: "Loading the examples\u2026",
|
|
316
|
+
examplesFailed: "Couldn't load the examples.",
|
|
317
|
+
examplesNone: "No examples yet. Run it, then save the run as an example.",
|
|
318
|
+
examplesShown: (count) => count === 1 ? "1 example" : `${count} examples`,
|
|
319
|
+
replaceEnteredTitle: "Replace what you entered?",
|
|
320
|
+
replaceEnteredDescription: (name) => `Filling the form with \u201C${name}\u201D replaces every value in it.`,
|
|
321
|
+
replaceEnteredConfirm: "Replace",
|
|
322
|
+
exampleActions: (name) => `Actions for ${name}`,
|
|
323
|
+
renameExample: "Rename",
|
|
324
|
+
deleteExample: "Delete",
|
|
325
|
+
renameExampleTitle: "Rename the example",
|
|
326
|
+
exampleName: "Name",
|
|
327
|
+
renaming: "Renaming\u2026",
|
|
328
|
+
renameFailed: "Couldn't rename the example.",
|
|
329
|
+
deleteExampleTitle: (name) => `Delete \u201C${name}\u201D?`,
|
|
330
|
+
deleteExampleDescription: "This cannot be undone.",
|
|
331
|
+
deleting: "Deleting\u2026",
|
|
332
|
+
deleteFailed: "Couldn't delete the example.",
|
|
333
|
+
close: "Close",
|
|
334
|
+
cancel: "Cancel",
|
|
335
|
+
save: "Save",
|
|
336
|
+
tryAgain: "Try again",
|
|
337
|
+
showMore: "Show more",
|
|
338
|
+
loadingMore: "Loading more\u2026",
|
|
339
|
+
loadMoreFailed: "Couldn't load more."
|
|
256
340
|
};
|
|
257
341
|
|
|
258
342
|
// src/react/locales/fr.ts
|
|
@@ -270,6 +354,21 @@ var MEGABYTES = new Intl.NumberFormat("fr-FR", {
|
|
|
270
354
|
unitDisplay: "short",
|
|
271
355
|
maximumFractionDigits: 1
|
|
272
356
|
});
|
|
357
|
+
var AND2 = new Intl.ListFormat("fr", { type: "conjunction" });
|
|
358
|
+
var OR2 = new Intl.ListFormat("fr", { type: "disjunction" });
|
|
359
|
+
var TIME2 = new Intl.DateTimeFormat("fr-FR", { hour: "2-digit", minute: "2-digit" });
|
|
360
|
+
var DAY2 = new Intl.DateTimeFormat("fr-FR", { day: "numeric", month: "short" });
|
|
361
|
+
var DAY_YEAR2 = new Intl.DateTimeFormat("fr-FR", {
|
|
362
|
+
day: "numeric",
|
|
363
|
+
month: "short",
|
|
364
|
+
year: "numeric"
|
|
365
|
+
});
|
|
366
|
+
function formatFileDate2(date) {
|
|
367
|
+
const days = calendarDaysBefore(date);
|
|
368
|
+
if (days === 0) return `Aujourd\u2019hui, ${TIME2.format(date)}`;
|
|
369
|
+
if (days === 1) return "Hier";
|
|
370
|
+
return inCurrentYear(date) ? DAY2.format(date) : DAY_YEAR2.format(date);
|
|
371
|
+
}
|
|
273
372
|
function plural(count, one, other) {
|
|
274
373
|
return PLURALS.select(count) === "one" ? one : other;
|
|
275
374
|
}
|
|
@@ -338,7 +437,61 @@ var FR_FIELD_STRINGS = {
|
|
|
338
437
|
optionalInputsCount: (count) => `${count} ${plural(count, "entr\xE9e facultative", "entr\xE9es facultatives")}`,
|
|
339
438
|
requiredField: "Obligatoire",
|
|
340
439
|
incompleteField: "Incomplet\xA0: remplissez ses champs obligatoires",
|
|
341
|
-
uploadFailed: "Ce fichier n\u2019a pas pu \xEAtre envoy\xE9. R\xE9essayez."
|
|
440
|
+
uploadFailed: "Ce fichier n\u2019a pas pu \xEAtre envoy\xE9. R\xE9essayez.",
|
|
441
|
+
chooseFromSource: "Choisir parmi les fichiers de l\u2019\xE9quipe",
|
|
442
|
+
chooseFromSourceAria: (label) => label ? `Choisir parmi les fichiers de l\u2019\xE9quipe pour ${label}` : "Choisir parmi les fichiers de l\u2019\xE9quipe",
|
|
443
|
+
filePickerTitle: "Les fichiers de l\u2019\xE9quipe",
|
|
444
|
+
filePickerTakes: (formats) => `Fichiers ${AND2.format(formats)} uniquement, ceux que cette entr\xE9e accepte`,
|
|
445
|
+
filePickerSearch: "Rechercher des fichiers",
|
|
446
|
+
filePickerSearchPlaceholder: "Rechercher par nom",
|
|
447
|
+
filePickerScope: "Quels fichiers",
|
|
448
|
+
filePickerMine: "Les miens",
|
|
449
|
+
filePickerEveryone: "Toute l\u2019\xE9quipe",
|
|
450
|
+
filePickerUse: (count, name) => {
|
|
451
|
+
if (count === 0) return "Choisissez un fichier";
|
|
452
|
+
if (count === 1 && name) return `Utiliser ${name}`;
|
|
453
|
+
return `Utiliser ${count} ${plural(count, "fichier", "fichiers")}`;
|
|
454
|
+
},
|
|
455
|
+
filePickerLoading: "Chargement de vos fichiers\u2026",
|
|
456
|
+
filePickerFailed: "Impossible de charger vos fichiers.",
|
|
457
|
+
filePickerNoMatch: "Aucun fichier ne correspond.",
|
|
458
|
+
filePickerClearSearch: "Effacer la recherche",
|
|
459
|
+
filePickerNoneTeam: (formats) => `L\u2019\xE9quipe n\u2019a encore aucun fichier ${OR2.format(formats)}.`,
|
|
460
|
+
filePickerNoneMine: (formats) => `Vous n\u2019avez encore ni ajout\xE9 ni cr\xE9\xE9 de fichier ${OR2.format(formats)}.`,
|
|
461
|
+
filePickerShowEveryone: "Voir ceux de l\u2019\xE9quipe",
|
|
462
|
+
filePickerUpload: "Envoyer un fichier",
|
|
463
|
+
filePickerShown: (count) => `${count} ${plural(count, "fichier", "fichiers")}`,
|
|
464
|
+
testFile: "Fichier de test",
|
|
465
|
+
fileSize: formatBytes2,
|
|
466
|
+
fileDate: formatFileDate2,
|
|
467
|
+
fillWithExample: "Remplir avec un exemple",
|
|
468
|
+
examplesTitle: "Exemples",
|
|
469
|
+
examplesHint: "En choisir un remplit le formulaire. Rien ne s\u2019ex\xE9cute avant que vous le lanciez.",
|
|
470
|
+
examplesLoading: "Chargement des exemples\u2026",
|
|
471
|
+
examplesFailed: "Impossible de charger les exemples.",
|
|
472
|
+
examplesNone: "Aucun exemple pour le moment. Lancez-le, puis enregistrez l\u2019ex\xE9cution comme exemple.",
|
|
473
|
+
examplesShown: (count) => `${count} ${plural(count, "exemple", "exemples")}`,
|
|
474
|
+
replaceEnteredTitle: "Remplacer ce que vous avez saisi\xA0?",
|
|
475
|
+
replaceEnteredDescription: (name) => `Remplir le formulaire avec \xAB\xA0${name}\xA0\xBB remplace toutes ses valeurs.`,
|
|
476
|
+
replaceEnteredConfirm: "Remplacer",
|
|
477
|
+
exampleActions: (name) => `Actions pour ${name}`,
|
|
478
|
+
renameExample: "Renommer",
|
|
479
|
+
deleteExample: "Supprimer",
|
|
480
|
+
renameExampleTitle: "Renommer l\u2019exemple",
|
|
481
|
+
exampleName: "Nom",
|
|
482
|
+
renaming: "Renommage\u2026",
|
|
483
|
+
renameFailed: "Impossible de renommer l\u2019exemple.",
|
|
484
|
+
deleteExampleTitle: (name) => `Supprimer \xAB\xA0${name}\xA0\xBB\xA0?`,
|
|
485
|
+
deleteExampleDescription: "Cette action est irr\xE9versible.",
|
|
486
|
+
deleting: "Suppression\u2026",
|
|
487
|
+
deleteFailed: "Impossible de supprimer l\u2019exemple.",
|
|
488
|
+
close: "Fermer",
|
|
489
|
+
cancel: "Annuler",
|
|
490
|
+
save: "Enregistrer",
|
|
491
|
+
tryAgain: "R\xE9essayer",
|
|
492
|
+
showMore: "Afficher plus",
|
|
493
|
+
loadingMore: "Chargement de la suite\u2026",
|
|
494
|
+
loadMoreFailed: "Impossible de charger la suite."
|
|
342
495
|
};
|
|
343
496
|
|
|
344
497
|
// src/react/locales/index.ts
|
|
@@ -457,6 +610,622 @@ function encodedFileSummary(url, strings) {
|
|
|
457
610
|
const format = [...DOCUMENT_FORMATS, ...IMAGE_FORMATS].find((known) => known.mimeType === view.mediaType)?.label ?? view.mediaType;
|
|
458
611
|
return strings.encodedFileSummary(format, view.bytes);
|
|
459
612
|
}
|
|
613
|
+
function startFor(key) {
|
|
614
|
+
return { key, status: key === null ? "idle" : "loading", items: [], cursor: null, more: "idle" };
|
|
615
|
+
}
|
|
616
|
+
function useSourcePages(load, key) {
|
|
617
|
+
const [stored, setState] = useState(() => startFor(key));
|
|
618
|
+
if (stored.key !== key) setState(startFor(key));
|
|
619
|
+
const state = stored.key === key ? stored : startFor(key);
|
|
620
|
+
const loadRef = useRef(load);
|
|
621
|
+
const inFlight = useRef(null);
|
|
622
|
+
const followed = useRef(/* @__PURE__ */ new Set());
|
|
623
|
+
useEffect(() => {
|
|
624
|
+
loadRef.current = load;
|
|
625
|
+
});
|
|
626
|
+
const read = useCallback(
|
|
627
|
+
(forKey, cursor, phase) => {
|
|
628
|
+
inFlight.current?.abort();
|
|
629
|
+
const controller = new AbortController();
|
|
630
|
+
inFlight.current = controller;
|
|
631
|
+
const seen = new Set(phase === "first" ? [] : followed.current);
|
|
632
|
+
const follow = (from) => {
|
|
633
|
+
if (from !== void 0) seen.add(from);
|
|
634
|
+
let page;
|
|
635
|
+
try {
|
|
636
|
+
page = Promise.resolve(loadRef.current(from, controller.signal));
|
|
637
|
+
} catch (error) {
|
|
638
|
+
page = Promise.reject(error);
|
|
639
|
+
}
|
|
640
|
+
page.then(
|
|
641
|
+
(answer) => {
|
|
642
|
+
if (inFlight.current !== controller) return;
|
|
643
|
+
const offered = answer.nextCursor ?? null;
|
|
644
|
+
const next = offered !== null && seen.has(offered) ? null : offered;
|
|
645
|
+
const items = [...answer.items];
|
|
646
|
+
if (items.length === 0 && next !== null) {
|
|
647
|
+
follow(next);
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
inFlight.current = null;
|
|
651
|
+
followed.current = seen;
|
|
652
|
+
setState(
|
|
653
|
+
(previous) => previous.key !== forKey ? previous : {
|
|
654
|
+
key: forKey,
|
|
655
|
+
status: "ready",
|
|
656
|
+
items: phase === "first" ? items : [...previous.items, ...items],
|
|
657
|
+
cursor: next,
|
|
658
|
+
more: "idle"
|
|
659
|
+
}
|
|
660
|
+
);
|
|
661
|
+
},
|
|
662
|
+
() => {
|
|
663
|
+
if (inFlight.current !== controller) return;
|
|
664
|
+
inFlight.current = null;
|
|
665
|
+
setState(
|
|
666
|
+
(previous) => previous.key !== forKey ? previous : phase === "first" ? { key: forKey, status: "failed", items: [], cursor: null, more: "idle" } : { ...previous, more: "failed" }
|
|
667
|
+
);
|
|
668
|
+
}
|
|
669
|
+
);
|
|
670
|
+
};
|
|
671
|
+
follow(cursor);
|
|
672
|
+
},
|
|
673
|
+
[]
|
|
674
|
+
);
|
|
675
|
+
useEffect(() => {
|
|
676
|
+
if (key === null) {
|
|
677
|
+
inFlight.current?.abort();
|
|
678
|
+
inFlight.current = null;
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
read(key, void 0, "first");
|
|
682
|
+
}, [key, read]);
|
|
683
|
+
useEffect(
|
|
684
|
+
() => () => {
|
|
685
|
+
inFlight.current?.abort();
|
|
686
|
+
inFlight.current = null;
|
|
687
|
+
},
|
|
688
|
+
[]
|
|
689
|
+
);
|
|
690
|
+
const loadMore = useCallback(() => {
|
|
691
|
+
if (state.status !== "ready" || state.cursor === null || state.more === "loading") return;
|
|
692
|
+
setState((previous) => ({ ...previous, more: "loading" }));
|
|
693
|
+
read(state.key, state.cursor, "more");
|
|
694
|
+
}, [state.key, state.status, state.cursor, state.more, read]);
|
|
695
|
+
const retry = useCallback(() => {
|
|
696
|
+
if (state.status === "failed") {
|
|
697
|
+
setState((previous) => startFor(previous.key));
|
|
698
|
+
read(state.key, void 0, "first");
|
|
699
|
+
} else if (state.more === "failed") {
|
|
700
|
+
loadMore();
|
|
701
|
+
}
|
|
702
|
+
}, [state.key, state.status, state.more, read, loadMore]);
|
|
703
|
+
const updateItems = useCallback((update) => {
|
|
704
|
+
setState((previous) => ({ ...previous, items: update(previous.items) }));
|
|
705
|
+
}, []);
|
|
706
|
+
const drained = state.status === "ready" && state.items.length === 0 && state.cursor !== null && state.more === "idle";
|
|
707
|
+
useEffect(() => {
|
|
708
|
+
if (drained) loadMore();
|
|
709
|
+
}, [drained, loadMore]);
|
|
710
|
+
return {
|
|
711
|
+
status: state.status,
|
|
712
|
+
items: state.items,
|
|
713
|
+
hasMore: state.cursor !== null,
|
|
714
|
+
empty: state.status === "ready" && state.items.length === 0 && state.cursor === null,
|
|
715
|
+
more: state.more,
|
|
716
|
+
loadMore,
|
|
717
|
+
retry,
|
|
718
|
+
updateItems
|
|
719
|
+
};
|
|
720
|
+
}
|
|
721
|
+
function DimRows({ count = 4 }) {
|
|
722
|
+
return /* @__PURE__ */ jsx("div", { "aria-hidden": "true", "data-dim-rows": true, className: "divide-y divide-border", children: Array.from({ length: count }, (_, index) => /* @__PURE__ */ jsxs("div", { className: "flex min-h-16 items-center gap-3 px-4 py-3 opacity-60", children: [
|
|
723
|
+
/* @__PURE__ */ jsx("span", { className: "size-8 shrink-0 rounded-md bg-muted" }),
|
|
724
|
+
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-2", children: [
|
|
725
|
+
/* @__PURE__ */ jsx("span", { className: "h-3.5 w-2/5 rounded-sm bg-muted" }),
|
|
726
|
+
/* @__PURE__ */ jsx("span", { className: "h-3 w-3/5 rounded-sm bg-muted" })
|
|
727
|
+
] })
|
|
728
|
+
] }, index)) });
|
|
729
|
+
}
|
|
730
|
+
function ListAction({
|
|
731
|
+
onClick,
|
|
732
|
+
children,
|
|
733
|
+
className
|
|
734
|
+
}) {
|
|
735
|
+
return /* @__PURE__ */ jsx(
|
|
736
|
+
"button",
|
|
737
|
+
{
|
|
738
|
+
type: "button",
|
|
739
|
+
onClick,
|
|
740
|
+
className: cn(
|
|
741
|
+
"inline-flex min-h-11 items-center justify-center rounded-md border border-border px-4 text-[14px] text-foreground transition-colors hover:bg-muted sm:min-h-9",
|
|
742
|
+
className
|
|
743
|
+
),
|
|
744
|
+
children
|
|
745
|
+
}
|
|
746
|
+
);
|
|
747
|
+
}
|
|
748
|
+
function ListMessage({ text, children }) {
|
|
749
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-3 px-4 py-10 text-center", children: [
|
|
750
|
+
/* @__PURE__ */ jsx("p", { className: "text-[14px] text-foreground", children: text }),
|
|
751
|
+
children && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap justify-center gap-2", children })
|
|
752
|
+
] });
|
|
753
|
+
}
|
|
754
|
+
function MoreFooter({ pages }) {
|
|
755
|
+
const s = useFieldStrings();
|
|
756
|
+
if (pages.more === "failed") {
|
|
757
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-center gap-3 px-4 py-4", children: [
|
|
758
|
+
/* @__PURE__ */ jsx("p", { className: "text-[13px] text-muted-foreground", children: s.loadMoreFailed }),
|
|
759
|
+
/* @__PURE__ */ jsx(ListAction, { onClick: pages.retry, children: s.tryAgain })
|
|
760
|
+
] });
|
|
761
|
+
}
|
|
762
|
+
if (pages.more === "loading") {
|
|
763
|
+
return /* @__PURE__ */ jsxs("p", { className: "flex items-center justify-center gap-2 px-4 py-4 text-[13px] text-muted-foreground", children: [
|
|
764
|
+
/* @__PURE__ */ jsx(Loader2, { className: "size-4 animate-spin", "aria-hidden": "true" }),
|
|
765
|
+
s.loadingMore
|
|
766
|
+
] });
|
|
767
|
+
}
|
|
768
|
+
if (!pages.hasMore) return null;
|
|
769
|
+
return /* @__PURE__ */ jsx("div", { className: "flex justify-center px-4 py-4", children: /* @__PURE__ */ jsx(ListAction, { onClick: pages.loadMore, children: s.showMore }) });
|
|
770
|
+
}
|
|
771
|
+
var Dialog = DialogPrimitive.Root;
|
|
772
|
+
var DialogClose = DialogPrimitive.Close;
|
|
773
|
+
function closeAutoFocus(onCloseAutoFocus, returnFocus) {
|
|
774
|
+
return (event) => {
|
|
775
|
+
onCloseAutoFocus?.(event);
|
|
776
|
+
if (event.defaultPrevented || !returnFocus) return;
|
|
777
|
+
const target = returnFocus();
|
|
778
|
+
if (!target?.isConnected) return;
|
|
779
|
+
event.preventDefault();
|
|
780
|
+
target.focus();
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
var DialogOverlay = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
784
|
+
DialogPrimitive.Overlay,
|
|
785
|
+
{
|
|
786
|
+
ref,
|
|
787
|
+
className: cn("fixed inset-0 z-50 bg-black/50", className),
|
|
788
|
+
...props
|
|
789
|
+
}
|
|
790
|
+
));
|
|
791
|
+
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
792
|
+
var DialogContent = React5.forwardRef(({ className, layout = "dialog", returnFocus, onCloseAutoFocus, children, ...props }, ref) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
793
|
+
/* @__PURE__ */ jsx(DialogOverlay, {}),
|
|
794
|
+
/* @__PURE__ */ jsx(
|
|
795
|
+
DialogPrimitive.Content,
|
|
796
|
+
{
|
|
797
|
+
ref,
|
|
798
|
+
className: cn(
|
|
799
|
+
"fixed z-50 flex flex-col border-border bg-popover text-popover-foreground shadow-lg outline-hidden",
|
|
800
|
+
layout === "sheet" ? [
|
|
801
|
+
"inset-x-0 top-6 bottom-0 rounded-t-xl border-t",
|
|
802
|
+
"xl:inset-0 xl:m-auto xl:h-fit xl:max-h-[min(720px,calc(100dvh-4rem))] xl:w-[calc(100%-2rem)] xl:max-w-[560px] xl:rounded-xl xl:border"
|
|
803
|
+
] : "inset-0 m-auto h-fit w-[calc(100%-2rem)] max-w-sm gap-3 rounded-lg border p-4",
|
|
804
|
+
className
|
|
805
|
+
),
|
|
806
|
+
onCloseAutoFocus: closeAutoFocus(onCloseAutoFocus, returnFocus),
|
|
807
|
+
...props,
|
|
808
|
+
children
|
|
809
|
+
}
|
|
810
|
+
)
|
|
811
|
+
] }));
|
|
812
|
+
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
813
|
+
var DialogTitle = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
814
|
+
DialogPrimitive.Title,
|
|
815
|
+
{
|
|
816
|
+
ref,
|
|
817
|
+
className: cn("text-[16px] font-semibold text-foreground", className),
|
|
818
|
+
...props
|
|
819
|
+
}
|
|
820
|
+
));
|
|
821
|
+
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
822
|
+
var DialogDescription = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
823
|
+
DialogPrimitive.Description,
|
|
824
|
+
{
|
|
825
|
+
ref,
|
|
826
|
+
className: cn("text-[13px] text-muted-foreground", className),
|
|
827
|
+
...props
|
|
828
|
+
}
|
|
829
|
+
));
|
|
830
|
+
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
831
|
+
var toggleVariants = cva(
|
|
832
|
+
"inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 gap-2",
|
|
833
|
+
{
|
|
834
|
+
variants: {
|
|
835
|
+
variant: {
|
|
836
|
+
default: "bg-transparent",
|
|
837
|
+
outline: "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground"
|
|
838
|
+
},
|
|
839
|
+
size: {
|
|
840
|
+
default: "h-10 px-3 min-w-10",
|
|
841
|
+
sm: "h-9 px-2.5 min-w-9",
|
|
842
|
+
lg: "h-11 px-5 min-w-11"
|
|
843
|
+
}
|
|
844
|
+
},
|
|
845
|
+
defaultVariants: {
|
|
846
|
+
variant: "default",
|
|
847
|
+
size: "default"
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
);
|
|
851
|
+
var Toggle = React5.forwardRef(({ className, variant, size, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
852
|
+
TogglePrimitive.Root,
|
|
853
|
+
{
|
|
854
|
+
ref,
|
|
855
|
+
className: cn(toggleVariants({ variant, size, className })),
|
|
856
|
+
...props
|
|
857
|
+
}
|
|
858
|
+
));
|
|
859
|
+
Toggle.displayName = TogglePrimitive.Root.displayName;
|
|
860
|
+
var ToggleGroupContext = React5.createContext({
|
|
861
|
+
size: "default",
|
|
862
|
+
variant: "default"
|
|
863
|
+
});
|
|
864
|
+
var ToggleGroup = React5.forwardRef(({ className, variant, size, children, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
865
|
+
ToggleGroupPrimitive.Root,
|
|
866
|
+
{
|
|
867
|
+
ref,
|
|
868
|
+
className: cn("flex items-center justify-center gap-1", className),
|
|
869
|
+
...props,
|
|
870
|
+
children: /* @__PURE__ */ jsx(ToggleGroupContext.Provider, { value: { variant, size }, children })
|
|
871
|
+
}
|
|
872
|
+
));
|
|
873
|
+
ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName;
|
|
874
|
+
var ToggleGroupItem = React5.forwardRef(({ className, children, variant, size, ...props }, ref) => {
|
|
875
|
+
const context = React5.useContext(ToggleGroupContext);
|
|
876
|
+
return /* @__PURE__ */ jsx(
|
|
877
|
+
ToggleGroupPrimitive.Item,
|
|
878
|
+
{
|
|
879
|
+
ref,
|
|
880
|
+
className: cn(
|
|
881
|
+
toggleVariants({
|
|
882
|
+
variant: context.variant || variant,
|
|
883
|
+
size: context.size || size
|
|
884
|
+
}),
|
|
885
|
+
className
|
|
886
|
+
),
|
|
887
|
+
...props,
|
|
888
|
+
children
|
|
889
|
+
}
|
|
890
|
+
);
|
|
891
|
+
});
|
|
892
|
+
ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName;
|
|
893
|
+
var SEARCH_PAUSE_MS = 250;
|
|
894
|
+
var SWIPE_CLOSE_PX = 96;
|
|
895
|
+
function FilePickerEntry({ onOpen, label, disabled, ref, id }) {
|
|
896
|
+
const s = useFieldStrings();
|
|
897
|
+
return /* @__PURE__ */ jsxs(
|
|
898
|
+
"button",
|
|
899
|
+
{
|
|
900
|
+
ref,
|
|
901
|
+
id,
|
|
902
|
+
type: "button",
|
|
903
|
+
onClick: onOpen,
|
|
904
|
+
disabled,
|
|
905
|
+
"aria-haspopup": "dialog",
|
|
906
|
+
"aria-label": s.chooseFromSourceAria(label),
|
|
907
|
+
className: "flex min-h-11 w-full items-center justify-center gap-2 rounded-md border border-border px-3 text-[14px] text-foreground transition-colors hover:bg-muted disabled:cursor-not-allowed disabled:opacity-50 sm:min-h-9",
|
|
908
|
+
children: [
|
|
909
|
+
/* @__PURE__ */ jsx(Folder, { className: "size-4 shrink-0 text-muted-foreground", "aria-hidden": "true" }),
|
|
910
|
+
s.chooseFromSource
|
|
911
|
+
]
|
|
912
|
+
}
|
|
913
|
+
);
|
|
914
|
+
}
|
|
915
|
+
function FilePicker({
|
|
916
|
+
open,
|
|
917
|
+
onOpenChange,
|
|
918
|
+
returnFocusTo,
|
|
919
|
+
onCloseAutoFocus,
|
|
920
|
+
disabled = false,
|
|
921
|
+
...props
|
|
922
|
+
}) {
|
|
923
|
+
const [drag, setDrag] = useState(0);
|
|
924
|
+
const shown = open && !disabled;
|
|
925
|
+
useEffect(() => {
|
|
926
|
+
if (open && disabled) onOpenChange(false);
|
|
927
|
+
}, [open, disabled, onOpenChange]);
|
|
928
|
+
const heldFocus = useRef(null);
|
|
929
|
+
useLayoutEffect(() => {
|
|
930
|
+
if (!open) return;
|
|
931
|
+
const active = document.activeElement;
|
|
932
|
+
heldFocus.current = active instanceof HTMLElement && active !== document.body ? active : null;
|
|
933
|
+
}, [open]);
|
|
934
|
+
return /* @__PURE__ */ jsx(Dialog, { open: shown, onOpenChange, children: shown && /* @__PURE__ */ jsx(
|
|
935
|
+
DialogContent,
|
|
936
|
+
{
|
|
937
|
+
layout: "sheet",
|
|
938
|
+
onCloseAutoFocus,
|
|
939
|
+
returnFocus: () => returnFocusTo?.current ?? heldFocus.current,
|
|
940
|
+
style: drag > 0 ? { transform: `translateY(${drag}px)` } : void 0,
|
|
941
|
+
onClick: (event) => event.stopPropagation(),
|
|
942
|
+
children: /* @__PURE__ */ jsx(FilePickerBody, { ...props, onDrag: setDrag, onClose: () => onOpenChange(false) })
|
|
943
|
+
}
|
|
944
|
+
) });
|
|
945
|
+
}
|
|
946
|
+
function FilePickerBody({
|
|
947
|
+
source,
|
|
948
|
+
formats,
|
|
949
|
+
multiple = false,
|
|
950
|
+
maxChoices,
|
|
951
|
+
held,
|
|
952
|
+
onUse,
|
|
953
|
+
onUpload,
|
|
954
|
+
onDrag,
|
|
955
|
+
onClose
|
|
956
|
+
}) {
|
|
957
|
+
const s = useFieldStrings();
|
|
958
|
+
const searchId = useId();
|
|
959
|
+
const [search, setSearch] = useState("");
|
|
960
|
+
const [query, setQuery] = useState("");
|
|
961
|
+
const [scope, setScope] = useState(source.initialScope);
|
|
962
|
+
const [chosen, setChosen] = useState(/* @__PURE__ */ new Map());
|
|
963
|
+
useEffect(() => {
|
|
964
|
+
const next = search.trim();
|
|
965
|
+
if (next === query) return;
|
|
966
|
+
const timer = setTimeout(() => setQuery(next), SEARCH_PAUSE_MS);
|
|
967
|
+
return () => clearTimeout(timer);
|
|
968
|
+
}, [search, query]);
|
|
969
|
+
const mediaTypes = useMemo(() => formats.map((format) => format.mimeType), [formats]);
|
|
970
|
+
const labels = useMemo(() => formats.map((format) => format.label), [formats]);
|
|
971
|
+
const load = (cursor, signal) => source.list({ search: query, scope, mediaTypes, cursor, signal }).then((page) => ({ items: page.files, nextCursor: page.nextCursor }));
|
|
972
|
+
const pages = useSourcePages(load, JSON.stringify([query, scope, mediaTypes]));
|
|
973
|
+
const fits = (files) => maxChoices === void 0 || chosenFilesAdded(held, files) <= maxChoices;
|
|
974
|
+
const toggle = (file) => setChosen((previous) => {
|
|
975
|
+
if (!multiple) return previous.has(file.id) ? previous : /* @__PURE__ */ new Map([[file.id, file]]);
|
|
976
|
+
const next = new Map(previous);
|
|
977
|
+
if (next.has(file.id)) next.delete(file.id);
|
|
978
|
+
else if (fits([...next.values(), file])) next.set(file.id, file);
|
|
979
|
+
return next;
|
|
980
|
+
});
|
|
981
|
+
const choices = [...chosen.values()];
|
|
982
|
+
const use6 = () => {
|
|
983
|
+
if (choices.length === 0) return;
|
|
984
|
+
onUse(choices);
|
|
985
|
+
onClose();
|
|
986
|
+
};
|
|
987
|
+
const clearSearch = () => {
|
|
988
|
+
setSearch("");
|
|
989
|
+
setQuery("");
|
|
990
|
+
};
|
|
991
|
+
const status = pickerStatus(s, pages, query, scope, labels);
|
|
992
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
993
|
+
/* @__PURE__ */ jsxs(SheetHeader, { onDrag, onClose, children: [
|
|
994
|
+
/* @__PURE__ */ jsx(DialogTitle, { className: "text-[20px]", children: s.filePickerTitle }),
|
|
995
|
+
/* @__PURE__ */ jsx(DialogDescription, { children: s.filePickerTakes(labels) })
|
|
996
|
+
] }),
|
|
997
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2 px-4 pb-3", children: [
|
|
998
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
999
|
+
/* @__PURE__ */ jsx("label", { htmlFor: searchId, className: "sr-only", children: s.filePickerSearch }),
|
|
1000
|
+
/* @__PURE__ */ jsx(
|
|
1001
|
+
Search,
|
|
1002
|
+
{
|
|
1003
|
+
className: "pointer-events-none absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground",
|
|
1004
|
+
"aria-hidden": "true"
|
|
1005
|
+
}
|
|
1006
|
+
),
|
|
1007
|
+
/* @__PURE__ */ jsx(
|
|
1008
|
+
"input",
|
|
1009
|
+
{
|
|
1010
|
+
id: searchId,
|
|
1011
|
+
type: "search",
|
|
1012
|
+
value: search,
|
|
1013
|
+
onChange: (event) => setSearch(event.target.value),
|
|
1014
|
+
onKeyDown: (event) => {
|
|
1015
|
+
if (event.key === "Enter") event.preventDefault();
|
|
1016
|
+
},
|
|
1017
|
+
placeholder: s.filePickerSearchPlaceholder,
|
|
1018
|
+
autoComplete: "off",
|
|
1019
|
+
className: "h-11 w-full rounded-md border border-border bg-input pr-3 pl-9 text-[16px] text-foreground placeholder:text-muted-foreground focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-ring"
|
|
1020
|
+
}
|
|
1021
|
+
)
|
|
1022
|
+
] }),
|
|
1023
|
+
/* @__PURE__ */ jsxs(
|
|
1024
|
+
ToggleGroup,
|
|
1025
|
+
{
|
|
1026
|
+
type: "single",
|
|
1027
|
+
value: scope,
|
|
1028
|
+
onValueChange: (value) => {
|
|
1029
|
+
if (value === "mine" || value === "everyone") setScope(value);
|
|
1030
|
+
},
|
|
1031
|
+
"aria-label": s.filePickerScope,
|
|
1032
|
+
className: "grid grid-cols-2 gap-1 rounded-md border border-border p-1",
|
|
1033
|
+
children: [
|
|
1034
|
+
/* @__PURE__ */ jsx(ToggleGroupItem, { value: "mine", className: "h-11 w-full text-[15px]", children: s.filePickerMine }),
|
|
1035
|
+
/* @__PURE__ */ jsx(ToggleGroupItem, { value: "everyone", className: "h-11 w-full text-[15px]", children: s.filePickerEveryone })
|
|
1036
|
+
]
|
|
1037
|
+
}
|
|
1038
|
+
)
|
|
1039
|
+
] }),
|
|
1040
|
+
/* @__PURE__ */ jsx("p", { role: "status", className: "sr-only", children: status }),
|
|
1041
|
+
/* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-y-auto border-t border-border", children: pages.status === "idle" || pages.status === "loading" ? /* @__PURE__ */ jsx(DimRows, {}) : pages.status === "failed" ? /* @__PURE__ */ jsx(ListMessage, { text: s.filePickerFailed, children: /* @__PURE__ */ jsx(ListAction, { onClick: pages.retry, children: s.tryAgain }) }) : pages.empty ? query !== "" ? /* @__PURE__ */ jsx(ListMessage, { text: s.filePickerNoMatch, children: /* @__PURE__ */ jsx(ListAction, { onClick: clearSearch, children: s.filePickerClearSearch }) }) : /* @__PURE__ */ jsxs(ListMessage, { text: status, children: [
|
|
1042
|
+
scope === "mine" && /* @__PURE__ */ jsx(ListAction, { onClick: () => setScope("everyone"), children: s.filePickerShowEveryone }),
|
|
1043
|
+
onUpload && /* @__PURE__ */ jsx(
|
|
1044
|
+
ListAction,
|
|
1045
|
+
{
|
|
1046
|
+
onClick: () => {
|
|
1047
|
+
onClose();
|
|
1048
|
+
onUpload();
|
|
1049
|
+
},
|
|
1050
|
+
children: s.filePickerUpload
|
|
1051
|
+
}
|
|
1052
|
+
)
|
|
1053
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1054
|
+
pages.items.length > 0 && /* @__PURE__ */ jsx(
|
|
1055
|
+
"div",
|
|
1056
|
+
{
|
|
1057
|
+
role: multiple ? "group" : "radiogroup",
|
|
1058
|
+
"aria-label": s.filePickerTitle,
|
|
1059
|
+
className: "divide-y divide-border",
|
|
1060
|
+
children: pages.items.map((file) => {
|
|
1061
|
+
const isChosen = chosen.has(file.id);
|
|
1062
|
+
return /* @__PURE__ */ jsx(
|
|
1063
|
+
FileRow,
|
|
1064
|
+
{
|
|
1065
|
+
file,
|
|
1066
|
+
formats,
|
|
1067
|
+
role: multiple ? "checkbox" : "radio",
|
|
1068
|
+
chosen: isChosen,
|
|
1069
|
+
disabled: !isChosen && !fits([...choices, file]),
|
|
1070
|
+
onToggle: () => toggle(file)
|
|
1071
|
+
},
|
|
1072
|
+
file.id
|
|
1073
|
+
);
|
|
1074
|
+
})
|
|
1075
|
+
}
|
|
1076
|
+
),
|
|
1077
|
+
/* @__PURE__ */ jsx(MoreFooter, { pages })
|
|
1078
|
+
] }) }),
|
|
1079
|
+
/* @__PURE__ */ jsx("div", { className: "border-t border-border px-4 pt-3 pb-[max(0.75rem,env(safe-area-inset-bottom))]", children: /* @__PURE__ */ jsx(
|
|
1080
|
+
"button",
|
|
1081
|
+
{
|
|
1082
|
+
type: "button",
|
|
1083
|
+
onClick: use6,
|
|
1084
|
+
disabled: choices.length === 0,
|
|
1085
|
+
className: "flex h-12 w-full items-center justify-center rounded-md bg-primary px-4 text-[16px] font-medium text-primary-foreground transition-colors hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-50",
|
|
1086
|
+
children: /* @__PURE__ */ jsx("span", { className: "truncate", children: s.filePickerUse(choices.length, choices[0]?.name) })
|
|
1087
|
+
}
|
|
1088
|
+
) })
|
|
1089
|
+
] });
|
|
1090
|
+
}
|
|
1091
|
+
function pickerStatus(s, pages, query, scope, labels) {
|
|
1092
|
+
if (pages.status === "idle" || pages.status === "loading") return s.filePickerLoading;
|
|
1093
|
+
if (pages.status === "failed") return s.filePickerFailed;
|
|
1094
|
+
if (pages.more === "failed") return s.loadMoreFailed;
|
|
1095
|
+
if (pages.items.length > 0) return s.filePickerShown(pages.items.length);
|
|
1096
|
+
if (!pages.empty) return s.filePickerLoading;
|
|
1097
|
+
if (query !== "") return s.filePickerNoMatch;
|
|
1098
|
+
return scope === "mine" ? s.filePickerNoneMine(labels) : s.filePickerNoneTeam(labels);
|
|
1099
|
+
}
|
|
1100
|
+
function SheetHeader({
|
|
1101
|
+
onDrag,
|
|
1102
|
+
onClose,
|
|
1103
|
+
children
|
|
1104
|
+
}) {
|
|
1105
|
+
const s = useFieldStrings();
|
|
1106
|
+
const start = useRef(null);
|
|
1107
|
+
const offset = useRef(0);
|
|
1108
|
+
const onPointerDown = (event) => {
|
|
1109
|
+
if (event.pointerType === "mouse") return;
|
|
1110
|
+
if (window.matchMedia?.("(min-width: 80rem)").matches) return;
|
|
1111
|
+
start.current = event.clientY;
|
|
1112
|
+
offset.current = 0;
|
|
1113
|
+
};
|
|
1114
|
+
const onPointerMove = (event) => {
|
|
1115
|
+
if (start.current === null) return;
|
|
1116
|
+
offset.current = Math.max(0, event.clientY - start.current);
|
|
1117
|
+
onDrag(offset.current);
|
|
1118
|
+
};
|
|
1119
|
+
const onPointerEnd = () => {
|
|
1120
|
+
if (start.current === null) return;
|
|
1121
|
+
const closes = offset.current > SWIPE_CLOSE_PX;
|
|
1122
|
+
start.current = null;
|
|
1123
|
+
offset.current = 0;
|
|
1124
|
+
onDrag(0);
|
|
1125
|
+
if (closes) onClose();
|
|
1126
|
+
};
|
|
1127
|
+
return /* @__PURE__ */ jsxs(
|
|
1128
|
+
"div",
|
|
1129
|
+
{
|
|
1130
|
+
className: "touch-none px-4 pt-2 pb-3 select-none",
|
|
1131
|
+
onPointerDown,
|
|
1132
|
+
onPointerMove,
|
|
1133
|
+
onPointerUp: onPointerEnd,
|
|
1134
|
+
onPointerCancel: onPointerEnd,
|
|
1135
|
+
children: [
|
|
1136
|
+
/* @__PURE__ */ jsx(
|
|
1137
|
+
"span",
|
|
1138
|
+
{
|
|
1139
|
+
"aria-hidden": "true",
|
|
1140
|
+
className: "mx-auto mb-2 block h-1.5 w-12 rounded-full bg-muted-foreground/40 xl:hidden"
|
|
1141
|
+
}
|
|
1142
|
+
),
|
|
1143
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
|
|
1144
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 space-y-1 pt-1", children }),
|
|
1145
|
+
/* @__PURE__ */ jsx(
|
|
1146
|
+
DialogClose,
|
|
1147
|
+
{
|
|
1148
|
+
"aria-label": s.close,
|
|
1149
|
+
className: "flex size-11 shrink-0 items-center justify-center rounded-full border border-border text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
1150
|
+
children: /* @__PURE__ */ jsx(X, { className: "size-5", "aria-hidden": "true" })
|
|
1151
|
+
}
|
|
1152
|
+
)
|
|
1153
|
+
] })
|
|
1154
|
+
]
|
|
1155
|
+
}
|
|
1156
|
+
);
|
|
1157
|
+
}
|
|
1158
|
+
function rowFormat(file, formats) {
|
|
1159
|
+
const type = file.mediaType ? normalizeMimeType(file.mediaType) : "";
|
|
1160
|
+
return formats.find((format) => format.mimeType === type) ?? formatOfFilename(formats, file.name);
|
|
1161
|
+
}
|
|
1162
|
+
function rowMeta(s, file, format) {
|
|
1163
|
+
const parts = [];
|
|
1164
|
+
if (format) parts.push(format.label);
|
|
1165
|
+
if (file.size !== void 0) parts.push(s.fileSize(file.size));
|
|
1166
|
+
if (file.origin) parts.push(file.origin);
|
|
1167
|
+
if (file.createdAt) {
|
|
1168
|
+
const date = new Date(file.createdAt);
|
|
1169
|
+
if (!Number.isNaN(date.getTime())) parts.push(s.fileDate(date));
|
|
1170
|
+
}
|
|
1171
|
+
return parts.join(" \xB7 ");
|
|
1172
|
+
}
|
|
1173
|
+
function FileRow({
|
|
1174
|
+
file,
|
|
1175
|
+
formats,
|
|
1176
|
+
role,
|
|
1177
|
+
chosen,
|
|
1178
|
+
disabled,
|
|
1179
|
+
onToggle
|
|
1180
|
+
}) {
|
|
1181
|
+
const s = useFieldStrings();
|
|
1182
|
+
const format = rowFormat(file, formats);
|
|
1183
|
+
const isImage = format?.mimeType.startsWith("image/") ?? false;
|
|
1184
|
+
const meta = rowMeta(s, file, format);
|
|
1185
|
+
const Glyph = isImage ? ImageIcon : FileText;
|
|
1186
|
+
return /* @__PURE__ */ jsxs(
|
|
1187
|
+
"button",
|
|
1188
|
+
{
|
|
1189
|
+
type: "button",
|
|
1190
|
+
role,
|
|
1191
|
+
"aria-checked": chosen,
|
|
1192
|
+
disabled,
|
|
1193
|
+
onClick: onToggle,
|
|
1194
|
+
className: cn(
|
|
1195
|
+
"flex min-h-16 w-full items-center gap-3 px-4 py-2.5 text-left transition-colors hover:bg-muted/60 disabled:cursor-not-allowed disabled:opacity-50",
|
|
1196
|
+
"focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-ring",
|
|
1197
|
+
chosen && "bg-muted"
|
|
1198
|
+
),
|
|
1199
|
+
children: [
|
|
1200
|
+
/* @__PURE__ */ jsx(
|
|
1201
|
+
Glyph,
|
|
1202
|
+
{
|
|
1203
|
+
className: "size-6 shrink-0 text-muted-foreground",
|
|
1204
|
+
strokeWidth: 1.5,
|
|
1205
|
+
"aria-hidden": "true"
|
|
1206
|
+
}
|
|
1207
|
+
),
|
|
1208
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
|
|
1209
|
+
/* @__PURE__ */ jsx("span", { className: "block truncate text-[16px] font-medium text-foreground", children: file.name }),
|
|
1210
|
+
(file.kind === "test" || meta) && /* @__PURE__ */ jsxs("span", { className: "block truncate text-[13px] text-muted-foreground", children: [
|
|
1211
|
+
file.kind === "test" && /* @__PURE__ */ jsxs("span", { className: "text-foreground", children: [
|
|
1212
|
+
s.testFile,
|
|
1213
|
+
meta && " \xB7 "
|
|
1214
|
+
] }),
|
|
1215
|
+
meta
|
|
1216
|
+
] })
|
|
1217
|
+
] }),
|
|
1218
|
+
/* @__PURE__ */ jsx(
|
|
1219
|
+
Check,
|
|
1220
|
+
{
|
|
1221
|
+
className: cn("size-5 shrink-0 text-foreground", !chosen && "invisible"),
|
|
1222
|
+
"aria-hidden": "true"
|
|
1223
|
+
}
|
|
1224
|
+
)
|
|
1225
|
+
]
|
|
1226
|
+
}
|
|
1227
|
+
);
|
|
1228
|
+
}
|
|
460
1229
|
var IMAGE_EXT_RE = /\.(jpg|jpeg|png|gif|webp|bmp|svg|avif)(\?|$)/i;
|
|
461
1230
|
var PDF_EXT_RE = /\.pdf(\?|$)/i;
|
|
462
1231
|
var DATA_URL_MIME_RE = /^data:([^;,]+)/i;
|
|
@@ -484,6 +1253,7 @@ function FileField({
|
|
|
484
1253
|
uploading,
|
|
485
1254
|
uploadError,
|
|
486
1255
|
resolveUrl,
|
|
1256
|
+
fileSource,
|
|
487
1257
|
error,
|
|
488
1258
|
disabled,
|
|
489
1259
|
category
|
|
@@ -497,6 +1267,9 @@ function FileField({
|
|
|
497
1267
|
const [localPreview, setLocalPreview] = useState(null);
|
|
498
1268
|
const [resolved, setResolved] = useState(null);
|
|
499
1269
|
const localUrlRef = useRef(null);
|
|
1270
|
+
const [pickerOpen, setPickerOpen] = useState(false);
|
|
1271
|
+
const cardRef = useRef(null);
|
|
1272
|
+
const pickerEntryRef = useRef(null);
|
|
500
1273
|
const setLocal = useCallback((next) => {
|
|
501
1274
|
if (localUrlRef.current) URL.revokeObjectURL(localUrlRef.current);
|
|
502
1275
|
localUrlRef.current = next?.objectUrl ?? null;
|
|
@@ -532,7 +1305,12 @@ function FileField({
|
|
|
532
1305
|
[formats, setLocal, onDropFile]
|
|
533
1306
|
);
|
|
534
1307
|
const busy = disabled || uploading;
|
|
535
|
-
const {
|
|
1308
|
+
const {
|
|
1309
|
+
getRootProps,
|
|
1310
|
+
getInputProps,
|
|
1311
|
+
isDragActive,
|
|
1312
|
+
open: openFileDialog
|
|
1313
|
+
} = useDropzone({
|
|
536
1314
|
maxFiles: 1,
|
|
537
1315
|
multiple: false,
|
|
538
1316
|
// Disabled, not merely unrendered, when there is no upload path: the hook
|
|
@@ -570,7 +1348,30 @@ function FileField({
|
|
|
570
1348
|
dismissUploadError();
|
|
571
1349
|
onChange(void 0);
|
|
572
1350
|
}, [setLocal, onChange, dismissUploadError]);
|
|
1351
|
+
const chooseFromSource = useCallback(
|
|
1352
|
+
(file) => {
|
|
1353
|
+
setLocal(null);
|
|
1354
|
+
setResolved(null);
|
|
1355
|
+
setRejected(null);
|
|
1356
|
+
dismissUploadError();
|
|
1357
|
+
onChange(sourceFileValue(file));
|
|
1358
|
+
},
|
|
1359
|
+
[setLocal, onChange, dismissUploadError]
|
|
1360
|
+
);
|
|
573
1361
|
const localIsCurrent = !!localPreview && (localPreview.boundUrl === void 0 || localPreview.boundUrl === value?.url);
|
|
1362
|
+
const wasUploading = useRef(!!uploading);
|
|
1363
|
+
useEffect(() => {
|
|
1364
|
+
const ended = wasUploading.current && !uploading;
|
|
1365
|
+
wasUploading.current = !!uploading;
|
|
1366
|
+
if (!localPreview || localPreview.boundUrl !== void 0) return;
|
|
1367
|
+
if (failure !== null || ended && !value?.url) setLocal(null);
|
|
1368
|
+
}, [uploading, failure, localPreview, value?.url, setLocal]);
|
|
1369
|
+
const lastUrl = useRef(value?.url);
|
|
1370
|
+
useEffect(() => {
|
|
1371
|
+
if (lastUrl.current === value?.url) return;
|
|
1372
|
+
lastUrl.current = value?.url;
|
|
1373
|
+
if (uploadError !== void 0) setDismissedUploadError(uploadError);
|
|
1374
|
+
}, [value?.url, uploadError]);
|
|
574
1375
|
useEffect(() => {
|
|
575
1376
|
if (!localPreview) return;
|
|
576
1377
|
if (localPreview.boundUrl === void 0) {
|
|
@@ -611,13 +1412,15 @@ function FileField({
|
|
|
611
1412
|
};
|
|
612
1413
|
const urlValue = value?.url ?? "";
|
|
613
1414
|
const urlText = presentation === "studio" || isReadableLink(urlValue) || urlValue === typedUrl ? urlValue : "";
|
|
614
|
-
|
|
1415
|
+
const canChoose = fileSource !== void 0;
|
|
1416
|
+
if (!canUpload && !allowUrl && !canChoose) {
|
|
615
1417
|
throw new Error(
|
|
616
|
-
`The file field at "${id}" has no way in: the form's environment supplies no onDropFile and sets allowUrl to false. Supply onDropFile so the file can be uploaded,
|
|
1418
|
+
`The file field at "${id}" has no way in: the form's environment supplies no onDropFile and no fileSource, and sets allowUrl to false. Supply onDropFile so the file can be uploaded, leave allowUrl unset so a link can be pasted, or supply a fileSource so a stored file can be chosen.`
|
|
617
1419
|
);
|
|
618
1420
|
}
|
|
619
1421
|
const linkOpen = allowUrl && (!canUpload || showUrl);
|
|
620
|
-
const noUploadLineShown = !canUpload && !hasFile && !uploading;
|
|
1422
|
+
const noUploadLineShown = !canUpload && allowUrl && !hasFile && !uploading;
|
|
1423
|
+
const choosingOnly = !canUpload && !allowUrl;
|
|
621
1424
|
const noUploadLineId = `${domId}-no-upload`;
|
|
622
1425
|
return /* @__PURE__ */ jsxs(
|
|
623
1426
|
FieldShell,
|
|
@@ -631,7 +1434,7 @@ function FileField({
|
|
|
631
1434
|
error,
|
|
632
1435
|
htmlFor: domId,
|
|
633
1436
|
children: [
|
|
634
|
-
hasFile && !uploading ? /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
1437
|
+
hasFile && !uploading ? /* @__PURE__ */ jsxs("div", { ref: cardRef, tabIndex: -1, className: "space-y-2 outline-none", children: [
|
|
635
1438
|
/* @__PURE__ */ jsx(
|
|
636
1439
|
FileChip,
|
|
637
1440
|
{
|
|
@@ -661,7 +1464,7 @@ function FileField({
|
|
|
661
1464
|
/* @__PURE__ */ jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }),
|
|
662
1465
|
s.uploading
|
|
663
1466
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
664
|
-
/* @__PURE__ */ jsx("p", { id: noUploadLineId, className: "text-[12px] text-muted-foreground", children: s.uploadUnavailable }),
|
|
1467
|
+
noUploadLineShown && /* @__PURE__ */ jsx("p", { id: noUploadLineId, className: "text-[12px] text-muted-foreground", children: s.uploadUnavailable }),
|
|
665
1468
|
hint && /* @__PURE__ */ jsx("p", { className: "font-mono text-[10.5px] text-muted-foreground", children: hint })
|
|
666
1469
|
] }) })
|
|
667
1470
|
) : (
|
|
@@ -734,14 +1537,45 @@ function FileField({
|
|
|
734
1537
|
) : allowUrl && /* @__PURE__ */ jsxs(
|
|
735
1538
|
"button",
|
|
736
1539
|
{
|
|
737
|
-
type: "button",
|
|
1540
|
+
type: "button",
|
|
1541
|
+
disabled: busy,
|
|
1542
|
+
onClick: () => setShowUrl(true),
|
|
1543
|
+
className: "flex w-fit items-center gap-1 font-mono text-[11px] text-muted-foreground transition-colors hover:text-foreground disabled:opacity-50 max-sm:min-h-11",
|
|
1544
|
+
children: [
|
|
1545
|
+
/* @__PURE__ */ jsx(Link2, { className: "h-3 w-3" }),
|
|
1546
|
+
s.pasteUrlInstead
|
|
1547
|
+
]
|
|
1548
|
+
}
|
|
1549
|
+
),
|
|
1550
|
+
fileSource && !hasFile && /* @__PURE__ */ jsx(
|
|
1551
|
+
FilePickerEntry,
|
|
1552
|
+
{
|
|
1553
|
+
ref: pickerEntryRef,
|
|
1554
|
+
id: choosingOnly ? domId : void 0,
|
|
1555
|
+
label: fieldLabel(field.title, field.name, presentation),
|
|
1556
|
+
disabled: busy,
|
|
1557
|
+
onOpen: () => setPickerOpen(true)
|
|
1558
|
+
}
|
|
1559
|
+
),
|
|
1560
|
+
fileSource && /* @__PURE__ */ jsx(
|
|
1561
|
+
FilePicker,
|
|
1562
|
+
{
|
|
1563
|
+
source: fileSource,
|
|
1564
|
+
formats,
|
|
1565
|
+
open: pickerOpen,
|
|
1566
|
+
onOpenChange: setPickerOpen,
|
|
1567
|
+
onUse: (files) => {
|
|
1568
|
+
const file = files[0];
|
|
1569
|
+
if (file) chooseFromSource(file);
|
|
1570
|
+
},
|
|
1571
|
+
onUpload: canUpload ? openFileDialog : void 0,
|
|
738
1572
|
disabled: busy,
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
1573
|
+
returnFocusTo: pickerEntryRef,
|
|
1574
|
+
onCloseAutoFocus: (event) => {
|
|
1575
|
+
if (!cardRef.current) return;
|
|
1576
|
+
event.preventDefault();
|
|
1577
|
+
cardRef.current.focus();
|
|
1578
|
+
}
|
|
745
1579
|
}
|
|
746
1580
|
)
|
|
747
1581
|
]
|
|
@@ -843,7 +1677,7 @@ function ClearButton({ disabled, onClick }) {
|
|
|
843
1677
|
}
|
|
844
1678
|
var Select = SelectPrimitive.Root;
|
|
845
1679
|
var SelectValue = SelectPrimitive.Value;
|
|
846
|
-
var SelectTrigger =
|
|
1680
|
+
var SelectTrigger = React5.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
847
1681
|
SelectPrimitive.Trigger,
|
|
848
1682
|
{
|
|
849
1683
|
ref,
|
|
@@ -862,7 +1696,7 @@ var SelectTrigger = React2.forwardRef(({ className, children, ...props }, ref) =
|
|
|
862
1696
|
}
|
|
863
1697
|
));
|
|
864
1698
|
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
865
|
-
var SelectScrollUpButton =
|
|
1699
|
+
var SelectScrollUpButton = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
866
1700
|
SelectPrimitive.ScrollUpButton,
|
|
867
1701
|
{
|
|
868
1702
|
ref,
|
|
@@ -872,7 +1706,7 @@ var SelectScrollUpButton = React2.forwardRef(({ className, ...props }, ref) => /
|
|
|
872
1706
|
}
|
|
873
1707
|
));
|
|
874
1708
|
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
|
875
|
-
var SelectScrollDownButton =
|
|
1709
|
+
var SelectScrollDownButton = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
876
1710
|
SelectPrimitive.ScrollDownButton,
|
|
877
1711
|
{
|
|
878
1712
|
ref,
|
|
@@ -882,7 +1716,7 @@ var SelectScrollDownButton = React2.forwardRef(({ className, ...props }, ref) =>
|
|
|
882
1716
|
}
|
|
883
1717
|
));
|
|
884
1718
|
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
|
|
885
|
-
var SelectContent =
|
|
1719
|
+
var SelectContent = React5.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
|
|
886
1720
|
SelectPrimitive.Content,
|
|
887
1721
|
{
|
|
888
1722
|
ref,
|
|
@@ -910,7 +1744,7 @@ var SelectContent = React2.forwardRef(({ className, children, position = "popper
|
|
|
910
1744
|
}
|
|
911
1745
|
) }));
|
|
912
1746
|
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
913
|
-
var SelectLabel =
|
|
1747
|
+
var SelectLabel = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
914
1748
|
SelectPrimitive.Label,
|
|
915
1749
|
{
|
|
916
1750
|
ref,
|
|
@@ -919,7 +1753,7 @@ var SelectLabel = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE
|
|
|
919
1753
|
}
|
|
920
1754
|
));
|
|
921
1755
|
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
|
922
|
-
var SelectItem =
|
|
1756
|
+
var SelectItem = React5.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
923
1757
|
SelectPrimitive.Item,
|
|
924
1758
|
{
|
|
925
1759
|
ref,
|
|
@@ -935,7 +1769,7 @@ var SelectItem = React2.forwardRef(({ className, children, ...props }, ref) => /
|
|
|
935
1769
|
}
|
|
936
1770
|
));
|
|
937
1771
|
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
938
|
-
var SelectSeparator =
|
|
1772
|
+
var SelectSeparator = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
939
1773
|
SelectPrimitive.Separator,
|
|
940
1774
|
{
|
|
941
1775
|
ref,
|
|
@@ -944,68 +1778,6 @@ var SelectSeparator = React2.forwardRef(({ className, ...props }, ref) => /* @__
|
|
|
944
1778
|
}
|
|
945
1779
|
));
|
|
946
1780
|
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
|
947
|
-
var toggleVariants = cva(
|
|
948
|
-
"inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 gap-2",
|
|
949
|
-
{
|
|
950
|
-
variants: {
|
|
951
|
-
variant: {
|
|
952
|
-
default: "bg-transparent",
|
|
953
|
-
outline: "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground"
|
|
954
|
-
},
|
|
955
|
-
size: {
|
|
956
|
-
default: "h-10 px-3 min-w-10",
|
|
957
|
-
sm: "h-9 px-2.5 min-w-9",
|
|
958
|
-
lg: "h-11 px-5 min-w-11"
|
|
959
|
-
}
|
|
960
|
-
},
|
|
961
|
-
defaultVariants: {
|
|
962
|
-
variant: "default",
|
|
963
|
-
size: "default"
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
);
|
|
967
|
-
var Toggle = React2.forwardRef(({ className, variant, size, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
968
|
-
TogglePrimitive.Root,
|
|
969
|
-
{
|
|
970
|
-
ref,
|
|
971
|
-
className: cn(toggleVariants({ variant, size, className })),
|
|
972
|
-
...props
|
|
973
|
-
}
|
|
974
|
-
));
|
|
975
|
-
Toggle.displayName = TogglePrimitive.Root.displayName;
|
|
976
|
-
var ToggleGroupContext = React2.createContext({
|
|
977
|
-
size: "default",
|
|
978
|
-
variant: "default"
|
|
979
|
-
});
|
|
980
|
-
var ToggleGroup = React2.forwardRef(({ className, variant, size, children, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
981
|
-
ToggleGroupPrimitive.Root,
|
|
982
|
-
{
|
|
983
|
-
ref,
|
|
984
|
-
className: cn("flex items-center justify-center gap-1", className),
|
|
985
|
-
...props,
|
|
986
|
-
children: /* @__PURE__ */ jsx(ToggleGroupContext.Provider, { value: { variant, size }, children })
|
|
987
|
-
}
|
|
988
|
-
));
|
|
989
|
-
ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName;
|
|
990
|
-
var ToggleGroupItem = React2.forwardRef(({ className, children, variant, size, ...props }, ref) => {
|
|
991
|
-
const context = React2.useContext(ToggleGroupContext);
|
|
992
|
-
return /* @__PURE__ */ jsx(
|
|
993
|
-
ToggleGroupPrimitive.Item,
|
|
994
|
-
{
|
|
995
|
-
ref,
|
|
996
|
-
className: cn(
|
|
997
|
-
toggleVariants({
|
|
998
|
-
variant: context.variant || variant,
|
|
999
|
-
size: context.size || size
|
|
1000
|
-
}),
|
|
1001
|
-
className
|
|
1002
|
-
),
|
|
1003
|
-
...props,
|
|
1004
|
-
children
|
|
1005
|
-
}
|
|
1006
|
-
);
|
|
1007
|
-
});
|
|
1008
|
-
ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName;
|
|
1009
1781
|
var CLEAR_VALUE = "__none__";
|
|
1010
1782
|
function EnumField({ field, value, onChange, id, error, disabled }) {
|
|
1011
1783
|
const s = useFieldStrings();
|
|
@@ -1288,12 +2060,39 @@ function ObjectField({ field, value, onChange, id, error, env }) {
|
|
|
1288
2060
|
error && /* @__PURE__ */ jsx("p", { className: "text-[11px] text-destructive", role: "alert", children: error })
|
|
1289
2061
|
] });
|
|
1290
2062
|
}
|
|
2063
|
+
|
|
2064
|
+
// src/react/focus.ts
|
|
2065
|
+
var FOCUSABLE = "a[href], button, input, select, textarea, [tabindex]";
|
|
2066
|
+
function takesFocus(element) {
|
|
2067
|
+
if (element.tabIndex < 0 || element.matches(":disabled")) return false;
|
|
2068
|
+
return element.closest("[hidden], [inert]") === null;
|
|
2069
|
+
}
|
|
2070
|
+
function followingFocusable(from, skip) {
|
|
2071
|
+
if (!from) return null;
|
|
2072
|
+
for (const element of from.ownerDocument.querySelectorAll(FOCUSABLE)) {
|
|
2073
|
+
if (!(from.compareDocumentPosition(element) & Node.DOCUMENT_POSITION_FOLLOWING)) continue;
|
|
2074
|
+
if (skip?.contains(element)) continue;
|
|
2075
|
+
if (takesFocus(element)) return element;
|
|
2076
|
+
}
|
|
2077
|
+
return null;
|
|
2078
|
+
}
|
|
2079
|
+
function firstFocusable(within) {
|
|
2080
|
+
if (!within) return null;
|
|
2081
|
+
for (const element of within.querySelectorAll(FOCUSABLE)) {
|
|
2082
|
+
if (takesFocus(element)) return element;
|
|
2083
|
+
}
|
|
2084
|
+
return null;
|
|
2085
|
+
}
|
|
1291
2086
|
function ListField({ field, value, onChange, id, error, env }) {
|
|
1292
2087
|
const s = useFieldStrings();
|
|
1293
2088
|
const presentation = useFieldPresentation();
|
|
1294
2089
|
const isApp = presentation === "app";
|
|
1295
2090
|
const items = value ?? [];
|
|
1296
2091
|
const [rowKeys, setRowKeys] = useRowKeys(items.length);
|
|
2092
|
+
const [pickerOpen, setPickerOpen] = useState(false);
|
|
2093
|
+
const pickerEntryRef = useRef(null);
|
|
2094
|
+
const rowsRef = useRef(null);
|
|
2095
|
+
const landedRow = useRef(null);
|
|
1297
2096
|
const [staleErrors, setStaleErrors] = useState(NO_ERRORS);
|
|
1298
2097
|
const setItem = (index, itemValue) => {
|
|
1299
2098
|
const next = items.slice();
|
|
@@ -1337,6 +2136,9 @@ function ListField({ field, value, onChange, id, error, env }) {
|
|
|
1337
2136
|
};
|
|
1338
2137
|
}, [env, staleErrors]);
|
|
1339
2138
|
const isFull = field.maxItemCount !== void 0 && items.length >= field.maxItemCount;
|
|
2139
|
+
const fileSource = env?.fileSource;
|
|
2140
|
+
const fileItem = field.item.kind === "document" || field.item.kind === "image" ? field.item : null;
|
|
2141
|
+
const room = roomForChosenFiles(items, field.maxItemCount);
|
|
1340
2142
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
1341
2143
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-baseline gap-x-2 gap-y-1", children: [
|
|
1342
2144
|
/* @__PURE__ */ jsx(
|
|
@@ -1354,11 +2156,12 @@ function ListField({ field, value, onChange, id, error, env }) {
|
|
|
1354
2156
|
shownAsOptional(field) && /* @__PURE__ */ jsx("span", { className: "ml-auto font-mono text-[10px] uppercase tracking-wider text-muted-foreground", children: s.optionalBadge })
|
|
1355
2157
|
] }),
|
|
1356
2158
|
field.description && /* @__PURE__ */ jsx("p", { className: "text-[12px] leading-relaxed text-muted-foreground", children: field.description }),
|
|
1357
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
2159
|
+
/* @__PURE__ */ jsxs("div", { ref: rowsRef, className: "space-y-2", children: [
|
|
1358
2160
|
items.length === 0 && /* @__PURE__ */ jsx("p", { className: "rounded-md border border-dashed border-border bg-input/50 px-3 py-4 text-center text-[12px] text-muted-foreground", children: s.noItemsYet }),
|
|
1359
2161
|
items.map((item, index) => /* @__PURE__ */ jsxs(
|
|
1360
2162
|
"div",
|
|
1361
2163
|
{
|
|
2164
|
+
"data-list-row": true,
|
|
1362
2165
|
className: "flex items-start gap-2 rounded-md border border-border bg-card/40 p-3",
|
|
1363
2166
|
children: [
|
|
1364
2167
|
/* @__PURE__ */ jsx("span", { className: "mt-1 w-5 shrink-0 text-center font-mono text-[11px] text-muted-foreground", children: index + 1 }),
|
|
@@ -1407,11 +2210,56 @@ function ListField({ field, value, onChange, id, error, env }) {
|
|
|
1407
2210
|
s.addItem
|
|
1408
2211
|
]
|
|
1409
2212
|
}
|
|
1410
|
-
)
|
|
2213
|
+
),
|
|
2214
|
+
fileSource && fileItem && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2215
|
+
/* @__PURE__ */ jsx(
|
|
2216
|
+
FilePickerEntry,
|
|
2217
|
+
{
|
|
2218
|
+
ref: pickerEntryRef,
|
|
2219
|
+
label: fieldLabel(field.title, field.name, presentation),
|
|
2220
|
+
disabled: env?.disabled || busy || room === 0,
|
|
2221
|
+
onOpen: () => setPickerOpen(true)
|
|
2222
|
+
}
|
|
2223
|
+
),
|
|
2224
|
+
/* @__PURE__ */ jsx(
|
|
2225
|
+
FilePicker,
|
|
2226
|
+
{
|
|
2227
|
+
source: fileSource,
|
|
2228
|
+
formats: fileItem.formats,
|
|
2229
|
+
multiple: true,
|
|
2230
|
+
maxChoices: room,
|
|
2231
|
+
held: items,
|
|
2232
|
+
open: pickerOpen,
|
|
2233
|
+
onOpenChange: setPickerOpen,
|
|
2234
|
+
disabled: env?.disabled || busy,
|
|
2235
|
+
returnFocusTo: pickerEntryRef,
|
|
2236
|
+
onCloseAutoFocus: (event) => {
|
|
2237
|
+
const landed = landedRow.current;
|
|
2238
|
+
landedRow.current = null;
|
|
2239
|
+
if (landed === null || !pickerEntryRef.current?.disabled) return;
|
|
2240
|
+
const rows = rowsRef.current?.querySelectorAll(":scope > [data-list-row]");
|
|
2241
|
+
const target = firstFocusable(rows?.[landed]);
|
|
2242
|
+
if (!target) return;
|
|
2243
|
+
event.preventDefault();
|
|
2244
|
+
target.focus();
|
|
2245
|
+
},
|
|
2246
|
+
onUse: (files) => {
|
|
2247
|
+
const next = addChosenFiles(items, files);
|
|
2248
|
+
landedRow.current = lastWrittenRow(items, next);
|
|
2249
|
+
onChange(next);
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2252
|
+
)
|
|
2253
|
+
] })
|
|
1411
2254
|
] }),
|
|
1412
2255
|
error && /* @__PURE__ */ jsx("p", { className: "text-[11px] text-destructive", role: "alert", children: error })
|
|
1413
2256
|
] });
|
|
1414
2257
|
}
|
|
2258
|
+
function lastWrittenRow(before, after) {
|
|
2259
|
+
let index = after.length - 1;
|
|
2260
|
+
while (index >= 0 && after[index] === before[index]) index -= 1;
|
|
2261
|
+
return index >= 0 ? index : null;
|
|
2262
|
+
}
|
|
1415
2263
|
function listIsBusy(id, uploadingIds) {
|
|
1416
2264
|
if (!uploadingIds?.size) return false;
|
|
1417
2265
|
const prefix = `${id}.`;
|
|
@@ -1581,6 +2429,7 @@ function FieldRenderer({ field, value, onChange, id, error, env }) {
|
|
|
1581
2429
|
uploading: env?.uploadingIds?.has(id),
|
|
1582
2430
|
uploadError: env?.uploadErrors?.get(id),
|
|
1583
2431
|
resolveUrl: env?.resolveUrl,
|
|
2432
|
+
fileSource: env?.fileSource,
|
|
1584
2433
|
id,
|
|
1585
2434
|
error,
|
|
1586
2435
|
disabled
|
|
@@ -1598,6 +2447,7 @@ function FieldRenderer({ field, value, onChange, id, error, env }) {
|
|
|
1598
2447
|
uploading: env?.uploadingIds?.has(id),
|
|
1599
2448
|
uploadError: env?.uploadErrors?.get(id),
|
|
1600
2449
|
resolveUrl: env?.resolveUrl,
|
|
2450
|
+
fileSource: env?.fileSource,
|
|
1601
2451
|
id,
|
|
1602
2452
|
error,
|
|
1603
2453
|
disabled
|
|
@@ -1641,6 +2491,450 @@ function FieldRenderer({ field, value, onChange, id, error, env }) {
|
|
|
1641
2491
|
);
|
|
1642
2492
|
}
|
|
1643
2493
|
}
|
|
2494
|
+
var AlertDialog = AlertDialogPrimitive.Root;
|
|
2495
|
+
var AlertDialogContent = React5.forwardRef(({ className, returnFocus, onCloseAutoFocus, ...props }, ref) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2496
|
+
/* @__PURE__ */ jsx(AlertDialogPrimitive.Overlay, { className: "fixed inset-0 z-50 bg-black/50" }),
|
|
2497
|
+
/* @__PURE__ */ jsx(
|
|
2498
|
+
AlertDialogPrimitive.Content,
|
|
2499
|
+
{
|
|
2500
|
+
ref,
|
|
2501
|
+
className: cn(
|
|
2502
|
+
"fixed inset-0 z-50 m-auto grid h-fit w-[calc(100%-2rem)] max-w-sm gap-3 rounded-lg border border-border bg-popover p-4 text-popover-foreground shadow-lg outline-hidden",
|
|
2503
|
+
className
|
|
2504
|
+
),
|
|
2505
|
+
onCloseAutoFocus: closeAutoFocus(onCloseAutoFocus, returnFocus),
|
|
2506
|
+
...props
|
|
2507
|
+
}
|
|
2508
|
+
)
|
|
2509
|
+
] }));
|
|
2510
|
+
AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
|
|
2511
|
+
var AlertDialogTitle = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2512
|
+
AlertDialogPrimitive.Title,
|
|
2513
|
+
{
|
|
2514
|
+
ref,
|
|
2515
|
+
className: cn("text-[16px] font-semibold text-foreground", className),
|
|
2516
|
+
...props
|
|
2517
|
+
}
|
|
2518
|
+
));
|
|
2519
|
+
AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
|
|
2520
|
+
var AlertDialogDescription = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2521
|
+
AlertDialogPrimitive.Description,
|
|
2522
|
+
{
|
|
2523
|
+
ref,
|
|
2524
|
+
className: cn("text-[13px] text-muted-foreground", className),
|
|
2525
|
+
...props
|
|
2526
|
+
}
|
|
2527
|
+
));
|
|
2528
|
+
AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;
|
|
2529
|
+
var AlertDialogCancel = AlertDialogPrimitive.Cancel;
|
|
2530
|
+
var AlertDialogAction = AlertDialogPrimitive.Action;
|
|
2531
|
+
var DropdownMenu = DropdownMenuPrimitive.Root;
|
|
2532
|
+
var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
|
|
2533
|
+
var DropdownMenuContent = React5.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2534
|
+
DropdownMenuPrimitive.Content,
|
|
2535
|
+
{
|
|
2536
|
+
ref,
|
|
2537
|
+
sideOffset,
|
|
2538
|
+
className: cn(
|
|
2539
|
+
"z-50 min-w-36 overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md",
|
|
2540
|
+
className
|
|
2541
|
+
),
|
|
2542
|
+
...props
|
|
2543
|
+
}
|
|
2544
|
+
));
|
|
2545
|
+
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
|
|
2546
|
+
var DropdownMenuItem = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2547
|
+
DropdownMenuPrimitive.Item,
|
|
2548
|
+
{
|
|
2549
|
+
ref,
|
|
2550
|
+
className: cn(
|
|
2551
|
+
"flex min-h-11 cursor-default select-none items-center gap-2 rounded-sm px-3 text-[14px] outline-hidden data-highlighted:bg-accent data-highlighted:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 sm:min-h-9",
|
|
2552
|
+
className
|
|
2553
|
+
),
|
|
2554
|
+
...props
|
|
2555
|
+
}
|
|
2556
|
+
));
|
|
2557
|
+
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
|
|
2558
|
+
var buttonClass = "inline-flex min-h-11 items-center justify-center gap-2 rounded-md px-4 text-[14px] transition-colors disabled:cursor-not-allowed disabled:opacity-50 sm:min-h-9";
|
|
2559
|
+
var secondaryClass = cn(buttonClass, "border border-border text-foreground hover:bg-muted");
|
|
2560
|
+
var primaryClass = cn(
|
|
2561
|
+
buttonClass,
|
|
2562
|
+
"bg-primary font-medium text-primary-foreground hover:bg-primary/90"
|
|
2563
|
+
);
|
|
2564
|
+
var dangerClass = cn(
|
|
2565
|
+
buttonClass,
|
|
2566
|
+
"bg-destructive font-medium text-destructive-foreground hover:bg-destructive/90"
|
|
2567
|
+
);
|
|
2568
|
+
function FillWithExample({
|
|
2569
|
+
source,
|
|
2570
|
+
fields,
|
|
2571
|
+
touched,
|
|
2572
|
+
onFill,
|
|
2573
|
+
disabled,
|
|
2574
|
+
className
|
|
2575
|
+
}) {
|
|
2576
|
+
const s = useFieldStrings();
|
|
2577
|
+
const [open, setOpen] = useState(false);
|
|
2578
|
+
const [opening, setOpening] = useState(0);
|
|
2579
|
+
const [closing, setClosing] = useState(0);
|
|
2580
|
+
const [replacing, setReplacing] = useState(null);
|
|
2581
|
+
const [renaming, setRenaming] = useState(null);
|
|
2582
|
+
const [deleting, setDeleting] = useState(null);
|
|
2583
|
+
const control = useRef(null);
|
|
2584
|
+
const closeButton = useRef(null);
|
|
2585
|
+
const sheet = useRef(null);
|
|
2586
|
+
const afterControl = useRef(null);
|
|
2587
|
+
const rows = useRef(/* @__PURE__ */ new Map());
|
|
2588
|
+
const menus = useRef(/* @__PURE__ */ new Map());
|
|
2589
|
+
const afterRowDialog = useRef(null);
|
|
2590
|
+
const register = (map, id) => (element) => {
|
|
2591
|
+
map.set(id, element);
|
|
2592
|
+
return () => {
|
|
2593
|
+
if (map.get(id) === element) map.delete(id);
|
|
2594
|
+
};
|
|
2595
|
+
};
|
|
2596
|
+
const load = (cursor, signal) => source.list({ cursor, signal }).then((page) => ({ items: page.examples, nextCursor: page.nextCursor }));
|
|
2597
|
+
const probe = useSourcePages(load, source.hideWhenEmpty ? `probe-${closing}` : null);
|
|
2598
|
+
const pages = useSourcePages(load, open ? `open-${opening}` : null);
|
|
2599
|
+
const answer = probe.status === "failed" || probe.more === "failed" ? true : probe.items.length > 0 ? true : probe.empty ? false : null;
|
|
2600
|
+
const [hasExamples, setHasExamples] = useState(null);
|
|
2601
|
+
if (answer !== null && answer !== hasExamples) setHasExamples(answer);
|
|
2602
|
+
if (disabled && (open || replacing || renaming || deleting)) {
|
|
2603
|
+
if (open) setClosing((count) => count + 1);
|
|
2604
|
+
setOpen(false);
|
|
2605
|
+
setReplacing(null);
|
|
2606
|
+
setRenaming(null);
|
|
2607
|
+
setDeleting(null);
|
|
2608
|
+
}
|
|
2609
|
+
if (source.hideWhenEmpty && !open && (answer ?? hasExamples) !== true) return null;
|
|
2610
|
+
const closeList = () => {
|
|
2611
|
+
if (source.hideWhenEmpty && pages.status === "ready") {
|
|
2612
|
+
if (pages.items.length > 0) setHasExamples(true);
|
|
2613
|
+
else if (pages.empty) {
|
|
2614
|
+
afterControl.current = followingFocusable(control.current, sheet.current);
|
|
2615
|
+
setHasExamples(false);
|
|
2616
|
+
}
|
|
2617
|
+
}
|
|
2618
|
+
setOpen(false);
|
|
2619
|
+
setClosing((count) => count + 1);
|
|
2620
|
+
};
|
|
2621
|
+
const fill = (example) => {
|
|
2622
|
+
if (disabled) return;
|
|
2623
|
+
onFill(runValuesFromInputs(example.inputs, fields), example);
|
|
2624
|
+
setReplacing(null);
|
|
2625
|
+
closeList();
|
|
2626
|
+
};
|
|
2627
|
+
const choose = (example) => {
|
|
2628
|
+
if (touched) setReplacing(example);
|
|
2629
|
+
else fill(example);
|
|
2630
|
+
};
|
|
2631
|
+
const manages = source.rename !== void 0 || source.delete !== void 0;
|
|
2632
|
+
const status = pages.status === "idle" || pages.status === "loading" ? s.examplesLoading : pages.status === "failed" ? s.examplesFailed : pages.more === "failed" ? s.loadMoreFailed : pages.items.length > 0 ? s.examplesShown(pages.items.length) : pages.empty ? s.examplesNone : s.examplesLoading;
|
|
2633
|
+
const returnFromRowDialog = () => {
|
|
2634
|
+
const next = afterRowDialog.current;
|
|
2635
|
+
afterRowDialog.current = null;
|
|
2636
|
+
if (!next) return null;
|
|
2637
|
+
const target = next.id === void 0 ? void 0 : (next.to === "menu" ? menus : rows).current.get(next.id);
|
|
2638
|
+
return target?.isConnected ? target : closeButton.current;
|
|
2639
|
+
};
|
|
2640
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2641
|
+
/* @__PURE__ */ jsxs(
|
|
2642
|
+
"button",
|
|
2643
|
+
{
|
|
2644
|
+
ref: control,
|
|
2645
|
+
type: "button",
|
|
2646
|
+
disabled,
|
|
2647
|
+
"aria-haspopup": "dialog",
|
|
2648
|
+
onClick: () => {
|
|
2649
|
+
setOpening((count) => count + 1);
|
|
2650
|
+
setOpen(true);
|
|
2651
|
+
},
|
|
2652
|
+
className: cn(secondaryClass, className),
|
|
2653
|
+
children: [
|
|
2654
|
+
/* @__PURE__ */ jsx(Sparkles, { className: "size-4 text-muted-foreground", "aria-hidden": "true" }),
|
|
2655
|
+
s.fillWithExample
|
|
2656
|
+
]
|
|
2657
|
+
}
|
|
2658
|
+
),
|
|
2659
|
+
/* @__PURE__ */ jsx(
|
|
2660
|
+
Dialog,
|
|
2661
|
+
{
|
|
2662
|
+
open,
|
|
2663
|
+
onOpenChange: (next) => {
|
|
2664
|
+
if (next) setOpen(true);
|
|
2665
|
+
else closeList();
|
|
2666
|
+
},
|
|
2667
|
+
children: open && /* @__PURE__ */ jsxs(
|
|
2668
|
+
DialogContent,
|
|
2669
|
+
{
|
|
2670
|
+
layout: "sheet",
|
|
2671
|
+
className: "top-auto max-h-[calc(100dvh-1.5rem)]",
|
|
2672
|
+
ref: sheet,
|
|
2673
|
+
returnFocus: () => control.current ?? afterControl.current,
|
|
2674
|
+
onClick: (event) => event.stopPropagation(),
|
|
2675
|
+
children: [
|
|
2676
|
+
/* @__PURE__ */ jsx("div", { className: "px-4 pt-4 pb-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
|
|
2677
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 space-y-1 pt-1", children: [
|
|
2678
|
+
/* @__PURE__ */ jsx(DialogTitle, { className: "text-[20px]", children: s.examplesTitle }),
|
|
2679
|
+
/* @__PURE__ */ jsx(DialogDescription, { children: s.examplesHint })
|
|
2680
|
+
] }),
|
|
2681
|
+
/* @__PURE__ */ jsx(
|
|
2682
|
+
DialogClose,
|
|
2683
|
+
{
|
|
2684
|
+
ref: closeButton,
|
|
2685
|
+
"aria-label": s.close,
|
|
2686
|
+
className: "flex size-11 shrink-0 items-center justify-center rounded-full border border-border text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
2687
|
+
children: /* @__PURE__ */ jsx(X, { className: "size-5", "aria-hidden": "true" })
|
|
2688
|
+
}
|
|
2689
|
+
)
|
|
2690
|
+
] }) }),
|
|
2691
|
+
/* @__PURE__ */ jsx("p", { role: "status", className: "sr-only", children: status }),
|
|
2692
|
+
/* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-y-auto border-t border-border pb-[env(safe-area-inset-bottom)]", children: pages.status === "idle" || pages.status === "loading" ? /* @__PURE__ */ jsx(DimRows, { count: 3 }) : pages.status === "failed" ? /* @__PURE__ */ jsx(ListMessage, { text: s.examplesFailed, children: /* @__PURE__ */ jsx(ListAction, { onClick: pages.retry, children: s.tryAgain }) }) : pages.empty ? /* @__PURE__ */ jsx(ListMessage, { text: s.examplesNone }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2693
|
+
pages.items.length > 0 && /* @__PURE__ */ jsx("ul", { className: "divide-y divide-border", children: pages.items.map((example) => /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-1 pr-2", children: [
|
|
2694
|
+
/* @__PURE__ */ jsx(
|
|
2695
|
+
"button",
|
|
2696
|
+
{
|
|
2697
|
+
ref: register(rows.current, example.id),
|
|
2698
|
+
type: "button",
|
|
2699
|
+
onClick: () => choose(example),
|
|
2700
|
+
className: "flex min-h-16 min-w-0 flex-1 items-center px-4 py-2.5 text-left transition-colors hover:bg-muted/60 focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-ring",
|
|
2701
|
+
children: /* @__PURE__ */ jsx("span", { className: "truncate text-[16px] font-medium text-foreground", children: example.name })
|
|
2702
|
+
}
|
|
2703
|
+
),
|
|
2704
|
+
manages && // Not modal, so the question a menu item opens takes
|
|
2705
|
+
// the focus without the menu fighting it for the page.
|
|
2706
|
+
/* @__PURE__ */ jsxs(DropdownMenu, { modal: false, children: [
|
|
2707
|
+
/* @__PURE__ */ jsx(
|
|
2708
|
+
DropdownMenuTrigger,
|
|
2709
|
+
{
|
|
2710
|
+
ref: register(menus.current, example.id),
|
|
2711
|
+
"aria-label": s.exampleActions(example.name),
|
|
2712
|
+
className: "flex size-11 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
2713
|
+
children: /* @__PURE__ */ jsx(MoreHorizontal, { className: "size-5", "aria-hidden": "true" })
|
|
2714
|
+
}
|
|
2715
|
+
),
|
|
2716
|
+
/* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", children: [
|
|
2717
|
+
source.rename && /* @__PURE__ */ jsx(DropdownMenuItem, { onSelect: () => setRenaming(example), children: s.renameExample }),
|
|
2718
|
+
source.delete && /* @__PURE__ */ jsx(
|
|
2719
|
+
DropdownMenuItem,
|
|
2720
|
+
{
|
|
2721
|
+
onSelect: () => setDeleting(example),
|
|
2722
|
+
className: "text-destructive data-highlighted:text-destructive",
|
|
2723
|
+
children: s.deleteExample
|
|
2724
|
+
}
|
|
2725
|
+
)
|
|
2726
|
+
] })
|
|
2727
|
+
] })
|
|
2728
|
+
] }, example.id)) }),
|
|
2729
|
+
/* @__PURE__ */ jsx(MoreFooter, { pages })
|
|
2730
|
+
] }) })
|
|
2731
|
+
]
|
|
2732
|
+
}
|
|
2733
|
+
)
|
|
2734
|
+
}
|
|
2735
|
+
),
|
|
2736
|
+
/* @__PURE__ */ jsx(
|
|
2737
|
+
AlertDialog,
|
|
2738
|
+
{
|
|
2739
|
+
open: replacing !== null,
|
|
2740
|
+
onOpenChange: (next) => {
|
|
2741
|
+
if (!next) setReplacing(null);
|
|
2742
|
+
},
|
|
2743
|
+
children: replacing && /* @__PURE__ */ jsxs(
|
|
2744
|
+
AlertDialogContent,
|
|
2745
|
+
{
|
|
2746
|
+
returnFocus: () => {
|
|
2747
|
+
const row = rows.current.get(replacing.id);
|
|
2748
|
+
return row?.isConnected ? row : control.current;
|
|
2749
|
+
},
|
|
2750
|
+
onClick: (event) => event.stopPropagation(),
|
|
2751
|
+
children: [
|
|
2752
|
+
/* @__PURE__ */ jsx(AlertDialogTitle, { children: s.replaceEnteredTitle }),
|
|
2753
|
+
/* @__PURE__ */ jsx(AlertDialogDescription, { children: s.replaceEnteredDescription(replacing.name) }),
|
|
2754
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap justify-end gap-2", children: [
|
|
2755
|
+
/* @__PURE__ */ jsx(AlertDialogCancel, { className: secondaryClass, children: s.cancel }),
|
|
2756
|
+
/* @__PURE__ */ jsx(AlertDialogAction, { className: primaryClass, onClick: () => fill(replacing), children: s.replaceEnteredConfirm })
|
|
2757
|
+
] })
|
|
2758
|
+
]
|
|
2759
|
+
}
|
|
2760
|
+
)
|
|
2761
|
+
}
|
|
2762
|
+
),
|
|
2763
|
+
source.rename && renaming && /* @__PURE__ */ jsx(
|
|
2764
|
+
RenameExampleDialog,
|
|
2765
|
+
{
|
|
2766
|
+
example: renaming,
|
|
2767
|
+
rename: source.rename,
|
|
2768
|
+
returnFocus: returnFromRowDialog,
|
|
2769
|
+
onDone: (renamed) => {
|
|
2770
|
+
pages.updateItems(
|
|
2771
|
+
(items) => items.map((item) => item.id === renaming.id ? renamed : item)
|
|
2772
|
+
);
|
|
2773
|
+
afterRowDialog.current = { id: renamed.id, to: "menu" };
|
|
2774
|
+
setRenaming(null);
|
|
2775
|
+
},
|
|
2776
|
+
onCancel: () => {
|
|
2777
|
+
afterRowDialog.current = { id: renaming.id, to: "menu" };
|
|
2778
|
+
setRenaming(null);
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2781
|
+
),
|
|
2782
|
+
source.delete && deleting && /* @__PURE__ */ jsx(
|
|
2783
|
+
DeleteExampleDialog,
|
|
2784
|
+
{
|
|
2785
|
+
example: deleting,
|
|
2786
|
+
remove: source.delete,
|
|
2787
|
+
returnFocus: returnFromRowDialog,
|
|
2788
|
+
onDone: (deleted) => {
|
|
2789
|
+
const index = pages.items.findIndex((item) => item.id === deleted.id);
|
|
2790
|
+
const neighbour = pages.items[index + 1] ?? pages.items[index - 1];
|
|
2791
|
+
pages.updateItems((items) => items.filter((item) => item.id !== deleted.id));
|
|
2792
|
+
afterRowDialog.current = { id: neighbour?.id, to: "row" };
|
|
2793
|
+
setDeleting(null);
|
|
2794
|
+
},
|
|
2795
|
+
onCancel: () => {
|
|
2796
|
+
afterRowDialog.current = { id: deleting.id, to: "menu" };
|
|
2797
|
+
setDeleting(null);
|
|
2798
|
+
}
|
|
2799
|
+
}
|
|
2800
|
+
)
|
|
2801
|
+
] });
|
|
2802
|
+
}
|
|
2803
|
+
function RenameExampleDialog({
|
|
2804
|
+
example,
|
|
2805
|
+
rename,
|
|
2806
|
+
returnFocus,
|
|
2807
|
+
onDone,
|
|
2808
|
+
onCancel
|
|
2809
|
+
}) {
|
|
2810
|
+
const s = useFieldStrings();
|
|
2811
|
+
const fieldId = useId();
|
|
2812
|
+
const [name, setName] = useState(example.name);
|
|
2813
|
+
const [state, setState] = useState("idle");
|
|
2814
|
+
const trimmed = name.trim();
|
|
2815
|
+
const save = () => {
|
|
2816
|
+
if (trimmed === "" || state === "busy") return;
|
|
2817
|
+
setState("busy");
|
|
2818
|
+
let renamed;
|
|
2819
|
+
try {
|
|
2820
|
+
renamed = Promise.resolve(rename(example, trimmed));
|
|
2821
|
+
} catch (error) {
|
|
2822
|
+
renamed = Promise.reject(error);
|
|
2823
|
+
}
|
|
2824
|
+
renamed.then(
|
|
2825
|
+
(stored) => onDone(stored ?? { ...example, name: trimmed }),
|
|
2826
|
+
() => setState("failed")
|
|
2827
|
+
);
|
|
2828
|
+
};
|
|
2829
|
+
const onKeyDown = (event) => {
|
|
2830
|
+
if (event.key !== "Enter") return;
|
|
2831
|
+
event.preventDefault();
|
|
2832
|
+
save();
|
|
2833
|
+
};
|
|
2834
|
+
return /* @__PURE__ */ jsx(
|
|
2835
|
+
Dialog,
|
|
2836
|
+
{
|
|
2837
|
+
open: true,
|
|
2838
|
+
onOpenChange: (next) => {
|
|
2839
|
+
if (!next && state !== "busy") onCancel();
|
|
2840
|
+
},
|
|
2841
|
+
children: /* @__PURE__ */ jsxs(DialogContent, { returnFocus, onClick: (event) => event.stopPropagation(), children: [
|
|
2842
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: s.renameExampleTitle }),
|
|
2843
|
+
/* @__PURE__ */ jsx(DialogDescription, { className: "sr-only", children: example.name }),
|
|
2844
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
2845
|
+
/* @__PURE__ */ jsx("label", { htmlFor: fieldId, className: "text-[13px] font-medium text-foreground", children: s.exampleName }),
|
|
2846
|
+
/* @__PURE__ */ jsx(
|
|
2847
|
+
"input",
|
|
2848
|
+
{
|
|
2849
|
+
id: fieldId,
|
|
2850
|
+
type: "text",
|
|
2851
|
+
value: name,
|
|
2852
|
+
onChange: (event) => setName(event.target.value),
|
|
2853
|
+
onKeyDown,
|
|
2854
|
+
disabled: state === "busy",
|
|
2855
|
+
autoComplete: "off",
|
|
2856
|
+
className: "h-11 w-full rounded-md border border-border bg-input px-3 text-[16px] text-foreground focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-ring"
|
|
2857
|
+
}
|
|
2858
|
+
)
|
|
2859
|
+
] }),
|
|
2860
|
+
state === "failed" && /* @__PURE__ */ jsx("p", { role: "alert", className: "text-[13px] text-destructive", children: s.renameFailed }),
|
|
2861
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap justify-end gap-2", children: [
|
|
2862
|
+
/* @__PURE__ */ jsx(
|
|
2863
|
+
"button",
|
|
2864
|
+
{
|
|
2865
|
+
type: "button",
|
|
2866
|
+
onClick: onCancel,
|
|
2867
|
+
disabled: state === "busy",
|
|
2868
|
+
className: secondaryClass,
|
|
2869
|
+
children: s.cancel
|
|
2870
|
+
}
|
|
2871
|
+
),
|
|
2872
|
+
/* @__PURE__ */ jsx(
|
|
2873
|
+
"button",
|
|
2874
|
+
{
|
|
2875
|
+
type: "button",
|
|
2876
|
+
onClick: save,
|
|
2877
|
+
disabled: trimmed === "" || state === "busy",
|
|
2878
|
+
className: primaryClass,
|
|
2879
|
+
children: state === "busy" ? s.renaming : state === "failed" ? s.tryAgain : s.save
|
|
2880
|
+
}
|
|
2881
|
+
)
|
|
2882
|
+
] })
|
|
2883
|
+
] })
|
|
2884
|
+
}
|
|
2885
|
+
);
|
|
2886
|
+
}
|
|
2887
|
+
function DeleteExampleDialog({
|
|
2888
|
+
example,
|
|
2889
|
+
remove,
|
|
2890
|
+
returnFocus,
|
|
2891
|
+
onDone,
|
|
2892
|
+
onCancel
|
|
2893
|
+
}) {
|
|
2894
|
+
const s = useFieldStrings();
|
|
2895
|
+
const [state, setState] = useState("idle");
|
|
2896
|
+
const confirm = () => {
|
|
2897
|
+
if (state === "busy") return;
|
|
2898
|
+
setState("busy");
|
|
2899
|
+
let removed;
|
|
2900
|
+
try {
|
|
2901
|
+
removed = Promise.resolve(remove(example));
|
|
2902
|
+
} catch (error) {
|
|
2903
|
+
removed = Promise.reject(error);
|
|
2904
|
+
}
|
|
2905
|
+
removed.then(
|
|
2906
|
+
() => onDone(example),
|
|
2907
|
+
() => setState("failed")
|
|
2908
|
+
);
|
|
2909
|
+
};
|
|
2910
|
+
return /* @__PURE__ */ jsx(
|
|
2911
|
+
AlertDialog,
|
|
2912
|
+
{
|
|
2913
|
+
open: true,
|
|
2914
|
+
onOpenChange: (next) => {
|
|
2915
|
+
if (!next && state !== "busy") onCancel();
|
|
2916
|
+
},
|
|
2917
|
+
children: /* @__PURE__ */ jsxs(AlertDialogContent, { returnFocus, onClick: (event) => event.stopPropagation(), children: [
|
|
2918
|
+
/* @__PURE__ */ jsx(AlertDialogTitle, { children: s.deleteExampleTitle(example.name) }),
|
|
2919
|
+
/* @__PURE__ */ jsx(AlertDialogDescription, { children: s.deleteExampleDescription }),
|
|
2920
|
+
state === "failed" && /* @__PURE__ */ jsx("p", { role: "alert", className: "text-[13px] text-destructive", children: s.deleteFailed }),
|
|
2921
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap justify-end gap-2", children: [
|
|
2922
|
+
/* @__PURE__ */ jsx(AlertDialogCancel, { disabled: state === "busy", className: secondaryClass, children: s.cancel }),
|
|
2923
|
+
/* @__PURE__ */ jsx(
|
|
2924
|
+
"button",
|
|
2925
|
+
{
|
|
2926
|
+
type: "button",
|
|
2927
|
+
onClick: confirm,
|
|
2928
|
+
disabled: state === "busy",
|
|
2929
|
+
className: dangerClass,
|
|
2930
|
+
children: state === "busy" ? s.deleting : state === "failed" ? s.tryAgain : s.deleteExample
|
|
2931
|
+
}
|
|
2932
|
+
)
|
|
2933
|
+
] })
|
|
2934
|
+
] })
|
|
2935
|
+
}
|
|
2936
|
+
);
|
|
2937
|
+
}
|
|
1644
2938
|
var EMPTY_IDS = /* @__PURE__ */ new Set();
|
|
1645
2939
|
function withId(ids, id) {
|
|
1646
2940
|
if (ids.has(id)) return ids;
|
|
@@ -1668,7 +2962,9 @@ function useMethodForm({
|
|
|
1668
2962
|
prepareFields,
|
|
1669
2963
|
order,
|
|
1670
2964
|
initialValues,
|
|
1671
|
-
uploadFile
|
|
2965
|
+
uploadFile,
|
|
2966
|
+
fileSource,
|
|
2967
|
+
exampleSource
|
|
1672
2968
|
}) {
|
|
1673
2969
|
const orderKey = order ? order.join("\0") : "";
|
|
1674
2970
|
const fields = useMemo(() => {
|
|
@@ -1681,22 +2977,29 @@ function useMethodForm({
|
|
|
1681
2977
|
return initialValues ?? seedInputs(fields);
|
|
1682
2978
|
}, [initialValues, fields]);
|
|
1683
2979
|
const [edited, setEdited] = useState(null);
|
|
2980
|
+
const [given, setGiven] = useState(null);
|
|
1684
2981
|
const [uploadingIds, setUploadingIds] = useState(EMPTY_IDS);
|
|
1685
2982
|
const [failedUploadIds, setFailedUploadIds] = useState(EMPTY_IDS);
|
|
1686
2983
|
const [attempted, setAttempted] = useState(false);
|
|
2984
|
+
const [resets, setResets] = useState(0);
|
|
1687
2985
|
const pendingUploads = useRef(/* @__PURE__ */ new Map());
|
|
1688
2986
|
const uploadCounter = useRef(0);
|
|
1689
2987
|
const values = edited ?? initial;
|
|
1690
2988
|
const setValues = useCallback(
|
|
1691
|
-
(next) =>
|
|
2989
|
+
(next) => {
|
|
2990
|
+
setGiven((previous) => previous ?? initial);
|
|
2991
|
+
setEdited((previous) => typeof next === "function" ? next(previous ?? initial) : next);
|
|
2992
|
+
},
|
|
1692
2993
|
[initial]
|
|
1693
2994
|
);
|
|
1694
2995
|
const reset = useCallback((next) => {
|
|
1695
2996
|
pendingUploads.current.clear();
|
|
1696
2997
|
setEdited(next ?? null);
|
|
2998
|
+
setGiven(next ?? null);
|
|
1697
2999
|
setUploadingIds(EMPTY_IDS);
|
|
1698
3000
|
setFailedUploadIds(EMPTY_IDS);
|
|
1699
3001
|
setAttempted(false);
|
|
3002
|
+
setResets((count) => count + 1);
|
|
1700
3003
|
}, []);
|
|
1701
3004
|
const dropFile = useMemo(() => {
|
|
1702
3005
|
if (!uploadFile) return void 0;
|
|
@@ -1717,6 +3020,7 @@ function useMethodForm({
|
|
|
1717
3020
|
(stored) => {
|
|
1718
3021
|
if (!current()) return;
|
|
1719
3022
|
const value = typeof stored === "string" ? { url: stored, filename: file.name } : { url: stored.url, filename: stored.filename ?? file.name };
|
|
3023
|
+
setGiven((previous) => previous ?? initial);
|
|
1720
3024
|
setEdited((previous) => setValueAtPath(previous ?? initial, path, value));
|
|
1721
3025
|
},
|
|
1722
3026
|
() => {
|
|
@@ -1736,6 +3040,10 @@ function useMethodForm({
|
|
|
1736
3040
|
);
|
|
1737
3041
|
const uploading = uploadingIds.size > 0;
|
|
1738
3042
|
const ready = readiness.ready === readiness.total && !uploading;
|
|
3043
|
+
const touched = useMemo(
|
|
3044
|
+
() => uploading || edited !== null && given !== null && !sameRunValues(edited, given, fields),
|
|
3045
|
+
[uploading, edited, given, fields]
|
|
3046
|
+
);
|
|
1739
3047
|
const attempt = useCallback(() => {
|
|
1740
3048
|
setAttempted(true);
|
|
1741
3049
|
return ready;
|
|
@@ -1748,12 +3056,16 @@ function useMethodForm({
|
|
|
1748
3056
|
uploading,
|
|
1749
3057
|
ready,
|
|
1750
3058
|
attempted,
|
|
3059
|
+
touched,
|
|
1751
3060
|
setValues,
|
|
1752
3061
|
reset,
|
|
1753
3062
|
attempt,
|
|
3063
|
+
resets,
|
|
1754
3064
|
uploadingIds,
|
|
1755
3065
|
failedUploadIds,
|
|
1756
|
-
dropFile
|
|
3066
|
+
dropFile,
|
|
3067
|
+
fileSource,
|
|
3068
|
+
exampleSource
|
|
1757
3069
|
};
|
|
1758
3070
|
}
|
|
1759
3071
|
function MethodForm({ locale, strings, presentation, ...props }) {
|
|
@@ -1777,14 +3089,35 @@ function MethodFormFields({
|
|
|
1777
3089
|
}) {
|
|
1778
3090
|
const s = useFieldStrings();
|
|
1779
3091
|
const [showOptional, setShowOptional] = useState(false);
|
|
1780
|
-
const {
|
|
3092
|
+
const {
|
|
3093
|
+
fields,
|
|
3094
|
+
values,
|
|
3095
|
+
setValues,
|
|
3096
|
+
reset,
|
|
3097
|
+
attempted,
|
|
3098
|
+
touched,
|
|
3099
|
+
resets,
|
|
3100
|
+
uploadingIds,
|
|
3101
|
+
failedUploadIds,
|
|
3102
|
+
dropFile,
|
|
3103
|
+
fileSource,
|
|
3104
|
+
exampleSource
|
|
3105
|
+
} = form;
|
|
1781
3106
|
const uploadErrors = useMemo(
|
|
1782
3107
|
() => new Map([...failedUploadIds].map((id) => [id, s.uploadFailed])),
|
|
1783
3108
|
[failedUploadIds, s.uploadFailed]
|
|
1784
3109
|
);
|
|
1785
3110
|
const env = useMemo(
|
|
1786
|
-
() => ({
|
|
1787
|
-
|
|
3111
|
+
() => ({
|
|
3112
|
+
disabled,
|
|
3113
|
+
onDropFile: dropFile,
|
|
3114
|
+
uploadingIds,
|
|
3115
|
+
uploadErrors,
|
|
3116
|
+
allowUrl,
|
|
3117
|
+
resolveUrl,
|
|
3118
|
+
fileSource
|
|
3119
|
+
}),
|
|
3120
|
+
[disabled, dropFile, uploadingIds, uploadErrors, allowUrl, resolveUrl, fileSource]
|
|
1788
3121
|
);
|
|
1789
3122
|
const folds = (field) => {
|
|
1790
3123
|
const value = ownProp(values, field.name);
|
|
@@ -1812,6 +3145,16 @@ function MethodFormFields({
|
|
|
1812
3145
|
return isFilled(value) && !fieldFilled(field, value) ? s.incompleteField : void 0;
|
|
1813
3146
|
};
|
|
1814
3147
|
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-6", className), children: [
|
|
3148
|
+
exampleSource && /* @__PURE__ */ jsx(
|
|
3149
|
+
FillWithExample,
|
|
3150
|
+
{
|
|
3151
|
+
source: exampleSource,
|
|
3152
|
+
fields,
|
|
3153
|
+
touched,
|
|
3154
|
+
onFill: (next) => reset(next),
|
|
3155
|
+
disabled
|
|
3156
|
+
}
|
|
3157
|
+
),
|
|
1815
3158
|
visible.map((field) => /* @__PURE__ */ jsx(
|
|
1816
3159
|
FieldRenderer,
|
|
1817
3160
|
{
|
|
@@ -1822,7 +3165,7 @@ function MethodFormFields({
|
|
|
1822
3165
|
env,
|
|
1823
3166
|
onChange: (next) => setValues((previous) => ({ ...previous, [field.name]: next }))
|
|
1824
3167
|
},
|
|
1825
|
-
field.name
|
|
3168
|
+
`${field.name}:${resets}`
|
|
1826
3169
|
)),
|
|
1827
3170
|
(folded.length > 0 || structureOpen) && /* @__PURE__ */ jsx(OptionalToggle, { count: folded.length, expanded, onToggle: toggle, noun: "input" })
|
|
1828
3171
|
] });
|
|
@@ -2319,7 +3662,7 @@ function ResultAt({ segment, children }) {
|
|
|
2319
3662
|
var TooltipProvider = TooltipPrimitive.Provider;
|
|
2320
3663
|
var TooltipRoot = TooltipPrimitive.Root;
|
|
2321
3664
|
var TooltipTrigger = TooltipPrimitive.Trigger;
|
|
2322
|
-
var TooltipContent =
|
|
3665
|
+
var TooltipContent = React5.forwardRef(({ className, sideOffset = 6, ...props }, ref) => /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
2323
3666
|
TooltipPrimitive.Content,
|
|
2324
3667
|
{
|
|
2325
3668
|
ref,
|
|
@@ -3301,12 +4644,12 @@ function useResolvedMarkup(markup) {
|
|
|
3301
4644
|
}
|
|
3302
4645
|
var LEX_OPTIONS = { gfm: true, breaks: true };
|
|
3303
4646
|
function Markdown({ text, className, proseImages }) {
|
|
3304
|
-
const tokens =
|
|
4647
|
+
const tokens = React5.useMemo(() => marked.lexer(text, LEX_OPTIONS), [text]);
|
|
3305
4648
|
const fromEnv = useProseImages();
|
|
3306
4649
|
const mode = proseImages ?? fromEnv;
|
|
3307
4650
|
return /* @__PURE__ */ jsx(ProseImagesContext, { value: mode, children: /* @__PURE__ */ jsx("div", { className: cn("space-y-2 text-[13px] leading-relaxed text-foreground", className), children: /* @__PURE__ */ jsx(Blocks, { tokens }) }) });
|
|
3308
4651
|
}
|
|
3309
|
-
var ProseImagesContext =
|
|
4652
|
+
var ProseImagesContext = React5.createContext("link");
|
|
3310
4653
|
var HEADING_CLASS = {
|
|
3311
4654
|
1: "text-[16px] font-semibold",
|
|
3312
4655
|
2: "text-[14.5px] font-semibold",
|
|
@@ -3463,8 +4806,8 @@ function InlineToken({ token }) {
|
|
|
3463
4806
|
}
|
|
3464
4807
|
}
|
|
3465
4808
|
function ProseImage({ token }) {
|
|
3466
|
-
const mode =
|
|
3467
|
-
const insideLink =
|
|
4809
|
+
const mode = React5.use(ProseImagesContext);
|
|
4810
|
+
const insideLink = React5.use(InsideLinkContext);
|
|
3468
4811
|
const src = proseImageUrl(token.href);
|
|
3469
4812
|
if (!src) return /* @__PURE__ */ jsx(Fragment, { children: token.text });
|
|
3470
4813
|
if (mode === "load") {
|
|
@@ -3490,7 +4833,7 @@ function ProseImage({ token }) {
|
|
|
3490
4833
|
}
|
|
3491
4834
|
);
|
|
3492
4835
|
}
|
|
3493
|
-
var InsideLinkContext =
|
|
4836
|
+
var InsideLinkContext = React5.createContext(false);
|
|
3494
4837
|
function proseImageUrl(href) {
|
|
3495
4838
|
const url = viewableUrl(href);
|
|
3496
4839
|
return url && /^https?:/.test(url) ? url : void 0;
|
|
@@ -4854,6 +6197,6 @@ function pdfFileName(field, value, baseName) {
|
|
|
4854
6197
|
return name === void 0 ? "" : name.replace(/\.[^.]+$/, "");
|
|
4855
6198
|
}
|
|
4856
6199
|
|
|
4857
|
-
export { BooleanField, ConceptPill, DEFAULT_FIELD_STRINGS, DateField, DocumentField, EN_FIELD_STRINGS, EnumField, FIELD_STRINGS_BY_LOCALE, FR_FIELD_STRINGS, FieldDomIdProvider, FieldPresentationProvider, FieldRenderer, FieldShell, FieldStringsProvider, HtmlPreview, ImageField, JsonView, ListField, Markdown, MethodForm, NumberField, ObjectField, OptionalToggle, PdfDownloadButton, ProseField, ResultEnvProvider, ResultField, ResultRoot, SUPPORTED_LOCALES, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, StuffViewer, Switch, TextField, ToggleGroup, ToggleGroupItem, UnknownField, cn, fieldControlClass, fieldStringsFor, humanizeFieldName, renderHtmlPdf, resolveHtmlStorageUrls, saveInBrowser, useFieldDomId, useFieldPresentation, useFieldStrings, useMethodForm, useProseImages, useResolveShareUrl, useResolveUrl, useResolvedUrl };
|
|
4858
|
-
//# sourceMappingURL=chunk-
|
|
4859
|
-
//# sourceMappingURL=chunk-
|
|
6200
|
+
export { BooleanField, ConceptPill, DEFAULT_FIELD_STRINGS, DateField, DocumentField, EN_FIELD_STRINGS, EnumField, FIELD_STRINGS_BY_LOCALE, FR_FIELD_STRINGS, FieldDomIdProvider, FieldPresentationProvider, FieldRenderer, FieldShell, FieldStringsProvider, FilePicker, FilePickerEntry, FillWithExample, HtmlPreview, ImageField, JsonView, ListField, Markdown, MethodForm, NumberField, ObjectField, OptionalToggle, PdfDownloadButton, ProseField, ResultEnvProvider, ResultField, ResultRoot, SUPPORTED_LOCALES, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, StuffViewer, Switch, TextField, ToggleGroup, ToggleGroupItem, UnknownField, cn, fieldControlClass, fieldStringsFor, humanizeFieldName, renderHtmlPdf, resolveHtmlStorageUrls, saveInBrowser, useFieldDomId, useFieldPresentation, useFieldStrings, useMethodForm, useProseImages, useResolveShareUrl, useResolveUrl, useResolvedUrl };
|
|
6201
|
+
//# sourceMappingURL=chunk-CSLDIWB6.js.map
|
|
6202
|
+
//# sourceMappingURL=chunk-CSLDIWB6.js.map
|