@ostack.tech/ui-kform 0.8.2 → 0.9.1

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.
Files changed (33) hide show
  1. package/dist/chunks/{en-DdEhXMHn.js → en-DwjQmgp3.js} +11 -13
  2. package/dist/chunks/en-DwjQmgp3.js.map +1 -0
  3. package/dist/locales/en-GB.js +1 -1
  4. package/dist/locales/en-US.js +1 -1
  5. package/dist/locales/fr-FR.js +10 -12
  6. package/dist/locales/fr-FR.js.map +1 -1
  7. package/dist/locales/pt-PT.js +10 -12
  8. package/dist/locales/pt-PT.js.map +1 -1
  9. package/dist/ostack-ui-kform.css +2 -5
  10. package/dist/ostack-ui-kform.css.map +1 -1
  11. package/dist/ostack-ui-kform.js +453 -117
  12. package/dist/ostack-ui-kform.js.map +1 -1
  13. package/dist/types/components/Annexes/AnnexesContext.d.ts +1 -1
  14. package/dist/types/components/Annexes/AnnexesManager.d.ts +4 -0
  15. package/dist/types/components/Annexes/AnnexesMenu.d.ts +2 -2
  16. package/dist/types/components/FormPages/FormPage.d.ts +7 -2
  17. package/dist/types/components/FormPages/FormPagesContext.d.ts +1 -0
  18. package/dist/types/components/FormPages/FormPagesSidebar.d.ts +2 -2
  19. package/dist/types/components/IssueMessage/IssueMessage.d.ts +3 -1
  20. package/dist/types/components/IssueMessages/IssueMessages.d.ts +4 -0
  21. package/dist/types/components/IssuesPanel/IssuesPanel.d.ts +20 -0
  22. package/dist/types/components/IssuesPanel/IssuesPanelControls.d.ts +2 -2
  23. package/dist/types/components/LoadAction/LoadAction.d.ts +4 -1
  24. package/dist/types/components/PrintAction/PrintAction.d.ts +4 -1
  25. package/dist/types/components/SaveAction/SaveAction.d.ts +8 -2
  26. package/dist/types/components/SubmitAction/SubmitAction.d.ts +4 -1
  27. package/dist/types/components/ValidateAction/ValidateAction.d.ts +4 -1
  28. package/dist/types/providers/LocalizationProvider/LocalizationObject.d.ts +4 -4
  29. package/dist/types/utils/useControlIssues.d.ts +4 -1
  30. package/package.json +2 -2
  31. package/scss/components/FormPages/_FormPages.scss +1 -2
  32. package/scss/components/IssueMessages/_IssueMessages.scss +0 -4
  33. package/dist/chunks/en-DdEhXMHn.js.map +0 -1
@@ -1,8 +1,8 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
- import { usePrefix as usePrefix$1, useControllableState, useLatestValues, combineEventHandlers, LocalizationProvider as LocalizationProvider$1, usePrinting, useConstant, useSpacing, useCssVars, NATIVE_CONTROLS, useResponsiveValues, useCombinedRef, cx, useIsInRoot, warnOnce, usePrintInProgress, PrefixProvider, Root, computed, TabContent, ErrorBoundary, DocumentTitle, Spinner, useToastManager, useStartPrintingTask, Tabs, useErrorReporter, EMPTY_STORE, Field, Feedback, FeedbackList, FeedbackPopover, useMediaBreakpointUp, DropdownMenu, DropdownMenuTrigger, Button, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuGroup, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent, DropdownMenuItem, useAlertDialog, DropdownMenuRadioItem, controlStatusToAccent, VisuallyHidden, IconButton, Tab, boolDataAttr, TabList, useIsInTableCell, useDataTableColumnLabel, useOnFieldLabelChange, Checkbox, OptionsGroup, Option, CheckboxGroup, useDateTransformer, DateInput, DateRangeInput, usePrintClassNames, Input, Dialog, Tooltip, DialogTrigger, ControlAddon, Icon, DialogContent, DialogHeader, DialogTitle, DialogBody, Alert, Stack, Popover, PopoverTrigger, PopoverContent, useMeasure, Container, Select, MenuListItem, MenuList, StepContent, Step, StepList, Stepper, CloseButton, useScrollPosition, setBoolDataAttr, Card, CardHeader, CardTitle, CardBody, useIntersectionObserver, useKeyboardShortcut, NumericInput, Link, usePrint, usePrinterDocumentTitle, PrinterTrigger, RadioGroup, Radio, ButtonGroup, AlertDialog, AlertDialogTrigger, AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogBody, AlertDialogDescription, AlertDialogFooter, AlertDialogCancel, AlertDialogAction, DataTableCell, DataTableRow, useDataTableApiRef, DataTable, Slot, DataTableContent, DataTablePagination, DataTableRowsPerPage, TextArea, PortalContext } from "@ostack.tech/ui";
2
+ import { usePrefix as usePrefix$1, useControllableState, useLatestValues, combineEventHandlers, LocalizationProvider as LocalizationProvider$1, usePrinting, useConstant, useSpacing, useCssVars, NATIVE_CONTROLS, useResponsiveValues, useCombinedRef, cx, useIsInRoot, warnOnce, usePrintInProgress, PrefixProvider, Root, computed, TabContent, ErrorBoundary, DocumentTitle, Spinner, useToastManager, useStartPrintingTask, Tabs, useErrorReporter, EMPTY_STORE, Field, VisuallyHidden, Feedback, FeedbackList, FeedbackPopover, useMediaBreakpointUp, DropdownMenu, DropdownMenuTrigger, Button, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuGroup, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent, DropdownMenuItem, useAlertDialog, DropdownMenuRadioItem, controlStatusToAccent, IconButton, Tab, boolDataAttr, TabList, combineAriaIds, useIsInTableCell, useDataTableColumnLabel, useOnFieldLabelChange, Checkbox, OptionsGroup, Option, CheckboxGroup, useDateTransformer, DateInput, DateRangeInput, usePrintClassNames, Input, Dialog, Tooltip, DialogTrigger, ControlAddon, Icon, DialogContent, DialogHeader, DialogTitle, DialogBody, Alert, Stack, Popover, PopoverTrigger, PopoverContent, useMeasure, Container, Select, MenuListItem, MenuList, StepContent, Step, StepList, Stepper, useKeyboardShortcut, CloseButton, useScrollPosition, setBoolDataAttr, Card, CardHeader, CardTitle, CardBody, useIntersectionObserver, NumericInput, Link, usePrint, usePrinterDocumentTitle, PrinterTrigger, RadioGroup, Radio, ButtonGroup, AlertDialog, AlertDialogTrigger, AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogBody, AlertDialogDescription, AlertDialogFooter, AlertDialogCancel, AlertDialogAction, DataTableCell, DataTableRow, useDataTableApiRef, DataTable, Slot, DataTableContent, DataTablePagination, DataTableRowsPerPage, TextArea, PortalContext } from "@ostack.tech/ui";
3
3
  import { AbsolutePath, AbsolutePathFragment, PathMultimap, sliceTable, listableSize, Path, ValidationFailure, nullableSchemaInnerSchema, compareSchemaPaths, PromiseCancellationException, arrayToTable, indexOfTableRowId, isComputedSchema } from "@ostack.tech/kform";
4
4
  import { useResolvedPath, equals, useFormController, useForm, FormContext, CurrentPath, useCurrentPath, useFormManager, useFormattedValue, InvalidPathError, AtPathError, useIssuesTracker, useFormContext, useInput, useListableInput, formatTemporalAsString, useTemporalInput, useFileInput, toFileList, useController, useNumericInput, formatNumericAsString, useFormatter } from "@ostack.tech/kform-react";
5
- import { createContext, useContext, useCallback, useMemo, useRef, useEffect, forwardRef, useState, useImperativeHandle, startTransition, Suspense, useDeferredValue, Children, isValidElement, createElement, memo } from "react";
5
+ import { createContext, useContext, useCallback, useMemo, useRef, useEffect, forwardRef, useState, useImperativeHandle, startTransition, Suspense, useDeferredValue, Children, isValidElement, useId, createElement, memo } from "react";
6
6
  import { createStore, useStore } from "zustand";
7
7
  import { subscribeWithSelector } from "zustand/middleware";
8
8
  import { useShallow } from "zustand/react/shallow";
