@jobber/components 4.34.0 → 4.36.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.
- package/dist/DataList/DataList.const.d.ts +2 -0
- package/dist/DataList/DataList.d.ts +4 -0
- package/dist/DataList/DataList.types.d.ts +39 -0
- package/dist/DataList/components/DataListAction/DataListAction.d.ts +4 -0
- package/dist/DataList/components/DataListAction/index.d.ts +1 -0
- package/dist/DataList/components/DataListActionsMenu/DataListActionsMenu.d.ts +11 -0
- package/dist/DataList/components/DataListActionsMenu/index.d.ts +1 -0
- package/dist/DataList/components/DataListItemActions/DataListItemActions.d.ts +8 -0
- package/dist/DataList/components/DataListItemActions/DataListItemActionsOverflow.d.ts +7 -0
- package/dist/DataList/components/DataListItemActions/index.d.ts +1 -0
- package/dist/DataList/components/DataListLayoutInternal/DataListItemInternal.d.ts +8 -0
- package/dist/DataList/context/DataListContext/DataListContext.d.ts +1 -0
- package/dist/DataList/index.js +208 -45
- package/package.json +3 -3
|
@@ -15,4 +15,6 @@ export declare const SEARCH_DEBOUNCE_DELAY: number;
|
|
|
15
15
|
export declare const DATA_LIST_FILTERING_SPINNER_TEST_ID = "ATL-DataList-filteringSpinner";
|
|
16
16
|
export declare const DATA_LIST_LOADING_MORE_SPINNER_TEST_ID = "ATL-DataList-loadingMoreSpinner";
|
|
17
17
|
export declare const DATA_LOAD_MORE_TEST_ID = "ATL-DataList-LoadMore-trigger";
|
|
18
|
+
export declare const TRANSITION_DURATION_IN_SECONDS: number;
|
|
19
|
+
export declare const TRANSITION_DELAY_IN_SECONDS: number;
|
|
18
20
|
export {};
|
|
@@ -4,10 +4,14 @@ import { DataListFilters } from "./components/DataListFilters";
|
|
|
4
4
|
import { DataListSearch } from "./components/DataListSearch";
|
|
5
5
|
import { DataListEmptyState } from "./components/DataListEmptyState";
|
|
6
6
|
import { DataListObject, DataListProps } from "./DataList.types";
|
|
7
|
+
import { DataListItemActions } from "./components/DataListItemActions";
|
|
8
|
+
import { DataListAction } from "./components/DataListAction";
|
|
7
9
|
export declare function DataList<T extends DataListObject>(props: DataListProps<T>): JSX.Element;
|
|
8
10
|
export declare namespace DataList {
|
|
9
11
|
var Layout: typeof DataListLayout;
|
|
10
12
|
var EmptyState: typeof DataListEmptyState;
|
|
11
13
|
var Filters: typeof DataListFilters;
|
|
12
14
|
var Search: typeof DataListSearch;
|
|
15
|
+
var ItemActions: typeof DataListItemActions;
|
|
16
|
+
var Action: typeof DataListAction;
|
|
13
17
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ReactElement, ReactNode } from "react";
|
|
2
|
+
import { IconNames } from "@jobber/design";
|
|
2
3
|
import { Breakpoints } from "./DataList.const";
|
|
3
4
|
import { ButtonProps } from "../Button";
|
|
4
5
|
export { Breakpoints } from "./DataList.const";
|
|
@@ -76,6 +77,14 @@ export interface DataListProps<T extends DataListObject> {
|
|
|
76
77
|
* The callback function when the user scrolls to the bottom of the list.
|
|
77
78
|
*/
|
|
78
79
|
readonly onLoadMore?: () => void;
|
|
80
|
+
/**
|
|
81
|
+
* Callback when an item checkbox is clicked.
|
|
82
|
+
*/
|
|
83
|
+
readonly onSelect?: (items: T["id"][]) => void;
|
|
84
|
+
/**
|
|
85
|
+
* The list of Selected Item ids
|
|
86
|
+
*/
|
|
87
|
+
readonly selected?: T["id"][];
|
|
79
88
|
}
|
|
80
89
|
export interface DataListLayoutProps<T extends DataListObject> {
|
|
81
90
|
readonly children: (item: DataListItemType<T[]>) => JSX.Element;
|
|
@@ -122,4 +131,34 @@ export interface DataListContextProps<T extends DataListObject> extends DataList
|
|
|
122
131
|
readonly searchComponent?: ReactElement<DataListSearchProps>;
|
|
123
132
|
readonly emptyStateComponents?: ReactElement<DataListEmptyStateProps>[];
|
|
124
133
|
readonly layoutComponents?: ReactElement<DataListLayoutProps<T>>[];
|
|
134
|
+
readonly itemActionComponent?: ReactElement<DataListItemActionsProps<T>>;
|
|
135
|
+
}
|
|
136
|
+
type Fragment<T> = T | T[];
|
|
137
|
+
export interface DataListItemActionsProps<T extends DataListObject> {
|
|
138
|
+
/**
|
|
139
|
+
* The actions to render for each item in the DataList. This only accepts the
|
|
140
|
+
* DataList.Action component.
|
|
141
|
+
*/
|
|
142
|
+
readonly children?: Fragment<ReactElement<DataListActionProps<T>>>;
|
|
143
|
+
}
|
|
144
|
+
export interface DataListActionProps<T extends DataListObject> {
|
|
145
|
+
/**
|
|
146
|
+
* The label of the action
|
|
147
|
+
*/
|
|
148
|
+
readonly label: string;
|
|
149
|
+
/**
|
|
150
|
+
* The icon beside the label
|
|
151
|
+
*/
|
|
152
|
+
readonly icon?: IconNames;
|
|
153
|
+
/**
|
|
154
|
+
* Adjust the styling of an action label and icon to be more destructive.
|
|
155
|
+
*/
|
|
156
|
+
readonly destructive?: boolean;
|
|
157
|
+
/**
|
|
158
|
+
* The callback function when the action is clicked.
|
|
159
|
+
*/
|
|
160
|
+
readonly onClick?: (data: T) => void;
|
|
161
|
+
}
|
|
162
|
+
export interface InternalDataListActionProps<T extends DataListObject> extends DataListActionProps<T> {
|
|
163
|
+
readonly item: T;
|
|
125
164
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { DataListActionProps, DataListObject, InternalDataListActionProps } from "../../DataList.types";
|
|
3
|
+
export declare function DataListAction<T extends DataListObject>(_: DataListActionProps<T>): null;
|
|
4
|
+
export declare function InternalDataListAction<T extends DataListObject>({ label, icon, destructive, onClick, item, }: InternalDataListActionProps<T>): JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./DataListAction";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { PropsWithChildren } from "react";
|
|
2
|
+
interface DataListActionsMenuProps {
|
|
3
|
+
readonly visible: boolean;
|
|
4
|
+
readonly position: {
|
|
5
|
+
readonly x: number;
|
|
6
|
+
readonly y: number;
|
|
7
|
+
};
|
|
8
|
+
readonly onRequestClose: () => void;
|
|
9
|
+
}
|
|
10
|
+
export declare function DataListActionsMenu({ visible, position, onRequestClose, children, }: PropsWithChildren<DataListActionsMenuProps>): JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./DataListActionsMenu";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { DataListItemActionsProps, DataListObject } from "../../DataList.types";
|
|
3
|
+
export declare function DataListItemActions<T extends DataListObject>(_: DataListItemActionsProps<T>): null;
|
|
4
|
+
interface InternalDataListItemActionsProps<T extends DataListObject> {
|
|
5
|
+
readonly item: T;
|
|
6
|
+
}
|
|
7
|
+
export declare function InternalDataListItemActions<T extends DataListObject>({ item, }: InternalDataListItemActionsProps<T>): JSX.Element | null;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ReactElement } from "react";
|
|
2
|
+
import { DataListActionProps, DataListObject, InternalDataListActionProps } from "../../DataList.types";
|
|
3
|
+
interface DataListItemActionsOverflowProps<T extends DataListObject> extends Pick<InternalDataListActionProps<T>, "item"> {
|
|
4
|
+
readonly actions: ReactElement<DataListActionProps<T>>[];
|
|
5
|
+
}
|
|
6
|
+
export declare function DataListItemActionsOverflow<T extends DataListObject>({ item, actions, }: DataListItemActionsOverflowProps<T>): JSX.Element;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./DataListItemActions";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { DataListObject } from "../../DataList.types";
|
|
3
|
+
interface ListItemInternalProps<T extends DataListObject> {
|
|
4
|
+
readonly children: JSX.Element;
|
|
5
|
+
readonly item: T;
|
|
6
|
+
}
|
|
7
|
+
export declare function DataListItemInternal<T extends DataListObject>({ children, item, }: ListItemInternalProps<T>): JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -5,6 +5,7 @@ export declare const defaultValues: {
|
|
|
5
5
|
data: never[];
|
|
6
6
|
headers: {};
|
|
7
7
|
children: never[];
|
|
8
|
+
selected: never[];
|
|
8
9
|
};
|
|
9
10
|
export declare const DataListContext: import("react").Context<DataListContextProps<DataListObject>>;
|
|
10
11
|
export declare function useDataListContext(): DataListContextProps<DataListObject>;
|
package/dist/DataList/index.js
CHANGED
|
@@ -6,28 +6,35 @@ var React = require('react');
|
|
|
6
6
|
var styleInject_es = require('../style-inject.es-9d2f5f4e.js');
|
|
7
7
|
var Text = require('../Text-e7ed0974.js');
|
|
8
8
|
var Glimmer = require('../Glimmer-cfa92a88.js');
|
|
9
|
+
var framerMotion = require('framer-motion');
|
|
9
10
|
var design = require('@jobber/design');
|
|
10
11
|
var isEmpty = require('lodash/isEmpty');
|
|
11
12
|
var InlineLabel = require('../InlineLabel-afd5fc6f.js');
|
|
12
13
|
var FormatDate = require('../FormatDate-70ea5b43.js');
|
|
13
14
|
var Heading = require('../Heading-a1191b15.js');
|
|
14
15
|
var classnames = require('classnames');
|
|
15
|
-
require('
|
|
16
|
+
require('uuid');
|
|
17
|
+
require('react-hook-form');
|
|
18
|
+
var Checkbox = require('../Checkbox-3bccf65c.js');
|
|
19
|
+
var Typography = require('../Typography-fd6f932a.js');
|
|
20
|
+
require('react-router-dom');
|
|
21
|
+
var Button = require('../Button-7698424c.js');
|
|
22
|
+
require('react-dom');
|
|
23
|
+
var Tooltip = require('../Tooltip-bf67fe6e.js');
|
|
24
|
+
require('react-popper');
|
|
25
|
+
var useFocusTrap = require('@jobber/hooks/useFocusTrap');
|
|
26
|
+
var useRefocusOnActivator = require('@jobber/hooks/useRefocusOnActivator');
|
|
27
|
+
var useOnKeyDown = require('@jobber/hooks/useOnKeyDown');
|
|
28
|
+
var Icon = require('../Icon-405a216c.js');
|
|
16
29
|
var useInView = require('@jobber/hooks/useInView');
|
|
17
30
|
var debounce = require('lodash/debounce');
|
|
18
31
|
var InputText = require('../InputText-bb03f6d1.js');
|
|
19
|
-
var Button = require('../Button-7698424c.js');
|
|
20
32
|
var AnimatedSwitcher = require('../AnimatedSwitcher-d1e1ddcf.js');
|
|
21
33
|
var Spinner = require('../Spinner-9d8fc7ff.js');
|
|
22
34
|
require('../tslib.es6-5b8768b7.js');
|
|
23
35
|
require('../Content-2ca1ffe1.js');
|
|
24
36
|
require('../FormField-0f880b07.js');
|
|
25
|
-
require('uuid');
|
|
26
|
-
require('react-hook-form');
|
|
27
|
-
require('../Icon-405a216c.js');
|
|
28
37
|
require('../InputValidation-b5a3d92c.js');
|
|
29
|
-
require('framer-motion');
|
|
30
|
-
require('react-router-dom');
|
|
31
38
|
|
|
32
39
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
33
40
|
|
|
@@ -36,13 +43,13 @@ var isEmpty__default = /*#__PURE__*/_interopDefaultLegacy(isEmpty);
|
|
|
36
43
|
var classnames__default = /*#__PURE__*/_interopDefaultLegacy(classnames);
|
|
37
44
|
var debounce__default = /*#__PURE__*/_interopDefaultLegacy(debounce);
|
|
38
45
|
|
|
39
|
-
var css_248z$
|
|
40
|
-
var styles$
|
|
41
|
-
styleInject_es.styleInject(css_248z$
|
|
46
|
+
var css_248z$b = ".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 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$b = {"wrapper":"TkdrExYnvcY-","titleContainer":"IcAlZHoB4LI-","headerFilters":"TFO76ysivmg-","headerTitles":"jGHZZYZm1ZY-","headerLabel":"Gj9kAGnfKco-","listItem":"ise8kHCfhCY-","selectable":"d-79rkMqufg-","selected":"_4L7iXXzLr5k-","filtering":"Kkp-IYmwq-s-","filteringSpinner":"m-eCShL7TU4-"};
|
|
48
|
+
styleInject_es.styleInject(css_248z$b);
|
|
42
49
|
|
|
43
|
-
var css_248z$
|
|
44
|
-
var styles$
|
|
45
|
-
styleInject_es.styleInject(css_248z$
|
|
50
|
+
var css_248z$a = ".F56prQsXm3A- {\n min-width: 80px;\n margin-left: calc(16px / 2);\n margin-left: var(--space-small);\n}\n";
|
|
51
|
+
var styles$a = {"results":"F56prQsXm3A-"};
|
|
52
|
+
styleInject_es.styleInject(css_248z$a);
|
|
46
53
|
|
|
47
54
|
const DATALIST_TOTALCOUNT_TEST_ID = "ATL-DataList-TotalCount";
|
|
48
55
|
function DataListTotalCount({ totalCount, loading, }) {
|
|
@@ -58,12 +65,12 @@ function DataListTotalCount({ totalCount, loading, }) {
|
|
|
58
65
|
totalCount.toLocaleString(),
|
|
59
66
|
" results)"));
|
|
60
67
|
}
|
|
61
|
-
return (React__default["default"].createElement("div", { className: styles$
|
|
68
|
+
return (React__default["default"].createElement("div", { className: styles$a.results, "data-testid": DATALIST_TOTALCOUNT_TEST_ID }, output));
|
|
62
69
|
}
|
|
63
70
|
|
|
64
|
-
var css_248z$
|
|
65
|
-
var styles$
|
|
66
|
-
styleInject_es.styleInject(css_248z$
|
|
71
|
+
var css_248z$9 = ".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";
|
|
72
|
+
var styles$9 = {"loadingItem":"Rh--6fVpkm4-","mobileLoadingState":"zbS7UvpVoWI-"};
|
|
73
|
+
styleInject_es.styleInject(css_248z$9);
|
|
67
74
|
|
|
68
75
|
const EMPTY_RESULTS_MESSAGE = "List is looking empty";
|
|
69
76
|
const EMPTY_FILTER_RESULTS_MESSAGE = "No results for selected filters";
|
|
@@ -83,10 +90,12 @@ const SEARCH_DEBOUNCE_DELAY = design.tokens["timing-slowest"];
|
|
|
83
90
|
const DATA_LIST_FILTERING_SPINNER_TEST_ID = "ATL-DataList-filteringSpinner";
|
|
84
91
|
const DATA_LIST_LOADING_MORE_SPINNER_TEST_ID = "ATL-DataList-loadingMoreSpinner";
|
|
85
92
|
const DATA_LOAD_MORE_TEST_ID = "ATL-DataList-LoadMore-trigger";
|
|
93
|
+
const TRANSITION_DURATION_IN_SECONDS = design.tokens["timing-base"] / 1000;
|
|
94
|
+
const TRANSITION_DELAY_IN_SECONDS = design.tokens["timing-quick"] / 1000;
|
|
86
95
|
|
|
87
|
-
var css_248z$
|
|
88
|
-
var styles$
|
|
89
|
-
styleInject_es.styleInject(css_248z$
|
|
96
|
+
var css_248z$8 = ".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";
|
|
97
|
+
var styles$8 = {"tags":"WRV-UmQmPzo-","tagCount":"liQeWCMenD0-"};
|
|
98
|
+
styleInject_es.styleInject(css_248z$8);
|
|
90
99
|
|
|
91
100
|
function DataListTags({ items }) {
|
|
92
101
|
const ref = React.useRef(null);
|
|
@@ -106,10 +115,10 @@ function DataListTags({ items }) {
|
|
|
106
115
|
elements === null || elements === void 0 ? void 0 : elements.forEach(element => observer.unobserve(element));
|
|
107
116
|
};
|
|
108
117
|
}, [items]);
|
|
109
|
-
return (React__default["default"].createElement("div", { className: styles$
|
|
118
|
+
return (React__default["default"].createElement("div", { className: styles$8.tags, ref: ref },
|
|
110
119
|
items.filter(Boolean).map((tag, index) => (React__default["default"].createElement("div", { key: tag, "data-tag-element": index },
|
|
111
120
|
React__default["default"].createElement(InlineLabel.InlineLabel, null, tag)))),
|
|
112
|
-
Boolean(visibleItems) && (React__default["default"].createElement("div", { className: styles$
|
|
121
|
+
Boolean(visibleItems) && (React__default["default"].createElement("div", { className: styles$8.tagCount },
|
|
113
122
|
React__default["default"].createElement(Text.Text, null,
|
|
114
123
|
"+",
|
|
115
124
|
visibleItems)))));
|
|
@@ -187,7 +196,7 @@ function generateListItemElements(data) {
|
|
|
187
196
|
* Generate the header elements with the default styling
|
|
188
197
|
*/
|
|
189
198
|
function generateHeaderElements(headers) {
|
|
190
|
-
const headerElements = Object.keys(headers).reduce((acc, key) => (Object.assign(Object.assign({}, acc), { [key]: (React__default["default"].createElement("div", { className: styles$
|
|
199
|
+
const headerElements = Object.keys(headers).reduce((acc, key) => (Object.assign(Object.assign({}, acc), { [key]: (React__default["default"].createElement("div", { className: styles$b.headerLabel },
|
|
191
200
|
React__default["default"].createElement(Text.Text, { variation: "subdued", maxLines: "single", size: "small" }, headers[key]))) })), {});
|
|
192
201
|
return isEmpty__default["default"](headerElements) ? undefined : headerElements;
|
|
193
202
|
}
|
|
@@ -227,11 +236,171 @@ function isLayoutVisible({ layoutSize, mediaMatches, sizePropsOfLayouts, }) {
|
|
|
227
236
|
return isVisibleBreakpoint && largerLayoutIsNotVisible;
|
|
228
237
|
}
|
|
229
238
|
|
|
239
|
+
const defaultValues = {
|
|
240
|
+
title: "",
|
|
241
|
+
data: [],
|
|
242
|
+
headers: {},
|
|
243
|
+
children: [],
|
|
244
|
+
selected: [],
|
|
245
|
+
};
|
|
246
|
+
const DataListContext = React.createContext(defaultValues);
|
|
247
|
+
function useDataListContext() {
|
|
248
|
+
return React.useContext(DataListContext);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function DataListItemInternal({ children, item, }) {
|
|
252
|
+
const { selected, onSelect } = useDataListContext();
|
|
253
|
+
if (selected !== undefined && onSelect) {
|
|
254
|
+
return (React__default["default"].createElement("div", { className: classnames__default["default"](styles$b.selectable, {
|
|
255
|
+
[styles$b.selected]: selected === null || selected === void 0 ? void 0 : selected.length,
|
|
256
|
+
}) },
|
|
257
|
+
React__default["default"].createElement(Checkbox.Checkbox, { checked: selected === null || selected === void 0 ? void 0 : selected.includes(item.id), onChange: handleChange }),
|
|
258
|
+
children));
|
|
259
|
+
}
|
|
260
|
+
return children;
|
|
261
|
+
function handleChange() {
|
|
262
|
+
if (selected === null || selected === void 0 ? void 0 : selected.includes(item.id)) {
|
|
263
|
+
onSelect === null || onSelect === void 0 ? void 0 : onSelect(selected === null || selected === void 0 ? void 0 : selected.filter(id => id !== item.id));
|
|
264
|
+
}
|
|
265
|
+
else if (selected) {
|
|
266
|
+
onSelect === null || onSelect === void 0 ? void 0 : onSelect([...selected, item.id]);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
var css_248z$7 = ".jHcHGQ-HDbk- {\n display: -ms-flexbox;\n display: flex;\n position: absolute;\n top: calc((16px / 2) * -1);\n top: calc(calc(16px / 2) * -1);\n top: calc(var(--space-small) * -1);\n right: 0;\n z-index: 6;\n z-index: var(--elevation-menu);\n box-shadow: 0px calc(16px / 16) calc(16px / 4) 0px\n rgba(0, 0, 0, 0.1),\n 0px calc(16px / 4) 12px 0px rgba(0, 0, 0, 0.05);\n box-shadow: var(--shadow-base);\n padding: calc(16px / 4);\n padding: var(--space-smaller);\n border: calc(16px / 16) solid rgb(225, 225, 225);\n border: var(--border-base) solid var(--color-border);\n border-radius: calc(16px / 2);\n border-radius: var(--radius-larger);\n background-color: rgba(255, 255, 255, 1);\n background-color: var(--color-surface);\n gap: calc(16px / 4);\n gap: var(--space-smaller);\n}\n";
|
|
272
|
+
var styles$7 = {"menu":"jHcHGQ-HDbk-"};
|
|
273
|
+
styleInject_es.styleInject(css_248z$7);
|
|
274
|
+
|
|
275
|
+
var css_248z$6 = ".iyg43v-S9yU- {\n display: -ms-flexbox;\n display: flex;\n width: 100%;\n min-height: 44px;\n padding: calc(16px / 2);\n padding: var(--space-small);\n border: none;\n border-radius: 0;\n text-align: left;\n background: none;\n cursor: pointer;\n transition: background 200ms ease;\n transition: background var(--timing-base) ease;\n -webkit-appearance: none;\n appearance: none;\n -ms-flex-align: center;\n align-items: center;\n gap: calc(16px / 2);\n gap: var(--space-small);\n}\n\n.iyg43v-S9yU-:hover,\n.iyg43v-S9yU-:focus {\n background-color: rgb(250, 246, 219);\n background-color: var(--color-surface--hover);\n}\n\n.AUJNqz93ZDA- {\n font-weight: 500;\n}\n";
|
|
276
|
+
var styles$6 = {"action":"iyg43v-S9yU-","label":"AUJNqz93ZDA-"};
|
|
277
|
+
styleInject_es.styleInject(css_248z$6);
|
|
278
|
+
|
|
279
|
+
function DataListAction(
|
|
280
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
281
|
+
_) {
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
function InternalDataListAction({ label, icon, destructive, onClick, item, }) {
|
|
285
|
+
const color = destructive ? "critical" : "blue";
|
|
286
|
+
return (React__default["default"].createElement("button", { className: styles$6.action, onClick: () => onClick === null || onClick === void 0 ? void 0 : onClick(item) },
|
|
287
|
+
icon && React__default["default"].createElement(Icon.Icon, { name: icon, color: color }),
|
|
288
|
+
React__default["default"].createElement(Typography.Typography, { textColor: color },
|
|
289
|
+
React__default["default"].createElement("span", { className: styles$6.label }, label))));
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
var css_248z$5 = ".aokwZU8jbWU- {\n position: fixed;\n top: 0;\n top: var(--actions-menu-y, 0);\n left: 0;\n left: var(--actions-menu-x, 0);\n z-index: 6;\n z-index: var(--elevation-menu);\n min-width: 150px;\n box-shadow: 0px calc(16px / 16) calc(16px / 4) 0px\n rgba(0, 0, 0, 0.1),\n 0px calc(16px / 4) 12px 0px rgba(0, 0, 0, 0.05);\n box-shadow: var(--shadow-base);\n padding: calc(16px / 4);\n padding: var(--space-smaller);\n border: calc(16px / 16) solid rgb(225, 225, 225);\n border: var(--border-base) solid var(--color-border);\n border-radius: calc(16px / 2);\n border-radius: var(--radius-larger);\n background-color: rgba(255, 255, 255, 1);\n background-color: var(--color-surface);\n}\n\n.XtVRP97TVSE- {\n position: fixed;\n top: 0;\n left: 0;\n z-index: 6;\n z-index: var(--elevation-menu);\n width: 100%;\n height: 100%;\n}\n";
|
|
293
|
+
var styles$5 = {"menu":"aokwZU8jbWU-","overlay":"XtVRP97TVSE-"};
|
|
294
|
+
styleInject_es.styleInject(css_248z$5);
|
|
295
|
+
|
|
296
|
+
const variants$1 = {
|
|
297
|
+
hidden: { opacity: 0, y: -10 },
|
|
298
|
+
visible: { opacity: 1, y: 0 },
|
|
299
|
+
};
|
|
300
|
+
function DataListActionsMenu({ visible = false, position, onRequestClose, children, }) {
|
|
301
|
+
const [ref, setRef] = React.useState();
|
|
302
|
+
useRefocusOnActivator.useRefocusOnActivator(visible);
|
|
303
|
+
const focusTrapRef = useFocusTrap.useFocusTrap(visible);
|
|
304
|
+
useOnKeyDown.useOnKeyDown(onRequestClose, "Escape");
|
|
305
|
+
return (React__default["default"].createElement(framerMotion.AnimatePresence, null, visible && (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
306
|
+
React__default["default"].createElement("div", { className: styles$5.overlay, onClick: onRequestClose }),
|
|
307
|
+
React__default["default"].createElement(framerMotion.motion.div, { ref: setRef, variants: variants$1, initial: "hidden", animate: "visible", exit: "hidden", transition: { duration: TRANSITION_DELAY_IN_SECONDS }, className: styles$5.menu, style: getPositionCssVars() },
|
|
308
|
+
React__default["default"].createElement("div", { tabIndex: 0, ref: focusTrapRef }, children))))));
|
|
309
|
+
function getPositionCssVars() {
|
|
310
|
+
const { posX, posY } = getPosition();
|
|
311
|
+
return {
|
|
312
|
+
"--actions-menu-x": `${posX}px`,
|
|
313
|
+
"--actions-menu-y": `${posY}px`,
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
function getPosition() {
|
|
317
|
+
const rect = ref === null || ref === void 0 ? void 0 : ref.getBoundingClientRect();
|
|
318
|
+
const { width = 0, height = 0 } = rect || {};
|
|
319
|
+
const { x = 0, y = 0 } = position;
|
|
320
|
+
const xIsOffScreen = x + width > window.innerWidth;
|
|
321
|
+
const yIsOffScreen = y + height > window.innerHeight;
|
|
322
|
+
const yOffSet = y + height - window.innerHeight;
|
|
323
|
+
const newPosX = Math.floor(xIsOffScreen ? x - width : x);
|
|
324
|
+
const newPosY = Math.floor(yIsOffScreen ? y - yOffSet : y);
|
|
325
|
+
return { posX: newPosX, posY: newPosY };
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function DataListItemActionsOverflow({ item, actions, }) {
|
|
330
|
+
const [menuPosition, setMenuPosition] = React.useState({ x: 0, y: 0 });
|
|
331
|
+
const [showMenu, setShowMenu] = React.useState(false);
|
|
332
|
+
return (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
333
|
+
React__default["default"].createElement(Tooltip.Tooltip, { message: "More actions" },
|
|
334
|
+
React__default["default"].createElement(Button.Button, { icon: "more", ariaLabel: "More actions", type: "secondary", variation: "subtle", onClick: handleMoreClick })),
|
|
335
|
+
React__default["default"].createElement(DataListActionsMenu, { visible: showMenu, position: menuPosition, onRequestClose: handleClose }, React.Children.map(actions, action => (React__default["default"].createElement(InternalDataListAction, Object.assign({}, action.props, { item: item })))))));
|
|
336
|
+
function handleMoreClick(event) {
|
|
337
|
+
setShowMenu(true);
|
|
338
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
339
|
+
const posX = rect.x + rect.width;
|
|
340
|
+
const posY = rect.y + rect.height;
|
|
341
|
+
setMenuPosition({ x: posX, y: posY });
|
|
342
|
+
}
|
|
343
|
+
function handleClose() {
|
|
344
|
+
setShowMenu(false);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// This component is meant to capture the props of the DataList.ItemActions
|
|
349
|
+
function DataListItemActions(
|
|
350
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
351
|
+
_) {
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
const variants = {
|
|
355
|
+
hidden: { opacity: 0, y: 10 },
|
|
356
|
+
visible: { opacity: 1, y: 0 },
|
|
357
|
+
};
|
|
358
|
+
function InternalDataListItemActions({ item, }) {
|
|
359
|
+
const { itemActionComponent } = useDataListContext();
|
|
360
|
+
if (!itemActionComponent)
|
|
361
|
+
return null;
|
|
362
|
+
const { children } = itemActionComponent.props;
|
|
363
|
+
const childrenArray = React.Children.toArray(children).filter(React.isValidElement);
|
|
364
|
+
const exposedActions = getExposedActions(childrenArray);
|
|
365
|
+
childrenArray.splice(0, exposedActions.length);
|
|
366
|
+
return (React__default["default"].createElement(framerMotion.motion.div, { variants: variants, initial: "hidden", animate: "visible", exit: "hidden", transition: {
|
|
367
|
+
duration: TRANSITION_DURATION_IN_SECONDS,
|
|
368
|
+
delay: TRANSITION_DELAY_IN_SECONDS,
|
|
369
|
+
}, className: styles$7.menu },
|
|
370
|
+
exposedActions.map(({ props }) => {
|
|
371
|
+
if (!props.icon)
|
|
372
|
+
return null;
|
|
373
|
+
return (React__default["default"].createElement(Tooltip.Tooltip, { key: props.label, message: props.label },
|
|
374
|
+
React__default["default"].createElement(Button.Button, { icon: props.icon, ariaLabel: props.label, onClick: () => { var _a; return (_a = props.onClick) === null || _a === void 0 ? void 0 : _a.call(props, item); }, type: "secondary", variation: "subtle" })));
|
|
375
|
+
}),
|
|
376
|
+
React__default["default"].createElement(DataListItemActionsOverflow, { actions: childrenArray, item: item })));
|
|
377
|
+
}
|
|
378
|
+
function getExposedActions(childrenArray) {
|
|
379
|
+
const firstTwoChildren = childrenArray.slice(0, 2);
|
|
380
|
+
return firstTwoChildren.reduce((result, child, i) => {
|
|
381
|
+
const hasIcon = Boolean(child.props.icon);
|
|
382
|
+
const isFirstChild = i === 0;
|
|
383
|
+
if (isFirstChild && hasIcon) {
|
|
384
|
+
return [...result, child];
|
|
385
|
+
}
|
|
386
|
+
const isSecondChild = i === 1;
|
|
387
|
+
const hasFirstChild = result.length === 1;
|
|
388
|
+
if (isSecondChild && hasIcon && hasFirstChild) {
|
|
389
|
+
return [...result, child];
|
|
390
|
+
}
|
|
391
|
+
return result;
|
|
392
|
+
}, []);
|
|
393
|
+
}
|
|
394
|
+
|
|
230
395
|
function DataListItems({ layouts, mediaMatches, data, }) {
|
|
231
396
|
const elementData = generateListItemElements(data);
|
|
397
|
+
const [hover, setHover] = React.useState();
|
|
232
398
|
return (React__default["default"].createElement(DataListLayoutInternal, { layouts: layouts, mediaMatches: mediaMatches, renderLayout: layout => {
|
|
233
399
|
return (React__default["default"].createElement(React__default["default"].Fragment, null, elementData.map((child, i) => {
|
|
234
|
-
|
|
400
|
+
const item = data[i];
|
|
401
|
+
return (React__default["default"].createElement("div", { onMouseEnter: () => setHover(item.id), onMouseLeave: () => setHover(undefined), className: styles$b.listItem, key: item.id },
|
|
402
|
+
React__default["default"].createElement(DataListItemInternal, { item: data[i] }, layout.props.children(child)),
|
|
403
|
+
React__default["default"].createElement(framerMotion.AnimatePresence, null, hover === item.id && (React__default["default"].createElement(InternalDataListItemActions, { item: item })))));
|
|
235
404
|
})));
|
|
236
405
|
} }));
|
|
237
406
|
}
|
|
@@ -247,7 +416,7 @@ function DataListHeader({ layouts, mediaMatches, headerData, headerVisibility, }
|
|
|
247
416
|
if (!showHeader || !headerData)
|
|
248
417
|
return React__default["default"].createElement(React__default["default"].Fragment, null);
|
|
249
418
|
return (React__default["default"].createElement(DataListLayoutInternal, { layouts: layouts, renderLayout: layout => {
|
|
250
|
-
return (React__default["default"].createElement("div", { className: styles$
|
|
419
|
+
return (React__default["default"].createElement("div", { className: styles$b.headerTitles }, layout.props.children(headerData)));
|
|
251
420
|
}, mediaMatches: mediaMatches }));
|
|
252
421
|
}
|
|
253
422
|
|
|
@@ -263,13 +432,13 @@ function DataListLoadingState({ headers, layouts, mediaMatches, }) {
|
|
|
263
432
|
if (layout.props.size === "xs") {
|
|
264
433
|
return React__default["default"].createElement(LoadingStateXSBreakpoint, null);
|
|
265
434
|
}
|
|
266
|
-
return (React__default["default"].createElement(React__default["default"].Fragment, null, loadingElements.map((child, i) => (React__default["default"].createElement("div", { className: styles$
|
|
435
|
+
return (React__default["default"].createElement(React__default["default"].Fragment, null, loadingElements.map((child, i) => (React__default["default"].createElement("div", { className: styles$9.loadingItem, key: i, "data-testid": DATALIST_LOADINGSTATE_ROW_TEST_ID }, layout.props.children(child))))));
|
|
267
436
|
} }));
|
|
268
437
|
}
|
|
269
438
|
function LoadingStateXSBreakpoint() {
|
|
270
439
|
const loadingData = new Array(LOADING_STATE_LIMIT_ITEMS).fill(0);
|
|
271
440
|
return (React__default["default"].createElement(React__default["default"].Fragment, null, loadingData.map((_, i) => {
|
|
272
|
-
return (React__default["default"].createElement("div", { className: styles$
|
|
441
|
+
return (React__default["default"].createElement("div", { className: styles$9.mobileLoadingState, key: i },
|
|
273
442
|
React__default["default"].createElement(Glimmer.Glimmer.Text, null)));
|
|
274
443
|
})));
|
|
275
444
|
}
|
|
@@ -286,17 +455,6 @@ styleInject_es.styleInject(css_248z$4);
|
|
|
286
455
|
|
|
287
456
|
const CONTAINER_TEST_ID = "ATL-DataListFilters-Container";
|
|
288
457
|
|
|
289
|
-
const defaultValues = {
|
|
290
|
-
title: "",
|
|
291
|
-
data: [],
|
|
292
|
-
headers: {},
|
|
293
|
-
children: [],
|
|
294
|
-
};
|
|
295
|
-
const DataListContext = React.createContext(defaultValues);
|
|
296
|
-
function useDataListContext() {
|
|
297
|
-
return React.useContext(DataListContext);
|
|
298
|
-
}
|
|
299
|
-
|
|
300
458
|
// This component is meant to capture the props of the DataList.Filters
|
|
301
459
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
302
460
|
function DataListFilters(_) {
|
|
@@ -483,14 +641,17 @@ function breakpointToMediaQuery(breakpoint) {
|
|
|
483
641
|
}
|
|
484
642
|
|
|
485
643
|
function DataList(props) {
|
|
644
|
+
var _a;
|
|
486
645
|
const searchComponent = getCompoundComponent(props.children, DataListSearch);
|
|
487
646
|
const filterComponent = getCompoundComponent(props.children, DataListFilters);
|
|
488
647
|
const layoutComponents = getCompoundComponents(props.children, DataListLayout);
|
|
489
648
|
const emptyStateComponents = getCompoundComponents(props.children, DataListEmptyState);
|
|
490
|
-
|
|
649
|
+
const itemActionComponent = getCompoundComponent(props.children, DataListItemActions);
|
|
650
|
+
return (React__default["default"].createElement(DataListContext.Provider, { value: Object.assign(Object.assign({ searchComponent,
|
|
491
651
|
filterComponent,
|
|
492
652
|
layoutComponents,
|
|
493
|
-
emptyStateComponents
|
|
653
|
+
emptyStateComponents,
|
|
654
|
+
itemActionComponent }, props), { selected: (_a = props.selected) !== null && _a !== void 0 ? _a : [] }) },
|
|
494
655
|
React__default["default"].createElement(InternalDataList, null)));
|
|
495
656
|
}
|
|
496
657
|
function InternalDataList() {
|
|
@@ -501,21 +662,21 @@ function InternalDataList() {
|
|
|
501
662
|
const initialLoading = loadingState === "initial";
|
|
502
663
|
const showEmptyState = !initialLoading && data.length === 0;
|
|
503
664
|
const shouldRenderLoadMoreTrigger = !initialLoading && !showEmptyState;
|
|
504
|
-
return (React__default["default"].createElement("div", { className: styles$
|
|
505
|
-
React__default["default"].createElement("div", { className: styles$
|
|
665
|
+
return (React__default["default"].createElement("div", { className: styles$b.wrapper },
|
|
666
|
+
React__default["default"].createElement("div", { className: styles$b.titleContainer },
|
|
506
667
|
title && React__default["default"].createElement(Heading.Heading, { level: 3 }, title),
|
|
507
668
|
React__default["default"].createElement(DataListTotalCount, { totalCount: totalCount, loading: initialLoading })),
|
|
508
669
|
React__default["default"].createElement("div", { ref: backToTopRef }),
|
|
509
670
|
React__default["default"].createElement(DataListStickyHeader, null,
|
|
510
|
-
React__default["default"].createElement("div", { className: styles$
|
|
671
|
+
React__default["default"].createElement("div", { className: styles$b.headerFilters },
|
|
511
672
|
React__default["default"].createElement(InternalDataListFilters, null),
|
|
512
673
|
React__default["default"].createElement(InternalDataListSearch, null)),
|
|
513
674
|
headerData && (React__default["default"].createElement(DataListHeader, { layouts: layoutComponents, headerData: headerData, headerVisibility: headerVisibility, mediaMatches: mediaMatches }))),
|
|
514
675
|
initialLoading && (React__default["default"].createElement(DataListLoadingState, { headers: headers, layouts: layoutComponents, mediaMatches: mediaMatches })),
|
|
515
676
|
showEmptyState && React__default["default"].createElement(InternalDataListEmptyState, null),
|
|
516
677
|
!initialLoading && (React__default["default"].createElement(DataListItems, { data: data, layouts: layoutComponents, mediaMatches: mediaMatches })),
|
|
517
|
-
loadingState === "filtering" && (React__default["default"].createElement("div", { "data-testid": DATA_LIST_FILTERING_SPINNER_TEST_ID, className: styles$
|
|
518
|
-
React__default["default"].createElement("div", { className: styles$
|
|
678
|
+
loadingState === "filtering" && (React__default["default"].createElement("div", { "data-testid": DATA_LIST_FILTERING_SPINNER_TEST_ID, className: styles$b.filtering },
|
|
679
|
+
React__default["default"].createElement("div", { className: styles$b.filteringSpinner },
|
|
519
680
|
React__default["default"].createElement(Spinner.Spinner, { size: "small" })))),
|
|
520
681
|
shouldRenderLoadMoreTrigger && (React__default["default"].createElement(DataListLoadMore, { onBackToTop: handleBackToTop }))));
|
|
521
682
|
function handleBackToTop() {
|
|
@@ -535,5 +696,7 @@ DataList.Layout = DataListLayout;
|
|
|
535
696
|
DataList.EmptyState = DataListEmptyState;
|
|
536
697
|
DataList.Filters = DataListFilters;
|
|
537
698
|
DataList.Search = DataListSearch;
|
|
699
|
+
DataList.ItemActions = DataListItemActions;
|
|
700
|
+
DataList.Action = DataListAction;
|
|
538
701
|
|
|
539
702
|
exports.DataList = DataList;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jobber/components",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.36.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@jobber/design": "^0.44.4",
|
|
23
23
|
"@jobber/formatters": "*",
|
|
24
|
-
"@jobber/hooks": "^2.
|
|
24
|
+
"@jobber/hooks": "^2.3.0",
|
|
25
25
|
"@popperjs/core": "^2.0.6",
|
|
26
26
|
"@std-proposal/temporal": "0.0.1",
|
|
27
27
|
"@tanstack/react-table": "8.5.13",
|
|
@@ -84,5 +84,5 @@
|
|
|
84
84
|
"> 1%",
|
|
85
85
|
"IE 10"
|
|
86
86
|
],
|
|
87
|
-
"gitHead": "
|
|
87
|
+
"gitHead": "0bc5252f5ef1f24f7a46fbe49204084bc4469b98"
|
|
88
88
|
}
|