asma-ui-core 3.105.0 → 3.107.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.
Files changed (72) hide show
  1. package/dist/asma-ui-core.css +1 -1
  2. package/dist/components/custom/module/header-layout/DynamicToolbar.js +99 -97
  3. package/dist/components/custom/module/header-layout/ToolbarActionGroup.js +60 -41
  4. package/dist/components/custom/module/header-layout/ToolbarRows.js +51 -47
  5. package/dist/components/custom/module/header-layout/useTranslations.js +12 -10
  6. package/dist/components/custom/page/page-header/PageHeader.js +41 -40
  7. package/dist/components/custom/widget/widget/StyledWidget.js +21 -20
  8. package/dist/components/data-display/chip/StyledChip.js +70 -53
  9. package/dist/components/data-display/tooltip/StyledTooltip.js +116 -73
  10. package/dist/components/feedback/dialog/DialogBusyContext.js +32 -0
  11. package/dist/components/feedback/dialog/StyledDialog.js +81 -72
  12. package/dist/components/feedback/dialog/dialog-footer/StyledDialogFooter.js +76 -71
  13. package/dist/components/feedback/minimizable-dialog/MinimizableDialog.js +133 -137
  14. package/dist/components/feedback/minimizable-dialog/components/CloseBtn.js +11 -8
  15. package/dist/components/feedback/minimizable-dialog/components/FullscreenBtn.js +6 -6
  16. package/dist/components/feedback/minimizable-dialog/components/MinimizeBtn.js +1 -1
  17. package/dist/components/feedback/minimizable-dialog/v2/MinimizableDialogV2.js +108 -88
  18. package/dist/components/feedback/minimizable-dialog/v2/useTranslations.js +6 -4
  19. package/dist/components/inputs/button/StyledButton.js +83 -33
  20. package/dist/components/inputs/button/StyledButton.module.js +13 -13
  21. package/dist/components/inputs/dynamic-select/components/DynamicInteractiveChipGroup.js +32 -32
  22. package/dist/components/inputs/dynamic-select/components/DynamicSelectAutocomplete.js +6 -6
  23. package/dist/components/inputs/select/StyledSelect.js +8 -8
  24. package/dist/components/inputs/select-autocomplete/StyledSelectAutocomplete.js +14 -14
  25. package/dist/components/navigation/link/StyledLink.js +53 -26
  26. package/dist/components/navigation/link/StyledLink.module.js +6 -6
  27. package/dist/components/navigation/menu/StyledMenuItem.js +35 -30
  28. package/dist/components/navigation/tabs/StyledTab.js +23 -25
  29. package/dist/components/utils/bottom-sheet/StyledBottomSheet.js +6 -6
  30. package/dist/components/utils/copy-wrapper/CopyButton.js +4 -4
  31. package/dist/components/utils/copy-wrapper/CopyWrapper.js +4 -4
  32. package/dist/datetime/components/date-picker/components/BaseDatePickerInput.js +66 -56
  33. package/dist/datetime/components/date-picker/components/DatePickerInputSingle.js +13 -12
  34. package/dist/datetime/components/time-picker/TimePickerInput.js +47 -39
  35. package/dist/datetime/helpers/getTitleLabelling.js +10 -0
  36. package/dist/datetime/shared-components/button/StyledButton.module.js +11 -11
  37. package/dist/helpers/focusable.js +2 -2
  38. package/dist/index.js +589 -585
  39. package/dist/src/components/custom/module/header-layout/ToolbarActionGroup.d.ts +13 -2
  40. package/dist/src/components/custom/module/header-layout/ToolbarRows.d.ts +2 -1
  41. package/dist/src/components/custom/module/header-layout/planToolbarActions.d.ts +18 -1
  42. package/dist/src/components/custom/module/header-layout/useTranslations.d.ts +2 -0
  43. package/dist/src/components/custom/widget/widget/StyledWidget.d.ts +5 -0
  44. package/dist/src/components/data-display/chip/StyledChip.d.ts +6 -0
  45. package/dist/src/components/data-display/interactive-chip/StyledInteractiveChip.d.ts +7 -1
  46. package/dist/src/components/data-display/tooltip/StyledTooltip.d.ts +16 -2
  47. package/dist/src/components/feedback/dialog/DialogBusy.test.d.ts +1 -0
  48. package/dist/src/components/feedback/dialog/DialogBusyContext.d.ts +28 -0
  49. package/dist/src/components/feedback/dialog/StyledDialog.d.ts +5 -0
  50. package/dist/src/components/feedback/dialog/dialog-footer/StyledDialogFooter.d.ts +9 -8
  51. package/dist/src/components/feedback/dialog/index.d.ts +1 -0
  52. package/dist/src/components/feedback/minimizable-dialog/components/CloseBtn.d.ts +2 -0
  53. package/dist/src/components/feedback/minimizable-dialog/types.d.ts +11 -0
  54. package/dist/src/components/feedback/minimizable-dialog/v2/types.d.ts +2 -0
  55. package/dist/src/components/feedback/minimizable-dialog/v2/useTranslations.d.ts +2 -0
  56. package/dist/src/components/inputs/button/StyledButton.d.ts +25 -1
  57. package/dist/src/components/inputs/button/StyledButtonBusy.test.d.ts +1 -0
  58. package/dist/src/components/navigation/link/StyledLink.d.ts +6 -0
  59. package/dist/src/components/navigation/menu/StyledMenuItem.d.ts +8 -1
  60. package/dist/src/components/navigation/tabs/StyledTab.d.ts +6 -0
  61. package/dist/src/datetime/components/date-picker/components/BaseDatePickerInput.d.ts +2 -0
  62. package/dist/src/datetime/components/date-picker/types.d.ts +6 -0
  63. package/dist/src/datetime/components/time-picker/types.d.ts +6 -1
  64. package/dist/src/datetime/helpers/getTitleLabelling.d.ts +12 -0
  65. package/dist/src/forms/submitChanged.d.ts +3 -0
  66. package/dist/src/helpers/focusable.d.ts +8 -0
  67. package/dist/src/helpers/index.d.ts +1 -0
  68. package/dist/src/helpers/uiCoreLocale.d.ts +1 -0
  69. package/dist/src/table/shared-components/StyledMenuItem.d.ts +5 -1
  70. package/dist/table/components/columns/action-column/components/RowActionMenu.js +63 -69
  71. package/dist/table/shared-components/StyledMenuItem.js +28 -16
  72. package/package.json +1 -1
