@primer/components 0.0.0-2021927184638 → 0.0.0-2021927202224

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.
@@ -1,24 +1,25 @@
1
1
  import * as History from 'history';
2
2
  import React from 'react';
3
- import { SystemCommonProps, SystemFlexProps } from './constants';
4
3
  import { SxProp } from './sx';
5
4
  import { ComponentProps } from './utils/types';
6
- declare const BreadcrumbsBase: import("styled-components").StyledComponent<"nav", any, SystemFlexProps & SystemCommonProps & SxProp, never>;
7
- export declare type BreadcrumbsProps = ComponentProps<typeof BreadcrumbsBase>;
8
- declare function Breadcrumbs({ className, children, theme, ...rest }: React.PropsWithChildren<BreadcrumbsProps>): JSX.Element;
5
+ declare const BreadcrumbsBase: import("styled-components").StyledComponent<"nav", any, SxProp, never>;
6
+ export declare type BreadcrumbsProps = React.PropsWithChildren<{
7
+ className?: string;
8
+ } & SxProp>;
9
+ declare function Breadcrumbs({ className, children, sx: sxProp }: React.PropsWithChildren<BreadcrumbsProps>): JSX.Element;
9
10
  declare namespace Breadcrumbs {
10
11
  var displayName: string;
11
12
  }
12
13
  declare const BreadcrumbsItem: import("styled-components").StyledComponent<"a", any, {
13
14
  to?: History.LocationDescriptor<unknown> | undefined;
14
15
  selected?: boolean | undefined;
15
- } & SystemCommonProps & SxProp, never>;
16
+ } & SxProp, never>;
16
17
  export declare type BreadcrumbsItemProps = ComponentProps<typeof BreadcrumbsItem>;
17
18
  declare const _default: typeof Breadcrumbs & {
18
19
  Item: import("styled-components").StyledComponent<"a", any, {
19
20
  to?: History.LocationDescriptor<unknown> | undefined;
20
21
  selected?: boolean | undefined;
21
- } & SystemCommonProps & SxProp, never>;
22
+ } & SxProp, never>;
22
23
  };
23
24
  export default _default;
24
25
  /**
@@ -28,7 +29,7 @@ export declare const Breadcrumb: typeof Breadcrumbs & {
28
29
  Item: import("styled-components").StyledComponent<"a", any, {
29
30
  to?: History.LocationDescriptor<unknown> | undefined;
30
31
  selected?: boolean | undefined;
31
- } & SystemCommonProps & SxProp, never>;
32
+ } & SxProp, never>;
32
33
  };
33
34
  /**
34
35
  * @deprecated Use the `BreadcrumbsProps` type instead
@@ -19,8 +19,6 @@ var _sx = _interopRequireDefault(require("./sx"));
19
19
 
20
20
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
21
 
22
- function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
23
-
24
22
  const SELECTED_CLASS = 'selected';
25
23
 
26
24
  const Wrapper = _styledComponents.default.li.withConfig({
@@ -31,23 +29,20 @@ const Wrapper = _styledComponents.default.li.withConfig({
31
29
  const BreadcrumbsBase = _styledComponents.default.nav.withConfig({
32
30
  displayName: "Breadcrumbs__BreadcrumbsBase",
33
31
  componentId: "hwwoo0-1"
34
- })(["display:flex;justify-content:space-between;", ";", ";", ";"], _constants.COMMON, _constants.FLEX, _sx.default);
32
+ })(["display:flex;justify-content:space-between;", ";"], _sx.default);
35
33
 
36
34
  function Breadcrumbs({
37
35
  className,
38
36
  children,
39
- theme,
40
- ...rest
37
+ sx: sxProp
41
38
  }) {
42
- const wrappedChildren = _react.default.Children.map(children, child => /*#__PURE__*/_react.default.createElement(Wrapper, {
43
- theme: theme
44
- }, child));
39
+ const wrappedChildren = _react.default.Children.map(children, child => /*#__PURE__*/_react.default.createElement(Wrapper, null, child));
45
40
 
