formanitor 0.0.9 → 0.0.11
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 +127 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.mjs +127 -21
- 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 {
|
|
@@ -243,12 +244,14 @@ interface PersistenceProvider {
|
|
|
243
244
|
type Listener = (state: FormState) => void;
|
|
244
245
|
type EventListener = (event: string, payload?: any) => void;
|
|
245
246
|
type UploadHandler = (file: File | Blob, filename: string) => Promise<string>;
|
|
247
|
+
type DraftChangeHandler = (payload: SavedState) => void | Promise<void>;
|
|
246
248
|
interface StoreConfig {
|
|
247
249
|
persistence?: PersistenceProvider;
|
|
248
250
|
prefillData?: Record<string, any>;
|
|
249
251
|
role?: string;
|
|
250
252
|
onEvent?: EventListener;
|
|
251
253
|
onUpload?: UploadHandler;
|
|
254
|
+
onDraftChange?: DraftChangeHandler;
|
|
252
255
|
}
|
|
253
256
|
declare class FormStore {
|
|
254
257
|
private state;
|
|
@@ -259,6 +262,7 @@ declare class FormStore {
|
|
|
259
262
|
private prefillData;
|
|
260
263
|
private config;
|
|
261
264
|
private saveTimeout;
|
|
265
|
+
private draftCallbackTimeout;
|
|
262
266
|
constructor(schema: FormDef, config?: StoreConfig);
|
|
263
267
|
private initializeDefaults;
|
|
264
268
|
getState(): FormState;
|
|
@@ -277,6 +281,7 @@ declare class FormStore {
|
|
|
277
281
|
setRole(role: string): void;
|
|
278
282
|
load(): Promise<void>;
|
|
279
283
|
private scheduleSave;
|
|
284
|
+
private scheduleDraftCallback;
|
|
280
285
|
save(): Promise<void>;
|
|
281
286
|
/**
|
|
282
287
|
* Prepare values for outbound submission to the backend.
|
|
@@ -298,7 +303,25 @@ declare class FormStore {
|
|
|
298
303
|
transition(toState: string): void;
|
|
299
304
|
private checkEvents;
|
|
300
305
|
private emit;
|
|
306
|
+
/**
|
|
307
|
+
* Update mutable config properties (callbacks, role) without recreating
|
|
308
|
+
* the store. This allows the host app to pass fresh closures (e.g. an
|
|
309
|
+
* upload handler whose auth token was initially undefined) after the
|
|
310
|
+
* initial render.
|
|
311
|
+
*/
|
|
312
|
+
updateConfig(next: Partial<StoreConfig>): void;
|
|
301
313
|
getUploadHandler(): UploadHandler | undefined;
|
|
314
|
+
private preSubmitHandlers;
|
|
315
|
+
registerPreSubmitHandler(fieldId: string, fn: () => Promise<void>): void;
|
|
316
|
+
unregisterPreSubmitHandler(fieldId: string): void;
|
|
317
|
+
/**
|
|
318
|
+
* Runs all registered pre-submit handlers in parallel.
|
|
319
|
+
* Call this before getSerializedValuesForSubmission() to ensure any
|
|
320
|
+
* unconfirmed signatures (or similar) are uploaded first.
|
|
321
|
+
*/
|
|
322
|
+
flushPendingUploads(): Promise<void>;
|
|
323
|
+
incrementPendingUploads(): void;
|
|
324
|
+
decrementPendingUploads(): void;
|
|
302
325
|
markSubmitAttempted(): void;
|
|
303
326
|
subscribe(listener: Listener): () => void;
|
|
304
327
|
private notify;
|
|
@@ -332,6 +355,7 @@ declare function useForm(): {
|
|
|
332
355
|
hasPersistence: boolean;
|
|
333
356
|
getSerializedValues: () => FormValues;
|
|
334
357
|
markSubmitAttempted: () => void;
|
|
358
|
+
flushPendingUploads: () => Promise<void>;
|
|
335
359
|
};
|
|
336
360
|
|
|
337
361
|
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 {
|
|
@@ -243,12 +244,14 @@ interface PersistenceProvider {
|
|
|
243
244
|
type Listener = (state: FormState) => void;
|
|
244
245
|
type EventListener = (event: string, payload?: any) => void;
|
|
245
246
|
type UploadHandler = (file: File | Blob, filename: string) => Promise<string>;
|
|
247
|
+
type DraftChangeHandler = (payload: SavedState) => void | Promise<void>;
|
|
246
248
|
interface StoreConfig {
|
|
247
249
|
persistence?: PersistenceProvider;
|
|
248
250
|
prefillData?: Record<string, any>;
|
|
249
251
|
role?: string;
|
|
250
252
|
onEvent?: EventListener;
|
|
251
253
|
onUpload?: UploadHandler;
|
|
254
|
+
onDraftChange?: DraftChangeHandler;
|
|
252
255
|
}
|
|
253
256
|
declare class FormStore {
|
|
254
257
|
private state;
|
|
@@ -259,6 +262,7 @@ declare class FormStore {
|
|
|
259
262
|
private prefillData;
|
|
260
263
|
private config;
|
|
261
264
|
private saveTimeout;
|
|
265
|
+
private draftCallbackTimeout;
|
|
262
266
|
constructor(schema: FormDef, config?: StoreConfig);
|
|
263
267
|
private initializeDefaults;
|
|
264
268
|
getState(): FormState;
|
|
@@ -277,6 +281,7 @@ declare class FormStore {
|
|
|
277
281
|
setRole(role: string): void;
|
|
278
282
|
load(): Promise<void>;
|
|
279
283
|
private scheduleSave;
|
|
284
|
+
private scheduleDraftCallback;
|
|
280
285
|
save(): Promise<void>;
|
|
281
286
|
/**
|
|
282
287
|
* Prepare values for outbound submission to the backend.
|
|
@@ -298,7 +303,25 @@ declare class FormStore {
|
|
|
298
303
|
transition(toState: string): void;
|
|
299
304
|
private checkEvents;
|
|
300
305
|
private emit;
|
|
306
|
+
/**
|
|
307
|
+
* Update mutable config properties (callbacks, role) without recreating
|
|
308
|
+
* the store. This allows the host app to pass fresh closures (e.g. an
|
|
309
|
+
* upload handler whose auth token was initially undefined) after the
|
|
310
|
+
* initial render.
|
|
311
|
+
*/
|
|
312
|
+
updateConfig(next: Partial<StoreConfig>): void;
|
|
301
313
|
getUploadHandler(): UploadHandler | undefined;
|
|
314
|
+
private preSubmitHandlers;
|
|
315
|
+
registerPreSubmitHandler(fieldId: string, fn: () => Promise<void>): void;
|
|
316
|
+
unregisterPreSubmitHandler(fieldId: string): void;
|
|
317
|
+
/**
|
|
318
|
+
* Runs all registered pre-submit handlers in parallel.
|
|
319
|
+
* Call this before getSerializedValuesForSubmission() to ensure any
|
|
320
|
+
* unconfirmed signatures (or similar) are uploaded first.
|
|
321
|
+
*/
|
|
322
|
+
flushPendingUploads(): Promise<void>;
|
|
323
|
+
incrementPendingUploads(): void;
|
|
324
|
+
decrementPendingUploads(): void;
|
|
302
325
|
markSubmitAttempted(): void;
|
|
303
326
|
subscribe(listener: Listener): () => void;
|
|
304
327
|
private notify;
|
|
@@ -332,6 +355,7 @@ declare function useForm(): {
|
|
|
332
355
|
hasPersistence: boolean;
|
|
333
356
|
getSerializedValues: () => FormValues;
|
|
334
357
|
markSubmitAttempted: () => void;
|
|
358
|
+
flushPendingUploads: () => Promise<void>;
|
|
335
359
|
};
|
|
336
360
|
|
|
337
361
|
declare function useField(fieldId: string): {
|
package/dist/index.mjs
CHANGED
|
@@ -178,6 +178,7 @@ var FormStore = class {
|
|
|
178
178
|
config;
|
|
179
179
|
// Cache for debounce
|
|
180
180
|
saveTimeout = null;
|
|
181
|
+
draftCallbackTimeout = null;
|
|
181
182
|
constructor(schema, config = {}) {
|
|
182
183
|
this.schema = schema;
|
|
183
184
|
this.config = config;
|
|
@@ -197,7 +198,8 @@ var FormStore = class {
|
|
|
197
198
|
workflowState: initialWorkflowState,
|
|
198
199
|
isValid: true,
|
|
199
200
|
isSubmitting: false,
|
|
200
|
-
submitAttempted: false
|
|
201
|
+
submitAttempted: false,
|
|
202
|
+
pendingUploads: 0
|
|
201
203
|
};
|
|
202
204
|
this.initializeDefaults();
|
|
203
205
|
this.evaluate();
|
|
@@ -246,7 +248,10 @@ var FormStore = class {
|
|
|
246
248
|
this.checkEvents(fieldId, "onValueChange", value);
|
|
247
249
|
this.evaluate();
|
|
248
250
|
this.notify();
|
|
249
|
-
this.
|
|
251
|
+
this.scheduleDraftCallback();
|
|
252
|
+
if (!this.config.onDraftChange) {
|
|
253
|
+
this.scheduleSave();
|
|
254
|
+
}
|
|
250
255
|
}
|
|
251
256
|
setTouched(fieldId) {
|
|
252
257
|
if (this.state.touched[fieldId]) return;
|
|
@@ -282,6 +287,26 @@ var FormStore = class {
|
|
|
282
287
|
this.save();
|
|
283
288
|
}, 1e3);
|
|
284
289
|
}
|
|
290
|
+
scheduleDraftCallback() {
|
|
291
|
+
if (!this.config.onDraftChange) return;
|
|
292
|
+
if (this.draftCallbackTimeout) {
|
|
293
|
+
clearTimeout(this.draftCallbackTimeout);
|
|
294
|
+
}
|
|
295
|
+
this.draftCallbackTimeout = setTimeout(() => {
|
|
296
|
+
const payload = {
|
|
297
|
+
// For consumer callbacks, send values in the same
|
|
298
|
+
// serialized shape used for outbound submissions so
|
|
299
|
+
// media/signature fields are wrapped consistently.
|
|
300
|
+
values: this.serializeValuesForSubmission(this.state.values),
|
|
301
|
+
meta: {
|
|
302
|
+
updatedAt: Date.now(),
|
|
303
|
+
workflowState: this.state.workflowState,
|
|
304
|
+
version: this.schema.version
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
this.config.onDraftChange?.(payload);
|
|
308
|
+
}, 2500);
|
|
309
|
+
}
|
|
285
310
|
async save() {
|
|
286
311
|
const payload = {
|
|
287
312
|
values: this.state.values,
|
|
@@ -459,9 +484,53 @@ var FormStore = class {
|
|
|
459
484
|
this.config.onEvent(event, finalPayload);
|
|
460
485
|
}
|
|
461
486
|
}
|
|
487
|
+
/**
|
|
488
|
+
* Update mutable config properties (callbacks, role) without recreating
|
|
489
|
+
* the store. This allows the host app to pass fresh closures (e.g. an
|
|
490
|
+
* upload handler whose auth token was initially undefined) after the
|
|
491
|
+
* initial render.
|
|
492
|
+
*/
|
|
493
|
+
updateConfig(next) {
|
|
494
|
+
let needsReeval = false;
|
|
495
|
+
if (next.onUpload !== void 0) this.config.onUpload = next.onUpload;
|
|
496
|
+
if (next.onEvent !== void 0) this.config.onEvent = next.onEvent;
|
|
497
|
+
if (next.onDraftChange !== void 0) this.config.onDraftChange = next.onDraftChange;
|
|
498
|
+
if (next.role !== void 0 && next.role !== this.config.role) {
|
|
499
|
+
this.config.role = next.role;
|
|
500
|
+
needsReeval = true;
|
|
501
|
+
}
|
|
502
|
+
if (needsReeval) {
|
|
503
|
+
this.evaluate();
|
|
504
|
+
this.notify();
|
|
505
|
+
}
|
|
506
|
+
}
|
|
462
507
|
getUploadHandler() {
|
|
463
508
|
return this.config.onUpload;
|
|
464
509
|
}
|
|
510
|
+
preSubmitHandlers = /* @__PURE__ */ new Map();
|
|
511
|
+
registerPreSubmitHandler(fieldId, fn) {
|
|
512
|
+
this.preSubmitHandlers.set(fieldId, fn);
|
|
513
|
+
}
|
|
514
|
+
unregisterPreSubmitHandler(fieldId) {
|
|
515
|
+
this.preSubmitHandlers.delete(fieldId);
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Runs all registered pre-submit handlers in parallel.
|
|
519
|
+
* Call this before getSerializedValuesForSubmission() to ensure any
|
|
520
|
+
* unconfirmed signatures (or similar) are uploaded first.
|
|
521
|
+
*/
|
|
522
|
+
async flushPendingUploads() {
|
|
523
|
+
const handlers = Array.from(this.preSubmitHandlers.values());
|
|
524
|
+
await Promise.all(handlers.map((fn) => fn()));
|
|
525
|
+
}
|
|
526
|
+
incrementPendingUploads() {
|
|
527
|
+
this.state.pendingUploads = (this.state.pendingUploads ?? 0) + 1;
|
|
528
|
+
this.notify();
|
|
529
|
+
}
|
|
530
|
+
decrementPendingUploads() {
|
|
531
|
+
this.state.pendingUploads = Math.max(0, (this.state.pendingUploads ?? 0) - 1);
|
|
532
|
+
this.notify();
|
|
533
|
+
}
|
|
465
534
|
// Mark that a submit attempt has been made so UI can decide when to show errors
|
|
466
535
|
markSubmitAttempted() {
|
|
467
536
|
if (!this.state.submitAttempted) {
|
|
@@ -493,6 +562,11 @@ var FormProvider = ({ schema, config, children }) => {
|
|
|
493
562
|
if (!storeRef.current) {
|
|
494
563
|
storeRef.current = new FormStore(schema, config);
|
|
495
564
|
}
|
|
565
|
+
useEffect(() => {
|
|
566
|
+
if (storeRef.current && config) {
|
|
567
|
+
storeRef.current.updateConfig(config);
|
|
568
|
+
}
|
|
569
|
+
});
|
|
496
570
|
useEffect(() => {
|
|
497
571
|
storeRef.current?.load();
|
|
498
572
|
}, []);
|
|
@@ -523,7 +597,8 @@ function useForm() {
|
|
|
523
597
|
availableTransitions: store.getAvailableTransitions(),
|
|
524
598
|
hasPersistence: store.hasPersistence(),
|
|
525
599
|
getSerializedValues: store.getSerializedValuesForSubmission.bind(store),
|
|
526
|
-
markSubmitAttempted: store.markSubmitAttempted.bind(store)
|
|
600
|
+
markSubmitAttempted: store.markSubmitAttempted.bind(store),
|
|
601
|
+
flushPendingUploads: store.flushPendingUploads.bind(store)
|
|
527
602
|
};
|
|
528
603
|
}
|
|
529
604
|
function useField(fieldId) {
|
|
@@ -1431,6 +1506,7 @@ var ImageUploadWidget = ({ fieldId }) => {
|
|
|
1431
1506
|
}
|
|
1432
1507
|
setIsUploading(true);
|
|
1433
1508
|
setTouched();
|
|
1509
|
+
store.incrementPendingUploads();
|
|
1434
1510
|
try {
|
|
1435
1511
|
const previewUrl = URL.createObjectURL(file);
|
|
1436
1512
|
setPreview(previewUrl);
|
|
@@ -1443,6 +1519,7 @@ var ImageUploadWidget = ({ fieldId }) => {
|
|
|
1443
1519
|
setPreview(null);
|
|
1444
1520
|
} finally {
|
|
1445
1521
|
setIsUploading(false);
|
|
1522
|
+
store.decrementPendingUploads();
|
|
1446
1523
|
}
|
|
1447
1524
|
};
|
|
1448
1525
|
const handleRemove = () => {
|
|
@@ -1542,6 +1619,22 @@ var SignatureUploadWidget = ({ fieldId }) => {
|
|
|
1542
1619
|
const [hasDrawing, setHasDrawing] = useState(false);
|
|
1543
1620
|
const [isUploading, setIsUploading] = useState(false);
|
|
1544
1621
|
const [isConfirmed, setIsConfirmed] = useState(false);
|
|
1622
|
+
const [uploadError, setUploadError] = useState(null);
|
|
1623
|
+
const confirmSignatureRef = useRef(null);
|
|
1624
|
+
useEffect(() => {
|
|
1625
|
+
if (hasDrawing && !isConfirmed) {
|
|
1626
|
+
store.registerPreSubmitHandler(fieldId, async () => {
|
|
1627
|
+
if (confirmSignatureRef.current) {
|
|
1628
|
+
await confirmSignatureRef.current();
|
|
1629
|
+
}
|
|
1630
|
+
});
|
|
1631
|
+
} else {
|
|
1632
|
+
store.unregisterPreSubmitHandler(fieldId);
|
|
1633
|
+
}
|
|
1634
|
+
return () => {
|
|
1635
|
+
store.unregisterPreSubmitHandler(fieldId);
|
|
1636
|
+
};
|
|
1637
|
+
}, [hasDrawing, isConfirmed, fieldId, store]);
|
|
1545
1638
|
const showError = !!error && (touched || state.submitAttempted);
|
|
1546
1639
|
const displayUrl = useMemo(() => extractDisplayUrl(value), [value]);
|
|
1547
1640
|
const showPreview = displayUrl !== null;
|
|
@@ -1580,6 +1673,7 @@ var SignatureUploadWidget = ({ fieldId }) => {
|
|
|
1580
1673
|
if (disabled) return;
|
|
1581
1674
|
setIsDrawing(true);
|
|
1582
1675
|
setIsConfirmed(false);
|
|
1676
|
+
setUploadError(null);
|
|
1583
1677
|
setTouched();
|
|
1584
1678
|
const ctx = canvasRef.current?.getContext("2d");
|
|
1585
1679
|
if (!ctx) return;
|
|
@@ -1660,7 +1754,9 @@ var SignatureUploadWidget = ({ fieldId }) => {
|
|
|
1660
1754
|
const confirmSignature = async () => {
|
|
1661
1755
|
if (!hasDrawing) return;
|
|
1662
1756
|
setIsUploading(true);
|
|
1757
|
+
setUploadError(null);
|
|
1663
1758
|
setTouched();
|
|
1759
|
+
store.incrementPendingUploads();
|
|
1664
1760
|
try {
|
|
1665
1761
|
const svg = generateSVG();
|
|
1666
1762
|
const blob = new Blob([svg], { type: "image/svg+xml" });
|
|
@@ -1671,10 +1767,15 @@ var SignatureUploadWidget = ({ fieldId }) => {
|
|
|
1671
1767
|
setHasDrawing(false);
|
|
1672
1768
|
} catch (err) {
|
|
1673
1769
|
console.error("[SignatureUpload] Upload failed:", err);
|
|
1770
|
+
setUploadError(
|
|
1771
|
+
err instanceof Error ? err.message : "Signature upload failed. Please try again."
|
|
1772
|
+
);
|
|
1674
1773
|
} finally {
|
|
1675
1774
|
setIsUploading(false);
|
|
1775
|
+
store.decrementPendingUploads();
|
|
1676
1776
|
}
|
|
1677
1777
|
};
|
|
1778
|
+
confirmSignatureRef.current = confirmSignature;
|
|
1678
1779
|
const canClear = showPreview ? !disabled : hasDrawing || isConfirmed;
|
|
1679
1780
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
1680
1781
|
/* @__PURE__ */ jsxs(Label, { children: [
|
|
@@ -1742,19 +1843,22 @@ var SignatureUploadWidget = ({ fieldId }) => {
|
|
|
1742
1843
|
isConfirmed ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-green-600", children: [
|
|
1743
1844
|
/* @__PURE__ */ jsx(Check, { className: "h-4 w-4" }),
|
|
1744
1845
|
/* @__PURE__ */ jsx("span", { children: "Signature saved" })
|
|
1745
|
-
] }) : /* @__PURE__ */ jsxs(
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1846
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1847
|
+
/* @__PURE__ */ jsxs(
|
|
1848
|
+
Button,
|
|
1849
|
+
{
|
|
1850
|
+
type: "button",
|
|
1851
|
+
onClick: confirmSignature,
|
|
1852
|
+
disabled: !hasDrawing || isUploading,
|
|
1853
|
+
className: "text-xs",
|
|
1854
|
+
children: [
|
|
1855
|
+
/* @__PURE__ */ jsx(Check, { className: "h-4 w-4 mr-1" }),
|
|
1856
|
+
isUploading ? "Saving\u2026" : "Confirm"
|
|
1857
|
+
]
|
|
1858
|
+
}
|
|
1859
|
+
),
|
|
1860
|
+
uploadError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500 mt-1", children: uploadError })
|
|
1861
|
+
] })
|
|
1758
1862
|
] })
|
|
1759
1863
|
),
|
|
1760
1864
|
showError && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500", children: error })
|
|
@@ -2740,6 +2844,7 @@ var FormControls = ({
|
|
|
2740
2844
|
onSubmit
|
|
2741
2845
|
}) => {
|
|
2742
2846
|
const { state, availableTransitions, submit, transition, hasPersistence, markSubmitAttempted } = useForm();
|
|
2847
|
+
const hasUploadsInFlight = (state.pendingUploads ?? 0) > 0;
|
|
2743
2848
|
const draftAvailable = onSaveDraft || hasPersistence && submit;
|
|
2744
2849
|
const submitAvailable = onSubmit || availableTransitions.length > 0 && transition;
|
|
2745
2850
|
if (!draftAvailable && !submitAvailable) {
|
|
@@ -2760,7 +2865,8 @@ var FormControls = ({
|
|
|
2760
2865
|
onClick: onSaveDraft || submit,
|
|
2761
2866
|
variant: "outline",
|
|
2762
2867
|
size: "sm",
|
|
2763
|
-
|
|
2868
|
+
disabled: hasUploadsInFlight,
|
|
2869
|
+
children: hasUploadsInFlight ? "Upload in progress\u2026" : "Save Draft"
|
|
2764
2870
|
}
|
|
2765
2871
|
),
|
|
2766
2872
|
submitAvailable && /* @__PURE__ */ jsx(Fragment, { children: availableTransitions.length > 0 ? availableTransitions.map((t) => /* @__PURE__ */ jsx(
|
|
@@ -2774,9 +2880,9 @@ var FormControls = ({
|
|
|
2774
2880
|
transition(t.to);
|
|
2775
2881
|
}
|
|
2776
2882
|
},
|
|
2777
|
-
disabled: !state.isValid,
|
|
2883
|
+
disabled: !state.isValid || hasUploadsInFlight,
|
|
2778
2884
|
size: "sm",
|
|
2779
|
-
children: availableTransitions.length > 1 ? `Submit to ${t.to}` : "Submit"
|
|
2885
|
+
children: hasUploadsInFlight ? "Upload in progress\u2026" : availableTransitions.length > 1 ? `Submit to ${t.to}` : "Submit"
|
|
2780
2886
|
},
|
|
2781
2887
|
t.to
|
|
2782
2888
|
)) : onSubmit ? /* @__PURE__ */ jsx(
|
|
@@ -2786,9 +2892,9 @@ var FormControls = ({
|
|
|
2786
2892
|
markSubmitAttempted();
|
|
2787
2893
|
onSubmit(state.workflowState || "submit");
|
|
2788
2894
|
},
|
|
2789
|
-
disabled: !state.isValid,
|
|
2895
|
+
disabled: !state.isValid || hasUploadsInFlight,
|
|
2790
2896
|
size: "sm",
|
|
2791
|
-
children: "Submit"
|
|
2897
|
+
children: hasUploadsInFlight ? "Upload in progress\u2026" : "Submit"
|
|
2792
2898
|
}
|
|
2793
2899
|
) : null })
|
|
2794
2900
|
] })
|