@rjsf/core 5.15.1 → 5.16.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/dist/core.umd.js CHANGED
@@ -374,6 +374,7 @@
374
374
  errorSchema,
375
375
  idSchema,
376
376
  name,
377
+ title,
377
378
  disabled = false,
378
379
  readonly = false,
379
380
  autofocus = false,
@@ -386,7 +387,7 @@
386
387
  rawErrors
387
388
  } = this.props;
388
389
  const { keyedFormData } = this.state;
389
- const title = schema.title === void 0 ? name : schema.title;
390
+ const fieldTitle = schema.title || title || name;
390
391
  const { schemaUtils, formContext } = registry;
391
392
  const uiOptions = utils.getUiOptions(uiSchema);
392
393
  const _schemaItems = isObject(schema.items) ? schema.items : {};
@@ -406,6 +407,7 @@
406
407
  key,
407
408
  index,
408
409
  name: name && `${name}-${index}`,
410
+ title: fieldTitle ? `${fieldTitle}-${index + 1}` : void 0,
409
411
  canAdd,
410
412
  canMoveUp: index > 0,
411
413
  canMoveDown: index < formData.length - 1,
@@ -429,7 +431,7 @@
429
431
  readonly,
430
432
  required,
431
433
  schema,
432
- title,
434
+ title: fieldTitle,
433
435
  formContext,
434
436
  formData,
435
437
  rawErrors,
@@ -602,6 +604,7 @@
602
604
  idSeparator = "_",
603
605
  idSchema,
604
606
  name,
607
+ title,
605
608
  disabled = false,
606
609
  readonly = false,
607
610
  autofocus = false,
@@ -613,7 +616,7 @@
613
616
  } = this.props;
614
617
  const { keyedFormData } = this.state;
615
618
  let { formData: items = [] } = this.props;
616
- const title = schema.title || name;
619
+ const fieldTitle = schema.title || title || name;
617
620
  const uiOptions = utils.getUiOptions(uiSchema);
618
621
  const { schemaUtils, formContext } = registry;
619
622
  const _schemaItems = isObject(schema.items) ? schema.items : [];
@@ -645,6 +648,7 @@
645
648
  key,
646
649
  index,
647
650
  name: name && `${name}-${index}`,
651
+ title: fieldTitle ? `${fieldTitle}-${index + 1}` : void 0,
648
652
  canAdd,
649
653
  canRemove: additional,
650
654
  canMoveUp: index >= itemSchemas.length + 1,
@@ -667,7 +671,7 @@
667
671
  registry,
668
672
  schema,
669
673
  uiSchema,
670
- title,
674
+ title: fieldTitle,
671
675
  formContext,
672
676
  rawErrors
673
677
  };
@@ -697,7 +701,8 @@
697
701
  onBlur,
698
702
  onFocus,
699
703
  rawErrors,
700
- totalItems
704
+ totalItems,
705
+ title
701
706
  } = props;
702
707
  const { disabled, hideError, idPrefix, idSeparator, readonly, uiSchema, registry, formContext } = this.props;
