@jobber/components 4.38.0 → 4.39.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.
@@ -99,6 +99,7 @@ export interface DataListProps<T extends DataListObject> {
99
99
  * The list of Selected Item ids
100
100
  */
101
101
  readonly selected?: T["id"][];
102
+ readonly onSelectAll?: () => void;
102
103
  }
103
104
  export interface DataListLayoutProps<T extends DataListObject> {
104
105
  readonly children: (item: DataListItemType<T[]>) => JSX.Element;
@@ -0,0 +1,7 @@
1
+ /// <reference types="react" />
2
+ interface DataListSortingArrowsProps {
3
+ readonly order?: "asc" | "desc";
4
+ }
5
+ export declare const SORTING_ICON_TEST_ID = "ATL-DataList-Sorting-Icon";
6
+ export declare function DataListSortingArrows({ order }: DataListSortingArrowsProps): JSX.Element;
7
+ export {};
@@ -7,5 +7,5 @@ interface DataListHeaderProps<T extends DataListObject> {
7
7
  readonly headerData?: DataListItemTypeFromHeader<T, DataListHeaderType<T>>;
8
8
  readonly headerVisibility: NonNullable<DataListProps<T>["headerVisibility"]>;
9
9
  }
10
- export declare function DataListHeader<T extends DataListObject>({ layouts, mediaMatches, headerData, headerVisibility, }: DataListHeaderProps<T>): JSX.Element;
10
+ export declare function DataListHeader<T extends DataListObject>({ layouts, mediaMatches, headerData, headerVisibility, }: DataListHeaderProps<T>): JSX.Element | null;
11
11
  export {};
@@ -0,0 +1,7 @@
1
+ /// <reference types="react" />
2
+ import { ReactElement } from "react-markdown/lib/react-markdown";
3
+ interface DataListHeaderCheckbox {
4
+ readonly children: ReactElement;
5
+ }
6
+ export declare function DataListHeaderCheckbox({ children }: DataListHeaderCheckbox): JSX.Element;
7
+ export {};
@@ -12,7 +12,6 @@ var design = require('@jobber/design');
12
12
  var isEmpty = require('lodash/isEmpty');
13
13
  var InlineLabel = require('../InlineLabel-afd5fc6f.js');
14
14
  var classnames = require('classnames');
15
- var Icon = require('../Icon-405a216c.js');
16
15
  var FormatDate = require('../FormatDate-70ea5b43.js');
17
16
  var Heading = require('../Heading-a1191b15.js');
18
17
  require('uuid');
@@ -27,10 +26,11 @@ require('react-popper');
27
26
  var useFocusTrap = require('@jobber/hooks/useFocusTrap');
28
27
  var useRefocusOnActivator = require('@jobber/hooks/useRefocusOnActivator');
29
28
  var useOnKeyDown = require('@jobber/hooks/useOnKeyDown');
29
+ var AnimatedSwitcher = require('../AnimatedSwitcher-d1e1ddcf.js');
30
+ var Icon = require('../Icon-405a216c.js');
30
31
  var useInView = require('@jobber/hooks/useInView');
31
32
  var debounce = require('lodash/debounce');
32
33
  var InputText = require('../InputText-d1a52550.js');
33
- var AnimatedSwitcher = require('../AnimatedSwitcher-d1e1ddcf.js');
34
34
  var Spinner = require('../Spinner-9d8fc7ff.js');
35
35
  require('../Content-2ca1ffe1.js');
36
36
  require('../FormField-d6138b7f.js');
@@ -43,8 +43,8 @@ var isEmpty__default = /*#__PURE__*/_interopDefaultLegacy(isEmpty);
43
43
  var classnames__default = /*#__PURE__*/_interopDefaultLegacy(classnames);
44
44
  var debounce__default = /*#__PURE__*/_interopDefaultLegacy(debounce);
45
45
 
46
- var css_248z$d = ".TkdrExYnvcY- {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-direction: column;\n flex-direction: column;\n position: relative;\n z-index: 0;\n z-index: var(--elevation-default);\n -ms-flex: 1;\n flex: 1;\n}\n\n.IcAlZHoB4LI- {\n display: -ms-flexbox;\n display: flex;\n position: relative;\n z-index: 1;\n z-index: var(--elevation-base);\n margin-bottom: calc(16px / 2);\n margin-bottom: var(--space-small);\n -ms-flex-align: center;\n align-items: center;\n}\n\n.TFO76ysivmg- {\n display: grid;\n padding: calc(16px / 2) 0;\n padding: var(--space-small) 0;\n gap: calc(16px / 2);\n grid-gap: calc(16px / 2);\n grid-gap: var(--space-small);\n gap: var(--space-small);\n grid-template-columns: auto -webkit-max-content;\n grid-template-columns: auto max-content;\n}\n\n.jGHZZYZm1ZY- {\n padding: calc(16px / 2);\n padding: var(--space-small);\n border-bottom: calc(16px / 8) solid rgb(225, 225, 225);\n border-bottom: var(--border-thick) solid var(--color-border);\n}\n\n.ise8kHCfhCY- {\n position: relative;\n padding: calc(16px / 2);\n padding: var(--space-small);\n border-bottom: calc(16px / 16) solid rgb(225, 225, 225);\n border-bottom: var(--border-base) solid var(--color-border);\n}\n\n.d-79rkMqufg- {\n display: grid;\n -webkit-column-gap: calc(16px / 2);\n -webkit-column-gap: var(--space-small);\n -moz-column-gap: calc(16px / 2);\n -moz-column-gap: var(--space-small);\n column-gap: calc(16px / 2);\n grid-column-gap: calc(16px / 2);\n grid-column-gap: var(--space-small);\n column-gap: var(--space-small);\n -ms-flex-align: start;\n align-items: flex-start;\n grid-template-columns: -webkit-max-content minmax(0px, auto);\n grid-template-columns: max-content minmax(0px, auto);\n}\n\n@media (min-width: 768px) {\n\n.d-79rkMqufg- {\n -ms-flex-align: center;\n align-items: center;\n}\n }\n\n@media (--medium-screens-and-up) {\n\n.d-79rkMqufg- {\n -ms-flex-align: center;\n align-items: center;\n}\n }\n\n.ise8kHCfhCY- .d-79rkMqufg- > :first-child {\n padding-top: calc(16px / 4);\n padding-top: var(--space-smaller);\n opacity: 1;\n transition: opacity 100ms ease-in-out;\n transition: opacity var(--transition-properties);\n --transition-properties: var(--timing-quick) ease-in-out;\n}\n\n@media (min-width: 768px) {\n\n.ise8kHCfhCY- .d-79rkMqufg- > :first-child {\n padding-top: 0;\n opacity: 0;\n}\n }\n\n@media (--medium-screens-and-up) {\n\n.ise8kHCfhCY- .d-79rkMqufg- > :first-child {\n padding-top: 0;\n opacity: 0;\n}\n }\n\n.ise8kHCfhCY-:hover .d-79rkMqufg- > :first-child,\n.ise8kHCfhCY-:focus-within .d-79rkMqufg- > :first-child,\n.ise8kHCfhCY- .d-79rkMqufg-._4L7iXXzLr5k- > :first-child {\n opacity: 1;\n}\n\n.Kkp-IYmwq-s- {\n display: -ms-flexbox;\n display: flex;\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n background-color: rgba(255, 255, 255, 0.6);\n background-color: var(--color-overlay--dimmed);\n -ms-flex-align: start;\n align-items: flex-start;\n -ms-flex-pack: center;\n justify-content: center;\n}\n\n.m-eCShL7TU4- {\n position: sticky;\n top: 50vh;\n}\n";
47
- var styles$d = {"wrapper":"TkdrExYnvcY-","titleContainer":"IcAlZHoB4LI-","headerFilters":"TFO76ysivmg-","headerTitles":"jGHZZYZm1ZY-","listItem":"ise8kHCfhCY-","selectable":"d-79rkMqufg-","selected":"_4L7iXXzLr5k-","filtering":"Kkp-IYmwq-s-","filteringSpinner":"m-eCShL7TU4-"};
46
+ var css_248z$d = ".TkdrExYnvcY-,\n.TkdrExYnvcY- * {\n box-sizing: border-box;\n}\n\n.TkdrExYnvcY- {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-direction: column;\n flex-direction: column;\n position: relative;\n z-index: 0;\n z-index: var(--elevation-default);\n -ms-flex: 1;\n flex: 1;\n}\n\n.IcAlZHoB4LI- {\n display: -ms-flexbox;\n display: flex;\n position: relative;\n z-index: 1;\n z-index: var(--elevation-base);\n margin-bottom: calc(16px / 2);\n margin-bottom: var(--space-small);\n -ms-flex-align: center;\n align-items: center;\n}\n\n.TFO76ysivmg- {\n display: grid;\n padding: calc(16px / 2) 0;\n padding: var(--space-small) 0;\n gap: calc(16px / 2);\n grid-gap: calc(16px / 2);\n grid-gap: var(--space-small);\n gap: var(--space-small);\n grid-template-columns: auto -webkit-max-content;\n grid-template-columns: auto max-content;\n}\n\n.jGHZZYZm1ZY- {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-direction: column;\n flex-direction: column;\n -ms-flex-pack: center;\n justify-content: center;\n min-height: calc(16px * 3);\n min-height: var(--space-largest);\n padding: calc(16px / 2);\n padding: var(--space-small);\n border-bottom: calc(16px / 8) solid rgb(225, 225, 225);\n border-bottom: var(--border-thick) solid var(--color-border);\n}\n\n.jMSVGIAr5tk- > p {\n font-weight: 500;\n}\n\n.jMSVGIAr5tk- {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-align: center;\n align-items: center;\n gap: calc(16px / 4);\n gap: var(--space-smaller);\n margin: calc((16px / 2) * -1) 0;\n margin: calc(calc(16px / 2) * -1) 0;\n margin: calc(var(--space-small) * -1) 0;\n}\n\n.ise8kHCfhCY- {\n position: relative;\n padding: calc(16px / 2);\n padding: var(--space-small);\n border-bottom: calc(16px / 16) solid rgb(225, 225, 225);\n border-bottom: var(--border-base) solid var(--color-border);\n}\n\n.d-79rkMqufg- {\n display: grid;\n -ms-flex-align: start;\n align-items: flex-start;\n}\n\n@media (min-width: 768px) {\n\n.d-79rkMqufg- {\n -ms-flex-align: center;\n align-items: center;\n}\n }\n\n@media (--medium-screens-and-up) {\n\n.d-79rkMqufg- {\n -ms-flex-align: center;\n align-items: center;\n}\n }\n\n.d-79rkMqufg-,\n.jGHZZYZm1ZY- .d-79rkMqufg- {\n grid-template-columns: -webkit-max-content minmax(0px, auto);\n grid-template-columns: max-content minmax(0px, auto);\n -webkit-column-gap: calc(16px / 2);\n -webkit-column-gap: var(--space-small);\n -moz-column-gap: calc(16px / 2);\n -moz-column-gap: var(--space-small);\n column-gap: calc(16px / 2);\n column-gap: var(--space-small);\n}\n\n.jGHZZYZm1ZY- .d-79rkMqufg- {\n display: grid;\n -ms-flex-align: center;\n align-items: center;\n}\n\n.qm-SSuWTXkI- {\n display: -ms-flexbox;\n display: flex;\n visibility: hidden;\n}\n\n.qm-SSuWTXkI-.VA9RnQp6nbI- {\n visibility: visible;\n}\n\n.ise8kHCfhCY- .d-79rkMqufg- > :first-child {\n padding-top: calc(16px / 4);\n padding-top: var(--space-smaller);\n opacity: 1;\n transition: opacity 100ms ease-in-out;\n transition: opacity var(--transition-properties);\n --transition-properties: var(--timing-quick) ease-in-out;\n}\n\n@media (min-width: 768px) {\n\n.ise8kHCfhCY- .d-79rkMqufg- > :first-child {\n padding-top: 0;\n opacity: 0;\n}\n }\n\n@media (--medium-screens-and-up) {\n\n.ise8kHCfhCY- .d-79rkMqufg- > :first-child {\n padding-top: 0;\n opacity: 0;\n}\n }\n\n.ise8kHCfhCY-:hover .d-79rkMqufg- > :first-child,\n.ise8kHCfhCY-:focus-within .d-79rkMqufg- > :first-child,\n.ise8kHCfhCY- .d-79rkMqufg-._4L7iXXzLr5k- > :first-child {\n opacity: 1;\n}\n\n.Kkp-IYmwq-s- {\n display: -ms-flexbox;\n display: flex;\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n background-color: rgba(255, 255, 255, 0.6);\n background-color: var(--color-overlay--dimmed);\n -ms-flex-align: start;\n align-items: flex-start;\n -ms-flex-pack: center;\n justify-content: center;\n}\n\n.m-eCShL7TU4- {\n position: sticky;\n top: 50vh;\n}\n";
47
+ var styles$d = {"wrapper":"TkdrExYnvcY-","titleContainer":"IcAlZHoB4LI-","headerFilters":"TFO76ysivmg-","headerTitles":"jGHZZYZm1ZY-","headerBatchSelect":"jMSVGIAr5tk-","listItem":"ise8kHCfhCY-","selectable":"d-79rkMqufg-","selectAllCheckbox":"qm-SSuWTXkI-","visible":"VA9RnQp6nbI-","selected":"_4L7iXXzLr5k-","filtering":"Kkp-IYmwq-s-","filteringSpinner":"m-eCShL7TU4-"};
48
48
  styleInject_es.styleInject(css_248z$d);
49
49
 
50
50
  var css_248z$c = ".F56prQsXm3A- {\n min-width: 80px;\n margin-left: calc(16px / 2);\n margin-left: var(--space-small);\n}\n";
@@ -147,22 +147,23 @@ function buildIntersectionThreshold(items) {
147
147
  return thresholds;
148
148
  }
149
149
 
150
- var css_248z$9 = ".fLmJZJJqMcE- {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-align: center;\n align-items: center;\n padding: 0;\n border: none;\n background-color: transparent;\n}\n\n.UG8cHUT3Hds- {\n cursor: pointer;\n}\n\n.fLmJZJJqMcE- > * {\n font-weight: 500;\n}\n";
150
+ var css_248z$9 = ".fLmJZJJqMcE- {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-align: center;\n align-items: center;\n padding: 0;\n border: none;\n background-color: transparent;\n}\n\n.UG8cHUT3Hds- {\n cursor: pointer;\n}\n";
151
151
  var styles$9 = {"headerLabel":"fLmJZJJqMcE-","sortable":"UG8cHUT3Hds-"};
152
152
  styleInject_es.styleInject(css_248z$9);
153
153
 
154
- var css_248z$8 = ".XWu7WFLqpYw- {\n position: absolute;\n bottom: calc((16px * 1) - (16px / 8));\n bottom: calc(calc(16px * 1) - calc(16px / 8));\n bottom: calc(var(--space-base) - var(--space-smallest));\n}\n\n.bZLExYQzHAk- {\n position: absolute;\n bottom: calc(16px / 2);\n bottom: var(--space-small);\n}\n";
155
- var styles$8 = {"arrowUp":"XWu7WFLqpYw-","arrowDown":"bZLExYQzHAk-"};
154
+ var css_248z$8 = ".AN5egORYy-0- {\n padding-right: calc(16px / 2);\n padding-right: var(--space-small);\n}\n\n.AN5egORYy-0- path {\n fill: rgba(101, 120, 132, 1);\n fill: var(--color-greyBlue);\n transition: all 200ms ease;\n transition: all var(--timing-base) ease;\n}\n\n.AN5egORYy-0- path.F1uTDCK0Sb0- {\n fill: rgb(1, 41, 57);\n fill: var(--color-blue);\n}\n\n.AN5egORYy-0- path._6KYeQXWXLQ8- {\n fill: rgb(193, 201, 206);\n fill: var(--color-greyBlue--lighter);\n}\n";
155
+ var styles$8 = {"sortIcon":"AN5egORYy-0-","active":"F1uTDCK0Sb0-","inactive":"_6KYeQXWXLQ8-"};
156
156
  styleInject_es.styleInject(css_248z$8);
157
157
 
158
- function SortingArrows({ order }) {
159
- const activeColor = "blue";
160
- const inactiveColor = "greyBlueLighter";
161
- return (React__default["default"].createElement("div", null,
162
- React__default["default"].createElement("span", { className: styles$8.arrowUp },
163
- React__default["default"].createElement(Icon.Icon, { name: "arrowUp", color: order === "asc" ? activeColor : inactiveColor, size: "small" })),
164
- React__default["default"].createElement("span", { className: styles$8.arrowDown },
165
- React__default["default"].createElement(Icon.Icon, { name: "arrowDown", color: order === "desc" ? activeColor : inactiveColor, size: "small" }))));
158
+ const SORTING_ICON_TEST_ID = "ATL-DataList-Sorting-Icon";
159
+ function DataListSortingArrows({ order }) {
160
+ return (React__default["default"].createElement("div", { className: styles$8.sortIcon, "data-testid": SORTING_ICON_TEST_ID },
161
+ React__default["default"].createElement("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" },
162
+ React__default["default"].createElement("path", { className: getActiveClassName("asc"), d: "M16.2929 10.6661C15.9024 11.0566 15.2692 11.0566 14.8787 10.6661L12.2891 8.14263L9.70711 10.6661C9.31658 11.0566 8.68342 11.0566 8.29289 10.6661C7.90237 10.2756 7.90237 9.64239 8.29289 9.25186L11.5858 5.95897C11.9763 5.56845 12.6095 5.56845 13 5.95897L16.2929 9.25186C16.6834 9.64239 16.6834 10.2756 16.2929 10.6661Z" }),
163
+ React__default["default"].createElement("path", { className: getActiveClassName("desc"), d: "M8.29292 13.3339C8.68345 12.9434 9.31661 12.9434 9.70714 13.3339L12.2968 15.8573L14.8787 13.3339C15.2692 12.9434 15.9024 12.9434 16.2929 13.3339C16.6834 13.7244 16.6834 14.3576 16.2929 14.7481L13 18.041C12.6095 18.4315 11.9763 18.4315 11.5858 18.041L8.29292 14.7481C7.9024 14.3576 7.9024 13.7244 8.29292 13.3339Z" }))));
164
+ function getActiveClassName(targetOrder) {
165
+ return order === targetOrder ? styles$8.active : styles$8.inactive;
166
+ }
166
167
  }
167
168
 
168
169
  const defaultValues = {
@@ -186,7 +187,7 @@ function DataListHeaderTile({ headers, headerKey, }) {
186
187
  [styles$9.sortable]: isSortable,
187
188
  }), onClick: handleOnClick },
