@skyscanner/backpack-web 36.4.0 → 36.5.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.
@@ -21,6 +21,7 @@ export type Props = DefaultProps & {
21
21
  };
22
22
  type DefaultProps = {
23
23
  className?: string | null;
24
+ isoLabel?: string;
24
25
  isBlocked?: boolean;
25
26
  isFocused?: boolean;
26
27
  isKeyboardFocusable?: boolean;
@@ -120,6 +120,7 @@ class BpkCalendarDate extends PureComponent {
120
120
  classNames.push(className);
121
121
  }
122
122
  delete buttonProps.preventKeyboardFocus;
123
+ delete buttonProps.isoLabel;
123
124
  return /*#__PURE__*/_jsx("button", {
124
125
  type: "button",
125
126
  style: style,
@@ -33,12 +33,18 @@ export type Props = DefaultProps & {
33
33
  */
34
34
  weekStartsOn: 0 | 1 | 2 | 3 | 4 | 5 | 6;
35
35
  };
36
+ export type DateProps = {
37
+ val: Date;
38
+ customLabel: string | Date;
39
+ isoLabel: string;
40
+ };
36
41
  type State = {
37
- calendarMonthWeeks: Date[][];
42
+ calendarMonthWeeks: DateProps[][];
38
43
  };
39
44
  declare class BpkCalendarGrid extends Component<Props, State> {
40
45
  static defaultProps: DefaultProps;
41
46
  constructor(props: Props);
47
+ componentDidMount(): void;
42
48
  UNSAFE_componentWillReceiveProps(nextProps: Props): void;
43
49
  render(): import("react/jsx-runtime").JSX.Element;
44
50
  }
@@ -18,11 +18,11 @@
18
18
 
19
19
  import { Component } from 'react';
20
20
  import { cssModules, isDeviceIos } from "../../bpk-react-utils";
21
+ import deferCallback from "../../bpk-react-utils/src/deferCallback";
21
22
  import { addCalendarGridTransition } from "./BpkCalendarGridTransition";
22
23
  import BpkCalendarWeek from "./BpkCalendarWeek";
23
24
  import { CALENDAR_SELECTION_TYPE } from "./custom-proptypes";
24
- import { addMonths, formatIsoDate, getCalendarMonthWeeks, isSameMonth } from "./date-utils";
25
- import { memoize } from "./utils";
25
+ import { addMonths, getCalendar, getCalendarNoCustomLabel, isSameMonth } from "./date-utils";
26
26
  import STYLES from "./BpkCalendarGrid.module.css";
27
27
 
28
28
  // This should be imported after `./BpkCalendarGrid.module.css`.
@@ -59,17 +59,22 @@ class BpkCalendarGrid extends Component {
59
59
  };
60
60
  constructor(props) {
61
61
  super(props);
62
-
63
- // We cache expensive calculations (and identities) in state
64
62
  this.state = {
65
- calendarMonthWeeks: getCalendarMonthWeeks(props.month, props.weekStartsOn)
63
+ // Do not run expensive date formatting in the constructor
64
+ calendarMonthWeeks: getCalendarNoCustomLabel(props.month, props.weekStartsOn)
66
65
  };
67
66
  }
67
+ componentDidMount() {
68
+ // Defer expensive date formatting until after render to improve INP.
69
+ deferCallback(() => this.setState({
70
+ calendarMonthWeeks: getCalendar(this.props.month, this.props.weekStartsOn, this.props.formatDateFull)
71
+ }));
72
+ }
68
73
  UNSAFE_componentWillReceiveProps(nextProps) {
69
74
  // We cache expensive calculations (and identities) in state
70
75
  if (!isSameMonth(nextProps.month, this.props.month) || nextProps.weekStartsOn !== this.props.weekStartsOn) {
71
76
  this.setState({
72
- calendarMonthWeeks: getCalendarMonthWeeks(nextProps.month, nextProps.weekStartsOn)
77
+ calendarMonthWeeks: getCalendar(nextProps.month, nextProps.weekStartsOn, nextProps.formatDateFull)
73
78
  });
74
79
  }
75
80
  }
@@ -81,7 +86,6 @@ class BpkCalendarGrid extends Component {
81
86
  dateModifiers,
82
87
  dateProps,
83
88
  focusedDate,
84
- formatDateFull,
85
89
  ignoreOutsideDate,
86
90
  isKeyboardFocusable,
87
91
  markOutsideDays,
@@ -108,7 +112,6 @@ class BpkCalendarGrid extends Component {
108
112
  dates: dates,
109
113
  onDateClick: onDateClick,
110
114
  onDateKeyDown: onDateKeyDown,
111
- formatDateFull: memoize(formatDateFull),
112
115
  DateComponent: DateComponent,
113
116
  dateModifiers: dateModifiers,
114
117
  preventKeyboardFocus: preventKeyboardFocus,
@@ -123,7 +126,7 @@ class BpkCalendarGrid extends Component {
123
126
  ignoreOutsideDate: ignoreOutsideDate,
124
127
  dateProps: dateProps,
125
128
  cellClassName: cellClassName
126
- }, formatIsoDate(dates[0])))
129
+ }, dates[0].isoLabel))
127
130
  })
