@douglasneuroinformatics/libui 3.7.5 → 3.8.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.
@@ -1247,9 +1247,10 @@ type FormProps<TSchema extends z.ZodType<FormDataType>, TData extends z.TypeOf<T
1247
1247
  resetBtn?: boolean;
1248
1248
  revalidateOnBlur?: boolean;
1249
1249
  submitBtnLabel?: string;
1250
+ suspendWhileSubmitting?: boolean;
1250
1251
  validationSchema: z.ZodType<TData>;
1251
1252
  };
1252
- declare const Form: <TSchema extends z.ZodType<FormDataType>, TData extends z.TypeOf<TSchema> = z.TypeOf<TSchema>>({ additionalButtons, className, content, fieldsFooter, id, initialValues, onError, onSubmit, preventResetValuesOnReset, readOnly, resetBtn, revalidateOnBlur, submitBtnLabel, validationSchema, ...props }: FormProps<TSchema, TData>) => react_jsx_runtime.JSX.Element;
1253
+ declare const Form: <TSchema extends z.ZodType<FormDataType>, TData extends z.TypeOf<TSchema> = z.TypeOf<TSchema>>({ additionalButtons, className, content, fieldsFooter, id, initialValues, onError, onSubmit, preventResetValuesOnReset, readOnly, resetBtn, revalidateOnBlur, submitBtnLabel, suspendWhileSubmitting, validationSchema, ...props }: FormProps<TSchema, TData>) => react_jsx_runtime.JSX.Element;
1253
1254
 