188
189
  React__default["default"].createElement(Text.Text, { maxLines: "single" }, headers[headerKey]),
189
- (sortingState === null || sortingState === void 0 ? void 0 : sortingState.key) === headerKey && (React__default["default"].createElement(SortingArrows, { order: sortingState.direction }))));
190
+ (sortingState === null || sortingState === void 0 ? void 0 : sortingState.key) === headerKey && (React__default["default"].createElement(DataListSortingArrows, { order: sortingState.direction }))));
190
191
  function toggleSorting(sortingKey) {
191
192
  if ((sortingState === null || sortingState === void 0 ? void 0 : sortingState.direction) === "desc") {
192
193
  sorting === null || sorting === void 0 ? void 0 : sorting.onSort(undefined);
@@ -449,6 +450,35 @@ function DataListItems({ layouts, mediaMatches, data, }) {
449
450
  } }));
450
451
  }
451
452
 
453
+ function DataListHeaderCheckbox({ children }) {
454
+ const { data, totalCount, selected = [], onSelectAll, onSelect, } = useDataListContext();
455
+ if (!onSelectAll && !onSelect)
456
+ return children;
457
+ return (React__default["default"].createElement("div", { className: classnames__default["default"](styles$d.selectable) },
458
+ React__default["default"].createElement("div", { className: classnames__default["default"](styles$d.selectAllCheckbox, {
459
+ [styles$d.visible]: Boolean(onSelectAll),
460
+ }) },
461
+ React__default["default"].createElement(Checkbox.Checkbox, { checked: isAllSelected(), indeterminate: selected.length > 0 && !isAllSelected(), onChange: onSelectAll })),
462
+ React__default["default"].createElement(AnimatedSwitcher.AnimatedSwitcher, { switched: Boolean(selected.length), initialChild: children, switchTo: React__default["default"].createElement("div", { className: styles$d.headerBatchSelect },
463
+ React__default["default"].createElement(Text.Text, null,
464
+ React__default["default"].createElement("b", null,
465
+ selected.length,
466
+ " selected")),
467
+ React__default["default"].createElement(Button.Button, { label: "Deselect All", onClick: () => onSelect === null || onSelect === void 0 ? void 0 : onSelect([]), type: "tertiary" })) })));
468
+ function isAllSelected() {
469
+ // If there's a totalCount, we can use that to accurately determine if the
470
+ // user have "selected all".
471
+ if (totalCount) {
472
+ return totalCount === selected.length;
473
+ }
474
+ // Otherwise, we'll use the total count of data. This is not as reliable, as
475
+ // it's possible that the would select all loaded data while we're
476
+ // loading more. It's still hard to get to that state as the load more
477
+ // triggers before you see the last item.
478
+ return data.length > 0 && selected.length >= data.length;
479
+ }
480
+ }
481
+
452
482
  function DataListHeader({ layouts, mediaMatches, headerData, headerVisibility, }) {
453
483
  const matchingMediaQueries = Object.keys(mediaMatches || {}).filter((key) => !!(mediaMatches === null || mediaMatches === void 0 ? void 0 : mediaMatches[key]));
454
484
  const sortedVisibleBreakpoints = sortSizeProp(matchingMediaQueries);
@@ -458,10 +488,9 @@ function DataListHeader({ layouts, mediaMatches, headerData, headerVisibility, }
458
488
  return (_a = headerVisibility[breakpoint]) !== null && _a !== void 0 ? _a : previousVisibility;
459
489
  }, true);
