@carbon/react 1.90.0 → 1.91.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 (118) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +921 -921
  2. package/es/components/CodeSnippet/CodeSnippet.d.ts +1 -1
  3. package/es/components/CodeSnippet/CodeSnippet.js +1 -1
  4. package/es/components/ComboBox/ComboBox.js +1 -12
  5. package/es/components/ComboButton/index.js +1 -1
  6. package/es/components/ComposedModal/ComposedModal.js +1 -1
  7. package/es/components/Copy/Copy.d.ts +1 -1
  8. package/es/components/Copy/Copy.js +1 -1
  9. package/es/components/CopyButton/CopyButton.d.ts +1 -1
  10. package/es/components/CopyButton/CopyButton.js +1 -1
  11. package/es/components/DataTable/DataTable.d.ts +60 -15
  12. package/es/components/DataTable/DataTable.js +106 -179
  13. package/es/components/DataTable/Table.d.ts +2 -2
  14. package/es/components/DataTable/Table.js +1 -1
  15. package/es/components/DataTable/TableExpandHeader.d.ts +1 -1
  16. package/es/components/DataTable/TableExpandHeader.js +1 -1
  17. package/es/components/DatePicker/DatePicker.d.ts +0 -12
  18. package/es/components/DatePicker/DatePicker.js +3 -3
  19. package/es/components/DatePicker/plugins/rangePlugin.d.ts +19 -2
  20. package/es/components/DatePicker/plugins/rangePlugin.js +18 -14
  21. package/es/components/Dropdown/Dropdown.js +1 -12
  22. package/es/components/FeatureFlags/index.js +1 -0
  23. package/es/components/IconButton/index.js +1 -1
  24. package/es/components/Menu/MenuItem.d.ts +1 -1
  25. package/es/components/Menu/MenuItem.js +5 -5
  26. package/es/components/Modal/Modal.js +1 -1
  27. package/es/components/MultiSelect/FilterableMultiSelect.js +1 -1
  28. package/es/components/MultiSelect/MultiSelect.js +1 -12
  29. package/es/components/Notification/Notification.d.ts +6 -6
  30. package/es/components/Notification/Notification.js +6 -6
  31. package/es/components/OverflowMenu/OverflowMenu.js +1 -1
  32. package/es/components/OverflowMenu/next/index.js +1 -1
  33. package/es/components/Popover/index.js +1 -1
  34. package/es/components/Search/Search.d.ts +4 -2
  35. package/es/components/Search/Search.js +5 -4
  36. package/es/components/Slider/Slider.d.ts +144 -188
  37. package/es/components/Slider/Slider.js +787 -710
  38. package/es/components/Slider/index.d.ts +2 -2
  39. package/es/components/Tabs/Tabs.d.ts +4 -0
  40. package/es/components/TextArea/TextArea.js +13 -6
  41. package/es/components/TextInput/ControlledPasswordInput.js +2 -2
  42. package/es/components/TextInput/PasswordInput.js +2 -2
  43. package/es/components/TextInput/TextInput.js +2 -2
  44. package/es/components/TextInput/util.d.ts +17 -5
  45. package/es/components/TextInput/util.js +2 -7
  46. package/es/components/UIShell/HeaderPanel.d.ts +1 -1
  47. package/es/index.d.ts +12 -13
  48. package/es/index.js +25 -24
  49. package/es/internal/defaultItemToString.d.ts +7 -0
  50. package/es/internal/defaultItemToString.js +17 -0
  51. package/es/internal/index.d.ts +1 -0
  52. package/es/prop-types/deprecateValuesWithin.d.ts +8 -1
  53. package/es/prop-types/deprecateValuesWithin.js +6 -6
  54. package/es/prop-types/requiredIfGivenPropIsTruthy.d.ts +8 -7
  55. package/es/prop-types/requiredIfGivenPropIsTruthy.js +10 -10
  56. package/lib/components/CodeSnippet/CodeSnippet.d.ts +1 -1
  57. package/lib/components/CodeSnippet/CodeSnippet.js +1 -1
  58. package/lib/components/ComboBox/ComboBox.js +3 -14
  59. package/lib/components/ComboButton/index.js +1 -1
  60. package/lib/components/ComposedModal/ComposedModal.js +1 -1
  61. package/lib/components/Copy/Copy.d.ts +1 -1
  62. package/lib/components/Copy/Copy.js +1 -1
  63. package/lib/components/CopyButton/CopyButton.d.ts +1 -1
  64. package/lib/components/CopyButton/CopyButton.js +1 -1
  65. package/lib/components/DataTable/DataTable.d.ts +60 -15
  66. package/lib/components/DataTable/DataTable.js +106 -179
  67. package/lib/components/DataTable/Table.d.ts +2 -2
  68. package/lib/components/DataTable/Table.js +1 -1
  69. package/lib/components/DataTable/TableExpandHeader.d.ts +1 -1
  70. package/lib/components/DataTable/TableExpandHeader.js +3 -3
  71. package/lib/components/DatePicker/DatePicker.d.ts +0 -12
  72. package/lib/components/DatePicker/DatePicker.js +2 -2
  73. package/lib/components/DatePicker/plugins/rangePlugin.d.ts +19 -2
  74. package/lib/components/DatePicker/plugins/rangePlugin.js +18 -16
  75. package/lib/components/Dropdown/Dropdown.js +3 -14
  76. package/lib/components/FeatureFlags/index.js +1 -0
  77. package/lib/components/IconButton/index.js +1 -1
  78. package/lib/components/Menu/MenuItem.d.ts +1 -1
  79. package/lib/components/Menu/MenuItem.js +6 -6
  80. package/lib/components/Modal/Modal.js +1 -1
  81. package/lib/components/MultiSelect/FilterableMultiSelect.js +8 -8
  82. package/lib/components/MultiSelect/MultiSelect.js +2 -13
  83. package/lib/components/Notification/Notification.d.ts +6 -6
  84. package/lib/components/Notification/Notification.js +6 -6
  85. package/lib/components/OverflowMenu/OverflowMenu.js +1 -1
  86. package/lib/components/OverflowMenu/next/index.js +1 -1
  87. package/lib/components/Popover/index.js +1 -1
  88. package/lib/components/Search/Search.d.ts +4 -2
  89. package/lib/components/Search/Search.js +5 -4
  90. package/lib/components/Slider/Slider.d.ts +144 -188
  91. package/lib/components/Slider/Slider.js +784 -709
  92. package/lib/components/Slider/index.d.ts +2 -2
  93. package/lib/components/Tabs/Tabs.d.ts +4 -0
  94. package/lib/components/TextArea/TextArea.js +13 -6
  95. package/lib/components/TextInput/ControlledPasswordInput.js +1 -1
  96. package/lib/components/TextInput/PasswordInput.js +1 -1
  97. package/lib/components/TextInput/TextInput.js +1 -1
  98. package/lib/components/TextInput/util.d.ts +17 -5
  99. package/lib/components/TextInput/util.js +2 -7
  100. package/lib/components/UIShell/HeaderPanel.d.ts +1 -1
  101. package/lib/index.d.ts +12 -13
  102. package/lib/index.js +51 -28
  103. package/lib/internal/defaultItemToString.d.ts +7 -0
  104. package/lib/internal/defaultItemToString.js +19 -0
  105. package/lib/internal/index.d.ts +1 -0
  106. package/lib/prop-types/deprecateValuesWithin.d.ts +8 -1
  107. package/lib/prop-types/deprecateValuesWithin.js +6 -8
  108. package/lib/prop-types/requiredIfGivenPropIsTruthy.d.ts +8 -7
  109. package/lib/prop-types/requiredIfGivenPropIsTruthy.js +10 -12
  110. package/package.json +8 -7
  111. package/es/components/MultiSelect/tools/itemToString.d.ts +0 -1
  112. package/es/components/MultiSelect/tools/itemToString.js +0 -21
  113. package/es/components/Slider/index.js +0 -14
  114. package/es/internal/createClassWrapper.js +0 -23
  115. package/lib/components/MultiSelect/tools/itemToString.d.ts +0 -1
  116. package/lib/components/MultiSelect/tools/itemToString.js +0 -23
  117. package/lib/components/Slider/index.js +0 -20
  118. package/lib/internal/createClassWrapper.js +0 -25
