@primer/components 31.0.2-rc.c7dafefb → 31.2.0-rc.a53b3afb

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 (100) hide show
  1. package/.storybook/main.js +7 -9
  2. package/.storybook/preview.js +5 -1
  3. package/CHANGELOG.md +11 -1
  4. package/dist/browser.esm.js +11 -10
  5. package/dist/browser.esm.js.map +1 -1
  6. package/dist/browser.umd.js +11 -10
  7. package/dist/browser.umd.js.map +1 -1
  8. package/docs/content/FilterList.md +2 -2
  9. package/docs/content/TextInputWithTokens.mdx +114 -0
  10. package/docs/content/theming.md +23 -0
  11. package/lib/Autocomplete/Autocomplete.d.ts +4 -4
  12. package/lib/Autocomplete/AutocompleteInput.d.ts +4 -4
  13. package/lib/Button/Button.d.ts +5 -5
  14. package/lib/Button/ButtonBase.d.ts +1 -1
  15. package/lib/Button/ButtonClose.d.ts +3 -3
  16. package/lib/Button/ButtonDanger.d.ts +5 -5
  17. package/lib/Button/ButtonInvisible.d.ts +5 -5
  18. package/lib/Button/ButtonOutline.d.ts +5 -5
  19. package/lib/Button/ButtonPrimary.d.ts +5 -5
  20. package/lib/CircleBadge.d.ts +2 -2
  21. package/lib/CircleOcticon.d.ts +4 -4
  22. package/lib/Dialog.d.ts +4 -4
  23. package/lib/Dropdown.d.ts +16 -16
  24. package/lib/DropdownMenu/DropdownButton.d.ts +6 -6
  25. package/lib/FilterList.d.ts +3 -3
  26. package/lib/Flash.d.ts +1 -1
  27. package/lib/Label.d.ts +1 -1
  28. package/lib/Position.d.ts +4 -4
  29. package/lib/ProgressBar.d.ts +1 -1
  30. package/lib/SelectMenu/SelectMenu.d.ts +24 -24
  31. package/lib/SelectMenu/SelectMenuItem.d.ts +1 -1
  32. package/lib/TextInputWithTokens.d.ts +8 -4
  33. package/lib/TextInputWithTokens.js +61 -8
  34. package/lib/Timeline.d.ts +4 -4
  35. package/lib/Token/AvatarToken.d.ts +1 -1
  36. package/lib/Token/IssueLabelToken.d.ts +1 -1
  37. package/lib/Token/Token.d.ts +1 -1
  38. package/lib/_TextInputWrapper.d.ts +1 -1
  39. package/lib/_TextInputWrapper.js +1 -1
  40. package/lib/__tests__/KeyPaths.types.test.d.ts +10 -0
  41. package/lib/__tests__/KeyPaths.types.test.js +10 -0
  42. package/lib/__tests__/TextInputWithTokens.test.js +149 -9
  43. package/lib/stories/TextInputWithTokens.stories.js +18 -1
  44. package/lib/sx.d.ts +8 -2
  45. package/lib/theme.d.ts +78 -0
  46. package/lib/theme.js +3 -1
  47. package/lib/utils/types/KeyPaths.d.ts +3 -0
  48. package/lib/utils/types/KeyPaths.js +1 -0
  49. package/lib-esm/Autocomplete/Autocomplete.d.ts +4 -4
  50. package/lib-esm/Autocomplete/AutocompleteInput.d.ts +4 -4
  51. package/lib-esm/Button/Button.d.ts +5 -5
  52. package/lib-esm/Button/ButtonBase.d.ts +1 -1
  53. package/lib-esm/Button/ButtonClose.d.ts +3 -3
  54. package/lib-esm/Button/ButtonDanger.d.ts +5 -5
  55. package/lib-esm/Button/ButtonInvisible.d.ts +5 -5
  56. package/lib-esm/Button/ButtonOutline.d.ts +5 -5
  57. package/lib-esm/Button/ButtonPrimary.d.ts +5 -5
  58. package/lib-esm/CircleBadge.d.ts +2 -2
  59. package/lib-esm/CircleOcticon.d.ts +4 -4
  60. package/lib-esm/Dialog.d.ts +4 -4
  61. package/lib-esm/Dropdown.d.ts +16 -16
  62. package/lib-esm/DropdownMenu/DropdownButton.d.ts +6 -6
  63. package/lib-esm/FilterList.d.ts +3 -3
  64. package/lib-esm/Flash.d.ts +1 -1
  65. package/lib-esm/Label.d.ts +1 -1
  66. package/lib-esm/Position.d.ts +4 -4
  67. package/lib-esm/ProgressBar.d.ts +1 -1
  68. package/lib-esm/SelectMenu/SelectMenu.d.ts +24 -24
  69. package/lib-esm/SelectMenu/SelectMenuItem.d.ts +1 -1
  70. package/lib-esm/TextInputWithTokens.d.ts +8 -4
  71. package/lib-esm/TextInputWithTokens.js +60 -8
  72. package/lib-esm/Timeline.d.ts +4 -4
  73. package/lib-esm/Token/AvatarToken.d.ts +1 -1
  74. package/lib-esm/Token/IssueLabelToken.d.ts +1 -1
  75. package/lib-esm/Token/Token.d.ts +1 -1
  76. package/lib-esm/_TextInputWrapper.d.ts +1 -1
  77. package/lib-esm/_TextInputWrapper.js +1 -1
  78. package/lib-esm/__tests__/KeyPaths.types.test.d.ts +10 -0
  79. package/lib-esm/__tests__/KeyPaths.types.test.js +3 -0
  80. package/lib-esm/__tests__/TextInputWithTokens.test.js +142 -9
  81. package/lib-esm/stories/TextInputWithTokens.stories.js +14 -0
  82. package/lib-esm/sx.d.ts +8 -2
  83. package/lib-esm/theme.d.ts +78 -0
  84. package/lib-esm/theme.js +2 -1
  85. package/lib-esm/utils/types/KeyPaths.d.ts +3 -0
  86. package/lib-esm/utils/types/KeyPaths.js +1 -0
  87. package/package-lock.json +37942 -41
  88. package/package.json +2 -1
  89. package/src/TextInputWithTokens.tsx +64 -8
  90. package/src/_TextInputWrapper.tsx +1 -0
  91. package/src/__tests__/KeyPaths.types.test.ts +13 -0
  92. package/src/__tests__/TextInputWithTokens.test.tsx +133 -1
  93. package/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap +7 -0
  94. package/src/__tests__/__snapshots__/TextInput.test.tsx.snap +6 -0
  95. package/src/__tests__/__snapshots__/TextInputWithTokens.test.tsx.snap +463 -0
  96. package/src/stories/TextInputWithTokens.stories.tsx +9 -0
  97. package/src/sx.ts +14 -2
  98. package/src/theme.ts +86 -0
  99. package/src/utils/types/KeyPaths.ts +4 -0
  100. package/stats.html +1 -1
