@jobber/components 4.32.0 → 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.
@@ -3,8 +3,9 @@
3
3
  */
4
4
  type ValuesOf<T extends readonly unknown[]> = T[number];
5
5
  export type Breakpoints = ValuesOf<typeof BREAKPOINTS>;
6
- export declare const EMPTY_FILTER_RESULTS_MESSAGE = "No Results for Selected Filters";
7
- export declare const EMPTY_FILTER_RESULTS_ACTION_LABEL = "Clear Filters";
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
  */
@@ -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 import("./components/EmptyState").EmptyState;
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>;
@@ -47,11 +48,9 @@ export interface DataListProps<T extends DataListObject> {
47
48
  */
48
49
  readonly loadingState?: "initial" | "filtering" | "loadingMore" | "none";
49
50
  /**
50
- * Temporary prop for setting default state for if filters are applied
51
- *
52
- * @default false
51
+ * Adjusts the DataList to show the UX when it is filtered.
53
52
  */
54
- readonly filterApplied?: boolean;
53
+ readonly filtered?: boolean;
55
54
  /**
56
55
  * The title of the DataList.
57
56
  */
@@ -93,8 +92,30 @@ export interface DataListSearchProps {
93
92
  export interface DataListFiltersProps {
94
93
  readonly children: ReactElement | ReactElement[];
95
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
+ }
96
116
  export interface DataListContextProps<T extends DataListObject> extends DataListProps<T> {
97
117
  readonly filterComponent?: ReactElement<DataListFiltersProps>;
98
118
  readonly searchComponent?: ReactElement<DataListSearchProps>;
119
+ readonly emptyStateComponents?: ReactElement<DataListEmptyStateProps>[];
99
120
  readonly layoutComponents?: ReactElement<DataListLayoutProps<T>>[];
100
121
  }
@@ -1,6 +1,5 @@
1
- import React, { ReactElement } from "react";
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,4 @@
1
+ /// <reference types="react" />
2
+ import { DataListEmptyStateProps } from "../../DataList.types";
3
+ export declare function DataListEmptyState(_: DataListEmptyStateProps): null;
4
+ export declare function InternalDataListEmptyState(): JSX.Element;
@@ -0,0 +1 @@
1
+ export * from "./DataListEmptyState";
@@ -0,0 +1 @@
1
+ export * from "./DataListStickyHeader";
@@ -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 isEmpty = require('lodash/isEmpty');
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
21
  var Spinner = require('../Spinner-9d8fc7ff.js');
23
- require('../Icon-405a216c.js');
24
22
  require('../tslib.es6-5b8768b7.js');
25
23
  require('../Content-2ca1ffe1.js');
26
24
  require('../FormField-0f880b07.js');
27
25
  require('uuid');
28
26
  require('react-hook-form');
27
+ require('../Icon-405a216c.js');
29
28
  require('../InputValidation-b5a3d92c.js');
30
29
  require('framer-motion');
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 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";
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
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 = "._--dXJma0jX0- {\n display: -ms-flexbox;\n display: flex;\n height: 100%;\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}\n";
44
- var styles$6 = {"emptyStateWrapper":"_--dXJma0jX0-"};
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
- function DataListEmptyState({ message, action }) {
48
- return (React__default["default"].createElement("div", { className: styles$6.emptyStateWrapper },
49
- React__default["default"].createElement(Text.Text, { align: "center" }, message),
50
- action && (React__default["default"].createElement(Button.Button, Object.assign({}, Object.assign(Object.assign({}, action), { variation: "subtle" }))))));
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
- function DataListLayout(
54
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
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 EMPTY_FILTER_RESULTS_MESSAGE = "No Results for Selected Filters";
60
- const EMPTY_FILTER_RESULTS_ACTION_LABEL = "Clear Filters";
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
  */
@@ -73,9 +83,9 @@ const SEARCH_DEBOUNCE_DELAY = design.tokens["timing-slowest"];
73
83
  const DATA_LIST_FILTERING_SPINNER_TEST_ID = "ATL-DataList-filteringSpinner";
74
84
  const DATA_LIST_LOADING_MORE_SPINNER_TEST_ID = "ATL-DataList-loadingMoreSpinner";
75
85
 
76
- var css_248z$5 = ".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";
77
- var styles$5 = {"tags":"WRV-UmQmPzo-","tagCount":"liQeWCMenD0-"};
78
- styleInject_es.styleInject(css_248z$5);
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);
79
89
 
80
90
  function DataListTags({ items }) {
81
91
  const ref = React.useRef(null);
@@ -97,10 +107,10 @@ function DataListTags({ items }) {
97
107
  elements === null || elements === void 0 ? void 0 : elements.forEach(element => observer.unobserve(element));
98
108
  };
99
109
  }, [items]);
100
- return (React__default["default"].createElement("div", { className: styles$5.tags, ref: ref },
110
+ return (React__default["default"].createElement("div", { className: styles$4.tags, ref: ref },
101
111
  items.filter(Boolean).map((tag, index) => (React__default["default"].createElement("div", { key: tag, "data-tag-element": index },
102
112
  React__default["default"].createElement(InlineLabel.InlineLabel, null, tag)))),
103
- Boolean(visibleItems) && (React__default["default"].createElement("div", { className: styles$5.tagCount },
113
+ Boolean(visibleItems) && (React__default["default"].createElement("div", { className: styles$4.tagCount },
104
114
  React__default["default"].createElement(Text.Text, null,
105
115
  "+",
106
116
  visibleItems)))));
@@ -182,60 +192,10 @@ function generateHeaderElements(headers) {
182
192
  React__default["default"].createElement(Text.Text, { variation: "subdued", maxLines: "single", size: "small" }, headers[key]))) })), {});
183
193
  return isEmpty__default["default"](headerElements) ? undefined : headerElements;
184
194
  }
