formanitor 0.0.8 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +107 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.mjs +107 -33
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -224,6 +224,7 @@ interface FormState {
|
|
|
224
224
|
isValid: boolean;
|
|
225
225
|
isSubmitting: boolean;
|
|
226
226
|
submitAttempted?: boolean;
|
|
227
|
+
pendingUploads: number;
|
|
227
228
|
}
|
|
228
229
|
|
|
229
230
|
interface SavedState {
|
|
@@ -298,7 +299,25 @@ declare class FormStore {
|
|
|
298
299
|
transition(toState: string): void;
|
|
299
300
|
private checkEvents;
|
|
300
301
|
private emit;
|
|
302
|
+
/**
|
|
303
|
+
* Update mutable config properties (callbacks, role) without recreating
|
|
304
|
+
* the store. This allows the host app to pass fresh closures (e.g. an
|
|
305
|
+
* upload handler whose auth token was initially undefined) after the
|
|
306
|
+
* initial render.
|
|
307
|
+
*/
|
|
308
|
+
updateConfig(next: Partial<StoreConfig>): void;
|
|
301
309
|
getUploadHandler(): UploadHandler | undefined;
|
|
310
|
+
private preSubmitHandlers;
|
|
311
|
+
registerPreSubmitHandler(fieldId: string, fn: () => Promise<void>): void;
|
|
312
|
+
unregisterPreSubmitHandler(fieldId: string): void;
|
|
313
|
+
/**
|
|
314
|
+
* Runs all registered pre-submit handlers in parallel.
|
|
315
|
+
* Call this before getSerializedValuesForSubmission() to ensure any
|
|
316
|
+
* unconfirmed signatures (or similar) are uploaded first.
|
|
317
|
+
*/
|
|
318
|
+
flushPendingUploads(): Promise<void>;
|
|
319
|
+
incrementPendingUploads(): void;
|
|
320
|
+
decrementPendingUploads(): void;
|
|
302
321
|
markSubmitAttempted(): void;
|
|
303
322
|
subscribe(listener: Listener): () => void;
|
|
304
323
|
private notify;
|
|
@@ -332,6 +351,7 @@ declare function useForm(): {
|
|
|
332
351
|
hasPersistence: boolean;
|
|
333
352
|
getSerializedValues: () => FormValues;
|
|
334
353
|
markSubmitAttempted: () => void;
|
|
354
|
+
flushPendingUploads: () => Promise<void>;
|
|
335
355
|
};
|
|
336
356
|
|
|
337
357
|
declare function useField(fieldId: string): {
|
package/dist/index.d.ts
CHANGED
|
@@ -224,6 +224,7 @@ interface FormState {
|
|
|
224
224
|
isValid: boolean;
|
|
225
225
|
isSubmitting: boolean;
|
|
226
226
|
submitAttempted?: boolean;
|
|
227
|
+
pendingUploads: number;
|
|
227
228
|
}
|
|
228
229
|
|
|
229
230
|
interface SavedState {
|
|
@@ -298,7 +299,25 @@ declare class FormStore {
|
|
|
298
299
|
transition(toState: string): void;
|
|
299
300
|
private checkEvents;
|
|
300
301
|
private emit;
|
|
302
|
+
/**
|
|
303
|
+
* Update mutable config properties (callbacks, role) without recreating
|
|
304
|
+
* the store. This allows the host app to pass fresh closures (e.g. an
|
|
305
|
+
* upload handler whose auth token was initially undefined) after the
|
|
306
|
+
* initial render.
|
|
307
|
+
*/
|
|
308
|
+
updateConfig(next: Partial<StoreConfig>): void;
|
|
301
309
|
getUploadHandler(): UploadHandler | undefined;
|
|
310
|
+
private preSubmitHandlers;
|
|
311
|
+
registerPreSubmitHandler(fieldId: string, fn: () => Promise<void>): void;
|
|
312
|
+
unregisterPreSubmitHandler(fieldId: string): void;
|
|
313
|
+
/**
|
|
314
|
+
* Runs all registered pre-submit handlers in parallel.
|
|
315
|
+
* Call this before getSerializedValuesForSubmission() to ensure any
|
|
316
|
+
* unconfirmed signatures (or similar) are uploaded first.
|
|
317
|
+
*/
|
|
318
|
+
flushPendingUploads(): Promise<void>;
|
|
319
|
+
incrementPendingUploads(): void;
|
|
320
|
+
decrementPendingUploads(): void;
|
|
302
321
|
markSubmitAttempted(): void;
|
|
303
322
|
subscribe(listener: Listener): () => void;
|
|
304
323
|
private notify;
|
|
@@ -332,6 +351,7 @@ declare function useForm(): {
|
|
|
332
351
|
hasPersistence: boolean;
|
|
333
352
|
getSerializedValues: () => FormValues;
|
|
334
353
|
markSubmitAttempted: () => void;
|
|
354
|
+
flushPendingUploads: () => Promise<void>;
|
|
335
355
|
};
|
|
336
356
|
|
|
337
357
|
declare function useField(fieldId: string): {
|
package/dist/index.mjs
CHANGED
|
@@ -155,10 +155,6 @@ var NO_OP_PROVIDER = {
|
|
|
155
155
|
function applyPrefill(currentValues, fields, prefilledData = {}) {
|
|
156
156
|
const newValues = { ...currentValues };
|
|
157
157
|
fields.forEach((field) => {
|
|
158
|
-
const currentValue = newValues[field.id];
|
|
159
|
-
if (!isEmpty(currentValue)) {
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
158
|
if (field.prefill?.value !== void 0) {
|
|
163
159
|
newValues[field.id] = field.prefill.value;
|
|
164
160
|
return;
|
|
@@ -170,9 +166,6 @@ function applyPrefill(currentValues, fields, prefilledData = {}) {
|
|
|
170
166
|
});
|
|
171
167
|
return newValues;
|
|
172
168
|
}
|
|
173
|
-
function isEmpty(val) {
|
|
174
|
-
return val === void 0 || val === null || val === "";
|
|
175
|
-
}
|
|
176
169
|
|
|
177
170
|
// src/core/store.ts
|
|
178
171
|
var FormStore = class {
|
|
@@ -204,7 +197,8 @@ var FormStore = class {
|
|
|
204
197
|
workflowState: initialWorkflowState,
|
|
205
198
|
isValid: true,
|
|
206
199
|
isSubmitting: false,
|
|
207
|
-
submitAttempted: false
|
|
200
|
+
submitAttempted: false,
|
|
201
|
+
pendingUploads: 0
|
|
208
202
|
};
|
|
209
203
|
this.initializeDefaults();
|
|
210
204
|
this.evaluate();
|
|
@@ -466,9 +460,52 @@ var FormStore = class {
|
|
|
466
460
|
this.config.onEvent(event, finalPayload);
|
|
467
461
|
}
|
|
468
462
|
}
|
|
463
|
+
/**
|
|
464
|
+
* Update mutable config properties (callbacks, role) without recreating
|
|
465
|
+
* the store. This allows the host app to pass fresh closures (e.g. an
|
|
466
|
+
* upload handler whose auth token was initially undefined) after the
|
|
467
|
+
* initial render.
|
|
468
|
+
*/
|
|
469
|
+
updateConfig(next) {
|
|
470
|
+
let needsReeval = false;
|
|
471
|
+
if (next.onUpload !== void 0) this.config.onUpload = next.onUpload;
|
|
472
|
+
if (next.onEvent !== void 0) this.config.onEvent = next.onEvent;
|
|
473
|
+
if (next.role !== void 0 && next.role !== this.config.role) {
|
|
474
|
+
this.config.role = next.role;
|
|
475
|
+
needsReeval = true;
|
|
476
|
+
}
|
|
477
|
+
if (needsReeval) {
|
|
478
|
+
this.evaluate();
|
|
479
|
+
this.notify();
|
|
480
|
+
}
|
|
481
|
+
}
|
|
469
482
|
getUploadHandler() {
|
|
470
483
|
return this.config.onUpload;
|
|
471
484
|
}
|
|
485
|
+
preSubmitHandlers = /* @__PURE__ */ new Map();
|
|
486
|
+
registerPreSubmitHandler(fieldId, fn) {
|
|
487
|
+
this.preSubmitHandlers.set(fieldId, fn);
|
|
488
|
+
}
|
|
489
|
+
unregisterPreSubmitHandler(fieldId) {
|
|
490
|
+
this.preSubmitHandlers.delete(fieldId);
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Runs all registered pre-submit handlers in parallel.
|
|
494
|
+
* Call this before getSerializedValuesForSubmission() to ensure any
|
|
495
|
+
* unconfirmed signatures (or similar) are uploaded first.
|
|
496
|
+
*/
|
|
497
|
+
async flushPendingUploads() {
|
|
498
|
+
const handlers = Array.from(this.preSubmitHandlers.values());
|
|
499
|
+
await Promise.all(handlers.map((fn) => fn()));
|
|
500
|
+
}
|
|
501
|
+
incrementPendingUploads() {
|
|
502
|
+
this.state.pendingUploads = (this.state.pendingUploads ?? 0) + 1;
|
|
503
|
+
this.notify();
|
|
504
|
+
}
|
|
505
|
+
decrementPendingUploads() {
|
|
506
|
+
this.state.pendingUploads = Math.max(0, (this.state.pendingUploads ?? 0) - 1);
|
|
507
|
+
this.notify();
|
|
508
|
+
}
|
|
472
509
|
// Mark that a submit attempt has been made so UI can decide when to show errors
|
|
473
510
|
markSubmitAttempted() {
|
|
474
511
|
if (!this.state.submitAttempted) {
|
|
@@ -500,6 +537,11 @@ var FormProvider = ({ schema, config, children }) => {
|
|
|
500
537
|
if (!storeRef.current) {
|
|
501
538
|
storeRef.current = new FormStore(schema, config);
|
|
502
539
|
}
|
|
540
|
+
useEffect(() => {
|
|
541
|
+
if (storeRef.current && config) {
|
|
542
|
+
storeRef.current.updateConfig(config);
|
|
543
|
+
}
|
|
544
|
+
});
|
|
503
545
|
useEffect(() => {
|
|
504
546
|
storeRef.current?.load();
|
|
505
547
|
}, []);
|
|
@@ -530,7 +572,8 @@ function useForm() {
|
|
|
530
572
|
availableTransitions: store.getAvailableTransitions(),
|
|
531
573
|
hasPersistence: store.hasPersistence(),
|
|
532
574
|
getSerializedValues: store.getSerializedValuesForSubmission.bind(store),
|
|
533
|
-
markSubmitAttempted: store.markSubmitAttempted.bind(store)
|
|
575
|
+
markSubmitAttempted: store.markSubmitAttempted.bind(store),
|
|
576
|
+
flushPendingUploads: store.flushPendingUploads.bind(store)
|
|
534
577
|
};
|
|
535
578
|
}
|
|
536
579
|
function useField(fieldId) {
|
|
@@ -1438,6 +1481,7 @@ var ImageUploadWidget = ({ fieldId }) => {
|
|
|
1438
1481
|
}
|
|
1439
1482
|
setIsUploading(true);
|
|
1440
1483
|
setTouched();
|
|
1484
|
+
store.incrementPendingUploads();
|
|
1441
1485
|
try {
|
|
1442
1486
|
const previewUrl = URL.createObjectURL(file);
|
|
1443
1487
|
setPreview(previewUrl);
|
|
@@ -1450,6 +1494,7 @@ var ImageUploadWidget = ({ fieldId }) => {
|
|
|
1450
1494
|
setPreview(null);
|
|
1451
1495
|
} finally {
|
|
1452
1496
|
setIsUploading(false);
|
|
1497
|
+
store.decrementPendingUploads();
|
|
1453
1498
|
}
|
|
1454
1499
|
};
|
|
1455
1500
|
const handleRemove = () => {
|
|
@@ -1549,6 +1594,22 @@ var SignatureUploadWidget = ({ fieldId }) => {
|
|
|
1549
1594
|
const [hasDrawing, setHasDrawing] = useState(false);
|
|
1550
1595
|
const [isUploading, setIsUploading] = useState(false);
|
|
1551
1596
|
const [isConfirmed, setIsConfirmed] = useState(false);
|
|
1597
|
+
const [uploadError, setUploadError] = useState(null);
|
|
1598
|
+
const confirmSignatureRef = useRef(null);
|
|
1599
|
+
useEffect(() => {
|
|
1600
|
+
if (hasDrawing && !isConfirmed) {
|
|
1601
|
+
store.registerPreSubmitHandler(fieldId, async () => {
|
|
1602
|
+
if (confirmSignatureRef.current) {
|
|
1603
|
+
await confirmSignatureRef.current();
|
|
1604
|
+
}
|
|
1605
|
+
});
|
|
1606
|
+
} else {
|
|
1607
|
+
store.unregisterPreSubmitHandler(fieldId);
|
|
1608
|
+
}
|
|
1609
|
+
return () => {
|
|
1610
|
+
store.unregisterPreSubmitHandler(fieldId);
|
|
1611
|
+
};
|
|
1612
|
+
}, [hasDrawing, isConfirmed, fieldId, store]);
|
|
1552
1613
|
const showError = !!error && (touched || state.submitAttempted);
|
|
1553
1614
|
const displayUrl = useMemo(() => extractDisplayUrl(value), [value]);
|
|
1554
1615
|
const showPreview = displayUrl !== null;
|
|
@@ -1587,6 +1648,7 @@ var SignatureUploadWidget = ({ fieldId }) => {
|
|
|
1587
1648
|
if (disabled) return;
|
|
1588
1649
|
setIsDrawing(true);
|
|
1589
1650
|
setIsConfirmed(false);
|
|
1651
|
+
setUploadError(null);
|
|
1590
1652
|
setTouched();
|
|
1591
1653
|
const ctx = canvasRef.current?.getContext("2d");
|
|
1592
1654
|
if (!ctx) return;
|
|
@@ -1667,7 +1729,9 @@ var SignatureUploadWidget = ({ fieldId }) => {
|
|
|
1667
1729
|
const confirmSignature = async () => {
|
|
1668
1730
|
if (!hasDrawing) return;
|
|
1669
1731
|
setIsUploading(true);
|
|
1732
|
+
setUploadError(null);
|
|
1670
1733
|
setTouched();
|
|
1734
|
+
store.incrementPendingUploads();
|
|
1671
1735
|
try {
|
|
1672
1736
|
const svg = generateSVG();
|
|
1673
1737
|
const blob = new Blob([svg], { type: "image/svg+xml" });
|
|
@@ -1678,10 +1742,15 @@ var SignatureUploadWidget = ({ fieldId }) => {
|
|
|
1678
1742
|
setHasDrawing(false);
|
|
1679
1743
|
} catch (err) {
|
|
1680
1744
|
console.error("[SignatureUpload] Upload failed:", err);
|
|
1745
|
+
setUploadError(
|
|
1746
|
+
err instanceof Error ? err.message : "Signature upload failed. Please try again."
|
|
1747
|
+
);
|
|
1681
1748
|
} finally {
|
|
1682
1749
|
setIsUploading(false);
|
|
1750
|
+
store.decrementPendingUploads();
|
|
1683
1751
|
}
|
|
1684
1752
|
};
|
|
1753
|
+
confirmSignatureRef.current = confirmSignature;
|
|
1685
1754
|
const canClear = showPreview ? !disabled : hasDrawing || isConfirmed;
|
|
1686
1755
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
1687
1756
|
/* @__PURE__ */ jsxs(Label, { children: [
|
|
@@ -1749,19 +1818,22 @@ var SignatureUploadWidget = ({ fieldId }) => {
|
|
|
1749
1818
|
isConfirmed ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-green-600", children: [
|
|
1750
1819
|
/* @__PURE__ */ jsx(Check, { className: "h-4 w-4" }),
|
|
1751
1820
|
/* @__PURE__ */ jsx("span", { children: "Signature saved" })
|
|
1752
|
-
] }) : /* @__PURE__ */ jsxs(
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1821
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1822
|
+
/* @__PURE__ */ jsxs(
|
|
1823
|
+
Button,
|
|
1824
|
+
{
|
|
1825
|
+
type: "button",
|
|
1826
|
+
onClick: confirmSignature,
|
|
1827
|
+
disabled: !hasDrawing || isUploading,
|
|
1828
|
+
className: "text-xs",
|
|
1829
|
+
children: [
|
|
1830
|
+
/* @__PURE__ */ jsx(Check, { className: "h-4 w-4 mr-1" }),
|
|
1831
|
+
isUploading ? "Saving\u2026" : "Confirm"
|
|
1832
|
+
]
|
|
1833
|
+
}
|
|
1834
|
+
),
|
|
1835
|
+
uploadError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500 mt-1", children: uploadError })
|
|
1836
|
+
] })
|
|
1765
1837
|
] })
|
|
1766
1838
|
),
|
|
1767
1839
|
showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error })
|
|
@@ -2341,10 +2413,10 @@ var ReadOnlySelect = ({ fieldDef, value }) => {
|
|
|
2341
2413
|
return String(opt.value) === String(value) || opt.value === value;
|
|
2342
2414
|
});
|
|
2343
2415
|
const displayValue = selectedOption ? selectedOption.label : value ?? "";
|
|
2344
|
-
const
|
|
2416
|
+
const isEmpty = !value && value !== 0;
|
|
2345
2417
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
2346
2418
|
/* @__PURE__ */ jsx(Label, { className: "text-sm font-medium text-gray-700", children: fieldDef.label }),
|
|
2347
|
-
/* @__PURE__ */ jsx("div", { className: "text-gray-900 border border-gray-200 rounded-md p-3 bg-gray-50 min-h-[2.5rem] flex items-center", children: loading ? /* @__PURE__ */ jsx("span", { className: "text-gray-400 italic", children: "Loading..." }) :
|
|
2419
|
+
/* @__PURE__ */ jsx("div", { className: "text-gray-900 border border-gray-200 rounded-md p-3 bg-gray-50 min-h-[2.5rem] flex items-center", children: loading ? /* @__PURE__ */ jsx("span", { className: "text-gray-400 italic", children: "Loading..." }) : isEmpty ? /* @__PURE__ */ jsx("span", { className: "text-gray-400 italic", children: "No value" }) : displayValue })
|
|
2348
2420
|
] });
|
|
2349
2421
|
};
|
|
2350
2422
|
var ReadOnlyMultiSelect = ({ fieldDef, value }) => {
|
|
@@ -2368,10 +2440,10 @@ var ReadOnlyMultiSelect = ({ fieldDef, value }) => {
|
|
|
2368
2440
|
});
|
|
2369
2441
|
return option ? option.label : String(val);
|
|
2370
2442
|
}).filter(Boolean);
|
|
2371
|
-
const
|
|
2443
|
+
const isEmpty = selectedLabels.length === 0;
|
|
2372
2444
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
2373
2445
|
/* @__PURE__ */ jsx(Label, { className: "text-sm font-medium text-gray-700", children: fieldDef.label }),
|
|
2374
|
-
/* @__PURE__ */ jsx("div", { className: "text-gray-900 border border-gray-200 rounded-md p-3 bg-gray-50 min-h-[2.5rem]", children: loading ? /* @__PURE__ */ jsx("span", { className: "text-gray-400 italic", children: "Loading..." }) :
|
|
2446
|
+
/* @__PURE__ */ jsx("div", { className: "text-gray-900 border border-gray-200 rounded-md p-3 bg-gray-50 min-h-[2.5rem]", children: loading ? /* @__PURE__ */ jsx("span", { className: "text-gray-400 italic", children: "Loading..." }) : isEmpty ? /* @__PURE__ */ jsx("span", { className: "text-gray-400 italic", children: "No values selected" }) : /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: selectedLabels.map((label, idx) => /* @__PURE__ */ jsx(
|
|
2375
2447
|
"span",
|
|
2376
2448
|
{
|
|
2377
2449
|
className: "inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800",
|
|
@@ -2574,10 +2646,10 @@ var ReadOnlyRadio = ({ fieldDef, value }) => {
|
|
|
2574
2646
|
(opt) => String(opt.value) === String(value) || opt.value === value
|
|
2575
2647
|
);
|
|
2576
2648
|
const displayValue = selectedOption ? selectedOption.label : value ?? "";
|
|
2577
|
-
const
|
|
2649
|
+
const isEmpty = value == null || value === "";
|
|
2578
2650
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
2579
2651
|
/* @__PURE__ */ jsx(Label, { className: "text-sm font-medium text-gray-700", children: fieldDef.label }),
|
|
2580
|
-
/* @__PURE__ */ jsx("div", { className: "text-gray-900 border border-gray-200 rounded-md p-3 bg-gray-50 min-h-[2.5rem] flex items-center", children: loading ? /* @__PURE__ */ jsx("span", { className: "text-gray-400 italic", children: "Loading..." }) :
|
|
2652
|
+
/* @__PURE__ */ jsx("div", { className: "text-gray-900 border border-gray-200 rounded-md p-3 bg-gray-50 min-h-[2.5rem] flex items-center", children: loading ? /* @__PURE__ */ jsx("span", { className: "text-gray-400 italic", children: "Loading..." }) : isEmpty ? /* @__PURE__ */ jsx("span", { className: "text-gray-400 italic", children: "No value" }) : displayValue })
|
|
2581
2653
|
] });
|
|
2582
2654
|
};
|
|
2583
2655
|
function isOptionSelected2(selected, optValue) {
|
|
@@ -2747,6 +2819,7 @@ var FormControls = ({
|
|
|
2747
2819
|
onSubmit
|
|
2748
2820
|
}) => {
|
|
2749
2821
|
const { state, availableTransitions, submit, transition, hasPersistence, markSubmitAttempted } = useForm();
|
|
2822
|
+
const hasUploadsInFlight = (state.pendingUploads ?? 0) > 0;
|
|
2750
2823
|
const draftAvailable = onSaveDraft || hasPersistence && submit;
|
|
2751
2824
|
const submitAvailable = onSubmit || availableTransitions.length > 0 && transition;
|
|
2752
2825
|
if (!draftAvailable && !submitAvailable) {
|
|
@@ -2767,7 +2840,8 @@ var FormControls = ({
|
|
|
2767
2840
|
onClick: onSaveDraft || submit,
|
|
2768
2841
|
variant: "outline",
|
|
2769
2842
|
size: "sm",
|
|
2770
|
-
|
|
2843
|
+
disabled: hasUploadsInFlight,
|
|
2844
|
+
children: hasUploadsInFlight ? "Upload in progress\u2026" : "Save Draft"
|
|
2771
2845
|
}
|
|
2772
2846
|
),
|
|
2773
2847
|
submitAvailable && /* @__PURE__ */ jsx(Fragment, { children: availableTransitions.length > 0 ? availableTransitions.map((t) => /* @__PURE__ */ jsx(
|
|
@@ -2781,9 +2855,9 @@ var FormControls = ({
|
|
|
2781
2855
|
transition(t.to);
|
|
2782
2856
|
}
|
|
2783
2857
|
},
|
|
2784
|
-
disabled: !state.isValid,
|
|
2858
|
+
disabled: !state.isValid || hasUploadsInFlight,
|
|
2785
2859
|
size: "sm",
|
|
2786
|
-
children: availableTransitions.length > 1 ? `Submit to ${t.to}` : "Submit"
|
|
2860
|
+
children: hasUploadsInFlight ? "Upload in progress\u2026" : availableTransitions.length > 1 ? `Submit to ${t.to}` : "Submit"
|
|
2787
2861
|
},
|
|
2788
2862
|
t.to
|
|
2789
2863
|
)) : onSubmit ? /* @__PURE__ */ jsx(
|
|
@@ -2793,9 +2867,9 @@ var FormControls = ({
|
|
|
2793
2867
|
markSubmitAttempted();
|
|
2794
2868
|
onSubmit(state.workflowState || "submit");
|
|
2795
2869
|
},
|
|
2796
|
-
disabled: !state.isValid,
|
|
2870
|
+
disabled: !state.isValid || hasUploadsInFlight,
|
|
2797
2871
|
size: "sm",
|
|
2798
|
-
children: "Submit"
|
|
2872
|
+
children: hasUploadsInFlight ? "Upload in progress\u2026" : "Submit"
|
|
2799
2873
|
}
|
|
2800
2874
|
) : null })
|
|
2801
2875
|
] })
|