46
- return /*#__PURE__*/_react.default.createElement(BreadcrumbsBase, _extends({
41
+ return /*#__PURE__*/_react.default.createElement(BreadcrumbsBase, {
47
42
  className: className,
48
43
  "aria-label": "Breadcrumbs",
49
- theme: theme
50
- }, rest), /*#__PURE__*/_react.default.createElement(_Box.default, {
44
+ sx: sxProp
45
+ }, /*#__PURE__*/_react.default.createElement(_Box.default, {
51
46
  as: "ol",
52
47
  my: 0,
53
48
  pl: 0
@@ -63,7 +58,7 @@ const BreadcrumbsItem = _styledComponents.default.a.attrs(props => ({
63
58
  })).withConfig({
64
59
  displayName: "Breadcrumbs__BreadcrumbsItem",
65
60
  componentId: "hwwoo0-2"
66
- })(["color:", ";display:inline-block;font-size:", ";text-decoration:none;&:hover{text-decoration:underline;}&.selected{color:", ";pointer-events:none;}", " ", ";"], (0, _constants.get)('colors.accent.fg'), (0, _constants.get)('fontSizes.1'), (0, _constants.get)('colors.fg.default'), _constants.COMMON, _sx.default);
61
+ })(["color:", ";display:inline-block;font-size:", ";text-decoration:none;&:hover{text-decoration:underline;}&.selected{color:", ";pointer-events:none;}", ";"], (0, _constants.get)('colors.accent.fg'), (0, _constants.get)('fontSizes.1'), (0, _constants.get)('colors.fg.default'), _sx.default);
67
62
 
68
63
  Breadcrumbs.displayName = 'Breadcrumbs';
69
64
  BreadcrumbsItem.displayName = 'Breadcrumbs.Item';
@@ -32,6 +32,10 @@ declare const TextInputWithTokens: React.ForwardRefExoticComponent<Pick<{
32
32
  * Whether the remove buttons should be rendered in the tokens
33
33
  */
34
34
  hideTokenRemoveButtons?: boolean | undefined;
35
+ /**
36
+ * The number of tokens to display before truncating
37
+ */
38
+ visibleTokenCount?: number | undefined;
35
39
  } & Pick<Omit<Pick<{
36
40
  [x: string]: any;
37
41
  [x: number]: any;
@@ -25,6 +25,8 @@ var _TextInputWrapper = _interopRequireDefault(require("./_TextInputWrapper"));
25
25
 
26
26
  var _Box = _interopRequireDefault(require("./Box"));
27
27
 
28
+ var _Text = _interopRequireDefault(require("./Text"));
29
+
28
30
  var _iterateFocusableElements = require("./utils/iterateFocusableElements");
29
31
 
30
32
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -35,7 +37,13 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
35
37
 
36
38
  function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
37
39
 
38
- // using forwardRef is important so that other components (ex. Autocomplete) can use the ref
40
+ const overflowCountFontSizeMap = {
41
+ small: 0,
42
+ medium: 1,
43
+ large: 1,
44
+ extralarge: 2
45
+ }; // using forwardRef is important so that other components (ex. Autocomplete) can use the ref
46
+
39
47
  function TextInputWithTokensInnerComponent({
40
48
  icon: IconComponent,
41
49
  contrast,
@@ -55,9 +63,11 @@ function TextInputWithTokensInnerComponent({
55
63
  minWidth: minWidthProp,
56
64
  maxWidth: maxWidthProp,
57
65
  variant: variantProp,
66
+ visibleTokenCount,
58
67
  ...rest
59
68
  }, externalRef) {
60
69
  const {
70
+ onBlur,
61
71
  onFocus,
62
72
  onKeyDown,
63
73
  ...inputPropsRest
@@ -66,6 +76,7 @@ function TextInputWithTokensInnerComponent({
66
76
  const localInputRef = (0, _react.useRef)(null);
67
77
  const combinedInputRef = (0, _useCombinedRefs.useCombinedRefs)(localInputRef, ref);
68
78
  const [selectedTokenIndex, setSelectedTokenIndex] = (0, _react.useState)();
79
+ const [tokensAreTruncated, setTokensAreTruncated] = (0, _react.useState)(Boolean(visibleTokenCount));
69
80
  const {
70
81
  containerRef
71
82
  } = (0, _useFocusZone.useFocusZone)({
@@ -126,20 +137,45 @@ function TextInputWithTokensInnerComponent({
126
137
  };
127
138
 
128
139
  const handleTokenBlur = () => {
129
- setSelectedTokenIndex(undefined);
140
+ setSelectedTokenIndex(undefined); // HACK: wait a tick and check the focused element before hiding truncated tokens
141
+ // this prevents the tokens from hiding when the user is moving focus between tokens,
142
+ // but still hides the tokens when the user blurs the token by tabbing out or clicking somewhere else on the page
143
+
144
+ setTimeout(() => {
145
+ var _containerRef$current4;
146
+
147
+ if (!((_containerRef$current4 = containerRef.current) !== null && _containerRef$current4 !== void 0 && _containerRef$current4.contains(document.activeElement)) && visibleTokenCount) {
148
+ setTokensAreTruncated(true);
149
+ }
150
+ }, 0);
130
151
  };
131
152
 
132
- const handleTokenKeyUp = e => {
133
- if (e.key === 'Escape') {
153
+ const handleTokenKeyUp = event => {
154
+ if (event.key === 'Escape') {
134
155
  var _ref$current2;
135
156
 
136
157
  (_ref$current2 = ref.current) === null || _ref$current2 === void 0 ? void 0 : _ref$current2.focus();
137
158
  }
138
159
  };
139
160
 
140
- const handleInputFocus = e => {
141
- onFocus && onFocus(e);
161
+ const handleInputFocus = event => {
162
+ onFocus && onFocus(event);
142
163
  setSelectedTokenIndex(undefined);
164
+ visibleTokenCount && setTokensAreTruncated(false);
165
+ };
166
+
167
+ const handleInputBlur = event => {
168
+ onBlur && onBlur(event); // HACK: wait a tick and check the focused element before hiding truncated tokens
169
+ // this prevents the tokens from hiding when the user is moving focus from the input to a token,
170
+ // but still hides the tokens when the user blurs the input by tabbing out or clicking somewhere else on the page
171
+
172
+ setTimeout(() => {
173
+ var _containerRef$current5;
174
+
175
+ if (!((_containerRef$current5 = containerRef.current) !== null && _containerRef$current5 !== void 0 && _containerRef$current5.contains(document.activeElement)) && visibleTokenCount) {
176
+ setTokensAreTruncated(true);
177
+ }
178
+ }, 0);
143
179
  };
144
180
 
145
181
  const handleInputKeyDown = e => {
@@ -177,6 +213,17 @@ function TextInputWithTokensInnerComponent({
177
213
  }
178
214
  };
179
215
 
216
+ const focusInput = () => {
217
+ var _combinedInputRef$cur;
218
+
219
+ (_combinedInputRef$cur = combinedInputRef.current) === null || _combinedInputRef$cur === void 0 ? void 0 : _combinedInputRef$cur.focus();
220
+ };
221
+
222
+ const preventTokenClickPropagation = event => {
223
+ event.stopPropagation();
224
+ };
225
+
226
+ const visibleTokens = tokensAreTruncated ? tokens.slice(0, visibleTokenCount) : tokens;
180
227
  return /*#__PURE__*/_react.default.createElement(_TextInputWrapper.default, {
181
228
  block: block,
182
229
  className: className,
@@ -188,6 +235,7 @@ function TextInputWithTokensInnerComponent({
188
235
  minWidth: minWidthProp,
189
236
  maxWidth: maxWidthProp,
190
237
  variant: variantProp,
238
+ onClick: focusInput,
191
239
  sx: { ...(block ? {
192
240
  display: 'flex',
193
241
  width: '100%'
@@ -227,12 +275,13 @@ function TextInputWithTokensInnerComponent({
227
275
  ref: combinedInputRef,
228
276
  disabled: disabled,
229
277
  onFocus: handleInputFocus,
278
+ onBlur: handleInputBlur,
230
279
  onKeyDown: handleInputKeyDown,
231
280
  type: "text",
232
281
  sx: {
233
282
  height: '100%'
234
283
  }
235
- }, inputPropsRest))), tokens.length && TokenComponent ? tokens.map(({
284
+ }, inputPropsRest))), TokenComponent ? visibleTokens.map(({
236
285
  id,
237
286
  ...tokenRest
238
287
  }, i) => /*#__PURE__*/_react.default.createElement(TokenComponent, _extends({
@@ -240,6 +289,7 @@ function TextInputWithTokensInnerComponent({
240
289
  onFocus: handleTokenFocus(i),
241
290
  onBlur: handleTokenBlur,
242
291
  onKeyUp: handleTokenKeyUp,
292
+ onClick: preventTokenClickPropagation,
243
293
  isSelected: selectedTokenIndex === i,
244
294
  onRemove: () => {
245
295
  handleTokenRemove(id);
@@ -247,7 +297,10 @@ function TextInputWithTokensInnerComponent({
247
297
  hideRemoveButton: hideTokenRemoveButtons,
248
298
  size: size,
249
299
  tabIndex: 0
250
- }, tokenRest))) : null));
300
+ }, tokenRest))) : null, tokensAreTruncated ? /*#__PURE__*/_react.default.createElement(_Text.default, {
301
+ color: "fg.muted",
302
+ fontSize: size && overflowCountFontSizeMap[size]
303
+ }, "+", tokens.length - visibleTokens.length) : null));
251
304
  }
252
305
 
253
306
  TextInputWithTokensInnerComponent.displayName = "TextInputWithTokensInnerComponent";
@@ -39,7 +39,7 @@ const sizeVariants = (0, _styledSystem.variant)({
39
39
  const TextInputWrapper = _styledComponents.default.span.withConfig({
40
40
  displayName: "_TextInputWrapper__TextInputWrapper",
41
41
  componentId: "sc-5vfcis-0"
42
- })(["display:inline-flex;align-items:stretch;min-height:34px;font-size:", ";line-height:20px;color:", ";vertical-align:middle;background-repeat:no-repeat;background-position:right 8px center;border:1px solid ", ";border-radius:", ";outline:none;box-shadow:", ";", " .TextInput-icon{align-self:center;color:", ";margin:0 ", ";flex-shrink:0;}&:focus-within{border-color:", ";box-shadow:", ";}", " ", " ", " @media (min-width:", "){font-size:", ";}", " ", " ", " ", " ", ";"], (0, _constants.get)('fontSizes.1'), (0, _constants.get)('colors.fg.default'), (0, _constants.get)('colors.border.default'), (0, _constants.get)('radii.2'), (0, _constants.get)('shadows.primer.shadow.inset'), props => {
42
+ })(["display:inline-flex;align-items:stretch;min-height:34px;font-size:", ";line-height:20px;color:", ";vertical-align:middle;background-repeat:no-repeat;background-position:right 8px center;border:1px solid ", ";border-radius:", ";outline:none;box-shadow:", ";cursor:text;", " .TextInput-icon{align-self:center;color:", ";margin:0 ", ";flex-shrink:0;}&:focus-within{border-color:", ";box-shadow:", ";}", " ", " ", " @media (min-width:", "){font-size:", ";}", " ", " ", " ", " ", ";"], (0, _constants.get)('fontSizes.1'), (0, _constants.get)('colors.fg.default'), (0, _constants.get)('colors.border.default'), (0, _constants.get)('radii.2'), (0, _constants.get)('shadows.primer.shadow.inset'), props => {
43
43
  if (props.hasIcon) {
44
44
  return (0, _styledComponents.css)(["padding:0;"]);
45
45
  } else {
@@ -1,24 +1,25 @@
1
1
  import * as History from 'history';
2
2
  import React from 'react';
3
- import { SystemCommonProps, SystemFlexProps } from './constants';
4
3
  import { SxProp } from './sx';
5
4
  import { ComponentProps } from './utils/types';
6
- declare const BreadcrumbsBase: import("styled-components").StyledComponent<"nav", any, SystemFlexProps & SystemCommonProps & SxProp, never>;
7
- export declare type BreadcrumbsProps = ComponentProps<typeof BreadcrumbsBase>;
8
- declare function Breadcrumbs({ className, children, theme, ...rest }: React.PropsWithChildren<BreadcrumbsProps>): JSX.Element;
5
+ declare const BreadcrumbsBase: import("styled-components").StyledComponent<"nav", any, SxProp, never>;
6
+ export declare type BreadcrumbsProps = React.PropsWithChildren<{
7
+ className?: string;
8
+ } & SxProp>;
9
+ declare function Breadcrumbs({ className, children, sx: sxProp }: React.PropsWithChildren<BreadcrumbsProps>): JSX.Element;
9
10
  declare namespace Breadcrumbs {
10
11
  var displayName: string;
11
12
  }
12
13
  declare const BreadcrumbsItem: import("styled-components").StyledComponent<"a", any, {
13
14
  to?: History.LocationDescriptor<unknown> | undefined;
14
15
  selected?: boolean | undefined;
15
- } & SystemCommonProps & SxProp, never>;
16
+ } & SxProp, never>;
16
17
  export declare type BreadcrumbsItemProps = ComponentProps<typeof BreadcrumbsItem>;
17
18
  declare const _default: typeof Breadcrumbs & {
18
19
  Item: import("styled-components").StyledComponent<"a", any, {
19
20
  to?: History.LocationDescriptor<unknown> | undefined;
20
21
  selected?: boolean | undefined;
21
- } & SystemCommonProps & SxProp, never>;
22
+ } & SxProp, never>;
22
23
  };
23
24
  export default _default;
24
25
  /**
@@ -28,7 +29,7 @@ export declare const Breadcrumb: typeof Breadcrumbs & {
28
29
  Item: import("styled-components").StyledComponent<"a", any, {
29
30
  to?: History.LocationDescriptor<unknown> | undefined;
30
31
  selected?: boolean | undefined;
31
- } & SystemCommonProps & SxProp, never>;
32
+ } & SxProp, never>;
32
33
  };
33
34
  /**
34
35
  * @deprecated Use the `BreadcrumbsProps` type instead
@@ -1,11 +1,9 @@
1
- function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
-
3
1
  import classnames from 'classnames'; // eslint-disable-next-line import/no-namespace
4
2
 
5
3
  import React from 'react';
6
4
  import styled from 'styled-components';
7
5
  import Box from './Box';
8
- import { COMMON, FLEX, get } from './constants';
6
+ import { get } from './constants';
9
7
  import sx from './sx';
10
8
  const SELECTED_CLASS = 'selected';
11
9
  const Wrapper = styled.li.withConfig({
@@ -15,22 +13,19 @@ const Wrapper = styled.li.withConfig({
15
13
  const BreadcrumbsBase = styled.nav.withConfig({
16
14
  displayName: "Breadcrumbs__BreadcrumbsBase",
17
15
  componentId: "hwwoo0-1"
18
- })(["display:flex;justify-content:space-between;", ";", ";", ";"], COMMON, FLEX, sx);
16
+ })(["display:flex;justify-content:space-between;", ";"], sx);
19
17
 
20
18
  function Breadcrumbs({
21
19
  className,
22
20
  children,
23
- theme,
24
- ...rest
21
+ sx: sxProp
25
22
  }) {
26
- const wrappedChildren = React.Children.map(children, child => /*#__PURE__*/React.createElement(Wrapper, {
27
- theme: theme
28
- }, child));
29
- return /*#__PURE__*/React.createElement(BreadcrumbsBase, _extends({
23
+ const wrappedChildren = React.Children.map(children, child => /*#__PURE__*/React.createElement(Wrapper, null, child));
24
+ return /*#__PURE__*/React.createElement(BreadcrumbsBase, {
30
25
  className: className,
31
26
  "aria-label": "Breadcrumbs",
32
- theme: theme
33
- }, rest), /*#__PURE__*/React.createElement(Box, {
27
+ sx: sxProp
28
+ }, /*#__PURE__*/React.createElement(Box, {
34
29
  as: "ol",
35
30
  my: 0,
36
31
  pl: 0
@@ -45,7 +40,7 @@ const BreadcrumbsItem = styled.a.attrs(props => ({
45
40
  })).withConfig({
46
41
  displayName: "Breadcrumbs__BreadcrumbsItem",
47
42
  componentId: "hwwoo0-2"
48
- })(["color:", ";display:inline-block;font-size:", ";text-decoration:none;&:hover{text-decoration:underline;}&.selected{color:", ";pointer-events:none;}", " ", ";"], get('colors.accent.fg'), get('fontSizes.1'), get('colors.fg.default'), COMMON, sx);
43
+ })(["color:", ";display:inline-block;font-size:", ";text-decoration:none;&:hover{text-decoration:underline;}&.selected{color:", ";pointer-events:none;}", ";"], get('colors.accent.fg'), get('fontSizes.1'), get('colors.fg.default'), sx);
49
44
  Breadcrumbs.displayName = 'Breadcrumbs';
50
45
  BreadcrumbsItem.displayName = 'Breadcrumbs.Item';
51
46
  export default Object.assign(Breadcrumbs, {
@@ -32,6 +32,10 @@ declare const TextInputWithTokens: React.ForwardRefExoticComponent<Pick<{
32
32
  * Whether the remove buttons should be rendered in the tokens
33
33
  */
34
34
  hideTokenRemoveButtons?: boolean | undefined;
35
+ /**
36
+ * The number of tokens to display before truncating
37
+ */
38
+ visibleTokenCount?: number | undefined;
35
39
  } & Pick<Omit<Pick<{
36
40
  [x: string]: any;
37
41
  [x: number]: any;
@@ -10,9 +10,16 @@ import { useProvidedRefOrCreate } from './hooks';
10
10
  import UnstyledTextInput from './_UnstyledTextInput';
11
11
  import TextInputWrapper from './_TextInputWrapper';
12
12
  import Box from './Box';
13
+ import Text from './Text';
13
14
  import { isFocusable } from './utils/iterateFocusableElements'; // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
15
 
15
- // using forwardRef is important so that other components (ex. Autocomplete) can use the ref
16
+ const overflowCountFontSizeMap = {
17
+ small: 0,
18
+ medium: 1,
19
+ large: 1,
20
+ extralarge: 2
21
+ }; // using forwardRef is important so that other components (ex. Autocomplete) can use the ref
22
+
16
23
  function TextInputWithTokensInnerComponent({
17
24
  icon: IconComponent,
18
25
  contrast,
@@ -32,9 +39,11 @@ function TextInputWithTokensInnerComponent({
32
39
  minWidth: minWidthProp,
33
40
  maxWidth: maxWidthProp,
34
41
  variant: variantProp,
42
+ visibleTokenCount,
35
43
  ...rest
36
44
  }, externalRef) {
37
45
  const {
46
+ onBlur,
38
47
  onFocus,
39
48
  onKeyDown,
40
49
  ...inputPropsRest
@@ -43,6 +52,7 @@ function TextInputWithTokensInnerComponent({
43
52
  const localInputRef = useRef(null);
44
53
  const combinedInputRef = useCombinedRefs(localInputRef, ref);
45
54
  const [selectedTokenIndex, setSelectedTokenIndex] = useState();
55
+ const [tokensAreTruncated, setTokensAreTruncated] = useState(Boolean(visibleTokenCount));
46
56
  const {
47
57
  containerRef
48
58
  } = useFocusZone({
@@ -103,20 +113,45 @@ function TextInputWithTokensInnerComponent({
103
113
  };
104
114
 
105
115
  const handleTokenBlur = () => {
106
- setSelectedTokenIndex(undefined);
116
+ setSelectedTokenIndex(undefined); // HACK: wait a tick and check the focused element before hiding truncated tokens
117
+ // this prevents the tokens from hiding when the user is moving focus between tokens,
118
+ // but still hides the tokens when the user blurs the token by tabbing out or clicking somewhere else on the page
119
+
120
+ setTimeout(() => {
121
+ var _containerRef$current4;
122
+
123
+ if (!((_containerRef$current4 = containerRef.current) !== null && _containerRef$current4 !== void 0 && _containerRef$current4.contains(document.activeElement)) && visibleTokenCount) {
124
+ setTokensAreTruncated(true);
125
+ }
126
+ }, 0);
107
127
  };
108
128
 
109
- const handleTokenKeyUp = e => {
110
- if (e.key === 'Escape') {
129
+ const handleTokenKeyUp = event => {
130
+ if (event.key === 'Escape') {
111
131
  var _ref$current2;
112
132
 
113
133
  (_ref$current2 = ref.current) === null || _ref$current2 === void 0 ? void 0 : _ref$current2.focus();
114
134
  }
115
135
  };
116
136
 
117
- const handleInputFocus = e => {
118
- onFocus && onFocus(e);
137
+ const handleInputFocus = event => {
138
+ onFocus && onFocus(event);
119
139
  setSelectedTokenIndex(undefined);
140
+ visibleTokenCount && setTokensAreTruncated(false);
141
+ };
142
+
143
+ const handleInputBlur = event => {
144
+ onBlur && onBlur(event); // HACK: wait a tick and check the focused element before hiding truncated tokens
145
+ // this prevents the tokens from hiding when the user is moving focus from the input to a token,
146
+ // but still hides the tokens when the user blurs the input by tabbing out or clicking somewhere else on the page
147
+
148
+ setTimeout(() => {
149
+ var _containerRef$current5;
150
+
151
+ if (!((_containerRef$current5 = containerRef.current) !== null && _containerRef$current5 !== void 0 && _containerRef$current5.contains(document.activeElement)) && visibleTokenCount) {
152
+ setTokensAreTruncated(true);
153
+ }
154
+ }, 0);
120
155
  };
121
156
 
122
157
  const handleInputKeyDown = e => {
@@ -154,6 +189,17 @@ function TextInputWithTokensInnerComponent({
154
189
  }
155
190
  };
156
191
 
192
+ const focusInput = () => {
193
+ var _combinedInputRef$cur;
194
+
195
+ (_combinedInputRef$cur = combinedInputRef.current) === null || _combinedInputRef$cur === void 0 ? void 0 : _combinedInputRef$cur.focus();
196
+ };
197
+
198
+ const preventTokenClickPropagation = event => {
199
+ event.stopPropagation();
200
+ };
201
+
202
+ const visibleTokens = tokensAreTruncated ? tokens.slice(0, visibleTokenCount) : tokens;
157
203
  return /*#__PURE__*/React.createElement(TextInputWrapper, {
158
204
  block: block,
159
205
  className: className,
@@ -165,6 +211,7 @@ function TextInputWithTokensInnerComponent({
165
211
  minWidth: minWidthProp,
166
212
  maxWidth: maxWidthProp,
167
213
  variant: variantProp,
214
+ onClick: focusInput,
168
215
  sx: { ...(block ? {
169
216
  display: 'flex',
170
217
  width: '100%'
@@ -204,12 +251,13 @@ function TextInputWithTokensInnerComponent({
204
251
  ref: combinedInputRef,
205
252
  disabled: disabled,
206
253
  onFocus: handleInputFocus,
254
+ onBlur: handleInputBlur,
207
255
  onKeyDown: handleInputKeyDown,
208
256
  type: "text",
209
257
  sx: {
210
258
  height: '100%'
211
259
  }
212
- }, inputPropsRest))), tokens.length && TokenComponent ? tokens.map(({
260
+ }, inputPropsRest))), TokenComponent ? visibleTokens.map(({
213
261
  id,
214
262
  ...tokenRest
215
263
  }, i) => /*#__PURE__*/React.createElement(TokenComponent, _extends({
@@ -217,6 +265,7 @@ function TextInputWithTokensInnerComponent({
217
265
  onFocus: handleTokenFocus(i),
218
266
  onBlur: handleTokenBlur,
219
267
  onKeyUp: handleTokenKeyUp,
268
+ onClick: preventTokenClickPropagation,
220
269
  isSelected: selectedTokenIndex === i,
221
270
  onRemove: () => {
222
271
  handleTokenRemove(id);
@@ -224,7 +273,10 @@ function TextInputWithTokensInnerComponent({
224
273
  hideRemoveButton: hideTokenRemoveButtons,
225
274
  size: size,
226
275
  tabIndex: 0
227
- }, tokenRest))) : null));
276
+ }, tokenRest))) : null, tokensAreTruncated ? /*#__PURE__*/React.createElement(Text, {
277
+ color: "fg.muted",
278
+ fontSize: size && overflowCountFontSizeMap[size]
279
+ }, "+", tokens.length - visibleTokens.length) : null));
228
280
  }
229
281
 
230
282
  TextInputWithTokensInnerComponent.displayName = "TextInputWithTokensInnerComponent";
@@ -21,7 +21,7 @@ const sizeVariants = variant({
21
21
  const TextInputWrapper = styled.span.withConfig({
22
22
  displayName: "_TextInputWrapper__TextInputWrapper",
23
23
  componentId: "sc-5vfcis-0"
24
- })(["display:inline-flex;align-items:stretch;min-height:34px;font-size:", ";line-height:20px;color:", ";vertical-align:middle;background-repeat:no-repeat;background-position:right 8px center;border:1px solid ", ";border-radius:", ";outline:none;box-shadow:", ";", " .TextInput-icon{align-self:center;color:", ";margin:0 ", ";flex-shrink:0;}&:focus-within{border-color:", ";box-shadow:", ";}", " ", " ", " @media (min-width:", "){font-size:", ";}", " ", " ", " ", " ", ";"], get('fontSizes.1'), get('colors.fg.default'), get('colors.border.default'), get('radii.2'), get('shadows.primer.shadow.inset'), props => {
24
+ })(["display:inline-flex;align-items:stretch;min-height:34px;font-size:", ";line-height:20px;color:", ";vertical-align:middle;background-repeat:no-repeat;background-position:right 8px center;border:1px solid ", ";border-radius:", ";outline:none;box-shadow:", ";cursor:text;", " .TextInput-icon{align-self:center;color:", ";margin:0 ", ";flex-shrink:0;}&:focus-within{border-color:", ";box-shadow:", ";}", " ", " ", " @media (min-width:", "){font-size:", ";}", " ", " ", " ", " ", ";"], get('fontSizes.1'), get('colors.fg.default'), get('colors.border.default'), get('radii.2'), get('shadows.primer.shadow.inset'), props => {
25
25
  if (props.hasIcon) {
26
26
  return css(["padding:0;"]);
27
27
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primer/components",
3
- "version": "0.0.0-2021927184638",
3
+ "version": "0.0.0-2021927202224",
4
4
  "description": "Primer react components",
5
5
  "main": "lib/index.js",
6
6
  "module": "lib-esm/index.js",