185
- /**
186
- * Modify EmptyState to include an empty filter results when filtering happens
187
- */
188
- function generateDataListEmptyState({ children, isFilterApplied, setIsFilterApplied, }) {
189
- if (!children)
190
- return;
191
- const EmptyStateComponent = getCompoundComponent(children, DataListEmptyState);
192
- if (isFilterApplied && React.isValidElement(EmptyStateComponent)) {
193
- let overrideEmptyStateProps;
194
- if (isFilterApplied) {
195
- overrideEmptyStateProps = {
196
- message: EMPTY_FILTER_RESULTS_MESSAGE,
197
- action: {
198
- label: EMPTY_FILTER_RESULTS_ACTION_LABEL,
199
- onClick: () => {
200
- setIsFilterApplied(false);
201
- alert("Filters Cleared");
202
- },
203
- },
204
- };
205
- }
206
- return React__default["default"].cloneElement(EmptyStateComponent, overrideEmptyStateProps);
207
- }
208
- return EmptyStateComponent;
209
- }
210
195
  function sortSizeProp(sizeProp) {
211
196
  return sizeProp.sort((a, b) => BREAKPOINTS.indexOf(a) - BREAKPOINTS.indexOf(b));
212
197
  }
213
198
 
214
- var css_248z$4 = ".F56prQsXm3A- {\n min-width: 80px;\n margin-left: calc(16px / 2);\n margin-left: var(--space-small);\n}\n";
215
- var styles$4 = {"results":"F56prQsXm3A-"};
216
- styleInject_es.styleInject(css_248z$4);
217
-
218
- const DATALIST_TOTALCOUNT_TEST_ID = "ATL-DataList-TotalCount";
219
- function DataListTotalCount({ totalCount, loading, }) {
220
- if (totalCount === undefined)
221
- return null;
222
- let output = null;
223
- if (totalCount === null && loading) {
224
- output = React__default["default"].createElement(Glimmer.Glimmer, { size: "auto", shape: "rectangle" });
225
- }
226
- if (typeof totalCount === "number") {
227
- output = (React__default["default"].createElement(Text.Text, { variation: "subdued" },
228
- "(",
229
- totalCount.toLocaleString(),
230
- " results)"));
231
- }
232
- return (React__default["default"].createElement("div", { className: styles$4.results, "data-testid": DATALIST_TOTALCOUNT_TEST_ID }, output));
233
- }
234
-
235
- 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";
236
- var styles$3 = {"loadingItem":"Rh--6fVpkm4-","mobileLoadingState":"zbS7UvpVoWI-"};
237
- styleInject_es.styleInject(css_248z$3);
238
-
239
199
  function DataListLayoutInternal({ layouts, renderLayout, mediaMatches, }) {
240
200
  const sizePropsOfLayouts = layouts === null || layouts === void 0 ? void 0 : layouts.map(layout => layout.props.size || "xs");
241
201
  const layoutToRender = layouts === null || layouts === void 0 ? void 0 : layouts.find(layout => {
@@ -304,42 +264,29 @@ function DataListLoadingState({ 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$3.loadingItem, key: i, "data-testid": DATALIST_LOADINGSTATE_ROW_TEST_ID }, layout.props.children(child))))));
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$3.mobileLoadingState, key: i },
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 useLayoutMediaQueries() {
319
- const mediaQueries = BREAKPOINTS.reduce((previous, breakpoint) => (Object.assign(Object.assign({}, previous), { [breakpoint]: window.matchMedia(breakpointToMediaQuery(breakpoint)) })), {});
320
- const initialMatches = BREAKPOINTS.reduce((previous, breakpoint) => (Object.assign(Object.assign({}, previous), { [breakpoint]: mediaQueries[breakpoint].matches })), {});
321
- const [matches, setMatches] = React.useState(initialMatches);
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$2.filters, {
377
- [styles$2.overflowLeft]: !isLeftVisible,
378
- [styles$2.overflowRight]: !isRightVisible,
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$2.filterActions },
381
- React__default["default"].createElement("span", { ref: leftRef, className: styles$2.overflowTrigger }),
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$2.overflowTrigger }))));
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,45 +388,93 @@ function InternalDataListSearch() {
427
388
  }