@@ -2,7 +2,7 @@ function _extends() { _extends = Object.assign || function (target) { for (var i
2
2
 
3
3
  import React from 'react';
4
4
  import { render } from '../utils/testing';
5
- import { render as HTMLRender, cleanup, fireEvent } from '@testing-library/react';
5
+ import { render as HTMLRender, fireEvent, act, cleanup } from '@testing-library/react';
6
6
  import { axe, toHaveNoViolations } from 'jest-axe';
7
7
  import 'babel-polyfill';
8
8
  import { tokenSizes } from '../Token/TokenBase';
@@ -46,8 +46,18 @@ const LabelledTextInputWithTokens = ({
46
46
  tokens: tokens,
47
47
  onTokenRemove: onTokenRemove,
48
48
  id: "tokenInput"
49
- }, rest)));
49
+ }, rest))); // describe('axe test', () => {
50
+ // it('should have no axe violations', async () => {
51
+ // const onRemoveMock = jest.fn()
52
+ // const {container} = HTMLRender(<LabelledTextInputWithTokens tokens={mockTokens} onTokenRemove={onRemoveMock} />)
53
+ // const results = await axe(container)
54
+ // expect(results).toHaveNoViolations()
55
+ // cleanup()
56
+ // })
57
+ // })
50
58
 