@@ -681,6 +681,7 @@ const FormAppElement = forwardRef(function FormAppElement2({
681
681
  prefix
682
682
  });
683
683
  const { store } = useFormAppContext();
684
+ const formTitle = useFormTitle();
684
685
  useEffect(
685
686
  () => store.subscribe(
686
687
  (state) => state.topBarHeight,
@@ -726,7 +727,8 @@ const FormAppElement = forwardRef(function FormAppElement2({
726
727
  {
727
728
  className: cx(prefix("form-app"), className),
728
729
  style: { ...cssVars, ...style },
729
- tabIndex: 0,
730
+ "aria-label": formTitle,
731
+ tabIndex: -1,
730
732
  ...dataAttrs,
731
733
  ...otherProps,
732
734
  ref: combinedFormAppRef,
@@ -1238,6 +1240,7 @@ function useCreateAnnexesContext({
1238
1240
  set({ nextActiveAnnex: addedPath });
1239
1241
  await setPromise;
1240
1242
  latest.onAnnexAdd?.(addedPath);
1243
+ return addedPath;
1241
1244
  },
1242
1245
  removeAnnex: async (path, isRepetitive) => {
1243
1246
  if (isRepetitive) {
@@ -1897,11 +1900,15 @@ function IssueMessage({
1897
1900
  issue,
1898
1901
  schema,
1899
1902
  displayIssueCode,
1903
+ visuallyHiddenErrorCodePrefix,
1904
+ visuallyHiddenWarningCodePrefix,
1900
1905
  unknownErrorMessage,
1901
1906
  unknownWarningMessage,
1902
1907
  issueCodeProps
1903
1908
  }) {
1904
1909
  const [locale7] = useLocale();
1910
+ visuallyHiddenErrorCodePrefix ??= locale7.IssueMessages.visuallyHiddenErrorCodePrefix;
1911
+ visuallyHiddenWarningCodePrefix ??= locale7.IssueMessages.visuallyHiddenWarningCodePrefix;
1905
1912
  unknownErrorMessage ??= locale7.IssueMessages.unknownErrorMessage;
1906
1913
  unknownWarningMessage ??= locale7.IssueMessages.unknownWarningMessage;
1907
1914
  let message = useRegisteredIssueMessage(path, issue.code);
@@ -1914,7 +1921,16 @@ function IssueMessage({
1914
1921
  return /* @__PURE__ */ jsxs(CurrentPath, { path, children: [
1915
1922
  typeof message === "function" ? message(issue.data ?? {}, schema, path) : message,
1916
1923
  (displayIssueCode || unknownIssue) && /* @__PURE__ */ jsxs("span", { ...issueCodeProps, children: [
1924
+ " ",
1917
1925
  "(",
1926
+ issue.severity === "error" && visuallyHiddenErrorCodePrefix && /* @__PURE__ */ jsxs(VisuallyHidden, { children: [
1927
+ visuallyHiddenErrorCodePrefix,
1928
+ " "
1929
+ ] }),
1930
+ issue.severity === "warning" && visuallyHiddenWarningCodePrefix && /* @__PURE__ */ jsxs(VisuallyHidden, { children: [
1931
+ visuallyHiddenWarningCodePrefix,
1932
+ " "
1933
+ ] }),
1918
1934
  issue.code,
1919
1935
  ")"
1920
1936
  ] })
@@ -1925,6 +1941,8 @@ const IssueMessages = forwardRef(function IssueMessages2({
1925
1941
  issues,
1926
1942
  messages,
1927
1943
  displayIssueCodes,
1944
+ visuallyHiddenErrorCodePrefix,
1945
+ visuallyHiddenWarningCodePrefix,
1928
1946
  unknownErrorMessage,
1929
1947
  unknownWarningMessage,
1930
1948
  unwrapped,
@@ -1974,6 +1992,8 @@ const IssueMessages = forwardRef(function IssueMessages2({
1974
1992
  issue,
1975
1993
  schema,
1976
1994
  displayIssueCode: displayIssueCodes,
1995
+ visuallyHiddenErrorCodePrefix,
1996
+ visuallyHiddenWarningCodePrefix,
1977
1997
  unknownErrorMessage,
1978
1998
  unknownWarningMessage,
1979
1999
  issueCodeProps: { className: prefix("issue-messages__issue-code") }
@@ -1984,6 +2004,8 @@ const IssueMessages = forwardRef(function IssueMessages2({
1984
2004
  absolutePath,
1985
2005
  schema,
1986
2006
  displayIssueCodes,
2007
+ visuallyHiddenErrorCodePrefix,
2008
+ visuallyHiddenWarningCodePrefix,
1987
2009
  unknownErrorMessage,
1988
2010
  unknownWarningMessage,
1989
2011
  prefix
@@ -2050,6 +2072,7 @@ function displayStatusToColor(displayStatus) {
2050
2072
  }
2051
2073
  function AnnexesMenu({
2052
2074
  menuButtonText,
2075
+ menuButtonLabel,
2053
2076
  addAnnexText,
2054
2077
  removeAnnexButtonLabel,
2055
2078
  removeAnnexKeyboardHint,
@@ -2077,8 +2100,16 @@ function AnnexesMenu({
2077
2100
  [store]
2078
2101
  );
2079
2102
  const annexes = useStore(store, (state) => state.annexes);
2103
+ const addedAnnexPathRef = useRef(null);
2080
2104
  const newItems = useMemo(
2081
- () => annexes.map((annex) => /* @__PURE__ */ jsx(AnnexesMenuNewItem, { annex }, annex.path.toString())),
2105
+ () => annexes.map((annex) => /* @__PURE__ */ jsx(
2106
+ AnnexesMenuNewItem,
2107
+ {
2108
+ annex,
2109
+ addedAnnexPathRef
2110
+ },
2111
+ annex.path.toString()
2112
+ )),
2082
2113
  [annexes]
2083
2114
  );
2084
2115
  const tabStates = useStore(
@@ -2097,6 +2128,17 @@ function AnnexesMenu({
2097
2128
  [issuesDisplayMode, resetFocus, store]
2098
2129
  )
2099
2130
  );
2131
+ const focus = useFocus();
2132
+ const handleCloseAutoFocus = useCallback(
2133
+ (evt) => {
2134
+ if (addedAnnexPathRef.current) {
2135
+ evt.preventDefault();
2136
+ focus(addedAnnexPathRef.current);
2137
+ addedAnnexPathRef.current = null;
2138
+ }
2139
+ },
2140
+ [focus]
2141
+ );
2100
2142
  const combinedMenuTriggerRef = useCombinedRef(
2101
2143
  menuTriggerRef,
2102
2144
  menuTriggerProps?.ref
@@ -2114,6 +2156,7 @@ function AnnexesMenu({
2114
2156
  {
2115
2157
  variant: "ghost",
2116
2158
  iconPlacement: "end",
2159
+ "aria-label": menuButtonLabel,
2117
2160
  ...menuTriggerProps,
2118
2161
  className: cx(
2119
2162
  prefix("annexes__menu-trigger"),
@@ -2135,6 +2178,11 @@ function AnnexesMenu({
2135
2178
  align: "start",
2136
2179
  ...menuContentProps,
2137
2180
  className: cx(prefix("annexes__menu"), menuContentProps?.className),
2181
+ onCloseAutoFocus: combineEventHandlers(
2182
+ menuContentProps?.onCloseAutoFocus,
2183
+ // eslint-disable-next-line react-hooks/refs
2184
+ handleCloseAutoFocus
2185
+ ),
2138
2186
  children: [
2139
2187
  /* @__PURE__ */ jsx(
2140
2188
  DropdownMenuRadioGroup,
@@ -2267,9 +2315,15 @@ function AnnexesMenuItem({
2267
2315
  /* @__PURE__ */ jsxs("div", { className: prefix("annexes__menu-annex-content-container"), children: [
2268
2316
  /* @__PURE__ */ jsxs("div", { className: prefix("annexes__menu-annex-title"), children: [
2269
2317
  title,
2270
- subtitle && /* @__PURE__ */ jsx("span", { className: prefix("annexes__menu-annex-subtitle"), children: subtitle })
2318
+ subtitle && /* @__PURE__ */ jsxs("span", { className: prefix("annexes__menu-annex-subtitle"), children: [
2319
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: ", " }),
2320
+ subtitle
2321
+ ] })
2271
2322
  ] }),
2272
- nonRepetitiveDescription && /* @__PURE__ */ jsx("div", { className: prefix("annexes__menu-annex-description"), children: nonRepetitiveDescription })
2323
+ nonRepetitiveDescription && /* @__PURE__ */ jsxs("div", { className: prefix("annexes__menu-annex-description"), children: [
2324
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: ", " }),
2325
+ nonRepetitiveDescription
2326
+ ] })
2273
2327
  ] }),
2274
2328
  isRemovable && !formIsReadOnly && /* @__PURE__ */ jsxs(Fragment, { children: [
2275
2329
  removeAnnexKeyboardHint && /* @__PURE__ */ jsx(VisuallyHidden, { children: removeAnnexKeyboardHint }),
@@ -2283,7 +2337,7 @@ function AnnexesMenuItem({
2283
2337
  circle: true,
2284
2338
  disabled: formIsDisabled,
2285
2339
  onClick: handleRemoveButtonClick,
2286
- "aria-hidden": true
2340
+ tabIndex: -1
2287
2341
  }
2288
2342
  )
2289
2343
  ] })
@@ -2291,7 +2345,10 @@ function AnnexesMenuItem({
2291
2345
  }
2292
2346
  );
2293
2347
  }
2294
- function AnnexesMenuNewItem({ annex }) {
2348
+ function AnnexesMenuNewItem({
2349
+ annex,
2350
+ addedAnnexPathRef
2351
+ }) {
2295
2352
  const prefix = usePrefix();
2296
2353
  const formIsDisabled = useFormIsDisabled();
2297
2354
  const formManager = useFormManager();
@@ -2340,8 +2397,8 @@ function AnnexesMenuNewItem({ annex }) {
2340
2397
  if (toAdd == null) {
2341
2398
  return;
2342
2399
  }
2343
- void store.getState().actions.addAnnex(annex.path, toAdd);
2344
- }, [annex, formManager, store]);
2400
+ addedAnnexPathRef.current = await store.getState().actions.addAnnex(annex.path, toAdd);
2401
+ }, [addedAnnexPathRef, annex, formManager, store]);
2345
2402
  return /* @__PURE__ */ jsx(
2346
2403
  DropdownMenuItem,
2347
2404
  {
@@ -2354,7 +2411,10 @@ function AnnexesMenuNewItem({ annex }) {
2354
2411
  },
2355
2412
  children: /* @__PURE__ */ jsxs(CurrentPath, { path: isRepetitive ? annex.path.parent() : annex.path, children: [
2356
2413
  /* @__PURE__ */ jsx("div", { className: prefix("annexes__menu-new-annex-title"), children: title }),
2357
- annex.description && /* @__PURE__ */ jsx("div", { className: prefix("annexes__menu-new-annex-description"), children: annex.description })
2414
+ annex.description && /* @__PURE__ */ jsxs("div", { className: prefix("annexes__menu-new-annex-description"), children: [
2415
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: ", " }),
2416
+ annex.description
2417
+ ] })
2358
2418
  ] })
2359
2419
  }
2360
2420
  );
@@ -2364,10 +2424,9 @@ function AnnexTab({ path }) {
2364
2424
  const issuesDisplayMode = useIssuesDisplayMode();
2365
2425
  const deferredIssuesToDisplay = useAnnexState(
2366
2426
  path,
2367
- useShallow(
2368
- (state) => issuesDisplayMode === "inline" && state?.deferredIssuesToDisplay || []
2369
- )
2427
+ useShallow((state) => state?.deferredIssuesToDisplay ?? [])
2370
2428
  );
2429
+ const hasIssues = deferredIssuesToDisplay.length > 0;
2371
2430
  const deferredDisplayStatus = useAnnexState(
2372
2431
  path,
2373
2432
  (state) => state?.deferredDisplayStatus
@@ -2380,15 +2439,31 @@ function AnnexTab({ path }) {
2380
2439
  useCallback(
2381
2440
  (focusedPath) => {
2382
2441
  if (tabRef.current && path.equals(focusedPath)) {
2383
- if (issuesDisplayMode === "panel") {
2384
- visiblyFocus(tabRef.current);
2385
- }
2442
+ visiblyFocus(tabRef.current);
2386
2443
  setTimeout(() => resetFocus());
2387
2444
  }
2388
2445
  },
2389
- [issuesDisplayMode, path, resetFocus]
2446
+ [path, resetFocus]
2390
2447
  )
2391
2448
  );
2449
+ const generatedId = useId();
2450
+ const issueMessagesId = prefix(`annexes-annex-issue-messages-${generatedId}`);
2451
+ const [issuesPopoverOpen, setIssuesPopoverOpen] = useState(false);
2452
+ const [tabFocused, setTabFocused] = useState(false);
2453
+ const handleTabFocus = useCallback(() => {
2454
+ setTabFocused(true);
2455
+ }, []);
2456
+ const handleTabBlur = useCallback(() => {
2457
+ setTabFocused(false);
2458
+ }, []);
2459
+ const handleIssuesPopoverOpenAutoFocus = useCallback(
2460
+ (evt) => {
2461
+ if (tabFocused) {
2462
+ evt.preventDefault();
2463
+ }
2464
+ },
2465
+ [tabFocused]
2466
+ );
2392
2467
  return /* @__PURE__ */ jsxs(Fragment, { children: [
2393
2468
  /* @__PURE__ */ jsx(
2394
2469
  Tab,
@@ -2396,26 +2471,53 @@ function AnnexTab({ path }) {
2396
2471
  className: prefix("annexes__tab"),
2397
2472
  value: path.toString(),
2398
2473
  status: displayStatusToControlStatus(deferredDisplayStatus),
2399
- "data-has-issues": boolDataAttr(deferredIssuesToDisplay.length > 0),
2474
+ onFocus: handleTabFocus,
2475
+ onBlur: handleTabBlur,
2476
+ "data-has-issues": boolDataAttr(
2477
+ issuesDisplayMode === "inline" && hasIssues
2478
+ ),
2400
2479
  tabInnerProps: { className: prefix("annexes__tab-inner") },
2480
+ "aria-describedby": hasIssues ? issueMessagesId : void 0,
2401
2481
  ref: tabRef,
2402
2482
  children: /* @__PURE__ */ jsxs(CurrentPath, { path, children: [
2403
2483
  /* @__PURE__ */ jsx("span", { className: prefix("annexes__tab-title"), children: title }),
2404
- subtitle && /* @__PURE__ */ jsx("span", { className: prefix("annexes__tab-subtitle"), children: subtitle })
2484
+ subtitle && /* @__PURE__ */ jsxs("span", { className: prefix("annexes__tab-subtitle"), children: [
2485
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: ", " }),
2486
+ subtitle
2487
+ ] })
2405
2488
  ] })
2406
2489
  }
2407
2490
  ),
2491
+ hasIssues && issuesDisplayMode === "panel" && /* @__PURE__ */ jsx(
2492
+ IssueMessages,
2493
+ {
2494
+ hidden: true,
2495
+ id: issueMessagesId,
2496
+ path,
2497
+ issues: deferredIssuesToDisplay
2498
+ }
2499
+ ),
2408
2500
  issuesDisplayMode === "inline" && /* @__PURE__ */ jsx(
2409
2501
  IssuesPopover,
2410
2502
  {
2411
2503
  path,
2504
+ open: hasIssues && (tabFocused || issuesPopoverOpen),
2505
+ onOpenChange: setIssuesPopoverOpen,
2506
+ onOpenAutoFocus: handleIssuesPopoverOpenAutoFocus,
2412
2507
  buttonContainerProps: {
2413
2508
  className: prefix("annexes__tab-issues-popover-button-container")
2414
2509
  },
2415
2510
  iconButtonProps: {
2416
- className: prefix("annexes__tab-issues-popover-button")
2511
+ className: prefix("annexes__tab-issues-popover-button"),
2512
+ tabIndex: -1
2417
2513
  },
2418
- children: /* @__PURE__ */ jsx(IssueMessages, { issues: deferredIssuesToDisplay })
2514
+ children: /* @__PURE__ */ jsx(
2515
+ IssueMessages,
2516
+ {
2517
+ id: issueMessagesId,
2518
+ issues: deferredIssuesToDisplay
2519
+ }
2520
+ )
2419
2521
  }
2420
2522
  )
2421
2523
  ] });
@@ -2447,6 +2549,7 @@ const AnnexesTabList = forwardRef(function AnnexManager({ hideNonActiveOnSmallSc
2447
2549
  });
2448
2550
  const AnnexesManager = forwardRef(function AnnexManager2({
2449
2551
  menuButtonText,
2552
+ menuButtonLabel,
2450
2553
  addAnnexText,
2451
2554
  removeAnnexButtonLabel,
2452
2555
  removeAnnexKeyboardHint,
@@ -2468,6 +2571,7 @@ const AnnexesManager = forwardRef(function AnnexManager2({
2468
2571
  const [locale7] = useLocale();
2469
2572
  ariaLabel ??= locale7.AnnexesManager["aria-label"];
2470
2573
  menuButtonText ??= locale7.AnnexesManager.menuButtonText;
2574
+ menuButtonLabel ??= locale7.AnnexesManager.menuButtonLabel;
2471
2575
  addAnnexText ??= locale7.AnnexesManager.addAnnexText;
2472
2576
  removeAnnexButtonLabel ??= locale7.AnnexesManager.removeAnnexButtonLabel;
2473
2577
  removeAnnexKeyboardHint ??= locale7.AnnexesManager.removeAnnexKeyboardHint;
@@ -2475,13 +2579,12 @@ const AnnexesManager = forwardRef(function AnnexManager2({
2475
2579
  removeAnnexConfirmDialogMessage ??= locale7.AnnexesManager.removeAnnexConfirmDialogMessage;
2476
2580
  removeAnnexConfirmDialogOkText ??= locale7.AnnexesManager.removeAnnexConfirmDialogOkText;
2477
2581
  removeAnnexConfirmDialogCancelText ??= locale7.AnnexesManager.removeAnnexConfirmDialogCancelText;
2582
+ const managerRef = useRef(null);
2478
2583
  const store = useAnnexesContext();
2479
2584
  const issuesDisplayMode = useIssuesDisplayMode();
2480
2585
  const tablessStates = useStore(
2481
2586
  store,
2482
- useShallow(
2483
- (state) => issuesDisplayMode === "inline" ? state.tablessStates() : []
2484
- )
2587
+ (state) => state.tablessStates()
2485
2588
  );
2486
2589
  const tablessPaths = useMemo(
2487
2590
  () => tablessStates.map((state) => state.path),
@@ -2491,6 +2594,16 @@ const AnnexesManager = forwardRef(function AnnexManager2({
2491
2594
  () => tablessStates.map((state) => state.deferredIssuesToDisplay || []),
2492
2595
  [tablessStates]
2493
2596
  );
2597
+ const hasIssues = useMemo(
2598
+ () => deferredTablessIssuesToDisplay.some((issues) => issues.length > 0),
2599
+ [deferredTablessIssuesToDisplay]
2600
+ );
2601
+ const hasErrors = useMemo(
2602
+ () => deferredTablessIssuesToDisplay.some(
2603
+ (issues) => issues.some((issue) => issue.severity === "error")
2604
+ ),
2605
+ [deferredTablessIssuesToDisplay]
2606
+ );
2494
2607
  const formManager = useFormManager();
2495
2608
  const shouldRenderMenu = useStore(
2496
2609
  store,
@@ -2498,13 +2611,62 @@ const AnnexesManager = forwardRef(function AnnexManager2({
2498
2611
  (annex) => annex.path.lastFragment === AbsolutePathFragment.Wildcard || formManager.schema(annex.path).typeInfo.nullable
2499
2612
  )
2500
2613
  );
2614
+ const generatedId = useId();
2615
+ const menuContentId = menuContentProps?.id ?? prefix(`annexes-menu-content-${generatedId}`);
2616
+ const handleAnnexesMenuOpenChange = useCallback(
2617
+ (open) => {
2618
+ const managerEl = managerRef.current;
2619
+ if (managerEl) {
2620
+ const oldAriaOwns = managerEl.getAttribute("aria-owns")?.split(" ") ?? [];
2621
+ let newAriaOwns;
2622
+ if (open) {
2623
+ newAriaOwns = [...oldAriaOwns, menuContentId];
2624
+ } else {
2625
+ newAriaOwns = oldAriaOwns.filter((id) => id !== menuContentId);
2626
+ }
2627
+ if (newAriaOwns.length > 0) {
2628
+ managerEl.setAttribute("aria-owns", newAriaOwns.join(" "));
2629
+ } else {
2630
+ managerEl.removeAttribute("aria-owns");
2631
+ }
2632
+ }
2633
+ },
2634
+ [menuContentId]
2635
+ );
2636
+ const issueMessagesId = prefix(`annexes-issue-messages-${generatedId}`);
2637
+ const [issuesPopoverOpen, setIssuesPopoverOpen] = useState(false);
2638
+ const [menuTriggerFocused, setMenuTriggerFocused] = useState(false);
2639
+ const handleMenuTriggerFocus = useCallback(() => {
2640
+ setMenuTriggerFocused(true);
2641
+ }, []);
2642
+ const handleMenuTriggerBlur = useCallback(() => {
2643
+ setMenuTriggerFocused(false);
2644
+ }, []);
2645
+ const handleIssuesPopoverOpenAutoFocus = useCallback(
2646
+ (evt) => {
2647
+ if (menuTriggerFocused) {
2648
+ evt.preventDefault();
2649
+ }
2650
+ },
2651
+ [menuTriggerFocused]
2652
+ );
2653
+ const feedbackList = /* @__PURE__ */ jsx(FeedbackList, { id: issueMessagesId, hidden: issuesDisplayMode === "panel", children: tablessStates.map((state, i) => /* @__PURE__ */ jsx(
2654
+ IssueMessages,
2655
+ {
2656
+ path: state.path,
2657
+ issues: deferredTablessIssuesToDisplay[i] ?? [],
2658
+ unwrapped: true
2659
+ },
2660
+ state.path.toString()
2661
+ )) });
2662
+ const combinedManagerRef = useCombinedRef(managerRef, forwardedRef);
2501
2663
  return /* @__PURE__ */ jsxs(
2502
2664
  "nav",
2503
2665
  {
2504
2666
  className: cx(prefix("annexes__manager"), className),
2505
2667
  "aria-label": ariaLabel,
2506
2668
  ...otherProps,
2507
- ref: forwardedRef,
2669
+ ref: combinedManagerRef,
2508
2670
  children: [
2509
2671
  shouldRenderMenu && /* @__PURE__ */ jsx(
2510
2672
  "div",
@@ -2518,6 +2680,7 @@ const AnnexesManager = forwardRef(function AnnexManager2({
2518
2680
  AnnexesMenu,
2519
2681
  {
2520
2682
  menuButtonText,
2683
+ menuButtonLabel,
2521
2684
  addAnnexText,
2522
2685
  removeAnnexButtonLabel,
2523
2686
  removeAnnexKeyboardHint,
@@ -2526,28 +2689,44 @@ const AnnexesManager = forwardRef(function AnnexManager2({
2526
2689
  removeAnnexConfirmDialogOkText,
2527
2690
  removeAnnexConfirmDialogCancelText,
2528
2691
  ...menuProps,
2529
- menuTriggerProps,
2530
- menuContentProps
2692
+ onOpenChange: combineEventHandlers(
2693
+ handleAnnexesMenuOpenChange,
2694
+ menuProps?.onOpenChange
2695
+ ),
2696
+ menuTriggerProps: {
2697
+ "aria-invalid": hasErrors || void 0,
2698
+ ...menuTriggerProps,
2699
+ "aria-describedby": combineAriaIds(
2700
+ menuTriggerProps?.["aria-describedby"],
2701
+ issueMessagesId
2702
+ ),
2703
+ onFocus: combineEventHandlers(
2704
+ menuTriggerProps?.onFocus,
2705
+ handleMenuTriggerFocus
2706
+ ),
2707
+ onBlur: combineEventHandlers(
2708
+ menuTriggerProps?.onBlur,
2709
+ handleMenuTriggerBlur
2710
+ )
2711
+ },
2712
+ menuContentProps: { ...menuContentProps, id: menuContentId }
2531
2713
  }
2532
2714
  )
2533
2715
  }
2534
2716
  ),
2717
+ shouldRenderMenu && issuesDisplayMode === "panel" && hasIssues && feedbackList,
2535
2718
  shouldRenderMenu && issuesDisplayMode === "inline" && /* @__PURE__ */ jsx(
2536
2719
  IssuesPopover,
2537
2720
  {
2721
+ open: hasIssues && (menuTriggerFocused || issuesPopoverOpen),
2722
+ onOpenChange: setIssuesPopoverOpen,
2723
+ onOpenAutoFocus: handleIssuesPopoverOpenAutoFocus,
2538
2724
  buttonContainerProps: {
2539
2725
  className: prefix("annexes__issues-popover-container")
2540
2726
  },
2727
+ iconButtonProps: { tabIndex: -1 },
2541
2728
  relevantPaths: tablessPaths,
2542
- children: /* @__PURE__ */ jsx(FeedbackList, { children: tablessStates.map((state, i) => /* @__PURE__ */ jsx(
2543
- IssueMessages,
2544
- {
2545
- path: state.path,
2546
- issues: deferredTablessIssuesToDisplay[i] ?? [],
2547
- unwrapped: true
2548
- },
2549
- state.path.toString()
2550
- )) })
2729
+ children: feedbackList
2551
2730
  }
2552
2731
  ),
2553
2732
  /* @__PURE__ */ jsx(
@@ -3045,9 +3224,7 @@ const DateControl = forwardRef(function DateControl2({
3045
3224
  onDisplayStatusChange,
3046
3225
  onDirtyStatusChange,
3047
3226
  onTouchedStatusChange,
3048
- locale: dateFnsLocale,
3049
- shortFormat,
3050
- fullFormat,
3227
+ format: dateFormat,
3051
3228
  required,
3052
3229
  minDate,
3053
3230
  maxDate,
@@ -3061,9 +3238,7 @@ const DateControl = forwardRef(function DateControl2({
3061
3238
  ...otherProps
3062
3239
  }, forwardedRef) {
3063
3240
  const { format: format2, parse } = useTemporalStringTransformer({
3064
- locale: dateFnsLocale,
3065
- shortFormat,
3066
- fullFormat
3241
+ format: dateFormat
3067
3242
  });
3068
3243
  const [formattedValue, setFormattedValue] = useState("");
3069
3244
  const controller = useTemporalInput(path, {
@@ -3132,9 +3307,7 @@ const DateControl = forwardRef(function DateControl2({
3132
3307
  {
3133
3308
  value: formattedValue,
3134
3309
  name: inputProps.name,
3135
- locale: dateFnsLocale,
3136
- shortFormat,
3137
- fullFormat,
3310
+ format: dateFormat,
3138
3311
  required: required ?? restrictions.required === true,
3139
3312
  minDate: minDate ?? minDateRestriction(schema),
3140
3313
  maxDate: maxDate ?? maxDateRestriction(schema),
@@ -3199,9 +3372,7 @@ const DateRangeControl = forwardRef(function DateRangeControl2({
3199
3372
  onEndDirtyStatusChange,
3200
3373
  onEndTouchedStatusChange,
3201
3374
  onValueChange,
3202
- locale: dateFnsLocale,
3203
- shortFormat,
3204
- fullFormat,
3375
+ format: dateFormat,
3205
3376
  onBlurToOutside,
3206
3377
  endAdornment,
3207
3378
  ...otherProps
@@ -3210,9 +3381,7 @@ const DateRangeControl = forwardRef(function DateRangeControl2({
3210
3381
  issuesPanelStartLabelSuffix ??= locale7.DateRangeControl.issuesPanelStartLabelSuffix;
3211
3382
  issuesPanelEndLabelSuffix ??= locale7.DateRangeControl.issuesPanelEndLabelSuffix;
3212
3383
  const { format: format2, parse } = useTemporalStringTransformer({
3213
- locale: dateFnsLocale,
3214
- shortFormat,
3215
- fullFormat
3384
+ format: dateFormat
3216
3385
  });
3217
3386
  const [formattedValue, setFormattedValue] = useState({
3218
3387
  start: "",
@@ -3338,9 +3507,7 @@ const DateRangeControl = forwardRef(function DateRangeControl2({
3338
3507
  DateRangeInput,
3339
3508
  {
3340
3509
  value: formattedValue,
3341
- locale: dateFnsLocale,
3342
- shortFormat,
3343
- fullFormat,
3510
+ format: dateFormat,
3344
3511
  required: required ?? (startRestrictions.required === true || endRestrictions.required === true),
3345
3512
  minDate: minDate ?? minDateRestriction(startSchema),
3346
3513
  maxDate: maxDate ?? maxDateRestriction(endSchema),
@@ -3777,6 +3944,7 @@ const FormPageHeader = forwardRef(function FormPageHeader2({
3777
3944
  ...otherProps
3778
3945
  }, forwardedRef) {
3779
3946
  const prefix = usePrefix();
3947
+ const [locale7] = useLocale();
3780
3948
  const printing = usePrinting();
3781
3949
  const currentPath = useCurrentPath();
3782
3950
  const issuesDisplayMode = useIssuesDisplayMode();
@@ -3792,6 +3960,10 @@ const FormPageHeader = forwardRef(function FormPageHeader2({
3792
3960
  );
3793
3961
  const code = useFormPageState(currentPath, (state) => state?.code);
3794
3962
  const title = useFormPageState(currentPath, (state) => state?.title);
3963
+ const visuallyHiddenCodePrefix = useFormPageState(
3964
+ currentPath,
3965
+ (state) => state?.visuallyHiddenCodePrefix ?? locale7.FormPage.visuallyHiddenCodePrefix
3966
+ );
3795
3967
  return /* @__PURE__ */ jsxs(
3796
3968
  "div",
3797
3969
  {
@@ -3802,24 +3974,34 @@ const FormPageHeader = forwardRef(function FormPageHeader2({
3802
3974
  ),
3803
3975
  ref: forwardedRef,
3804
3976
  children: [
3805
- /* @__PURE__ */ jsx(
3806
- "div",
3807
- {
3808
- ...codeProps,
3809
- className: cx(prefix("form-pages__page-code"), codeProps?.className),
3810
- "data-status": displayStatusToControlStatus(deferredDisplayStatus),
3811
- "data-accent": controlStatusToAccent(
3812
- displayStatusToControlStatus(deferredDisplayStatus)
3813
- ),
3814
- children: code
3815
- }
3816
- ),
3817
- /* @__PURE__ */ jsx(
3977
+ /* @__PURE__ */ jsxs(
3818
3978
  "h2",
3819
3979
  {
3980
+ tabIndex: -1,
3820
3981
  ...titleProps,
3821
3982
  className: cx(prefix("form-pages__page-title"), titleProps?.className),
3822
- children: title
3983
+ children: [
3984
+ /* @__PURE__ */ jsx(
3985
+ "span",
3986
+ {
3987
+ ...codeProps,
3988
+ className: cx(prefix("form-pages__page-code"), codeProps?.className),
3989
+ "data-status": displayStatusToControlStatus(deferredDisplayStatus),
3990
+ "data-accent": controlStatusToAccent(
3991
+ displayStatusToControlStatus(deferredDisplayStatus)
3992
+ ),
3993
+ children: code != null && typeof code !== "boolean" && /* @__PURE__ */ jsxs(Fragment, { children: [
3994
+ visuallyHiddenCodePrefix && /* @__PURE__ */ jsxs(VisuallyHidden, { children: [
3995
+ visuallyHiddenCodePrefix,
3996
+ " "
3997
+ ] }),
3998
+ code,
3999
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: ", " })
4000
+ ] })
4001
+ }
4002
+ ),
4003
+ title
4004
+ ]
3823
4005
  }
3824
4006
  ),
3825
4007
  !printing && /* @__PURE__ */ jsxs(
@@ -3907,6 +4089,7 @@ const FormPage = forwardRef(
3907
4089
  className,
3908
4090
  helperText,
3909
4091
  helperButtonLabel,
4092
+ visuallyHiddenCodePrefix: _visuallyHiddenCodePrefix,
3910
4093
  issueMessages,
3911
4094
  ownIssueMessages,
3912
4095
  headerProps,
@@ -3922,12 +4105,16 @@ const FormPage = forwardRef(
3922
4105
  helperPopoverProps,
3923
4106
  helperPopoverContentProps,
3924
4107
  children,
4108
+ "aria-label": ariaLabel,
4109
+ "aria-labelledby": ariaLabelledBy,
3925
4110
  ...otherProps
3926
4111
  }, forwardedRef) {
3927
4112
  const prefix = usePrefix();
3928
4113
  const [locale7] = useLocale();
3929
4114
  helperButtonLabel ??= locale7.FormPage.helperButtonLabel;
3930
4115
  const printing = usePrinting();
4116
+ const generatedId = useId();
4117
+ const titleId = titleProps?.id ?? prefix(`form-page-title-${generatedId}`);
3931
4118
  const store = useFormPagesContext();
3932
4119
  const pagePath = useResolvedPath(path);
3933
4120
  const activePage = useStore(store, (state) => state.activePage);
@@ -3971,9 +4158,11 @@ const FormPage = forwardRef(
3971
4158
  {
3972
4159
  title: printing ? void 0 : documentTitle ?? void 0,
3973
4160
  children: /* @__PURE__ */ jsx(
3974
- "div",
4161
+ "section",
3975
4162
  {
3976
4163
  className: cx(prefix("form-pages__page"), className),
4164
+ "aria-label": ariaLabel,
4165
+ "aria-labelledby": ariaLabelledBy ?? (ariaLabel === void 0 ? titleId : void 0),
3977
4166
  ...otherProps,
3978
4167
  ref: forwardedRef,
3979
4168
  children: /* @__PURE__ */ jsx(FormAppStatus, { disabled, readOnly, children: /* @__PURE__ */ jsxs(FormAppIssueMessages, { issueMessages, children: [
@@ -3984,7 +4173,7 @@ const FormPage = forwardRef(
3984
4173
  helperButtonLabel,
3985
4174
  ownIssueMessages,
3986
4175
  codeProps,
3987
- titleProps,
4176
+ titleProps: { ...titleProps, id: titleId },
3988
4177
  headerPopoverContainerProps,
3989
4178
  issuesPopoverProps,
3990
4179
  issueMessagesProps,
@@ -4100,6 +4289,7 @@ const FormPages = forwardRef(
4100
4289
  title: child.props.title,
4101
4290
  documentTitle: child.props.documentTitle,
4102
4291
  code: child.props.code,
4292
+ visuallyHiddenCodePrefix: child.props.visuallyHiddenCodePrefix,
4103
4293
  issuesPanelLabel: child.props.issuesPanelLabel
4104
4294
  }));
4105
4295
  const resolvedPages = useMemo(
@@ -4291,6 +4481,7 @@ const FormPagesSelect = forwardRef(function FormPagesSelect2({
4291
4481
  );
4292
4482
  });
4293
4483
  function FormPageSidebarItem({ path }) {
4484
+ const [locale7] = useLocale();
4294
4485
  const prefix = usePrefix();
4295
4486
  const store = useFormPagesContext();
4296
4487
  const activePage = useStore(store, (state) => state.activePage);
@@ -4302,6 +4493,10 @@ function FormPageSidebarItem({ path }) {
4302
4493
  );
4303
4494
  const code = useFormPageState(path, (state) => state?.code);
4304
4495
  const title = useFormPageState(path, (state) => state?.title);
4496
+ const visuallyHiddenCodePrefix = useFormPageState(
4497
+ path,
4498
+ (state) => state?.visuallyHiddenCodePrefix ?? locale7.FormPage.visuallyHiddenCodePrefix
4499
+ );
4305
4500
  const issuesDisplayMode = useIssuesDisplayMode();
4306
4501
  const itemActionRef = useRef(null);
4307
4502
  const resetFocus = useResetFocus();
@@ -4328,7 +4523,11 @@ function FormPageSidebarItem({ path }) {
4328
4523
  onSelect: handleClick,
4329
4524
  color: "primary",
4330
4525
  contentProps: { className: prefix("form-pages__sidebar-item-content") },
4331
- actionProps: { ref: itemActionRef },
4526
+ actionProps: {
4527
+ "aria-current": isSelected ? "page" : void 0,
4528
+ "aria-invalid": deferredDisplayStatus === "error" || void 0,
4529
+ ref: itemActionRef
4530
+ },
4332
4531
  children: /* @__PURE__ */ jsxs(CurrentPath, { path, children: [
4333
4532
  /* @__PURE__ */ jsx(
4334
4533
  "span",
@@ -4339,7 +4538,14 @@ function FormPageSidebarItem({ path }) {
4339
4538
  "data-accent": controlStatusToAccent(
4340
4539
  displayStatusToControlStatus(deferredDisplayStatus)
4341
4540
  ),
4342
- children: code
4541
+ children: code != null && typeof code !== "boolean" && /* @__PURE__ */ jsxs(Fragment, { children: [
4542
+ visuallyHiddenCodePrefix && /* @__PURE__ */ jsxs(VisuallyHidden, { children: [
4543
+ visuallyHiddenCodePrefix,
4544
+ " "
4545
+ ] }),
4546
+ code,
4547
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: ", " })
4548
+ ] })
4343
4549
  }
4344
4550
  ),
4345
4551
  title
@@ -4368,7 +4574,7 @@ const FormPagesSidebar = forwardRef(function FormPagesSidebar2({ className, ...o
4368
4574
  const pages = useStore(store, (state) => state.pages);
4369
4575
  const combinedSidebarRef = useCombinedRef(setSidebarEl, forwardedRef);
4370
4576
  return /* @__PURE__ */ jsx(
4371
- "aside",
4577
+ "div",
4372
4578
  {
4373
4579
  className: cx(prefix("form-pages__sidebar"), className),
4374
4580
  ...otherProps,
@@ -4832,10 +5038,15 @@ function IssuesPanelControls({
4832
5038
  buttonsColor,
4833
5039
  closePanel,
4834
5040
  focusButtonLabel,
5041
+ focusKeybinds,
4835
5042
  previousIssueButtonLabel,
5043
+ previousIssueKeybinds,
4836
5044
  nextIssueButtonLabel,
5045
+ nextIssueKeybinds,
4837
5046
  firstIssueButtonLabel,
5047
+ firstIssueKeybinds,
4838
5048
  lastIssueButtonLabel,
5049
+ lastIssueKeybinds,
4839
5050
  paginationLabel,
4840
5051
  validatingSpinnerProps,
4841
5052
  paginationProps,
@@ -4847,11 +5058,48 @@ function IssuesPanelControls({
4847
5058
  closeButtonProps
4848
5059
  }) {
4849
5060
  const prefix = usePrefix();
5061
+ const formIsDisabled = useFormIsDisabled();
4850
5062
  const { validating } = useFormIsValidating();
4851
5063
  const deferredValidating = useDeferredValue(validating);
4852
5064
  const currentPageInitialized = currentPageController.useInitialized();
4853
5065
  const currentPageExists = currentPageController.useExists();
4854
5066
  const focus = useFocus();
5067
+ const handleFocus = useCallback(
5068
+ () => focus(currentPagePath),
5069
+ [currentPagePath, focus]
5070
+ );
5071
+ const focusButtonLoading = !currentPageInitialized;
5072
+ const focusButtonDisabled = formIsDisabled || !currentPageExists;
5073
+ const firstIssueButtonDisabled = formIsDisabled || firstIssueButtonProps?.disabled || currentPageIndex === 0;
5074
+ const previousIssueButtonDisabled = formIsDisabled || previousIssueButtonProps?.disabled || currentPageIndex === 0;
5075
+ const nextIssueButtonDisabled = formIsDisabled || nextIssueButtonProps?.disabled || currentPageIndex === nPages - 1;
5076
+ const lastIssueButtonDisabled = formIsDisabled || lastIssueButtonProps?.disabled || currentPageIndex === nPages - 1;
5077
+ const formAppEl = useFormAppElement();
5078
+ useKeyboardShortcut(focusKeybinds, handleFocus, {
5079
+ disabled: focusButtonLoading || focusButtonDisabled,
5080
+ target: formAppEl,
5081
+ preventDefault: true
5082
+ });
5083
+ useKeyboardShortcut(firstIssueKeybinds, goToFirstPage, {
5084
+ disabled: firstIssueButtonDisabled,
5085
+ target: formAppEl,
5086
+ preventDefault: true
5087
+ });
5088
+ useKeyboardShortcut(previousIssueKeybinds, goToPreviousPage, {
5089
+ disabled: previousIssueButtonDisabled,
5090
+ target: formAppEl,
5091
+ preventDefault: true
5092
+ });
5093
+ useKeyboardShortcut(nextIssueKeybinds, goToNextPage, {
5094
+ disabled: nextIssueButtonDisabled,
5095
+ target: formAppEl,
5096
+ preventDefault: true
5097
+ });
5098
+ useKeyboardShortcut(lastIssueKeybinds, goToLastPage, {
5099
+ disabled: lastIssueButtonDisabled,
5100
+ target: formAppEl,
5101
+ preventDefault: true
5102
+ });
4855
5103
  return /* @__PURE__ */ jsxs("div", { className: prefix("issues-panel__controls"), children: [
4856
5104
  nPages > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
4857
5105
  deferredValidating && /* @__PURE__ */ jsx(
@@ -4868,7 +5116,7 @@ function IssuesPanelControls({
4868
5116
  "div",
4869
5117
  {
4870
5118
  role: "presentation",
4871
- "aria-live": "polite",
5119
+ "aria-live": "assertive",
4872
5120
  ...paginationProps,
4873
5121
  className: cx(
4874
5122
  prefix("issues-panel__pagination"),
@@ -4895,12 +5143,13 @@ function IssuesPanelControls({
4895
5143
  prefix("issues-panel__focus"),
4896
5144
  focusButtonProps?.className
4897
5145
  ),
4898
- label: focusButtonLabel ?? "",
4899
- loading: !currentPageInitialized,
4900
- disabled: !currentPageExists,
5146
+ label: focusButtonLabel,
5147
+ keybinds: focusKeybinds,
5148
+ loading: focusButtonLoading,
5149
+ disabled: focusButtonDisabled,
4901
5150
  onClick: combineEventHandlers(
4902
5151
  focusButtonProps?.onClick,
4903
- () => focus(currentPagePath)
5152
+ handleFocus
4904
5153
  )
4905
5154
  }
4906
5155
  ),
@@ -4915,8 +5164,9 @@ function IssuesPanelControls({
4915
5164
  prefix("issues-panel__first"),
4916
5165
  firstIssueButtonProps?.className
4917
5166
  ),
4918
- label: firstIssueButtonLabel ?? "",
4919
- disabled: firstIssueButtonProps?.disabled || currentPageIndex === 0,
5167
+ label: firstIssueButtonLabel,
5168
+ keybinds: firstIssueKeybinds,
5169
+ disabled: firstIssueButtonDisabled,
4920
5170
  onClick: combineEventHandlers(
4921
5171
  firstIssueButtonProps?.onClick,
4922
5172
  goToFirstPage
@@ -4934,8 +5184,9 @@ function IssuesPanelControls({
4934
5184
  prefix("issues-panel__previous"),
4935
5185
  previousIssueButtonProps?.className
4936
5186
  ),
4937
- label: previousIssueButtonLabel ?? "",
4938
- disabled: previousIssueButtonProps?.disabled || currentPageIndex === 0,
5187
+ label: previousIssueButtonLabel,
5188
+ keybinds: previousIssueKeybinds,
5189
+ disabled: previousIssueButtonDisabled,
4939
5190
  onClick: combineEventHandlers(
4940
5191
  previousIssueButtonProps?.onClick,
4941
5192
  goToPreviousPage
@@ -4953,8 +5204,9 @@ function IssuesPanelControls({
4953
5204
  prefix("issues-panel__next"),
4954
5205
  nextIssueButtonProps?.className
4955
5206
  ),
4956
- label: nextIssueButtonLabel ?? "",
4957
- disabled: nextIssueButtonProps?.disabled || currentPageIndex === nPages - 1,
5207
+ label: nextIssueButtonLabel,
5208
+ keybinds: nextIssueKeybinds,
5209
+ disabled: nextIssueButtonDisabled,
4958
5210
  onClick: combineEventHandlers(
4959
5211
  nextIssueButtonProps?.onClick,
4960
5212
  goToNextPage
@@ -4972,8 +5224,9 @@ function IssuesPanelControls({
4972
5224
  prefix("issues-panel__last"),
4973
5225
  lastIssueButtonProps?.className
4974
5226
  ),
4975
- label: lastIssueButtonLabel ?? "",
4976
- disabled: lastIssueButtonProps?.disabled || currentPageIndex === nPages - 1,
5227
+ label: lastIssueButtonLabel,
5228
+ keybinds: lastIssueKeybinds,
5229
+ disabled: lastIssueButtonDisabled,
4977
5230
  onClick: combineEventHandlers(
4978
5231
  lastIssueButtonProps?.onClick,
4979
5232
  goToLastPage
@@ -5126,8 +5379,6 @@ const IssuesPanelMessagesCard = forwardRef(function IssuesPanelMessagesCard2({
5126
5379
  /* @__PURE__ */ jsx(
5127
5380
  CardTitle,
5128
5381
  {
5129
- role: "presentation",
5130
- "aria-live": "polite",
5131
5382
  ...titleProps,
5132
5383
  className: cx(
5133
5384
  prefix("issues-panel__title"),
@@ -5236,7 +5487,7 @@ const IssuesPanelSummaryCard = forwardRef(function IssuesPanelSummaryCard2({
5236
5487
  CardTitle,
5237
5488
  {
5238
5489
  role: "presentation",
5239
- "aria-live": "polite",
5490
+ "aria-live": "assertive",
5240
5491
  ...titleProps,
5241
5492
  className: cx(
5242
5493
  prefix("issues-panel__title"),
@@ -5260,6 +5511,11 @@ const IssuesPanelSummaryCard = forwardRef(function IssuesPanelSummaryCard2({
5260
5511
  }
5261
5512
  );
5262
5513
  });
5514
+ const DEFAULT_FOCUS_KEYBINDS = "Alt+Shift+F";
5515
+ const DEFAULT_PREVIOUS_ISSUE_KEYBINDS = "Alt+Shift+ArrowLeft";
5516
+ const DEFAULT_NEXT_ISSUE_KEYBINDS = "Alt+Shift+ArrowRight";
5517
+ const DEFAULT_FIRST_ISSUE_KEYBINDS = "Alt+Shift+Home";
5518
+ const DEFAULT_LAST_ISSUE_KEYBINDS = "Alt+Shift+End";
5263
5519
  const IssuesPanel = forwardRef(function ValidationPanel({
5264
5520
  defaultOpen = false,
5265
5521
  open: controlledOpen,
@@ -5271,10 +5527,15 @@ const IssuesPanel = forwardRef(function ValidationPanel({
5271
5527
  errorsLabel,
5272
5528
  warningsLabel,
5273
5529
  focusButtonLabel,
5530
+ focusKeybinds,
5274
5531
  previousIssueButtonLabel,
5532
+ previousIssueKeybinds,
5275
5533
  nextIssueButtonLabel,
5534
+ nextIssueKeybinds,
5276
5535
  firstIssueButtonLabel,
5536
+ firstIssueKeybinds,
5277
5537
  lastIssueButtonLabel,
5538
+ lastIssueKeybinds,
5278
5539
  paginationLabel,
5279
5540
  noIssuesMessage,
5280
5541
  resolvedTitle,
@@ -5301,10 +5562,25 @@ const IssuesPanel = forwardRef(function ValidationPanel({
5301
5562
  errorsLabel ??= locale7.IssuesPanel.errorsLabel;
5302
5563
  warningsLabel ??= locale7.IssuesPanel.warningsLabel;
5303
5564
  focusButtonLabel ??= locale7.IssuesPanel.focusButtonLabel;
5565
+ if (focusKeybinds === void 0) {
5566
+ focusKeybinds = locale7.IssuesPanel.focusKeybinds ?? DEFAULT_FOCUS_KEYBINDS;
5567
+ }
5304
5568
  previousIssueButtonLabel ??= locale7.IssuesPanel.previousIssueButtonLabel;
5569
+ if (previousIssueKeybinds === void 0) {
5570
+ previousIssueKeybinds = locale7.IssuesPanel.previousIssueKeybinds ?? DEFAULT_PREVIOUS_ISSUE_KEYBINDS;
5571
+ }
5305
5572
  nextIssueButtonLabel ??= locale7.IssuesPanel.nextIssueButtonLabel;
5573
+ if (nextIssueKeybinds === void 0) {
5574
+ nextIssueKeybinds = locale7.IssuesPanel.nextIssueKeybinds ?? DEFAULT_NEXT_ISSUE_KEYBINDS;
5575
+ }
5306
5576
  firstIssueButtonLabel ??= locale7.IssuesPanel.firstIssueButtonLabel;
5577
+ if (firstIssueKeybinds === void 0) {
5578
+ firstIssueKeybinds = locale7.IssuesPanel.firstIssueKeybinds ?? DEFAULT_FIRST_ISSUE_KEYBINDS;
5579
+ }
5307
5580
  lastIssueButtonLabel ??= locale7.IssuesPanel.lastIssueButtonLabel;
5581
+ if (lastIssueKeybinds === void 0) {
5582
+ lastIssueKeybinds = locale7.IssuesPanel.lastIssueKeybinds ?? DEFAULT_LAST_ISSUE_KEYBINDS;
5583
+ }
5308
5584
  paginationLabel ??= locale7.IssuesPanel.paginationLabel;
5309
5585
  noIssuesMessage ??= locale7.IssuesPanel.noIssuesMessage;
5310
5586
  resolvedTitle ??= locale7.IssuesPanel.resolvedTitle;
@@ -5325,6 +5601,17 @@ const IssuesPanel = forwardRef(function ValidationPanel({
5325
5601
  currentPagePath ?? AbsolutePath.ROOT,
5326
5602
  { enabled: open && !formIsLoading && currentPagePath !== null }
5327
5603
  );
5604
+ useEffect(() => {
5605
+ if (currentPagePath === null && issuesTrackerResult.initialized && issuesTrackerResult.info.length > 0) {
5606
+ setCurrentPagePath(latestInteraction);
5607
+ }
5608
+ }, [
5609
+ currentPagePath,
5610
+ issuesTrackerResult.info?.length,
5611
+ issuesTrackerResult.initialized,
5612
+ latestInteraction,
5613
+ setCurrentPagePath
5614
+ ]);
5328
5615
  const lastExistingPageIndex = useRef(null);
5329
5616
  const currentPageIndex = useMemo(() => {
5330
5617
  const idx = currentPagePath ? info?.findIndex(({ path }) => currentPagePath.equals(path)) ?? -1 : -1;
@@ -5455,10 +5742,15 @@ const IssuesPanel = forwardRef(function ValidationPanel({
5455
5742
  buttonsColor,
5456
5743
  closePanel: close,
5457
5744
  focusButtonLabel,
5745
+ focusKeybinds,
5458
5746
  previousIssueButtonLabel,
5747
+ previousIssueKeybinds,
5459
5748
  nextIssueButtonLabel,
5749
+ nextIssueKeybinds,
5460
5750
  firstIssueButtonLabel,
5751
+ firstIssueKeybinds,
5461
5752
  lastIssueButtonLabel,
5753
+ lastIssueKeybinds,
5462
5754
  paginationLabel,
5463
5755
  validatingSpinnerProps,
5464
5756
  paginationProps,
@@ -5560,6 +5852,7 @@ function mostRelevantIssuePath(info, latestInteraction, formSchema, issuesOrderC
5560
5852
  }
5561
5853
  return info[0].path;
5562
5854
  }
5855
+ const DEFAULT_LOAD_KEYBINDS = "$mod+O";
5563
5856
  function LoadAction({
5564
5857
  label,
5565
5858
  keybinds,
@@ -5581,7 +5874,9 @@ function LoadAction({
5581
5874
  }) {
5582
5875
  const [locale7] = useLocale();
5583
5876
  label ??= locale7.LoadAction.label;
5584
- keybinds ??= locale7.LoadAction.keybinds;
5877
+ if (keybinds === void 0) {
5878
+ keybinds = locale7.LoadAction.keybinds ?? DEFAULT_LOAD_KEYBINDS;
5879
+ }
5585
5880
  const { load } = useFormLoader({
5586
5881
  decode,
5587
5882
  path,
@@ -5599,7 +5894,7 @@ function LoadAction({
5599
5894
  const formIsLoading = useFormIsLoading();
5600
5895
  const formAppEl = useFormAppElement();
5601
5896
  useKeyboardShortcut(keybinds, () => load(), {
5602
- enabled: !disabled && !loading && !formIsDisabled && !formIsLoading,
5897
+ disabled: disabled || loading || formIsDisabled || formIsLoading,
5603
5898
  target: formAppEl,
5604
5899
  preventDefault: true
5605
5900
  });
@@ -5613,6 +5908,7 @@ function LoadAction({
5613
5908
  onClick: combineEventHandlers(() => load(), onClick),
5614
5909
  disabled: disabled || formIsDisabled,
5615
5910
  loading: loading || formIsLoading,
5911
+ keybinds,
5616
5912
  children: label
5617
5913
  }
5618
5914
  );
@@ -5769,6 +6065,7 @@ const PathLink = forwardRef(function PathLink2({ to, buildHref = DEFAULT_HREF_BU
5769
6065
  }
5770
6066
  );
5771
6067
  });
6068
+ const DEFAULT_PRINT_KEYBINDS = "$mod+P";
5772
6069
  function PrintAction({
5773
6070
  label,
5774
6071
  keybinds,
@@ -5779,7 +6076,9 @@ function PrintAction({
5779
6076
  }) {
5780
6077
  const [locale7] = useLocale();
5781
6078
  label ??= locale7.PrintAction.label;
5782
- keybinds ??= locale7.PrintAction.keybinds;
6079
+ if (keybinds === void 0) {
6080
+ keybinds = locale7.PrintAction.keybinds ?? DEFAULT_PRINT_KEYBINDS;
6081
+ }
5783
6082
  const printInProgress = usePrintInProgress();
5784
6083
  const formIsDisabled = useFormIsDisabled();
5785
6084
  const formIsLoading = useFormIsLoading();
@@ -5794,7 +6093,7 @@ function PrintAction({
5794
6093
  );
5795
6094
  };
5796
6095
  useKeyboardShortcut(keybinds, handlePrint, {
5797
- enabled: !disabled && !loading && !formIsDisabled && !formIsLoading && !printInProgress,
6096
+ disabled: disabled || loading || formIsDisabled || formIsLoading || printInProgress,
5798
6097
  target: formAppEl,
5799
6098
  preventDefault: true
5800
6099
  });
@@ -5813,6 +6112,7 @@ function PrintAction({
5813
6112
  ...otherProps,
5814
6113
  loading: loading || printInProgress,
5815
6114
  disabled: disabled || formIsDisabled || formIsLoading,
6115
+ keybinds,
5816
6116
  children: label
5817
6117
  }
5818
6118
  )
@@ -6116,6 +6416,8 @@ function defaultFileName(formTitle, extension) {
6116
6416
  const date = format(/* @__PURE__ */ new Date(), "yyyy-MM-dd");
6117
6417
  return [[formTitle, date].filter(Boolean).join(" "), extension].filter(Boolean).join("");
6118
6418
  }
6419
+ const DEFAULT_SAVE_KEYBINDS = "$mod+S";
6420
+ const DEFAULT_SAVE_AS_KEYBINDS = "$mod+Shift+S";
6119
6421
  function SaveAction({
6120
6422
  label,
6121
6423
  keybinds,
@@ -6145,10 +6447,14 @@ function SaveAction({
6145
6447
  }) {
6146
6448
  const [locale7] = useLocale();
6147
6449
  label ??= locale7.SaveAction.label;
6148
- keybinds ??= locale7.SaveAction.keybinds;
6450
+ if (keybinds === void 0) {
6451
+ keybinds = locale7.SaveAction.keybinds ?? DEFAULT_SAVE_KEYBINDS;
6452
+ }
6149
6453
  saveOptionsLabel ??= locale7.SaveAction.saveOptionsLabel;
6150
6454
  saveAsLabel ??= locale7.SaveAction.saveAsLabel;
6151
- saveAsKeybinds ??= locale7.SaveAction.saveAsKeybinds;
6455
+ if (saveAsKeybinds === void 0) {
6456
+ saveAsKeybinds = locale7.SaveAction.saveAsKeybinds ?? DEFAULT_SAVE_AS_KEYBINDS;
6457
+ }
6152
6458
  const { save, supportsFileSystemAPIs } = useFormSaver({
6153
6459
  path,
6154
6460
  encode,
@@ -6165,14 +6471,14 @@ function SaveAction({
6165
6471
  const formIsSaving = useFormIsSaving();
6166
6472
  const formIsLoading = useFormIsLoading();
6167
6473
  const formAppEl = useFormAppElement();
6168
- const shortcutsEnabled = !disabled && !loading && !formIsSaving && !formIsLoading;
6474
+ const shortcutsDisabled = disabled || loading || formIsSaving || formIsLoading;
6169
6475
  useKeyboardShortcut(keybinds, () => save({ overwrite: !disableOverwrite }), {
6170
- enabled: shortcutsEnabled,
6476
+ disabled: shortcutsDisabled,
6171
6477
  target: formAppEl,
6172
6478
  preventDefault: true
6173
6479
  });
6174
6480
  useKeyboardShortcut(saveAsKeybinds, () => save(), {
6175
- enabled: shortcutsEnabled,
6481
+ disabled: shortcutsDisabled,
6176
6482
  target: formAppEl,
6177
6483
  preventDefault: true
6178
6484
  });
@@ -6190,6 +6496,7 @@ function SaveAction({
6190
6496
  ),
6191
6497
  disabled: disabled || formIsLoading,
6192
6498
  loading: loading || formIsSaving,
6499
+ keybinds,
6193
6500
  children: label
6194
6501
  }
6195
6502
  );
@@ -6214,6 +6521,7 @@ function SaveAction({
6214
6521
  onClick: () => save(),
6215
6522
  disabled: disabled || formIsLoading,
6216
6523
  loading: loading || formIsSaving,
6524
+ keybinds: saveAsKeybinds,
6217
6525
  children: saveAsLabel
6218
6526
  }
6219
6527
  ) })
@@ -6541,6 +6849,7 @@ const SelectMultipleControl = forwardRef(function SelectMultipleControl2({
6541
6849
  inlineIssues
6542
6850
  ] });
6543
6851
  });
6852
+ const DEFAULT_SUBMIT_KEYBINDS = "$mod+Enter";
6544
6853
  function SubmitAction({
6545
6854
  onSubmit,
6546
6855
  onInvalidSubmit,
@@ -6579,7 +6888,9 @@ function SubmitAction({
6579
6888
  const prefix = usePrefix();
6580
6889
  const [locale7] = useLocale();
6581
6890
  label ??= locale7.SubmitAction.label;
6582
- keybinds ??= locale7.SubmitAction.keybinds;
6891
+ if (keybinds === void 0) {
6892
+ keybinds = locale7.SubmitAction.keybinds ?? DEFAULT_SUBMIT_KEYBINDS;
6893
+ }
6583
6894
  dialogTitle ??= locale7.SubmitAction.dialogTitle;
6584
6895
  dialogDescription ??= locale7.SubmitAction.dialogDescription;
6585
6896
  dialogBody ??= locale7.SubmitAction.dialogBody;
@@ -6624,9 +6935,19 @@ function SubmitAction({
6624
6935
  setConfirmingSubmission(false);
6625
6936
  }
6626
6937
  };
6627
- const handleInvalidSubmit = async (issues, event) => {
6628
- await startIssuesNavigation({ validate: false });
6629
- onInvalidSubmit?.(issues, event);
6938
+ const preventCloseAutoFocus = useRef(false);
6939
+ const handleInvalidSubmit = (issues, event) => {
6940
+ preventCloseAutoFocus.current = true;
6941
+ setTimeout(async () => {
6942
+ await startIssuesNavigation({ validate: false });
6943
+ onInvalidSubmit?.(issues, event);
6944
+ });
6945
+ };
6946
+ const handleCloseAutoFocus = (event) => {
6947
+ if (preventCloseAutoFocus.current) {
6948
+ event.preventDefault();
6949
+ }
6950
+ preventCloseAutoFocus.current = false;
6630
6951
  };
6631
6952
  const handleSuccessfulSubmit = (submitResult, event) => {
6632
6953
  const message = typeof successMessage === "function" ? successMessage(submitResult) : successMessage;
@@ -6678,7 +6999,7 @@ function SubmitAction({
6678
6999
  convertExternalIssuesTableRowIndicesToIds
6679
7000
  });
6680
7001
  useKeyboardShortcut(keybinds, handleAction, {
6681
- enabled: !disabled && !loading && !formIsDisabled && !formIsLoading && !submitting,
7002
+ disabled: disabled || loading || formIsDisabled || formIsLoading || submitting,
6682
7003
  target: formAppEl,
6683
7004
  preventDefault: true
6684
7005
  });
@@ -6694,6 +7015,7 @@ function SubmitAction({
6694
7015
  onClick: combineEventHandlers(handleAction, onClick),
6695
7016
  disabled: disabled || formIsDisabled || formIsLoading,
6696
7017
  loading: loading || submitting,
7018
+ keybinds,
6697
7019
  children: label
6698
7020
  }
6699
7021
  ) }),
@@ -6702,6 +7024,11 @@ function SubmitAction({
6702
7024
  {
6703
7025
  color: "primary",
6704
7026
  ...dialogContentProps,
7027
+ onCloseAutoFocus: combineEventHandlers(
7028
+ dialogContentProps?.onCloseAutoFocus,
7029
+ handleCloseAutoFocus,
7030
+ { checkDefaultPrevented: true }
7031
+ ),
6705
7032
  portalProps: {
6706
7033
  container: formAppEl,
6707
7034
  ...dialogContentProps?.portalProps
@@ -7224,8 +7551,7 @@ function tableControlActionsColumn({
7224
7551
  ...columnOverrides
7225
7552
  };
7226
7553
  }
7227
- const TableControlContent = forwardRef(function TableControlContent2({ containerProps, ...otherProps }, forwardedRef) {
7228
- const prefix = usePrefix();
7554
+ const TableControlContent = forwardRef(function TableControlContent2({ scrollableProps, ...otherProps }, forwardedRef) {
7229
7555
  const { autofocusRef, handleFocus, controller } = useTableControlContext();
7230
7556
  const handleContainerOnBlur = useCallback(() => {
7231
7557
  const { initialized, exists, touched } = controller.getState();
@@ -7241,18 +7567,13 @@ const TableControlContent = forwardRef(function TableControlContent2({ container
7241
7567
  editable: true,
7242
7568
  variant: "control",
7243
7569
  status: printing ? void 0 : displayStatusToControlStatus(deferredDisplayStatus),
7244
- containerProps: {
7245
- ...containerProps,
7246
- className: cx(
7247
- prefix("table-control__content-container"),
7248
- containerProps?.className
7249
- ),
7250
- onFocus: combineEventHandlers(containerProps?.onFocus, handleFocus),
7570
+ scrollableProps: {
7571
+ onFocus: combineEventHandlers(scrollableProps?.onFocus, handleFocus),
7251
7572
  onBlur: combineEventHandlers(
7252
- containerProps?.onBlur,
7573
+ scrollableProps?.onBlur,
7253
7574
  handleContainerOnBlur
7254
7575
  ),
7255
- ref: useCombinedRef(autofocusRef, containerProps?.ref)
7576
+ ref: useCombinedRef(autofocusRef, scrollableProps?.ref)
7256
7577
  },
7257
7578
  ...otherProps,
7258
7579
  ref: forwardedRef
@@ -7430,6 +7751,7 @@ const TopBarActions = forwardRef(function TopBarActions2({ className, ...otherPr
7430
7751
  }
7431
7752
  );
7432
7753
  });
7754
+ const DEFAULT_VALIDATE_KEYBINDS = "Alt+Shift+V";
7433
7755
  function ValidateAction({
7434
7756
  label,
7435
7757
  keybinds,
@@ -7440,7 +7762,9 @@ function ValidateAction({
7440
7762
  }) {
7441
7763
  const [locale7] = useLocale();
7442
7764
  label ??= locale7.ValidateAction.label;
7443
- keybinds ??= locale7.ValidateAction.keybinds;
7765
+ if (keybinds === void 0) {
7766
+ keybinds = locale7.ValidateAction.keybinds ?? DEFAULT_VALIDATE_KEYBINDS;
7767
+ }
7444
7768
  const { validate } = useFormValidator();
7445
7769
  const { validatingAutomatically, validatingManually } = useFormIsValidating();
7446
7770
  const deferredValidatingAutomatically = useDeferredValue(
@@ -7450,7 +7774,7 @@ function ValidateAction({
7450
7774
  const formIsLoading = useFormIsLoading();
7451
7775
  const formAppEl = useFormAppElement();
7452
7776
  useKeyboardShortcut(keybinds, validate, {
7453
- enabled: !disabled && !loading && !formIsDisabled && !formIsLoading && !validatingManually,
7777
+ disabled: disabled || loading || formIsDisabled || formIsLoading || validatingManually,
7454
7778
  target: formAppEl,
7455
7779
  preventDefault: true
7456
7780
  });
@@ -7465,6 +7789,7 @@ function ValidateAction({
7465
7789
  loading: loading || validatingManually,
7466
7790
  disabled: disabled || formIsDisabled || formIsLoading,
7467
7791
  showSpinner: deferredValidatingAutomatically,
7792
+ keybinds,
7468
7793
  children: label
7469
7794
  }
7470
7795
  );
@@ -7479,6 +7804,17 @@ export {
7479
7804
  CheckboxControl,
7480
7805
  CheckboxGroupControl,
7481
7806
  ControlField,
7807
+ DEFAULT_FIRST_ISSUE_KEYBINDS,
7808
+ DEFAULT_FOCUS_KEYBINDS,
7809
+ DEFAULT_LAST_ISSUE_KEYBINDS,
7810
+ DEFAULT_LOAD_KEYBINDS,
7811
+ DEFAULT_NEXT_ISSUE_KEYBINDS,
7812
+ DEFAULT_PREVIOUS_ISSUE_KEYBINDS,
7813
+ DEFAULT_PRINT_KEYBINDS,
7814
+ DEFAULT_SAVE_AS_KEYBINDS,
7815
+ DEFAULT_SAVE_KEYBINDS,
7816
+ DEFAULT_SUBMIT_KEYBINDS,
7817
+ DEFAULT_VALIDATE_KEYBINDS,
7482
7818
  DateControl,
7483
7819
  DateRangeControl,
7484
7820
  FileControl,