428
389
  }
429
390
 
430
- var css_248z = ".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";
431
- var styles = {"header":"PGOHzrMh374-","stuck":"PGjWc5ocjpI-"};
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
- function DataListStickyHeader({ children }) {
435
- const [isStuck, setIsStuck] = React.useState(false);
436
- const ref = React.useRef(null);
437
- const handleObserver = React.useCallback(([e]) => setIsStuck(e.intersectionRatio < 1), [setIsStuck]);
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
- if (!window.IntersectionObserver)
440
- return;
441
- const observer = new IntersectionObserver(handleObserver, { threshold: 1 });
442
- ref.current && observer.observe(ref.current);
446
+ BREAKPOINTS.forEach(breakpoint => {
447
+ mediaQueries[breakpoint].addEventListener("change", handlers[breakpoint]);
448
+ });
443
449
  return () => {
444
- ref.current && observer.unobserve(ref.current);
450
+ BREAKPOINTS.forEach(breakpoint => {
451
+ mediaQueries[breakpoint].removeEventListener("change", handlers[breakpoint]);
452
+ });
445
453
  };
446
- }, [handleObserver, ref.current]);
447
- return (React__default["default"].createElement("div", { ref: ref, className: classnames__default["default"](styles.header, { [styles.stuck]: isStuck }) }, children));
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);
454
- return (React__default["default"].createElement(DataListContext.Provider, { value: Object.assign({ searchComponent, filterComponent, layoutComponents }, props) },
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) },
455
470
  React__default["default"].createElement(InternalDataList, null)));
456
471
  }
457
472
  function InternalDataList() {
458
- const { data, headers, filterApplied = false, children, title, totalCount, headerVisibility = { xs: true, sm: true, md: true, lg: true, xl: true }, loadingState = "none", layoutComponents, } = useDataListContext();
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
476
  const initialLoading = loadingState === "initial";
462
477
  const showEmptyState = !initialLoading && data.length === 0;
463
- const [isFilterApplied, setIsFilterApplied] = React.useState(filterApplied);
464
- const EmptyStateComponent = generateDataListEmptyState({
465
- children,
466
- isFilterApplied,
467
- setIsFilterApplied,
468
- });
469
478
  return (React__default["default"].createElement("div", { className: styles$7.wrapper },
470
479
  React__default["default"].createElement("div", { className: styles$7.titleContainer },
471
480
  title && React__default["default"].createElement(Heading.Heading, { level: 3 }, title),
@@ -476,13 +485,13 @@ function InternalDataList() {
476
485
  React__default["default"].createElement(InternalDataListSearch, null)),
477
486
  headerData && (React__default["default"].createElement(DataListHeader, { layouts: layoutComponents, headerData: headerData, headerVisibility: headerVisibility, mediaMatches: mediaMatches }))),
478
487
  initialLoading && (React__default["default"].createElement(DataListLoadingState, { headers: headers, layouts: layoutComponents, mediaMatches: mediaMatches })),
488
+ showEmptyState && React__default["default"].createElement(InternalDataListEmptyState, null),
479
489
  !initialLoading && (React__default["default"].createElement(DataListItems, { data: data, layouts: layoutComponents, mediaMatches: mediaMatches })),
480
490
  loadingState === "filtering" && (React__default["default"].createElement("div", { "data-testid": DATA_LIST_FILTERING_SPINNER_TEST_ID, className: styles$7.filtering },
481
491
  React__default["default"].createElement("div", { className: styles$7.filteringSpinner },
482
492
  React__default["default"].createElement(Spinner.Spinner, { size: "small" })))),
483
493
  loadingState === "loadingMore" && (React__default["default"].createElement("div", { "data-testid": DATA_LIST_LOADING_MORE_SPINNER_TEST_ID, className: styles$7.loadingMore },
484
- React__default["default"].createElement(Spinner.Spinner, { size: "small" }))),
485
- showEmptyState && EmptyStateComponent));
494
+ React__default["default"].createElement(Spinner.Spinner, { size: "small" })))));
486
495
  }
487
496
  DataList.Layout = DataListLayout;
488
497
  DataList.EmptyState = DataListEmptyState;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jobber/components",
3
- "version": "4.32.0",
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": "a4f52ed97ef70b37eaee9a3b1fd09e26fcc595c1"
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";