@carbon/react 1.89.0-rc.1 → 1.90.0-rc.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 (68) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +1152 -849
  2. package/README.md +2 -2
  3. package/es/components/ComposedModal/ComposedModal.js +16 -5
  4. package/es/components/DataTable/DataTable.d.ts +3 -8
  5. package/es/components/DataTable/DataTable.js +10 -3
  6. package/es/components/DataTable/TableExpandRow.d.ts +33 -5
  7. package/es/components/DataTable/TableExpandRow.js +4 -2
  8. package/es/components/DataTable/TableHeader.d.ts +1 -2
  9. package/es/components/DataTable/TableHeader.js +1 -2
  10. package/es/components/DataTable/TableRow.d.ts +3 -6
  11. package/es/components/DataTable/TableRow.js +35 -22
  12. package/es/components/DataTable/state/sorting.d.ts +55 -14
  13. package/es/components/DataTable/state/sorting.js +40 -50
  14. package/es/components/DataTable/tools/sorting.js +4 -0
  15. package/es/components/Dialog/Dialog.d.ts +245 -0
  16. package/es/components/Dialog/Dialog.js +593 -0
  17. package/es/components/Dialog/index.d.ts +3 -251
  18. package/es/components/Dialog/index.js +1 -609
  19. package/es/components/FeatureFlags/index.d.ts +3 -1
  20. package/es/components/FeatureFlags/index.js +5 -2
  21. package/es/components/FileUploader/FileUploader.d.ts +28 -6
  22. package/es/components/FileUploader/FileUploader.js +152 -38
  23. package/es/components/Menu/MenuItem.js +2 -1
  24. package/es/components/Modal/Modal.js +14 -8
  25. package/es/components/NumberInput/NumberInput.js +11 -6
  26. package/es/components/Popover/index.js +6 -2
  27. package/es/components/StructuredList/StructuredList.js +4 -2
  28. package/es/components/Tag/DismissibleTag.d.ts +5 -0
  29. package/es/components/Tag/DismissibleTag.js +6 -1
  30. package/es/components/Toggletip/index.js +20 -8
  31. package/es/components/TreeView/TreeNode.d.ts +28 -0
  32. package/es/components/TreeView/TreeNode.js +6 -5
  33. package/es/index.d.ts +2 -1
  34. package/es/index.js +2 -0
  35. package/lib/components/ComposedModal/ComposedModal.js +16 -5
  36. package/lib/components/DataTable/DataTable.d.ts +3 -8
  37. package/lib/components/DataTable/DataTable.js +10 -3
  38. package/lib/components/DataTable/TableExpandRow.d.ts +33 -5
  39. package/lib/components/DataTable/TableExpandRow.js +4 -2
  40. package/lib/components/DataTable/TableHeader.d.ts +1 -2
  41. package/lib/components/DataTable/TableHeader.js +1 -2
  42. package/lib/components/DataTable/TableRow.d.ts +3 -6
  43. package/lib/components/DataTable/TableRow.js +34 -21
  44. package/lib/components/DataTable/state/sorting.d.ts +55 -14
  45. package/lib/components/DataTable/state/sorting.js +39 -50
  46. package/lib/components/DataTable/tools/sorting.js +4 -0
  47. package/lib/components/Dialog/Dialog.d.ts +245 -0
  48. package/lib/components/Dialog/Dialog.js +602 -0
  49. package/lib/components/Dialog/index.d.ts +3 -251
  50. package/lib/components/Dialog/index.js +9 -614
  51. package/lib/components/FeatureFlags/index.d.ts +3 -1
  52. package/lib/components/FeatureFlags/index.js +5 -2
  53. package/lib/components/FileUploader/FileUploader.d.ts +28 -6
  54. package/lib/components/FileUploader/FileUploader.js +151 -37
  55. package/lib/components/Menu/MenuItem.js +2 -1
  56. package/lib/components/Modal/Modal.js +21 -15
  57. package/lib/components/NumberInput/NumberInput.js +10 -5
  58. package/lib/components/Popover/index.js +6 -2
  59. package/lib/components/StructuredList/StructuredList.js +4 -2
  60. package/lib/components/Tag/DismissibleTag.d.ts +5 -0
  61. package/lib/components/Tag/DismissibleTag.js +6 -1
  62. package/lib/components/Toggletip/index.js +19 -7
  63. package/lib/components/TreeView/TreeNode.d.ts +28 -0
  64. package/lib/components/TreeView/TreeNode.js +6 -5
  65. package/lib/index.d.ts +2 -1
  66. package/lib/index.js +60 -58
  67. package/package.json +15 -15
  68. package/telemetry.yml +16 -0
