@primer/react 38.39.1-rc.99036c1d8 → 38.40.0-rc.37bd8a025

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,11 +1,21 @@
1
1
  # @primer/react
2
2
 
3
- ## 38.39.1
3
+ ## 38.40.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#8422](https://github.com/primer/react/pull/8422) [`2909f19`](https://github.com/primer/react/commit/2909f19f64dbbc12aefb3455139596d88e5098b2) Thanks [@tay1orjones](https://github.com/tay1orjones)! - NavList, ActionList: Add a `disableItemGap` prop to render navigation items edge-to-edge.
8
+
9
+ - [#8386](https://github.com/primer/react/pull/8386) [`6c64598`](https://github.com/primer/react/commit/6c645987c5ad27d5c23f57190a10b8707b29c58c) Thanks [@rickyzhangca](https://github.com/rickyzhangca)! - DataTable: Add config-driven row groups that can be interleaved with standalone rows.
4
10
 
5
11
  ### Patch Changes
6
12
 
7
13
  - [#8408](https://github.com/primer/react/pull/8408) [`c880319`](https://github.com/primer/react/commit/c8803199ddb0e669596f6e2370fd4117a055cfc3) Thanks [@janmaarten-a11y](https://github.com/janmaarten-a11y)! - Button and LinkButton: Limit link variant underlines to the text label when visuals are present
8
14
 
15
+ - [#8411](https://github.com/primer/react/pull/8411) [`8c52029`](https://github.com/primer/react/commit/8c520293151054fd39e5094f4740e97e89ce18d8) Thanks [@mattcosta7](https://github.com/mattcosta7)! - Tooltip: Prevent React Fragment triggers from crashing and provide a clear development warning
16
+
17
+ - [#8409](https://github.com/primer/react/pull/8409) [`9d0632c`](https://github.com/primer/react/commit/9d0632ccc6c23e92cbbe786ce922795c92931b04) Thanks [@iansan5653](https://github.com/iansan5653)! - Fix Tooltip ref handling to preserve child element ref
18
+
9
19
  ## 38.39.0
10
20
 
11
21
  ### Minor Changes
@@ -17,7 +17,7 @@ import { clsx } from "clsx";
17
17
  //#region src/ActionList/List.tsx
18
18
  const UnwrappedList = (props, forwardedRef) => {
19
19
  var _slots$heading$props$;
20
- const $ = c(40);
20
+ const $ = c(41);
21
21
  let className;
22
22
  let restProps;
23
23
  let role;
@@ -26,8 +26,9 @@ const UnwrappedList = (props, forwardedRef) => {
26
26
  let t1;
27
27
  let t2;
28
28
  let t3;
29
+ let t4;
29
30
  if ($[0] !== props) {
30
- ({as: t0, variant: t1, selectionVariant, showDividers: t2, role, disableFocusZone: t3, className, ...restProps} = props);
31
+ ({as: t0, variant: t1, selectionVariant, showDividers: t2, role, disableFocusZone: t3, disableItemGap: t4, className, ...restProps} = props);
31
32
  $[0] = props;
32
33
  $[1] = className;
33
34
  $[2] = restProps;
@@ -37,6 +38,7 @@ const UnwrappedList = (props, forwardedRef) => {
37
38
  $[6] = t1;
38
39
  $[7] = t2;
39
40
  $[8] = t3;
41
+ $[9] = t4;
40
42
  } else {
41
43
  className = $[1];
42
44
  restProps = $[2];
@@ -46,17 +48,19 @@ const UnwrappedList = (props, forwardedRef) => {
46
48
  t1 = $[6];
47
49
  t2 = $[7];
48
50
  t3 = $[8];
51
+ t4 = $[9];
49
52
  }
50
53
  const Component = t0 === void 0 ? "ul" : t0;
51
54
  const variant = t1 === void 0 ? "inset" : t1;
52
55
  const showDividers = t2 === void 0 ? false : t2;
53
56
  const disableFocusZone = t3 === void 0 ? false : t3;
54
- let t4;
55
- if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
56
- t4 = { heading: Heading };
57
- $[9] = t4;
58
- } else t4 = $[9];
59
- const [slots, childrenWithoutSlots] = useSlots(restProps.children, t4);
57
+ const disableItemGap = t4 === void 0 ? false : t4;
58
+ let t5;
59
+ if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
60
+ t5 = { heading: Heading };
61
+ $[10] = t5;
62
+ } else t5 = $[10];
63
+ const [slots, childrenWithoutSlots] = useSlots(restProps.children, t5);
60
64
  const headingId = useId$1();
61
65
  const { listRole: listRoleFromContainer, listLabelledBy, selectionVariant: containerSelectionVariant, enableFocusZone: enableFocusZoneFromContainer, container } = React.useContext(ActionListContainerContext);
62
66
  const ariaLabelledBy = slots.heading ? (_slots$heading$props$ = slots.heading.props.id) !== null && _slots$heading$props$ !== void 0 ? _slots$heading$props$ : headingId : listLabelledBy;
@@ -67,58 +71,58 @@ const UnwrappedList = (props, forwardedRef) => {
67
71
  const providedOrCreatedRef = useProvidedRefOrCreate(forwardedRef);
68
72
  const readRef = mergedRefEnabled ? listRef : providedOrCreatedRef;
69
73
  const appliedRef = mergedRefEnabled ? mergedRef : providedOrCreatedRef;
70
- const itemGapEnabled = useFeatureFlag("primer_react_action_list_item_gap") && container === "NavList";
74
+ const itemGapEnabled = useFeatureFlag("primer_react_action_list_item_gap") && !disableItemGap && container === "NavList";
71
75
  let enableFocusZone = false;
72
76
  if (enableFocusZoneFromContainer !== void 0) enableFocusZone = enableFocusZoneFromContainer;
73
77
  else if (listRole && !disableFocusZone) {
74
- let t5;
75
- if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
76
- t5 = [
78
+ let t6;
79
+ if ($[11] === Symbol.for("react.memo_cache_sentinel")) {
80
+ t6 = [
77
81
  "menu",
78
82
  "menubar",
79
83
  "listbox"
80
84
  ];
81
- $[10] = t5;
82
- } else t5 = $[10];
83
- enableFocusZone = t5.includes(listRole);
85
+ $[11] = t6;
86
+ } else t6 = $[11];
87
+ enableFocusZone = t6.includes(listRole);
84
88
  }
85
- const t5 = !enableFocusZone;
86
- const t6 = listRole === "menu" || container === "SelectPanel" || container === "FilteredActionList" ? "wrap" : void 0;
87
- let t7;
88
- if ($[11] !== readRef || $[12] !== t5 || $[13] !== t6) {
89
- t7 = {
90
- disabled: t5,
89
+ const t6 = !enableFocusZone;
90
+ const t7 = listRole === "menu" || container === "SelectPanel" || container === "FilteredActionList" ? "wrap" : void 0;
91
+ let t8;
92
+ if ($[12] !== readRef || $[13] !== t6 || $[14] !== t7) {
93
+ t8 = {
94
+ disabled: t6,
91
95
  containerRef: readRef,
92
96
  bindKeys: FocusKeys.ArrowVertical | FocusKeys.HomeAndEnd | FocusKeys.PageUpDown,
93
- focusOutBehavior: t6
97
+ focusOutBehavior: t7
94
98
  };
95
- $[11] = readRef;
96
- $[12] = t5;
99
+ $[12] = readRef;
97
100
  $[13] = t6;
98
101
  $[14] = t7;
99
- } else t7 = $[14];
100
- useFocusZone(t7);
101
- const t8 = selectionVariant || containerSelectionVariant;
102
- let t9;
103
- if ($[15] !== headingId || $[16] !== listRole || $[17] !== showDividers || $[18] !== t8 || $[19] !== variant) {
104
- t9 = {
102
+ $[15] = t8;
103
+ } else t8 = $[15];
104
+ useFocusZone(t8);
105
+ const t9 = selectionVariant || containerSelectionVariant;
106
+ let t10;
107
+ if ($[16] !== headingId || $[17] !== listRole || $[18] !== showDividers || $[19] !== t9 || $[20] !== variant) {
108
+ t10 = {
105
109
  variant,
106
- selectionVariant: t8,
110
+ selectionVariant: t9,
107
111
  showDividers,
108
112
  role: listRole,
109
113
  headingId
110
114
  };
111
- $[15] = headingId;
112
- $[16] = listRole;
113
- $[17] = showDividers;
114
- $[18] = t8;
115
- $[19] = variant;
116
- $[20] = t9;
117
- } else t9 = $[20];
118
- const listContextValue = t9;
119
- let t10;
120
- if ($[21] !== readRef.current) {
121
- t10 = () => {
115
+ $[16] = headingId;
116
+ $[17] = listRole;
117
+ $[18] = showDividers;
118
+ $[19] = t9;
119
+ $[20] = variant;
120
+ $[21] = t10;
121
+ } else t10 = $[21];
122
+ const listContextValue = t10;
123
+ let t11;
124
+ if ($[22] !== readRef.current) {
125
+ t11 = () => {
122
126
  const list = readRef.current;
123
127
  if (!list) return;
124
128
  const hasMixed = list.querySelector("[data-has-description=\"true\"]") !== null && list.querySelector("[data-has-description=\"false\"]") !== null;
@@ -126,56 +130,56 @@ const UnwrappedList = (props, forwardedRef) => {
126
130
  if (hasMixed && current !== "true") list.setAttribute("data-mixed-descriptions", "true");
127
131
  else if (!hasMixed && current !== null) list.removeAttribute("data-mixed-descriptions");
128
132
  };
129
- $[21] = readRef.current;
130
- $[22] = t10;
131
- } else t10 = $[22];
132
- useIsomorphicLayoutEffect(t10);
133
- const t11 = slots.heading;
134
- let t12;
135
- if ($[23] !== className) {
136
- t12 = clsx(ActionList_module_css_default.ActionList, className);
137
- $[23] = className;
138
- $[24] = t12;
139
- } else t12 = $[24];
140
- const t13 = itemGapEnabled ? "" : void 0;
141
- let t14;
142
- if ($[25] !== Component || $[26] !== appliedRef || $[27] !== ariaLabelledBy || $[28] !== childrenWithoutSlots || $[29] !== listRole || $[30] !== restProps || $[31] !== showDividers || $[32] !== t12 || $[33] !== t13 || $[34] !== variant) {
143
- t14 = /*#__PURE__*/ jsx(Component, {
144
- className: t12,
133
+ $[22] = readRef.current;
134
+ $[23] = t11;
135
+ } else t11 = $[23];
136
+ useIsomorphicLayoutEffect(t11);
137
+ const t12 = slots.heading;
138
+ let t13;
139
+ if ($[24] !== className) {
140
+ t13 = clsx(ActionList_module_css_default.ActionList, className);
141
+ $[24] = className;
142
+ $[25] = t13;
143
+ } else t13 = $[25];
144
+ const t14 = itemGapEnabled ? "" : void 0;
145
+ let t15;
146
+ if ($[26] !== Component || $[27] !== appliedRef || $[28] !== ariaLabelledBy || $[29] !== childrenWithoutSlots || $[30] !== listRole || $[31] !== restProps || $[32] !== showDividers || $[33] !== t13 || $[34] !== t14 || $[35] !== variant) {
147
+ t15 = /*#__PURE__*/ jsx(Component, {
148
+ className: t13,
145
149
  role: listRole,
146
150
  "aria-labelledby": ariaLabelledBy,
147
151
  ref: appliedRef,
148
152
  "data-component": "ActionList",
149
153
  "data-dividers": showDividers,
150
154
  "data-variant": variant,
151
- "data-item-gap": t13,
155
+ "data-item-gap": t14,
152
156
  ...restProps,
153
157
  children: childrenWithoutSlots
154
158
  });
155
- $[25] = Component;
156
- $[26] = appliedRef;
157
- $[27] = ariaLabelledBy;
158
- $[28] = childrenWithoutSlots;
159
- $[29] = listRole;
160
- $[30] = restProps;
161
- $[31] = showDividers;
162
- $[32] = t12;
159
+ $[26] = Component;
160
+ $[27] = appliedRef;
161
+ $[28] = ariaLabelledBy;
162
+ $[29] = childrenWithoutSlots;
163
+ $[30] = listRole;
164
+ $[31] = restProps;
165
+ $[32] = showDividers;
163
166
  $[33] = t13;
164
- $[34] = variant;
165
- $[35] = t14;
166
- } else t14 = $[35];
167
- let t15;
168
- if ($[36] !== listContextValue || $[37] !== slots.heading || $[38] !== t14) {
169
- t15 = /*#__PURE__*/ jsxs(ListContext.Provider, {
167
+ $[34] = t14;
168
+ $[35] = variant;
169
+ $[36] = t15;
170
+ } else t15 = $[36];
171
+ let t16;
172
+ if ($[37] !== listContextValue || $[38] !== slots.heading || $[39] !== t15) {
173
+ t16 = /*#__PURE__*/ jsxs(ListContext.Provider, {
170
174
  value: listContextValue,
171
- children: [t11, t14]
175
+ children: [t12, t15]
172
176
  });
173
- $[36] = listContextValue;
174
- $[37] = slots.heading;
175
- $[38] = t14;
177
+ $[37] = listContextValue;
178
+ $[38] = slots.heading;
176
179
  $[39] = t15;
177
- } else t15 = $[39];
178
- return t15;
180
+ $[40] = t16;
181
+ } else t16 = $[40];
182
+ return t16;
179
183
  };
180
184
  const List = fixedForwardRef(UnwrappedList);
181
185
  Object.assign(List, { displayName: "ActionList" });
@@ -22,6 +22,7 @@ declare const ActionList: (<As extends React.ElementType = "ul">(props: Distribu
22
22
  role?: AriaRole;
23
23
  disableFocusZone?: boolean;
24
24
  className?: string;
25
+ disableItemGap?: boolean;
25
26
  } & {
26
27
  children?: import("react").ReactNode | undefined;
27
28
  }, "as"> & {
@@ -100,6 +100,10 @@ type ActionListProps<As extends React.ElementType = 'ul'> = PolymorphicProps<As,
100
100
  */
101
101
  disableFocusZone?: boolean;
102
102
  className?: string;
103
+ /**
104
+ * Disable the gap between items when this `ActionList` is rendered in a `NavList`.
105
+ */
106
+ disableItemGap?: boolean;
103
107
  }>>;
104
108
  //#endregion
105
109
  export { ActionListItemProps, ActionListProps };
@@ -1,11 +1,11 @@
1
- import { ObjectPaths } from "./utils.js";
2
- import { UniqueRow } from "./row.js";
1
+ import { IsAny, ObjectPaths } from "./utils.js";
2
+ import { DataTableData, DataTableRowGroup, UniqueRow } from "./row.js";
3
3
  import { SortDirection } from "./sorting.js";
4
4
  import { Column } from "./column.js";
5
- import React from "react";
5
+ import { ReactElement } from "react";
6
6
 
7
7
  //#region src/DataTable/DataTable.d.ts
8
- type DataTableProps<Data extends UniqueRow> = {
8
+ type DataTableBaseProps<Data extends UniqueRow> = {
9
9
  /**
10
10
  * Provide an id to an element which uniquely describes this table
11
11
  */
@@ -19,10 +19,6 @@ type DataTableProps<Data extends UniqueRow> = {
19
19
  * a cell
20
20
  */
21
21
  cellPadding?: 'condensed' | 'normal' | 'spacious';
22
- /**
23
- * Provide a collection of the rows which will be rendered inside of the table
24
- */
25
- data: Array<Data>;
26
22
  /**
27
23
  * Provide the columns for the table and the fields in `data` to which they
28
24
  * correspond
@@ -60,17 +56,21 @@ type DataTableProps<Data extends UniqueRow> = {
60
56
  */
61
57
  onToggleSort?: (columnId: ObjectPaths<Data> | string | number, direction: Exclude<SortDirection, 'NONE'>) => void;
62
58
  };
63
- declare function DataTable<Data extends UniqueRow>({
64
- 'aria-labelledby': labelledby,
65
- 'aria-describedby': describedby,
66
- cellPadding,
67
- columns,
68
- data,
69
- initialSortColumn,
70
- initialSortDirection,
71
- externalSorting,
72
- getRowId,
73
- onToggleSort
74
- }: DataTableProps<Data>): React.JSX.Element;
59
+ type DataTableProps<Data extends UniqueRow> = DataTableBaseProps<Data> & {
60
+ /**
61
+ * Provide a collection of rows, row groups, or a mixture of both.
62
+ */
63
+ data: DataTableData<Data>;
64
+ };
65
+ type DataFromItem<Item> = Item extends DataTableRowGroup<infer Data> ? Data : Item extends UniqueRow ? Item : never;
66
+ type DataFromInput<Input extends DataTableData<UniqueRow>> = IsAny<Input> extends true ? UniqueRow : DataFromItem<Input[number]>;
67
+ type InferredDataTableProps<Input extends DataTableData<UniqueRow>> = DataTableBaseProps<DataFromInput<Input>> & {
68
+ data: Input & DataTableData<DataFromInput<Input>>;
69
+ };
70
+ interface DataTableComponent {
71
+ <Data extends UniqueRow>(props: DataTableProps<Data>): ReactElement;
72
+ <Input extends DataTableData<UniqueRow>>(props: InferredDataTableProps<Input>): ReactElement;
73
+ }
74
+ declare const DataTable: DataTableComponent;
75
75
  //#endregion
76
76
  export { DataTable, DataTableProps };
@@ -1,13 +1,14 @@
1
1
  import { c } from "../utils/react-compiler-runtime.js";
2
2
  import { useTable } from "./useTable.js";
3
3
  import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, TableSortHeader } from "./Table.js";
4
+ import { TableGroup } from "./TableGroup.js";
4
5
  import { jsx, jsxs } from "react/jsx-runtime";
5
6
  //#region src/DataTable/DataTable.tsx
6
7
  function defaultGetRowId(row) {
7
8
  return row.id;
8
9
  }
9
- function DataTable(t0) {
10
- const $ = c(27);
10
+ function DataTableImplementation(t0) {
11
+ const $ = c(28);
11
12
  const { "aria-labelledby": labelledby, "aria-describedby": describedby, cellPadding, columns, data, initialSortColumn, initialSortDirection, externalSorting, getRowId: t1, onToggleSort } = t0;
12
13
  const getRowId = t1 === void 0 ? defaultGetRowId : t1;
13
14
  let t2;
@@ -28,13 +29,15 @@ function DataTable(t0) {
28
29
  $[5] = initialSortDirection;
29
30
  $[6] = t2;
30
31
  } else t2 = $[6];
31
- const { headers, rows, actions, gridTemplateColumns } = useTable(t2);
32
+ const { headers, bodies, actions, gridTemplateColumns } = useTable(t2);
33
+ const renderRow = _temp;
32
34
  let t3;
33
35
  if ($[7] !== actions || $[8] !== headers || $[9] !== onToggleSort) {
34
36
  let t4;
35
37
  if ($[11] !== actions || $[12] !== onToggleSort) {
36
38
  t4 = (header) => {
37
39
  if (header.isSortable()) return /*#__PURE__*/ jsx(TableSortHeader, {
40
+ id: header.domId,
38
41
  align: header.column.align,
39
42
  direction: header.getSortDirection(),
40
43
  onToggleSort: () => {
@@ -45,6 +48,7 @@ function DataTable(t0) {
45
48
  children: typeof header.column.header === "string" ? header.column.header : header.column.header()
46
49
  }, header.id);
47
50
  return /*#__PURE__*/ jsx(TableHeader, {
51
+ id: header.domId,
48
52
  align: header.column.align,
49
53
  children: typeof header.column.header === "string" ? header.column.header : header.column.header()
50
54
  }, header.id);
@@ -66,43 +70,54 @@ function DataTable(t0) {
66
70
  $[15] = t4;
67
71
  } else t4 = $[15];
68
72
  let t5;
69
- if ($[16] !== rows) {
70
- t5 = rows.map(_temp);
71
- $[16] = rows;
72
- $[17] = t5;
73
- } else t5 = $[17];
74
- let t6;
75
- if ($[18] !== t5) {
76
- t6 = /*#__PURE__*/ jsx(TableBody, { children: t5 });
73
+ if ($[16] !== bodies || $[17] !== headers.length) {
74
+ let t6;
75
+ if ($[19] !== headers.length) {
76
+ t6 = (body) => body.type === "row-group" ? /*#__PURE__*/ jsx(TableGroup, {
77
+ id: body.id,
78
+ label: body.label,
79
+ rowCount: body.rows.length,
80
+ colSpan: headers.length,
81
+ "aria-label": body["aria-label"],
82
+ children: body.rows.map(renderRow)
83
+ }, body.key) : /*#__PURE__*/ jsx(TableBody, { children: body.rows.map(renderRow) }, body.key);
84
+ $[19] = headers.length;
85
+ $[20] = t6;
86
+ } else t6 = $[20];
87
+ t5 = bodies.map(t6);
88
+ $[16] = bodies;
89
+ $[17] = headers.length;
77
90
  $[18] = t5;
78
- $[19] = t6;
79
- } else t6 = $[19];
80
- let t7;
81
- if ($[20] !== cellPadding || $[21] !== describedby || $[22] !== gridTemplateColumns || $[23] !== labelledby || $[24] !== t4 || $[25] !== t6) {
82
- t7 = /*#__PURE__*/ jsxs(Table, {
91
+ } else t5 = $[18];
92
+ let t6;
93
+ if ($[21] !== cellPadding || $[22] !== describedby || $[23] !== gridTemplateColumns || $[24] !== labelledby || $[25] !== t4 || $[26] !== t5) {
94
+ t6 = /*#__PURE__*/ jsxs(Table, {
83
95
  "aria-labelledby": labelledby,
84
96
  "aria-describedby": describedby,
85
97
  cellPadding,
86
98
  gridTemplateColumns,
87
- children: [t4, t6]
99
+ children: [t4, t5]
88
100
  });
89
- $[20] = cellPadding;
90
- $[21] = describedby;
91
- $[22] = gridTemplateColumns;
92
- $[23] = labelledby;
93
- $[24] = t4;
94
- $[25] = t6;
95
- $[26] = t7;
96
- } else t7 = $[26];
97
- return t7;
101
+ $[21] = cellPadding;
102
+ $[22] = describedby;
103
+ $[23] = gridTemplateColumns;
104
+ $[24] = labelledby;
105
+ $[25] = t4;
106
+ $[26] = t5;
107
+ $[27] = t6;
108
+ } else t6 = $[27];
109
+ return t6;
98
110
  }
99
111
  function _temp(row) {
100
112
  return /*#__PURE__*/ jsx(TableRow, { children: row.getCells().map((cell) => /*#__PURE__*/ jsx(TableCell, {
113
+ id: cell.domId,
101
114
  scope: cell.rowHeader ? "row" : void 0,
102
115
  align: cell.column.align,
116
+ headers: cell.headers,
103
117
  children: cell.column.renderCell ? cell.column.renderCell(row.getValue()) : cell.getValue()
104
118
  }, cell.id)) }, row.id);
105
119
  }
106
120
  _temp.displayName = "_temp";
121
+ const DataTable = DataTableImplementation;
107
122
  //#endregion
108
123
  export { DataTable };