@shipengine/elements 2.21.0 → 2.22.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.
Files changed (87) hide show
  1. package/cjs/components/grid-controller/grid-controller.cjs +25 -7
  2. package/cjs/components/grid-controller/grid-controller.styles.cjs +7 -2
  3. package/cjs/components/grid-controller/grid-footer.cjs +30 -15
  4. package/cjs/components/grid-controller/grid-footer.styles.cjs +24 -0
  5. package/cjs/components/grid-controller/index.cjs +1 -1
  6. package/cjs/components/grid-controller/sortable-header/index.cjs +9 -0
  7. package/cjs/components/grid-controller/{sortable-header.cjs → sortable-header/sortable-header.cjs} +3 -5
  8. package/cjs/components/grid-controller/sortable-header/sortable-header.styles.cjs +18 -0
  9. package/cjs/components/grid-filters/components/created-date-filter/created-date-filter.cjs +3 -0
  10. package/cjs/components/grid-filters/components/label-id-filter/label-id-filter.cjs +2 -0
  11. package/cjs/components/grid-filters/components/shipment-id-filter/shipment-id-filter.cjs +2 -0
  12. package/cjs/components/grid-filters/components/tracking-status-filter/tracking-status-filter.cjs +2 -0
  13. package/cjs/components/grid-filters/grid-filters.cjs +6 -0
  14. package/cjs/elements/labels-grid/hooks/use-labels-grid.cjs +63 -29
  15. package/cjs/elements/labels-grid/hooks/use-tracking-status-filter.cjs +109 -0
  16. package/cjs/elements/labels-grid/labels-grid.cjs +47 -30
  17. package/cjs/elements/purchase-label/components/fund-and-purchase/fund-and-purchase.cjs +22 -14
  18. package/cjs/elements/purchase-label/components/rate-form/rate-form.cjs +1 -1
  19. package/cjs/elements/shipments-grid/hooks/use-shipments-grid.cjs +6 -5
  20. package/cjs/elements/shipments-grid/shipments-grid.cjs +56 -24
  21. package/cjs/hooks/use-sortable-query.cjs +36 -0
  22. package/cjs/locales/en/common.cjs +1 -0
  23. package/cjs/package.cjs +1 -1
  24. package/cjs/utilities/feature-flags/feature-flags.cjs +1 -1
  25. package/esm/components/grid-controller/grid-controller.js +27 -9
  26. package/esm/components/grid-controller/grid-controller.styles.js +7 -2
  27. package/esm/components/grid-controller/grid-footer.js +32 -17
  28. package/esm/components/grid-controller/grid-footer.styles.js +20 -0
  29. package/esm/components/grid-controller/index.js +1 -1
  30. package/esm/components/grid-controller/sortable-header/index.js +1 -0
  31. package/esm/components/grid-controller/{sortable-header.js → sortable-header/sortable-header.js} +3 -5
  32. package/esm/components/grid-controller/sortable-header/sortable-header.styles.js +14 -0
  33. package/esm/components/grid-filters/components/created-date-filter/created-date-filter.js +3 -0
  34. package/esm/components/grid-filters/components/label-id-filter/label-id-filter.js +2 -0
  35. package/esm/components/grid-filters/components/shipment-id-filter/shipment-id-filter.js +2 -0
  36. package/esm/components/grid-filters/components/tracking-status-filter/tracking-status-filter.js +2 -0
  37. package/esm/components/grid-filters/grid-filters.js +6 -0
  38. package/esm/elements/labels-grid/hooks/use-labels-grid.js +64 -30
  39. package/esm/elements/labels-grid/hooks/use-tracking-status-filter.js +105 -0
  40. package/esm/elements/labels-grid/labels-grid.js +48 -31
  41. package/esm/elements/purchase-label/components/fund-and-purchase/fund-and-purchase.js +22 -14
  42. package/esm/elements/purchase-label/components/rate-form/rate-form.js +1 -1
  43. package/esm/elements/shipments-grid/hooks/use-shipments-grid.js +6 -5
  44. package/esm/elements/shipments-grid/shipments-grid.js +57 -25
  45. package/esm/hooks/use-sortable-query.js +32 -0
  46. package/esm/locales/en/common.js +1 -0
  47. package/esm/package.js +1 -1
  48. package/esm/utilities/feature-flags/feature-flags.js +1 -1
  49. package/package.json +3 -3
  50. package/types/src/components/grid-controller/grid-controller.d.ts +2 -1
  51. package/types/src/components/grid-controller/grid-controller.styles.d.ts +6 -1
  52. package/types/src/components/grid-controller/grid-footer.d.ts +9 -1
  53. package/types/src/components/grid-controller/grid-footer.styles.d.ts +16 -0
  54. package/types/src/components/grid-controller/sortable-header/index.d.ts +1 -0
  55. package/types/src/components/grid-controller/{sortable-header.d.ts → sortable-header/sortable-header.d.ts} +2 -2
  56. package/types/src/components/grid-controller/sortable-header/sortable-header.styles.d.ts +10 -0
  57. package/types/src/components/grid-filters/components/created-date-filter/created-date-filter.d.ts +2 -1
  58. package/types/src/components/grid-filters/components/label-id-filter/label-id-filter.d.ts +2 -1
  59. package/types/src/components/grid-filters/components/shipment-id-filter/shipment-id-filter.d.ts +2 -1
  60. package/types/src/components/grid-filters/components/tracking-status-filter/tracking-status-filter.d.ts +2 -1
  61. package/types/src/components/grid-filters/grid-filters.d.ts +2 -1
  62. package/types/src/elements/labels-grid/hooks/use-labels-grid.d.ts +4 -3
  63. package/types/src/elements/labels-grid/hooks/use-tracking-status-filter.d.ts +25 -0
  64. package/types/src/elements/labels-grid/labels-grid.d.ts +36 -21
  65. package/types/src/elements/manage-carriers/manage-carriers.d.ts +1 -0
  66. package/types/src/elements/manage-external-carriers/manage-external-carriers.d.ts +1 -0
  67. package/types/src/elements/manage-funding/manage-funding-element.d.ts +1 -0
  68. package/types/src/elements/manage-warehouses/manage-warehouses.d.ts +1 -0
  69. package/types/src/elements/payment-method-settings/payment-method-settings-element.d.ts +1 -0
  70. package/types/src/elements/purchase-label/components/fund-and-purchase/fund-and-purchase.d.ts +2 -2
  71. package/types/src/elements/purchase-label/purchase-label.d.ts +1 -0
  72. package/types/src/elements/select-label-layout/select-label-layout-element.d.ts +1 -0
  73. package/types/src/elements/shipment-summary/shipment-summary.d.ts +1 -0
  74. package/types/src/elements/shipments-grid/hooks/use-shipments-grid.d.ts +7 -1
  75. package/types/src/elements/shipments-grid/shipments-grid.d.ts +10 -1
  76. package/types/src/elements/theme-creator/theme-creator.d.ts +1 -0
  77. package/types/src/elements/transaction-history/transaction-history-element.d.ts +1 -0
  78. package/types/src/elements/unit-settings/unit-settings-element.d.ts +1 -0
  79. package/types/src/elements/vat-settings/vat-settings-element.d.ts +1 -0
  80. package/types/src/elements/void-label/void-label.d.ts +1 -0
  81. package/types/src/hooks/use-sortable-query.d.ts +13 -0
  82. package/types/src/locales/en/index.d.ts +1 -0
  83. package/types/src/workflows/account-settings/account-settings.d.ts +1 -0
  84. package/types/src/workflows/carrier-services/carrier-services.d.ts +1 -0
  85. package/types/src/workflows/connect-external-carrier/connect-external-carrier.d.ts +1 -0
  86. package/types/src/workflows/label-workflow/label-workflow.d.ts +1 -0
  87. package/types/src/workflows/onboarding/onboarding.d.ts +1 -0
