@jobber/components 4.78.4 → 4.79.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.
@@ -2,105 +2,11 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var React = require('react');
6
- var framerMotion = require('framer-motion');
7
- var design = require('@jobber/design');
5
+ var AnimatedPresence = require('../AnimatedPresence-20a02aaa.js');
6
+ require('react');
7
+ require('framer-motion');
8
+ require('@jobber/design');
8
9
 
9
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
10
10
 
11
- var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
12
11
 
13
- const TIMING_QUICK = toSeconds(design.tokens["timing-quick"]);
14
- const TIMING_BASE = toSeconds(design.tokens["timing-base"]);
15
- const baseTransition = {
16
- visible: { opacity: 1 },
17
- hidden: { opacity: 0 },
18
- };
19
- const fade = {
20
- visible: { opacity: 1 },
21
- hidden: { opacity: 0 },
22
- };
23
- const popIn = {
24
- visible: Object.assign({ scale: 1 }, baseTransition.visible),
25
- hidden: Object.assign({ scale: 0.95 }, baseTransition.hidden),
26
- };
27
- const fromTop = {
28
- visible: Object.assign({ y: 0 }, baseTransition.visible),
29
- hidden: Object.assign({ y: -design.tokens["space-base"] }, baseTransition.hidden),
30
- };
31
- const fromBottom = {
32
- visible: Object.assign({ y: 0 }, baseTransition.visible),
33
- hidden: Object.assign({ y: design.tokens["space-base"] }, baseTransition.hidden),
34
- };
35
- const fromLeft = {
36
- visible: Object.assign({ x: 0 }, baseTransition.visible),
37
- hidden: Object.assign({ x: -design.tokens["space-base"] }, baseTransition.hidden),
38
- };
39
- const fromRight = {
40
- visible: Object.assign({ x: 0 }, baseTransition.visible),
41
- hidden: Object.assign({ x: design.tokens["space-base"] }, baseTransition.hidden),
42
- };
43
- const fromLeftToRight = {
44
- initial: Object.assign({ x: -design.tokens["space-base"] }, baseTransition.hidden),
45
- visible: Object.assign({ x: 0 }, baseTransition.visible),
46
- hidden: Object.assign({ x: design.tokens["space-base"] }, baseTransition.hidden),
47
- };
48
- const fromRightToLeft = {
49
- initial: Object.assign({ x: design.tokens["space-base"] }, baseTransition.hidden),
50
- visible: Object.assign({ x: 0 }, baseTransition.visible),
51
- hidden: Object.assign({ x: -design.tokens["space-base"] }, baseTransition.hidden),
52
- };
53
- function toSeconds(ms) {
54
- return ms / 1000;
55
- }
56
-
57
- function usePreviousValue(value) {
58
- const [previousValue, setPreviousValue] = React.useState(value);
59
- React.useEffect(() => {
60
- setPreviousValue(value);
61
- }, [value]);
62
- return [previousValue, setPreviousValue];
63
- }
64
-
65
- const transitions = {
66
- fromBottom,
67
- fromTop,
68
- fromLeft,
69
- fromRight,
70
- popIn,
71
- fromLeftToRight,
72
- fromRightToLeft,
73
- fade,
74
- };
75
- function AnimatedPresence(props) {
76
- const shouldReduceMotion = framerMotion.useReducedMotion();
77
- if (shouldReduceMotion) {
78
- return React__default["default"].createElement(React__default["default"].Fragment, null, props.children);
79
- }
80
- return React__default["default"].createElement(InternalAnimatedPresence, Object.assign({}, props));
81
- }
82
- function InternalAnimatedPresence({ transition = "fromTop", initial = false, children, }) {
83
- const transitionVariation = transitions[transition];
84
- const hasInitialTransition = "initial" in transitionVariation;
85
- const childCount = React.Children.count(children);
86
- // Set the initial value to 0 so it staggers the animation on mount when
87
- // initial is true.
88
- const [lastChildIndex, setLastChildIndex] = usePreviousValue(0);
89
- // Whenever the children count changes, update the last index.
90
- React.useEffect(() => {
91
- setLastChildIndex(childCount - 1);
92
- }, [childCount]);
93
- return (React__default["default"].createElement(framerMotion.AnimatePresence, { initial: initial, mode: "popLayout" }, React.Children.map(children, (child, i) => child && (React__default["default"].createElement(framerMotion.motion.div, { layout: true, variants: transitionVariation, initial: hasInitialTransition ? "initial" : "hidden", animate: "visible", exit: "hidden", transition: {
94
- duration: TIMING_BASE,
95
- delay: generateDelayTime(i),
96
- } }, child)))));
97
- function generateDelayTime(index) {
98
- // Don't add a delay if it's already rendered.
99
- if (lastChildIndex > index)
100
- return 0;
101
- // Stagger the animation starting after the previous last child index.
102
- return (index - lastChildIndex) * TIMING_QUICK;
103
- }
104
- }
105
-
106
- exports.AnimatedPresence = AnimatedPresence;
12
+ exports.AnimatedPresence = AnimatedPresence.AnimatedPresence;
@@ -0,0 +1,104 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+ var framerMotion = require('framer-motion');
5
+ var design = require('@jobber/design');
6
+
7
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8
+
9
+ var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
10
+
11
+ const TIMING_QUICK = toSeconds(design.tokens["timing-quick"]);
12
+ const TIMING_BASE = toSeconds(design.tokens["timing-base"]);
13
+ const baseTransition = {
14
+ visible: { opacity: 1 },
15
+ hidden: { opacity: 0 },
16
+ };
17
+ const fade = {
18
+ visible: { opacity: 1 },
19
+ hidden: { opacity: 0 },
20
+ };
21
+ const popIn = {
22
+ visible: Object.assign({ scale: 1 }, baseTransition.visible),
23
+ hidden: Object.assign({ scale: 0.95 }, baseTransition.hidden),
24
+ };
25
+ const fromTop = {
26
+ visible: Object.assign({ y: 0 }, baseTransition.visible),
27
+ hidden: Object.assign({ y: -design.tokens["space-base"] }, baseTransition.hidden),
28
+ };
29
+ const fromBottom = {
30
+ visible: Object.assign({ y: 0 }, baseTransition.visible),
31
+ hidden: Object.assign({ y: design.tokens["space-base"] }, baseTransition.hidden),
32
+ };
33
+ const fromLeft = {
34
+ visible: Object.assign({ x: 0 }, baseTransition.visible),
35
+ hidden: Object.assign({ x: -design.tokens["space-base"] }, baseTransition.hidden),
36
+ };
37
+ const fromRight = {
38
+ visible: Object.assign({ x: 0 }, baseTransition.visible),
39
+ hidden: Object.assign({ x: design.tokens["space-base"] }, baseTransition.hidden),
40
+ };
41
+ const fromLeftToRight = {
42
+ initial: Object.assign({ x: -design.tokens["space-base"] }, baseTransition.hidden),
43
+ visible: Object.assign({ x: 0 }, baseTransition.visible),
44
+ hidden: Object.assign({ x: design.tokens["space-base"] }, baseTransition.hidden),
45
+ };
46
+ const fromRightToLeft = {
47
+ initial: Object.assign({ x: design.tokens["space-base"] }, baseTransition.hidden),
48
+ visible: Object.assign({ x: 0 }, baseTransition.visible),
49
+ hidden: Object.assign({ x: -design.tokens["space-base"] }, baseTransition.hidden),
50
+ };
51
+ function toSeconds(ms) {
52
+ return ms / 1000;
53
+ }
54
+
55
+ function usePreviousValue(value) {
56
+ const [previousValue, setPreviousValue] = React.useState(value);
57
+ React.useEffect(() => {
58
+ setPreviousValue(value);
59
+ }, [value]);
60
+ return [previousValue, setPreviousValue];
61
+ }
62
+
63
+ const transitions = {
64
+ fromBottom,
65
+ fromTop,
66
+ fromLeft,
67
+ fromRight,
68
+ popIn,
69
+ fromLeftToRight,
70
+ fromRightToLeft,
71
+ fade,
72
+ };
73
+ function AnimatedPresence(props) {
74
+ const shouldReduceMotion = framerMotion.useReducedMotion();
75
+ if (shouldReduceMotion) {
76
+ return React__default["default"].createElement(React__default["default"].Fragment, null, props.children);
77
+ }
78
+ return React__default["default"].createElement(InternalAnimatedPresence, Object.assign({}, props));
79
+ }
80
+ function InternalAnimatedPresence({ transition = "fromTop", initial = false, children, }) {
81
+ const transitionVariation = transitions[transition];
82
+ const hasInitialTransition = "initial" in transitionVariation;
83
+ const childCount = React.Children.count(children);
84
+ // Set the initial value to 0 so it staggers the animation on mount when
85
+ // initial is true.
86
+ const [lastChildIndex, setLastChildIndex] = usePreviousValue(0);
87
+ // Whenever the children count changes, update the last index.
88
+ React.useEffect(() => {
89
+ setLastChildIndex(childCount - 1);
90
+ }, [childCount]);
91
+ return (React__default["default"].createElement(framerMotion.AnimatePresence, { initial: initial, mode: "popLayout" }, React.Children.map(children, (child, i) => child && (React__default["default"].createElement(framerMotion.motion.div, { layout: true, variants: transitionVariation, initial: hasInitialTransition ? "initial" : "hidden", animate: "visible", exit: "hidden", transition: {
92
+ duration: TIMING_BASE,
93
+ delay: generateDelayTime(i),
94
+ } }, child)))));
95
+ function generateDelayTime(index) {
96
+ // Don't add a delay if it's already rendered.
97
+ if (lastChildIndex > index)
98
+ return 0;
99
+ // Stagger the animation starting after the previous last child index.
100
+ return (index - lastChildIndex) * TIMING_QUICK;
101
+ }
102
+ }
103
+
104
+ exports.AnimatedPresence = AnimatedPresence;
@@ -34,6 +34,10 @@ export interface ComboboxProps {
34
34
  * The amount of time in ms to debounce the onSearch callback. Defaults to 300ms.
35
35
  */
36
36
  readonly onSearchDebounce?: number;
37
+ /**
38
+ * Callback to load more options, this is called when the user scrolls to the bottom of the list.
39
+ */
40
+ readonly onLoadMore?: () => void;
37
41
  /**
38
42
  * The Chip heading for the trigger
39
43
  */
@@ -97,6 +101,10 @@ export interface ComboboxContentProps {
97
101
  * Function called when search input changes.
98
102
  */
99
103
  readonly handleSearchChange: (value: string) => void;
104
+ /**
105
+ * Callback to load more options, this is called when the user scrolls to the bottom of the list.
106
+ */
107
+ readonly onLoadMore?: () => void;
100
108
  /**
101
109
  * Reference to the wrapping div element of all the Combobox pieces
102
110
  */
@@ -191,6 +199,10 @@ export interface ComboboxListProps {
191
199
  * Should loading state be shown.
192
200
  */
193
201
  readonly loading?: boolean;
202
+ /**
203
+ * Callback to load more options, this is called when the user scrolls to the bottom of the list.
204
+ */
205
+ readonly onLoadMore?: () => void;
194
206
  }
195
207
  export interface ComboboxActionProps {
196
208
  /**
@@ -0,0 +1,6 @@
1
+ /// <reference types="react" />
2
+ interface ComboboxLoadMoreProps {
3
+ readonly onLoadMore: () => void;
4
+ }
5
+ export declare function ComboboxLoadMore({ onLoadMore }: ComboboxLoadMoreProps): JSX.Element;
6
+ export {};
@@ -0,0 +1 @@
1
+ export { ComboboxLoadMore } from "./ComboboxLoadMore";
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var Combobox = require('../Combobox-1c91da1f.js');
5
+ var Combobox = require('../Combobox-ca9ac94b.js');
6
6
  require('react');
7
7
  require('classnames');
8
8
  require('react-dom');
@@ -14,6 +14,10 @@ require('../Typography-c45bf216.js');
14
14
  require('../Glimmer-7c317864.js');
15
15
  require('../tslib.es6-754e2961.js');
16
16
  require('../Content-e3f7b6fc.js');
17
+ require('../Spinner-9d8fc7ff.js');
18
+ require('../AnimatedPresence-20a02aaa.js');
19
+ require('framer-motion');
20
+ require('@jobber/hooks/useInView');
17
21
  require('../Button-b73a5e01.js');
18
22
  require('react-router-dom');
19
23
  require('@jobber/hooks/useRefocusOnActivator');
@@ -21,11 +25,9 @@ require('@jobber/hooks/useFocusTrap');
21
25
  require('react-popper');
22
26
  require('@jobber/hooks/useOnKeyDown');
23
27
  require('../Chip-c91fd6c8.js');
24
- require('@jobber/hooks/useInView');
25
28
  require('../Avatar-76a799fa.js');
26
29
  require('color');
27
30
  require('../Tooltip-27771182.js');
28
- require('framer-motion');
29
31
  require('lodash/debounce');
30
32
  require('lodash/noop');
31
33
  require('@jobber/hooks/useAssert');
@@ -7,7 +7,10 @@ var styleInject_es = require('./style-inject.es-9d2f5f4e.js');
7
7
  var Icon = require('./Icon-405a216c.js');
8
8
  var Text = require('./Text-259af966.js');
9
9
  var Glimmer = require('./Glimmer-7c317864.js');
10
+ var Spinner = require('./Spinner-9d8fc7ff.js');
11
+ var AnimatedPresence = require('./AnimatedPresence-20a02aaa.js');
10
12
  var tslib_es6 = require('./tslib.es6-754e2961.js');
13
+ var useInView = require('@jobber/hooks/useInView');
11
14
  var Typography = require('./Typography-c45bf216.js');
12
15
  var Button = require('./Button-b73a5e01.js');
13
16
  var useRefocusOnActivator = require('@jobber/hooks/useRefocusOnActivator');
@@ -28,13 +31,13 @@ var ReactDOM__default = /*#__PURE__*/_interopDefaultLegacy(ReactDOM);
28
31
  var debounce__default = /*#__PURE__*/_interopDefaultLegacy(debounce);
29
32
  var noop__default = /*#__PURE__*/_interopDefaultLegacy(noop);
30
33
 
31
- var css_248z$6 = ".m1w5vdUZ6rQ- {\n z-index: 1002;\n z-index: var(--elevation-tooltip);\n width: calc((16px * 4) * 3.75);\n width: calc(calc(16px * 4) * 3.75);\n width: calc(var(--space-extravagant) * 3.75);\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 margin-top: calc(16px / 2);\n margin-top: var(--space-small);\n border: calc(16px / 16) solid rgb(217, 223, 225);\n border: var(--border-base) solid var(--color-border);\n border-radius: calc(16px / 2);\n border-radius: var(--radius-larger);\n overflow: auto;\n background: rgba(255, 255, 255, 1);\n background: var(--color-surface);\n}\n\n.jobber-retheme .m1w5vdUZ6rQ- {\n border-radius: calc(16px / 8);\n border-radius: var(--radius-base);\n}\n\n/* CAUTION: Tests for content visibility assume this class' presence hides the content\n* so please be careful if you change this class name, or the css rules within.\n*/\n\n.m1w5vdUZ6rQ-.Zlkv2HA096A- {\n display: none;\n visibility: hidden;\n}\n\n.m1w5vdUZ6rQ-:focus,\n.m1w5vdUZ6rQ-:focus-visible {\n outline: none;\n}\n\n.m1w5vdUZ6rQ-:focus-visible {\n box-shadow: 0px 0px 0px calc(16px / 8) rgba(255, 255, 255, 1),\n 0px 0px 0px calc(16px / 4) rgb(147, 161, 169);\n box-shadow: var(--shadow-focus);\n}\n\n.YQry-Rd6zfQ- {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-direction: column;\n flex-direction: column;\n position: sticky;\n gap: calc(16px / 4);\n gap: var(--space-smaller);\n bottom: 0;\n width: 100%;\n background-color: rgba(255, 255, 255, 1);\n background-color: var(--color-surface);\n}\n\n.TcpqL34s4lI- {\n padding-bottom: calc(16px / 2);\n padding-bottom: var(--space-small);\n}\n";
32
- var styles$6 = {"content":"m1w5vdUZ6rQ-","hidden":"Zlkv2HA096A-","actions":"YQry-Rd6zfQ-","actionPadding":"TcpqL34s4lI-"};
33
- styleInject_es.styleInject(css_248z$6);
34
+ var css_248z$7 = ".m1w5vdUZ6rQ- {\n z-index: 1002;\n z-index: var(--elevation-tooltip);\n width: calc((16px * 4) * 3.75);\n width: calc(calc(16px * 4) * 3.75);\n width: calc(var(--space-extravagant) * 3.75);\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 margin-top: calc(16px / 2);\n margin-top: var(--space-small);\n border: calc(16px / 16) solid rgb(217, 223, 225);\n border: var(--border-base) solid var(--color-border);\n border-radius: calc(16px / 2);\n border-radius: var(--radius-larger);\n overflow: auto;\n background: rgba(255, 255, 255, 1);\n background: var(--color-surface);\n}\n\n.jobber-retheme .m1w5vdUZ6rQ- {\n border-radius: calc(16px / 8);\n border-radius: var(--radius-base);\n}\n\n/* CAUTION: Tests for content visibility assume this class' presence hides the content\n* so please be careful if you change this class name, or the css rules within.\n*/\n\n.m1w5vdUZ6rQ-.Zlkv2HA096A- {\n display: none;\n visibility: hidden;\n}\n\n.m1w5vdUZ6rQ-:focus,\n.m1w5vdUZ6rQ-:focus-visible {\n outline: none;\n}\n\n.m1w5vdUZ6rQ-:focus-visible {\n box-shadow: 0px 0px 0px calc(16px / 8) rgba(255, 255, 255, 1),\n 0px 0px 0px calc(16px / 4) rgb(147, 161, 169);\n box-shadow: var(--shadow-focus);\n}\n\n.YQry-Rd6zfQ- {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-direction: column;\n flex-direction: column;\n position: sticky;\n gap: calc(16px / 4);\n gap: var(--space-smaller);\n bottom: 0;\n width: 100%;\n background-color: rgba(255, 255, 255, 1);\n background-color: var(--color-surface);\n}\n\n.TcpqL34s4lI- {\n padding-bottom: calc(16px / 2);\n padding-bottom: var(--space-small);\n}\n";
35
+ var styles$7 = {"content":"m1w5vdUZ6rQ-","hidden":"Zlkv2HA096A-","actions":"YQry-Rd6zfQ-","actionPadding":"TcpqL34s4lI-"};
36
+ styleInject_es.styleInject(css_248z$7);
34
37
 
35
- var css_248z$5 = ".MIyb-oFZg9w- {\n position: relative;\n}\n\n.WZPK91I4aJs- {\n width: 100%;\n padding: calc(16px * 1);\n padding: var(--space-base);\n padding-right: calc((16px * 1.5) * 2.25);\n padding-right: calc(calc(16px * 1.5) * 2.25);\n padding-right: calc(var(--space-large) * 2.25);\n border: none;\n border-bottom: calc(16px / 16) solid rgb(217, 223, 225);\n border-bottom: var(--border-base) solid var(--color-border);\n font-family: \"Inter\", Helvetica, Arial, sans-serif;\n font-family: var(--typography--fontFamily-normal);\n font-size: calc((16px * 1) * 0.875);\n font-size: calc(calc(16px * 1) * 0.875);\n font-size: var(--typography--fontSize-base);\n}\n\n.WZPK91I4aJs-::-webkit-search-decoration,\n.WZPK91I4aJs-::-webkit-search-cancel-button,\n.WZPK91I4aJs-::-webkit-search-results-button,\n.WZPK91I4aJs-::-webkit-search-results-decoration {\n -webkit-appearance: none;\n}\n\n.WZPK91I4aJs-:focus {\n outline: none;\n}\n\n._7loHrVUe-Rk- {\n display: -ms-flexbox;\n display: flex;\n position: absolute;\n top: 50%;\n right: calc(16px * 1);\n right: var(--space-base);\n z-index: 1002;\n z-index: var(--elevation-tooltip);\n width: calc(16px * 1.5);\n width: var(--space-large);\n height: calc(16px * 1.5);\n height: var(--space-large);\n padding: 0;\n border: none;\n border-radius: 100%;\n border-radius: var(--radius-circle);\n background-color: rgb(238, 240, 242);\n background-color: var(--color-surface--background);\n cursor: pointer;\n -webkit-transform: translateY(-50%);\n transform: translateY(-50%);\n -ms-flex-pack: center;\n justify-content: center;\n -ms-flex-align: center;\n align-items: center;\n}\n\n._7loHrVUe-Rk-:focus {\n outline: transparent;\n}\n\n._7loHrVUe-Rk-:focus-visible {\n box-shadow: 0px 0px 0px calc(16px / 8) rgba(255, 255, 255, 1),\n 0px 0px 0px calc(16px / 4) rgb(147, 161, 169);\n box-shadow: var(--shadow-focus);\n}\n";
36
- var styles$5 = {"search":"MIyb-oFZg9w-","searchInput":"WZPK91I4aJs-","clearSearch":"_7loHrVUe-Rk-"};
37
- styleInject_es.styleInject(css_248z$5);
38
+ var css_248z$6 = ".MIyb-oFZg9w- {\n position: relative;\n}\n\n.WZPK91I4aJs- {\n width: 100%;\n padding: calc(16px * 1);\n padding: var(--space-base);\n padding-right: calc((16px * 1.5) * 2.25);\n padding-right: calc(calc(16px * 1.5) * 2.25);\n padding-right: calc(var(--space-large) * 2.25);\n border: none;\n border-bottom: calc(16px / 16) solid rgb(217, 223, 225);\n border-bottom: var(--border-base) solid var(--color-border);\n font-family: \"Inter\", Helvetica, Arial, sans-serif;\n font-family: var(--typography--fontFamily-normal);\n font-size: calc((16px * 1) * 0.875);\n font-size: calc(calc(16px * 1) * 0.875);\n font-size: var(--typography--fontSize-base);\n}\n\n.WZPK91I4aJs-::-webkit-search-decoration,\n.WZPK91I4aJs-::-webkit-search-cancel-button,\n.WZPK91I4aJs-::-webkit-search-results-button,\n.WZPK91I4aJs-::-webkit-search-results-decoration {\n -webkit-appearance: none;\n}\n\n.WZPK91I4aJs-:focus {\n outline: none;\n}\n\n._7loHrVUe-Rk- {\n display: -ms-flexbox;\n display: flex;\n position: absolute;\n top: 50%;\n right: calc(16px * 1);\n right: var(--space-base);\n z-index: 1002;\n z-index: var(--elevation-tooltip);\n width: calc(16px * 1.5);\n width: var(--space-large);\n height: calc(16px * 1.5);\n height: var(--space-large);\n padding: 0;\n border: none;\n border-radius: 100%;\n border-radius: var(--radius-circle);\n background-color: rgb(238, 240, 242);\n background-color: var(--color-surface--background);\n cursor: pointer;\n -webkit-transform: translateY(-50%);\n transform: translateY(-50%);\n -ms-flex-pack: center;\n justify-content: center;\n -ms-flex-align: center;\n align-items: center;\n}\n\n._7loHrVUe-Rk-:focus {\n outline: transparent;\n}\n\n._7loHrVUe-Rk-:focus-visible {\n box-shadow: 0px 0px 0px calc(16px / 8) rgba(255, 255, 255, 1),\n 0px 0px 0px calc(16px / 4) rgb(147, 161, 169);\n box-shadow: var(--shadow-focus);\n}\n";
39
+ var styles$6 = {"search":"MIyb-oFZg9w-","searchInput":"WZPK91I4aJs-","clearSearch":"_7loHrVUe-Rk-"};
40
+ styleInject_es.styleInject(css_248z$6);
38
41
 
39
42
  function ComboboxContentSearch(props) {
40
43
  const searchRef = React.useRef(null);
@@ -46,9 +49,9 @@ function ComboboxContentSearch(props) {
46
49
  }, 0);
47
50
  }
48
51
  }, [props.open]);