59
+
60
+ jest.useFakeTimers();
51
61
  describe('TextInputWithTokens', () => {
52
62
  it('renders without tokens', () => {
53
63
  const onRemoveMock = jest.fn();
@@ -115,6 +125,14 @@ describe('TextInputWithTokens', () => {
115
125
  onTokenRemove: onRemoveMock
116
126
  }))).toMatchSnapshot();
117
127
  });
128
+ it('renders a truncated set of tokens', () => {
129
+ const onRemoveMock = jest.fn();
130
+ expect(render( /*#__PURE__*/React.createElement(TextInputWithTokens, {
131
+ tokens: mockTokens,
132
+ onTokenRemove: onRemoveMock,
133
+ visibleTokenCount: 2
134
+ }))).toMatchSnapshot();
135
+ });
118
136
  it('focuses the previous token when keying ArrowLeft', () => {
119
137
  var _document$activeEleme, _document$activeEleme2;
120
138
 
@@ -220,8 +238,123 @@ describe('TextInputWithTokens', () => {
220
238
  expect((_document$activeEleme8 = document.activeElement) === null || _document$activeEleme8 === void 0 ? void 0 : _document$activeEleme8.id).not.toEqual(lastTokenNode.id);
221
239
  expect((_document$activeEleme9 = document.activeElement) === null || _document$activeEleme9 === void 0 ? void 0 : _document$activeEleme9.id).toEqual(inputNode.id);
222
240
  });
241
+ it('does not focus the input when clicking a token', () => {
242
+ var _document$activeEleme10;
243
+
244
+ const onRemoveMock = jest.fn();
245
+ const {
246
+ getByLabelText,
247
+ getByText
248
+ } = HTMLRender( /*#__PURE__*/React.createElement(LabelledTextInputWithTokens, {
249
+ tokens: mockTokens,
250
+ onTokenRemove: onRemoveMock,
251
+ visibleTokenCount: 2
252
+ }));
253
+ const inputNode = getByLabelText('Tokens');
254
+ const tokenNode = getByText(mockTokens[0].text);
255
+ expect(document.activeElement).not.toEqual(inputNode.id);
256
+ fireEvent.click(tokenNode);
257
+ expect((_document$activeEleme10 = document.activeElement) === null || _document$activeEleme10 === void 0 ? void 0 : _document$activeEleme10.id).not.toEqual(inputNode.id);
258
+ });
259
+ it('focuses the input when clicking somewhere in the component besides the tokens', () => {
260
+ var _document$activeEleme11;
261
+
262
+ const onRemoveMock = jest.fn();
263
+ const {
264
+ getByLabelText,
265
+ getByText
266
+ } = HTMLRender( /*#__PURE__*/React.createElement(LabelledTextInputWithTokens, {
267
+ tokens: mockTokens,
268
+ onTokenRemove: onRemoveMock,
269
+ visibleTokenCount: 2
270
+ }));
271
+ const inputNode = getByLabelText('Tokens');
272
+ const truncatedTokenCount = getByText('+6');
273
+ expect(document.activeElement).not.toEqual(inputNode.id);
274
+ fireEvent.click(truncatedTokenCount);
275
+ expect((_document$activeEleme11 = document.activeElement) === null || _document$activeEleme11 === void 0 ? void 0 : _document$activeEleme11.id).toEqual(inputNode.id);
276
+ });
277
+ it('shows all tokens when the input is focused and hides them when it is blurred (when visibleTokenCount is set)', () => {
278
+ const onRemoveMock = jest.fn();
279
+ const visibleTokenCount = 2;
280
+ const {
281
+ getByLabelText,
282
+ getByText
283
+ } = HTMLRender( /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(LabelledTextInputWithTokens, {
284
+ tokens: mockTokens,
285
+ onTokenRemove: onRemoveMock,
286
+ visibleTokenCount: visibleTokenCount
287
+ }), /*#__PURE__*/React.createElement("button", {
288
+ id: "focusableOutsideComponent"
289
+ }, "Focus me")));
290
+ const inputNode = getByLabelText('Tokens');
291
+ const focusableOutsideComponentNode = getByText('Focus me');
292
+ const allTokenLabels = mockTokens.map(token => token.text);
293
+ const truncatedTokenCountNode = getByText('+6');
294
+ act(() => {
295
+ jest.runAllTimers();
296
+ fireEvent.focus(inputNode);
297
+ });
298
+ setTimeout(() => {
299
+ for (const tokenLabel of allTokenLabels) {
300
+ const tokenNode = getByText(tokenLabel);
301
+ expect(tokenNode).toBeDefined();
302
+ }
303
+ }, 0);
304
+ act(() => {
305
+ jest.runAllTimers(); // onBlur isn't called on input unless we specifically fire the "blur" event
306
+ // eslint-disable-next-line github/no-blur
307
+
308
+ fireEvent.blur(inputNode);
309
+ fireEvent.focus(focusableOutsideComponentNode);
310
+ });
311
+ setTimeout(() => {
312
+ expect(truncatedTokenCountNode).toBeDefined();
313
+
314
+ for (const tokenLabel of allTokenLabels) {
315
+ const tokenNode = getByText(tokenLabel);
316
+
317
+ if (allTokenLabels.indexOf(tokenLabel) > visibleTokenCount) {
318
+ // eslint-disable-next-line jest/no-conditional-expect
319
+ expect(tokenNode).toBeDefined();
320
+ } else {
321
+ // eslint-disable-next-line jest/no-conditional-expect
322
+ expect(tokenNode).not.toBeDefined();
323
+ }
324
+ }
325
+ }, 0);
326
+ jest.useRealTimers();
327
+ });
328
+ it('does not hide tokens when blurring the input to focus within the component (when visibleTokenCount is set)', () => {
329
+ const onRemoveMock = jest.fn();
330
+ const visibleTokenCount = 2;
331
+ const {
332
+ getByLabelText,
333
+ getByText
334
+ } = HTMLRender( /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(LabelledTextInputWithTokens, {
335
+ tokens: mockTokens,
336
+ onTokenRemove: onRemoveMock,
337
+ visibleTokenCount: visibleTokenCount
338
+ }), /*#__PURE__*/React.createElement("button", {
339
+ id: "focusableOutsideComponent"
340
+ }, "Focus me")));
341
+ const inputNode = getByLabelText('Tokens');
342
+ const firstTokenNode = getByText(mockTokens[visibleTokenCount - 1].text);
343
+ const allTokenLabels = mockTokens.map(token => token.text);
344
+ const truncatedTokenCountNode = getByText('+6');
345
+ act(() => {
346
+ fireEvent.focus(inputNode);
347
+ fireEvent.focus(firstTokenNode);
348
+ });
349
+ expect(truncatedTokenCountNode).toBeDefined();
350
+
351
+ for (const tokenLabel of allTokenLabels) {
352
+ const tokenNode = getByText(tokenLabel);
353
+ expect(tokenNode).toBeDefined();
354
+ }
355
+ });
223
356
  it('focuses the first token when keying ArrowRight in the input', () => {
224
- var _document$activeEleme10, _document$activeEleme11;
357
+ var _document$activeEleme12, _document$activeEleme13;
225
358
 
226
359
  const onRemoveMock = jest.fn();
227
360
  const {
@@ -238,8 +371,8 @@ describe('TextInputWithTokens', () => {
238
371
  fireEvent.keyDown(inputNode, {
239
372
  key: 'ArrowRight'
240
373
  });
241
- expect((_document$activeEleme10 = document.activeElement) === null || _document$activeEleme10 === void 0 ? void 0 : _document$activeEleme10.id).not.toEqual(inputNode.id);
242
- expect((_document$activeEleme11 = document.activeElement) === null || _document$activeEleme11 === void 0 ? void 0 : _document$activeEleme11.id).toEqual(firstTokenNode.id);
374
+ expect((_document$activeEleme12 = document.activeElement) === null || _document$activeEleme12 === void 0 ? void 0 : _document$activeEleme12.id).not.toEqual(inputNode.id);
375
+ expect((_document$activeEleme13 = document.activeElement) === null || _document$activeEleme13 === void 0 ? void 0 : _document$activeEleme13.id).toEqual(firstTokenNode.id);
243
376
  });
244
377
  it('calls onTokenRemove on the last token when keying Backspace in an empty input', () => {
245
378
  const onRemoveMock = jest.fn();
@@ -324,9 +457,9 @@ describe('TextInputWithTokens', () => {
324
457
  });
325
458
  jest.runAllTimers();
326
459
  setTimeout(() => {
327
- var _document$activeEleme12;
460
+ var _document$activeEleme14;
328
461
 
329
- expect((_document$activeEleme12 = document.activeElement) === null || _document$activeEleme12 === void 0 ? void 0 : _document$activeEleme12.textContent).toBe(mockTokens[1].text);
462
+ expect((_document$activeEleme14 = document.activeElement) === null || _document$activeEleme14 === void 0 ? void 0 : _document$activeEleme14.textContent).toBe(mockTokens[1].text);
330
463
  }, 0);
331
464
  jest.useRealTimers();
332
465
  });
@@ -348,9 +481,9 @@ describe('TextInputWithTokens', () => {
348
481
  });
349
482
  jest.runAllTimers();
350
483
  setTimeout(() => {
351
- var _document$activeEleme13;
484
+ var _document$activeEleme15;
352
485
 
353
- expect((_document$activeEleme13 = document.activeElement) === null || _document$activeEleme13 === void 0 ? void 0 : _document$activeEleme13.id).toBe(inputNode.id);
486
+ expect((_document$activeEleme15 = document.activeElement) === null || _document$activeEleme15 === void 0 ? void 0 : _document$activeEleme15.id).toBe(inputNode.id);
354
487
  }, 0);
355
488
  jest.useRealTimers();
356
489
  });
@@ -171,6 +171,20 @@ export const TokenRemoveButtonsHidden = () => {
171
171
  });
