@primer/react 38.6.3-rc.f8f5fddc3 → 38.7.0-rc.92435c0d2

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.

Potentially problematic release.


This version of @primer/react might be problematic. Click here for more details.

Files changed (73) hide show
  1. package/CHANGELOG.md +46 -1
  2. package/dist/ActionBar/ActionBar.d.ts +8 -0
  3. package/dist/ActionBar/ActionBar.d.ts.map +1 -1
  4. package/dist/ActionBar/ActionBar.js +83 -53
  5. package/dist/ActionBar/index.d.ts +1 -0
  6. package/dist/ActionBar/index.d.ts.map +1 -1
  7. package/dist/Autocomplete/Autocomplete.d.ts +0 -3
  8. package/dist/Autocomplete/Autocomplete.d.ts.map +1 -1
  9. package/dist/Autocomplete/Autocomplete.js +69 -23
  10. package/dist/Autocomplete/AutocompleteContext.d.ts +23 -3
  11. package/dist/Autocomplete/AutocompleteContext.d.ts.map +1 -1
  12. package/dist/Autocomplete/AutocompleteContext.js +20 -1
  13. package/dist/Autocomplete/AutocompleteInput.d.ts.map +1 -1
  14. package/dist/Autocomplete/AutocompleteInput.js +8 -5
  15. package/dist/Autocomplete/AutocompleteMenu.d.ts.map +1 -1
  16. package/dist/Autocomplete/AutocompleteMenu.js +123 -121
  17. package/dist/{BaseStyles-79fd37c4.css → BaseStyles-7e59cc50.css} +2 -2
  18. package/dist/BaseStyles-7e59cc50.css.map +1 -0
  19. package/dist/BaseStyles.module.css.js +1 -1
  20. package/dist/Dialog/{Dialog-1a61e61a.css → Dialog-92b5e3b7.css} +2 -2
  21. package/dist/Dialog/Dialog-92b5e3b7.css.map +1 -0
  22. package/dist/Dialog/Dialog.d.ts.map +1 -1
  23. package/dist/Dialog/Dialog.js +21 -5
  24. package/dist/Dialog/Dialog.module.css.js +1 -1
  25. package/dist/FeatureFlags/DefaultFeatureFlags.d.ts.map +1 -1
  26. package/dist/FeatureFlags/DefaultFeatureFlags.js +1 -0
  27. package/dist/FeatureFlags/FeatureFlags.d.ts +6 -0
  28. package/dist/FeatureFlags/FeatureFlags.d.ts.map +1 -1
  29. package/dist/FeatureFlags/FeatureFlags.js +41 -32
  30. package/dist/FilteredActionList/FilteredActionList.d.ts +6 -1
  31. package/dist/FilteredActionList/FilteredActionList.d.ts.map +1 -1
  32. package/dist/FilteredActionList/FilteredActionList.js +4 -2
  33. package/dist/PageLayout/{PageLayout-c092f3db.css → PageLayout-51007c87.css} +2 -2
  34. package/dist/PageLayout/PageLayout-51007c87.css.map +1 -0
  35. package/dist/PageLayout/PageLayout.d.ts.map +1 -1
  36. package/dist/PageLayout/PageLayout.js +399 -313
  37. package/dist/PageLayout/PageLayout.module.css.js +1 -1
  38. package/dist/PageLayout/paneUtils.d.ts +11 -0
  39. package/dist/PageLayout/paneUtils.d.ts.map +1 -0
  40. package/dist/PageLayout/paneUtils.js +34 -0
  41. package/dist/PageLayout/usePaneWidth.d.ts +2 -1
  42. package/dist/PageLayout/usePaneWidth.d.ts.map +1 -1
  43. package/dist/PageLayout/usePaneWidth.js +56 -44
  44. package/dist/SelectPanel/SelectPanel.d.ts +6 -1
  45. package/dist/SelectPanel/SelectPanel.d.ts.map +1 -1
  46. package/dist/SelectPanel/SelectPanel.js +3 -1
  47. package/dist/TextInput/TextInput-dff8f842.css +2 -0
  48. package/dist/TextInput/TextInput-dff8f842.css.map +1 -0
  49. package/dist/TextInput/TextInput.d.ts +5 -0
  50. package/dist/TextInput/TextInput.d.ts.map +1 -1
  51. package/dist/TextInput/TextInput.js +125 -51
  52. package/dist/TextInput/TextInput.module.css.js +5 -0
  53. package/dist/Textarea/{TextArea-54099020.css → TextArea-53e27580.css} +2 -2
  54. package/dist/Textarea/TextArea-53e27580.css.map +1 -0
  55. package/dist/Textarea/TextArea.module.css.js +2 -2
  56. package/dist/Textarea/Textarea.d.ts +10 -0
  57. package/dist/Textarea/Textarea.d.ts.map +1 -1
  58. package/dist/Textarea/Textarea.js +215 -69
  59. package/dist/hooks/useFocusZone.d.ts +4 -0
  60. package/dist/hooks/useFocusZone.d.ts.map +1 -1
  61. package/dist/internal/utils/hasInteractiveNodes.d.ts.map +1 -1
  62. package/dist/internal/utils/hasInteractiveNodes.js +22 -16
  63. package/dist/utils/__tests__/character-counter.test.d.ts +2 -0
  64. package/dist/utils/__tests__/character-counter.test.d.ts.map +1 -0
  65. package/dist/utils/character-counter.d.ts +27 -0
  66. package/dist/utils/character-counter.d.ts.map +1 -0
  67. package/dist/utils/character-counter.js +65 -0
  68. package/generated/components.json +16 -0
  69. package/package.json +9 -9
  70. package/dist/BaseStyles-79fd37c4.css.map +0 -1
  71. package/dist/Dialog/Dialog-1a61e61a.css.map +0 -1
  72. package/dist/PageLayout/PageLayout-c092f3db.css.map +0 -1
  73. package/dist/Textarea/TextArea-54099020.css.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Textarea.d.ts","sourceRoot":"","sources":["../../src/Textarea/Textarea.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,sBAAsB,EAAe,MAAM,OAAO,CAAA;AAC/D,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,qCAAqC,CAAA;AAE7E,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,gBAAgB,CAAA;AAElD,eAAO,MAAM,qBAAqB,IAAI,CAAA;AACtC,eAAO,MAAM,qBAAqB,KAAK,CAAA;AACvC,eAAO,MAAM,uBAAuB,SAAS,CAAA;AAE7C,MAAM,MAAM,aAAa,GAAG;IAC1B;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;OAEG;IACH,gBAAgB,CAAC,EAAE,oBAAoB,CAAA;IACvC;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,YAAY,GAAG,UAAU,CAAA;IACpD;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;OAEG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;CAC5B,GAAG,sBAAsB,CAAC,mBAAmB,CAAC,CAAA;AAE/C;;;GAGG;AACH,QAAA,MAAM,QAAQ;IA1CZ;;OAEG;eACQ,OAAO;IAClB;;OAEG;uBACgB,oBAAoB;IACvC;;OAEG;YACK,OAAO;IACf;;OAEG;aACM,MAAM,GAAG,MAAM,GAAG,YAAY,GAAG,UAAU;IACpD;;OAEG;eACQ,OAAO;IAClB;;OAEG;gBACS,MAAM;IAClB;;OAEG;gBACS,MAAM;IAClB;;OAEG;gBACS,MAAM;IAClB;;OAEG;YACK,KAAK,CAAC,aAAa;2FAwD5B,CAAA;wBAK0B,cAAc,CAAC,OAAO,QAAQ,CAAC;AAA1D,wBAA0D"}