49
- return (React__default["default"].createElement("div", { className: styles$5.search },
50
- React__default["default"].createElement("input", { type: "search", ref: searchRef, className: styles$5.searchInput, placeholder: props.placeholder ? `Search ${props.placeholder}` : "Search", onChange: (event) => handleSearch(event), value: props.searchValue }),
51
- props.searchValue && (React__default["default"].createElement("button", { className: styles$5.clearSearch, onClick: clearSearch, type: "button", "data-testid": "ATL-Combobox-Content-Search-Clear", "aria-label": "Clear search" },
52
+ return (React__default["default"].createElement("div", { className: styles$6.search },
53
+ React__default["default"].createElement("input", { type: "search", ref: searchRef, className: styles$6.searchInput, placeholder: props.placeholder ? `Search ${props.placeholder}` : "Search", onChange: (event) => handleSearch(event), value: props.searchValue }),
54
+ props.searchValue && (React__default["default"].createElement("button", { className: styles$6.clearSearch, onClick: clearSearch, type: "button", "data-testid": "ATL-Combobox-Content-Search-Clear", "aria-label": "Clear search" },
52
55
  React__default["default"].createElement(Icon.Icon, { name: "remove", size: "small" })))));
53
56
  function clearSearch() {
54
57
  var _a;
@@ -62,13 +65,13 @@ function ComboboxContentSearch(props) {
62
65
  }
63
66
  }
64
67
 
65
- var css_248z$4 = ".SgMzjOcdE-E- {\n position: relative;\n padding: calc(16px / 2) 0;\n padding: var(--space-small) 0;\n}\n\n.TwoTCjgcssc- {\n display: -ms-flexbox;\n display: flex;\n max-height: calc((16px / 2) * 33.33);\n max-height: calc(calc(16px / 2) * 33.33);\n max-height: calc(var(--space-small) * 33.33);\n margin: 0;\n padding: 0;\n overflow: auto;\n list-style: none;\n -ms-flex-direction: column;\n flex-direction: column;\n gap: calc(16px / 4);\n gap: var(--space-smaller);\n}\n\n._8T5M7MGwCRE-,\n._4y5NXkNeIQM- {\n padding: calc(16px / 2) calc(16px * 1);\n padding: var(--space-small) var(--space-base);\n}\n\n.SgMzjOcdE-E-::before,\n.SgMzjOcdE-E-::after {\n content: \"\";\n display: block;\n position: absolute;\n right: 0;\n left: 0;\n height: calc(16px * 1);\n height: var(--space-base);\n pointer-events: none;\n transition: opacity 0.3s ease-in-out;\n}\n\n.SgMzjOcdE-E-::after {\n bottom: calc(16px / 2);\n bottom: var(--space-small);\n background: linear-gradient(\n 180deg,\n rgba(255, 255, 255, 0) 0%,\n rgb(255, 255, 255) 100%\n );\n}\n\n.SgMzjOcdE-E-::before {\n top: calc(16px / 2);\n top: var(--space-small);\n background: linear-gradient(\n to bottom,\n rgba(255, 255, 255, 1),\n rgba(255, 255, 255, 0)\n );\n}\n\n.T6E3VwBGoQM-::before,\n._6HQzxMQkXnE-::before {\n opacity: 0;\n}\n\n._5YsJZyMDkbA-::after,\n._6HQzxMQkXnE-::after {\n opacity: 0;\n}\n\n.A6z4OI58xoE- {\n padding: calc(16px * 1) calc(16px * 1);\n padding: var(--space-base) var(--space-base);\n}\n";
66
- var styles$4 = {"container":"SgMzjOcdE-E-","optionsList":"TwoTCjgcssc-","filterMessage":"_8T5M7MGwCRE-","emptyStateMessage":"_4y5NXkNeIQM-","scrollTop":"T6E3VwBGoQM-","scrollNone":"_6HQzxMQkXnE-","scrollBottom":"_5YsJZyMDkbA-","loadingContainer":"A6z4OI58xoE-"};
67
- styleInject_es.styleInject(css_248z$4);
68
+ var css_248z$5 = ".SgMzjOcdE-E- {\n position: relative;\n padding: calc(16px / 2) 0;\n padding: var(--space-small) 0;\n}\n\n.TwoTCjgcssc- {\n display: -ms-flexbox;\n display: flex;\n\n max-height: calc((16px / 2) * 33.33);\n\n max-height: calc(calc(16px / 2) * 33.33);\n\n max-height: calc(var(--space-small) * 33.33);\n margin: 0;\n padding: 0;\n overflow: auto;\n list-style: none;\n -ms-flex-direction: column;\n flex-direction: column;\n gap: calc(16px / 4);\n gap: var(--space-smaller);\n}\n\n._8T5M7MGwCRE-,\n._4y5NXkNeIQM- {\n padding: calc(16px / 2) calc(16px * 1);\n padding: var(--space-small) var(--space-base);\n}\n\n.SgMzjOcdE-E-::before,\n.SgMzjOcdE-E-::after {\n content: \"\";\n display: block;\n position: absolute;\n right: 0;\n left: 0;\n height: calc(16px * 1);\n height: var(--space-base);\n pointer-events: none;\n transition: opacity 0.3s ease-in-out;\n}\n\n.SgMzjOcdE-E-::after {\n bottom: calc(16px / 2);\n bottom: var(--space-small);\n background: linear-gradient(\n 180deg,\n rgba(255, 255, 255, 0) 0%,\n rgb(255, 255, 255) 100%\n );\n}\n\n.SgMzjOcdE-E-::before {\n top: calc(16px / 2);\n top: var(--space-small);\n background: linear-gradient(\n to bottom,\n rgba(255, 255, 255, 1),\n rgba(255, 255, 255, 0)\n );\n}\n\n.T6E3VwBGoQM-::before,\n._6HQzxMQkXnE-::before {\n opacity: 0;\n}\n\n._5YsJZyMDkbA-::after,\n._6HQzxMQkXnE-::after {\n opacity: 0;\n}\n\n.A6z4OI58xoE- {\n padding: calc(16px * 1) calc(16px * 1);\n padding: var(--space-base) var(--space-base);\n}\n\n.A6z4OI58xoE-.QqHBSf52fPk- {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-pack: center;\n justify-content: center;\n position: sticky;\n bottom: 0;\n padding: calc(16px * 1) 0;\n padding: var(--space-base) 0;\n}\n\n.A6z4OI58xoE-.QqHBSf52fPk-:empty {\n display: none;\n}\n";
69
+ var styles$5 = {"container":"SgMzjOcdE-E-","optionsList":"TwoTCjgcssc-","filterMessage":"_8T5M7MGwCRE-","emptyStateMessage":"_4y5NXkNeIQM-","scrollTop":"T6E3VwBGoQM-","scrollNone":"_6HQzxMQkXnE-","scrollBottom":"_5YsJZyMDkbA-","loadingContainer":"A6z4OI58xoE-","hasOptions":"QqHBSf52fPk-"};
70
+ styleInject_es.styleInject(css_248z$5);
68
71
 
69
- var css_248z$3 = "._5QdRGmaNHvc- {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-negative: 0;\n flex-shrink: 0;\n min-height: calc((calc(16px * 3) - calc(16px / 4)));\n min-height: calc((var(--space-largest) - var(--space-smaller)));\n box-sizing: border-box;\n margin: 0 calc(16px / 2);\n margin: 0 var(--space-small);\n padding: calc(16px / 2);\n padding: var(--space-small);\n border-radius: calc(16px / 4);\n border-radius: var(--radius-large);\n color: rgb(1, 41, 57);\n color: var(--color-heading);\n font-weight: 500;\n cursor: pointer;\n transition: all 200ms;\n transition: all var(--timing-base);\n -ms-flex-pack: justify;\n justify-content: space-between;\n -ms-flex-align: center;\n align-items: center;\n}\n\n.jobber-retheme ._5QdRGmaNHvc- {\n border-radius: calc(16px / 8);\n border-radius: var(--radius-base);\n}\n\n._5QdRGmaNHvc-:hover,\n._5QdRGmaNHvc-:focus-visible {\n background-color: rgb(244, 246, 250);\n background-color: var(--color-surface--hover);\n}\n\n._5QdRGmaNHvc-:focus,\n._5QdRGmaNHvc-:focus-visible {\n outline: none;\n}\n\n._5QdRGmaNHvc-:focus-visible {\n box-shadow: 0px 0px 0px calc(16px / 8) rgba(255, 255, 255, 1),\n 0px 0px 0px calc(16px / 4) rgb(147, 161, 169);\n box-shadow: var(--shadow-focus);\n}\n";
70
- var styles$3 = {"option":"_5QdRGmaNHvc-"};
71
- styleInject_es.styleInject(css_248z$3);
72
+ var css_248z$4 = "._5QdRGmaNHvc- {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-negative: 0;\n flex-shrink: 0;\n min-height: calc((calc(16px * 3) - calc(16px / 4)));\n min-height: calc((var(--space-largest) - var(--space-smaller)));\n box-sizing: border-box;\n margin: 0 calc(16px / 2);\n margin: 0 var(--space-small);\n padding: calc(16px / 2);\n padding: var(--space-small);\n border-radius: calc(16px / 4);\n border-radius: var(--radius-large);\n color: rgb(1, 41, 57);\n color: var(--color-heading);\n font-weight: 500;\n cursor: pointer;\n transition: all 200ms;\n transition: all var(--timing-base);\n -ms-flex-pack: justify;\n justify-content: space-between;\n -ms-flex-align: center;\n align-items: center;\n}\n\n.jobber-retheme ._5QdRGmaNHvc- {\n border-radius: calc(16px / 8);\n border-radius: var(--radius-base);\n}\n\n._5QdRGmaNHvc-:hover,\n._5QdRGmaNHvc-:focus-visible {\n background-color: rgb(244, 246, 250);\n background-color: var(--color-surface--hover);\n}\n\n._5QdRGmaNHvc-:focus,\n._5QdRGmaNHvc-:focus-visible {\n outline: none;\n}\n\n._5QdRGmaNHvc-:focus-visible {\n box-shadow: 0px 0px 0px calc(16px / 8) rgba(255, 255, 255, 1),\n 0px 0px 0px calc(16px / 4) rgb(147, 161, 169);\n box-shadow: var(--shadow-focus);\n}\n";
73
+ var styles$4 = {"option":"_5QdRGmaNHvc-"};
74
+ styleInject_es.styleInject(css_248z$4);
72
75
 
73
76
  const ComboboxContext = React__default["default"].createContext({});
74
77
  function ComboboxContextProvider(_a) {
@@ -80,29 +83,42 @@ function ComboboxOption(props) {
80
83
  const { selected, selectionHandler } = React.useContext(ComboboxContext);
81
84
  const isSelected = selected.some(selection => selection.id.toString() === props.id.toString());
82
85
  return (React__default["default"].createElement("li", { key: props.id, tabIndex: -1, "data-selected": isSelected, role: "option", "aria-selected": isSelected, onClick: () => selectionHandler &&
83
- selectionHandler({ id: props.id, label: props.label }), className: classnames__default["default"](styles$3.option) },
86
+ selectionHandler({ id: props.id, label: props.label }), className: classnames__default["default"](styles$4.option) },
84
87
  props.label,
85
88
  React__default["default"].createElement("div", null, isSelected && React__default["default"].createElement(Icon.Icon, { name: "checkmark", color: "blue" }))));
86
89
  }
87
90
 
91
+ var css_248z$3 = "._3s8-RC5Ky3s- {\n -webkit-transform: translateY(calc((16px * 3) * -1));\n -webkit-transform: translateY(calc(calc(16px * 3) * -1));\n -webkit-transform: translateY(calc(var(--space-largest) * -1));\n transform: translateY(calc((16px * 3) * -1));\n transform: translateY(calc(calc(16px * 3) * -1));\n transform: translateY(calc(var(--space-largest) * -1));\n}\n";
92
+ var styles$3 = {"trigger":"_3s8-RC5Ky3s-"};
93
+ styleInject_es.styleInject(css_248z$3);
94
+
95
+ function ComboboxLoadMore({ onLoadMore }) {
96
+ const [inViewRef, isInView] = useInView.useInView();
97
+ React.useEffect(() => {
98
+ isInView && onLoadMore();
99
+ }, [isInView]);
100
+ return (React__default["default"].createElement("div", { "data-testid": "ATL-Combobox-Loadmore-Trigger", ref: inViewRef, className: styles$3.trigger }));
101
+ }
102
+
88
103
  function ComboboxContentList(props) {
89
104
  const optionsExist = props.options.length > 0;
90
- const showOptions = optionsExist && !props.loading;
91
105
  const hasSearchTerm = props.searchValue.length > 0;
92
106
  const { listScrollState } = useScrollState(props.optionsListRef, props.options);
93
- return (React__default["default"].createElement("div", { className: classnames__default["default"](styles$4.container, styles$4[listScrollState]) },
94
- optionsExist && (React__default["default"].createElement("ul", { className: styles$4.optionsList, role: "listbox", "aria-multiselectable": props.multiselect, ref: props.optionsListRef },
95
- showOptions &&
96
- props.options.map(option => {
97
- return (React__default["default"].createElement(ComboboxOption, { key: option.id, id: option.id, label: option.label }));
98
- }),
99
- props.loading && (React__default["default"].createElement(React__default["default"].Fragment, null, Array.from({ length: 5 }).map((_, index) => (React__default["default"].createElement("div", { className: styles$4.loadingContainer, key: index },
100
- React__default["default"].createElement(Glimmer.Glimmer, { shape: "rectangle", size: "small" })))))))),
101
- hasSearchTerm && !optionsExist && (React__default["default"].createElement("div", { className: styles$4.filterMessage },
107
+ return (React__default["default"].createElement("div", { className: classnames__default["default"](styles$5.container, styles$5[listScrollState]) },
108
+ optionsExist && (React__default["default"].createElement("ul", { className: styles$5.optionsList, role: "listbox", "aria-multiselectable": props.multiselect, ref: props.optionsListRef },
109
+ props.options.map(option => {
110
+ return (React__default["default"].createElement(ComboboxOption, { key: option.id, id: option.id, label: option.label }));
111
+ }),
112
+ React__default["default"].createElement("div", { className: classnames__default["default"]([styles$5.loadingContainer, styles$5.hasOptions]) },
113
+ React__default["default"].createElement(AnimatedPresence.AnimatedPresence, { transition: "fromBottom" }, Boolean(props.loading && optionsExist) && (React__default["default"].createElement(Spinner.Spinner, { size: "small" })))),
114
+ props.onLoadMore && (React__default["default"].createElement(ComboboxLoadMore, { onLoadMore: props.onLoadMore })))),
115
+ props.loading && !optionsExist && (React__default["default"].createElement(React__default["default"].Fragment, null, Array.from({ length: 5 }).map((_, index) => (React__default["default"].createElement("div", { className: styles$5.loadingContainer, key: index },
116
+ React__default["default"].createElement(Glimmer.Glimmer, { shape: "rectangle", size: "small" })))))),
117
+ hasSearchTerm && !props.loading && !optionsExist && (React__default["default"].createElement("div", { className: styles$5.filterMessage },
102
118
  React__default["default"].createElement(Text.Text, { variation: "subdued" },
103
119
  "No results for ",
104
120
  `“${props.searchValue}”`))),
105
- !hasSearchTerm && !optionsExist && (React__default["default"].createElement("div", { className: styles$4.emptyStateMessage },
121
+ !hasSearchTerm && !props.loading && !optionsExist && (React__default["default"].createElement("div", { className: styles$5.emptyStateMessage },
106
122
  React__default["default"].createElement(Text.Text, { variation: "subdued" }, getZeroIndexStateText(props.subjectNoun))))));
107
123
  }
108
124
  function getZeroIndexStateText(subjectNoun) {
@@ -283,16 +299,16 @@ function ComboboxContent(props) {
283
299
  const optionsExist = props.options.length > 0;
284
300
  const { optionsListRef } = useComboboxContent(props.open, props.selected);
285
301
  const { popperRef, popperStyles, attributes } = useComboboxAccessibility(props.handleSelection, props.options, optionsListRef, props.open, props.wrapperRef);
286
- const template = (React__default["default"].createElement("div", Object.assign({ ref: popperRef, id: "ATL-Combobox-Content", "data-testid": "ATL-Combobox-Content", tabIndex: 0, className: classnames__default["default"](styles$6.content, { [styles$6.hidden]: !props.open }), style: popperStyles.popper }, attributes.popper),
302
+ const template = (React__default["default"].createElement("div", Object.assign({ ref: popperRef, id: "ATL-Combobox-Content", "data-testid": "ATL-Combobox-Content", tabIndex: 0, className: classnames__default["default"](styles$7.content, { [styles$7.hidden]: !props.open }), style: popperStyles.popper }, attributes.popper),
287
303
  React__default["default"].createElement(ComboboxContentSearch, { open: props.open, placeholder: props.subjectNoun, searchValue: props.searchValue, setSearchValue: props.setSearchValue, handleSearchChange: props.handleSearchChange }),
288
304
  props.multiselect && optionsExist && (React__default["default"].createElement(ComboboxContentHeader, { hasOptionsVisible: optionsExist, subjectNoun: props.subjectNoun, selectedCount: props.selected.length, onClearAll: () => {
289
305
  props.selectedStateSetter([]);
290
306
  }, onSelectAll: () => {
291
307
  props.selectedStateSetter(props.options);
292
308
  } })),
293
- React__default["default"].createElement(ComboboxContentList, { multiselect: props.multiselect, options: props.options, selected: props.selected, optionsListRef: optionsListRef, searchValue: props.searchValue, subjectNoun: props.subjectNoun, loading: props.loading }),
294
- props.actionElements && (React__default["default"].createElement("div", { className: styles$6.actions, role: "group" }, props.actionElements.map((child, index, childrenArray) => (React__default["default"].createElement("div", { key: index, className: classnames__default["default"]({
295
- [styles$6.actionPadding]: index === childrenArray.length - 1,
309
+ React__default["default"].createElement(ComboboxContentList, { multiselect: props.multiselect, options: props.options, selected: props.selected, optionsListRef: optionsListRef, searchValue: props.searchValue, subjectNoun: props.subjectNoun, loading: props.loading, onLoadMore: props.onLoadMore }),
310
+ props.actionElements && (React__default["default"].createElement("div", { className: styles$7.actions, role: "group" }, props.actionElements.map((child, index, childrenArray) => (React__default["default"].createElement("div", { key: index, className: classnames__default["default"]({
311
+ [styles$7.actionPadding]: index === childrenArray.length - 1,
296
312
  }) }, child)))))));
297
313
  return ReactDOM__default["default"].createPortal(template, document.body);
298
314
  }
@@ -448,7 +464,7 @@ function Combobox(props) {
448
464
  React__default["default"].createElement("div", { ref: wrapperRef, className: styles.wrapper },
449
465
  open && (React__default["default"].createElement("div", { className: styles.overlay, onClick: () => handleClose(), "data-testid": "ATL-Combobox-Overlay" })),
450
466
  triggerElement || (React__default["default"].createElement(ComboboxTrigger, { label: props.label, selected: props.selected })),
451
- React__default["default"].createElement(ComboboxContent, { multiselect: props.multiSelect, subjectNoun: props.subjectNoun, selected: selectedOptions, actionElements: actionElements, selectedStateSetter: selectedStateSetter, handleSelection: handleSelection, searchValue: searchValue, setSearchValue: setSearchValue, wrapperRef: wrapperRef, open: open, setOpen: setOpen, options: props.onSearch ? options : internalFilteredOptions, loading: props.loading, handleSearchChange: handleSearchChange }))));
467
+ React__default["default"].createElement(ComboboxContent, { multiselect: props.multiSelect, subjectNoun: props.subjectNoun, selected: selectedOptions, actionElements: actionElements, selectedStateSetter: selectedStateSetter, handleSelection: handleSelection, searchValue: searchValue, setSearchValue: setSearchValue, wrapperRef: wrapperRef, open: open, setOpen: setOpen, options: props.onSearch ? options : internalFilteredOptions, loading: props.loading, handleSearchChange: handleSearchChange, onLoadMore: props.onLoadMore }))));
452
468
  }
453
469
  Combobox.Activator = ComboboxActivator;
454
470
  Combobox.Action = ComboboxAction;
@@ -26,7 +26,7 @@ var ReactDOM = require('react-dom');
26
26
  var Checkbox = require('../Checkbox-99f6297f.js');
27
27
  var reactRouterDom = require('react-router-dom');
28
28
  var AnimatedSwitcher = require('../AnimatedSwitcher-3d45ec5d.js');
29
- var Combobox = require('../Combobox-1c91da1f.js');
29
+ var Combobox = require('../Combobox-ca9ac94b.js');
30
30
  var Chip = require('../Chip-c91fd6c8.js');
31
31
  var debounce = require('lodash/debounce');
32
32
  var InputText = require('../InputText-6e356985.js');
@@ -37,6 +37,7 @@ require('react-popper');
37
37
  require('../getAtlantisConfig-0f3e8af2.js');
38
38
  require('uuid');
39
39
  require('react-hook-form');
40
+ require('../AnimatedPresence-20a02aaa.js');
40
41
  require('@jobber/hooks/useAssert');
41
42
  require('../Avatar-76a799fa.js');
42
43
  require('color');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jobber/components",
3
- "version": "4.78.4",
3
+ "version": "4.79.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": "f1a0ac8ba5499c0d892c534a5916c2c799e85ad7"
87
+ "gitHead": "78a7f41466245e133f4966509bea0e4121c3e77c"
88
88
  }