@skyscanner/backpack-web 38.9.0 → 38.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -44,47 +44,49 @@ class AnimateHeight extends Component {
44
44
  this.contentElement.style.display = 'none';
45
45
  }
46
46
  }
47
- UNSAFE_componentWillReceiveProps(nextProps) {
47
+ componentDidUpdate(prevProps, prevState) {
48
48
  const {
49
- height
49
+ duration,
50
+ height,
51
+ transitionOverflow
50
52
  } = this.props;
51
53
 
52
54
  // Check if 'height' prop has changed
53
- if (this.contentElement && nextProps.height !== height) {
55
+ if (this.contentElement && height !== prevProps.height) {
54
56
  // Cache content height
55
57
  this.contentElement.style.display = '';
56
- this.contentElement.style.overflow = this.props.transitionOverflow;
58
+ this.contentElement.style.overflow = transitionOverflow;
57
59
  const contentHeight = this.contentElement.offsetHeight;
58
60
  this.contentElement.style.overflow = '';
59
61
  let newHeight = null;
60
62
  let shouldSetTimeout = false;
61
63
  let timeoutHeight = null;
62
- let timeoutOverflow = this.props.transitionOverflow;
63
- let timeoutDuration = nextProps.duration;
64
+ let timeoutOverflow = transitionOverflow;
65
+ let timeoutDuration = duration;
64
66
  clearTimeout(this.timeoutID);
65
- if (isNumber(nextProps.height)) {
67
+ if (isNumber(height)) {
66
68
  // If new height is a number
67
- newHeight = nextProps.height < 0 ? 0 : nextProps.height;
69
+ newHeight = height < 0 ? 0 : height;
68
70
  } else {
69
- // If not, animate to content height
70
- // and then reset to auto
71
+ // If not, animate to content height and then reset to auto
71
72
  newHeight = contentHeight;
72
73
  shouldSetTimeout = true;
73
74
  timeoutHeight = 'auto';
74
75
  timeoutOverflow = 'visible';
75
76
  }
76
- if (this.state.height === 'auto') {
77
- // If previous height was 'auto'
78
- // set it explicitly to be able to use transition
77
+
78
+ // If previous height was 'auto'
79
+ // set it explicitly to be able to use transition
80
+ if (prevState.height === 'auto') {
79
81
  shouldSetTimeout = true;
80
82
  timeoutHeight = newHeight;
81
83
  newHeight = contentHeight;
82
84
  timeoutDuration = 50;
83
85
  }
84
- this.setState((state, props) => ({
86
+ this.setState({
85
87
  height: newHeight,
86
- overflow: props.transitionOverflow
87
- }));
88
+ overflow: transitionOverflow
89
+ });
88
90
  if (shouldSetTimeout) {
89
91
  this.timeoutID = setTimeout(() => {
90
92
  this.setState({
@@ -1,4 +1,4 @@
1
- import type { ReactElement, HTMLProps, InputHTMLAttributes, Ref } from 'react';
1
+ import type { ReactElement, HTMLProps, InputHTMLAttributes, Ref, SyntheticEvent } from 'react';
2
2
  export type BpkAutoSuggestTheme = {
3
3
  container?: string;
4
4
  containerOpen?: string;
@@ -19,6 +19,7 @@ export type BpkAutoSuggestTheme = {
19
19
  export type EnterKeyHintType = 'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send';
20
20
  export type BpkInputRenderProps = InputHTMLAttributes<HTMLInputElement> & {
21
21
  ref?: Ref<HTMLInputElement>;
22
+ onClear?: (e: SyntheticEvent<HTMLButtonElement>) => void;
22
23
  };
23
24
  export type BpkAutoSuggestProps<T> = {
24
25
  suggestions: T[];
@@ -85,7 +85,7 @@ const BpkAutosuggest = /*#__PURE__*/forwardRef(({
85
85
  changes,
86
86
  type
87
87
  } = actionAndChanges;
88
- const shouldForceKeepOpen = alwaysRenderSuggestions && state.inputValue && state.inputValue.length > 0 && hasSuggestions && changes.isOpen === false;
88
+ const shouldForceKeepOpen = alwaysRenderSuggestions && hasSuggestions && changes.isOpen === false;
89
89
  if (shouldForceKeepOpen) {
90
90
  return {
91
91
  ...changes,
@@ -135,12 +135,12 @@ const BpkAutosuggest = /*#__PURE__*/forwardRef(({
135
135
  method: type,
136
136
  newValue: newInputValue ?? ''
137
137
  });
138
- if (newInputValue?.length) {
138
+ if (newInputValue?.length > 0) {
139
139
  if (newIsOpen) {
140
140
  onSuggestionsFetchRequested(newInputValue);
141
141
  }
142
- } else if (suggestionsCount) {
143
- onSuggestionsClearRequested();
142
+ } else {
143
+ onSuggestionsFetchRequested('');
144
144
  }
145
145
  },
146
146
  onSelectedItemChange(changes) {
@@ -171,7 +171,7 @@ const BpkAutosuggest = /*#__PURE__*/forwardRef(({
171
171
  refs
172
172
  } = useFloating({
173
173
  placement: 'bottom-start',
174
- middleware: isDesktop ? [offset(17), flip(), shift(), size({
174
+ middleware: isDesktop ? [offset(4), flip(), shift(), size({
175
175
  apply({
176
176
  elements,
177
177
  rects
@@ -222,6 +222,8 @@ const BpkAutosuggest = /*#__PURE__*/forwardRef(({
222
222
  if (!isOpen && inputValue.length) {
223
223
  onSuggestionsFetchRequested(inputValue);
224
224
  openMenu();
225
+ } else if (alwaysRenderSuggestions && !inputValue) {
226
+ onSuggestionsFetchRequested('');
225
227
  } else {
226
228
  onClick?.();
227
229
  }
@@ -232,22 +234,6 @@ const BpkAutosuggest = /*#__PURE__*/forwardRef(({
232
234
  onLoad?.(inputValue);
233
235
  }
234
236
  };
235
- const onKeyDown = e => {
236
- if (e.key !== 'Enter') {
237
- return;
238
- }
239
- if (e.key === 'Enter' && suggestionsCount) {
240
- onSuggestionSelected?.({
241
- suggestion: suggestions[0],
242
- inputValue
243
- });
244
- }
245
- if (defaultValue) {
246
- handleInputInteraction();
247
- } else if (!hasSuggestions) {
248
- onSuggestionSelected?.();
249
- }
250
- };
251
237
  const handleSuggestionClick = () => {
252
238
  if (!focusInputOnSuggestionClick) {
253
239
  document.activeElement?.blur?.();
@@ -256,6 +242,10 @@ const BpkAutosuggest = /*#__PURE__*/forwardRef(({
256
242
  const clearSuggestions = e => {
257
243
  e?.stopPropagation();
258
244
  setInputValue('');
245
+ if (alwaysRenderSuggestions) {
246
+ hasLoadedInitiallyRef.current = true;
247
+ onSuggestionsFetchRequested('');
248
+ }
259
249
  };
260
250
 
261
251
  // Render suggestions function to render single section suggestion
@@ -309,7 +299,7 @@ const BpkAutosuggest = /*#__PURE__*/forwardRef(({
309
299
  className: theme.sectionContainer,
310
300
  role: "group",
311
301
  "aria-labelledby": sectionId,
312
- children: [/*#__PURE__*/_jsx("div", {
302
+ children: [sectionTitleElement && /*#__PURE__*/_jsx("div", {
313
303
  id: sectionId,
314
304
  className: theme.sectionTitle,
315
305
  children: sectionTitleElement
@@ -338,7 +328,6 @@ const BpkAutosuggest = /*#__PURE__*/forwardRef(({
338
328
  value,
339
329
  ...finalInputProps
340
330
  } = getInputProps({
341
- onKeyDown,
342
331
  ref: forwardedRef,
343
332
  onClick: handleInputInteraction,
344
333
  onFocus: handleInputInteraction,
@@ -348,7 +337,7 @@ const BpkAutosuggest = /*#__PURE__*/forwardRef(({
348
337
  ...restInputProps
349
338
  });
350
339
  const setInputRef = node => {
351
- refs.setReference(node);
340
+ if (refs.reference?.current === node) return;
352
341
 
353
342
  // convert input ref from Downshift
354
343
  if (typeof downshiftInputRef === 'function') {
@@ -357,12 +346,6 @@ const BpkAutosuggest = /*#__PURE__*/forwardRef(({
357
346
  downshiftInputRef.current = node;
358
347
  }
359
348
  };
360
- let normalizedInputValue = '';
361
- if (Array.isArray(value)) {
362
- normalizedInputValue = value.join(', ');
363
- } else if (typeof value === 'string' || typeof value === 'number') {
364
- normalizedInputValue = value;
365
- }
366
349
  if (renderInputComponent) {
367
350
  return renderInputComponent({
368
351
  ref: setInputRef,
@@ -386,21 +369,28 @@ const BpkAutosuggest = /*#__PURE__*/forwardRef(({
386
369
  }), /*#__PURE__*/_jsx("div", {
387
370
  className: getClassName(theme.inputWrapper),
388
371
  children: /*#__PURE__*/_jsx(BpkInput, {
389
- value: normalizedInputValue,
372
+ value: inputValue,
390
373
  inputRef: setInputRef,
391
374
  clearButtonMode: showClear ? 'whileEditing' : 'never',
392
375
  clearButtonLabel: ariaLabels?.clearButton || 'Clear input',
393
- onClear: clearSuggestions,
394
376
  name: inputName || id,
395
377
  id: id,
396
378
  ...finalInputProps,
397
- enterKeyHint: enterKeyHint
379
+ enterKeyHint: enterKeyHint,
380
+ onClear: clearSuggestions
398
381
  })
399
382
  })]
400
383
  })
401
384
  });
402
385
  };
386
+ const containerWrapperRef = useRef(null);
387
+ useEffect(() => {
388
+ if (containerWrapperRef.current) {
389
+ refs.setReference(containerWrapperRef.current);
390
+ }
391
+ }, [refs]);
403
392
  return /*#__PURE__*/_jsxs("div", {
393
+ ref: containerWrapperRef,
404
394
  className: getClassName(theme.container, suggestionsCount && theme.containerOpen),
405
395
  children: [renderInput(), showSuggestions && (isDesktop ? /*#__PURE__*/_jsx(FloatingPortal, {
406
396
  children: /*#__PURE__*/_jsxs("div", {
@@ -15,4 +15,4 @@
15
15
  * See the License for the specific language governing permissions and
16
16
  * limitations under the License.
17
17
  */
18
- .bpk-autosuggest__input{width:100%}.bpk-autosuggest__suggestions-container{border:.0625rem solid #e0e4e9;border-radius:.5rem;background-color:#fff}.bpk-autosuggest__arrow{width:1.5rem;height:1.5rem;fill:#fff}.bpk-autosuggest__arrow[data-hide]{visibility:hidden}.bpk-autosuggest__suggestions-list{min-width:fit-content;margin:0;padding:0;border-radius:.5rem;background-color:#fff;list-style:none;box-shadow:0px 4px 14px 0px rgba(37,32,31,.25);overflow:hidden}.bpk-autosuggest__suggestion-item{cursor:pointer;margin:0;font-size:1rem;line-height:1.5rem;font-weight:400}.bpk-autosuggest__suggestion-item:not(:last-child){box-shadow:0 -1px 0 0 #c1c7cf inset}.bpk-autosuggest__suggestion-item:active{background-color:#eff3f8}.bpk-autosuggest__suggestion-item--highlighted{background-color:#eff3f8}.bpk-autosuggest__suggestion{display:table;width:100%;padding:1rem}.bpk-autosuggest__suggestion--indent{padding-left:2rem}.bpk-autosuggest__suggestion-icon{display:table-cell;margin-right:.5rem;vertical-align:top;fill:#626971}html[dir=rtl] .bpk-autosuggest__suggestion-icon{margin-right:0;margin-left:.5rem}.bpk-autosuggest__suggestion-content{display:table-cell;width:100%;vertical-align:top}.bpk-autosuggest__suggestion-inner{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:space-between}.bpk-autosuggest__suggestion-value{display:block}.bpk-autosuggest__suggestion-sub-heading{display:table-cell;width:100%;vertical-align:top;margin:0;font-size:.75rem;line-height:1rem;font-weight:400}.bpk-autosuggest__suggestion-tertiary-label{display:table-cell;align-self:center;color:#626971;vertical-align:top;word-break:keep-all;margin:0;font-size:.75rem;line-height:1rem;font-weight:400}.bpk-autosuggest__section-container:not(:first-of-type){border-top:1px solid #c1c7cf}.bpk-autosuggest__visuallyhidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;white-space:nowrap;overflow:hidden;clip:rect(0 0 0 0)}
18
+ .bpk-autosuggest__input{width:100%}.bpk-autosuggest__suggestions-container{margin-top:.75rem;border:.0625rem solid #e0e4e9;border-radius:.5rem;background-color:#fff}.bpk-autosuggest__arrow{width:1.5rem;height:1.5rem;fill:#fff}.bpk-autosuggest__arrow[data-hide]{visibility:hidden}.bpk-autosuggest__suggestions-list{min-width:fit-content;margin:0;padding:0;border-radius:.5rem;background-color:#fff;list-style:none;box-shadow:0px 4px 14px 0px rgba(37,32,31,.25);overflow:hidden}.bpk-autosuggest__suggestion-item{cursor:pointer;margin:0;font-size:1rem;line-height:1.5rem;font-weight:400}.bpk-autosuggest__suggestion-item:not(:last-child){box-shadow:0 -1px 0 0 #c1c7cf inset}.bpk-autosuggest__suggestion-item:active{background-color:#eff3f8}.bpk-autosuggest__suggestion-item--highlighted{background-color:#eff3f8}.bpk-autosuggest__suggestion{display:table;width:100%;padding:1rem}.bpk-autosuggest__suggestion--indent{padding-left:2rem}.bpk-autosuggest__suggestion-icon{display:table-cell;margin-right:.5rem;vertical-align:top;fill:#626971}html[dir=rtl] .bpk-autosuggest__suggestion-icon{margin-right:0;margin-left:.5rem}.bpk-autosuggest__suggestion-content{display:table-cell;width:100%;vertical-align:top}.bpk-autosuggest__suggestion-inner{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:space-between}.bpk-autosuggest__suggestion-value{display:block}.bpk-autosuggest__suggestion-sub-heading{display:table-cell;width:100%;vertical-align:top;margin:0;font-size:.75rem;line-height:1rem;font-weight:400}.bpk-autosuggest__suggestion-tertiary-label{display:table-cell;align-self:center;color:#626971;vertical-align:top;word-break:keep-all;margin:0;font-size:.75rem;line-height:1rem;font-weight:400}.bpk-autosuggest__section-container:not(:first-of-type){border-top:1px solid #c1c7cf}.bpk-autosuggest__visuallyhidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;white-space:nowrap;overflow:hidden;clip:rect(0 0 0 0)}
@@ -25,7 +25,6 @@ declare class BpkBackgroundImage extends Component<BpkBackgroundImageProps> {
25
25
  };
26
26
  constructor(props: BpkBackgroundImageProps);
27
27
  componentDidMount(): void;
28
- UNSAFE_componentWillReceiveProps(newProps: BpkBackgroundImageProps): void;
29
28
  componentDidUpdate(prevProps: BpkBackgroundImageProps): void;
30
29
  onBackgroundImageError: () => void;
31
30
  onBackgroundImageLoad: () => void;
@@ -43,13 +43,12 @@ class BpkBackgroundImage extends Component {
43
43
  this.startImageLoad();
44
44
  }
45
45
  }
46
- UNSAFE_componentWillReceiveProps(newProps) {
47
- if (!this.props.inView && newProps.inView) {
48
- this.startImageLoad();
49
- }
50
- }
51
46
  componentDidUpdate(prevProps) {
52
- if (prevProps.src !== this.props.src) {
47
+ const {
48
+ inView,
49
+ src
50
+ } = this.props;
51
+ if (prevProps.src !== src || inView && !prevProps.inView) {
53
52
  this.startImageLoad();
54
53
  }
55
54
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyscanner/backpack-web",
3
- "version": "38.9.0",
3
+ "version": "38.10.0",
4
4
  "description": "Backpack Design System web library",
5
5
  "repository": {
6
6
  "type": "git",