1
+ {"version":3,"file":"Textarea.d.ts","sourceRoot":"","sources":["../../src/Textarea/Textarea.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,sBAAsB,EAAe,MAAM,OAAO,CAAA;AAC/D,OAAO,KAA8C,MAAM,OAAO,CAAA;AAElE,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,qCAAqC,CAAA;AAE7E,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,gBAAgB,CAAA;AAOlD,eAAO,MAAM,qBAAqB,IAAI,CAAA;AACtC,eAAO,MAAM,qBAAqB,KAAK,CAAA;AACvC,eAAO,MAAM,uBAAuB,SAAS,CAAA;AAE7C,MAAM,MAAM,aAAa,GAAG;IAC1B;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;OAEG;IACH,gBAAgB,CAAC,EAAE,oBAAoB,CAAA;IACvC;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,YAAY,GAAG,UAAU,CAAA;IACpD;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;OAEG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;IAC3B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,GAAG,sBAAsB,CAAC,mBAAmB,CAAC,CAAA;AAE/C;;;GAGG;AACH,QAAA,MAAM,QAAQ;IA/CZ;;OAEG;eACQ,OAAO;IAClB;;OAEG;uBACgB,oBAAoB;IACvC;;OAEG;YACK,OAAO;IACf;;OAEG;aACM,MAAM,GAAG,MAAM,GAAG,YAAY,GAAG,UAAU;IACpD;;OAEG;eACQ,OAAO;IAClB;;OAEG;gBACS,MAAM;IAClB;;OAEG;gBACS,MAAM;IAClB;;OAEG;gBACS,MAAM;IAClB;;OAEG;YACK,KAAK,CAAC,aAAa;IAC3B;;;OAGG;qBACc,MAAM;2FAyIxB,CAAA;wBAK0B,cAAc,CAAC,OAAO,QAAQ,CAAC;AAA1D,wBAA0D"}
@@ -1,8 +1,13 @@
1
1
  import { c } from 'react-compiler-runtime';
2
- import React from 'react';
2
+ import React, { useRef, useId, useEffect } from 'react';
3
3
  import { TextInputBaseWrapper } from '../internal/components/TextInputWrapper.js';
4
4
  import classes from './TextArea.module.css.js';
5
- import { jsx } from 'react/jsx-runtime';
5
+ import { AlertFillIcon } from '@primer/octicons-react';
6
+ import { CharacterCounter } from '../utils/character-counter.js';
7
+ import VisuallyHidden from '../_VisuallyHidden.js';
8
+ import { clsx } from 'clsx';
9
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
10
+ import Text from '../Text/Text.js';
6
11
 
7
12
  const DEFAULT_TEXTAREA_ROWS = 7;
8
13
  const DEFAULT_TEXTAREA_COLS = 30;
@@ -12,13 +17,16 @@ const DEFAULT_TEXTAREA_RESIZE = 'both';
12
17
  * This component accepts all native HTML <textarea> attributes as props.
13
18
  */
14
19
  const Textarea = /*#__PURE__*/React.forwardRef((t0, ref) => {
15
- const $ = c(37);
20
+ const $ = c(68);
16
21
  let block;
22
+ let characterLimit;
17
23
  let className;
18
24
  let contrast;
25
+ let defaultValue;
19
26
  let disabled;
20
27
  let maxHeight;
21
28
  let minHeight;
29
+ let onChange;
22
30
  let required;
23
31
  let rest;
24
32
  let style;
@@ -42,107 +50,245 @@ const Textarea = /*#__PURE__*/React.forwardRef((t0, ref) => {
42
50
  minHeight,
43
51
  maxHeight,
44
52
  style,
53
+ characterLimit,
54
+ onChange,
55
+ defaultValue,
45
56
  ...rest
46
57
  } = t0);
47
58
  $[0] = t0;
48
59
  $[1] = block;
49
- $[2] = className;
50
- $[3] = contrast;
51
- $[4] = disabled;
52
- $[5] = maxHeight;
53
- $[6] = minHeight;
54
- $[7] = required;
55
- $[8] = rest;
56
- $[9] = style;
57
- $[10] = t1;
58
- $[11] = t2;
59
- $[12] = t3;
60
- $[13] = validationStatus;
61
- $[14] = value;
60
+ $[2] = characterLimit;
61
+ $[3] = className;
62
+ $[4] = contrast;
63
+ $[5] = defaultValue;
64
+ $[6] = disabled;
65
+ $[7] = maxHeight;
66
+ $[8] = minHeight;
67
+ $[9] = onChange;
68
+ $[10] = required;
69
+ $[11] = rest;
70
+ $[12] = style;
71
+ $[13] = t1;
72
+ $[14] = t2;
73
+ $[15] = t3;
74
+ $[16] = validationStatus;
75
+ $[17] = value;
62
76
  } else {
63
77
  block = $[1];
64
- className = $[2];
65
- contrast = $[3];
66
- disabled = $[4];
67
- maxHeight = $[5];
68
- minHeight = $[6];
69
- required = $[7];
70
- rest = $[8];
71
- style = $[9];
72
- t1 = $[10];
73
- t2 = $[11];
74
- t3 = $[12];
75
- validationStatus = $[13];
76
- value = $[14];
78
+ characterLimit = $[2];
79
+ className = $[3];
80
+ contrast = $[4];
81
+ defaultValue = $[5];
82
+ disabled = $[6];
83
+ maxHeight = $[7];
84
+ minHeight = $[8];
85
+ onChange = $[9];
86
+ required = $[10];
87
+ rest = $[11];
88
+ style = $[12];
89
+ t1 = $[13];
90
+ t2 = $[14];
91
+ t3 = $[15];
92
+ validationStatus = $[16];
93
+ value = $[17];
77
94
  }
78
95
  const rows = t1 === undefined ? DEFAULT_TEXTAREA_ROWS : t1;
79
96
  const cols = t2 === undefined ? DEFAULT_TEXTAREA_COLS : t2;
80
97
  const resize = t3 === undefined ? DEFAULT_TEXTAREA_RESIZE : t3;
81
- const t4 = validationStatus === "error" ? "true" : "false";
98
+ const [characterCount, setCharacterCount] = React.useState("");
99
+ const [isOverLimit, setIsOverLimit] = React.useState(false);
100
+ const [screenReaderMessage, setScreenReaderMessage] = React.useState("");
101
+ const characterCounterRef = useRef(null);
102
+ const characterCountId = useId();
103
+ const characterCountStaticMessageId = useId();
104
+ let t4;
82
105
  let t5;
83
- if ($[15] !== maxHeight || $[16] !== minHeight || $[17] !== style) {
84
- t5 = {
106
+ if ($[18] !== characterLimit) {
107
+ t4 = () => {
108
+ if (characterLimit) {
109
+ characterCounterRef.current = new CharacterCounter({
110
+ onCountUpdate: (count, overLimit, message) => {
111
+ setCharacterCount(message);
112
+ setIsOverLimit(overLimit);
113
+ },
114
+ onScreenReaderAnnounce: message_0 => {
115
+ setScreenReaderMessage(message_0);
116
+ }
117
+ });
118
+ return () => {
119
+ var _characterCounterRef$;
120
+ (_characterCounterRef$ = characterCounterRef.current) === null || _characterCounterRef$ === void 0 ? void 0 : _characterCounterRef$.cleanup();
121
+ };
122
+ }
123
+ };
124
+ t5 = [characterLimit];
125
+ $[18] = characterLimit;
126
+ $[19] = t4;
127
+ $[20] = t5;
128
+ } else {
129
+ t4 = $[19];
130
+ t5 = $[20];
131
+ }
132
+ useEffect(t4, t5);
133
+ let t6;
134
+ let t7;
135
+ if ($[21] !== characterLimit || $[22] !== defaultValue || $[23] !== value) {
136
+ t6 = () => {
137
+ if (characterLimit && characterCounterRef.current) {
138
+ const currentValue = value !== undefined ? String(value) : defaultValue !== undefined ? String(defaultValue) : "";
139
+ characterCounterRef.current.updateCharacterCount(currentValue.length, characterLimit);
140
+ }
141
+ };
142
+ t7 = [value, defaultValue, characterLimit];
143
+ $[21] = characterLimit;
144
+ $[22] = defaultValue;
145
+ $[23] = value;
146
+ $[24] = t6;
147
+ $[25] = t7;
148
+ } else {
149
+ t6 = $[24];
150
+ t7 = $[25];
151
+ }
152
+ useEffect(t6, t7);
153
+ let t8;
154
+ if ($[26] !== characterLimit || $[27] !== onChange) {
155
+ t8 = e => {
156
+ var _onChange;
157
+ if (characterLimit && characterCounterRef.current) {
158
+ characterCounterRef.current.updateCharacterCount(e.target.value.length, characterLimit);
159
+ }
160
+ (_onChange = onChange) === null || _onChange === void 0 ? void 0 : _onChange(e);
161
+ };
162
+ $[26] = characterLimit;
163
+ $[27] = onChange;
164
+ $[28] = t8;
165
+ } else {
166
+ t8 = $[28];
167
+ }
168
+ const handleTextareaChange = t8;
169
+ const isValid = isOverLimit ? "error" : validationStatus;
170
+ const t9 = isValid === "error" ? "true" : "false";
171
+ let t10;
172
+ if ($[29] !== maxHeight || $[30] !== minHeight || $[31] !== style) {
173
+ t10 = {
85
174
  minHeight,
86
175
  maxHeight,
87
176
  ...style
88
177
  };
89
- $[15] = maxHeight;
90
- $[16] = minHeight;
91
- $[17] = style;
92
- $[18] = t5;
178
+ $[29] = maxHeight;
179
+ $[30] = minHeight;
180
+ $[31] = style;
181
+ $[32] = t10;
93
182
  } else {
94
- t5 = $[18];
183
+ t10 = $[32];
95
184
  }
96
- let t6;
97
- if ($[19] !== cols || $[20] !== disabled || $[21] !== ref || $[22] !== required || $[23] !== resize || $[24] !== rest || $[25] !== rows || $[26] !== t4 || $[27] !== t5 || $[28] !== value) {
98
- t6 = /*#__PURE__*/jsx("textarea", {
185
+ let t11;
186
+ if ($[33] !== characterCountStaticMessageId || $[34] !== characterLimit || $[35] !== rest) {
187
+ t11 = characterLimit ? [characterCountStaticMessageId, rest["aria-describedby"]].filter(Boolean).join(" ") || undefined : rest["aria-describedby"];
188
+ $[33] = characterCountStaticMessageId;
189
+ $[34] = characterLimit;
190
+ $[35] = rest;
191
+ $[36] = t11;
192
+ } else {
193
+ t11 = $[36];
194
+ }
195
+ let t12;
196
+ if ($[37] !== cols || $[38] !== defaultValue || $[39] !== disabled || $[40] !== handleTextareaChange || $[41] !== ref || $[42] !== required || $[43] !== resize || $[44] !== rest || $[45] !== rows || $[46] !== t10 || $[47] !== t11 || $[48] !== t9 || $[49] !== value) {
197
+ t12 = /*#__PURE__*/jsx("textarea", {
99
198
  value: value,
199
+ defaultValue: defaultValue,
100
200
  "data-resize": resize,
101
201
  "aria-required": required,
102
- "aria-invalid": t4,
202
+ "aria-invalid": t9,
103
203
  ref: ref,
104
204
  disabled: disabled,
105
205
  rows: rows,
106
206
  cols: cols,
107
207
  className: classes.TextArea,
108
- style: t5,
109
- ...rest
208
+ onChange: handleTextareaChange,
209
+ style: t10,
210
+ ...rest,
211
+ "aria-describedby": t11
110
212
  });
111
- $[19] = cols;
112
- $[20] = disabled;
113
- $[21] = ref;
114
- $[22] = required;
115
- $[23] = resize;
116
- $[24] = rest;
117
- $[25] = rows;
118
- $[26] = t4;
119
- $[27] = t5;
120
- $[28] = value;
121
- $[29] = t6;
213
+ $[37] = cols;
214
+ $[38] = defaultValue;
215
+ $[39] = disabled;
216
+ $[40] = handleTextareaChange;
217
+ $[41] = ref;
218
+ $[42] = required;
219
+ $[43] = resize;
220
+ $[44] = rest;
221
+ $[45] = rows;
222
+ $[46] = t10;
223
+ $[47] = t11;
224
+ $[48] = t9;
225
+ $[49] = value;
226
+ $[50] = t12;
122
227
  } else {
123
- t6 = $[29];
228
+ t12 = $[50];
124
229
  }
125
- let t7;
126
- if ($[30] !== block || $[31] !== className || $[32] !== contrast || $[33] !== disabled || $[34] !== t6 || $[35] !== validationStatus) {
127
- t7 = /*#__PURE__*/jsx(TextInputBaseWrapper, {
128
- validationStatus: validationStatus,
230
+ let t13;
231
+ if ($[51] !== block || $[52] !== className || $[53] !== contrast || $[54] !== disabled || $[55] !== isValid || $[56] !== t12) {
232
+ t13 = /*#__PURE__*/jsx(TextInputBaseWrapper, {
233
+ validationStatus: isValid,
129
234
  disabled: disabled,
130
235
  block: block,
131
236
  contrast: contrast,
132
237
  className: className,
133
- children: t6
238
+ children: t12
239
+ });
240
+ $[51] = block;
241
+ $[52] = className;
242
+ $[53] = contrast;
243
+ $[54] = disabled;
244
+ $[55] = isValid;
245
+ $[56] = t12;
246
+ $[57] = t13;
247
+ } else {
248
+ t13 = $[57];
249
+ }
250
+ let t14;
251
+ if ($[58] !== characterCount || $[59] !== characterCountId || $[60] !== characterCountStaticMessageId || $[61] !== characterLimit || $[62] !== isOverLimit || $[63] !== screenReaderMessage) {
252
+ t14 = characterLimit && /*#__PURE__*/jsxs(Fragment, {
253
+ children: [/*#__PURE__*/jsx(VisuallyHidden, {
254
+ "aria-live": "polite",
255
+ role: "status",
256
+ children: screenReaderMessage
257
+ }), /*#__PURE__*/jsxs(VisuallyHidden, {
258
+ id: characterCountStaticMessageId,
259
+ children: ["You can enter up to ", characterLimit, " ", characterLimit === 1 ? "character" : "characters"]
260
+ }), /*#__PURE__*/jsxs(Text, {
261
+ "aria-hidden": "true",
262
+ id: characterCountId,
263
+ size: "small",
264
+ className: clsx(classes.CharacterCounter, isOverLimit && classes["CharacterCounter--error"]),
265
+ children: [isOverLimit && /*#__PURE__*/jsx(AlertFillIcon, {
266
+ size: 16
267
+ }), characterCount]
268
+ })]
269
+ });
270
+ $[58] = characterCount;
271
+ $[59] = characterCountId;
272
+ $[60] = characterCountStaticMessageId;
273
+ $[61] = characterLimit;
274
+ $[62] = isOverLimit;
275
+ $[63] = screenReaderMessage;
276
+ $[64] = t14;
277
+ } else {
278
+ t14 = $[64];
279
+ }
280
+ let t15;
281
+ if ($[65] !== t13 || $[66] !== t14) {
282
+ t15 = /*#__PURE__*/jsxs(Fragment, {
283
+ children: [t13, t14]
134
284
  });
135
- $[30] = block;
136
- $[31] = className;
137
- $[32] = contrast;
138
- $[33] = disabled;
139
- $[34] = t6;
140
- $[35] = validationStatus;
141
- $[36] = t7;
285
+ $[65] = t13;
286
+ $[66] = t14;
287
+ $[67] = t15;
142
288
  } else {
143
- t7 = $[36];
289
+ t15 = $[67];
144
290
  }
145
- return t7;
291
+ return t15;
146
292
  });
147
293
  Textarea.displayName = 'Textarea';
148
294
  Textarea.__SLOT__ = Symbol('Textarea');
@@ -18,6 +18,10 @@ export interface FocusZoneHookSettings extends Omit<FocusZoneSettings, 'activeDe
18
18
  * any time.
19
19
  */
20
20
  disabled?: boolean;
21
+ /**
22
+ * Set to true to allow focus to move to elements that are dynamically prepended to the container.
23
+ */
24
+ focusPrependedElements?: boolean;
21
25
  }
22
26
  export declare function useFocusZone(settings?: FocusZoneHookSettings, dependencies?: React.DependencyList): {
23
27
  containerRef: React.RefObject<HTMLElement | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"useFocusZone.d.ts","sourceRoot":"","sources":["../../src/hooks/useFocusZone.ts"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAA;AAEtC,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,mBAAmB,CAAA;AAExD,OAAO,EAAC,SAAS,EAAC,MAAM,mBAAmB,CAAA;AAC3C,YAAY,EAAC,SAAS,EAAC,MAAM,mBAAmB,CAAA;AAEhD,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,yBAAyB,CAAC;IAC/F;;;OAGG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAA;IAElD;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAA;IAErE;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,wBAAgB,YAAY,CAC1B,QAAQ,GAAE,qBAA0B,EACpC,YAAY,GAAE,KAAK,CAAC,cAAmB,GACtC;IACD,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAA;IACjD,0BAA0B,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAA;CAChE,CAoCA"}
1
+ {"version":3,"file":"useFocusZone.d.ts","sourceRoot":"","sources":["../../src/hooks/useFocusZone.ts"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAA;AAEtC,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,mBAAmB,CAAA;AAExD,OAAO,EAAC,SAAS,EAAC,MAAM,mBAAmB,CAAA;AAC3C,YAAY,EAAC,SAAS,EAAC,MAAM,mBAAmB,CAAA;AAEhD,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,yBAAyB,CAAC;IAC/F;;;OAGG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAA;IAElD;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAA;IAErE;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAElB;;OAEG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAA;CACjC;AAED,wBAAgB,YAAY,CAC1B,QAAQ,GAAE,qBAA0B,EACpC,YAAY,GAAE,KAAK,CAAC,cAAmB,GACtC;IACD,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAA;IACjD,0BAA0B,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAA;CAChE,CAoCA"}
@@ -1 +1 @@
1
- {"version":3,"file":"hasInteractiveNodes.d.ts","sourceRoot":"","sources":["../../../src/internal/utils/hasInteractiveNodes.ts"],"names":[],"mappings":"AAwBA;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,EAAE,WAAW,CAAC,EAAE,WAAW,EAAE,WAUxF"}
1
+ {"version":3,"file":"hasInteractiveNodes.d.ts","sourceRoot":"","sources":["../../../src/internal/utils/hasInteractiveNodes.ts"],"names":[],"mappings":"AA2BA;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,EAAE,WAAW,CAAC,EAAE,WAAW,EAAE,WAkBxF"}
@@ -7,6 +7,9 @@ const nonValidSelectors = {
7
7
  const interactiveElementsSelectors = [`a[href]`, `button`, 'summary', 'select', 'input:not([type=hidden])', 'textarea', '[tabindex="0"]', `audio[controls]`, `video[controls]`, `[contenteditable]`];
8
8
  const interactiveElements = interactiveElementsSelectors.map(selector => `${selector}:not(${Object.values(nonValidSelectors).join('):not(')})`);
9
9
 
10
+ // Combined selector for fast querySelector check
11
+ const interactiveSelector = interactiveElements.join(', ');
12
+
10
13
  /**
11
14
  * Finds interactive nodes within the passed node.
12
15
  * If the node itself is interactive, or children within are, it will return true.
@@ -23,26 +26,29 @@ function hasInteractiveNodes(node, ignoreNodes) {
23
26
  // If one does exist, we can abort early.
24
27
 
25
28
  const nodesToIgnore = [node];
26
- const interactiveNodes = findInteractiveChildNodes(node, nodesToIgnore);
27
- return Boolean(interactiveNodes);
29
+
30
+ // Performance optimization: Use querySelectorAll with combined selector first
31
+ // This avoids recursive getComputedStyle calls for each node
32
+ const candidates = node.querySelectorAll(interactiveSelector);
33
+ for (const candidate of candidates) {
34
+ if (!nodesToIgnore.includes(candidate) && !isNonValidInteractiveNode(candidate)) {
35
+ return true;
36
+ }
37
+ }
38
+ return false;
28
39
  }
40
+
41
+ // Note: Only call getComputedStyle when CSS-based checks are insufficient
29
42
  function isNonValidInteractiveNode(node) {
30
- const nodeStyle = getComputedStyle(node);
43
+ // Fast path: Check attribute-based states first (no style recalc needed)
31
44
  const isNonInteractive = node.matches('[disabled], [hidden], [inert]');
45
+ if (isNonInteractive) return true;
46
+
47
+ // Only call getComputedStyle if attribute checks passed
48
+ // This is necessary for display:none and visibility:hidden which aren't detectable via attributes
49
+ const nodeStyle = getComputedStyle(node);
32
50
  const isHiddenVisually = nodeStyle.display === 'none' || nodeStyle.visibility === 'hidden';
33
- return isNonInteractive || isHiddenVisually;
34
- }
35
- function findInteractiveChildNodes(node, ignoreNodes) {
36
- if (!node) return;
37
- const ignoreSelector = ignoreNodes.find(elem => elem === node);
38
- const isNotValidNode = isNonValidInteractiveNode(node);
39
- if (node.matches(interactiveElements.join(', ')) && !ignoreSelector && !isNotValidNode) {
40
- return node;
41
- }
42
- for (const child of node.children) {
43
- const interactiveNode = findInteractiveChildNodes(child, ignoreNodes);
44
- if (interactiveNode) return true;
45
- }
51
+ return isHiddenVisually;
46
52
  }
47
53
 
48
54
  export { hasInteractiveNodes };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=character-counter.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"character-counter.test.d.ts","sourceRoot":"","sources":["../../../src/utils/__tests__/character-counter.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Shared character counting functionality for text inputs with character limits.
3
+ * Handles real-time character count updates, validation, and aria-live announcements.
4
+ */
5
+ export interface CharacterCounterCallbacks {
6
+ onCountUpdate: (count: number, isOverLimit: boolean, message: string) => void;
7
+ onScreenReaderAnnounce: (message: string) => void;
8
+ }
9
+ export declare class CharacterCounter {
10
+ private announceTimeout;
11
+ private callbacks;
12
+ private isInitialLoad;
13
+ constructor(callbacks: CharacterCounterCallbacks);
14
+ /**
15
+ * Update the character count based on current input value
16
+ */
17
+ updateCharacterCount(currentLength: number, maxLength: number): void;
18
+ /**
19
+ * Announce character count to screen readers with debouncing
20
+ */
21
+ private announceToScreenReader;
22
+ /**
23
+ * Clean up any pending timeouts
24
+ */
25
+ cleanup(): void;
26
+ }
27
+ //# sourceMappingURL=character-counter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"character-counter.d.ts","sourceRoot":"","sources":["../../src/utils/character-counter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7E,sBAAsB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CAClD;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,eAAe,CAAsB;IAC7C,OAAO,CAAC,SAAS,CAA2B;IAC5C,OAAO,CAAC,aAAa,CAAgB;gBAEzB,SAAS,EAAE,yBAAyB;IAIhD;;OAEG;IACH,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAyBpE;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAc9B;;OAEG;IACH,OAAO,IAAI,IAAI;CAKhB"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Shared character counting functionality for text inputs with character limits.
3
+ * Handles real-time character count updates, validation, and aria-live announcements.
4
+ */
5
+
6
+ const SCREEN_READER_DELAY = 500;
7
+ class CharacterCounter {
8
+ announceTimeout = null;
9
+ isInitialLoad = true;
10
+ constructor(callbacks) {
11
+ this.callbacks = callbacks;
12
+ }
13
+
14
+ /**
15
+ * Update the character count based on current input value
16
+ */
17
+ updateCharacterCount(currentLength, maxLength) {
18
+ const charactersRemaining = maxLength - currentLength;
19
+ let message = '';
20
+ if (charactersRemaining >= 0) {
21
+ const characterText = charactersRemaining === 1 ? 'character' : 'characters';
22
+ message = `${charactersRemaining} ${characterText} remaining`;
23
+ this.callbacks.onCountUpdate(charactersRemaining, false, message);
24
+ } else {
25
+ const charactersOver = -charactersRemaining;
26
+ const characterText = charactersOver === 1 ? 'character' : 'characters';
27
+ message = `${charactersOver} ${characterText} over`;
28
+ this.callbacks.onCountUpdate(charactersOver, true, message);
29
+ }
30
+ if (!this.isInitialLoad) {
31
+ this.announceToScreenReader(message);
32
+ }
33
+
34
+ // After first update, set isInitialLoad to false
35
+ if (this.isInitialLoad) {
36
+ this.isInitialLoad = false;
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Announce character count to screen readers with debouncing
42
+ */
43
+ announceToScreenReader(message) {
44
+ if (this.announceTimeout) {
45
+ clearTimeout(this.announceTimeout);
46
+ }
47
+ if (typeof window === 'undefined' || typeof window.setTimeout !== 'function') {
48
+ return;
49
+ }
50
+ this.announceTimeout = window.setTimeout(() => {
51
+ this.callbacks.onScreenReaderAnnounce(message);
52
+ }, SCREEN_READER_DELAY);
53
+ }
54
+
55
+ /**
56
+ * Clean up any pending timeouts
57
+ */
58
+ cleanup() {
59
+ if (this.announceTimeout) {
60
+ clearTimeout(this.announceTimeout);
61
+ }
62
+ }
63
+ }
64
+
65
+ export { CharacterCounter };
@@ -138,6 +138,12 @@
138
138
  "type": "Component | 'none'",
139
139
  "required": false,
140
140
  "description": "Icon displayed when the menu item is within the overflow menu. If 'none' is provided, no icon will be shown in the overflow menu."
141
+ },
142
+ {
143
+ "name": "returnFocusRef",
144
+ "type": "React.RefObject<HTMLElement>",
145
+ "required": false,
146
+ "description": "A ref to an element that should receive focus when the menu is closed."
141
147
  }
142
148
  ]
143
149
  }
@@ -7162,6 +7168,11 @@
7162
7168
  "defaultValue": "false",
7163
7169
  "description": "Creates a full-width input element"
7164
7170
  },
7171
+ {
7172
+ "name": "characterLimit",
7173
+ "type": "number",
7174
+ "description": "The maximum number of characters allowed in the input"
7175
+ },
7165
7176
  {
7166
7177
  "name": "contrast",
7167
7178
  "type": "boolean",
@@ -7501,6 +7512,11 @@
7501
7512
  "defaultValue": "'both'",
7502
7513
  "description": "Changes the resize behavior"
7503
7514
  },
7515
+ {
7516
+ "name": "characterLimit",
7517
+ "type": "number",
7518
+ "description": "The maximum number of characters allowed in the textarea"
7519
+ },
7504
7520
  {
7505
7521
  "name": "contrast",
7506
7522
  "type": "boolean",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@primer/react",
3
3
  "type": "module",
4
- "version": "38.6.3-rc.f8f5fddc3",
4
+ "version": "38.7.0-rc.92435c0d2",
5
5
  "description": "An implementation of GitHub's Primer Design System using React",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.js",
@@ -79,9 +79,9 @@
79
79
  "@github/tab-container-element": "^4.8.2",
80
80
  "@lit-labs/react": "1.2.1",
81
81
  "@oddbird/popover-polyfill": "^0.5.2",
82
- "@primer/behaviors": "^1.9.0",
82
+ "@primer/behaviors": "^1.9.1",
83
83
  "@primer/live-region-element": "^0.7.1",
84
- "@primer/octicons-react": "^19.13.0",
84
+ "@primer/octicons-react": "^19.21.0",
85
85
  "@primer/primitives": "10.x || 11.x",
86
86
  "clsx": "^2.1.1",
87
87
  "color2k": "^2.0.3",
@@ -114,11 +114,11 @@
114
114
  "@rollup/plugin-node-resolve": "16.0.3",
115
115
  "@rollup/plugin-typescript": "12.3.0",
116
116
  "@rollup/plugin-virtual": "3.0.2",
117
- "@storybook/addon-a11y": "^10.1.4",
118
- "@storybook/addon-docs": "^10.1.4",
119
- "@storybook/addon-links": "^10.1.4",
117
+ "@storybook/addon-a11y": "^10.1.10",
118
+ "@storybook/addon-docs": "^10.1.10",
119
+ "@storybook/addon-links": "^10.1.10",
120
120
  "@storybook/icons": "^2.0.1",
121
- "@storybook/react-vite": "^10.1.4",
121
+ "@storybook/react-vite": "^10.1.10",
122
122
  "@testing-library/dom": "^10.4.0",
123
123
  "@testing-library/jest-dom": "^6.4.5",
124
124
  "@testing-library/react": "^16.3.0",
@@ -170,9 +170,9 @@
170
170
  "react-is": "18.3.1",
171
171
  "recast": "0.23.7",
172
172
  "rimraf": "5.0.5",
173
- "rollup": "4.53.3",
173
+ "rollup": "4.54.0",
174
174
  "rollup-plugin-import-css": "^0.0.0",
175
- "storybook": "^10.1.4",
175
+ "storybook": "^10.1.10",
176
176
  "terser": "5.36.0",
177
177
  "ts-toolbelt": "9.6.0",
178
178
  "tsx": "4.20.3",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["src/BaseStyles.module.css.js"],"names":[],"mappings":"AAMA,EACE,qBACF,CAEA,KACE,QACF,CAEA,MAEE,wBACF,CAEA,8BACE,sCAAmB,CAAnB,kBACF,CAEA,6BACE,gCAAkB,CAAlB,iBACF,CAEA,oCACE,gDACE,sCAAmB,CAAnB,kBACF,CACF,CAEA,mCACE,8CACE,gCAAkB,CAAlB,iBACF,CACF,CAEA,mSAME,eAAgB,CADhB,YAEF,CAEA,0HAEE,YACF,CAIA,0BAKE,8EAAwD,CAJxD,wLAAkE,CAElE,4CA2BF,CArBI,6DACE,sCAAmB,CAAnB,kBACF,CAKA,4DACE,gCAAkB,CAAlB,iBACF,CAIF,uGACE,kDAAoD,CACpD,4BAAqB,CAArB,oBAKF,CAHE,kHACE,iCAA0B,CAA1B,yBACF","file":"BaseStyles-79fd37c4.css","sourcesContent":["/* stylelint-disable selector-max-specificity */\n/* stylelint-disable selector-type-no-unknown */\n\n/* -------------------------------- \n * Global Styles \n *--------------------------------- */\n* {\n box-sizing: border-box;\n}\n\nbody {\n margin: 0;\n}\n\ntable {\n /* stylelint-disable-next-line primer/borders */\n border-collapse: collapse;\n}\n\n[data-color-mode='light'] input {\n color-scheme: light;\n}\n\n[data-color-mode='dark'] input {\n color-scheme: dark;\n}\n\n@media (prefers-color-scheme: light) {\n [data-color-mode='auto'][data-light-theme*='light'] {\n color-scheme: light;\n }\n}\n\n@media (prefers-color-scheme: dark) {\n [data-color-mode='auto'][data-dark-theme*='dark'] {\n color-scheme: dark;\n }\n}\n\n[role='button']:focus:not(:focus-visible):not(:global(.focus-visible)),\n[role='tabpanel'][tabindex='0']:focus:not(:focus-visible):not(:global(.focus-visible)),\nbutton:focus:not(:focus-visible):not(:global(.focus-visible)),\nsummary:focus:not(:focus-visible):not(:global(.focus-visible)),\na:focus:not(:focus-visible):not(:global(.focus-visible)) {\n outline: none;\n box-shadow: none;\n}\n\n[tabindex='0']:focus:not(:focus-visible):not(:global(.focus-visible)),\ndetails-dialog:focus:not(:focus-visible):not(:global(.focus-visible)) {\n outline: none;\n}\n\n/* -------------------------------------------------------------------------- */\n\n.BaseStyles {\n font-family: var(--BaseStyles-fontFamily, var(--fontStack-system));\n /* stylelint-disable-next-line primer/typography */\n line-height: var(--BaseStyles-lineHeight, 1.5);\n /* stylelint-disable-next-line primer/colors */\n color: var(--BaseStyles-fgColor, var(--fgColor-default));\n\n /* Global styles for light mode */\n &:has([data-color-mode='light']) {\n input & {\n color-scheme: light;\n }\n }\n\n /* Global styles for dark mode */\n &:has([data-color-mode='dark']) {\n input & {\n color-scheme: dark;\n }\n }\n\n /* Low-specificity default link styling */\n :where(a:not([class*='prc-']):not([class*='PRC-']):not([class*='Primer_Brand__'])) {\n color: var(--fgColor-accent, var(--color-accent-fg));\n text-decoration: none;\n\n &:hover {\n text-decoration: underline;\n }\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/Dialog/Dialog.module.css.js"],"names":[],"mappings":"AAOA,oCACE,eAAgB,CAChB,cAAe,CACf,iBACF,CAEA,mDACE,GACE,SACF,CAEA,GACE,SACF,CACF,CAEA,sDACE,GACE,SAAU,CACV,mBACF,CAEA,GACE,SAAU,CACV,kBACF,CACF,CAEA,oDACE,GACE,0BACF,CACF,CAEA,yDACE,GACE,2BACF,CACF,CAEA,wDACE,GACE,0BACF,CACF,CAGA,0CACE,MAEE,cACF,CACF,CAEA,2BAQE,+EAAsE,CADtE,8EAAiD,CAHjD,QAAS,CAET,YAAa,CADb,MAAO,CAJP,cAAe,CAEf,OAAQ,CADR,KAoCF,CA1BE,oFAHA,kBAAmB,CACnB,sBAKA,CAEA,uDACE,kBAAmB,CACnB,0BACF,CAEA,wDACE,kBAAmB,CACnB,wBACF,CAEA,yBACE,wDACE,kBAAmB,CACnB,sBACF,CAEA,wDACE,eAAgB,CAChB,sBACF,CACF,CAGF,yBASE,mEAAwC,CACxC,8CAAwC,CACxC,wEAAmE,CACnE,mEAAwC,CAXxC,YAAa,CAOb,qBAAsB,CAFtB,WAAY,CACZ,8BAA+B,CAF/B,6BAA8B,CAD9B,eAAgB,CAShB,SAAU,CAVV,WA6HF,CAjHE,mDACE,WACF,CAEA,oDACE,WACF,CAEA,mDAEE,WACF,CAEA,oDACE,YACF,CAEA,oDACE,YACF,CAEA,yDApCF,yBAqCI,4GA2FJ,CA1FE,CAEA,uDACE,wEAKF,CAHE,yDAHF,uDAII,4GAEJ,CADE,CAGF,qDAGE,wEAAmE,CAEnE,2BAA4B,CAD5B,wBAAyB,CAHzB,aAAc,CACd,gBAQF,CAHE,yDAPF,qDAQI,gHAEJ,CADE,CAGF,sDAGE,wEAAmE,CAEnE,4BAA6B,CAD7B,yBAA0B,CAH1B,aAAc,CACd,gBAQF,CAHE,yDAPF,sDAQI,8GAEJ,CADE,CAGF,yBACE,sDAIE,wEAAmE,CADnE,WAAY,CADZ,WAwBF,CApBE,gFACE,WACF,CAEA,iFACE,WACF,CAEA,gFAEE,WACF,CAEA,iFACE,YACF,CAEA,iFACE,YACF,CAGF,sDAKE,wEAAmE,CAEnE,2BAA4B,CAD5B,4BAA6B,CAH7B,WAAY,CACZ,8BAA+B,CAF/B,gBAAiB,CADjB,YAWF,CAHE,yDATF,sDAUI,2GAEJ,CADE,CAGF,0DAKE,6BAA+B,CAC/B,WAAY,CAHZ,WAAY,CACZ,iBAAkB,CAFlB,gBAAiB,CADjB,UAUF,CAHE,yDARF,0DASI,4GAEJ,CADE,CAEJ,CAGF,kEAGE,yBAA2B,CAD3B,sDAEF,CAEA,wCACE,WACF,CAQA,uDACE,cAYF,CAVE,+FAGE,wCAAwB,CADxB,8GAA0E,CAE1E,+BAKF,CAHE,4CANF,+FAOI,mIAEJ,CADE,CAIJ,yBAME,yEAA8C,CAC9C,aAAc,CALd,eAAgB,CAEhB,eAAgB,CADhB,gCAA2B,CAF3B,SAOF,CAEA,8BACE,YACF,CAEA,gCACE,YAAa,CAGb,qBAAsB,CACtB,WAAY,CAFZ,wCAAiC,CADjC,uCAIF,CAEA,wBAEE,8CAAuC,CACvC,8CAA2C,CAF3C,QAGF,CAEA,2BAKE,gDAA2B,CAF3B,4CAAsC,CACtC,8CAA2C,CAH3C,QAAS,CACT,oCAIF,CAEA,uBAGE,WAAY,CADZ,aAEF,CAEA,gDALE,gCAoBF,CAfA,yBAEE,YAAa,CACb,cAAe,CAIf,aAAc,CADd,4BAAuB,CAFvB,wBAAyB,CAHzB,SAcF,CANE,0BATF,yBAYI,kBAAmB,CAFnB,gBAAiB,CAGjB,qBAAsB,CAFtB,iBAIJ,CADE","file":"Dialog-1a61e61a.css","sourcesContent":["/* The --prc-dialog-scrollgutter property is used only on the body element to\n * simulate scrollbar-gutter:stable. This property is not and should not\n * be used elsewhere in the DOM. There is a performance penalty to\n * setting inherited properties which can cause a large style recalc to\n * occur, so it benefits us to prevent inheritance for this property.\n * See https://web.dev/blog/at-property-performance\n */\n@property --prc-dialog-scrollgutter {\n initial-value: 0;\n inherits: false;\n syntax: '<length>';\n}\n\n@keyframes dialog-backdrop-appear {\n 0% {\n opacity: 0;\n }\n\n 100% {\n opacity: 1;\n }\n}\n\n@keyframes Overlay--motion-scaleFade {\n 0% {\n opacity: 0;\n transform: scale(0.5);\n }\n\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n}\n\n@keyframes Overlay--motion-slideUp {\n from {\n transform: translateY(100%);\n }\n}\n\n@keyframes Overlay--motion-slideInRight {\n from {\n transform: translateX(-100%);\n }\n}\n\n@keyframes Overlay--motion-slideInLeft {\n from {\n transform: translateX(100%);\n }\n}\n\n/* Used to determine whether there should be a border between the body and footer */\n@keyframes detect-scroll {\n from,\n to {\n --can-scroll: 1;\n }\n}\n\n.Backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n display: flex;\n background-color: var(--overlay-backdrop-bgColor);\n animation: dialog-backdrop-appear 200ms cubic-bezier(0.33, 1, 0.68, 1);\n align-items: center;\n justify-content: center;\n\n &[data-position-regular='center'] {\n align-items: center;\n justify-content: center;\n }\n\n &[data-position-regular='left'] {\n align-items: center;\n justify-content: flex-start;\n }\n\n &[data-position-regular='right'] {\n align-items: center;\n justify-content: flex-end;\n }\n\n @media (max-width: 767px) {\n &[data-position-narrow='center'] {\n align-items: center;\n justify-content: center;\n }\n\n &[data-position-narrow='bottom'] {\n align-items: end;\n justify-content: center;\n }\n }\n}\n\n.Dialog {\n display: flex;\n /* stylelint-disable-next-line primer/responsive-widths */\n width: 640px;\n min-width: 296px;\n max-width: calc(100dvw - 64px);\n height: auto;\n max-height: calc(100dvh - 64px);\n flex-direction: column;\n background-color: var(--overlay-bgColor);\n border-radius: var(--borderRadius-large);\n border-radius: var(--borderRadius-large, var(--borderRadius-large));\n box-shadow: var(--shadow-floating-small);\n opacity: 1;\n\n &:where([data-width='small']) {\n width: 296px;\n }\n\n &:where([data-width='medium']) {\n width: 320px;\n }\n\n &:where([data-width='large']) {\n /* stylelint-disable-next-line primer/responsive-widths */\n width: 480px;\n }\n\n &:where([data-height='small']) {\n height: 480px;\n }\n\n &:where([data-height='large']) {\n height: 640px;\n }\n\n @media screen and (prefers-reduced-motion: no-preference) {\n animation: Overlay--motion-scaleFade 0.2s cubic-bezier(0.33, 1, 0.68, 1) 1ms 1 normal none running;\n }\n\n &[data-position-regular='center'] {\n border-radius: var(--borderRadius-large, var(--borderRadius-large));\n\n @media screen and (prefers-reduced-motion: no-preference) {\n animation: Overlay--motion-scaleFade 0.2s cubic-bezier(0.33, 1, 0.68, 1) 1ms 1 normal none running;\n }\n }\n\n &[data-position-regular='left'] {\n height: 100dvh;\n max-height: unset;\n border-radius: var(--borderRadius-large, var(--borderRadius-large));\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n\n @media screen and (prefers-reduced-motion: no-preference) {\n animation: Overlay--motion-slideInRight 0.25s cubic-bezier(0.33, 1, 0.68, 1) 1ms 1 normal none running;\n }\n }\n\n &[data-position-regular='right'] {\n height: 100dvh;\n max-height: unset;\n border-radius: var(--borderRadius-large, var(--borderRadius-large));\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n\n @media screen and (prefers-reduced-motion: no-preference) {\n animation: Overlay--motion-slideInLeft 0.25s cubic-bezier(0.33, 1, 0.68, 1) 0s 1 normal none running;\n }\n }\n\n @media (max-width: 767px) {\n &[data-position-narrow='center'] {\n /* stylelint-disable-next-line primer/responsive-widths */\n width: 640px;\n height: auto;\n border-radius: var(--borderRadius-large, var(--borderRadius-large));\n\n &:where([data-width='small']) {\n width: 296px;\n }\n\n &:where([data-width='medium']) {\n width: 320px;\n }\n\n &:where([data-width='large']) {\n /* stylelint-disable-next-line primer/responsive-widths */\n width: 480px;\n }\n\n &:where([data-height='small']) {\n height: 480px;\n }\n\n &:where([data-height='large']) {\n height: 640px;\n }\n }\n\n &[data-position-narrow='bottom'] {\n width: 100dvw;\n max-width: 100dvw;\n height: auto;\n max-height: calc(100dvh - 64px);\n border-radius: var(--borderRadius-large, var(--borderRadius-large));\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n\n @media screen and (prefers-reduced-motion: no-preference) {\n animation: Overlay--motion-slideUp 0.25s cubic-bezier(0.33, 1, 0.68, 1) 1ms 1 normal none running;\n }\n }\n\n &[data-position-narrow='fullscreen'] {\n width: 100%;\n max-width: 100dvw;\n height: 100%;\n max-height: 100dvh;\n border-radius: unset !important;\n flex-grow: 1;\n\n @media screen and (prefers-reduced-motion: no-preference) {\n animation: Overlay--motion-scaleFade 0.2s cubic-bezier(0.33, 1, 0.68, 1) 1ms 1 normal none running;\n }\n }\n }\n}\n\nbody:has(.Dialog.DisableScroll) {\n /* stylelint-disable-next-line primer/spacing */\n padding-right: var(--prc-dialog-scrollgutter) !important;\n overflow: hidden !important;\n}\n\n.DialogOverflowWrapper {\n flex-grow: 1;\n}\n\n/*\nAdd a border between the body and footer if:\n- the dialog has a footer\n- the dialog has a body that can scroll\n- the browser supports the `animation-timeline` property and its `scroll()` function\n*/\n.Dialog:has(.Footer) {\n --can-scroll: 0;\n\n .DialogOverflowWrapper {\n /* If the browser does not support the `animation-timeline` property, always show a border */\n border-bottom: var(--borderWidth-default) solid var(--borderColor-default);\n animation: detect-scroll;\n animation-timeline: scroll(self);\n\n @supports (animation-timeline: scroll(self)) {\n border-bottom: calc(var(--borderWidth-thin) * var(--can-scroll)) solid var(--borderColor-default);\n }\n }\n}\n\n.Header {\n z-index: 1;\n max-height: 35vh;\n padding: var(--base-size-8);\n overflow-y: auto;\n /* stylelint-disable-next-line primer/box-shadow */\n box-shadow: 0 1px 0 var(--borderColor-default);\n flex-shrink: 0;\n}\n\n.HeaderInner {\n display: flex;\n}\n\n.HeaderContent {\n display: flex;\n padding-inline: var(--base-size-8);\n padding-block: var(--base-size-6);\n flex-direction: column;\n flex-grow: 1;\n}\n\n.Title {\n margin: 0; /* override default margin */\n font-size: var(--text-body-size-medium);\n font-weight: var(--text-title-weight-large);\n}\n\n.Subtitle {\n margin: 0; /* override default margin */\n margin-top: var(--base-size-4);\n font-size: var(--text-body-size-small);\n font-weight: var(--base-text-weight-normal);\n color: var(--fgColor-muted);\n}\n\n.Body {\n padding: var(--base-size-16);\n overflow: auto;\n flex-grow: 1;\n}\n\n.Footer {\n z-index: 1;\n display: flex;\n flex-flow: wrap;\n justify-content: flex-end;\n padding: var(--base-size-16);\n gap: var(--base-size-8);\n flex-shrink: 0;\n\n @media (max-height: 325px) {\n flex-wrap: nowrap;\n overflow-x: scroll;\n flex-direction: row;\n justify-content: unset;\n }\n}\n"]}