package/README.md CHANGED
@@ -114,14 +114,14 @@ function MyComponent() {
114
114
  ```
115
115
 
116
116
  For a full list of icons available, checkout our
117
- [website](https://www.carbondesignsystem.com/guidelines/icons/library/).
117
+ [website](https://carbondesignsystem.com/elements/icons/library/).
118
118
 
119
119
  ## 📖 API Documentation
120
120
 
121
121
  If you're looking for `@carbon/react` API documentation, check out:
122
122
 
123
123
  - [Storybook](https://react.carbondesignsystem.com/)
124
- - [Icon Library](https://www.carbondesignsystem.com/guidelines/icons/library/)
124
+ - [Icon Library](https://carbondesignsystem.com/elements/icons/library/)
125
125
 
126
126
  ## 🙌 Contributing
127
127
 
@@ -24,7 +24,7 @@ import { match } from '../../internal/keyboard/match.js';
24
24
  import { useFeatureFlag } from '../FeatureFlags/index.js';
25
25
  import { composeEventHandlers } from '../../tools/events.js';
26
26
  import { deprecate } from '../../prop-types/deprecate.js';
27
- import { unstable__Dialog } from '../Dialog/index.js';
27
+ import { Dialog } from '../Dialog/Dialog.js';
28
28
  import { warning } from '../../internal/warning.js';
29
29
  import { AILabel } from '../AILabel/index.js';
30
30
  import { isComponentElement } from '../../internal/utils.js';
@@ -166,9 +166,14 @@ const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
166
166
  } = evt;
167
167
  const mouseDownTarget = onMouseDownTarget.current;
168
168
  evt.stopPropagation();
169
- const containsModalFooter = Children.toArray(childrenWithProps).some(child => isComponentElement(child, ModalFooter));
170
- const isPassive = !containsModalFooter;
171
- const shouldCloseOnOutsideClick = isPassive ? preventCloseOnClickOutside !== false : preventCloseOnClickOutside === true;
169
+ const shouldCloseOnOutsideClick =
170
+ // Passive modals can close on clicks outside the modal when
171
+ // preventCloseOnClickOutside is undefined or explicitly set to false.
172
+ isPassive && !preventCloseOnClickOutside ||
173
+ // Non-passive modals have to explicitly opt-in for close on outside
174
+ // behavior by explicitly setting preventCloseOnClickOutside to false,
175
+ // rather than just leaving it undefined.
176
+ !isPassive && preventCloseOnClickOutside === false;
172
177
  if (shouldCloseOnOutsideClick && target instanceof Node && !elementOrParentIsFloatingMenu(target, selectorsFloatingMenus) && innerModal.current && !innerModal.current.contains(target) && !innerModal.current.contains(mouseDownTarget)) {
173
178
  closeModal(evt);
174
179
  }
@@ -252,6 +257,12 @@ const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
252
257
  return child;
253
258
  }
254
259
  });
260
+
261
+ // Modals without a footer are considered passive and carry limitations as
262
+ // outlined in the design spec.
263
+ const containsModalFooter = Children.toArray(childrenWithProps).some(child => isComponentElement(child, ModalFooter));
264
+ const isPassive = !containsModalFooter;
265
+ process.env.NODE_ENV !== "production" ? warning(!(!isPassive && preventCloseOnClickOutside === false), '`<ComposedModal>` prop `preventCloseOnClickOutside` should not be ' + '`false` when `<ModalFooter>` is present. Transactional, non-passive ' + 'Modals should not be dissmissable by clicking outside. ' + 'See: https://carbondesignsystem.com/components/modal/usage/#transactional-modal') : void 0;
255
266
  useEffect(() => {
256
267
  if (!open) return;
257
268
  const handleEscapeKey = event => {
@@ -304,7 +315,7 @@ const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
304
315
  const normalizedDecorator = candidateIsAILabel ? /*#__PURE__*/cloneElement(candidate, {
305
316
  size: 'sm'
306
317
  }) : null;
307
- const modalBody = enableDialogElement ? /*#__PURE__*/React.createElement(unstable__Dialog, {
318
+ const modalBody = enableDialogElement ? /*#__PURE__*/React.createElement(Dialog, {
308
319
  open: open,
309
320
  focusAfterCloseRef: launcherButtonRef,
310
321
  modal: true,
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import PropTypes from 'prop-types';
8
8
  import React, { type ChangeEvent, type MouseEvent, type ReactElement, type ReactNode } from 'react';
9
+ import { type SortRowFn } from './state/sorting';
9
10
  import type { DataTableSortState } from './state/sortStates';
10
11
  import { TranslateWithId } from '../../types/common';
11
12
  declare const translationKeys: {
@@ -181,13 +182,7 @@ export interface DataTableProps<RowType, ColTypes extends any[]> extends Transla
181
182
  render?: (renderProps: DataTableRenderProps<RowType, ColTypes>) => ReactElement;
182
183
  rows: Omit<DataTableRow<ColTypes>, 'cells'>[];
183
184
  size?: DataTableSize;
184
- sortRow?: (cellA: any, cellB: any, options: {
185
- sortDirection: DataTableSortState;
186
- sortStates: Record<DataTableSortState, DataTableSortState>;
187
- locale: string;
188
- key: string;
189
- compare: (a: number | string, b: number | string, locale?: string) => number;
190
- }) => number;
185
+ sortRow?: SortRowFn;
191
186
  stickyHeader?: boolean;
192
187
  useStaticWidth?: boolean;
193
188
  useZebraStyles?: boolean;
@@ -286,7 +281,7 @@ export declare const DataTable: {
286
281
  };
287
282
  TableHead: (props: React.HTMLAttributes<"thead">) => React.ReactElement<any>;
288
283
  TableHeader: React.ForwardRefExoticComponent<import("./TableHeader").TableHeaderProps & React.RefAttributes<HTMLTableCellElement>>;
289
- TableRow: React.ForwardRefExoticComponent<import("./TableRow").TableRowProps & React.RefAttributes<HTMLTableCellElement>>;
284
+ TableRow: React.ForwardRefExoticComponent<import("./TableRow").TableRowProps & React.RefAttributes<HTMLTableRowElement>>;
290
285
  TableSelectAll: {
291
286
  ({ ariaLabel: deprecatedAriaLabel, ["aria-label"]: ariaLabel, checked, id, indeterminate, name, onSelect, disabled, className, }: import("./TableSelectAll").TableSelectAllProps): import("react/jsx-runtime").JSX.Element;
292
287
  propTypes: {
@@ -549,9 +549,16 @@ const DataTable = props => {
549
549
  * @param headerKey - The field for the header that we are sorting by.
550
550
  */
551
551
  const handleSortBy = headerKey => () => {
552
- setState(prev => getNextSortState(props, prev, {
553
- key: headerKey
554
- }));
552
+ setState(prev => {
553
+ const sortState = getNextSortState(props, prev, {
554
+ key: headerKey
555
+ });
556
+ return {
557
+ ...prev,
558
+ // Preserve ALL existing state
559
+ ...sortState // Then apply only the sorting changes
560
+ };
561
+ });
555
562
  };
556
563
 
557
564
  /**
@@ -4,13 +4,41 @@
4
4
  * This source code is licensed under the Apache-2.0 license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- import React, { type MouseEventHandler, type PropsWithChildren } from 'react';
8
- import { TableRowProps } from './TableRow';
9
- export interface TableExpandRowProps extends PropsWithChildren<TableRowProps> {
7
+ import React, { type HTMLAttributes, type MouseEventHandler, type PropsWithChildren } from 'react';
8
+ /** Props shared between `TableRow` and `TableExpandRow`. */
9
+ export interface TableRowExpandInteropProps {
10
+ /**
11
+ * @deprecated Use `aria-label` instead.
12
+ */
13
+ ariaLabel?: string;
14
+ /**
15
+ * Specify the string read by a voice reader when the expand trigger is
16
+ * focused
17
+ */
18
+ 'aria-label'?: string;
19
+ /**
20
+ * Space separated list of one or more ID values referencing the TableExpandedRow(s) being controlled by the TableExpandRow
21
+ */
22
+ 'aria-controls'?: string;
23
+ /**
24
+ * Specify whether this row is expanded or not. This helps coordinate data
25
+ * attributes so that `TableExpandRow` and `TableExpandedRow` work together
26
+ */
27
+ isExpanded?: boolean;
28
+ /**
29
+ * Hook for when a listener initiates a request to expand the given row
30
+ */
31
+ onExpand?: MouseEventHandler<HTMLButtonElement>;
32
+ /**
33
+ * Specify if the row is selected.
34
+ */
35
+ isSelected?: boolean;
36
+ }
37
+ export interface TableExpandRowProps extends PropsWithChildren<Omit<HTMLAttributes<HTMLTableRowElement>, 'onClick'>>, Omit<TableRowExpandInteropProps, 'aria-label' | 'onExpand'> {
10
38
  /**
11
39
  * Space separated list of one or more ID values referencing the TableExpandedRow(s) being controlled by the TableExpandRow
12
40
  */
13
- ['aria-controls']?: string;
41
+ 'aria-controls'?: string;
14
42
  /**
15
43
  * @deprecated This prop has been deprecated and will be
16
44
  * removed in the next major release of Carbon. Use the
@@ -21,7 +49,7 @@ export interface TableExpandRowProps extends PropsWithChildren<TableRowProps> {
21
49
  * Specify the string read by a voice reader when the expand trigger is
22
50
  * focused
23
51
  */
24
- ['aria-label']: string;
52
+ 'aria-label': string;
25
53
  /**
26
54
  * The id of the matching th node in the table head. Addresses a11y concerns outlined here: https://www.ibm.com/able/guidelines/ci162/info_and_relationships.html and https://www.w3.org/TR/WCAG20-TECHS/H43
27
55
  */
@@ -17,6 +17,8 @@ import TableDecoratorRow from './TableDecoratorRow.js';
17
17
  import { AILabel } from '../AILabel/index.js';
18
18
  import { isComponentElement } from '../../internal/utils.js';
19
19
 
20
+ /** Props shared between `TableRow` and `TableExpandRow`. */
21
+
20
22
  const TableExpandRow = /*#__PURE__*/React.forwardRef(({
21
23
  ['aria-controls']: ariaControls,
22
24
  ['aria-label']: ariaLabel,
@@ -85,13 +87,13 @@ TableExpandRow.propTypes = {
85
87
  * Space separated list of one or more ID values referencing the TableExpandedRow(s) being controlled by the TableExpandRow
86
88
  * TODO: make this required in v12
87
89
  */
88
- ['aria-controls']: PropTypes.string,
90
+ 'aria-controls': PropTypes.string,
89
91
  /**
90
92
  * Specify the string read by a voice reader when the expand trigger is
91
93
  * focused
92
94
  */
93
95
  /**@ts-ignore*/
94
- ['aria-label']: PropTypes.string,
96
+ 'aria-label': PropTypes.string,
95
97
  /**
96
98
  * Deprecated, please use `aria-label` instead.
97
99
  * Specify the string read by a voice reader when the expand trigger is
@@ -5,9 +5,8 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import React, { type HTMLAttributes, type MouseEventHandler, type ReactNode } from 'react';
8
- import { sortStates } from './state/sorting';
9
8
  import { TranslateWithId } from '../../types/common';
10
- import { DataTableSortState } from './state/sortStates';
9
+ import { sortStates, type DataTableSortState } from './state/sortStates';
11
10
  export type TableHeaderTranslationKey = 'carbon.table.header.icon.description';
12
11
  export interface TableHeaderTranslationArgs {
13
12
  header: ReactNode;
@@ -10,12 +10,11 @@ import cx from 'classnames';
10
10
  import PropTypes from 'prop-types';
11
11
  import React, { useRef, cloneElement } from 'react';
12
12
  import { ArrowUp, ArrowsVertical } from '@carbon/icons-react';
13
- import './state/sorting.js';
14
13
  import { useId } from '../../internal/useId.js';
15
14
  import { usePrefix } from '../../internal/usePrefix.js';
15
+ import { sortStates } from './state/sortStates.js';
16
16
  import { AILabel } from '../AILabel/index.js';
17
17
  import { isComponentElement } from '../../internal/utils.js';
18
- import { sortStates } from './state/sortStates.js';
19
18
 
20
19
  const defaultScope = 'col';
21
20
  const translationKeys = {
@@ -5,15 +5,12 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import React, { type HTMLAttributes } from 'react';
8
- export interface TableRowProps extends HTMLAttributes<HTMLTableRowElement> {
8
+ import type { TableRowExpandInteropProps } from './TableExpandRow';
9
+ export interface TableRowProps extends HTMLAttributes<HTMLTableRowElement>, TableRowExpandInteropProps {
9
10
  /**
10
11
  * Specify an optional className to be applied to the container node
11
12
  */
12
13
  className?: string;
13
- /**
14
- * Specify if the row is selected
15
- */
16
- isSelected?: boolean;
17
14
  }
18
- declare const TableRow: React.ForwardRefExoticComponent<TableRowProps & React.RefAttributes<HTMLTableCellElement>>;
15
+ declare const TableRow: React.ForwardRefExoticComponent<TableRowProps & React.RefAttributes<HTMLTableRowElement>>;
19
16
  export default TableRow;
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
- import React, { Children } from 'react';
9
+ import React, { forwardRef, Children } from 'react';
10
10
  import PropTypes from 'prop-types';
11
11
  import cx from 'classnames';
12
12
  import { usePrefix } from '../../internal/usePrefix.js';
@@ -15,28 +15,10 @@ import TableDecoratorRow from './TableDecoratorRow.js';
15
15
  import { AILabel } from '../AILabel/index.js';
16
16
  import { isComponentElement } from '../../internal/utils.js';
17
17
 
18
- const TableRow = /*#__PURE__*/React.forwardRef((props, ref) => {
19
- const prefix = usePrefix();
20
- let rowHasAILabel;
21
- if (props?.children) {
22
- // TODO: Why is this loop a `map`? It's not returning anything. Ideally,
23
- // it seems that it should be a `some`. Maybe I'm missing something?
24
- Children.toArray(props.children).map(child => {
25
- if (isComponentElement(child, TableSlugRow)) {
26
- if (child.props.slug) {
27
- rowHasAILabel = true;
28
- }
29
- } else if (isComponentElement(child, TableDecoratorRow) && isComponentElement(child.props.decorator, AILabel)) {
30
- rowHasAILabel = true;
31
- }
32
- });
33
- }
18
+ const frFn = forwardRef;
19
+ const TableRow = frFn((props, ref) => {
34
20
  // Remove unnecessary props if provided to this component, these are
35
21
  // only useful in `TableExpandRow`
36
- const className = cx(props.className, {
37
- [`${prefix}--data-table--selected`]: props.isSelected,
38
- [`${prefix}--data-table--slug-row ${prefix}--data-table--ai-label-row`]: rowHasAILabel
39
- });
40
22
  const {
41
23
  ariaLabel,
42
24
  'aria-label': ariaLabelAlt,
@@ -46,6 +28,17 @@ const TableRow = /*#__PURE__*/React.forwardRef((props, ref) => {
46
28
  isSelected,
47
29
  ...cleanProps
48
30
  } = props;
31
+ const prefix = usePrefix();
32
+ const rowHasAILabel = Children.toArray(props.children).some(child => {
33
+ if (isComponentElement(child, TableSlugRow)) {
34
+ return !!child.props.slug;
35
+ }
36
+ return isComponentElement(child, TableDecoratorRow) && isComponentElement(child.props.decorator, AILabel);
37
+ });
38
+ const className = cx(props.className, {
39
+ [`${prefix}--data-table--selected`]: isSelected,
40
+ [`${prefix}--data-table--slug-row ${prefix}--data-table--ai-label-row`]: rowHasAILabel
41
+ });
49
42
  if (className) {
50
43
  cleanProps.className = className;
51
44
  }
@@ -61,7 +54,27 @@ TableRow.propTypes = {
61
54
  /**
62
55
  * Specify if the row is selected
63
56
  */
64
- isSelected: PropTypes.bool
57
+ isSelected: PropTypes.bool,
58
+ /**
59
+ * Non-standard alias for `aria-label`.
60
+ */
61
+ ariaLabel: PropTypes.string,
62
+ /**
63
+ * Accessible label for the row element.
64
+ */
65
+ 'aria-label': PropTypes.string,
66
+ /**
67
+ * Associates this row with the id of the corresponding expanded row content.
68
+ */
69
+ 'aria-controls': PropTypes.string,
70
+ /**
71
+ * Handler called when the row’s expand toggle is clicked.
72
+ */
73
+ onExpand: PropTypes.func,
74
+ /**
75
+ * Flag indicating whether the row is currently expanded.
76
+ */
77
+ isExpanded: PropTypes.bool
65
78
  };
66
79
 
67
80
  export { TableRow as default };
@@ -1,15 +1,56 @@
1
- export { sortStates };
2
- export const initialSortState: import("./sortStates").DataTableSortState;
3
- export function getNextSortDirection(prevHeader: string, header: string, prevState: string): string;
4
- export function getNextSortState(props: any, state: any, { key }: {
5
- key: any;
6
- }): any;
7
- export function getSortedState(props: {
1
+ /**
2
+ * Copyright IBM Corp. 2016, 2025
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import { type DataTableSortState } from './sortStates';
8
+ import type { DataTableCell } from '../DataTable';
9
+ export interface SortRowParams {
10
+ key: string;
11
+ sortDirection: DataTableSortState;
12
+ sortStates: Record<DataTableSortState, DataTableSortState>;
8
13
  locale: string;
9
- sortRows: Function;
10
- }, state: {
11
- rowIds: Array<string>;
12
- cellsById: object;
13
- initialRowOrder: Array<string>;
14
- }, key: string, sortDirection: string): object;
15
- import { sortStates } from './sortStates';
14
+ compare: (a: string | number, b: string | number, locale?: string) => number;
15
+ }
16
+ export type SortRowFn = (cellA: any, cellB: any, options: SortRowParams) => number;
17
+ interface Props {
18
+ locale?: string;
19
+ sortRow?: SortRowFn;
20
+ }
21
+ interface State<ColTypes extends any[]> {
22
+ rowIds: string[];
23
+ cellsById: Record<string, DataTableCell<ColTypes[number]>>;
24
+ initialRowOrder: string[];
25
+ sortHeaderKey: string | null;
26
+ sortDirection: DataTableSortState;
27
+ }
28
+ export declare const initialSortState: DataTableSortState;
29
+ /**
30
+ * Gets the next sort direction for a header.
31
+ *
32
+ * @param prevHeader - Key of the previously sorted header.
33
+ * @param currentHeader - Key of the currently selected header.
34
+ * @param prevState - Previous sort direction.
35
+ */
36
+ export declare const getNextSortDirection: (prevHeader: string, currentHeader: string, prevState: DataTableSortState) => DataTableSortState;
37
+ /**
38
+ * Gets the next sort state.
39
+ *
40
+ * @param props - Component props.
41
+ * @param state - Current table state.
42
+ * @param key - Header key to sort by.
43
+ */
44
+ export declare const getNextSortState: <ColTypes extends any[]>(props: Props, state: State<ColTypes>, { key }: {
45
+ key: string;
46
+ }) => Pick<State<ColTypes>, "sortHeaderKey" | "sortDirection" | "rowIds">;
47
+ /**
48
+ * Gets a sort state update.
49
+ *
50
+ * @param props - Component props.
51
+ * @param state - Current state of the table.
52
+ * @param key - Header key to sort by.
53
+ * @param sortDirection - Sort direction to apply.
54
+ */
55
+ export declare const getSortedState: <ColTypes extends any[]>({ locale, sortRow }: Props, { rowIds, cellsById, initialRowOrder }: State<ColTypes>, key: string, sortDirection: DataTableSortState) => Pick<State<ColTypes>, "rowIds" | "sortDirection" | "sortHeaderKey">;
56
+ export {};
@@ -8,37 +8,39 @@
8
8
  import { sortStates } from './sortStates.js';
9
9
  import { sortRows } from '../tools/sorting.js';
10
10
 
11
- // Our initialSortState should be `NONE`, unless a consumer has specified a
12
- // different initialSortState
13
11
  const initialSortState = sortStates.NONE;
14
12
 
15
13
  /**
16
- * Utility used to get the next sort state given the following pieces of
17
- * information:
14
+ * Gets the next sort direction for a header.
18
15
  *
19
- * @param {string} prevHeader the value of the previous header
20
- * @param {string} header the value of the currently selected header
21
- * @param {string} prevState the previous sort state of the table
22
- * @returns {string}
16
+ * @param prevHeader - Key of the previously sorted header.
17
+ * @param currentHeader - Key of the currently selected header.
18
+ * @param prevState - Previous sort direction.
23
19
  */
24
- const getNextSortDirection = (prevHeader, header, prevState) => {
25
- // If the previous header is equivalent to the current header, we know that we
26
- // have to derive the next sort state from the previous sort state
27
- if (prevHeader === header) {
28
- // When transitioning, we know that the sequence of states is as follows:
29
- // NONE -> ASC -> DESC -> NONE
30
- if (prevState === 'NONE') {
31
- return sortStates.ASC;
20
+ const getNextSortDirection = (prevHeader, currentHeader, prevState) => {
21
+ // Cycle for sorting the same header: NONE -> ASC -> DESC -> NONE.
22
+ if (prevHeader === currentHeader) {
23
+ switch (prevState) {
24
+ case sortStates.NONE:
25
+ return sortStates.ASC;
26
+ case sortStates.ASC:
27
+ return sortStates.DESC;
28
+ case sortStates.DESC:
29
+ return sortStates.NONE;
32
30
  }
33
- if (prevState === 'ASC') {
34
- return sortStates.DESC;
35
- }
36
- return sortStates.NONE;
37
31
  }
38
- // Otherwise, we have selected a new header and need to start off by sorting
39
- // in descending order by default
32
+
33
+ // Sorting a new header starts at ascending order.
40
34
  return sortStates.ASC;
41
35
  };
36
+
37
+ /**
38
+ * Gets the next sort state.
39
+ *
40
+ * @param props - Component props.
41
+ * @param state - Current table state.
42
+ * @param key - Header key to sort by.
43
+ */
42
44
  const getNextSortState = (props, state, {
43
45
  key
44
46
  }) => {
@@ -46,38 +48,26 @@ const getNextSortState = (props, state, {
46
48
  sortDirection,
47
49
  sortHeaderKey
48
50
  } = state;
49
- const nextSortDirection = getNextSortDirection(key, sortHeaderKey, sortDirection);
51
+ const nextSortDirection = getNextSortDirection(key, sortHeaderKey ?? '', sortDirection);
50
52
  return getSortedState(props, state, key, nextSortDirection);
51
53
  };
52
54
 
53
55
  /**
54
- * Derive the set of sorted state fields from props and state for the given
55
- * header key and sortDirection
56
+ * Gets a sort state update.
56
57
  *
57
- * @param {object} props
58
- * @param {string} props.locale The current locale
59
- * @param {Function} props.sortRows Method to handle sorting a collection of
60
- * rows
61
- * @param {object} state
62
- * @param {Array<string>} state.rowIds Array of row ids
63
- * @param {object} state.cellsById Lookup object for cells by id
64
- * @param {Array<string>} state.initialRowOrder Initial row order for the
65
- * current set of rows
66
- * @param {string} key The key for the given header we are serving the
67
- * sorted state for
68
- * @param {string} sortDirection The sortState that we want to order by
69
- * @returns {object}
58
+ * @param props - Component props.
59
+ * @param state - Current state of the table.
60
+ * @param key - Header key to sort by.
61
+ * @param sortDirection - Sort direction to apply.
70
62
  */
71
- const getSortedState = (props, state, key, sortDirection) => {
72
- const {
73
- rowIds,
74
- cellsById,
75
- initialRowOrder
76
- } = state;
77
- const {
78
- locale,
79
- sortRow
80
- } = props;
63
+ const getSortedState = ({
64
+ locale,
65
+ sortRow
66
+ }, {
67
+ rowIds,
68
+ cellsById,
69
+ initialRowOrder
70
+ }, key, sortDirection) => {
81
71
  const nextRowIds = sortDirection !== sortStates.NONE ? sortRows({
82
72
  rowIds,
83
73
  cellsById,
@@ -88,9 +78,9 @@ const getSortedState = (props, state, key, sortDirection) => {
88
78
  }) : initialRowOrder;
89
79
  return {
90
80
  sortHeaderKey: key,
91
- sortDirection: sortDirection,
81
+ sortDirection,
92
82
  rowIds: nextRowIds
93
83
  };
94
84
  };
95
85
 
96
- export { getNextSortDirection, getNextSortState, getSortedState, initialSortState, sortStates };
86
+ export { getNextSortDirection, getNextSortState, getSortedState, initialSortState };
@@ -42,6 +42,10 @@ const compareStrings = (a, b, locale = 'en') => {
42
42
  numeric: isNumeric
43
43
  });
44
44
  };
45
+
46
+ // TODO: Should `SortRowParams` in
47
+ // packages/react/src/components/DataTable/state/sorting.ts be used here?
48
+
45
49
  /**
46
50
  * Sorts table rows based on the provided column key and direction.
47
51
  */