128
131
  });
129
132
  }
@@ -1,11 +1,11 @@
1
1
  import type { ElementType } from 'react';
2
2
  import { Component } from 'react';
3
+ import type { DateProps } from './BpkCalendarGrid';
3
4
  import type { DateModifiers, SelectionConfiguration } from './custom-proptypes';
4
5
  export type Props = DefaultProps & {
5
6
  DateComponent: ElementType;
6
7
  dateModifiers: DateModifiers;
7
- dates: Date[];
8
- formatDateFull: (date: Date) => Date | string;
8
+ dates: DateProps[];
9
9
  preventKeyboardFocus: boolean;
10
10
  markToday: boolean;
11
11
  markOutsideDays: boolean;
@@ -67,13 +67,12 @@ function getSelectedDate(date, selectionConfiguration) {
67
67
  * Gets the correct selection type for the current date
68
68
  * @param {Date} date the current date of the calendar
69
69
  * @param {Object} selectionConfiguration the current selection configuration
70
- * @param {Function} formatDateFull function to format dates
71
70
  * @param {Date} month the current month of the calendar
72
71
  * @param {Number} weekStartsOn index of the first day of the week
73
72
  * @param {Boolean} ignoreOutsideDate ignore date outside current month
74
73
  * @returns {String} selection type to be passed to the date
75
74
  */
76
- function getSelectionType(date, selectionConfiguration, formatDateFull, month, weekStartsOn, ignoreOutsideDate) {
75
+ function getSelectionType(date, selectionConfiguration, month, weekStartsOn, ignoreOutsideDate) {
77
76
  const {
78
77
  endDate,
79
78
  startDate
@@ -85,7 +84,7 @@ function getSelectionType(date, selectionConfiguration, formatDateFull, month, w
85
84
  const sameEndDay = endDate && isSameDay(date, endDate);
86
85
  const rangeDates = startDate && endDate;
87
86
  const isEmptyCell = !isSameMonth(date, month) && ignoreOutsideDate;
88
- if (selectionConfiguration.type === CALENDAR_SELECTION_TYPE.single && selectionConfiguration.date && (selectionConfiguration.date === formatDateFull(date) || formatDateFull(selectionConfiguration.date) === formatDateFull(date))) {
87
+ if (selectionConfiguration.type === CALENDAR_SELECTION_TYPE.single && selectionConfiguration.date && isSameDay(date, selectionConfiguration.date)) {
89
88
  return SELECTION_TYPES.single;
90
89
  }
91
90
  if (selectionConfiguration.type === CALENDAR_SELECTION_TYPE.range) {
@@ -120,10 +119,10 @@ function getSelectionType(date, selectionConfiguration, formatDateFull, month, w
120
119
  }) && !sameStartDay && !sameEndDay) {
121
120
  return SELECTION_TYPES.middle;
122
121
  }
123
- if (startDate && formatDateFull(startDate) === formatDateFull(date)) {
122
+ if (sameStartDay) {
124
123
  return SELECTION_TYPES.start;
125
124
  }
126
- if (endDate && formatDateFull(endDate) === formatDateFull(date)) {
125
+ if (sameEndDay) {
127
126
  return SELECTION_TYPES.end;
128
127
  }
129
128
  }
@@ -139,9 +138,9 @@ function getSelectionType(date, selectionConfiguration, formatDateFull, month, w
139
138
  const singleDateHandler = (props, nextProps) => {
140
139
  const currentSelectConfig = props.selectionConfiguration;
141
140
  const nextSelectConfig = nextProps.selectionConfiguration;
142
- if ((nextSelectConfig.date && isSameWeek(nextSelectConfig.date, nextProps.dates[0], {
141
+ if ((nextSelectConfig.date && isSameWeek(nextSelectConfig.date, nextProps.dates[0].val, {
143
142
  weekStartsOn: nextProps.weekStartsOn
144
- }) || currentSelectConfig.date && isSameWeek(currentSelectConfig.date, props.dates[0], {
143
+ }) || currentSelectConfig.date && isSameWeek(currentSelectConfig.date, props.dates[0].val, {
145
144
  weekStartsOn: props.weekStartsOn
146
145
  })) && currentSelectConfig.date !== nextSelectConfig.date) {
147
146
  return true;
@@ -190,7 +189,7 @@ class BpkCalendarWeek extends Component {
190
189
  cellClassName: null
191
190
  };
192
191
  shouldComponentUpdate(nextProps) {
193
- const shallowProps = ['DateComponent', 'dateModifiers', 'formatDateFull', 'isKeyboardFocusable', 'markOutsideDays', 'markToday', 'onDateClick', 'onDateKeyDown', 'preventKeyboardFocus', 'weekStartsOn', 'dates', 'cellClassName'];
192
+ const shallowProps = ['DateComponent', 'dateModifiers', 'isKeyboardFocusable', 'markOutsideDays', 'markToday', 'onDateClick', 'onDateKeyDown', 'preventKeyboardFocus', 'weekStartsOn', 'dates', 'cellClassName'];
194
193
 
195
194
  // If any of the props have changed, component should update.
196
195
  if (!shallowEqualProps(this.props, nextProps, shallowProps)) {
@@ -200,9 +199,9 @@ class BpkCalendarWeek extends Component {
200
199
  // If focusedDate is changing, and it'll be included as part
201
200
  // of either the week we're rendering now or the next week
202
201
  // we'll render, component should update.
203
- if ((nextProps.focusedDate && isSameWeek(nextProps.focusedDate, nextProps.dates[0], {
202
+ if ((nextProps.focusedDate && isSameWeek(nextProps.focusedDate, nextProps.dates[0].val, {
204
203
  weekStartsOn: nextProps.weekStartsOn
205
- }) || this.props.focusedDate && isSameWeek(this.props.focusedDate, this.props.dates[0], {
204
+ }) || this.props.focusedDate && isSameWeek(this.props.focusedDate, this.props.dates[0].val, {
206
205
  weekStartsOn: this.props.weekStartsOn
207
206
  })) && this.props.focusedDate !== nextProps.focusedDate) {
208
207
  return true;
@@ -246,7 +245,6 @@ class BpkCalendarWeek extends Component {
246
245
  dateModifiers,
247
246
  dateProps,
248
247
  focusedDate,
249
- formatDateFull,
250
248
  ignoreOutsideDate,
251
249
  isKeyboardFocusable,
252
250
  markOutsideDays,
@@ -261,7 +259,7 @@ class BpkCalendarWeek extends Component {
261
259
  weekStartsOn
262
260
  } = this.props;
263
261
  if (ignoreOutsideDate) {
264
- const daysOutside = this.props.dates.map(date => isSameMonth(date, month));
262
+ const daysOutside = this.props.dates.map(date => isSameMonth(date.val, month));
265
263
  const shouldRender = daysOutside.reduce(or);
266
264
  if (!shouldRender) {
267
265
  return null;
@@ -270,33 +268,34 @@ class BpkCalendarWeek extends Component {
270
268
  return /*#__PURE__*/_jsx("div", {
271
269
  className: getClassName('bpk-calendar-week'),
272
270
  children: this.props.dates.map(date => {
273
- const isBlocked = minDate && maxDate ? !isWithinRange(date, {
271
+ const isBlocked = minDate && maxDate ? !isWithinRange(date.val, {
274
272
  start: minDate,
275
273
  end: maxDate
276
274
  }) : false;
277
- const dateSelectionType = getSelectionType(date, selectionConfiguration, formatDateFull, month, weekStartsOn, ignoreOutsideDate);
275
+ const dateSelectionType = getSelectionType(date.val, selectionConfiguration, month, weekStartsOn, ignoreOutsideDate);
278
276
  return /*#__PURE__*/_jsx(DateContainer, {
279
277
  className: cellClassName,
280
- isEmptyCell: !isSameMonth(date, month) && ignoreOutsideDate,
278
+ isEmptyCell: !isSameMonth(date.val, month) && ignoreOutsideDate,
281
279
  isBlocked: isBlocked,
282
280
  selectionType: dateSelectionType,
283
281
  children: /*#__PURE__*/_jsx(DateComponent, {
284
- date: date,
282
+ date: date.val,
285
283
  modifiers: dateModifiers,
286
- "aria-label": formatDateFull(date),
284
+ "aria-label": date.customLabel,
287
285
  onClick: onDateClick,
288
286
  onDateKeyDown: onDateKeyDown,
289
287
  preventKeyboardFocus: preventKeyboardFocus,
290
288
  isKeyboardFocusable: isKeyboardFocusable,
291
- isFocused: focusedDate && isSameDay(date, focusedDate),
292
- isSelected: getSelectedDate(date, selectionConfiguration),
289
+ isFocused: focusedDate && isSameDay(date.val, focusedDate),
290
+ isSelected: getSelectedDate(date.val, selectionConfiguration),
293
291
  isBlocked: isBlocked,
294
- isOutside: markOutsideDays && !isSameMonth(date, month),
295
- isToday: markToday && isToday(date),
292
+ isOutside: markOutsideDays && !isSameMonth(date.val, month),
293
+ isToday: markToday && isToday(date.val),
296
294
  selectionType: dateSelectionType,
295
+ isoLabel: date.isoLabel,
297
296
  ...dateProps
298
297
  })
299
- }, date.getDate());
298
+ }, date.val.getDate());
300
299
  })
301
300
  });
302
301
  }
@@ -105,7 +105,7 @@ const composeCalendar = (Nav, GridHeader, Grid, CalendarDate) => {
105
105
  DateComponent: CalendarDate,
106
106
  dateModifiers: dateModifiers,
107
107
  daysOfWeek: daysOfWeek,
108
- formatDateFull: formatDateFull,
108
+ formatDateFull: memoize(formatDateFull),
109
109
  formatMonth: memoize(formatMonth),
110
110
  month: month,
111
111
  onDateClick: onDateClick,
@@ -17,9 +17,11 @@ import { lastDayOfMonth } from 'date-fns/lastDayOfMonth';
17
17
  import { parseISO } from 'date-fns/parseISO';
18
18
  import { startOfDay } from 'date-fns/startOfDay';
19
19
  import { startOfMonth } from 'date-fns/startOfMonth';
20
+ import type { DateProps } from './BpkCalendarGrid';
20
21
  import type { DaysOfWeek } from './custom-proptypes';
21
22
  declare function daysInMonth(year: number, month: number): number;
22
- declare function getCalendarMonthWeeks(date: Date, weekStartsOn: number): Date[][];
23
+ declare function getCalendarNoCustomLabel(date: Date, weekStartsOn: number): DateProps[][];
24
+ declare function getCalendar(date: Date, weekStartsOn: number, formatDate: (d: Date) => Date | string): DateProps[][];
23
25
  declare function getLastDayOfWeekend(daysOfWeek: DaysOfWeek): number;
24
26
  declare function getFirstDayOfWeekend(daysOfWeek: DaysOfWeek): number;
25
27
  declare const orderDaysOfWeek: (daysOfWeek: DaysOfWeek, weekStartsOn: number) => import("./custom-proptypes").WeekDay[];
@@ -33,4 +35,4 @@ declare const setMonthYear: (date: Date | null, newMonth: number, newYear: numbe
33
35
  declare const parseIsoDate: typeof parseISO;
34
36
  declare const formatIsoDate: (date: Date) => string;
35
37
  declare const formatIsoMonth: (date: Date) => string;
36
- export { getCalendarMonthWeeks, getFirstDayOfWeekend, getLastDayOfWeekend, getMonthsInRange, getMonthRange, getDay, dateToBoundaries, isWithinRange, isSaturday, isSunday, isToday, isSameDay, isSameWeek, isSameMonth, isBefore, isAfter, differenceInCalendarMonths, addMonths, addDays, orderDaysOfWeek, setMonthYear, startOfMonth, lastDayOfMonth, startOfDay, format, daysInMonth, formatIsoDate, formatIsoMonth, parseIsoDate, endOfMonth, };
38
+ export { getCalendar, getCalendarNoCustomLabel, getFirstDayOfWeekend, getLastDayOfWeekend, getMonthsInRange, getMonthRange, getDay, dateToBoundaries, isWithinRange, isSaturday, isSunday, isToday, isSameDay, isSameWeek, isSameMonth, isBefore, isAfter, differenceInCalendarMonths, addMonths, addDays, orderDaysOfWeek, setMonthYear, startOfMonth, lastDayOfMonth, startOfDay, format, daysInMonth, formatIsoDate, formatIsoMonth, parseIsoDate, endOfMonth, };
@@ -84,13 +84,24 @@ function startOfWeek(year, month, day, weekStartsOn) {
84
84
  date.setUTCDate(date.getUTCDate() - diff);
85
85
  return [date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()];
86
86
  }
87
- function getCalendarMonthWeeks(date, weekStartsOn) {
87
+ function getCalendarNoCustomLabel(date, weekStartsOn) {
88
+ return getCalendarMonthWeeks(date, weekStartsOn);
89
+ }
90
+ function getCalendar(date, weekStartsOn, formatDate) {
91
+ return getCalendarMonthWeeks(date, weekStartsOn, formatDate);
92
+ }
93
+ function getCalendarMonthWeeks(date, weekStartsOn, formatDate) {
88
94
  let [year, month, day] = startOfWeek(date.getFullYear(), date.getMonth(), 1, weekStartsOn);
89
95
  const weeksInMonth = [];
90
96
  for (let i = 0; i < 6; i += 1) {
91
97
  const currWeek = [];
92
98
  for (let j = 0; j < 7; j += 1) {
93
- currWeek.push(dateAtStartOfDay(year, month, day));
99
+ const currDate = dateAtStartOfDay(year, month, day);
100
+ currWeek.push({
101
+ val: currDate,
102
+ isoLabel: formatIsoDate(currDate),
103
+ customLabel: formatDate ? formatDate(currDate) : ''
104
+ });
94
105
  [year, month, day] = addDay(year, month, day);
95
106
  }
96
107
  weeksInMonth.push(currWeek);
@@ -170,4 +181,4 @@ const setMonthYear = (date, newMonth, newYear) => {
170
181
  const parseIsoDate = parseISO;
171
182
  const formatIsoDate = date => format(date, 'yyyy-MM-dd');
172
183
  const formatIsoMonth = date => format(date, 'yyyy-MM');
173
- export { getCalendarMonthWeeks, getFirstDayOfWeekend, getLastDayOfWeekend, getMonthsInRange, getMonthRange, getDay, dateToBoundaries, isWithinRange, isSaturday, isSunday, isToday, isSameDay, isSameWeek, isSameMonth, isBefore, isAfter, differenceInCalendarMonths, addMonths, addDays, orderDaysOfWeek, setMonthYear, startOfMonth, lastDayOfMonth, startOfDay, format, daysInMonth, formatIsoDate, formatIsoMonth, parseIsoDate, endOfMonth };
184
+ export { getCalendar, getCalendarNoCustomLabel, getFirstDayOfWeekend, getLastDayOfWeekend, getMonthsInRange, getMonthRange, getDay, dateToBoundaries, isWithinRange, isSaturday, isSunday, isToday, isSameDay, isSameWeek, isSameMonth, isBefore, isAfter, differenceInCalendarMonths, addMonths, addDays, orderDaysOfWeek, setMonthYear, startOfMonth, lastDayOfMonth, startOfDay, format, daysInMonth, formatIsoDate, formatIsoMonth, parseIsoDate, endOfMonth };
@@ -8,7 +8,7 @@ import isRTL from './src/isRTL';
8
8
  import { setNativeValue } from './src/nativeEventHandler';
9
9
  import withDefaultProps from './src/withDefaultProps';
10
10
  import wrapDisplayName from './src/wrapDisplayName';
11
- export { Portal, TransitionInitialMount, cssModules, deprecated, withDefaultProps, wrapDisplayName, isDeviceIphone, isDeviceIpad, isDeviceIos, isRTL, BpkDialogWrapper, setNativeValue };
11
+ export { Portal, TransitionInitialMount, cssModules, deprecated, withDefaultProps, wrapDisplayName, isDeviceIphone, isDeviceIpad, isDeviceIos, isRTL, BpkDialogWrapper, setNativeValue, };
12
12
  declare const _default: {
13
13
  Portal: typeof Portal;
14
14
  TransitionInitialMount: ({ appearActiveClassName, appearClassName, children, transitionTimeout, }: {
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Mock deferCallback to immediately invoke the callback. This ensures that
3
+ * asynchronous state updates triggered by `deferCallback` run before asserting.
4
+ * https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback
5
+ * @param {function} callback - callback to execute, value cannot be returned.
6
+ * You'll typically want to wrap the callback `setState` to update React state.
7
+ * @returns {void}
8
+ */
9
+ export default function deferCallback(callback: () => void): void;
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * Backpack - Skyscanner's Design System
3
3
  *
4
- * Copyright 2022 Skyscanner Ltd
4
+ * Copyright 2016 Skyscanner Ltd
5
5
  *
6
6
  * Licensed under the Apache License, Version 2.0 (the "License");
7
7
  * you may not use this file except in compliance with the License.
@@ -16,15 +16,14 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
- import { renderHook } from '@testing-library/react';
20
- import { useScrollToInitialImage } from "./utils";
21
- describe('useScrollToInitialImage', () => {
22
- it('should scroll to initial image on mount', () => {
23
- const imagesRef = {
24
- current: [document.createElement('div'), document.createElement('div')]
25
- };
26
- const initialImageIndex = 0;
27
- renderHook(() => useScrollToInitialImage(initialImageIndex, imagesRef));
28
- expect(imagesRef.current[initialImageIndex].scrollIntoView).toHaveBeenCalledTimes(1);
29
- });
30
- });
19
+ /**
20
+ * Mock deferCallback to immediately invoke the callback. This ensures that
21
+ * asynchronous state updates triggered by `deferCallback` run before asserting.
22
+ * https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback
23
+ * @param {function} callback - callback to execute, value cannot be returned.
24
+ * You'll typically want to wrap the callback `setState` to update React state.
25
+ * @returns {void}
26
+ */
27
+ export default function deferCallback(callback) {
28
+ callback();
29
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Defer a task until the browser is idle, or till the next "tick" if the
3
+ * browser does not support the idle callback API. This is useful for deferring
4
+ * computationally heavy, non-essential tasks to keep the UI responsive. If the
5
+ * task has not completed within the timeout, it will be executed regardless.
6
+ *
7
+ * https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback
8
+ * @param {function} callback - callback to execute, value cannot be returned.
9
+ * You'll typically want to wrap the callback `setState` to update React state.
10
+ * @returns {void}
11
+ */
12
+ declare const deferCallback: (callback: () => void) => void;
13
+ export default deferCallback;
@@ -0,0 +1,39 @@
1
+ /*
2
+ * Backpack - Skyscanner's Design System
3
+ *
4
+ * Copyright 2016 Skyscanner Ltd
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ /**
20
+ * Defer a task until the browser is idle, or till the next "tick" if the
21
+ * browser does not support the idle callback API. This is useful for deferring
22
+ * computationally heavy, non-essential tasks to keep the UI responsive. If the
23
+ * task has not completed within the timeout, it will be executed regardless.
24
+ *
25
+ * https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback
26
+ * @param {function} callback - callback to execute, value cannot be returned.
27
+ * You'll typically want to wrap the callback `setState` to update React state.
28
+ * @returns {void}
29
+ */
30
+ const deferCallback = callback => {
31
+ if (window.requestIdleCallback) {
32
+ window.requestIdleCallback(callback, {
33
+ timeout: 500
34
+ });
35
+ } else {
36
+ setTimeout(callback, 0);
37
+ }
38
+ };
39
+ export default deferCallback;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyscanner/backpack-web",
3
- "version": "36.4.0",
3
+ "version": "36.5.0",
4
4
  "description": "Backpack Design System web library",
5
5
  "repository": {
6
6
  "type": "git",