1254
1255
  type HeadingProps = {
1255
1256
  children: string;
@@ -2633,12 +2633,17 @@ var NumberRecordField = ({
2633
2633
  setValue: setRecordValue,
2634
2634
  value: recordValue
2635
2635
  }) => {
2636
- const isFirstRenderRef = useRef3(true);
2636
+ const optionsRef = useRef3(options);
2637
2637
  useEffect4(() => {
2638
- if (isFirstRenderRef.current && !recordValue || !isFirstRenderRef.current) {
2638
+ if (!recordValue) {
2639
2639
  setRecordValue({});
2640
2640
  }
2641
- isFirstRenderRef.current = false;
2641
+ }, []);
2642
+ useEffect4(() => {
2643
+ if (optionsRef.current !== options) {
2644
+ setRecordValue({});
2645
+ optionsRef.current = options;
2646
+ }
2642
2647
  }, [options]);
2643
2648
  if (!recordValue) {
2644
2649
  return null;
@@ -2784,7 +2789,7 @@ var isValidDateString = (s) => /^(\d{4})-((0[1-9])|(1[0-2]))-((0[1-9])|([12])[0-
2784
2789
  var DateField = ({ disabled, error, label, name, readOnly, setValue, value }) => {
2785
2790
  const [isDatePickerOpen, setIsDatePickerOpen] = useState5(false);
2786
2791
  const [isInputFocused, setIsInputFocused] = useState5(false);
2787
- const [inputValue, setInputValue] = useState5("");
2792
+ const [inputValue, setInputValue] = useState5(value ? toBasicISOString2(value) : "");
2788
2793
  useEffect5(() => {
2789
2794
  const isSelecting = isDatePickerOpen || isInputFocused;
2790
2795
  if (isSelecting) {
@@ -3227,14 +3232,19 @@ var RecordArrayField = memo(function RecordArrayField2({
3227
3232
  setValue: setArrayValue,
3228
3233
  value: arrayValue
3229
3234
  }) {
3230
- const isFirstRenderRef = useRef4(true);
3235
+ const fieldsetRef = useRef4(fieldset);
3231
3236
  const { t } = useTranslation("libui");
3232
3237
  const createNewRecord = () => Object.fromEntries(Object.keys(fieldset).map((fieldName) => [fieldName, void 0]));
3233
3238
  useEffect8(() => {
3234
- if (isFirstRenderRef.current && !arrayValue || !isFirstRenderRef.current) {
3239
+ if (!arrayValue) {
3240
+ setArrayValue([createNewRecord()]);
3241
+ }
3242
+ }, []);
3243
+ useEffect8(() => {
3244
+ if (fieldsetRef.current !== fieldset) {
3235
3245
  setArrayValue([createNewRecord()]);
3246
+ fieldsetRef.current = fieldset;
3236
3247
  }
3237
- isFirstRenderRef.current = false;
3238
3248
  }, [fieldset]);
3239
3249
  if (!arrayValue) {
3240
3250
  return null;
@@ -3435,6 +3445,7 @@ var Form = ({
3435
3445
  resetBtn,
3436
3446
  revalidateOnBlur,
3437
3447
  submitBtnLabel,
3448
+ suspendWhileSubmitting,
3438
3449
  validationSchema,
3439
3450
  ...props
3440
3451
  }) => {
@@ -3444,6 +3455,7 @@ var Form = ({
3444
3455
  const [values, setValues] = useState8(
3445
3456
  initialValues ? getInitialValues(initialValues) : {}
3446
3457
  );
3458
+ const [isSubmitting, setIsSubmitting] = useState8(false);
3447
3459
  const handleError = (error) => {
3448
3460
  const fieldErrors = {};
3449
3461
  for (const issue of error.issues) {
@@ -3471,14 +3483,21 @@ var Form = ({
3471
3483
  }
3472
3484
  };
3473
3485
  const handleSubmit = async (event) => {
3474
- event.preventDefault();
3475
- const result = await validationSchema.safeParseAsync(values);
3476
- if (result.success) {
3477
- reset();
3478
- await onSubmit(result.data);
3479
- } else {
3480
- console.error(result.error.issues);
3481
- handleError(result.error);
3486
+ const minSubmitTime = new Promise((resolve) => setTimeout(resolve, 500));
3487
+ try {
3488
+ setIsSubmitting(true);
3489
+ event.preventDefault();
3490
+ const result = await validationSchema.safeParseAsync(values);
3491
+ if (result.success) {
3492
+ reset();
3493
+ await onSubmit(result.data);
3494
+ } else {
3495
+ console.error(result.error.issues);
3496
+ handleError(result.error);
3497
+ }
3498
+ } finally {
3499
+ await minSubmitTime;
3500
+ setIsSubmitting(false);
3482
3501
  }
3483
3502
  };
3484
3503
  const isGrouped = Array.isArray(content);
@@ -3495,6 +3514,7 @@ var Form = ({
3495
3514
  useEffect10(() => {
3496
3515
  revalidate();
3497
3516
  }, [resolvedLanguage]);
3517
+ const isSuspended = Boolean(suspendWhileSubmitting && isSubmitting);
3498
3518
  return /* @__PURE__ */ jsxs47(
3499
3519
  "form",
3500
3520
  {
@@ -3537,7 +3557,35 @@ var Form = ({
3537
3557
  fieldsFooter,
3538
3558
  /* @__PURE__ */ jsxs47("div", { className: "flex w-full gap-3", children: [
3539
3559
  additionalButtons?.left,
3540
- /* @__PURE__ */ jsx136(Button, { "aria-label": "Submit", className: "block w-full", disabled: readOnly, type: "submit", variant: "primary", children: submitBtnLabel ?? t("form.submit") }),
3560
+ /* @__PURE__ */ jsxs47(
3561
+ Button,
3562
+ {
3563
+ "aria-label": "Submit",
3564
+ className: "flex w-32 items-center justify-center gap-2",
3565
+ disabled: readOnly || isSuspended,
3566
+ type: "submit",
3567
+ variant: "primary",
3568
+ children: [
3569
+ submitBtnLabel ?? t("form.submit"),
3570
+ /* @__PURE__ */ jsx136(
3571
+ "svg",
3572
+ {
3573
+ className: cn("hidden h-4 w-4 animate-spin", isSuspended && "block"),
3574
+ fill: "none",
3575
+ height: "24",
3576
+ stroke: "currentColor",
3577
+ strokeLinecap: "round",
3578
+ strokeLinejoin: "round",
3579
+ strokeWidth: "2",
3580
+ viewBox: "0 0 24 24",
3581
+ width: "24",
3582
+ xmlns: "http://www.w3.org/2000/svg",
3583
+ children: /* @__PURE__ */ jsx136("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" })
3584
+ }
3585
+ )
3586
+ ]
3587
+ }
3588
+ ),
3541
3589
  resetBtn && /* @__PURE__ */ jsx136(
3542
3590
  Button,
3543
3591
  {