@@ -21,15 +21,33 @@ const GridController = ({
21
21
  data,
22
22
  footerContent,
23
23
  onRowClick,
24
+ isLoading: _isLoading = false,
24
25
  useCheckboxes: _useCheckboxes = false,
25
26
  filters,
26
27
  emptyContent
27
28
  }) => {
28
29
  var _a, _b, _c;
29
30
  const [isChecked, setIsChecked] = React.useState((_a = data === null || data === void 0 ? void 0 : data.map(() => false)) !== null && _a !== void 0 ? _a : []);
30
- const getColumnHeaderContents = () => {
31
- return columns.map(column => column.headerContent);
32
- };
31
+ const columnHeaderContents = React.useMemo(() => columns.map(column => column.headerContent), [columns]);
32
+ const loadingRows = React.useMemo(() => {
33
+ const items = [];
34
+ for (let index = 0; index < 5; index++) {
35
+ items.push(jsxRuntime.jsx(giger.TableRow, Object.assign({
36
+ css: gridController_styles.styles.skeletonTableRow,
37
+ withHover: false
38
+ }, {
39
+ children: columnHeaderContents.map((item, index) => jsxRuntime.jsx(giger.TableBodyCell, {
40
+ children: item && jsxRuntime.jsx(giger.Skeleton, {
41
+ animation: giger.SkeletonAnimation.WAVE,
42
+ height: 16,
43
+ variant: giger.SkeletonVariant.RECT,
44
+ width: 72
45
+ })
46
+ }, index))
47
+ }), `loading-row-${index}`));
48
+ }
49
+ return items;
50
+ }, [columnHeaderContents]);
33
51
  const isAllChecked = React.useMemo(() => isChecked.length > 0 && isChecked.every(check => check), [isChecked]);
34
52
  const isIndeterminate = React.useMemo(() => isChecked.some(check => check), [isChecked]);
35
53
  const toggleCheckbox = React.useCallback(index => {
@@ -70,7 +88,7 @@ const GridController = ({
70
88
  indeterminate: (_c = !isAllChecked && isIndeterminate) !== null && _c !== void 0 ? _c : false,
71
89
  onChange: event => toggleAllCheckboxes(event.target.checked)
72
90
  })
73
- })), getColumnHeaderContents().map((header, index) => jsxRuntime.jsx(giger.TableHeaderCell, Object.assign({
91
+ })), columnHeaderContents.map((header, index) => jsxRuntime.jsx(giger.TableHeaderCell, Object.assign({
74
92
  css: gridController_styles.styles.tableHeader
75
93
  }, {
76
94
  children: header
@@ -80,8 +98,8 @@ const GridController = ({
80
98
  outerWrapperStyles: gridController_styles.styles.tableWrapper,
81
99
  tableStyles: gridController_styles.styles.table
82
100
  }, {
83
- children: jsxRuntime.jsx(giger.TableBody, {
84
- children: data.map((row, index) => {
101
+ children: jsxRuntime.jsxs(giger.TableBody, {
102
+ children: [_isLoading && loadingRows, data.map((row, index) => {
85
103
  var _a;
86
104
  const allowOnClick = !!onRowClick && !(row === null || row === void 0 ? void 0 : row.disableOnRowClick);
87
105
  return jsxRuntime.jsxs(giger.TableRow, Object.assign({
@@ -102,7 +120,7 @@ const GridController = ({
102
120
  children: column.renderCellContent(row)
103
121
  }), index))]
104
122
  }), index);
105
- })
123
+ })]
106
124
  })
107
125
  }))]
108
126
  }));