703
708
  const {
@@ -719,6 +724,7 @@
719
724
  ItemSchemaField,
720
725
  {
721
726
  name,
727
+ title,
722
728
  index,
723
729
  schema: itemSchema,
724
730
  uiSchema: itemUiSchema,
@@ -776,12 +782,13 @@
776
782
  readonly,
777
783
  hideError,
778
784
  autofocus,
785
+ title,
779
786
  onChange,
780
787
  onFocus,
781
788
  onBlur,
782
789
  rawErrors
783
790
  } = props;
784
- const { title } = schema;
791
+ const { title: schemaTitle } = schema;
785
792
  const { widgets: widgets2, formContext, translateString, globalUiOptions } = registry;
786
793
  const {
787
794
  widget = "checkbox",
@@ -794,7 +801,7 @@
794
801
  const yes = translateString(utils.TranslatableString.YesLabel);
795
802
  const no = translateString(utils.TranslatableString.NoLabel);
796
803
  let enumOptions;
797
- const label = uiTitle ?? title ?? name;
804
+ const label = uiTitle ?? schemaTitle ?? title ?? name;
798
805
  if (Array.isArray(schema.oneOf)) {
799
806
  enumOptions = utils.optionsList({
800
807
  oneOf: schema.oneOf.map((option) => {
@@ -1219,14 +1226,15 @@
1219
1226
  idSeparator,
1220
1227
  onBlur,
1221
1228
  onFocus,
1222
- registry
1229
+ registry,
1230
+ title
1223
1231
  } = this.props;
1224
1232
  const { fields: fields2, formContext, schemaUtils, translateString, globalUiOptions } = registry;
1225
1233
  const { SchemaField: SchemaField2 } = fields2;
1226
1234
  const schema = schemaUtils.retrieveSchema(rawSchema, formData);
1227
1235
  const uiOptions = utils.getUiOptions(uiSchema, globalUiOptions);
1228
1236
  const { properties: schemaProperties = {} } = schema;
1229
- const title = uiOptions.title ?? schema.title ?? name;
1237
+ const templateTitle = uiOptions.title ?? schema.title ?? title ?? name;
1230
1238
  const description = uiOptions.description ?? schema.description;
1231
1239
  let orderedProperties;
1232
1240
  try {
@@ -1241,7 +1249,7 @@
1241
1249
  const Template = utils.getTemplate("ObjectFieldTemplate", registry, uiOptions);
1242
1250
  const templateProps = {
1243
1251
  // getDisplayLabel() always returns false for object types, so just check the `uiOptions.label`
1244
- title: uiOptions.label === false ? "" : title,
1252
+ title: uiOptions.label === false ? "" : templateTitle,
1245
1253
  description: uiOptions.label === false ? void 0 : description,
1246
1254
  properties: orderedProperties.map((name2) => {
1247
1255
  const addedByAdditionalProperties = has(schema, [utils.PROPERTIES_KEY, name2, utils.ADDITIONAL_PROPERTY_FLAG]);
@@ -1419,7 +1427,7 @@
1419
1427
  if (wasPropertyKeyModified) {
1420
1428
  label = name;
1421
1429
  } else {
1422
- label = utils.ADDITIONAL_PROPERTY_FLAG in schema ? name : uiOptions.title || props.schema.title || schema.title || name;
1430
+ label = utils.ADDITIONAL_PROPERTY_FLAG in schema ? name : uiOptions.title || props.schema.title || schema.title || props.title || name;
1423
1431
  }
1424
1432
  const description = uiOptions.description || props.schema.description || schema.description || "";
1425
1433
  const richDescription = uiOptions.enableMarkdownInDescription ? /* @__PURE__ */ jsxRuntime.jsx(Markdown, { children: description }) : description;
@@ -2262,26 +2270,6 @@
2262
2270
  function readyForChange(state) {
2263
2271
  return Object.values(state).every((value) => value !== -1);
2264
2272
  }
2265
- function dateElementProps(state, time, yearsRange = [1900, (/* @__PURE__ */ new Date()).getFullYear() + 2]) {
2266
- const { year, month, day, hour, minute, second } = state;
2267
- const data = [
2268
- {
2269
- type: "year",
2270
- range: yearsRange,
2271
- value: year
2272
- },
2273
- { type: "month", range: [1, 12], value: month },
2274
- { type: "day", range: [1, 31], value: day }
2275
- ];
2276
- if (time) {
2277
- data.push(
2278
- { type: "hour", range: [0, 23], value: hour },
2279
- { type: "minute", range: [0, 59], value: minute },
2280
- { type: "second", range: [0, 59], value: second }
2281
- );
2282
- }
2283
- return data;
2284
- }
2285
2273
  function DateElement({
2286
2274
  type,
2287
2275
  range,
@@ -2373,7 +2361,12 @@
2373
2361
  [disabled, readonly, onChange]
2374
2362
  );
2375
2363
  return /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "list-inline", children: [
2376
- dateElementProps(state, time, options.yearsRange).map((elemProps, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { className: "list-inline-item", children: /* @__PURE__ */ jsxRuntime.jsx(
2364
+ utils.getDateElementProps(
2365
+ state,
2366
+ time,
2367
+ options.yearsRange,
2368
+ options.format
2369
+ ).map((elemProps, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { className: "list-inline-item", children: /* @__PURE__ */ jsxRuntime.jsx(
2377
2370
  DateElement,
2378
2371
  {
2379
2372
  rootId: id,
@@ -2606,17 +2599,22 @@
2606
2599
  function FilesInfo({
2607
2600
  filesInfo,
2608
2601
  registry,
2609
- preview
2602
+ preview,
2603
+ onRemove,
2604
+ options
2610
2605
  }) {
2611
2606
  if (filesInfo.length === 0) {
2612
2607
  return null;
2613
2608
  }
2614
2609
  const { translateString } = registry;
2610
+ const { RemoveButton: RemoveButton2 } = utils.getTemplate("ButtonTemplates", registry, options);
2615
2611
  return /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "file-info", children: filesInfo.map((fileInfo, key) => {
2616
2612
  const { name, size, type } = fileInfo;
2613
+ const handleRemove = () => onRemove(key);
2617
2614
  return /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
2618
2615
  /* @__PURE__ */ jsxRuntime.jsx(Markdown, { children: translateString(utils.TranslatableString.FilesInfo, [name, type, String(size)]) }),
2619
- preview && /* @__PURE__ */ jsxRuntime.jsx(FileInfoPreview, { fileInfo, registry })
2616
+ preview && /* @__PURE__ */ jsxRuntime.jsx(FileInfoPreview, { fileInfo, registry }),
2617
+ /* @__PURE__ */ jsxRuntime.jsx(RemoveButton2, { onClick: handleRemove, registry })
2620
2618
  ] }, key);
2621
2619
  }) });
2622
2620
  }
@@ -2634,9 +2632,6 @@
2634
2632
  function FileWidget(props) {
2635
2633
  const { disabled, readonly, required, multiple, onChange, value, options, registry } = props;
2636
2634
  const BaseInputTemplate2 = utils.getTemplate("BaseInputTemplate", registry, options);
2637
- const [filesInfo, setFilesInfo] = react.useState(
2638
- Array.isArray(value) ? extractFileInfo(value) : extractFileInfo([value])
2639
- );
2640
2635
  const handleChange = react.useCallback(
2641
2636
  (event) => {
2642
2637
  if (!event.target.files) {
@@ -2645,15 +2640,25 @@
2645
2640
  processFiles(event.target.files).then((filesInfoEvent) => {
2646
2641
  const newValue = filesInfoEvent.map((fileInfo) => fileInfo.dataURL);
2647
2642
  if (multiple) {
2648
- setFilesInfo(filesInfo.concat(filesInfoEvent[0]));
2649
2643
  onChange(value.concat(newValue[0]));
2650
2644
  } else {
2651
- setFilesInfo(filesInfoEvent);
2652
2645
  onChange(newValue[0]);
2653
2646
  }
2654
2647
  });
2655
2648
  },
2656
- [multiple, value, filesInfo, onChange]
2649
+ [multiple, value, onChange]
2650
+ );
2651
+ const filesInfo = react.useMemo(() => extractFileInfo(Array.isArray(value) ? value : [value]), [value]);
2652
+ const rmFile = react.useCallback(
2653
+ (index) => {
2654
+ if (multiple) {
2655
+ const newValue = value.filter((_, i) => i !== index);
2656
+ onChange(newValue);
2657
+ } else {
2658
+ onChange(void 0);
2659
+ }
2660
+ },
2661
+ [multiple, value, onChange]
2657
2662
  );
2658
2663
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2659
2664
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -2668,7 +2673,16 @@
2668
2673
  accept: options.accept ? String(options.accept) : void 0
2669
2674
  }
2670
2675
  ),
2671
- /* @__PURE__ */ jsxRuntime.jsx(FilesInfo, { filesInfo, registry, preview: options.filePreview })
2676
+ /* @__PURE__ */ jsxRuntime.jsx(
2677
+ FilesInfo,
2678
+ {
2679
+ filesInfo,
2680
+ onRemove: rmFile,
2681
+ registry,
2682
+ preview: options.filePreview,
2683
+ options
2684
+ }
2685
+ )
2672
2686
  ] });
2673
2687
  }
2674
2688
  var FileWidget_default = FileWidget;
@@ -3125,6 +3139,17 @@
3125
3139
  );
3126
3140
  }
3127
3141
  };
3142
+ /** Provides a function that can be used to programmatically submit the `Form` */
3143
+ this.submit = () => {
3144
+ if (this.formElement.current) {
3145
+ this.formElement.current.dispatchEvent(
3146
+ new CustomEvent("submit", {
3147
+ cancelable: true
3148
+ })
3149
+ );
3150
+ this.formElement.current.requestSubmit();
3151
+ }
3152
+ };
3128
3153
  if (!props.validator) {
3129
3154
  throw new Error("A validator is required for Form functionality to work");
3130
3155
  }
@@ -3333,17 +3358,6 @@
3333
3358
  globalUiOptions: uiSchema[utils.UI_GLOBAL_OPTIONS_KEY]
3334
3359
  };
3335
3360
  }
3336
- /** Provides a function that can be used to programmatically submit the `Form` */
3337
- submit() {
3338
- if (this.formElement.current) {
3339
- this.formElement.current.dispatchEvent(
3340
- new CustomEvent("submit", {
3341
- cancelable: true
3342
- })
3343
- );
3344
- this.formElement.current.requestSubmit();
3345
- }
3346
- }
3347
3361
  /** Attempts to focus on the field associated with the `error`. Uses the `property` field to compute path of the error
3348
3362
  * field, then, using the `idPrefix` and `idSeparator` converts that path into an id. Then the input element with that
3349
3363
  * id is attempted to be found using the `formElement` ref. If it is located, then it is focused.
package/dist/index.esm.js CHANGED
@@ -412,6 +412,7 @@ var ArrayField = class extends Component {
412
412
  errorSchema,
413
413
  idSchema,
414
414
  name,
415
+ title,
415
416
  disabled = false,
416
417
  readonly = false,
417
418
  autofocus = false,
@@ -424,7 +425,7 @@ var ArrayField = class extends Component {
424
425
  rawErrors
425
426
  } = this.props;
426
427
  const { keyedFormData } = this.state;
427
- const title = schema.title === void 0 ? name : schema.title;
428
+ const fieldTitle = schema.title || title || name;
428
429
  const { schemaUtils, formContext } = registry;
429
430
  const uiOptions = getUiOptions(uiSchema);
430
431
  const _schemaItems = isObject(schema.items) ? schema.items : {};
@@ -444,6 +445,7 @@ var ArrayField = class extends Component {
444
445
  key,
445
446
  index,
446
447
  name: name && `${name}-${index}`,
448
+ title: fieldTitle ? `${fieldTitle}-${index + 1}` : void 0,
447
449
  canAdd,
448
450
  canMoveUp: index > 0,
449
451
  canMoveDown: index < formData.length - 1,
@@ -467,7 +469,7 @@ var ArrayField = class extends Component {
467
469
  readonly,
468
470
  required,
469
471
  schema,
470
- title,
472
+ title: fieldTitle,
471
473
  formContext,
472
474
  formData,
473
475
  rawErrors,
@@ -640,6 +642,7 @@ var ArrayField = class extends Component {
640
642
  idSeparator = "_",
641
643
  idSchema,
642
644
  name,
645
+ title,
643
646
  disabled = false,
644
647
  readonly = false,
645
648
  autofocus = false,
@@ -651,7 +654,7 @@ var ArrayField = class extends Component {
651
654
  } = this.props;
652
655
  const { keyedFormData } = this.state;
653
656
  let { formData: items = [] } = this.props;
654
- const title = schema.title || name;
657
+ const fieldTitle = schema.title || title || name;
655
658
  const uiOptions = getUiOptions(uiSchema);
656
659
  const { schemaUtils, formContext } = registry;
657
660
  const _schemaItems = isObject(schema.items) ? schema.items : [];
@@ -683,6 +686,7 @@ var ArrayField = class extends Component {
683
686
  key,
684
687
  index,
685
688
  name: name && `${name}-${index}`,
689
+ title: fieldTitle ? `${fieldTitle}-${index + 1}` : void 0,
686
690
  canAdd,
687
691
  canRemove: additional,
688
692
  canMoveUp: index >= itemSchemas.length + 1,
@@ -705,7 +709,7 @@ var ArrayField = class extends Component {
705
709
  registry,
706
710
  schema,
707
711
  uiSchema,
708
- title,
712
+ title: fieldTitle,
709
713
  formContext,
710
714
  rawErrors
711
715
  };
@@ -735,7 +739,8 @@ var ArrayField = class extends Component {
735
739
  onBlur,
736
740
  onFocus,
737
741
  rawErrors,
738
- totalItems
742
+ totalItems,
743
+ title
739
744
  } = props;
740
745
  const { disabled, hideError, idPrefix, idSeparator, readonly, uiSchema, registry, formContext } = this.props;
741
746
  const {
@@ -757,6 +762,7 @@ var ArrayField = class extends Component {
757
762
  ItemSchemaField,
758
763
  {
759
764
  name,
765
+ title,
760
766
  index,
761
767
  schema: itemSchema,
762
768
  uiSchema: itemUiSchema,
@@ -824,12 +830,13 @@ function BooleanField(props) {
824
830
  readonly,
825
831
  hideError,
826
832
  autofocus,
833
+ title,
827
834
  onChange,
828
835
  onFocus,
829
836
  onBlur,
830
837
  rawErrors
831
838
  } = props;
832
- const { title } = schema;
839
+ const { title: schemaTitle } = schema;
833
840
  const { widgets: widgets2, formContext, translateString, globalUiOptions } = registry;
834
841
  const {
835
842
  widget = "checkbox",
@@ -842,7 +849,7 @@ function BooleanField(props) {
842
849
  const yes = translateString(TranslatableString2.YesLabel);
843
850
  const no = translateString(TranslatableString2.NoLabel);
844
851
  let enumOptions;
845
- const label = uiTitle ?? title ?? name;
852
+ const label = uiTitle ?? schemaTitle ?? title ?? name;
846
853
  if (Array.isArray(schema.oneOf)) {
847
854
  enumOptions = optionsList2({
848
855
  oneOf: schema.oneOf.map((option) => {
@@ -1309,14 +1316,15 @@ var ObjectField = class extends Component3 {
1309
1316
  idSeparator,
1310
1317
  onBlur,
1311
1318
  onFocus,
1312
- registry
1319
+ registry,
1320
+ title
1313
1321
  } = this.props;
1314
1322
  const { fields: fields2, formContext, schemaUtils, translateString, globalUiOptions } = registry;
1315
1323
  const { SchemaField: SchemaField2 } = fields2;
1316
1324
  const schema = schemaUtils.retrieveSchema(rawSchema, formData);
1317
1325
  const uiOptions = getUiOptions4(uiSchema, globalUiOptions);
1318
1326
  const { properties: schemaProperties = {} } = schema;
1319
- const title = uiOptions.title ?? schema.title ?? name;
1327
+ const templateTitle = uiOptions.title ?? schema.title ?? title ?? name;
1320
1328
  const description = uiOptions.description ?? schema.description;
1321
1329
  let orderedProperties;
1322
1330
  try {
@@ -1331,7 +1339,7 @@ var ObjectField = class extends Component3 {
1331
1339
  const Template = getTemplate2("ObjectFieldTemplate", registry, uiOptions);
1332
1340
  const templateProps = {
1333
1341
  // getDisplayLabel() always returns false for object types, so just check the `uiOptions.label`
1334
- title: uiOptions.label === false ? "" : title,
1342
+ title: uiOptions.label === false ? "" : templateTitle,
1335
1343
  description: uiOptions.label === false ? void 0 : description,
1336
1344
  properties: orderedProperties.map((name2) => {
1337
1345
  const addedByAdditionalProperties = has(schema, [PROPERTIES_KEY, name2, ADDITIONAL_PROPERTY_FLAG]);
@@ -1528,7 +1536,7 @@ function SchemaFieldRender(props) {
1528
1536
  if (wasPropertyKeyModified) {
1529
1537
  label = name;
1530
1538
  } else {
1531
- label = ADDITIONAL_PROPERTY_FLAG2 in schema ? name : uiOptions.title || props.schema.title || schema.title || name;
1539
+ label = ADDITIONAL_PROPERTY_FLAG2 in schema ? name : uiOptions.title || props.schema.title || schema.title || props.title || name;
1532
1540
  }
1533
1541
  const description = uiOptions.description || props.schema.description || schema.description || "";
1534
1542
  const richDescription = uiOptions.enableMarkdownInDescription ? /* @__PURE__ */ jsx6(Markdown2, { children: description }) : description;
@@ -2484,7 +2492,8 @@ import {
2484
2492
  parseDateString,
2485
2493
  toDateString,
2486
2494
  pad,
2487
- TranslatableString as TranslatableString11
2495
+ TranslatableString as TranslatableString11,
2496
+ getDateElementProps
2488
2497
  } from "@rjsf/utils";
2489
2498
  import { jsx as jsx26, jsxs as jsxs14 } from "react/jsx-runtime";
2490
2499
  function rangeOptions(start, stop) {
@@ -2497,26 +2506,6 @@ function rangeOptions(start, stop) {
2497
2506
  function readyForChange(state) {
2498
2507
  return Object.values(state).every((value) => value !== -1);
2499
2508
  }
2500
- function dateElementProps(state, time, yearsRange = [1900, (/* @__PURE__ */ new Date()).getFullYear() + 2]) {
2501
- const { year, month, day, hour, minute, second } = state;
2502
- const data = [
2503
- {
2504
- type: "year",
2505
- range: yearsRange,
2506
- value: year
2507
- },
2508
- { type: "month", range: [1, 12], value: month },
2509
- { type: "day", range: [1, 31], value: day }
2510
- ];
2511
- if (time) {
2512
- data.push(
2513
- { type: "hour", range: [0, 23], value: hour },
2514
- { type: "minute", range: [0, 59], value: minute },
2515
- { type: "second", range: [0, 59], value: second }
2516
- );
2517
- }
2518
- return data;
2519
- }
2520
2509
  function DateElement({
2521
2510
  type,
2522
2511
  range,
@@ -2608,7 +2597,12 @@ function AltDateWidget({
2608
2597
  [disabled, readonly, onChange]
2609
2598
  );
2610
2599
  return /* @__PURE__ */ jsxs14("ul", { className: "list-inline", children: [
2611
- dateElementProps(state, time, options.yearsRange).map((elemProps, i) => /* @__PURE__ */ jsx26("li", { className: "list-inline-item", children: /* @__PURE__ */ jsx26(
2600
+ getDateElementProps(
2601
+ state,
2602
+ time,
2603
+ options.yearsRange,
2604
+ options.format
2605
+ ).map((elemProps, i) => /* @__PURE__ */ jsx26("li", { className: "list-inline-item", children: /* @__PURE__ */ jsx26(
2612
2606
  DateElement,
2613
2607
  {
2614
2608
  rootId: id,
@@ -2836,7 +2830,7 @@ function EmailWidget(props) {
2836
2830
  }
2837
2831
 
2838
2832
  // src/components/widgets/FileWidget.tsx
2839
- import { useCallback as useCallback8, useState as useState3 } from "react";
2833
+ import { useCallback as useCallback8, useMemo } from "react";
2840
2834
  import {
2841
2835
  dataURItoBlob,
2842
2836
  getTemplate as getTemplate14,
@@ -2898,17 +2892,22 @@ function FileInfoPreview({
2898
2892
  function FilesInfo({
2899
2893
  filesInfo,
2900
2894
  registry,
2901
- preview
2895
+ preview,
2896
+ onRemove,
2897
+ options
2902
2898
  }) {
2903
2899
  if (filesInfo.length === 0) {
2904
2900
  return null;
2905
2901
  }
2906
2902
  const { translateString } = registry;
2903
+ const { RemoveButton: RemoveButton2 } = getTemplate14("ButtonTemplates", registry, options);
2907
2904
  return /* @__PURE__ */ jsx34("ul", { className: "file-info", children: filesInfo.map((fileInfo, key) => {
2908
2905
  const { name, size, type } = fileInfo;
2906
+ const handleRemove = () => onRemove(key);
2909
2907
  return /* @__PURE__ */ jsxs17("li", { children: [
2910
2908
  /* @__PURE__ */ jsx34(Markdown4, { children: translateString(TranslatableString12.FilesInfo, [name, type, String(size)]) }),
2911
- preview && /* @__PURE__ */ jsx34(FileInfoPreview, { fileInfo, registry })
2909
+ preview && /* @__PURE__ */ jsx34(FileInfoPreview, { fileInfo, registry }),
2910
+ /* @__PURE__ */ jsx34(RemoveButton2, { onClick: handleRemove, registry })
2912
2911
  ] }, key);
2913
2912
  }) });
2914
2913
  }
@@ -2926,9 +2925,6 @@ function extractFileInfo(dataURLs) {
2926
2925
  function FileWidget(props) {
2927
2926
  const { disabled, readonly, required, multiple, onChange, value, options, registry } = props;
2928
2927
  const BaseInputTemplate2 = getTemplate14("BaseInputTemplate", registry, options);
2929
- const [filesInfo, setFilesInfo] = useState3(
2930
- Array.isArray(value) ? extractFileInfo(value) : extractFileInfo([value])
2931
- );
2932
2928
  const handleChange = useCallback8(
2933
2929
  (event) => {
2934
2930
  if (!event.target.files) {
@@ -2937,15 +2933,25 @@ function FileWidget(props) {
2937
2933
  processFiles(event.target.files).then((filesInfoEvent) => {
2938
2934
  const newValue = filesInfoEvent.map((fileInfo) => fileInfo.dataURL);
2939
2935
  if (multiple) {
2940
- setFilesInfo(filesInfo.concat(filesInfoEvent[0]));
2941
2936
  onChange(value.concat(newValue[0]));
2942
2937
  } else {
2943
- setFilesInfo(filesInfoEvent);
2944
2938
  onChange(newValue[0]);
2945
2939
  }
2946
2940
  });
2947
2941
  },
2948
- [multiple, value, filesInfo, onChange]
2942
+ [multiple, value, onChange]
2943
+ );
2944
+ const filesInfo = useMemo(() => extractFileInfo(Array.isArray(value) ? value : [value]), [value]);
2945
+ const rmFile = useCallback8(
2946
+ (index) => {
2947
+ if (multiple) {
2948
+ const newValue = value.filter((_, i) => i !== index);
2949
+ onChange(newValue);
2950
+ } else {
2951
+ onChange(void 0);
2952
+ }
2953
+ },
2954
+ [multiple, value, onChange]
2949
2955
  );
2950
2956
  return /* @__PURE__ */ jsxs17("div", { children: [
2951
2957
  /* @__PURE__ */ jsx34(
@@ -2960,7 +2966,16 @@ function FileWidget(props) {
2960
2966
  accept: options.accept ? String(options.accept) : void 0
2961
2967
  }
2962
2968
  ),
2963
- /* @__PURE__ */ jsx34(FilesInfo, { filesInfo, registry, preview: options.filePreview })
2969
+ /* @__PURE__ */ jsx34(
2970
+ FilesInfo,
2971
+ {
2972
+ filesInfo,
2973
+ onRemove: rmFile,
2974
+ registry,
2975
+ preview: options.filePreview,
2976
+ options
2977
+ }
2978
+ )
2964
2979
  ] });
2965
2980
  }
2966
2981
  var FileWidget_default = FileWidget;
@@ -3471,6 +3486,17 @@ var Form = class extends Component5 {
3471
3486
  );
3472
3487
  }
3473
3488
  };
3489
+ /** Provides a function that can be used to programmatically submit the `Form` */
3490
+ this.submit = () => {
3491
+ if (this.formElement.current) {
3492
+ this.formElement.current.dispatchEvent(
3493
+ new CustomEvent("submit", {
3494
+ cancelable: true
3495
+ })
3496
+ );
3497
+ this.formElement.current.requestSubmit();
3498
+ }
3499
+ };
3474
3500
  if (!props.validator) {
3475
3501
  throw new Error("A validator is required for Form functionality to work");
3476
3502
  }
@@ -3679,17 +3705,6 @@ var Form = class extends Component5 {
3679
3705
  globalUiOptions: uiSchema[UI_GLOBAL_OPTIONS_KEY]
3680
3706
  };
3681
3707
  }
3682
- /** Provides a function that can be used to programmatically submit the `Form` */
3683
- submit() {
3684
- if (this.formElement.current) {
3685
- this.formElement.current.dispatchEvent(
3686
- new CustomEvent("submit", {
3687
- cancelable: true
3688
- })
3689
- );
3690
- this.formElement.current.requestSubmit();
3691
- }
3692
- }
3693
3708
  /** Attempts to focus on the field associated with the `error`. Uses the `property` field to compute path of the error
3694
3709
  * field, then, using the `idPrefix` and `idSeparator` converts that path into an id. Then the input element with that
3695
3710
  * id is attempted to be found using the `formElement` ref. If it is located, then it is focused.