172
172
  };
173
173
  TokenRemoveButtonsHidden.displayName = "TokenRemoveButtonsHidden";
174
+ export const WithVisibleTokenCount = () => {
175
+ const [tokens, setTokens] = useState([...mockTokens].slice(0, 5));
176
+
177
+ const onTokenRemove = tokenId => {
178
+ setTokens(tokens.filter(token => token.id !== tokenId));
179
+ };
180
+
181
+ return /*#__PURE__*/React.createElement(TextInputWithTokens, {
182
+ tokens: tokens,
183
+ onTokenRemove: onTokenRemove,
184
+ visibleTokenCount: 2
185
+ });
186
+ };
187
+ WithVisibleTokenCount.displayName = "WithVisibleTokenCount";
174
188
  export const Unstyled = () => {
175
189
  const [tokens, setTokens] = useState([...mockTokens].slice(0, 2));
176
190
 
package/lib-esm/sx.d.ts CHANGED
@@ -1,6 +1,12 @@
1
- import { SystemStyleObject } from '@styled-system/css';
1
+ import { SystemCssProperties, SystemStyleObject } from '@styled-system/css';
2
+ import { ThemeColorPaths, ThemeShadowPaths } from './theme';
3
+ import { ColorProps, ShadowProps } from 'styled-system';
4
+ export declare type BetterCssProperties = {
5
+ [K in keyof SystemCssProperties]: K extends keyof ColorProps ? ThemeColorPaths | SystemCssProperties[K] : K extends keyof ShadowProps ? ThemeShadowPaths | SystemCssProperties[K] : SystemCssProperties[K];
6
+ };
7
+ export declare type BetterSystemStyleObject = BetterCssProperties | SystemStyleObject;
2
8
  export interface SxProp {
3
- sx?: SystemStyleObject;
9
+ sx?: BetterSystemStyleObject;
4
10
  }
5
11
  declare const sx: (props: SxProp) => import("@styled-system/css").CssFunctionReturnType;
6
12
  export default sx;
@@ -1,2 +1,80 @@
1
1
  import { theme } from './theme-preval';
2
+ import { KeyPaths } from './utils/types/KeyPaths';
2
3
  export default theme;
4
+ declare type ThemeColors = {
5
+ fg: {
6
+ default: string;
7
+ muted: string;
8
+ subtle: string;
9
+ onEmphasis: string;
10
+ };
11
+ canvas: {
12
+ default: string;
13
+ overlay: string;
14
+ inset: string;
15
+ subtle: string;
16
+ };
17
+ border: {
18
+ default: string;
19
+ muted: string;
20
+ subtle: string;
21
+ };
22
+ neutral: {
23
+ emphasisPlus: string;
24
+ emphasis: string;
25
+ muted: string;
26
+ subtle: string;
27
+ };
28
+ accent: {
29
+ fg: string;
30
+ emphasis: string;
31
+ muted: string;
32
+ subtle: string;
33
+ };
34
+ success: {
35
+ fg: string;
36
+ emphasis: string;
37
+ muted: string;
38
+ subtle: string;
39
+ };
40
+ attention: {
41
+ fg: string;
42
+ emphasis: string;
43
+ muted: string;
44
+ subtle: string;
45
+ };
46
+ severe: {
47
+ fg: string;
48
+ emphasis: string;
49
+ muted: string;
50
+ subtle: string;
51
+ };
52
+ danger: {
53
+ fg: string;
54
+ emphasis: string;
55
+ muted: string;
56
+ subtle: string;
57
+ };
58
+ done: {
59
+ fg: string;
60
+ emphasis: string;
61
+ muted: string;
62
+ subtle: string;
63
+ };
64
+ sponsors: {
65
+ fg: string;
66
+ emphasis: string;
67
+ muted: string;
68
+ subtle: string;
69
+ };
70
+ };
71
+ declare type ThemeShadows = {
72
+ shadow: {
73
+ small: string;
74
+ medium: string;
75
+ large: string;
76
+ extraLarge: string;
77
+ };
78
+ };
79
+ export declare type ThemeColorPaths = KeyPaths<ThemeColors>;
80
+ export declare type ThemeShadowPaths = KeyPaths<ThemeShadows>;
package/lib-esm/theme.js CHANGED
@@ -1,2 +1,3 @@
1
1
  import { theme } from './theme-preval';
2
- export default theme;
2
+ export default theme; // NOTE: for now, ThemeColors and ThemeShadows are handcrafted types. It would be nice if these
3
+ // were exports from primitives (or a different shape but derived from those exports).
@@ -0,0 +1,3 @@
1
+ export declare type KeyPaths<O extends Record<string, unknown>> = {
2
+ [K in keyof O]: K extends string ? (O[K] extends string ? `${K}` : `${K}.${KeyPaths<O[K]>}`) : never;
3
+ }[keyof O];
@@ -0,0 +1 @@
1
+ export {};