460
490
  if (!showHeader || !headerData)
461
- return React__default["default"].createElement(React__default["default"].Fragment, null);
462
- return (React__default["default"].createElement(DataListLayoutInternal, { layouts: layouts, renderLayout: layout => {
463
- return (React__default["default"].createElement("div", { className: styles$d.headerTitles }, layout.props.children(headerData)));
464
- }, mediaMatches: mediaMatches }));
491
+ return null;
492
+ return (React__default["default"].createElement(DataListLayoutInternal, { layouts: layouts, mediaMatches: mediaMatches, renderLayout: layout => (React__default["default"].createElement("div", { className: classnames__default["default"](styles$d.headerTitles) },
493
+ React__default["default"].createElement(DataListHeaderCheckbox, null, layout.props.children(headerData)))) }));
465
494
  }
466
495
 
467
496
  const LOADING_STATE_LIMIT_ITEMS = 10;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jobber/components",
3
- "version": "4.38.0",
3
+ "version": "4.39.0",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -84,5 +84,5 @@
84
84
  "> 1%",
85
85
  "IE 10"
86
86
  ],
87
- "gitHead": "3784b9f6104838ae10ea72eacf9119b8e1f43663"
87
+ "gitHead": "3ebee9c0f86bbe3a2fe26bf09572a5b4599a9a0c"
88
88
  }
@@ -1,4 +0,0 @@
1
- /// <reference types="react" />
2
- export declare function SortingArrows({ order }: {
3
- order: "asc" | "desc";
4
- }): JSX.Element;