@jobber/components 4.31.1 → 4.32.1
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.
- package/dist/DataList/DataList.const.d.ts +5 -2
- package/dist/DataList/DataList.d.ts +3 -2
- package/dist/DataList/DataList.types.d.ts +51 -8
- package/dist/DataList/DataList.utils.d.ts +1 -12
- package/dist/DataList/components/DataListEmptyState/DataListEmptyState.d.ts +4 -0
- package/dist/DataList/components/DataListEmptyState/index.d.ts +1 -0
- package/dist/DataList/components/DataListLayout/DataListLayout.d.ts +1 -9
- package/dist/DataList/components/DataListLayoutInternal/DataListHeader.d.ts +1 -2
- package/dist/DataList/components/DataListLayoutInternal/DataListItems.d.ts +1 -2
- package/dist/DataList/components/DataListLayoutInternal/DataListLayoutInternal.d.ts +1 -2
- package/dist/DataList/components/DataListLoadingState/DataListLoadingState.d.ts +2 -4
- package/dist/DataList/components/DataListStickyHeader/index.d.ts +1 -0
- package/dist/DataList/index.js +159 -144
- package/package.json +2 -2
- package/dist/DataList/components/EmptyState/EmptyState.d.ts +0 -21
- package/dist/DataList/components/EmptyState/index.d.ts +0 -1
|
@@ -3,12 +3,15 @@
|
|
|
3
3
|
*/
|
|
4
4
|
type ValuesOf<T extends readonly unknown[]> = T[number];
|
|
5
5
|
export type Breakpoints = ValuesOf<typeof BREAKPOINTS>;
|
|
6
|
-
export declare const
|
|
7
|
-
export declare const
|
|
6
|
+
export declare const EMPTY_RESULTS_MESSAGE = "List is looking empty";
|
|
7
|
+
export declare const EMPTY_FILTER_RESULTS_MESSAGE = "No results for selected filters";
|
|
8
|
+
export declare const EMPTY_STATE_ACTION_BUTTON_ONLY_ERROR = "DataListEmptyState action prop must be a Button component";
|
|
8
9
|
/**
|
|
9
10
|
* Breakpoints that we support
|
|
10
11
|
*/
|
|
11
12
|
export declare const BREAKPOINTS: readonly ["xs", "sm", "md", "lg", "xl"];
|
|
12
13
|
export declare const BREAKPOINT_SIZES: Record<Breakpoints, number>;
|
|
13
14
|
export declare const SEARCH_DEBOUNCE_DELAY: number;
|
|
15
|
+
export declare const DATA_LIST_FILTERING_SPINNER_TEST_ID = "ATL-DataList-filteringSpinner";
|
|
16
|
+
export declare const DATA_LIST_LOADING_MORE_SPINNER_TEST_ID = "ATL-DataList-loadingMoreSpinner";
|
|
14
17
|
export {};
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { DataListLayout } from "./components/DataListLayout";
|
|
3
|
-
import { DataListObject, DataListProps } from "./DataList.types";
|
|
4
3
|
import { DataListFilters } from "./components/DataListFilters";
|
|
5
4
|
import { DataListSearch } from "./components/DataListSearch";
|
|
5
|
+
import { DataListEmptyState } from "./components/DataListEmptyState";
|
|
6
|
+
import { DataListObject, DataListProps } from "./DataList.types";
|
|
6
7
|
export declare function DataList<T extends DataListObject>(props: DataListProps<T>): JSX.Element;
|
|
7
8
|
export declare namespace DataList {
|
|
8
9
|
var Layout: typeof DataListLayout;
|
|
9
|
-
var EmptyState: typeof
|
|
10
|
+
var EmptyState: typeof DataListEmptyState;
|
|
10
11
|
var Filters: typeof DataListFilters;
|
|
11
12
|
var Search: typeof DataListSearch;
|
|
12
13
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ReactElement, ReactNode } from "react";
|
|
2
2
|
import { Breakpoints } from "./DataList.const";
|
|
3
|
+
import { ButtonProps } from "../Button";
|
|
3
4
|
export { Breakpoints } from "./DataList.const";
|
|
4
5
|
export type DataListItemType<T extends DataListObject[]> = Record<keyof T[number], ReactElement>;
|
|
5
6
|
export type DataListItemTypeFromHeader<TData extends DataListObject, THeader extends DataListHeader<TData>> = Record<keyof THeader, ReactElement>;
|
|
@@ -29,21 +30,27 @@ export type DataListHeader<T extends DataListObject> = {
|
|
|
29
30
|
readonly [K in keyof T]?: string;
|
|
30
31
|
};
|
|
31
32
|
export interface DataListProps<T extends DataListObject> {
|
|
33
|
+
/**
|
|
34
|
+
* The data to render in the DataList.
|
|
35
|
+
*/
|
|
32
36
|
readonly data: T[];
|
|
37
|
+
/**
|
|
38
|
+
* The header of the DataList. The object keys are determined by the
|
|
39
|
+
* keys in the data.
|
|
40
|
+
*/
|
|
33
41
|
readonly headers: DataListHeader<T>;
|
|
34
42
|
/**
|
|
35
|
-
*
|
|
43
|
+
* Set the loading state of the DataList. There are a few guidelines on when to use what.
|
|
36
44
|
*
|
|
37
|
-
*
|
|
45
|
+
* - `"initial"` - loading the first set of data
|
|
46
|
+
* - `"filtering"` - loading after a filter is applied
|
|
47
|
+
* - `"loadingMore"` - loading more data after the user scrolls to the bottom
|
|
38
48
|
*/
|
|
39
|
-
readonly
|
|
49
|
+
readonly loadingState?: "initial" | "filtering" | "loadingMore" | "none";
|
|
40
50
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* @default false
|
|
51
|
+
* Adjusts the DataList to show the UX when it is filtered.
|
|
44
52
|
*/
|
|
45
|
-
readonly
|
|
46
|
-
readonly children: ReactElement | ReactElement[];
|
|
53
|
+
readonly filtered?: boolean;
|
|
47
54
|
/**
|
|
48
55
|
* The title of the DataList.
|
|
49
56
|
*/
|
|
@@ -64,15 +71,51 @@ export interface DataListProps<T extends DataListObject> {
|
|
|
64
71
|
readonly headerVisibility?: {
|
|
65
72
|
[Breakpoint in Breakpoints]?: boolean;
|
|
66
73
|
};
|
|
74
|
+
readonly children: ReactElement | ReactElement[];
|
|
75
|
+
}
|
|
76
|
+
export interface DataListLayoutProps<T extends DataListObject> {
|
|
77
|
+
readonly children: (item: DataListItemType<T[]>) => JSX.Element;
|
|
78
|
+
/**
|
|
79
|
+
* The breakpoint at which the layout should be displayed. It will be rendered until a layout with a larger breakpoint is found.
|
|
80
|
+
* @default "xs"
|
|
81
|
+
*/
|
|
82
|
+
readonly size?: Breakpoints;
|
|
67
83
|
}
|
|
68
84
|
export interface DataListSearchProps {
|
|
85
|
+
/**
|
|
86
|
+
* The placeholder text for the search input. This either uses the title prop
|
|
87
|
+
* prepended by "Search" or just falls back to "Search".
|
|
88
|
+
*/
|
|
69
89
|
readonly placeholder?: string;
|
|
70
90
|
readonly onSearch: (search: string) => void;
|
|
71
91
|
}
|
|
72
92
|
export interface DataListFiltersProps {
|
|
73
93
|
readonly children: ReactElement | ReactElement[];
|
|
74
94
|
}
|
|
95
|
+
export interface DataListEmptyStateProps {
|
|
96
|
+
/**
|
|
97
|
+
* The message that shows when the DataList is empty.
|
|
98
|
+
*/
|
|
99
|
+
readonly message: string;
|
|
100
|
+
/**
|
|
101
|
+
* The action that shows when the DataList is empty.
|
|
102
|
+
*
|
|
103
|
+
* This only accepts a Button component. Adding a non-Button component will
|
|
104
|
+
* throw an error.
|
|
105
|
+
*/
|
|
106
|
+
readonly action?: ReactElement<ButtonProps>;
|
|
107
|
+
/**
|
|
108
|
+
* Determine the type of empty state to show.
|
|
109
|
+
*
|
|
110
|
+
* By default, it will show the "empty" state when there is no data. If you
|
|
111
|
+
* want to show the "filtered" type, you need to set the `filtered` prop
|
|
112
|
+
* to the DataList component.
|
|
113
|
+
*/
|
|
114
|
+
readonly type?: "filtered" | "empty";
|
|
115
|
+
}
|
|
75
116
|
export interface DataListContextProps<T extends DataListObject> extends DataListProps<T> {
|
|
76
117
|
readonly filterComponent?: ReactElement<DataListFiltersProps>;
|
|
77
118
|
readonly searchComponent?: ReactElement<DataListSearchProps>;
|
|
119
|
+
readonly emptyStateComponents?: ReactElement<DataListEmptyStateProps>[];
|
|
120
|
+
readonly layoutComponents?: ReactElement<DataListLayoutProps<T>>[];
|
|
78
121
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ReactElement } from "react";
|
|
2
2
|
import { DataListHeader, DataListItemType, DataListItemTypeFromHeader, DataListObject } from "./DataList.types";
|
|
3
|
-
import { EmptyStateProps } from "./components/EmptyState";
|
|
4
3
|
import { Breakpoints } from "./DataList.const";
|
|
5
4
|
/**
|
|
6
5
|
* Return the child component that matches the `type` provided
|
|
@@ -18,14 +17,4 @@ export declare function generateListItemElements<T extends DataListObject>(data:
|
|
|
18
17
|
* Generate the header elements with the default styling
|
|
19
18
|
*/
|
|
20
19
|
export declare function generateHeaderElements<T extends DataListObject>(headers: DataListHeader<T>): DataListItemTypeFromHeader<T, DataListHeader<T>> | undefined;
|
|
21
|
-
interface UseDataListEmptyStateProps {
|
|
22
|
-
readonly children?: ReactElement | ReactElement[];
|
|
23
|
-
readonly isFilterApplied: boolean;
|
|
24
|
-
readonly setIsFilterApplied: (isFilterApplied: boolean) => void;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Modify EmptyState to include an empty filter results when filtering happens
|
|
28
|
-
*/
|
|
29
|
-
export declare function generateDataListEmptyState({ children, isFilterApplied, setIsFilterApplied, }: UseDataListEmptyStateProps): React.ReactElement<EmptyStateProps> | undefined;
|
|
30
20
|
export declare function sortSizeProp(sizeProp: Breakpoints[]): ("xs" | "sm" | "md" | "lg" | "xl")[];
|
|
31
|
-
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./DataListEmptyState";
|
|
@@ -1,11 +1,3 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import {
|
|
3
|
-
export interface DataListLayoutProps<T extends DataListObject> {
|
|
4
|
-
readonly children: (item: DataListItemType<T[]>) => JSX.Element;
|
|
5
|
-
/**
|
|
6
|
-
* The breakpoint at which the layout should be displayed. It will be rendered until a layout with a larger breakpoint is found.
|
|
7
|
-
* @default "xs"
|
|
8
|
-
*/
|
|
9
|
-
readonly size?: Breakpoints;
|
|
10
|
-
}
|
|
2
|
+
import { DataListLayoutProps, DataListObject } from "../../DataList.types";
|
|
11
3
|
export declare function DataListLayout<T extends DataListObject>(_: DataListLayoutProps<T>): JSX.Element;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Breakpoints } from "../../DataList.const";
|
|
3
|
-
import { DataListHeader as DataListHeaderType, DataListItemTypeFromHeader, DataListObject, DataListProps } from "../../DataList.types";
|
|
4
|
-
import { DataListLayoutProps } from "../DataListLayout/DataListLayout";
|
|
3
|
+
import { DataListHeader as DataListHeaderType, DataListItemTypeFromHeader, DataListLayoutProps, DataListObject, DataListProps } from "../../DataList.types";
|
|
5
4
|
interface DataListHeaderProps<T extends DataListObject> {
|
|
6
5
|
readonly layouts: React.ReactElement<DataListLayoutProps<T>>[] | undefined;
|
|
7
6
|
readonly mediaMatches?: Record<Breakpoints, boolean>;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Breakpoints } from "../../DataList.const";
|
|
3
|
-
import { DataListObject } from "../../DataList.types";
|
|
4
|
-
import { DataListLayoutProps } from "../DataListLayout/DataListLayout";
|
|
3
|
+
import { DataListLayoutProps, DataListObject } from "../../DataList.types";
|
|
5
4
|
interface DataListItemsProps<T extends DataListObject> {
|
|
6
5
|
readonly layouts: React.ReactElement<DataListLayoutProps<T>>[] | undefined;
|
|
7
6
|
readonly mediaMatches?: Record<Breakpoints, boolean>;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Breakpoints } from "../../DataList.const";
|
|
3
|
-
import { DataListObject } from "../../DataList.types";
|
|
4
|
-
import { DataListLayoutProps } from "../DataListLayout/DataListLayout";
|
|
3
|
+
import { DataListLayoutProps, DataListObject } from "../../DataList.types";
|
|
5
4
|
interface DataListLayoutInternalProps<T extends DataListObject> {
|
|
6
5
|
readonly layouts: React.ReactElement<DataListLayoutProps<T>>[] | undefined;
|
|
7
6
|
readonly renderLayout: (layout: React.ReactElement<DataListLayoutProps<T>>) => JSX.Element;
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { Breakpoints, DataListHeader, DataListObject } from "../../DataList.types";
|
|
3
|
-
import { DataListLayoutProps } from "../DataListLayout";
|
|
2
|
+
import { Breakpoints, DataListHeader, DataListLayoutProps, DataListObject } from "../../DataList.types";
|
|
4
3
|
interface DataListLoadingStateProps<T extends DataListObject> {
|
|
5
|
-
readonly loading: boolean;
|
|
6
4
|
readonly headers: DataListHeader<T>;
|
|
7
5
|
readonly layouts: React.ReactElement<DataListLayoutProps<T>>[] | undefined;
|
|
8
6
|
readonly mediaMatches?: Record<Breakpoints, boolean>;
|
|
9
7
|
}
|
|
10
8
|
export declare const LOADING_STATE_LIMIT_ITEMS = 10;
|
|
11
9
|
export declare const DATALIST_LOADINGSTATE_ROW_TEST_ID = "ATL-DataList-LoadingState-Row";
|
|
12
|
-
export declare function DataListLoadingState<T extends DataListObject>({
|
|
10
|
+
export declare function DataListLoadingState<T extends DataListObject>({ headers, layouts, mediaMatches, }: DataListLoadingStateProps<T>): JSX.Element;
|
|
13
11
|
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./DataListStickyHeader";
|
package/dist/DataList/index.js
CHANGED
|
@@ -4,30 +4,30 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var React = require('react');
|
|
6
6
|
var styleInject_es = require('../style-inject.es-9d2f5f4e.js');
|
|
7
|
-
var Button = require('../Button-7698424c.js');
|
|
8
7
|
var Text = require('../Text-e7ed0974.js');
|
|
9
|
-
var
|
|
8
|
+
var Glimmer = require('../Glimmer-cfa92a88.js');
|
|
10
9
|
var design = require('@jobber/design');
|
|
10
|
+
var isEmpty = require('lodash/isEmpty');
|
|
11
11
|
var InlineLabel = require('../InlineLabel-afd5fc6f.js');
|
|
12
12
|
var FormatDate = require('../FormatDate-70ea5b43.js');
|
|
13
13
|
var Heading = require('../Heading-a1191b15.js');
|
|
14
|
-
var Glimmer = require('../Glimmer-cfa92a88.js');
|
|
15
14
|
var classnames = require('classnames');
|
|
16
|
-
require('react-router-dom');
|
|
17
15
|
require('../Typography-fd6f932a.js');
|
|
18
16
|
var useInView = require('@jobber/hooks/useInView');
|
|
19
17
|
var debounce = require('lodash/debounce');
|
|
20
18
|
var InputText = require('../InputText-bb03f6d1.js');
|
|
19
|
+
var Button = require('../Button-7698424c.js');
|
|
21
20
|
var AnimatedSwitcher = require('../AnimatedSwitcher-d1e1ddcf.js');
|
|
22
|
-
require('../
|
|
21
|
+
var Spinner = require('../Spinner-9d8fc7ff.js');
|
|
23
22
|
require('../tslib.es6-5b8768b7.js');
|
|
24
23
|
require('../Content-2ca1ffe1.js');
|
|
25
24
|
require('../FormField-0f880b07.js');
|
|
26
25
|
require('uuid');
|
|
27
26
|
require('react-hook-form');
|
|
27
|
+
require('../Icon-405a216c.js');
|
|
28
28
|
require('../InputValidation-b5a3d92c.js');
|
|
29
29
|
require('framer-motion');
|
|
30
|
-
require('
|
|
30
|
+
require('react-router-dom');
|
|
31
31
|
|
|
32
32
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
33
33
|
|
|
@@ -36,28 +36,38 @@ var isEmpty__default = /*#__PURE__*/_interopDefaultLegacy(isEmpty);
|
|
|
36
36
|
var classnames__default = /*#__PURE__*/_interopDefaultLegacy(classnames);
|
|
37
37
|
var debounce__default = /*#__PURE__*/_interopDefaultLegacy(debounce);
|
|
38
38
|
|
|
39
|
-
var css_248z$7 = ".TkdrExYnvcY- {\n
|
|
40
|
-
var styles$7 = {"wrapper":"TkdrExYnvcY-","titleContainer":"IcAlZHoB4LI-","
|
|
39
|
+
var css_248z$7 = ".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.Gj9kAGnfKco- > * {\n font-weight: 500;\n}\n\n.ise8kHCfhCY- {\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.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: center;\n align-items: center;\n -ms-flex-pack: center;\n justify-content: center;\n}\n\n.m-eCShL7TU4- {\n position: sticky;\n top: 50vh;\n}\n\n.xeUxuTlqQtk- {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-pack: center;\n justify-content: center;\n padding: calc(16px / 2);\n padding: var(--space-small);\n}\n";
|
|
40
|
+
var styles$7 = {"wrapper":"TkdrExYnvcY-","titleContainer":"IcAlZHoB4LI-","headerFilters":"TFO76ysivmg-","headerTitles":"jGHZZYZm1ZY-","headerLabel":"Gj9kAGnfKco-","listItem":"ise8kHCfhCY-","filtering":"Kkp-IYmwq-s-","filteringSpinner":"m-eCShL7TU4-","loadingMore":"xeUxuTlqQtk-"};
|
|
41
41
|
styleInject_es.styleInject(css_248z$7);
|
|
42
42
|
|
|
43
|
-
var css_248z$6 = ".
|
|
44
|
-
var styles$6 = {"
|
|
43
|
+
var css_248z$6 = ".F56prQsXm3A- {\n min-width: 80px;\n margin-left: calc(16px / 2);\n margin-left: var(--space-small);\n}\n";
|
|
44
|
+
var styles$6 = {"results":"F56prQsXm3A-"};
|
|
45
45
|
styleInject_es.styleInject(css_248z$6);
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
const DATALIST_TOTALCOUNT_TEST_ID = "ATL-DataList-TotalCount";
|
|
48
|
+
function DataListTotalCount({ totalCount, loading, }) {
|
|
49
|
+
if (totalCount === undefined)
|
|
50
|
+
return null;
|
|
51
|
+
let output = null;
|
|
52
|
+
if (totalCount === null && loading) {
|
|
53
|
+
output = React__default["default"].createElement(Glimmer.Glimmer, { size: "auto", shape: "rectangle" });
|
|
54
|
+
}
|
|
55
|
+
if (typeof totalCount === "number") {
|
|
56
|
+
output = (React__default["default"].createElement(Text.Text, { variation: "subdued" },
|
|
57
|
+
"(",
|
|
58
|
+
totalCount.toLocaleString(),
|
|
59
|
+
" results)"));
|
|
60
|
+
}
|
|
61
|
+
return (React__default["default"].createElement("div", { className: styles$6.results, "data-testid": DATALIST_TOTALCOUNT_TEST_ID }, output));
|
|
51
62
|
}
|
|
52
63
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return React__default["default"].createElement(React__default["default"].Fragment, null);
|
|
57
|
-
}
|
|
64
|
+
var css_248z$5 = ".Rh--6fVpkm4- {\n padding: calc(16px / 2);\n padding: var(--space-small);\n}\n\n.zbS7UvpVoWI- {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-direction: column;\n flex-direction: column;\n -ms-flex-pack: justify;\n justify-content: space-between;\n height: calc(16px * 3);\n height: var(--space-largest);\n padding: calc(16px * 1) 0;\n padding: var(--space-base) 0;\n}\n";
|
|
65
|
+
var styles$5 = {"loadingItem":"Rh--6fVpkm4-","mobileLoadingState":"zbS7UvpVoWI-"};
|
|
66
|
+
styleInject_es.styleInject(css_248z$5);
|
|
58
67
|
|
|
59
|
-
const
|
|
60
|
-
const
|
|
68
|
+
const EMPTY_RESULTS_MESSAGE = "List is looking empty";
|
|
69
|
+
const EMPTY_FILTER_RESULTS_MESSAGE = "No results for selected filters";
|
|
70
|
+
const EMPTY_STATE_ACTION_BUTTON_ONLY_ERROR = "DataListEmptyState action prop must be a Button component";
|
|
61
71
|
/**
|
|
62
72
|
* Breakpoints that we support
|
|
63
73
|
*/
|
|
@@ -70,10 +80,12 @@ const BREAKPOINT_SIZES = {
|
|
|
70
80
|
xl: 1440,
|
|
71
81
|
};
|
|
72
82
|
const SEARCH_DEBOUNCE_DELAY = design.tokens["timing-slowest"];
|
|
83
|
+
const DATA_LIST_FILTERING_SPINNER_TEST_ID = "ATL-DataList-filteringSpinner";
|
|
84
|
+
const DATA_LIST_LOADING_MORE_SPINNER_TEST_ID = "ATL-DataList-loadingMoreSpinner";
|
|
73
85
|
|
|
74
|
-
var css_248z$
|
|
75
|
-
var styles$
|
|
76
|
-
styleInject_es.styleInject(css_248z$
|
|
86
|
+
var css_248z$4 = ".WRV-UmQmPzo- {\n display: -ms-flexbox;\n display: flex;\n position: relative;\n z-index: 0;\n z-index: var(--elevation-default);\n overflow: hidden;\n gap: calc(16px / 2);\n gap: var(--space-small);\n}\n\n.liQeWCMenD0- {\n --overflow-bg: var(--color-white);\n\n display: -ms-flexbox;\n\n display: flex;\n position: absolute;\n top: 0;\n right: 0;\n height: 100%;\n padding-left: calc(16px * 1);\n padding-left: var(--space-base);\n background-image: linear-gradient(\n 90deg,\n transparent 0,\n rgba(255, 255, 255, 1) calc(16px * 1),\n rgba(255, 255, 255, 1) 100%\n );\n background-image: linear-gradient(\n 90deg,\n transparent 0,\n var(--overflow-bg) var(--space-base),\n var(--overflow-bg) 100%\n );\n -ms-flex-align: center;\n align-items: center;\n}\n";
|
|
87
|
+
var styles$4 = {"tags":"WRV-UmQmPzo-","tagCount":"liQeWCMenD0-"};
|
|
88
|
+
styleInject_es.styleInject(css_248z$4);
|
|
77
89
|
|
|
78
90
|
function DataListTags({ items }) {
|
|
79
91
|
const ref = React.useRef(null);
|
|
@@ -95,10 +107,10 @@ function DataListTags({ items }) {
|
|
|
95
107
|
elements === null || elements === void 0 ? void 0 : elements.forEach(element => observer.unobserve(element));
|
|
96
108
|
};
|
|
97
109
|
}, [items]);
|
|
98
|
-
return (React__default["default"].createElement("div", { className: styles$
|
|
110
|
+
return (React__default["default"].createElement("div", { className: styles$4.tags, ref: ref },
|
|
99
111
|
items.filter(Boolean).map((tag, index) => (React__default["default"].createElement("div", { key: tag, "data-tag-element": index },
|
|
100
112
|
React__default["default"].createElement(InlineLabel.InlineLabel, null, tag)))),
|
|
101
|
-
Boolean(visibleItems) && (React__default["default"].createElement("div", { className: styles$
|
|
113
|
+
Boolean(visibleItems) && (React__default["default"].createElement("div", { className: styles$4.tagCount },
|
|
102
114
|
React__default["default"].createElement(Text.Text, null,
|
|
103
115
|
"+",
|
|
104
116
|
visibleItems)))));
|
|
@@ -180,60 +192,10 @@ function generateHeaderElements(headers) {
|
|
|
180
192
|
React__default["default"].createElement(Text.Text, { variation: "subdued", maxLines: "single", size: "small" }, headers[key]))) })), {});
|
|
181
193
|
return isEmpty__default["default"](headerElements) ? undefined : headerElements;
|
|
182
194
|
}
|
|
183
|
-
/**
|
|
184
|
-
* Modify EmptyState to include an empty filter results when filtering happens
|
|
185
|
-
*/
|
|
186
|
-
function generateDataListEmptyState({ children, isFilterApplied, setIsFilterApplied, }) {
|
|
187
|
-
if (!children)
|
|
188
|
-
return;
|
|
189
|
-
const EmptyStateComponent = getCompoundComponent(children, DataListEmptyState);
|
|
190
|
-
if (isFilterApplied && React.isValidElement(EmptyStateComponent)) {
|
|
191
|
-
let overrideEmptyStateProps;
|
|
192
|
-
if (isFilterApplied) {
|
|
193
|
-
overrideEmptyStateProps = {
|
|
194
|
-
message: EMPTY_FILTER_RESULTS_MESSAGE,
|
|
195
|
-
action: {
|
|
196
|
-
label: EMPTY_FILTER_RESULTS_ACTION_LABEL,
|
|
197
|
-
onClick: () => {
|
|
198
|
-
setIsFilterApplied(false);
|
|
199
|
-
alert("Filters Cleared");
|
|
200
|
-
},
|
|
201
|
-
},
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
return React__default["default"].cloneElement(EmptyStateComponent, overrideEmptyStateProps);
|
|
205
|
-
}
|
|
206
|
-
return EmptyStateComponent;
|
|
207
|
-
}
|
|
208
195
|
function sortSizeProp(sizeProp) {
|
|
209
196
|
return sizeProp.sort((a, b) => BREAKPOINTS.indexOf(a) - BREAKPOINTS.indexOf(b));
|
|
210
197
|
}
|
|
211
198
|
|
|
212
|
-
var css_248z$4 = ".F56prQsXm3A- {\n min-width: 80px;\n margin-left: calc(16px / 2);\n margin-left: var(--space-small);\n}\n";
|
|
213
|
-
var styles$4 = {"results":"F56prQsXm3A-"};
|
|
214
|
-
styleInject_es.styleInject(css_248z$4);
|
|
215
|
-
|
|
216
|
-
const DATALIST_TOTALCOUNT_TEST_ID = "ATL-DataList-TotalCount";
|
|
217
|
-
function DataListTotalCount({ totalCount, loading, }) {
|
|
218
|
-
if (totalCount === undefined)
|
|
219
|
-
return null;
|
|
220
|
-
let output = null;
|
|
221
|
-
if (totalCount === null && loading) {
|
|
222
|
-
output = React__default["default"].createElement(Glimmer.Glimmer, { size: "auto", shape: "rectangle" });
|
|
223
|
-
}
|
|
224
|
-
if (typeof totalCount === "number") {
|
|
225
|
-
output = (React__default["default"].createElement(Text.Text, { variation: "subdued" },
|
|
226
|
-
"(",
|
|
227
|
-
totalCount.toLocaleString(),
|
|
228
|
-
" results)"));
|
|
229
|
-
}
|
|
230
|
-
return (React__default["default"].createElement("div", { className: styles$4.results, "data-testid": DATALIST_TOTALCOUNT_TEST_ID }, output));
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
var css_248z$3 = ".Rh--6fVpkm4- {\n padding: calc(16px / 2);\n padding: var(--space-small);\n}\n\n.zbS7UvpVoWI- {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-direction: column;\n flex-direction: column;\n -ms-flex-pack: justify;\n justify-content: space-between;\n height: calc(16px * 3);\n height: var(--space-largest);\n padding: calc(16px * 1) 0;\n padding: var(--space-base) 0;\n}\n";
|
|
234
|
-
var styles$3 = {"loadingItem":"Rh--6fVpkm4-","mobileLoadingState":"zbS7UvpVoWI-"};
|
|
235
|
-
styleInject_es.styleInject(css_248z$3);
|
|
236
|
-
|
|
237
199
|
function DataListLayoutInternal({ layouts, renderLayout, mediaMatches, }) {
|
|
238
200
|
const sizePropsOfLayouts = layouts === null || layouts === void 0 ? void 0 : layouts.map(layout => layout.props.size || "xs");
|
|
239
201
|
const layoutToRender = layouts === null || layouts === void 0 ? void 0 : layouts.find(layout => {
|
|
@@ -292,9 +254,7 @@ function DataListHeader({ layouts, mediaMatches, headerData, headerVisibility, }
|
|
|
292
254
|
|
|
293
255
|
const LOADING_STATE_LIMIT_ITEMS = 10;
|
|
294
256
|
const DATALIST_LOADINGSTATE_ROW_TEST_ID = "ATL-DataList-LoadingState-Row";
|
|
295
|
-
function DataListLoadingState({
|
|
296
|
-
if (!loading)
|
|
297
|
-
return null;
|
|
257
|
+
function DataListLoadingState({ headers, layouts, mediaMatches, }) {
|
|
298
258
|
const loadingData = new Array(LOADING_STATE_LIMIT_ITEMS).fill(headers);
|
|
299
259
|
const loadingElements = loadingData.map(item => Object.keys(item).reduce((acc, key) => {
|
|
300
260
|
acc[key] = React__default["default"].createElement(Glimmer.Glimmer, null);
|
|
@@ -304,42 +264,29 @@ function DataListLoadingState({ loading, headers, layouts, mediaMatches, }) {
|
|
|
304
264
|
if (layout.props.size === "xs") {
|
|
305
265
|
return React__default["default"].createElement(LoadingStateXSBreakpoint, null);
|
|
306
266
|
}
|
|
307
|
-
return (React__default["default"].createElement(React__default["default"].Fragment, null, loadingElements.map((child, i) => (React__default["default"].createElement("div", { className: styles$
|
|
267
|
+
return (React__default["default"].createElement(React__default["default"].Fragment, null, loadingElements.map((child, i) => (React__default["default"].createElement("div", { className: styles$5.loadingItem, key: i, "data-testid": DATALIST_LOADINGSTATE_ROW_TEST_ID }, layout.props.children(child))))));
|
|
308
268
|
} }));
|
|
309
269
|
}
|
|
310
270
|
function LoadingStateXSBreakpoint() {
|
|
311
271
|
const loadingData = new Array(LOADING_STATE_LIMIT_ITEMS).fill(0);
|
|
312
272
|
return (React__default["default"].createElement(React__default["default"].Fragment, null, loadingData.map((_, i) => {
|
|
313
|
-
return (React__default["default"].createElement("div", { className: styles$
|
|
273
|
+
return (React__default["default"].createElement("div", { className: styles$5.mobileLoadingState, key: i },
|
|
314
274
|
React__default["default"].createElement(Glimmer.Glimmer.Text, null)));
|
|
315
275
|
})));
|
|
316
276
|
}
|
|
317
277
|
|
|
318
|
-
function
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
const handlers = BREAKPOINTS.reduce((previous, breakpoint) => {
|
|
323
|
-
const handler = (e) => setMatches(previousMatches => (Object.assign(Object.assign({}, previousMatches), { [breakpoint]: e.matches })));
|
|
324
|
-
return Object.assign(Object.assign({}, previous), { [breakpoint]: handler });
|
|
325
|
-
}, {});
|
|
326
|
-
// Set up mediaQuery event handlers
|
|
327
|
-
React.useEffect(() => {
|
|
328
|
-
BREAKPOINTS.forEach(breakpoint => {
|
|
329
|
-
mediaQueries[breakpoint].addEventListener("change", handlers[breakpoint]);
|
|
330
|
-
});
|
|
331
|
-
return () => {
|
|
332
|
-
BREAKPOINTS.forEach(breakpoint => {
|
|
333
|
-
mediaQueries[breakpoint].removeEventListener("change", handlers[breakpoint]);
|
|
334
|
-
});
|
|
335
|
-
};
|
|
336
|
-
}, [mediaQueries]);
|
|
337
|
-
return matches;
|
|
338
|
-
}
|
|
339
|
-
function breakpointToMediaQuery(breakpoint) {
|
|
340
|
-
return `(min-width: ${BREAKPOINT_SIZES[breakpoint]}px)`;
|
|
278
|
+
function DataListLayout(
|
|
279
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
280
|
+
_) {
|
|
281
|
+
return React__default["default"].createElement(React__default["default"].Fragment, null);
|
|
341
282
|
}
|
|
342
283
|
|
|
284
|
+
var css_248z$3 = ".E-mG3prPSN8- {\n -ms-flex-item-align: center;\n align-self: center;\n position: relative;\n min-width: 0;\n}\n\n._0LGNoZxtqSE- {\n display: grid;\n overflow-x: auto;\n grid-auto-flow: column;\n grid-auto-columns: -webkit-max-content;\n grid-auto-columns: max-content;\n -ms-flex-align: center;\n align-items: center;\n}\n\n._0LGNoZxtqSE- > :nth-child(n + 3):not(:last-child) {\n margin-left: calc(16px / 2);\n margin-left: var(--space-small);\n}\n\n.LA3-gtgehrE- {\n visibility: hidden;\n}\n\n.fSPvawYWzZ8-::before,\n.ChfEJMPPVTk-::after {\n content: \"\";\n position: absolute;\n top: 0;\n width: calc(16px * 1.5);\n width: var(--space-large);\n height: 100%;\n background-image: linear-gradient(\n to right,\n rgba(255, 255, 255, 1) 0%,\n rgba(255, 255, 255, 0) 100%\n );\n background-image: linear-gradient(\n var(--data-list-filters-overflow-shadow-angle, to right),\n var(--color-surface) 0%,\n rgba(var(--color-white--rgb), 0) 100%\n );\n pointer-events: none;\n}\n\n.fSPvawYWzZ8-::before {\n left: 0;\n}\n\n.ChfEJMPPVTk-::after {\n --data-list-filters-overflow-shadow-angle: to left;\n right: 0;\n}\n";
|
|
285
|
+
var styles$3 = {"filters":"E-mG3prPSN8-","filterActions":"_0LGNoZxtqSE-","overflowTrigger":"LA3-gtgehrE-","overflowLeft":"fSPvawYWzZ8-","overflowRight":"ChfEJMPPVTk-"};
|
|
286
|
+
styleInject_es.styleInject(css_248z$3);
|
|
287
|
+
|
|
288
|
+
const CONTAINER_TEST_ID = "ATL-DataListFilters-Container";
|
|
289
|
+
|
|
343
290
|
const defaultValues = {
|
|
344
291
|
title: "",
|
|
345
292
|
data: [],
|
|
@@ -351,12 +298,6 @@ function useDataListContext() {
|
|
|
351
298
|
return React.useContext(DataListContext);
|
|
352
299
|
}
|
|
353
300
|
|
|
354
|
-
var css_248z$2 = ".E-mG3prPSN8- {\n -ms-flex-item-align: center;\n align-self: center;\n position: relative;\n min-width: 0;\n}\n\n._0LGNoZxtqSE- {\n display: grid;\n overflow-x: auto;\n grid-auto-flow: column;\n grid-auto-columns: -webkit-max-content;\n grid-auto-columns: max-content;\n -ms-flex-align: center;\n align-items: center;\n}\n\n._0LGNoZxtqSE- > :nth-child(n + 3):not(:last-child) {\n margin-left: calc(16px / 2);\n margin-left: var(--space-small);\n}\n\n.LA3-gtgehrE- {\n visibility: hidden;\n}\n\n.fSPvawYWzZ8-::before,\n.ChfEJMPPVTk-::after {\n content: \"\";\n position: absolute;\n top: 0;\n width: calc(16px * 1.5);\n width: var(--space-large);\n height: 100%;\n background-image: linear-gradient(\n to right,\n rgba(255, 255, 255, 1) 0%,\n rgba(255, 255, 255, 0) 100%\n );\n background-image: linear-gradient(\n var(--data-list-filters-overflow-shadow-angle, to right),\n var(--color-surface) 0%,\n rgba(var(--color-white--rgb), 0) 100%\n );\n pointer-events: none;\n}\n\n.fSPvawYWzZ8-::before {\n left: 0;\n}\n\n.ChfEJMPPVTk-::after {\n --data-list-filters-overflow-shadow-angle: to left;\n right: 0;\n}\n";
|
|
355
|
-
var styles$2 = {"filters":"E-mG3prPSN8-","filterActions":"_0LGNoZxtqSE-","overflowTrigger":"LA3-gtgehrE-","overflowLeft":"fSPvawYWzZ8-","overflowRight":"ChfEJMPPVTk-"};
|
|
356
|
-
styleInject_es.styleInject(css_248z$2);
|
|
357
|
-
|
|
358
|
-
const CONTAINER_TEST_ID = "ATL-DataListFilters-Container";
|
|
359
|
-
|
|
360
301
|
// This component is meant to capture the props of the DataList.Filters
|
|
361
302
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
362
303
|
function DataListFilters(_) {
|
|
@@ -373,14 +314,34 @@ function InternalDataListFilters() {
|
|
|
373
314
|
if (!component)
|
|
374
315
|
return null;
|
|
375
316
|
const { children } = component.props;
|
|
376
|
-
return (React__default["default"].createElement("div", { "data-testid": CONTAINER_TEST_ID, className: classnames__default["default"](styles$
|
|
377
|
-
[styles$
|
|
378
|
-
[styles$
|
|
317
|
+
return (React__default["default"].createElement("div", { "data-testid": CONTAINER_TEST_ID, className: classnames__default["default"](styles$3.filters, {
|
|
318
|
+
[styles$3.overflowLeft]: !isLeftVisible,
|
|
319
|
+
[styles$3.overflowRight]: !isRightVisible,
|
|
379
320
|
}) },
|
|
380
|
-
React__default["default"].createElement("div", { className: styles$
|
|
381
|
-
React__default["default"].createElement("span", { ref: leftRef, className: styles$
|
|
321
|
+
React__default["default"].createElement("div", { className: styles$3.filterActions },
|
|
322
|
+
React__default["default"].createElement("span", { ref: leftRef, className: styles$3.overflowTrigger }),
|
|
382
323
|
children,
|
|
383
|
-
React__default["default"].createElement("span", { ref: rightRef, className: styles$
|
|
324
|
+
React__default["default"].createElement("span", { ref: rightRef, className: styles$3.overflowTrigger }))));
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
var css_248z$2 = ".PGOHzrMh374- {\n --offset: 1px;\n --sticky-header-transition-properties: var(--timing-base) ease-in-out;\n\n position: sticky;\n top: calc(1px * -1);\n top: calc(var(--offset) * -1);\n z-index: 1;\n z-index: var(--elevation-base);\n padding-top: 1px;\n padding-top: var(--offset);\n background-color: rgba(255, 255, 255, 1);\n background-color: var(--color-surface);\n}\n\n/**\n * Draw a border that gets covered by the column headers border when it shows up.\n *\n * Mostly to prevent us from writing some complex JS to remove the border when\n * the column headers show up.\n */\n\n.PGOHzrMh374-::before {\n content: \"\";\n display: block;\n position: absolute;\n bottom: 0;\n left: 50%;\n z-index: -1;\n width: 0;\n height: 0;\n background-color: rgb(225, 225, 225);\n background-color: var(--color-border);\n -webkit-transform: translateX(-50%);\n transform: translateX(-50%);\n transition: height var(--sticky-header-transition-properties)\n 100ms,\n width var(--sticky-header-transition-properties);\n transition: height var(--sticky-header-transition-properties)\n var(--timing-quick),\n width var(--sticky-header-transition-properties);\n}\n\n.PGjWc5ocjpI-::before {\n width: 100%;\n height: calc(16px / 8);\n height: var(--border-thick);\n transition: height var(--sticky-header-transition-properties),\n width var(--sticky-header-transition-properties) 100ms;\n transition: height var(--sticky-header-transition-properties),\n width var(--sticky-header-transition-properties) var(--timing-quick);\n}\n";
|
|
328
|
+
var styles$2 = {"header":"PGOHzrMh374-","stuck":"PGjWc5ocjpI-"};
|
|
329
|
+
styleInject_es.styleInject(css_248z$2);
|
|
330
|
+
|
|
331
|
+
function DataListStickyHeader({ children }) {
|
|
332
|
+
const [isStuck, setIsStuck] = React.useState(false);
|
|
333
|
+
const ref = React.useRef(null);
|
|
334
|
+
const handleObserver = React.useCallback(([e]) => setIsStuck(e.intersectionRatio < 1), [setIsStuck]);
|
|
335
|
+
React.useEffect(() => {
|
|
336
|
+
if (!window.IntersectionObserver)
|
|
337
|
+
return;
|
|
338
|
+
const observer = new IntersectionObserver(handleObserver, { threshold: 1 });
|
|
339
|
+
ref.current && observer.observe(ref.current);
|
|
340
|
+
return () => {
|
|
341
|
+
ref.current && observer.unobserve(ref.current);
|
|
342
|
+
};
|
|
343
|
+
}, [handleObserver, ref.current]);
|
|
344
|
+
return (React__default["default"].createElement("div", { ref: ref, className: classnames__default["default"](styles$2.header, { [styles$2.stuck]: isStuck }) }, children));
|
|
384
345
|
}
|
|
385
346
|
|
|
386
347
|
var css_248z$1 = ".SaPMOnvw-3c- {\n --transition-properties: var(--timing-base) ease-in-out;\n --button-offset: calc(var(--space-largest) - var(--space-smallest));\n\n position: absolute;\n /* Inputs are off by 1 when put beside a button */\n top: calc((16px / 2) - 1px);\n top: calc(calc(16px / 2) - 1px);\n top: calc(var(--space-small) - 1px);\n right: calc((16px * 3) - (16px / 8));\n right: calc(calc(16px * 3) - calc(16px / 8));\n right: var(--button-offset);\n visibility: hidden;\n width: 0;\n opacity: 0;\n transition: opacity 200ms ease-in-out,\n width 200ms ease-in-out, visibility 200ms ease-in-out;\n transition: opacity var(--transition-properties),\n width var(--transition-properties), visibility var(--transition-properties);\n}\n\n._3S1-91v2SYI- {\n visibility: visible;\n width: calc(100% - var(--button-offset));\n opacity: 1;\n}\n\n@media (min-width: 768px) {\n\n.SaPMOnvw-3c-,\n._3S1-91v2SYI- {\n position: static;\n visibility: visible;\n width: auto;\n opacity: 1;\n transition: none;\n}\n }\n\n@media (--medium-screens-and-up) {\n\n.SaPMOnvw-3c-,\n._3S1-91v2SYI- {\n position: static;\n visibility: visible;\n width: auto;\n opacity: 1;\n transition: none;\n}\n }\n\n._9GlBktsUALw- {\n display: block;\n}\n\n@media (min-width: 768px) {\n\n._9GlBktsUALw- {\n display: none;\n}\n }\n\n@media (--medium-screens-and-up) {\n\n._9GlBktsUALw- {\n display: none;\n}\n }\n\n/*\n * No Filters Styling\n *\n * When there are no filters, the search input is always visible.\n * ------------------------------------------------------------------------- */\n\n._3Pjrt42x454- .SaPMOnvw-3c- {\n position: static;\n visibility: visible;\n width: auto;\n opacity: 1;\n transition: none;\n}\n\n@media (min-width: 768px) {\n\n._3Pjrt42x454- .SaPMOnvw-3c- {\n max-width: 30%;\n}\n }\n\n@media (--medium-screens-and-up) {\n\n._3Pjrt42x454- .SaPMOnvw-3c- {\n max-width: 30%;\n}\n }\n\n._3Pjrt42x454- ._9GlBktsUALw- {\n display: none;\n}\n";
|
|
@@ -427,56 +388,110 @@ function InternalDataListSearch() {
|
|
|
427
388
|
}
|
|
428
389
|
}
|
|
429
390
|
|
|
430
|
-
var css_248z = ".
|
|
431
|
-
var styles = {"
|
|
391
|
+
var css_248z = ".zg3w9nQga-M- {\n display: -ms-flexbox;\n display: flex;\n box-sizing: border-box;\n padding: calc(16px * 1);\n padding: var(--space-base);\n -ms-flex-pack: center;\n justify-content: center;\n -ms-flex-direction: column;\n flex-direction: column;\n row-gap: calc(16px * 1);\n row-gap: var(--space-base);\n -ms-flex-align: center;\n align-items: center;\n -ms-flex: 1;\n flex: 1;\n}\n";
|
|
392
|
+
var styles = {"emptyStateWrapper":"zg3w9nQga-M-"};
|
|
432
393
|
styleInject_es.styleInject(css_248z);
|
|
433
394
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
395
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
396
|
+
function DataListEmptyState(_) {
|
|
397
|
+
return null;
|
|
398
|
+
}
|
|
399
|
+
function InternalDataListEmptyState() {
|
|
400
|
+
const { emptyStateComponents: components, filtered } = React.useContext(DataListContext);
|
|
401
|
+
const { message, action } = getMessages();
|
|
402
|
+
return (React__default["default"].createElement("div", { className: styles.emptyStateWrapper },
|
|
403
|
+
React__default["default"].createElement(Text.Text, { align: "center" }, message),
|
|
404
|
+
renderButton(action)));
|
|
405
|
+
function getMessages() {
|
|
406
|
+
const { defaultEmptyState, filteredEmptyState } = getEmptyStates(components);
|
|
407
|
+
if (filtered) {
|
|
408
|
+
return {
|
|
409
|
+
message: (filteredEmptyState === null || filteredEmptyState === void 0 ? void 0 : filteredEmptyState.props.message) || EMPTY_FILTER_RESULTS_MESSAGE,
|
|
410
|
+
action: filteredEmptyState === null || filteredEmptyState === void 0 ? void 0 : filteredEmptyState.props.action,
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
return {
|
|
414
|
+
message: (defaultEmptyState === null || defaultEmptyState === void 0 ? void 0 : defaultEmptyState.props.message) || EMPTY_RESULTS_MESSAGE,
|
|
415
|
+
action: defaultEmptyState === null || defaultEmptyState === void 0 ? void 0 : defaultEmptyState.props.action,
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
function renderButton(action) {
|
|
420
|
+
if (action) {
|
|
421
|
+
if (action.type === Button.Button) {
|
|
422
|
+
return React.cloneElement(action, {
|
|
423
|
+
variation: action.props.variation || "subtle",
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
throw new Error(EMPTY_STATE_ACTION_BUTTON_ONLY_ERROR);
|
|
427
|
+
}
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
function getEmptyStates(components) {
|
|
431
|
+
const defaultEmptyState = components === null || components === void 0 ? void 0 : components.find(es => es.props.type === "empty" || es.props.type === undefined);
|
|
432
|
+
const filteredEmptyState = components === null || components === void 0 ? void 0 : components.find(es => es.props.type === "filtered");
|
|
433
|
+
return { defaultEmptyState, filteredEmptyState };
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
function useLayoutMediaQueries() {
|
|
437
|
+
const mediaQueries = BREAKPOINTS.reduce((previous, breakpoint) => (Object.assign(Object.assign({}, previous), { [breakpoint]: window.matchMedia(breakpointToMediaQuery(breakpoint)) })), {});
|
|
438
|
+
const initialMatches = BREAKPOINTS.reduce((previous, breakpoint) => (Object.assign(Object.assign({}, previous), { [breakpoint]: mediaQueries[breakpoint].matches })), {});
|
|
439
|
+
const [matches, setMatches] = React.useState(initialMatches);
|
|
440
|
+
const handlers = BREAKPOINTS.reduce((previous, breakpoint) => {
|
|
441
|
+
const handler = (e) => setMatches(previousMatches => (Object.assign(Object.assign({}, previousMatches), { [breakpoint]: e.matches })));
|
|
442
|
+
return Object.assign(Object.assign({}, previous), { [breakpoint]: handler });
|
|
443
|
+
}, {});
|
|
444
|
+
// Set up mediaQuery event handlers
|
|
438
445
|
React.useEffect(() => {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
ref.current && observer.observe(ref.current);
|
|
446
|
+
BREAKPOINTS.forEach(breakpoint => {
|
|
447
|
+
mediaQueries[breakpoint].addEventListener("change", handlers[breakpoint]);
|
|
448
|
+
});
|
|
443
449
|
return () => {
|
|
444
|
-
|
|
450
|
+
BREAKPOINTS.forEach(breakpoint => {
|
|
451
|
+
mediaQueries[breakpoint].removeEventListener("change", handlers[breakpoint]);
|
|
452
|
+
});
|
|
445
453
|
};
|
|
446
|
-
}, [
|
|
447
|
-
return
|
|
454
|
+
}, [mediaQueries]);
|
|
455
|
+
return matches;
|
|
456
|
+
}
|
|
457
|
+
function breakpointToMediaQuery(breakpoint) {
|
|
458
|
+
return `(min-width: ${BREAKPOINT_SIZES[breakpoint]}px)`;
|
|
448
459
|
}
|
|
449
460
|
|
|
450
461
|
function DataList(props) {
|
|
451
462
|
const searchComponent = getCompoundComponent(props.children, DataListSearch);
|
|
452
463
|
const filterComponent = getCompoundComponent(props.children, DataListFilters);
|
|
453
|
-
|
|
464
|
+
const layoutComponents = getCompoundComponents(props.children, DataListLayout);
|
|
465
|
+
const emptyStateComponents = getCompoundComponents(props.children, DataListEmptyState);
|
|
466
|
+
return (React__default["default"].createElement(DataListContext.Provider, { value: Object.assign({ searchComponent,
|
|
467
|
+
filterComponent,
|
|
468
|
+
layoutComponents,
|
|
469
|
+
emptyStateComponents }, props) },
|
|
454
470
|
React__default["default"].createElement(InternalDataList, null)));
|
|
455
471
|
}
|
|
456
472
|
function InternalDataList() {
|
|
457
|
-
const { data, headers,
|
|
458
|
-
const allLayouts = getCompoundComponents(children, DataListLayout);
|
|
473
|
+
const { data, headers, title, totalCount, headerVisibility = { xs: true, sm: true, md: true, lg: true, xl: true }, loadingState = "none", layoutComponents, } = useDataListContext();
|
|
459
474
|
const headerData = generateHeaderElements(headers);
|
|
460
475
|
const mediaMatches = useLayoutMediaQueries();
|
|
461
|
-
const
|
|
462
|
-
const
|
|
463
|
-
const EmptyStateComponent = generateDataListEmptyState({
|
|
464
|
-
children,
|
|
465
|
-
isFilterApplied,
|
|
466
|
-
setIsFilterApplied,
|
|
467
|
-
});
|
|
476
|
+
const initialLoading = loadingState === "initial";
|
|
477
|
+
const showEmptyState = !initialLoading && data.length === 0;
|
|
468
478
|
return (React__default["default"].createElement("div", { className: styles$7.wrapper },
|
|
469
479
|
React__default["default"].createElement("div", { className: styles$7.titleContainer },
|
|
470
480
|
title && React__default["default"].createElement(Heading.Heading, { level: 3 }, title),
|
|
471
|
-
React__default["default"].createElement(DataListTotalCount, { totalCount: totalCount, loading:
|
|
481
|
+
React__default["default"].createElement(DataListTotalCount, { totalCount: totalCount, loading: initialLoading })),
|
|
472
482
|
React__default["default"].createElement(DataListStickyHeader, null,
|
|
473
483
|
React__default["default"].createElement("div", { className: styles$7.headerFilters },
|
|
474
484
|
React__default["default"].createElement(InternalDataListFilters, null),
|
|
475
485
|
React__default["default"].createElement(InternalDataListSearch, null)),
|
|
476
|
-
headerData && (React__default["default"].createElement(DataListHeader, { layouts:
|
|
477
|
-
React__default["default"].createElement(DataListLoadingState, {
|
|
478
|
-
|
|
479
|
-
|
|
486
|
+
headerData && (React__default["default"].createElement(DataListHeader, { layouts: layoutComponents, headerData: headerData, headerVisibility: headerVisibility, mediaMatches: mediaMatches }))),
|
|
487
|
+
initialLoading && (React__default["default"].createElement(DataListLoadingState, { headers: headers, layouts: layoutComponents, mediaMatches: mediaMatches })),
|
|
488
|
+
showEmptyState && React__default["default"].createElement(InternalDataListEmptyState, null),
|
|
489
|
+
!initialLoading && (React__default["default"].createElement(DataListItems, { data: data, layouts: layoutComponents, mediaMatches: mediaMatches })),
|
|
490
|
+
loadingState === "filtering" && (React__default["default"].createElement("div", { "data-testid": DATA_LIST_FILTERING_SPINNER_TEST_ID, className: styles$7.filtering },
|
|
491
|
+
React__default["default"].createElement("div", { className: styles$7.filteringSpinner },
|
|
492
|
+
React__default["default"].createElement(Spinner.Spinner, { size: "small" })))),
|
|
493
|
+
loadingState === "loadingMore" && (React__default["default"].createElement("div", { "data-testid": DATA_LIST_LOADING_MORE_SPINNER_TEST_ID, className: styles$7.loadingMore },
|
|
494
|
+
React__default["default"].createElement(Spinner.Spinner, { size: "small" })))));
|
|
480
495
|
}
|
|
481
496
|
DataList.Layout = DataListLayout;
|
|
482
497
|
DataList.EmptyState = DataListEmptyState;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jobber/components",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.32.1",
|
|
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": "
|
|
87
|
+
"gitHead": "71e830b2c91ff606f62100920e4ece78daa79b4b"
|
|
88
88
|
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/// <reference types="react" />
|
|
2
|
-
import { XOR } from "ts-xor";
|
|
3
|
-
import { ButtonProps } from "../../../Button";
|
|
4
|
-
interface ActionBase {
|
|
5
|
-
label: string;
|
|
6
|
-
}
|
|
7
|
-
interface AnchorAction extends ActionBase {
|
|
8
|
-
url: ButtonProps["url"];
|
|
9
|
-
}
|
|
10
|
-
interface LinkAction extends ActionBase {
|
|
11
|
-
to: ButtonProps["to"];
|
|
12
|
-
}
|
|
13
|
-
interface ClickAction extends ActionBase {
|
|
14
|
-
onClick: ButtonProps["onClick"];
|
|
15
|
-
}
|
|
16
|
-
export interface EmptyStateProps {
|
|
17
|
-
message: string;
|
|
18
|
-
action?: XOR<ClickAction, XOR<AnchorAction, LinkAction>>;
|
|
19
|
-
}
|
|
20
|
-
export declare function DataListEmptyState({ message, action }: EmptyStateProps): JSX.Element;
|
|
21
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { DataListEmptyState as EmptyState, EmptyStateProps, } from "./EmptyState";
|