@@ -37,6 +37,7 @@ import TableToolbarAction from './TableToolbarAction.js';
37
37
  import TableToolbarContent from './TableToolbarContent.js';
38
38
  import TableToolbarSearch from './TableToolbarSearch.js';
39
39
  import TableToolbarMenu from './TableToolbarMenu.js';
40
+ import { deprecate } from '../../prop-types/deprecate.js';
40
41
 
41
42
  const getInstanceId = setupGetInstanceId();
42
43
  const translationKeys = {
@@ -50,11 +51,8 @@ const translationKeys = {
50
51
  unselectRow: 'carbon.table.row.unselect'
51
52
  };
52
53
 
53
- // TODO: All code comments in this file should be revisited for accuracy and
54
- // clarity.
55
-
56
54
  /**
57
- * Message ids that will be passed to translateWithId().
55
+ * Message IDs that will be passed to translateWithId().
58
56
  */
59
57
 
60
58
  const defaultTranslations = {
@@ -80,14 +78,12 @@ const translateWithId = id => defaultTranslations[id];
80
78
  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20071
81
79
 
82
80
  /**
83
- * Data Tables are used to represent a collection of resources, displaying a
84
- * subset of their fields in columns, or headers. We prioritize direct updates
85
- * to the state of what we're rendering, so internally we end up normalizing the
86
- * given data and then denormalizing it when rendering.
87
- *
88
- * As a result, each part of the DataTable is accessible through look-up by id,
89
- * and updating the state of the single entity will cascade updates to the
90
- * consumer.
81
+ * DataTable components are used to represent a collection of resources,
82
+ * displaying a subset of their fields in columns, or headers. We prioritize
83
+ * direct updates to the state of what we're rendering, so internally we
84
+ * normalize the given data and then denormalize it at render time. Each part of
85
+ * the DataTable is accessible through look-up by ID, and updating the state of
86
+ * a single entity cascades updates to the consumer.
91
87
  */
92
88
  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20071
93
89
  const DataTable = props => {
@@ -110,24 +106,18 @@ const DataTable = props => {
110
106
  const instanceId = useMemo(() => getInstanceId(), []);
111
107
  const [state, setState] = useState(() => ({
112
108
  ...getDerivedStateFromProps(props, {}),
113
- isExpandedAll: false // Start with collapsed state, treat `undefined` as neutral state
109
+ // Initialize to collapsed. A value of `undefined` is treated as neutral.
110
+ isExpandedAll: false
114
111
  }));
115
112
  useEffect(() => {
116
113
  const nextRowIds = rows.map(row => row.id);
117
114
  const nextHeaders = headers.map(header => header.key);
118
115
  const hasRowIdsChanged = !isEqual(nextRowIds, state.rowIds);
119
- const currentHeaders = Object.keys(state.cellsById).reduce((acc, cellId) => {
120
- const headerKey = cellId.split(':')[1];
121
- if (headerKey && !acc.includes(headerKey)) {
122
- acc.push(headerKey);
123
- }
124
- return acc;
125
- }, []);
116
+ const currentHeaders = Array.from(new Set(Object.keys(state.cellsById).map(id => id.split(':')[1])));
126
117
  const hasHeadersChanged = !isEqual(nextHeaders, currentHeaders);
127
118
  const currentRows = state.rowIds.map(id => {
128
119
  const row = state.rowsById[id];
129
120
  return {
130
- // TODO: Investigate whether it be okay to just return `row`.
131
121
  id: row.id,
132
122
  disabled: row.disabled,
133
123
  isExpanded: row.isExpanded,
@@ -140,11 +130,6 @@ const DataTable = props => {
140
130
  }
141
131
  // eslint-disable-next-line react-hooks/exhaustive-deps -- https://github.com/carbon-design-system/carbon/issues/20071
142
132
  }, [headers, rows]);
143
-
144
- /**
145
- * Get the props associated with the given header. Mostly used for adding in
146
- * sorting behavior.
147
- */
148
133
  const getHeaderProps = ({
149
134
  header,
150
135
  onClick,
@@ -155,34 +140,36 @@ const DataTable = props => {
155
140
  sortDirection,
156
141
  sortHeaderKey
157
142
  } = state;
143
+ const {
144
+ key,
145
+ slug,
146
+ decorator
147
+ } = header;
158
148
  return {
159
149
  ...rest,
160
- key: header.key,
150
+ key,
161
151
  sortDirection,
162
152
  isSortable,
163
- isSortHeader: sortHeaderKey === header.key,
164
- slug: header.slug,
165
- decorator: header.decorator,
153
+ isSortHeader: sortHeaderKey === key,
154
+ slug,
155
+ decorator,
166
156
  onClick: event => {
167
157
  const nextSortState = getNextSortState(props, state, {
168
- key: header.key
158
+ key
169
159
  });
170
160
  setState(prev => ({
171
161
  ...prev,
172
162
  ...nextSortState
173
163
  }));
174
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20071
175
- onClick && handleOnHeaderClick(onClick, {
176
- sortHeaderKey: header.key,
177
- sortDirection: nextSortState.sortDirection
178
- })(event);
164
+ if (onClick) {
165
+ handleOnHeaderClick(onClick, {
166
+ sortHeaderKey: key,
167
+ sortDirection: nextSortState.sortDirection
168
+ })(event);
169
+ }
179
170
  }
180
171
  };
181
172
  };
182
-
183
- /**
184
- * Get the props associated with the given expand header.
185
- */
186
173
  const getExpandHeaderProps = ({
187
174
  onClick,
188
175
  onExpand,
@@ -195,39 +182,35 @@ const DataTable = props => {
195
182
  } = state;
196
183
  const isExpanded = isExpandedAll || rowIds.every(id => rowsById[id].isExpanded);
197
184
  const translationKey = isExpanded ? translationKeys.collapseAll : translationKeys.expandAll;
185
+ const handlers = [handleOnExpandAll, onExpand];
186
+ if (onClick) {
187
+ handlers.push(handleOnExpandHeaderClick(onClick, {
188
+ isExpanded
189
+ }));
190
+ }
198
191
  return {
199
192
  ...rest,
200
193
  'aria-label': t(translationKey),
201
- // Provide a string of all the expanded row id's, separated by a space.
194
+ // Provide a string of all expanded row IDs, separated by a space.
202
195
  'aria-controls': rowIds.map(id => `expanded-row-${id}`).join(' '),
203
196
  isExpanded,
204
- // Compose the event handlers so we don't overwrite a consumer's `onClick`
205
- // handler
206
- onExpand: composeEventHandlers([handleOnExpandAll, onExpand,
207
- // TODO: Avoid passing `false` to this function.
208
- onClick && handleOnExpandHeaderClick(onClick, {
209
- isExpanded
210
- })])
197
+ onExpand: composeEventHandlers(handlers)
211
198
  };
212
199
  };
213
200
 
214
201
  /**
215
- * Decorate consumer's `onClick` event handler with sort parameters
202
+ * Wraps the consumer's `onClick` with sorting metadata.
216
203
  */
217
204
  const handleOnHeaderClick = (onClick, sortParams) => {
218
205
  return event => onClick(event, sortParams);
219
206
  };
220
207
 
221
208
  /**
222
- * Decorate consumer's `onClick` event handler with expand parameters
209
+ * Wraps the consumer's `onClick` with sorting metadata.
223
210
  */
224
211
  const handleOnExpandHeaderClick = (onClick, expandParams) => {
225
212
  return event => onClick(event, expandParams);
226
213
  };
227
-
228
- /**
229
- * Get the props associated with the given row. Mostly used for expansion.
230
- */
231
214
  const getRowProps = ({
232
215
  row,
233
216
  onClick,
@@ -248,10 +231,6 @@ const DataTable = props => {
248
231
  disabled: row.disabled
249
232
  };
250
233
  };
251
-
252
- /**
253
- * Get the props associated with an expanded row
254
- */
255
234
  const getExpandedRowProps = ({
256
235
  row,
257
236
  ...rest
@@ -263,9 +242,7 @@ const DataTable = props => {
263
242
  };
264
243
 
265
244
  /**
266
- * Gets the props associated with selection for a header or a row, where
267
- * applicable. Most often used to indicate selection status of the table or
268
- * for a specific row.
245
+ * Gets the props associated with selection for a header or a row.
269
246
  */
270
247
  const getSelectionProps = ({
271
248
  onClick,
@@ -290,7 +267,7 @@ const DataTable = props => {
290
267
  // Otherwise, we're working on `TableSelectAll` which handles toggling the
291
268
  // selection state of all rows.
292
269
  const rowCount = state.rowIds.length;
293
- const selectedRowCount = getSelectedRows().length;
270
+ const selectedRowCount = selectedRows.length;
294
271
  const checked = rowCount > 0 && selectedRowCount === rowCount;
295
272
  const indeterminate = rowCount > 0 && selectedRowCount > 0 && selectedRowCount !== rowCount;
296
273
  const translationKey = checked || indeterminate ? translationKeys.unselectAll : translationKeys.selectAll;
@@ -315,13 +292,13 @@ const DataTable = props => {
315
292
  const {
316
293
  shouldShowBatchActions
317
294
  } = state;
318
- const totalSelected = getSelectedRows().length;
295
+ const selectedRowCount = selectedRows.length;
319
296
  return {
320
297
  onSelectAll: undefined,
321
- totalCount: state.rowIds.length || 0,
298
+ totalCount: state.rowIds.length,
322
299
  ...props,
323
- shouldShowBatchActions: shouldShowBatchActions && totalSelected > 0,
324
- totalSelected,
300
+ shouldShowBatchActions: shouldShowBatchActions && selectedRowCount > 0,
301
+ totalSelected: selectedRowCount,
325
302
  onCancel: handleOnCancel
326
303
  };
327
304
  };
@@ -342,77 +319,49 @@ const DataTable = props => {
342
319
  useStaticWidth
343
320
  };
344
321
  };
345
-
346
- // TODO: `getHeaderProps` and `getRowProps` return `key` props. Would it be
347
- // beneficial for this function to also return a `key` prop?
348
- /**
349
- * Get the props associated with the given table cell.
350
- */
351
322
  const getCellProps = ({
352
323
  cell: {
353
324
  hasAILabelHeader,
354
- hasDecoratorHeader
325
+ id
355
326
  },
356
327
  ...rest
357
328
  }) => {
358
329
  return {
359
330
  ...rest,
360
331
  hasAILabelHeader,
361
- hasDecoratorHeader
332
+ key: id
362
333
  };
363
334
  };
364
335
 
365
336
  /**
366
- * Helper utility to get all the currently selected rows
367
- *
368
- * @returns the array of rowIds that are currently selected
337
+ * Selected row IDs, excluding disabled rows.
369
338
  */
370
- const getSelectedRows = () => state.rowIds.filter(id => {
339
+ const selectedRows = state.rowIds.filter(id => {
371
340
  const row = state.rowsById[id];
372
341
  return row.isSelected && !row.disabled;
373
342
  });
343
+ const filteredRowIds = typeof state.filterInputValue === 'string' ? filterRows({
344
+ cellsById: state.cellsById,
345
+ getCellId,
346
+ headers,
347
+ inputValue: state.filterInputValue,
348
+ rowIds: state.rowIds
349
+ }) : state.rowIds;
374
350
 
375
351
  /**
376
- * Helper utility to get all of the available rows after applying the filter
377
- *
378
- * @returns the array of rowIds that are currently included through the filter
379
- */
380
- const getFilteredRowIds = () => {
381
- const filteredRowIds = typeof state.filterInputValue === 'string' ? filterRows({
382
- rowIds: state.rowIds,
383
- headers: headers,
384
- cellsById: state.cellsById,
385
- inputValue: state.filterInputValue,
386
- getCellId
387
- }) : state.rowIds;
388
- // TODO: Use strict equality check.
389
- if (filteredRowIds.length == 0) {
390
- return [];
391
- }
392
- return filteredRowIds;
393
- };
394
-
395
- /**
396
- * Helper for getting the table prefix for elements that require an
397
- * `id` attribute that is unique.
352
+ * Generates a prefix for table related IDs.
398
353
  */
399
354
  const getTablePrefix = () => `data-table-${instanceId}`;
400
355
 
401
356
  /**
402
- * Helper for toggling all selected items in a state. Does not call
403
- * setState, so use it when setting state.
404
- *
405
- * @returns object to put into this.setState (use spread operator)
357
+ * Generates a new `rowsById` object with updated selection state.
406
358
  */
407
- const setAllSelectedState = (initialState, isSelected, filteredRowIds) => {
359
+ const getUpdatedSelectionState = (initialState, isSelected) => {
408
360
  const {
409
361
  rowIds
410
362
  } = initialState;
411
- // TODO: Use strict inequality check.
412
- const isFiltered = rowIds.length != filteredRowIds.length;
363
+ const isFiltered = rowIds.length !== filteredRowIds.length;
413
364
  return {
414
- // TODO: Should the `reduce` be typed with `<Record<string,
415
- // DataTableRow<ColTypes>>>`?
416
365
  rowsById: rowIds.reduce((acc, id) => {
417
366
  const row = {
418
367
  ...initialState.rowsById[id]
@@ -420,62 +369,59 @@ const DataTable = props => {
420
369
  if (!row.disabled && (!isFiltered || filteredRowIds.includes(id))) {
421
370
  row.isSelected = isSelected;
422
371
  }
423
- acc[id] = row; // Local mutation for performance with large tables
372
+
373
+ // Local mutation for performance with large tables
374
+ acc[id] = row;
424
375
  return acc;
425
376
  }, {})
426
377
  };
427
378
  };
428
379
 
429
380
  /**
430
- * Handler for the `onCancel` event to hide the batch action bar and
431
- * deselect all selected rows
381
+ * Handler for `onCancel` to hide the batch action toolbar and deselect all
382
+ * rows.
432
383
  */
433
384
  const handleOnCancel = () => {
434
385
  setState(prev => {
435
386
  return {
436
387
  ...prev,
437
388
  shouldShowBatchActions: false,
438
- ...setAllSelectedState(prev, false, getFilteredRowIds())
389
+ ...getUpdatedSelectionState(prev, false)
439
390
  };
440
391
  });
441
392
  };
442
393
 
443
394
  /**
444
- * Handler for toggling the selection state of all rows in the database
395
+ * Handler for toggling the selection state of all rows.
445
396
  */
446
397
  const handleSelectAll = () => {
447
398
  setState(prev => {
448
- const filteredRowIds = getFilteredRowIds();
449
399
  const {
450
400
  rowsById
451
401
  } = prev;
452
- const isSelected = !(Object.values(rowsById).filter(row => row.isSelected && !row.disabled).length > 0);
402
+ const isSelected = !Object.values(rowsById).filter(row => row.isSelected && !row.disabled).length;
453
403
  return {
454
404
  ...prev,
455
405
  shouldShowBatchActions: isSelected,
456
- ...setAllSelectedState(prev, isSelected, filteredRowIds)
406
+ ...getUpdatedSelectionState(prev, isSelected)
457
407
  };
458
408
  });
459
409
  };
460
410
 
461
411
  /**
462
- * Handler for toggling the selection state of a given row.
412
+ * Handler for toggling selection state of a given row.
463
413
  */
464
414
  const handleOnSelectRow = rowId => () => {
465
415
  setState(prev => {
466
416
  const row = prev.rowsById[rowId];
467
417
  if (radio) {
468
- // TODO:
469
- // 1. Should the `reduce` be typed with `<Record<string,
470
- // DataTableRow<ColTypes>>>`?
471
- // 2. Add better parameter names. Use `acc` and `row`.
472
- //
473
- // deselect all radio buttons
474
- const rowsById = Object.entries(prev.rowsById).reduce((p, c) => {
475
- const [key, val] = c;
476
- val.isSelected = false;
477
- p[key] = val;
478
- return p;
418
+ // Deselect all radio buttons, then toggle the target row
419
+ const rowsById = Object.entries(prev.rowsById).reduce((acc, [id, row]) => {
420
+ acc[id] = {
421
+ ...row,
422
+ isSelected: false
423
+ };
424
+ return acc;
479
425
  }, {});
480
426
  return {
481
427
  ...prev,
@@ -483,8 +429,8 @@ const DataTable = props => {
483
429
  rowsById: {
484
430
  ...rowsById,
485
431
  [rowId]: {
486
- ...row,
487
- isSelected: !row.isSelected
432
+ ...rowsById[rowId],
433
+ isSelected: !rowsById[rowId].isSelected
488
434
  }
489
435
  }
490
436
  };
@@ -494,10 +440,8 @@ const DataTable = props => {
494
440
  const selectedRowsCount = !row.isSelected ? selectedRows + 1 : selectedRows - 1;
495
441
  return {
496
442
  ...prev,
497
- // Basic assumption here is that we want to show the batch action bar if
498
- // the row is being selected. If it's being unselected, then see if we
499
- // have a non-zero number of selected rows that batch actions could
500
- // still apply to
443
+ // Show batch action toolbar if selecting, or if there are other
444
+ // selected rows remaining.
501
445
  shouldShowBatchActions: !row.isSelected || selectedRowsCount > 0,
502
446
  rowsById: {
503
447
  ...prev.rowsById,
@@ -509,10 +453,6 @@ const DataTable = props => {
509
453
  };
510
454
  });
511
455
  };
512
-
513
- /**
514
- * Handler for toggling the expansion state of a given row.
515
- */
516
456
  const handleOnExpandRow = rowId => () => {
517
457
  setState(prev => {
518
458
  const row = prev.rowsById[rowId];
@@ -532,10 +472,6 @@ const DataTable = props => {
532
472
  };
533
473
  });
534
474
  };
535
-
536
- /**
537
- * Handler for changing the expansion state of all rows.
538
- */
539
475
  const handleOnExpandAll = () => {
540
476
  setState(prev => {
541
477
  const {
@@ -545,22 +481,19 @@ const DataTable = props => {
545
481
  return {
546
482
  ...prev,
547
483
  isExpandedAll: !isExpandedAll,
548
- // TODO: Add generic to `reduce`.
549
- rowsById: rowIds.reduce((acc, id) => ({
550
- ...acc,
551
- [id]: {
484
+ rowsById: rowIds.reduce((acc, id) => {
485
+ acc[id] = {
552
486
  ...prev.rowsById[id],
553
487
  isExpanded: !isExpandedAll
554
- }
555
- }), {})
488
+ };
489
+ return acc;
490
+ }, {})
556
491
  };
557
492
  });
558
493
  };
559
494
 
560
495
  /**
561
- * Handler for transitioning to the next sort state of the table
562
- *
563
- * @param headerKey - The field for the header that we are sorting by.
496
+ * Transitions to the next sort state of the table.
564
497
  */
565
498
  const handleSortBy = headerKey => () => {
566
499
  setState(prev => {
@@ -576,37 +509,20 @@ const DataTable = props => {
576
509
  };
577
510
 
578
511
  /**
579
- * Event handler for transitioning input value state changes for the table
580
- * filter component.
512
+ * Event handler for table filter input changes.
581
513
  */
582
514
  const handleOnInputValueChange = (event, defaultValue) => {
583
- if (event.target) {
584
- setState(prev => ({
585
- ...prev,
586
- filterInputValue: event.target.value
587
- }));
588
- }
589
- if (defaultValue) {
590
- setState(prev => ({
591
- ...prev,
592
- filterInputValue: defaultValue
593
- }));
594
- }
515
+ const value = defaultValue || event.target?.value;
516
+ setState(prev => ({
517
+ ...prev,
518
+ filterInputValue: value
519
+ }));
595
520
  };
596
-
597
- // TODO: Could getFilteredRowIds be used here?
598
- const filteredRowIds = typeof state.filterInputValue === 'string' ? filterRows({
599
- rowIds: state.rowIds,
600
- headers,
601
- cellsById: state.cellsById,
602
- inputValue: state.filterInputValue,
603
- getCellId
604
- }) : state.rowIds;
605
521
  const renderProps = {
606
522
  // Data derived from state
607
523
  rows: denormalize(filteredRowIds, state.rowsById, state.cellsById),
608
524
  headers: headers,
609
- selectedRows: denormalize(getSelectedRows(), state.rowsById, state.cellsById),
525
+ selectedRows: denormalize(selectedRows, state.rowsById, state.cellsById),
610
526
  // Prop accessors/getters
611
527
  getHeaderProps,
612
528
  getExpandHeaderProps,
@@ -660,6 +576,10 @@ DataTable.TableToolbarContent = TableToolbarContent;
660
576
  DataTable.TableToolbarSearch = TableToolbarSearch;
661
577
  DataTable.TableToolbarMenu = TableToolbarMenu;
662
578
  DataTable.propTypes = {
579
+ /**
580
+ * Pass in the children that will be rendered within the Table
581
+ */
582
+ children: PropTypes.node,
663
583
  /**
664
584
  * Experimental property. Allows table to align cell contents to the top if there is text wrapping in the content. Might have performance issues, intended for smaller tables
665
585
  */
@@ -695,6 +615,13 @@ DataTable.propTypes = {
695
615
  * Specify whether the control should be a radio button or inline checkbox
696
616
  */
697
617
  radio: PropTypes.bool,
618
+ /**
619
+ * @deprecated Use `children` instead. This prop will be removed in
620
+ * the next major version.
621
+ *
622
+ * https://www.patterns.dev/react/render-props-pattern/#children-as-a-function
623
+ */
624
+ render: deprecate(PropTypes.func),
698
625
  /**
699
626
  * The `rows` prop is where you provide us with a list of all the rows that
700
627
  * you want to render in the table. The only hard requirement is that this
@@ -721,13 +648,13 @@ DataTable.propTypes = {
721
648
  */
722
649
  stickyHeader: PropTypes.bool,
723
650
  /**
724
- * Optional method that takes in a message id and returns an
651
+ * Optional method that takes in a message ID and returns an
725
652
  * internationalized string. See `DataTable.translationKeys` for all
726
- * available message ids.
653
+ * available message IDs.
727
654
  */
728
655
  translateWithId: PropTypes.func,
729
656
  /**
730
- * `false` If true, will use a width of 'auto' instead of 100%
657
+ * If `true`, sets the table width to `auto` instead of `100%`.
731
658
  */
732
659
  useStaticWidth: PropTypes.bool,
733
660
  /**
@@ -26,7 +26,7 @@ export interface TableProps {
26
26
  */
27
27
  stickyHeader?: boolean;
28
28
  /**
29
- * `false` If true, will use a width of 'auto' instead of 100%
29
+ * If `true`, sets the table width to `auto` instead of `100%`.
30
30
  */
31
31
  useStaticWidth?: boolean;
32
32
  /**
@@ -67,7 +67,7 @@ export declare const Table: {
67
67
  */
68
68
  stickyHeader: PropTypes.Requireable<boolean>;
69
69
  /**
70
- * `false` If true, will use a width of 'auto' instead of 100%
70
+ * If `true`, sets the table width to `auto` instead of `100%`.
71
71
  */
72
72
  useStaticWidth: PropTypes.Requireable<boolean>;
73
73
  /**
@@ -166,7 +166,7 @@ Table.propTypes = {
166
166
  */
167
167
  stickyHeader: PropTypes.bool,
168
168
  /**
169
- * `false` If true, will use a width of 'auto' instead of 100%
169
+ * If `true`, sets the table width to `auto` instead of `100%`.
170
170
  */
171
171
  useStaticWidth: PropTypes.bool,
172
172
  /**
@@ -98,7 +98,7 @@ declare const TableExpandHeader: {
98
98
  * Specify whether this row is expanded or not. This helps coordinate data
99
99
  * attributes so that `TableExpandRow` and `TableExpandedRow` work together
100
100
  */
101
- isExpanded: React.Validator;
101
+ isExpanded: PropTypes.Validator<boolean | null | undefined>;
102
102
  /**
103
103
  * Hook for when a listener initiates a request to expand the given row
104
104
  */
@@ -12,7 +12,7 @@ import PropTypes from 'prop-types';
12
12
  import React from 'react';
13
13
  import { usePrefix } from '../../internal/usePrefix.js';
14
14
  import { deprecate } from '../../prop-types/deprecate.js';
15
- import requiredIfGivenPropIsTruthy from '../../prop-types/requiredIfGivenPropIsTruthy.js';
15
+ import { requiredIfGivenPropIsTruthy } from '../../prop-types/requiredIfGivenPropIsTruthy.js';
16
16
 
17
17
  const TableExpandHeader = ({
18
18
  ['aria-controls']: ariaControls,
@@ -8,18 +8,6 @@ import React, { ReactNode } from 'react';
8
8
  import flatpickr from 'flatpickr';
9
9
  import { DateLimit, DateOption } from 'flatpickr/dist/types/options';
10
10
  export type DatePickerTypes = 'simple' | 'single' | 'range';
11
- export type CalRef = {
12
- inline: boolean;
13
- disableMobile: boolean;
14
- defaultDate: Date;
15
- closeOnSelect: (evt: React.ChangeEvent<HTMLTextAreaElement>) => void;
16
- mode: 'simple' | 'single' | 'range';
17
- allowInput: boolean;
18
- dateFormat: string;
19
- locale: string;
20
- plugins: [];
21
- clickOpens: any;
22
- };
23
11
  export interface DatePickerProps {
24
12
  /**
25
13
  * Flatpickr prop passthrough enables direct date input, and when set to false,
@@ -14,7 +14,7 @@ import l10n from 'flatpickr/dist/l10n/index';
14
14
  import DatePickerInput from '../DatePickerInput/DatePickerInput.js';
15
15
  import { appendToPlugin } from './plugins/appendToPlugin.js';
16
16
  import carbonFlatpickrFixEventsPlugin from './plugins/fixEventsPlugin.js';
17
- import carbonFlatpickrRangePlugin from './plugins/rangePlugin.js';
17
+ import { rangePlugin } from './plugins/rangePlugin.js';
18
18
  import { deprecate } from '../../prop-types/deprecate.js';
19
19
  import { Escape, Tab, Enter } from '../../internal/keyboard/keys.js';
20
20
  import { match } from '../../internal/keyboard/match.js';
@@ -354,8 +354,8 @@ const DatePicker = /*#__PURE__*/React.forwardRef(function DatePicker({
354
354
  minDate: minDate,
355
355
  maxDate: maxDate,
356
356
  parseDate: parseDate,
357
- plugins: [datePickerType === 'range' ? carbonFlatpickrRangePlugin({
358
- input: endInputField.current
357
+ plugins: [datePickerType === 'range' ? rangePlugin({
358
+ input: endInputField.current ?? undefined
359
359
  }) : () => {}, appendTo ? appendToPlugin({
360
360
  appendTo
361
361
  }) : () => {}, carbonFlatpickrMonthSelectPlugin({
@@ -1,2 +1,19 @@
1
- declare function _default(config: object): Plugin;
2
- export default _default;
1
+ /**
2
+ * Copyright IBM Corp. 2019, 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 Config } from 'flatpickr/dist/plugins/rangePlugin';
8
+ import { Instance } from 'flatpickr/dist/types/instance';
9
+ /**
10
+ * @param config Plugin configuration.
11
+ * @returns An extension of Flatpickr `rangePlugin` that does the following:
12
+ * * Better ensures the calendar dropdown is always aligned to the `<input>` for the starting date.
13
+ * Workaround for: https://github.com/flatpickr/flatpickr/issues/1944
14
+ * * A logic to ensure `fp.setDate()` call won't end up with "startDate to endDate" set to the first `<input>`
15
+ */
16
+ export declare const rangePlugin: (config?: Config) => (fp: Instance) => Partial<import("flatpickr/dist/types/options").BaseOptions> & {
17
+ onReady: (import("flatpickr/dist/types/options").Hook | import("flatpickr/dist/types/options").Hook[] | undefined)[];
18
+ onPreCalendarPosition: () => void;
19
+ };