@@ -9,8 +9,12 @@ const styles = styles$1.createStyles({
9
9
  width: styles$1.scopeTheme(theme).spacing(6)
10
10
  }),
11
11
  filters: theme => ({
12
+ backgroundColor: styles$1.scopeTheme(theme).palette.white,
12
13
  borderBottom: `1px solid ${styles$1.scopeTheme(theme).palette.gray[200]}`,
13
- padding: `${styles$1.scopeTheme(theme).spacing()}px ${styles$1.scopeTheme(theme).spacing(2)}px`
14
+ padding: styles$1.scopeTheme(theme).spacing()
15
+ }),
16
+ skeletonTableRow: () => ({
17
+ height: "68px"
14
18
  }),
15
19
  table: {
16
20
  tableLayout: "initial"
@@ -26,7 +30,8 @@ const styles = styles$1.createStyles({
26
30
  border: "none"
27
31
  },
28
32
  wrapper: theme => Object.assign({
29
- height: "auto"
33
+ height: "auto",
34
+ overflow: "hidden"
30
35
  }, styles$1.scopeTheme(theme).getComponentOverride("Table"))
31
36
  });
32
37
 
@@ -5,6 +5,8 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var jsxRuntime = require('@emotion/react/jsx-runtime');
6
6
  var reactI18next = require('react-i18next');
7
7
  var giger = require('@shipengine/giger');
8
+ var gridFooter_styles = require('./grid-footer.styles.cjs');
9
+ var loader = require('../loader/loader.cjs');
8
10
 
9
11
  /**
10
12
  * @internal
@@ -21,30 +23,43 @@ const GridFooter = ({
21
23
  pageSize,
22
24
  total,
23
25
  showPagination,
24
- onPageChange
26
+ onPageChange,
27
+ isLoadingMore,
28
+ hasMoreUnfetchedResults
25
29
  }) => {
26
30
  const firstElementInPage = (page - 1) * pageSize + 1;
27
31
  const lastElementInPage = Math.min(page * pageSize, total);
28
- return jsxRuntime.jsxs(jsxRuntime.Fragment, {
29
- children: [jsxRuntime.jsx(giger.Typography, Object.assign({
30
- component: "span",
31
- variant: "body2"
32
+ return jsxRuntime.jsxs("div", Object.assign({
33
+ css: gridFooter_styles.styles.wrapper
34
+ }, {
35
+ children: [jsxRuntime.jsxs("div", Object.assign({
36
+ css: gridFooter_styles.styles.countWrapper
32
37
  }, {
33
- children: jsxRuntime.jsx(reactI18next.Trans, {
34
- components: [jsxRuntime.jsx("b", {})],
35
- count: total,
36
- i18nKey: "common:grid.row-count",
37
- values: {
38
- firstIndex: firstElementInPage,
39
- lastIndex: lastElementInPage
40
- }
41
- })
38
+ children: [firstElementInPage > 0 && jsxRuntime.jsx(giger.Typography, Object.assign({
39
+ component: "span",
40
+ variant: "body2"
41
+ }, {
42
+ children: jsxRuntime.jsx(reactI18next.Trans, {
43
+ components: [jsxRuntime.jsx("b", {})],
44
+ count: total,
45
+ i18nKey: hasMoreUnfetchedResults && total > 1 ? "common:grid.row-count-plus_other" : "common:grid.row-count",
46
+ values: {
47
+ firstIndex: firstElementInPage,
48
+ lastIndex: lastElementInPage
49
+ }
50
+ })
51
+ })), isLoadingMore && jsxRuntime.jsx("div", {
52
+ children: jsxRuntime.jsx(loader.Loader, {
53
+ css: gridFooter_styles.styles.loader,
54
+ size: giger.SpinnerSize.SIZE_SMALL
55
+ })
56
+ })]
42
57
  })), showPagination && jsxRuntime.jsx(giger.Pagination, {
43
58
  currentPage: page,
44
59
  onPageChange: onPageChange,
45
60
  totalPages: pages
46
61
  })]
47
- });
62
+ }));
48
63
  };
49
64
 
50
65
  exports.GridFooter = GridFooter;
@@ -0,0 +1,24 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var styles$1 = require('../../utilities/styles.cjs');
6
+
7
+ const styles = styles$1.createStyles({
8
+ countWrapper: theme => ({
9
+ alignItems: "center",
10
+ display: "flex",
11
+ gap: styles$1.scopeTheme(theme).spacing(1)
12
+ }),
13
+ loader: theme => ({
14
+ color: styles$1.scopeTheme(theme).palette.gray.main
15
+ }),
16
+ wrapper: {
17
+ alignItems: "center",
18
+ display: "flex",
19
+ justifyContent: "space-between",
20
+ width: "100%"
21
+ }
22
+ });
23
+
24
+ exports.styles = styles;
@@ -5,7 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var gridController = require('./grid-controller.cjs');
6
6
  var cellFormattedDate = require('./cell-formatted-date.cjs');
7
7
  var gridFooter = require('./grid-footer.cjs');
8
- var sortableHeader = require('./sortable-header.cjs');
8
+ var sortableHeader = require('./sortable-header/sortable-header.cjs');
9
9
 
10
10
 
11
11
 
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var sortableHeader = require('./sortable-header.cjs');
6
+
7
+
8
+
9
+ exports.SortableHeader = sortableHeader.SortableHeader;
@@ -5,6 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var jsxRuntime = require('@emotion/react/jsx-runtime');
6
6
  var giger = require('@shipengine/giger');
7
7
  var gigerTheme = require('@shipengine/giger-theme');
8
+ var sortableHeader_styles = require('./sortable-header.styles.cjs');
8
9
 
9
10
  /**
10
11
  * A reusable component for creating sortable table headers
@@ -23,17 +24,14 @@ const SortableHeader = ({
23
24
  };
24
25
  return jsxRuntime.jsxs("span", Object.assign({
25
26
  "aria-label": headerText,
26
- css: {
27
- alignItems: "center",
28
- cursor: "pointer",
29
- display: "flex"
30
- },
27
+ css: sortableHeader_styles.styles.span,
31
28
  onClick: onToggleSort,
32
29
  onKeyDown: handleKeyDown,
33
30
  role: "button",
34
31
  tabIndex: 0
35
32
  }, {
36
33
  children: [headerText, jsxRuntime.jsx(giger.Icon, {
34
+ css: sortableHeader_styles.styles.icon,
37
35
  name: sortDirection === "desc" ? gigerTheme.IconNames.SORT_BOTTOM : gigerTheme.IconNames.SORT_TOP,
38
36
  size: giger.IconSize.SIZE_SMALL
39
37
  })]
@@ -0,0 +1,18 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var styles$1 = require('../../../utilities/styles.cjs');
6
+
7
+ const styles = styles$1.createStyles({
8
+ icon: theme => ({
9
+ paddingLeft: styles$1.scopeTheme(theme).spacing()
10
+ }),
11
+ span: () => ({
12
+ alignItems: "center",
13
+ cursor: "pointer",
14
+ display: "flex"
15
+ })
16
+ });
17
+
18
+ exports.styles = styles;
@@ -24,6 +24,7 @@ var elementsContextProvider = require('../../../../elements-provider/elements-co
24
24
  * @see {@link CreatedDateFilterProps | The props for the `<CreatedDateFilter />` component}
25
25
  */