@@ -1,19 +1,30 @@
1
+ import { ReactNode } from 'react';
1
2
  import { DynamicToolbarAction, PlannedToolbarActions } from './planToolbarActions';
3
+ /** More-menu item state: a running action is disabled with the busy reason (disabled-states DIS-8). */
4
+ export declare function overflowItemState(action: DynamicToolbarAction, inProgressLabel?: string): {
5
+ disabled?: boolean;
6
+ disabledReason?: ReactNode;
7
+ 'aria-busy'?: boolean;
8
+ };
2
9
  /** True when the plan renders anything (inline buttons or the More menu). */
3
10
  export declare function hasPlannedActions(plan?: PlannedToolbarActions): boolean;
4
- export declare function ToolbarActionButton({ action, showLabel, selectionTone, }: {
11
+ export declare function ToolbarActionButton({ action, showLabel, selectionTone, inProgressLabel, }: {
5
12
  action: DynamicToolbarAction;
6
13
  showLabel: boolean;
7
14
  selectionTone?: boolean;
15
+ /** Busy announcement of a `loading` action, in the toolbar locale. */
16
+ inProgressLabel?: string;
8
17
  }): JSX.Element;
9
18
  export declare function MoreTriggerButton({ overflowMenuLabel, onOpen, }: {
10
19
  overflowMenuLabel: string;
11
20
  onOpen?: (anchor: HTMLElement) => void;
12
21
  }): JSX.Element;
13
22
  /** Inline action buttons plus the "More" overflow menu for a planned strip. */
14
- export declare function ToolbarActionGroup({ plan, overflowMenuLabel, className, selectionTone, registerActionWidth, }: {
23
+ export declare function ToolbarActionGroup({ plan, overflowMenuLabel, className, selectionTone, registerActionWidth, inProgressLabel, }: {
15
24
  plan: PlannedToolbarActions;
16
25
  overflowMenuLabel: string;
26
+ /** Reason and busy announcement of a `loading` action, in the toolbar locale. */
27
+ inProgressLabel?: string;
17
28
  className?: string;
18
29
  selectionTone?: boolean;
19
30
  /**
@@ -51,7 +51,7 @@ export declare function TitleBlock({ title, helperText, titleMeasureRef, }: {
51
51
  * Bulk actions render only in the `inline-selection` variant; the other
52
52
  * variants pair with a separate {@link SelectionRow} when selection is active.
53
53
  */
54
- export declare function UtilityCluster({ variant, beforeFilterActionsPlan, filter, search, afterSearchActionsPlan, bulkActionsPlan, showPageActions, overflowMenuLabel, searchMeasureRef, align, }: {
54
+ export declare function UtilityCluster({ variant, beforeFilterActionsPlan, filter, search, afterSearchActionsPlan, bulkActionsPlan, showPageActions, overflowMenuLabel, inProgressLabel, searchMeasureRef, align, }: {
55
55
  variant: UtilityRowVariant;
56
56
  beforeFilterActionsPlan: PlannedToolbarActions;
57
57
  filter?: ReactNode;
@@ -60,6 +60,7 @@ export declare function UtilityCluster({ variant, beforeFilterActionsPlan, filte
60
60
  bulkActionsPlan?: PlannedToolbarActions;
61
61
  showPageActions: boolean;
62
62
  overflowMenuLabel: string;
63
+ inProgressLabel?: string;
63
64
  searchMeasureRef?: MeasureRef;
64
65
  align?: 'start' | 'end';
65
66
  }): JSX.Element | null;
@@ -1,4 +1,4 @@
1
- import { ReactElement } from 'react';
1
+ import { ReactElement, ReactNode } from 'react';
2
2
  export interface DynamicToolbarActionRenderOptions {
3
3
  showLabel: boolean;
4
4
  }
@@ -8,6 +8,23 @@ export interface DynamicToolbarAction {
8
8
  onClick: () => void;
9
9
  icon?: ReactElement;
10
10
  disabled?: boolean;
11
+ /**
12
+ * Why the action is unavailable. With `disabled` the button or More-menu item stays focusable
13
+ * and shows the reason on hover, focus and tap (disabled-states DIS-1…DIS-3).
14
+ */
15
+ disabledReason?: ReactNode;
16
+ /**
17
+ * Busy: the button shows a spinner, sets `aria-busy` and ignores activation (disabled-states DIS-8).
18
+ * In the More menu the item is disabled with the reason "In progress" in the toolbar locale. Pass a
19
+ * boolean from the first render so the busy announcement region exists before it turns on.
20
+ */
21
+ loading?: boolean;
22
+ /**
23
+ * Whether a `loading` action keeps the dialog around it open (no Esc, backdrop, X or Cancel), inline
24
+ * and in the More menu; defaults to `true`, the rule for a running save (submit-buttons SUB-8). Pass
25
+ * `false` for an action that is not a save, such as a preview or a lookup.
26
+ */
27
+ holdsDialog?: boolean;
11
28
  hidden?: boolean;
12
29
  variant?: 'contained' | 'outlined' | 'text' | 'textGray' | 'textWhite';
13
30
  /** Visual tone. `danger` renders the action in the destructive/red palette. */
@@ -7,6 +7,7 @@ declare const translations: {
7
7
  back: string;
8
8
  menu: string;
9
9
  close: string;
10
+ inProgress: string;
10
11
  };
11
12
  no: {
12
13
  more: string;
@@ -15,6 +16,7 @@ declare const translations: {
15
16
  back: string;
16
17
  menu: string;
17
18
  close: string;
19
+ inProgress: string;
18
20
  };
19
21
  };
20
22
  export type ToolbarTranslations = (typeof translations)['en'];
@@ -25,6 +25,11 @@ export interface StyledWidgetProps {
25
25
  onClick?: () => void;
26
26
  hide?: boolean;
27
27
  disabled?: boolean;
28
+ /**
29
+ * @figmaProp none — behavioral. Why "view more" is unavailable. With `disabled` the button stays
30
+ * focusable and shows the reason on hover, focus and tap (disabled-states DIS-1…DIS-4).
31
+ */
32
+ disabledReason?: ReactNode;
28
33
  };
29
34
  /**
30
35
  * @param {string} persistKey - Unique key to persist expanded state
@@ -27,6 +27,12 @@ export interface StyledChipProps {
27
27
  size?: 'small' | 'medium';
28
28
  /** @figmaProp State = true→"Disabled" */
29
29
  disabled?: boolean;
30
+ /**
31
+ * @figmaProp none — behavioral. Why a clickable chip is unavailable. With `disabled` the chip stays
32
+ * focusable (`aria-disabled`), ignores activation and shows the reason on hover, focus and tap
33
+ * (disabled-states DIS-1…DIS-3).
34
+ */
35
+ disabledReason?: ReactNode;
30
36
  /** @figmaProp State = true→"Read only" */
31
37
  readOnly?: boolean;
32
38
  /** @figmaProp State = drives interactive Hovered/Focused/Pressed via native events */
@@ -1,4 +1,4 @@
1
- import { ComponentProps } from 'react';
1
+ import { ComponentProps, ReactNode } from 'react';
2
2
  import { StyledChip } from '../chip';
3
3
  /**
4
4
  * @figmaNode wXrXt5uKNNzV2DnQCgyYZH#13248-31089
@@ -19,6 +19,12 @@ export interface StyledInteractiveChipProps extends ComponentProps<typeof Styled
19
19
  size?: 'small' | 'medium';
20
20
  /** @figmaProp none — accessible name for the control */
21
21
  ariaLabel?: string;
22
+ /**
23
+ * @figmaProp none — behavioral. Why the chip can't be selected. With `disabled` the chip stays
24
+ * focusable (`aria-disabled`), ignores activation and shows the reason on hover, focus and tap
25
+ * (disabled-states DIS-1…DIS-4). Without `disabled` it has no effect.
26
+ */
27
+ disabledReason?: ReactNode;
22
28
  }
23
29
  /**
24
30
  * A `StyledChip` whose avatar is a native checkbox or radio (base-ui controls now render their own
@@ -30,6 +30,19 @@ export interface TooltipProps {
30
30
  disableHoverListener?: boolean;
31
31
  disableFocusListener?: boolean;
32
32
  disableTouchListener?: boolean;
33
+ /**
34
+ * A tap on a touch screen toggles the tooltip; it stays until the next tap, a tap outside,
35
+ * scroll or Escape — never a timer (disabled-states DIS-2, §5). Hover stays mouse-only so the
36
+ * emulated mouse events after a tap cannot toggle it a second time.
37
+ */
38
+ openOnTap?: boolean;
39
+ /**
40
+ * The text stays in the DOM and the trigger references it through `aria-describedby` while the
41
+ * tooltip is closed, so a screen reader announces it on focus (disabled-states DIS-2, 4.1.2).
42
+ */
43
+ persistentDescription?: boolean;
44
+ /** Share the persistent description with every focusable item in a composite control. */
45
+ persistentDescriptionId?: string;
33
46
  offsetDistance?: number;
34
47
  className?: string;
35
48
  slotProps?: TooltipSlotProps;
@@ -37,8 +50,9 @@ export interface TooltipProps {
37
50
  /**
38
51
  * Tooltip built on `@floating-ui/react` (replaces MUI `Tooltip`) — hover(+`enterDelay`)/focus open,
39
52
  * dismiss on blur/esc, `flip`/`shift` collision handling, optional arrow, portalled. Empty `title`
40
- * renders the child alone (MUI parity). Preserves the `#363E4A` design and the `title`/`placement`/
53
+ * renders the child alone (MUI parity); a Fragment child keeps its `display: contents` wrapper so
54
+ * it does not remount when a title appears. Preserves the `#363E4A` design and the `title`/`placement`/
41
55
  * `arrow`/`enterDelay`/`open`/`slotProps` surface (DEC-003). TASK-301.
42
56
  */
43
- export declare const StyledTooltip: (props: TooltipProps) => JSX.Element;
57
+ export declare const StyledTooltip: ({ children, ...props }: TooltipProps) => JSX.Element;
44
58
  export {};
@@ -0,0 +1,28 @@
1
+ import { ReactNode } from 'react';
2
+ import { UiCoreLocale } from '../../../helpers/uiCoreLocale';
3
+ export declare const WAIT_UNTIL_SAVED: {
4
+ readonly en: "Wait until saved";
5
+ readonly no: "Vent til lagringen er ferdig";
6
+ };
7
+ interface DialogBusyContextValue {
8
+ busy: boolean;
9
+ busyReason?: ReactNode;
10
+ /** Marks the dialog busy; the returned function ends that mark. */
11
+ registerBusy: () => () => void;
12
+ }
13
+ export declare const DialogBusyContext: import('react').Context<DialogBusyContextValue | null>;
14
+ /**
15
+ * A dialog (or popover) is busy while one of its buttons runs an action (`StyledButton loading`, unless
16
+ * the button passes `holdsDialog={false}`).
17
+ * Closing it then would hide a request that is still running, so every dismissal (Esc, backdrop click,
18
+ * the X button) is ignored until the action ends (submit-buttons SUB-4/SUB-8: Cancel waits for the result).
19
+ * Provide `contextValue` with `DialogBusyContext.Provider` around the dialog content.
20
+ */
21
+ export declare const useDialogBusyBoundary: (busyReason?: ReactNode, locale?: UiCoreLocale) => {
22
+ busy: boolean;
23
+ busyReason: ReactNode;
24
+ contextValue: DialogBusyContextValue;
25
+ };
26
+ /** Reports `busy` to the closest dialog, if any. Safe outside a dialog. */
27
+ export declare const useReportDialogBusy: (busy: boolean) => void;
28
+ export {};
@@ -1,4 +1,5 @@
1
1
  import { CSSProperties, ReactNode, SyntheticEvent } from 'react';
2
+ import { UiCoreLocale } from '../../../helpers/uiCoreLocale';
2
3
  export type DialogCloseReason = 'escapeKeyDown' | 'backdropClick';
3
4
  export type DialogMaxWidth = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | false;
4
5
  interface DialogPaperProps {
@@ -48,6 +49,10 @@ export interface IStyledDialogProps {
48
49
  onExited?: () => void;
49
50
  };
50
51
  };
52
+ /** Why close and Cancel wait while an action runs; defaults to "Wait until saved" in `locale`. */
53
+ busyReason?: ReactNode;
54
+ /** Language of the default busy reason; defaults to English. */
55
+ locale?: UiCoreLocale;
51
56
  onCloseText?: ReactNode;
52
57
  /** @figmaProp none — behavioral */
53
58
  showCloseIcon?: boolean;
@@ -18,17 +18,18 @@ export interface StyledDialogFooterButton {
18
18
  /** Trailing icon. `loading` supplies its own and wins. */
19
19
  endIcon?: ReactNode;
20
20
  /**
21
- * Shows a spinner after the label and makes the button busy (`aria-busy`, `aria-disabled`): it
22
- * keeps focus and ignores further presses. Consumers previously swapped
23
- * the label *for* a spinner, which changes the button's width mid-submit — hence the
24
- * hard-coded `w-[98px]` workarounds in the footers this replaces. Keeping the label
25
- * makes the width stable on its own.
21
+ * Marks the button busy: a spinner sits centred over the label, which stays in the layout
22
+ * (invisible, still the accessible name), so the button keeps its width. It keeps focus and
23
+ * ignores activation. Consumers previously swapped the label *for* a spinner, which changed
24
+ * the button's width mid-submit — hence the hard-coded `w-[98px]` workarounds in the footers
25
+ * this replaces.
26
26
  */
27
27
  loading?: boolean;
28
28
  /**
29
- * Wraps the button in a `StyledTooltip`. Falsy renders no tooltip, so the common
30
- * `tooltip={disabled && 'Locked for editing'}` reads naturally. It opens on hover and on
31
- * keyboard focus, since a disabled button stays focusable.
29
+ * Pass a constant `tooltip` (e.g. 'Locked for editing') and toggle `disabled` separately.
30
+ * With `disabled` it is the reason the action is unavailable (`disabledReason`):
31
+ * the button stays focusable and shows it on hover, focus and tap. Otherwise it is a plain
32
+ * hint anchored on a wrapper.
32
33
  */
33
34
  tooltip?: ReactNode;
34
35
  dataTest?: string;
@@ -3,3 +3,4 @@ export * from './StyledDialogActions';
3
3
  export * from './StyledDialogContent';
4
4
  export * from './StyledDialogTitle';
5
5
  export * from './dialog-footer';
6
+ export { DialogBusyContext, useDialogBusyBoundary, useReportDialogBusy } from './DialogBusyContext';
@@ -4,4 +4,6 @@ export declare const CloseBtn: React.FC<{
4
4
  onClick: () => void;
5
5
  tooltipTitle: string;
6
6
  buttonRef?: React.Ref<HTMLButtonElement>;
7
+ /** While set, the button is soft-disabled with this reason (e.g. a save is running). */
8
+ disabledReason?: React.ReactNode;
7
9
  }>;
@@ -19,7 +19,18 @@ export interface IMinimizableDialogProps {
19
19
  children?: React.ReactNode | ((props: IFloatingWindowProps) => ReactNode);
20
20
  className?: string;
21
21
  primaryButtonText?: string;
22
+ /**
23
+ * @figmaProp none — behavioral. Busy: the primary button shows a spinner and ignores activation;
24
+ * the secondary button, Esc and the close button wait with the reason "Wait until saved" (DIS-8).
25
+ */
22
26
  primaryButtonLoading?: boolean;
27
+ /** @figmaProp none — behavioral. Disables the primary button; pair it with `primaryButtonDisabledReason`. */
28
+ primaryButtonDisabled?: boolean;
29
+ /**
30
+ * @figmaProp none — behavioral. Why the primary action is unavailable. With `primaryButtonDisabled`
31
+ * the button stays focusable and shows the reason on hover, focus and tap (disabled-states DIS-1…DIS-4).
32
+ */
33
+ primaryButtonDisabledReason?: ReactNode;
23
34
  secondaryButtonText?: string;
24
35
  onPrimaryButtonClick?: () => void;
25
36
  onSecondaryButtonClick?: () => void;
@@ -30,6 +30,8 @@ export interface IMinimizableDialogV2Props {
30
30
  fullscreen?: string;
31
31
  };
32
32
  locale?: ILocale;
33
+ /** Why Close and Cancel wait while an action inside runs; defaults to "Wait until saved" in `locale`. */
34
+ busyReason?: ReactNode;
33
35
  dataTest: string;
34
36
  style?: React.CSSProperties;
35
37
  /**
@@ -2,6 +2,7 @@ import { ILocale } from './types';
2
2
  declare const translations: {
3
3
  en: {
4
4
  close: string;
5
+ waitUntilSaved: string;
5
6
  expand: string;
6
7
  minimize: string;
7
8
  fullscreen: string;
@@ -9,6 +10,7 @@ declare const translations: {
9
10
  };
10
11
  no: {
11
12
  close: string;
13
+ waitUntilSaved: string;
12
14
  expand: string;
13
15
  minimize: string;
14
16
  fullscreen: string;
@@ -1,4 +1,5 @@
1
1
  import { default as React, ReactNode } from 'react';
2
+ import { UiCoreLocale } from '../../../helpers/uiCoreLocale';
2
3
  export type StyledButtonType = 'contained' | 'outlined' | 'text' | 'textGray';
3
4
  interface commonProps {
4
5
  /** @figmaProp none — ref */
@@ -11,6 +12,29 @@ interface commonProps {
11
12
  endIcon?: ReactNode;
12
13
  /** @figmaProp none — test hook */
13
14
  dataTest: string;
15
+ /**
16
+ * @figmaProp none — behavioral. Why the action is unavailable. Together with `disabled` the
17
+ * button stays focusable (`aria-disabled` instead of the native attribute), ignores activation
18
+ * and shows the reason on hover, focus and tap (disabled-states DIS-1…DIS-4). Without
19
+ * `disabled` it has no effect.
20
+ */
21
+ disabledReason?: ReactNode;
22
+ /**
23
+ * @figmaProp none — behavioral. Busy: spinner centred over the label (the label stays invisible in the layout, so the width is kept), `aria-busy`, focus kept,
24
+ * activation ignored (disabled-states DIS-8, submit-buttons SUB-4). The start is announced politely.
25
+ * Pass a boolean from the first render: the announcement region exists only while `loading` is defined.
26
+ */
27
+ loading?: boolean;
28
+ /**
29
+ * @figmaProp none — behavioral. Whether a `loading` button keeps the dialog around it open (no Esc,
30
+ * backdrop, X or Cancel) until it ends; defaults to `true`, the rule for a running save (submit-buttons
31
+ * SUB-8). Pass `false` for an action that is not a save, such as a search or a lookup.
32
+ */
33
+ holdsDialog?: boolean;
34
+ /** Language of the default busy announcement; defaults to English. */
35
+ locale?: UiCoreLocale;
36
+ /** @figmaProp none — behavioral. Announced when `loading` starts; defaults to "In progress" in `locale`. */
37
+ loadingAnnouncement?: string;
14
38
  }
15
39
  interface variantTextGrayProps {
16
40
  /** @figmaProp Type = textGray→"Quaternary" (transparent bg, text-icon/body #49525f) */
@@ -50,5 +74,5 @@ export type StyledButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> &
50
74
  * @param refLink - ref to component
51
75
  * @param dataTest - data-test tag
52
76
  */
53
- export declare const StyledButton: ({ variant, className, size, children, refLink, startIcon, endIcon, dataTest, error, style: styleProp, ...otherProps }: StyledButtonProps) => JSX.Element;
77
+ export declare const StyledButton: ({ variant, className, size, children, refLink, startIcon, endIcon, dataTest, error, style: styleProp, disabled, disabledReason, loading, holdsDialog, loadingAnnouncement, locale, onClick, ...otherProps }: StyledButtonProps) => JSX.Element;
54
78
  export {};
@@ -10,6 +10,12 @@ export type StyledLinkProps = Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'onC
10
10
  onClick?: (event: MouseEvent<HTMLAnchorElement | HTMLButtonElement>) => void;
11
11
  /** @figmaProp State = true→"Disabled" (renders a non-interactive <span>, delta-300) */
12
12
  disabled?: boolean;
13
+ /**
14
+ * @figmaProp none — behavioral. Why the link is unavailable. With `disabled` the link stays
15
+ * focusable (`aria-disabled`), does not navigate and shows the reason on hover, focus and tap
16
+ * (disabled-states DIS-1…DIS-3). Without it a disabled link stays a plain `<span>`.
17
+ */
18
+ disabledReason?: ReactNode;
13
19
  /** @figmaProp Size = small→"Base" (14/20) | large→"Medium" (16/24); xs (12/20) = none (no DS size) */
14
20
  size?: 'small' | 'large' | 'xs';
15
21
  /** @figmaProp none — ref */
@@ -12,6 +12,13 @@ export interface StyledMenuItemProps {
12
12
  onMouseUp?: (event: MouseEvent<HTMLLIElement>) => void;
13
13
  /** @figmaProp State = true→"Disabled" */
14
14
  disabled?: boolean;
15
+ /**
16
+ * @figmaProp none — behavioral. Why the item is unavailable. With `disabled` the item stays in
17
+ * arrow-key navigation and shows the reason on hover, focus and tap (disabled-states DIS-1…DIS-3).
18
+ */
19
+ disabledReason?: ReactNode;
20
+ /** @figmaProp none — behavioral. The item's action is running; pair it with `disabled` and a reason. */
21
+ 'aria-busy'?: boolean;
15
22
  /** @figmaProp State = true→"Selected" */
16
23
  selected?: boolean;
17
24
  /** Compact vertical padding (MUI `MenuItem` `dense` parity, DEC-003). */
@@ -36,4 +43,4 @@ export interface StyledMenuItemProps {
36
43
  * Native `role="menuitem"` (replaces MUI `MenuItem`). Enter/Space activate; a disabled item stays
37
44
  * focusable but non-interactive (MUI parity). Public props preserved (DEC-003). TASK-303.
38
45
  */
39
- export declare const StyledMenuItem: ({ children, onClick, onMouseDown, onMouseUp, disabled, selected, dense, tooltip, className, classes, sx, "data-test": dataTest, "data-testid": dataTestId, value: _value, }: StyledMenuItemProps) => JSX.Element;
46
+ export declare const StyledMenuItem: ({ children, onClick, onMouseDown, onMouseUp, disabled, disabledReason, "aria-busy": ariaBusy, selected, dense, tooltip, className, classes, sx, "data-test": dataTest, "data-testid": dataTestId, value: _value, }: StyledMenuItemProps) => JSX.Element;
@@ -18,10 +18,16 @@ export interface StyledTabProps {
18
18
  * Enter does not select it.
19
19
  */
20
20
  disabled?: boolean;
21
+ /**
22
+ * @figmaProp none — behavioral. Why the tab is unavailable. With `disabled` the tab stays in
23
+ * arrow-key navigation and shows the reason on hover, focus and tap (disabled-states DIS-1…DIS-3).
24
+ */
25
+ disabledReason?: ReactNode;
21
26
  /**
22
27
  * @figmaProp none — a11y
23
28
  * Tooltip on the tab, opened by hover and keyboard focus and read as the tab's description —
24
29
  * typically why a `disabled` tab is unavailable (disabled-states DIS-1, DIS-2). Falsy renders none.
30
+ * A `disabledReason` takes its place while the tab is disabled.
25
31
  */
26
32
  tooltip?: ReactNode;
27
33
  className?: string;
@@ -1,3 +1,4 @@
1
+ import { AriaAttributes } from 'react';
1
2
  import { DayPickerProps as ReactDayPickerProps, Matcher } from 'react-day-picker';
2
3
  export interface IBaseDatePickerInput {
3
4
  dataTest: string;
@@ -23,5 +24,6 @@ export interface IBaseDatePickerInput {
23
24
  hideDefaultHelperText?: boolean;
24
25
  required?: boolean;
25
26
  minDate?: Date;
27
+ inputAriaProps?: AriaAttributes;
26
28
  }
27
29
  export declare const BaseDatePickerInput: React.FC<IBaseDatePickerInput>;
@@ -1,3 +1,4 @@
1
+ import { AriaAttributes } from 'react';
1
2
  import { DayPicker, Matcher } from 'react-day-picker';
2
3
  export type CalendarProps = React.ComponentProps<typeof DayPicker>;
3
4
  type CommonDatePickerProps = {
@@ -25,6 +26,11 @@ export interface DatePickerSingleFieldProps {
25
26
  disallowPast?: boolean;
26
27
  disallowFuture?: boolean;
27
28
  hideDefaultHelperText?: boolean;
29
+ /**
30
+ * Extra ARIA attributes for the text input (e.g. `aria-label`, `aria-required`). Without them the
31
+ * input is named by `title`, which is otherwise plain text above the field.
32
+ */
33
+ inputAriaProps?: AriaAttributes;
28
34
  }
29
35
  export interface DatePickerRangeFieldProps {
30
36
  labelFrom?: string;
@@ -1,4 +1,4 @@
1
- import { ReactNode } from 'react';
1
+ import { AriaAttributes, ReactNode } from 'react';
2
2
  /**
3
3
  * @param notBeforeTime - Start time of the range. Selected time must be after this value.
4
4
  */
@@ -24,5 +24,10 @@ export interface StyledTimePickerProps {
24
24
  * Unlike `notBeforeTime`, it never shows an error.
25
25
  */
26
26
  minTime?: Date;
27
+ /**
28
+ * Extra ARIA attributes for the text input (e.g. `aria-label`, `aria-required`) — for a visible
29
+ * label rendered outside the picker. Without them the input is named by `title` or `label`.
30
+ */
31
+ inputAriaProps?: AriaAttributes;
27
32
  }
28
33
  export type IPopupStateType = JSX.Element;
@@ -0,0 +1,12 @@
1
+ import { AriaAttributes } from 'react';
2
+ /**
3
+ * ARIA naming for a datetime input that shows its `title` as plain text above the field: points the
4
+ * input at the title unless a floating `label` or an explicit name in `inputAriaProps` already names it
5
+ * (`aria-labelledby` would otherwise override that name). `inputAriaProps` are spread last.
6
+ */
7
+ export declare const getTitleLabelling: ({ title, titleId, label, inputAriaProps, }: {
8
+ title?: string;
9
+ titleId: string;
10
+ label?: string;
11
+ inputAriaProps?: AriaAttributes;
12
+ }) => AriaAttributes;
@@ -3,4 +3,7 @@ export type SubmitChangedPatch<TFieldValues extends FieldValues> = (dirty: Parti
3
3
  export interface SubmitChangedOptions {
4
4
  touchInvalidFields?: boolean;
5
5
  }
6
+ /**
7
+ * Does not set react-hook-form `formState.isSubmitting`; callers drive the busy state from their own pending flag.
8
+ */
6
9
  export declare function submitChanged<TFieldValues extends FieldValues>(methods: UseFormReturn<TFieldValues>, onPatch: SubmitChangedPatch<TFieldValues>, onInvalid?: () => void, options?: SubmitChangedOptions): Promise<boolean>;
@@ -6,4 +6,12 @@ export declare const tabbableWithin: (root: ParentNode) => HTMLElement[];
6
6
  * disabled control, which the caller has to decide about.
7
7
  */
8
8
  export declare const firstTabbable: (root: HTMLElement) => HTMLElement | null;
9
+ /**
10
+ * The element a description belongs to for `root`: its first focusable element, including a
11
+ * roving-tabindex item (`tabindex="-1"`, an unselected tab or a menu item) that arrow keys still move
12
+ * focus to — inside a `tablist` or `menu` the wrapper would be a child those roles do not allow.
13
+ * Unlike `firstTabbable` it ignores a temporarily unreachable subtree: a reasoned control inside a
14
+ * collapsed accordion panel (`inert`) or a `display: none` parent is still the element a description
15
+ * belongs to once the panel opens, and neither state change re-renders the describer.
16
+ */
9
17
  export declare const firstFocusable: (root: HTMLElement) => HTMLElement | null;
@@ -1,3 +1,4 @@
1
1
  export * from './cn';
2
2
  export * from './omit';
3
3
  export * from './prepareForSlot';
4
+ export * from './uiCoreLocale';
@@ -0,0 +1 @@
1
+ export type UiCoreLocale = 'en' | 'no';
@@ -1,7 +1,11 @@
1
1
  import { MouseEvent, ReactNode } from 'react';
2
+ import { TooltipProps } from '../../components/data-display/tooltip/StyledTooltip';
2
3
  export interface StyledMenuItemProps {
3
4
  children?: ReactNode;
4
5
  disabled?: boolean;
6
+ /** Why a disabled item can't be used; keeps it reachable by arrow keys and shows the reason. */
7
+ disabledReason?: ReactNode;
8
+ reasonPlacement?: TooltipProps['placement'];
5
9
  selected?: boolean;
6
10
  className?: string;
7
11
  classes?: {
@@ -15,4 +19,4 @@ export interface StyledMenuItemProps {
15
19
  * Table row-action menu item (replaces MUI `MenuItem`). Native `role="menuitem"`; disabled stays
16
20
  * focusable but non-interactive. TASK-404.
17
21
  */
18
- export declare const StyledMenuItem: ({ children, disabled, selected, className, classes, onClick, onMouseDown, onMouseUp, }: StyledMenuItemProps) => JSX.Element;
22
+ export declare const StyledMenuItem: ({ children, disabled, disabledReason, reasonPlacement, selected, className, classes, onClick, onMouseDown, onMouseUp, }: StyledMenuItemProps) => JSX.Element;