26
26
  const CreatedDateFilter = ({
27
+ disabled: _disabled = false,
27
28
  filters,
28
29
  onFiltersUpdated
29
30
  }) => {
@@ -105,6 +106,7 @@ const CreatedDateFilter = ({
105
106
  }, [filters.createdDate]);
106
107
  return ((_a = filters.createdDate) === null || _a === void 0 ? void 0 : _a.value) ? jsxRuntime.jsxs(giger.Button, Object.assign({
107
108
  css: createdDateFilter_styles.styles.mainButton,
109
+ disabled: _disabled,
108
110
  onClick: onFilterClear,
109
111
  variant: giger.ButtonVariant.TEXT
110
112
  }, {
@@ -123,6 +125,7 @@ const CreatedDateFilter = ({
123
125
  })) : jsxRuntime.jsxs(jsxRuntime.Fragment, {
124
126
  children: [jsxRuntime.jsxs(giger.Button, Object.assign({
125
127
  css: createdDateFilter_styles.styles.mainButton,
128
+ disabled: _disabled,
126
129
  onClick: onToggleCreatedDateFilter,
127
130
  ref: buttonRef,
128
131
  variant: giger.ButtonVariant.TEXT
@@ -27,6 +27,7 @@ var submitButton = require('../../../field/submit-button/submit-button.cjs');
27
27
  * @see {@link LabelIdFilterProps | The props for the `<LabelIdFilter />` component}
28
28
  */
29
29
  const LabelIdFilter = ({
30
+ disabled: _disabled = false,
30
31
  filters,
31
32
  onFiltersUpdated
32
33
  }) => {
@@ -62,6 +63,7 @@ const LabelIdFilter = ({
62
63
  jsxRuntime.jsx(jsxRuntime.Fragment, {
63
64
  children: jsxRuntime.jsxs(jsxRuntime.Fragment, {
64
65
  children: [jsxRuntime.jsx(giger.Button, Object.assign({
66
+ disabled: _disabled,
65
67
  onClick: toggleLabelIdFilter,
66
68
  ref: buttonRef,
67
69
  variant: giger.ButtonVariant.TEXT
@@ -27,6 +27,7 @@ var submitButton = require('../../../field/submit-button/submit-button.cjs');
27
27
  * @see {@link ShipmentIdFilterProps | The props for the `<ShipmentIdFilter />` component}
28
28
  */
29
29
  const ShipmentIdFilter = ({
30
+ disabled: _disabled = false,
30
31
  filters,
31
32
  onFiltersUpdated
32
33
  }) => {
@@ -61,6 +62,7 @@ const ShipmentIdFilter = ({
61
62
  children: jsxRuntime.jsxs(jsxRuntime.Fragment, {
62
63
  children: [jsxRuntime.jsx(giger.Button, Object.assign({
63
64
  css: shipmentIdFilter_styles.styles.mainButton,
65
+ disabled: _disabled,
64
66
  onClick: toggleShipmentIdFilter,
65
67
  ref: buttonRef,
66
68
  variant: giger.ButtonVariant.TEXT
@@ -25,6 +25,7 @@ var spacer = require('../../../spacer/spacer.cjs');
25
25
  * @see {@link TrackingStatusFilterProps | The props for the `<TrackingStatusFilter />` component}
26
26
  */
27
27
  const TrackingStatusFilter = ({
28
+ disabled: _disabled = false,
28
29
  filters,
29
30
  onFiltersUpdated
30
31
  }) => {
@@ -109,6 +110,7 @@ const TrackingStatusFilter = ({
109
110
  }, [watchedValues]);
110
111
  return jsxRuntime.jsxs(jsxRuntime.Fragment, {
111
112
  children: [jsxRuntime.jsxs(giger.Button, Object.assign({
113
+ disabled: _disabled,
112
114
  onClick: toggleTrackingStatusFilter,
113
115
  ref: buttonRef,
114
116
  variant: giger.ButtonVariant.TEXT
@@ -22,6 +22,7 @@ var trackingStatusFilter = require('./components/tracking-status-filter/tracking
22
22
  const GridFilters = ({
23
23
  filters,
24
24
  onFiltersUpdated,
25
+ filtersDisabled: _filtersDisabled = false,
25
26
  onClearAllFilters
26
27
  }) => {
27
28
  var _a, _b, _c;
@@ -41,18 +42,23 @@ const GridFilters = ({
41
42
  });
42
43
  return jsxRuntime.jsxs("section", {
43
44
  children: [filters.shipmentId.enabled && jsxRuntime.jsx(shipmentIdFilter.ShipmentIdFilter, {
45
+ disabled: _filtersDisabled,
44
46
  filters: filters,
45
47
  onFiltersUpdated: onFiltersUpdated
46
48
  }), ((_a = filters.labelId) === null || _a === void 0 ? void 0 : _a.enabled) && jsxRuntime.jsx(labelIdFilter.LabelIdFilter, {
49
+ disabled: _filtersDisabled,
47
50
  filters: filters,
48
51
  onFiltersUpdated: onFiltersUpdated
49
52
  }), ((_b = filters.createdDate) === null || _b === void 0 ? void 0 : _b.enabled) && jsxRuntime.jsx(createdDateFilter.CreatedDateFilter, {
53
+ disabled: _filtersDisabled,
50
54
  filters: filters,
51
55
  onFiltersUpdated: onFiltersUpdated
52
56
  }), ((_c = filters.trackingStatus) === null || _c === void 0 ? void 0 : _c.enabled) && jsxRuntime.jsx(trackingStatusFilter.TrackingStatusFilter, {
57
+ disabled: _filtersDisabled,
53
58
  filters: filters,
54
59
  onFiltersUpdated: onFiltersUpdated
55
60
  }), shouldShowClearAll && jsxRuntime.jsx(giger.Button, Object.assign({
61
+ disabled: _filtersDisabled,
56
62
  onClick: () => {
57
63
  onClearAllFilters();
58
64
  },
@@ -6,18 +6,19 @@ var react = require('@emotion/react');
6
6
  var useGetServiceName = require('../../../hooks/use-get-service-name.cjs');
7
7
  var React = require('react');
8
8
  var reactApi = require('@shipengine/react-api');
9
+ var useTrackingStatusFilter = require('./use-tracking-status-filter.cjs');
9
10
  var usePager = require('../../../components/pager/usePager.cjs');
10
11
 
11
12
  const PAGE_SIZE = 20;
12
13
  const useLabelsGrid = ({
13
- createdDateSortBy,
14
14
  labelStatus,
15
15
  showShipmentIdFilter,
16
16
  showLabelIdFilter,
17
17
  showTrackingStatusFilter,
18
- fetchShipments
18
+ fetchShipments,
19
+ sortDir
19
20
  }) => {
20
- var _a, _b, _c;
21
+ var _a, _b, _c, _d, _e, _f;
21
22
  const initialFilters = {
22
23
  labelId: {
23
24
  enabled: !!showLabelIdFilter,
@@ -50,7 +51,7 @@ const useLabelsGrid = ({
50
51
  pagerProps.onPageSelect(1);
51
52
  setFilters(newFilters);
52
53
  };
53
- const hasActiveFilterValue = value => {
54
+ const hasActiveFilterValue = React.useCallback(value => {
54
55
  if (value === null || value === undefined) {
55
56
  return false;
56
57
  }
@@ -64,7 +65,7 @@ const useLabelsGrid = ({
64
65
  return value.trim() !== "";
65
66
  }
66
67
  return Boolean(value);
67
- };
68
+ }, []);
68
69
  const isAnyFilterActive = Object.keys(filters).some(key => {
69
70
  const filter = filters[key];
70
71
  return (filter === null || filter === void 0 ? void 0 : filter.enabled) && hasActiveFilterValue(filter === null || filter === void 0 ? void 0 : filter.value);
@@ -90,38 +91,64 @@ const useLabelsGrid = ({
90
91
  };
91
92
  setFilters(updatedFilters);
92
93
  }, [showLabelIdFilter, showShipmentIdFilter, showTrackingStatusFilter]);
94
+ const isTrackingStatusFilterActive = React.useMemo(() => {
95
+ var _a, _b;
96
+ return !!(((_a = filters.trackingStatus) === null || _a === void 0 ? void 0 : _a.enabled) && hasActiveFilterValue((_b = filters.trackingStatus) === null || _b === void 0 ? void 0 : _b.value));
97
+ }, [(_a = filters.trackingStatus) === null || _a === void 0 ? void 0 : _a.enabled, (_b = filters.trackingStatus) === null || _b === void 0 ? void 0 : _b.value, hasActiveFilterValue]);
98
+ // Use tracking status filter hook when the filter is active
99
+ const {
100
+ labels: trackingFilteredLabels,
101
+ isLoading: isTrackingFilterLoading,
102
+ isFetchingNextPage,
103
+ hasMoreUnfetchedResults,
104
+ paginationInfo: statusFilteredPaginationInfo
105
+ } = useTrackingStatusFilter.useTrackingStatusFilter({
106
+ currentPage: page,
107
+ isActive: isTrackingStatusFilterActive,
108
+ labelStatus,
109
+ pageSize,
110
+ shipmentId: ((_c = filters.shipmentId) === null || _c === void 0 ? void 0 : _c.value) || undefined,
111
+ sortDir: sortDir !== null && sortDir !== void 0 ? sortDir : "desc",
112
+ trackingStatusFilters: ((_d = filters.trackingStatus) === null || _d === void 0 ? void 0 : _d.value) || []
113
+ });
114
+ // Use regular API pagination when tracking status filter is not active
93
115
  const {
94
116
  data: listLabelsData,
95
117
  isLoading: isListLabelsLoading,
96
118
  isError: isListLabelsError
97
119
  } = reactApi.useListLabels({
120
+ enabled: !isTrackingStatusFilterActive,
98
121
  queryFnParams: {
99
122
  labelStatus,
100
123
  page,
101
124
  pageSize,
102
125
  shipmentId: filters.shipmentId.value || undefined,
103
- sortDir: createdDateSortBy !== null && createdDateSortBy !== void 0 ? createdDateSortBy : "desc"
126
+ sortDir: sortDir !== null && sortDir !== void 0 ? sortDir : "desc"
104
127
  }
105
128
  });
106
129
  const labels = React.useMemo(() => {
130
+ // If tracking status filter is active, use the filtered labels from the hook
131
+ if (isTrackingStatusFilterActive) {
132
+ return trackingFilteredLabels.map(label => Object.assign(Object.assign({}, label), {
133
+ bodyCellStyles: {
134
+ color: label.status === "voided" ? theme.palette.gray[400] : undefined
135
+ },
136
+ serviceName: getServiceName(label)
137
+ }));
138
+ }
139
+ // Otherwise, use the regular API pagination
107
140
  if (!(listLabelsData === null || listLabelsData === void 0 ? void 0 : listLabelsData.labels)) {
108
141
  return [];
109
142
  }
110
- return listLabelsData.labels.filter(label => {
111
- var _a, _b, _c, _d;
112
- // Filter by tracking status
113
- return !((_b = (_a = filters === null || filters === void 0 ? void 0 : filters.trackingStatus) === null || _a === void 0 ? void 0 : _a.value) === null || _b === void 0 ? void 0 : _b.length) ||
114
- // Voided labels still have an in_transit tracking status, exclude them if the in_transit filter is selected
115
- label.status !== "voided" && ((_c = filters === null || filters === void 0 ? void 0 : filters.trackingStatus) === null || _c === void 0 ? void 0 : _c.value.includes(label.trackingStatus)) ||
116
- // We show voided labels under tracking status also, include them if the voided filter is selected
117
- label.status === "voided" && ((_d = filters === null || filters === void 0 ? void 0 : filters.trackingStatus) === null || _d === void 0 ? void 0 : _d.value.includes(label.status));
118
- }).map(label => Object.assign(Object.assign({}, label), {
143
+ // No need to filter by tracking status here since that's handled by useTrackingStatusFilter
144
+ // when the tracking status filter is active
145
+ return listLabelsData.labels.map(label => Object.assign(Object.assign({}, label), {
119
146
  bodyCellStyles: {
120
147
  color: label.status === "voided" ? theme.palette.gray[400] : undefined
121
148
  },
122
149
  serviceName: getServiceName(label)
123
150
  }));
124
- }, [listLabelsData === null || listLabelsData === void 0 ? void 0 : listLabelsData.labels, (_a = filters === null || filters === void 0 ? void 0 : filters.trackingStatus) === null || _a === void 0 ? void 0 : _a.value, theme.palette.gray, getServiceName]);
151
+ }, [isTrackingStatusFilterActive, trackingFilteredLabels, listLabelsData === null || listLabelsData === void 0 ? void 0 : listLabelsData.labels, theme.palette.gray, getServiceName]);
125
152
  const {
126
153
  data: listShipmentsData,
127
154
  isFetching: isListShipmentsLoading,
@@ -130,18 +157,17 @@ const useLabelsGrid = ({
130
157
  // An empty array here should disable the query
131
158
  shipmentIds: fetchShipments ? labels === null || labels === void 0 ? void 0 : labels.map(label => label.shipmentId) : []
132
159
  });
133
- const shouldShowFilters = isAnyFilterEnabled && (isAnyFilterActive || Boolean(labels === null || labels === void 0 ? void 0 : labels.length));
134
160
  const {
135
161
  data: labelFilterData,
136
162
  isError: isLabelFilterError,
137
163
  isInitialLoading: isLabelFilterLoading
138
- } = reactApi.useGetLabel(((_b = filters.labelId) === null || _b === void 0 ? void 0 : _b.value) || undefined);
139
- const isLabelFilterActive = (_c = filters.labelId) === null || _c === void 0 ? void 0 : _c.value;
164
+ } = reactApi.useGetLabel(((_e = filters.labelId) === null || _e === void 0 ? void 0 : _e.value) || undefined);
165
+ const isLabelFilterActive = (_f = filters.labelId) === null || _f === void 0 ? void 0 : _f.value;
140
166
  const isStatusFilteredOut = (status, filter) => {
141
167
  return (filter === null || filter === void 0 ? void 0 : filter.length) && !filter.includes(status);
142
168
  };
143
169
  const getLabelById = labelById => {
144
- var _a, _b;
170
+ var _a, _b, _c, _d;
145
171
  // Check if filter by label id is active and there are no errors
146
172
  if (isLabelFilterActive && !isLabelFilterError) {
147
173
  let labelPassFilters = true;
@@ -150,14 +176,14 @@ const useLabelsGrid = ({
150
176
  labelPassFilters = false;
151
177
  }
152
178
  // Check if shipment filter has the same value if defined
153
- if ((filters === null || filters === void 0 ? void 0 : filters.shipmentId.value) !== "" && (filters === null || filters === void 0 ? void 0 : filters.shipmentId.value) !== (labelById === null || labelById === void 0 ? void 0 : labelById.shipmentId)) {
179
+ if (((_a = filters === null || filters === void 0 ? void 0 : filters.shipmentId) === null || _a === void 0 ? void 0 : _a.value) !== "" && ((_b = filters === null || filters === void 0 ? void 0 : filters.shipmentId) === null || _b === void 0 ? void 0 : _b.value) !== (labelById === null || labelById === void 0 ? void 0 : labelById.shipmentId)) {
154
180
  labelPassFilters = false;
155
181
  }
156
182
  if (
157
183
  // If Label status is voided and voided status is filtered out, don't show the label
158
- (labelById === null || labelById === void 0 ? void 0 : labelById.status) === "voided" && isStatusFilteredOut("voided", (_a = filters.trackingStatus) === null || _a === void 0 ? void 0 : _a.value) ||
184
+ (labelById === null || labelById === void 0 ? void 0 : labelById.status) === "voided" && isStatusFilteredOut("voided", (_c = filters.trackingStatus) === null || _c === void 0 ? void 0 : _c.value) ||
159
185
  // If Label status is not voided and tracking status is filtered out, don't show the label
160
- (labelById === null || labelById === void 0 ? void 0 : labelById.status) !== "voided" && (labelById === null || labelById === void 0 ? void 0 : labelById.trackingStatus) && isStatusFilteredOut(labelById.trackingStatus, (_b = filters.trackingStatus) === null || _b === void 0 ? void 0 : _b.value)) {
186
+ (labelById === null || labelById === void 0 ? void 0 : labelById.status) !== "voided" && (labelById === null || labelById === void 0 ? void 0 : labelById.trackingStatus) && isStatusFilteredOut(labelById.trackingStatus, (_d = filters.trackingStatus) === null || _d === void 0 ? void 0 : _d.value)) {
161
187
  labelPassFilters = false;
162
188
  }
163
189
  return labelPassFilters ? labelById : undefined;
@@ -192,20 +218,28 @@ const useLabelsGrid = ({
192
218
  clearAllFilters,
193
219
  filters,
194
220
  getGridData,
221
+ hasMoreUnfetchedResults: isTrackingStatusFilterActive ? hasMoreUnfetchedResults : false,
195
222
  isAnyFilterActive,
196
223
  isError: isListLabelsError || isListShipmentsError && fetchShipments,
197
- isLoading: isListLabelsLoading || isLabelFilterLoading || isListShipmentsLoading && fetchShipments,
224
+ isFetchingNextPage: isTrackingStatusFilterActive ? isFetchingNextPage : false,
225
+ // Calculate isLoading based on which query should be active
226
+ isLoading:
227
+ // Always include label filter loading when label ID filter is active
228
+ isLabelFilterActive && isLabelFilterLoading || (
229
+ // For tracking status filter
230
+ isTrackingStatusFilterActive ? isTrackingFilterLoading // Use tracking filter loading when active
231
+ : isListLabelsLoading || isListShipmentsLoading && fetchShipments),
198
232
  labels,
199
233
  pageConfig: {
200
- currentPage: labelFilteredById ? 1 : (listLabelsData === null || listLabelsData === void 0 ? void 0 : listLabelsData.page) || 0,
234
+ currentPage: labelFilteredById ? 1 : isTrackingStatusFilterActive ? statusFilteredPaginationInfo.currentPage : (listLabelsData === null || listLabelsData === void 0 ? void 0 : listLabelsData.page) || 0,
201
235
  pagerProps,
202
- pagesAmount: (listLabelsData === null || listLabelsData === void 0 ? void 0 : listLabelsData.pages) || 0,
236
+ pagesAmount: labelFilteredById ? 1 : isTrackingStatusFilterActive ? (statusFilteredPaginationInfo === null || statusFilteredPaginationInfo === void 0 ? void 0 : statusFilteredPaginationInfo.totalPages) || 1 : (listLabelsData === null || listLabelsData === void 0 ? void 0 : listLabelsData.pages) || 0,
203
237
  pageSize,
204
- showPagination: labelFilteredById ? false : ((listLabelsData === null || listLabelsData === void 0 ? void 0 : listLabelsData.total) || 0) > pageSize,
205
- totalElements: labelFilteredById ? 1 : (listLabelsData === null || listLabelsData === void 0 ? void 0 : listLabelsData.total) || 0
238
+ showPagination: labelFilteredById ? false : isTrackingStatusFilterActive ? ((statusFilteredPaginationInfo === null || statusFilteredPaginationInfo === void 0 ? void 0 : statusFilteredPaginationInfo.totalCount) || 0) > pageSize : ((listLabelsData === null || listLabelsData === void 0 ? void 0 : listLabelsData.total) || 0) > pageSize,
239
+ totalElements: labelFilteredById ? 1 : isTrackingStatusFilterActive ? (statusFilteredPaginationInfo === null || statusFilteredPaginationInfo === void 0 ? void 0 : statusFilteredPaginationInfo.totalCount) || 0 : (listLabelsData === null || listLabelsData === void 0 ? void 0 : listLabelsData.total) || 0
206
240
  },
207
241
  setFilters: onSetFilters,
208
- shouldShowFilters
242
+ shouldShowFilters: isAnyFilterEnabled
209
243
  };
210
244
  };
211
245
 
@@ -0,0 +1,109 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var React = require('react');
6
+ var reactApi = require('@shipengine/react-api');
7
+
8
+ const MIN_RESULTS = 20; // Minimum number of filtered results needed to stop fetching
9
+ const MAX_PAGES = 5; // Maximum number of pages to fetch if we have enough results
10
+ const useTrackingStatusFilter = ({
11
+ isActive,
12
+ labelStatus,
13
+ shipmentId,
14
+ trackingStatusFilters,
15
+ sortDir,
16
+ currentPage,
17
+ pageSize
18
+ }) => {
19
+ const [allLabels, setAllLabels] = React.useState([]);
20
+ const {
21
+ data: infiniteData,
22
+ fetchNextPage,
23
+ hasNextPage,
24
+ isLoading,
25
+ isFetchingNextPage
26
+ } = reactApi.useListLabelsInfinite({
27
+ enabled: isActive,
28
+ queryFnParams: {
29
+ labelStatus,
30
+ pageSize: 100,
31
+ shipmentId,
32
+ sortDir
33
+ }
34
+ });
35
+ React.useEffect(() => {
36
+ if (isActive && (infiniteData === null || infiniteData === void 0 ? void 0 : infiniteData.pages)) {
37
+ const allLabelsFromPages = infiniteData.pages.flatMap(page => page.labels || []);
38
+ setAllLabels(allLabelsFromPages);
39
+ }
40
+ }, [isActive, infiniteData === null || infiniteData === void 0 ? void 0 : infiniteData.pages]);
41
+ const filteredLabels = React.useMemo(() => {
42
+ if (!isActive || !trackingStatusFilters.length) {
43
+ return allLabels;
44
+ }
45
+ return allLabels.filter(label => {
46
+ if (label.status === "voided") {
47
+ return trackingStatusFilters.includes("voided");
48
+ }
49
+ return trackingStatusFilters.includes(label.trackingStatus);
50
+ });
51
+ }, [isActive, allLabels, trackingStatusFilters]);
52
+ const totalCount = filteredLabels.length;
53
+ const totalPages = Math.max(1, Math.ceil(totalCount / pageSize));
54
+ const paginatedLabels = React.useMemo(() => {
55
+ const startIndex = (currentPage - 1) * pageSize;
56
+ const endIndex = Math.min(startIndex + pageSize, filteredLabels.length);
57
+ return filteredLabels.slice(startIndex, endIndex);
58
+ }, [filteredLabels, currentPage, pageSize]);
59
+ // Check if we have enough data for the next page
60
+ const hasDataForNextPage = React.useMemo(() => {
61
+ const nextPageStart = currentPage * pageSize;
62
+ return nextPageStart < filteredLabels.length;
63
+ }, [currentPage, pageSize, filteredLabels.length]);
64
+ // Check if we have more unfetched results
65
+ const hasMoreUnfetchedResults = React.useMemo(() => {
66
+ return hasNextPage && (infiniteData === null || infiniteData === void 0 ? void 0 : infiniteData.pages) && infiniteData.pages.length >= MAX_PAGES && filteredLabels.length >= MIN_RESULTS;
67
+ }, [hasNextPage, infiniteData === null || infiniteData === void 0 ? void 0 : infiniteData.pages, filteredLabels.length]);
68
+ // Trigger fetchNextPage
69
+ React.useEffect(() => {
70
+ // Don't fetch if not active or already fetching
71
+ if (!isActive || isFetchingNextPage) return;
72
+ // Continue fetching if we don't have minimum results yet
73
+ if (filteredLabels.length < MIN_RESULTS && hasNextPage) {
74
+ fetchNextPage();
75
+ return;
76
+ }
77
+ // Continue fetching if we don't have data for the next page
78
+ if (!hasDataForNextPage && hasNextPage) {
79
+ fetchNextPage();
80
+ return;
81
+ }
82
+ // Stop fetching if we've reached max pages and have enough results
83
+ if ((infiniteData === null || infiniteData === void 0 ? void 0 : infiniteData.pages) && infiniteData.pages.length >= MAX_PAGES && filteredLabels.length >= MIN_RESULTS && hasDataForNextPage) {
84
+ return;
85
+ }
86
+ // Otherwise, fetch next page if available
87
+ if (hasNextPage) {
88
+ fetchNextPage();
89
+ }
90
+ }, [isActive, currentPage, pageSize, filteredLabels.length, hasNextPage, isFetchingNextPage, fetchNextPage, hasDataForNextPage, infiniteData === null || infiniteData === void 0 ? void 0 : infiniteData.pages]);
91
+ return {
92
+ allLabelsCount: totalCount,
93
+ fetchNextPage,
94
+ filteredLabelsCount: totalCount,
95
+ hasMorePages: hasNextPage,
96
+ hasMoreUnfetchedResults,
97
+ isFetchingNextPage,
98
+ isLoading: isLoading || filteredLabels.length === 0 && isFetchingNextPage,
99
+ labels: paginatedLabels,
100
+ paginationInfo: {
101
+ currentPage,
102
+ pageSize,
103
+ totalCount,
104
+ totalPages
105
+ }
106
+ };
107
+ };
108
+
109
+ exports.useTrackingStatusFilter = useTrackingStatusFilter;