@toptal/picasso-utils 4.0.1 → 4.0.2-alpha-pf-fix-alpha-release-4de9263c3.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.
Files changed (34) hide show
  1. package/dist-package/src/utils/ClickAwayListener/ClickAwayListener.d.ts +21 -0
  2. package/dist-package/src/utils/ClickAwayListener/ClickAwayListener.d.ts.map +1 -0
  3. package/dist-package/src/utils/ClickAwayListener/ClickAwayListener.js +111 -0
  4. package/dist-package/src/utils/ClickAwayListener/ClickAwayListener.js.map +1 -0
  5. package/dist-package/src/utils/ClickAwayListener/index.d.ts +5 -0
  6. package/dist-package/src/utils/ClickAwayListener/index.d.ts.map +1 -0
  7. package/dist-package/src/utils/ClickAwayListener/index.js +3 -0
  8. package/dist-package/src/utils/ClickAwayListener/index.js.map +1 -0
  9. package/dist-package/src/utils/Transitions/Rotate180/Rotate180.d.ts.map +1 -1
  10. package/dist-package/src/utils/Transitions/Rotate180/Rotate180.js +3 -9
  11. package/dist-package/src/utils/Transitions/Rotate180/Rotate180.js.map +1 -1
  12. package/dist-package/src/utils/Transitions/Rotate180/styles.d.ts +1 -2
  13. package/dist-package/src/utils/Transitions/Rotate180/styles.d.ts.map +1 -1
  14. package/dist-package/src/utils/Transitions/Rotate180/styles.js +6 -9
  15. package/dist-package/src/utils/Transitions/Rotate180/styles.js.map +1 -1
  16. package/dist-package/src/utils/capitalize.d.ts +1 -1
  17. package/dist-package/src/utils/capitalize.d.ts.map +1 -1
  18. package/dist-package/src/utils/capitalize.js +8 -1
  19. package/dist-package/src/utils/capitalize.js.map +1 -1
  20. package/dist-package/src/utils/index.d.ts +2 -1
  21. package/dist-package/src/utils/index.d.ts.map +1 -1
  22. package/dist-package/src/utils/index.js +1 -1
  23. package/dist-package/src/utils/index.js.map +1 -1
  24. package/package.json +7 -7
  25. package/src/utils/ClickAwayListener/ClickAwayListener.tsx +191 -0
  26. package/src/utils/ClickAwayListener/index.ts +5 -0
  27. package/src/utils/ClickAwayListener/test.tsx +99 -0
  28. package/src/utils/Modal/__snapshots__/test.tsx.snap +186 -58
  29. package/src/utils/Modal/test.tsx +2 -6
  30. package/src/utils/Transitions/Rotate180/Rotate180.tsx +3 -11
  31. package/src/utils/Transitions/Rotate180/__snapshots__/test.tsx.snap +2 -2
  32. package/src/utils/Transitions/Rotate180/styles.ts +6 -11
  33. package/src/utils/capitalize.ts +9 -1
  34. package/src/utils/index.ts +2 -1
@@ -0,0 +1,21 @@
1
+ import type { MouseEvent as ReactMouseEvent, ReactElement } from 'react';
2
+ type ClickAwayMouseEventHandler = 'onClick' | 'onMouseDown' | 'onMouseUp';
3
+ type ClickAwayTouchEventHandler = 'onTouchStart' | 'onTouchEnd';
4
+ export interface Props {
5
+ /** The wrapped element. */
6
+ children: ReactElement;
7
+ /** If `true`, the React tree is ignored and only the DOM tree is considered. Changes how portaled elements are handled. */
8
+ disableReactTree?: boolean;
9
+ /** The mouse event to listen to. Pass `false` to disable the mouse listener. */
10
+ mouseEvent?: ClickAwayMouseEventHandler | false;
11
+ /** Callback fired when a click-away event is detected. */
12
+ onClickAway: (event: ReactMouseEvent) => void;
13
+ /** The touch event to listen to. Pass `false` to disable the touch listener. */
14
+ touchEvent?: ClickAwayTouchEventHandler | false;
15
+ }
16
+ export declare const ClickAwayListener: {
17
+ (props: Props): JSX.Element;
18
+ displayName: string;
19
+ };
20
+ export default ClickAwayListener;
21
+ //# sourceMappingURL=ClickAwayListener.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClickAwayListener.d.ts","sourceRoot":"","sources":["../../../../src/utils/ClickAwayListener/ClickAwayListener.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,IAAI,eAAe,EAC7B,YAAY,EAGb,MAAM,OAAO,CAAA;AAId,KAAK,0BAA0B,GAAG,SAAS,GAAG,aAAa,GAAG,WAAW,CAAA;AACzE,KAAK,0BAA0B,GAAG,cAAc,GAAG,YAAY,CAAA;AAE/D,MAAM,WAAW,KAAK;IACpB,2BAA2B;IAC3B,QAAQ,EAAE,YAAY,CAAA;IACtB,2HAA2H;IAC3H,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,gFAAgF;IAChF,UAAU,CAAC,EAAE,0BAA0B,GAAG,KAAK,CAAA;IAC/C,0DAA0D;IAC1D,WAAW,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAA;IAC7C,gFAAgF;IAChF,UAAU,CAAC,EAAE,0BAA0B,GAAG,KAAK,CAAA;CAChD;AAsCD,eAAO,MAAM,iBAAiB;YAAW,KAAK;;CA6H7C,CAAA;AAID,eAAe,iBAAiB,CAAA"}
@@ -0,0 +1,111 @@
1
+ import React, { useCallback, useEffect, useRef } from 'react';
2
+ import { toReactEvent } from '@toptal/picasso-shared';
3
+ const mapEventPropToEvent = (eventProp) => eventProp.substring(2).toLowerCase();
4
+ const clickedRootScrollbar = (event, doc) => {
5
+ const { clientX, clientY } = event;
6
+ return (doc.documentElement.clientWidth < clientX ||
7
+ doc.documentElement.clientHeight < clientY);
8
+ };
9
+ const isEventInsideNode = (event, node, doc) => {
10
+ if (event.composedPath) {
11
+ return event.composedPath().indexOf(node) > -1;
12
+ }
13
+ return (!doc.documentElement.contains(event.target) ||
14
+ node.contains(event.target));
15
+ };
16
+ const setRef = (ref, value) => {
17
+ if (typeof ref === 'function') {
18
+ ref(value);
19
+ }
20
+ else if (ref) {
21
+ ;
22
+ ref.current = value;
23
+ }
24
+ };
25
+ export const ClickAwayListener = (props) => {
26
+ const { children, disableReactTree = false, mouseEvent = 'onClick', onClickAway, touchEvent = 'onTouchEnd', } = props;
27
+ const movedRef = useRef(false);
28
+ const nodeRef = useRef(null);
29
+ const activatedRef = useRef(false);
30
+ const syntheticEventRef = useRef(false);
31
+ useEffect(() => {
32
+ // Avoid activating synchronously so the interaction that mounts the
33
+ // component does not immediately count as a click-away.
34
+ const timeout = setTimeout(() => {
35
+ activatedRef.current = true;
36
+ }, 0);
37
+ return () => {
38
+ activatedRef.current = false;
39
+ clearTimeout(timeout);
40
+ };
41
+ }, []);
42
+ const childRef = children.ref;
43
+ const handleRef = useCallback((instance) => {
44
+ nodeRef.current = instance;
45
+ setRef(childRef, instance);
46
+ }, [childRef]);
47
+ const handleClickAway = useCallback((event) => {
48
+ var _a;
49
+ const insideReactTree = syntheticEventRef.current;
50
+ syntheticEventRef.current = false;
51
+ const node = nodeRef.current;
52
+ const doc = (_a = node === null || node === void 0 ? void 0 : node.ownerDocument) !== null && _a !== void 0 ? _a : document;
53
+ if (!activatedRef.current || !node || clickedRootScrollbar(event, doc)) {
54
+ return;
55
+ }
56
+ if (movedRef.current) {
57
+ movedRef.current = false;
58
+ return;
59
+ }
60
+ const insideDOM = isEventInsideNode(event, node, doc);
61
+ if (!insideDOM && (disableReactTree || !insideReactTree)) {
62
+ onClickAway(toReactEvent(event));
63
+ }
64
+ }, [disableReactTree, onClickAway]);
65
+ const createHandleSynthetic = (handlerName) => (event) => {
66
+ var _a;
67
+ syntheticEventRef.current = true;
68
+ const childrenPropsHandlers = children.props;
69
+ (_a = childrenPropsHandlers[handlerName]) === null || _a === void 0 ? void 0 : _a.call(childrenPropsHandlers, event);
70
+ };
71
+ const childrenProps = { ref: handleRef };
72
+ if (touchEvent !== false) {
73
+ childrenProps[touchEvent] = createHandleSynthetic(touchEvent);
74
+ }
75
+ if (mouseEvent !== false) {
76
+ childrenProps[mouseEvent] = createHandleSynthetic(mouseEvent);
77
+ }
78
+ useEffect(() => {
79
+ var _a, _b;
80
+ if (touchEvent === false) {
81
+ return undefined;
82
+ }
83
+ const mappedTouchEvent = mapEventPropToEvent(touchEvent);
84
+ const doc = (_b = (_a = nodeRef.current) === null || _a === void 0 ? void 0 : _a.ownerDocument) !== null && _b !== void 0 ? _b : document;
85
+ const handleTouchMove = () => {
86
+ movedRef.current = true;
87
+ };
88
+ doc.addEventListener(mappedTouchEvent, handleClickAway);
89
+ doc.addEventListener('touchmove', handleTouchMove);
90
+ return () => {
91
+ doc.removeEventListener(mappedTouchEvent, handleClickAway);
92
+ doc.removeEventListener('touchmove', handleTouchMove);
93
+ };
94
+ }, [handleClickAway, touchEvent]);
95
+ useEffect(() => {
96
+ var _a, _b;
97
+ if (mouseEvent === false) {
98
+ return undefined;
99
+ }
100
+ const mappedMouseEvent = mapEventPropToEvent(mouseEvent);
101
+ const doc = (_b = (_a = nodeRef.current) === null || _a === void 0 ? void 0 : _a.ownerDocument) !== null && _b !== void 0 ? _b : document;
102
+ doc.addEventListener(mappedMouseEvent, handleClickAway);
103
+ return () => {
104
+ doc.removeEventListener(mappedMouseEvent, handleClickAway);
105
+ };
106
+ }, [handleClickAway, mouseEvent]);
107
+ return React.createElement(React.Fragment, null, React.cloneElement(children, childrenProps));
108
+ };
109
+ ClickAwayListener.displayName = 'ClickAwayListener';
110
+ export default ClickAwayListener;
111
+ //# sourceMappingURL=ClickAwayListener.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClickAwayListener.js","sourceRoot":"","sources":["../../../../src/utils/ClickAwayListener/ClickAwayListener.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { Props } from './ClickAwayListener';
2
+ export { default } from './ClickAwayListener';
3
+ export { ClickAwayListener } from './ClickAwayListener';
4
+ export type ClickAwayListenerProps = Props;
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/ClickAwayListener/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAEhD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,MAAM,MAAM,sBAAsB,GAAG,KAAK,CAAA"}
@@ -0,0 +1,3 @@
1
+ export { default } from './ClickAwayListener';
2
+ export { ClickAwayListener } from './ClickAwayListener';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/utils/ClickAwayListener/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"Rotate180.d.ts","sourceRoot":"","sources":["../../../../../src/utils/Transitions/Rotate180/Rotate180.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,SAAS,EAAE,MAAM,OAAO,CAAA;AAGpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAMvD,MAAM,WAAW,KAAM,SAAQ,SAAS;IACtC,qCAAqC;IACrC,EAAE,EAAE,OAAO,CAAA;IACX,oCAAoC;IACpC,QAAQ,EAAE,SAAS,CAAA;CACpB;AAMD,eAAO,MAAM,SAAS;YAAW,KAAK;;CAmBrC,CAAA;AAID,eAAe,SAAS,CAAA"}
1
+ {"version":3,"file":"Rotate180.d.ts","sourceRoot":"","sources":["../../../../../src/utils/Transitions/Rotate180/Rotate180.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,SAAS,EAAE,MAAM,OAAO,CAAA;AAGpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAKvD,MAAM,WAAW,KAAM,SAAQ,SAAS;IACtC,qCAAqC;IACrC,EAAE,EAAE,OAAO,CAAA;IACX,oCAAoC;IACpC,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,eAAO,MAAM,SAAS;YAAW,KAAK;;CAgBrC,CAAA;AAID,eAAe,SAAS,CAAA"}
@@ -11,17 +11,11 @@ var __rest = (this && this.__rest) || function (s, e) {
11
11
  };
12
12
  import React from 'react';
13
13
  import cx from 'classnames';
14
- import { makeStyles } from '@material-ui/core/styles';
15
- import styles from './styles';
16
- const useStyles = makeStyles(styles, {
17
- name: 'Rotate180',
18
- });
14
+ import { twMerge } from '@toptal/picasso-tailwind-merge';
15
+ import { createRotate180ClassNames } from './styles';
19
16
  export const Rotate180 = (props) => {
20
17
  const { children, style, className, on } = props, rest = __rest(props, ["children", "style", "className", "on"]);
21
- const classes = useStyles();
22
- const childProps = Object.assign({ className: cx(className, classes.transition, {
23
- [classes.rotate180]: on,
24
- }), style }, rest);
18
+ const childProps = Object.assign({ className: twMerge(cx(createRotate180ClassNames(on)), className), style }, rest);
25
19
  return (React.createElement(React.Fragment, null, React.Children.map(children, child => React.cloneElement(child, childProps))));
26
20
  };
27
21
  Rotate180.displayName = 'Rotate180';
@@ -1 +1 @@
1
- {"version":3,"file":"Rotate180.js","sourceRoot":"","sources":["../../../../../src/utils/Transitions/Rotate180/Rotate180.tsx"],"names":[],"mappings":";;;;;;;;;;;AACA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,MAAM,YAAY,CAAA;AAG3B,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAErD,OAAO,MAAM,MAAM,UAAU,CAAA;AAS7B,MAAM,SAAS,GAAG,UAAU,CAAQ,MAAM,EAAE;IAC1C,IAAI,EAAE,WAAW;CAClB,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAY,EAAE,EAAE;IACxC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,KAAc,KAAK,EAAd,IAAI,UAAK,KAAK,EAAnD,wCAA2C,CAAQ,CAAA;IACzD,MAAM,OAAO,GAAG,SAAS,EAAE,CAAA;IAE3B,MAAM,UAAU,mBACd,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC,UAAU,EAAE;YAC3C,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,EAAE;SACxB,CAAC,EACF,KAAK,IACF,IAAI,CACR,CAAA;IAED,OAAO,CACL,0CACG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CACpC,KAAK,CAAC,YAAY,CAAC,KAAqB,EAAE,UAAU,CAAC,CACtD,CACA,CACJ,CAAA;AACH,CAAC,CAAA;AAED,SAAS,CAAC,WAAW,GAAG,WAAW,CAAA;AAEnC,eAAe,SAAS,CAAA"}
1
+ {"version":3,"file":"Rotate180.js","sourceRoot":"","sources":["../../../../../src/utils/Transitions/Rotate180/Rotate180.tsx"],"names":[],"mappings":";;;;;;;;;;;AACA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,MAAM,YAAY,CAAA;AAE3B,OAAO,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AAExD,OAAO,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAA;AASpD,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAY,EAAE,EAAE;IACxC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,KAAc,KAAK,EAAd,IAAI,UAAK,KAAK,EAAnD,wCAA2C,CAAQ,CAAA;IAEzD,MAAM,UAAU,mBACd,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC,yBAAyB,CAAC,EAAE,CAAC,CAAC,EAAE,SAAS,CAAC,EAChE,KAAK,IACF,IAAI,CACR,CAAA;IAED,OAAO,CACL,0CACG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CACpC,KAAK,CAAC,YAAY,CAAC,KAAqB,EAAE,UAAU,CAAC,CACtD,CACA,CACJ,CAAA;AACH,CAAC,CAAA;AAED,SAAS,CAAC,WAAW,GAAG,WAAW,CAAA;AAEnC,eAAe,SAAS,CAAA"}
@@ -1,3 +1,2 @@
1
- declare const _default: () => import("@material-ui/styles").StyleRules<{}, "transition" | "rotate180">;
2
- export default _default;
1
+ export declare const createRotate180ClassNames: (on: boolean) => string[];
3
2
  //# sourceMappingURL=styles.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../../../src/utils/Transitions/Rotate180/styles.ts"],"names":[],"mappings":";AAEA,wBAQI"}
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../../../src/utils/Transitions/Rotate180/styles.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,yBAAyB,OAAQ,OAAO,KAAG,MAAM,EAK7D,CAAA"}
@@ -1,10 +1,7 @@
1
- import { createStyles } from '@material-ui/core/styles';
2
- export default () => createStyles({
3
- transition: {
4
- transition: 'transform 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms',
5
- },
6
- rotate180: {
7
- transform: 'rotate(180deg)',
8
- },
9
- });
1
+ export const createRotate180ClassNames = (on) => [
2
+ 'transition-transform',
3
+ 'duration-150',
4
+ 'ease-in-out',
5
+ ...(on ? ['rotate-180'] : []),
6
+ ];
10
7
  //# sourceMappingURL=styles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"styles.js","sourceRoot":"","sources":["../../../../../src/utils/Transitions/Rotate180/styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEvD,eAAe,GAAG,EAAE,CAClB,YAAY,CAAC;IACX,UAAU,EAAE;QACV,UAAU,EAAE,kDAAkD;KAC/D;IACD,SAAS,EAAE;QACT,SAAS,EAAE,gBAAgB;KAC5B;CACF,CAAC,CAAA"}
1
+ {"version":3,"file":"styles.js","sourceRoot":"","sources":["../../../../../src/utils/Transitions/Rotate180/styles.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,EAAW,EAAY,EAAE,CAAC;IAClE,sBAAsB;IACtB,cAAc;IACd,aAAa;IACb,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;CAC9B,CAAA"}
@@ -1,2 +1,2 @@
1
- export { default as capitalize } from '@material-ui/core/utils/capitalize';
1
+ export declare const capitalize: (string: string) => string;
2
2
  //# sourceMappingURL=capitalize.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"capitalize.d.ts","sourceRoot":"","sources":["../../../src/utils/capitalize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,oCAAoC,CAAA"}
1
+ {"version":3,"file":"capitalize.d.ts","sourceRoot":"","sources":["../../../src/utils/capitalize.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,UAAU,WAAY,MAAM,KAAG,MAM3C,CAAA"}
@@ -1,2 +1,9 @@
1
- export { default as capitalize } from '@material-ui/core/utils/capitalize';
1
+ // Not equivalent to `text-transform: capitalize` — only the first letter of
2
+ // the whole string is uppercased, not the first letter of each word.
3
+ export const capitalize = (string) => {
4
+ if (typeof string !== 'string') {
5
+ throw new Error('Picasso: capitalize(string) expects a string argument.');
6
+ }
7
+ return string.charAt(0).toUpperCase() + string.slice(1);
8
+ };
2
9
  //# sourceMappingURL=capitalize.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"capitalize.js","sourceRoot":"","sources":["../../../src/utils/capitalize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,oCAAoC,CAAA"}
1
+ {"version":3,"file":"capitalize.js","sourceRoot":"","sources":["../../../src/utils/capitalize.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,qEAAqE;AACrE,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,MAAc,EAAU,EAAE;IACnD,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAA;IAC3E,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AACzD,CAAC,CAAA"}
@@ -8,7 +8,8 @@ export { colorUtils };
8
8
  export { breakpointsList as breakpoints, screens, isScreenSize, useBreakpoint, useScreens, shadows, colors as palette, gradients, generateRandomString, generateRandomStringOrGetEmptyInTest, sizes, } from '@toptal/picasso-provider';
9
9
  export type { BreakpointKeys } from '@toptal/picasso-provider';
10
10
  export { useIsomorphicLayoutEffect, isBrowser, type OverridableComponent, } from '@toptal/picasso-shared';
11
- export { default as ClickAwayListener } from '@material-ui/core/ClickAwayListener';
11
+ export { default as ClickAwayListener } from './ClickAwayListener';
12
+ export type { ClickAwayListenerProps } from './ClickAwayListener';
12
13
  export { capitalize } from './capitalize';
13
14
  export { default as disableUnsupportedProps } from './disable-unsupported-props';
14
15
  export { type FeatureOptions } from './disable-unsupported-props';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"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"}
@@ -8,7 +8,7 @@ const colorUtils = {
8
8
  export { colorUtils };
9
9
  export { breakpointsList as breakpoints, screens, isScreenSize, useBreakpoint, useScreens, shadows, colors as palette, gradients, generateRandomString, generateRandomStringOrGetEmptyInTest, sizes, } from '@toptal/picasso-provider';
10
10
  export { useIsomorphicLayoutEffect, isBrowser, } from '@toptal/picasso-shared';
11
- export { default as ClickAwayListener } from '@material-ui/core/ClickAwayListener';
11
+ export { default as ClickAwayListener } from './ClickAwayListener';
12
12
  export { capitalize } from './capitalize';
13
13
  export { default as disableUnsupportedProps } from './disable-unsupported-props';
14
14
  export { forwardRef, documentable } from './forward-ref';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toptal/picasso-utils",
3
- "version": "4.0.1",
3
+ "version": "4.0.2-alpha-pf-fix-alpha-release-4de9263c3.0",
4
4
  "description": "Toptal UI components library - Utils",
5
5
  "homepage": "https://github.com/toptal/picasso/tree/master/packages/picasso#readme",
6
6
  "bugs": {
@@ -24,18 +24,18 @@
24
24
  "dependencies": {
25
25
  "ap-style-title-case": "^1.1.2",
26
26
  "classnames": "^2.5.1",
27
- "@toptal/picasso-shared": "16.0.0"
27
+ "@toptal/picasso-shared": "16.0.1-alpha-pf-fix-alpha-release-4de9263c3.0",
28
+ "@toptal/picasso-tailwind-merge": "2.0.6-alpha-pf-fix-alpha-release-4de9263c3.0"
28
29
  },
29
30
  "devDependencies": {
30
31
  "styled-components": "^6.1.1",
31
- "@toptal/picasso-provider": "6.0.0",
32
- "@toptal/picasso-test-utils": "2.0.1"
32
+ "@toptal/picasso-test-utils": "2.0.2-alpha-pf-fix-alpha-release-4de9263c3.0",
33
+ "@toptal/picasso-provider": "6.0.1-alpha-pf-fix-alpha-release-4de9263c3.0"
33
34
  },
34
35
  "peerDependencies": {
35
- "@material-ui/core": "4.12.4",
36
- "@toptal/picasso-provider": "*",
36
+ "@toptal/picasso-provider": "6.0.1-alpha-pf-fix-alpha-release-4de9263c3.0",
37
37
  "notistack": "1.0.10",
38
- "react": ">=16.12.0 < 19.0.0"
38
+ "react": ">=16.12.0"
39
39
  },
40
40
  "publishConfig": {
41
41
  "access": "public"
@@ -0,0 +1,191 @@
1
+ import type {
2
+ MouseEvent as ReactMouseEvent,
3
+ ReactElement,
4
+ Ref,
5
+ SyntheticEvent,
6
+ } from 'react'
7
+ import React, { useCallback, useEffect, useRef } from 'react'
8
+ import { toReactEvent } from '@toptal/picasso-shared'
9
+
10
+ type ClickAwayMouseEventHandler = 'onClick' | 'onMouseDown' | 'onMouseUp'
11
+ type ClickAwayTouchEventHandler = 'onTouchStart' | 'onTouchEnd'
12
+
13
+ export interface Props {
14
+ /** The wrapped element. */
15
+ children: ReactElement
16
+ /** If `true`, the React tree is ignored and only the DOM tree is considered. Changes how portaled elements are handled. */
17
+ disableReactTree?: boolean
18
+ /** The mouse event to listen to. Pass `false` to disable the mouse listener. */
19
+ mouseEvent?: ClickAwayMouseEventHandler | false
20
+ /** Callback fired when a click-away event is detected. */
21
+ onClickAway: (event: ReactMouseEvent) => void
22
+ /** The touch event to listen to. Pass `false` to disable the touch listener. */
23
+ touchEvent?: ClickAwayTouchEventHandler | false
24
+ }
25
+
26
+ const mapEventPropToEvent = (
27
+ eventProp: ClickAwayMouseEventHandler | ClickAwayTouchEventHandler
28
+ ): string => eventProp.substring(2).toLowerCase()
29
+
30
+ const clickedRootScrollbar = (event: Event, doc: Document): boolean => {
31
+ const { clientX, clientY } = event as MouseEvent
32
+
33
+ return (
34
+ doc.documentElement.clientWidth < clientX ||
35
+ doc.documentElement.clientHeight < clientY
36
+ )
37
+ }
38
+
39
+ const isEventInsideNode = (
40
+ event: Event,
41
+ node: Element,
42
+ doc: Document
43
+ ): boolean => {
44
+ if (event.composedPath) {
45
+ return event.composedPath().indexOf(node) > -1
46
+ }
47
+
48
+ return (
49
+ !doc.documentElement.contains(event.target as Node) ||
50
+ node.contains(event.target as Node)
51
+ )
52
+ }
53
+
54
+ const setRef = <T,>(ref: Ref<T> | undefined, value: T | null): void => {
55
+ if (typeof ref === 'function') {
56
+ ref(value)
57
+ } else if (ref) {
58
+ ;(ref as React.MutableRefObject<T | null>).current = value
59
+ }
60
+ }
61
+
62
+ export const ClickAwayListener = (props: Props) => {
63
+ const {
64
+ children,
65
+ disableReactTree = false,
66
+ mouseEvent = 'onClick',
67
+ onClickAway,
68
+ touchEvent = 'onTouchEnd',
69
+ } = props
70
+
71
+ const movedRef = useRef(false)
72
+ const nodeRef = useRef<Element | null>(null)
73
+ const activatedRef = useRef(false)
74
+ const syntheticEventRef = useRef(false)
75
+
76
+ useEffect(() => {
77
+ // Avoid activating synchronously so the interaction that mounts the
78
+ // component does not immediately count as a click-away.
79
+ const timeout = setTimeout(() => {
80
+ activatedRef.current = true
81
+ }, 0)
82
+
83
+ return () => {
84
+ activatedRef.current = false
85
+ clearTimeout(timeout)
86
+ }
87
+ }, [])
88
+
89
+ const childRef = (children as { ref?: Ref<Element> }).ref
90
+
91
+ const handleRef = useCallback(
92
+ (instance: Element | null) => {
93
+ nodeRef.current = instance
94
+ setRef(childRef, instance)
95
+ },
96
+ [childRef]
97
+ )
98
+
99
+ const handleClickAway = useCallback(
100
+ (event: Event) => {
101
+ const insideReactTree = syntheticEventRef.current
102
+
103
+ syntheticEventRef.current = false
104
+
105
+ const node = nodeRef.current
106
+ const doc = node?.ownerDocument ?? document
107
+
108
+ if (!activatedRef.current || !node || clickedRootScrollbar(event, doc)) {
109
+ return
110
+ }
111
+
112
+ if (movedRef.current) {
113
+ movedRef.current = false
114
+
115
+ return
116
+ }
117
+
118
+ const insideDOM = isEventInsideNode(event, node, doc)
119
+
120
+ if (!insideDOM && (disableReactTree || !insideReactTree)) {
121
+ onClickAway(toReactEvent<ReactMouseEvent>(event))
122
+ }
123
+ },
124
+ [disableReactTree, onClickAway]
125
+ )
126
+
127
+ const createHandleSynthetic =
128
+ (handlerName: ClickAwayMouseEventHandler | ClickAwayTouchEventHandler) =>
129
+ (event: SyntheticEvent) => {
130
+ syntheticEventRef.current = true
131
+
132
+ const childrenPropsHandlers = children.props as Record<
133
+ string,
134
+ ((event: SyntheticEvent) => void) | undefined
135
+ >
136
+
137
+ childrenPropsHandlers[handlerName]?.(event)
138
+ }
139
+
140
+ const childrenProps: Record<string, unknown> = { ref: handleRef }
141
+
142
+ if (touchEvent !== false) {
143
+ childrenProps[touchEvent] = createHandleSynthetic(touchEvent)
144
+ }
145
+
146
+ if (mouseEvent !== false) {
147
+ childrenProps[mouseEvent] = createHandleSynthetic(mouseEvent)
148
+ }
149
+
150
+ useEffect(() => {
151
+ if (touchEvent === false) {
152
+ return undefined
153
+ }
154
+
155
+ const mappedTouchEvent = mapEventPropToEvent(touchEvent)
156
+ const doc = nodeRef.current?.ownerDocument ?? document
157
+
158
+ const handleTouchMove = () => {
159
+ movedRef.current = true
160
+ }
161
+
162
+ doc.addEventListener(mappedTouchEvent, handleClickAway)
163
+ doc.addEventListener('touchmove', handleTouchMove)
164
+
165
+ return () => {
166
+ doc.removeEventListener(mappedTouchEvent, handleClickAway)
167
+ doc.removeEventListener('touchmove', handleTouchMove)
168
+ }
169
+ }, [handleClickAway, touchEvent])
170
+
171
+ useEffect(() => {
172
+ if (mouseEvent === false) {
173
+ return undefined
174
+ }
175
+
176
+ const mappedMouseEvent = mapEventPropToEvent(mouseEvent)
177
+ const doc = nodeRef.current?.ownerDocument ?? document
178
+
179
+ doc.addEventListener(mappedMouseEvent, handleClickAway)
180
+
181
+ return () => {
182
+ doc.removeEventListener(mappedMouseEvent, handleClickAway)
183
+ }
184
+ }, [handleClickAway, mouseEvent])
185
+
186
+ return <>{React.cloneElement(children, childrenProps)}</>
187
+ }
188
+
189
+ ClickAwayListener.displayName = 'ClickAwayListener'
190
+
191
+ export default ClickAwayListener
@@ -0,0 +1,5 @@
1
+ import type { Props } from './ClickAwayListener'
2
+
3
+ export { default } from './ClickAwayListener'
4
+ export { ClickAwayListener } from './ClickAwayListener'
5
+ export type ClickAwayListenerProps = Props
@@ -0,0 +1,99 @@
1
+ import React from 'react'
2
+ import { render, fireEvent, act } from '@toptal/picasso-test-utils'
3
+
4
+ import { ClickAwayListener } from './ClickAwayListener'
5
+
6
+ const renderClickAwayListener = (
7
+ props: Partial<React.ComponentProps<typeof ClickAwayListener>> = {}
8
+ ) => {
9
+ const onClickAway = props.onClickAway ?? jest.fn()
10
+
11
+ const api = render(
12
+ <div>
13
+ <ClickAwayListener onClickAway={onClickAway} {...props}>
14
+ <button type='button'>inside</button>
15
+ </ClickAwayListener>
16
+ <span data-testid='outside'>outside</span>
17
+ </div>
18
+ )
19
+
20
+ // Listeners are activated asynchronously to ignore the mounting interaction.
21
+ act(() => {
22
+ jest.advanceTimersByTime(0)
23
+ })
24
+
25
+ return { ...api, onClickAway }
26
+ }
27
+
28
+ describe('ClickAwayListener', () => {
29
+ beforeEach(() => {
30
+ jest.useFakeTimers()
31
+ })
32
+
33
+ afterEach(() => {
34
+ jest.useRealTimers()
35
+ })
36
+
37
+ it('fires onClickAway when clicking outside the wrapped element', () => {
38
+ const { getByTestId, onClickAway } = renderClickAwayListener()
39
+
40
+ fireEvent.click(getByTestId('outside'))
41
+
42
+ expect(onClickAway).toHaveBeenCalledTimes(1)
43
+ })
44
+
45
+ it('does not fire onClickAway when clicking inside the wrapped element', () => {
46
+ const { getByText, onClickAway } = renderClickAwayListener()
47
+
48
+ fireEvent.click(getByText('inside'))
49
+
50
+ expect(onClickAway).not.toHaveBeenCalled()
51
+ })
52
+
53
+ it('does not fire before the listener is activated', () => {
54
+ const onClickAway = jest.fn()
55
+
56
+ const { getByTestId } = render(
57
+ <div>
58
+ <ClickAwayListener onClickAway={onClickAway}>
59
+ <button type='button'>inside</button>
60
+ </ClickAwayListener>
61
+ <span data-testid='outside'>outside</span>
62
+ </div>
63
+ )
64
+
65
+ fireEvent.click(getByTestId('outside'))
66
+
67
+ expect(onClickAway).not.toHaveBeenCalled()
68
+ })
69
+
70
+ it('respects a disabled mouse listener', () => {
71
+ const { getByTestId, onClickAway } = renderClickAwayListener({
72
+ mouseEvent: false,
73
+ })
74
+
75
+ fireEvent.click(getByTestId('outside'))
76
+
77
+ expect(onClickAway).not.toHaveBeenCalled()
78
+ })
79
+
80
+ it('preserves the child existing event handler', () => {
81
+ const onClick = jest.fn()
82
+
83
+ const { getByText } = render(
84
+ <ClickAwayListener onClickAway={jest.fn()}>
85
+ <button type='button' onClick={onClick}>
86
+ inside
87
+ </button>
88
+ </ClickAwayListener>
89
+ )
90
+
91
+ act(() => {
92
+ jest.advanceTimersByTime(0)
93
+ })
94
+
95
+ fireEvent.click(getByText('inside'))
96
+
97
+ expect(onClick).toHaveBeenCalledTimes(1)
98
+ })
99
+ })
@@ -3,6 +3,7 @@
3
3
  exports[`Modal useModal opens and closes modal 1`] = `
4
4
  <body>
5
5
  <div
6
+ data-base-ui-inert=""
6
7
  id="modal-root"
7
8
  />
8
9
  <div>
@@ -11,8 +12,8 @@ exports[`Modal useModal opens and closes modal 1`] = `
11
12
  >
12
13
  <button
13
14
  aria-disabled="false"
14
- aria-hidden="true"
15
15
  class="base-Button text-lg inline-flex items-center justify-center select-none appearance-none m-0 relative normal-case align-middle transition-colors duration-350 ease-out shrink-0 outline-hidden [[data-component-type="button"]+&]:ml cursor-pointer no-underline hover:no-underline rounded-sm shadow-none focus-visible:shadow-[0_0_0_3px_rgba(32,78,207,0.48)] focus-within:shadow-[0_0_0_3px_rgba(32,78,207,0.48)] border-none text-white visited:text-white hover:bg-[#4269D6] active:bg-[#1A41AB] bg-blue min-w h-8 py-0 px-4"
16
+ data-base-ui-inert=""
16
17
  data-component-type="button"
17
18
  role="button"
18
19
  tabindex="0"
@@ -25,47 +26,89 @@ exports[`Modal useModal opens and closes modal 1`] = `
25
26
  </span>
26
27
  </button>
27
28
  <div
28
- class="base-Modal fixed z-modal inset-0 flex flex-col text-lg leading-[normal] justify-center items-center"
29
- role="presentation"
29
+ data-base-ui-portal=""
30
+ id=":r2:"
30
31
  >
31
32
  <div
32
- aria-hidden="true"
33
- class="opacity-0 transition-opacity fixed -z inset-0 bg-black -webkit-tap-highlight-color bg-black/50"
34
- style="transition-duration: 300ms; opacity: 1;"
33
+ class="fixed z-modal inset-0 bg-black/50 transition-opacity data-starting-style:opacity data-ending-style:opacity"
34
+ data-base-ui-inert=""
35
+ data-open=""
36
+ data-starting-style=""
37
+ role="presentation"
38
+ style="user-select: none; transition-duration: 300ms;"
35
39
  />
36
- <div
37
- data-testid="sentinelStart"
40
+ <span
41
+ data-base-ui-focus-guard=""
42
+ data-base-ui-inert=""
43
+ data-type="inside"
44
+ role="button"
45
+ style="clip-path: inset(50%); overflow: hidden; white-space: nowrap; border: 0px; padding: 0px; width: 1px; height: 1px; margin: -1px; position: fixed; top: 0px; left: 0px;"
38
46
  tabindex="0"
39
47
  />
40
48
  <div
41
- class="bg-white shadow-2 duration-300 delay-0 opacity-0 transition-opacity outline-hidden overflow-y flex flex-col m-4 sm:h-auto sm:m-8 max-w-[calc(100%_ sm:max-w-[calc(100%_ rounded-md w-[40.625rem] relative max-h-[calc(100%_ sm:max-h-[calc(100%_"
49
+ class="fixed z-modal inset-0 flex flex-col text-lg leading-[normal] justify-center items-center transition-opacity data-starting-style:opacity data-ending-style:opacity"
50
+ data-base-ui-focusable=""
51
+ data-open=""
52
+ data-starting-style=""
53
+ id=":r0:"
42
54
  role="dialog"
43
- style="transition-duration: 300ms; opacity: 1;"
55
+ style="--nested-dialogs: 0; transition-duration: 300ms;"
44
56
  tabindex="-1"
45
57
  >
46
- <p>
47
- Modal content
48
- </p>
49
- <button
50
- aria-disabled="false"
51
- class="base-Button text-lg inline-flex items-center justify-center select-none appearance-none m-0 relative normal-case align-middle transition-colors duration-350 ease-out shrink-0 outline-hidden [[data-component-type="button"]+&]:ml cursor-pointer no-underline hover:no-underline rounded-sm shadow-none focus-visible:shadow-[0_0_0_3px_rgba(32,78,207,0.48)] focus-within:shadow-[0_0_0_3px_rgba(32,78,207,0.48)] border-none text-white visited:text-white hover:bg-[#4269D6] active:bg-[#1A41AB] bg-blue min-w h-8 py-0 px-4"
52
- data-component-type="button"
53
- role="button"
54
- tabindex="0"
55
- type="button"
58
+ <div
59
+ class="bg-white shadow-2 transition-shadow duration-300 delay-0 outline-hidden overflow-y flex flex-col m-4 sm:h-auto sm:m-8 max-w-[calc(100%_ sm:max-w-[calc(100%_ rounded-md w-[40.625rem] relative max-h-[calc(100%_ sm:max-h-[calc(100%_"
60
+ role="dialog"
61
+ tabindex="-1"
56
62
  >
57
- <span
58
- class="items-center inline-flex font-semibold whitespace-nowrap text-button"
63
+ <p>
64
+ Modal content
65
+ </p>
66
+ <button
67
+ aria-disabled="false"
68
+ class="base-Button text-lg inline-flex items-center justify-center select-none appearance-none m-0 relative normal-case align-middle transition-colors duration-350 ease-out shrink-0 outline-hidden [[data-component-type="button"]+&]:ml cursor-pointer no-underline hover:no-underline rounded-sm shadow-none focus-visible:shadow-[0_0_0_3px_rgba(32,78,207,0.48)] focus-within:shadow-[0_0_0_3px_rgba(32,78,207,0.48)] border-none text-white visited:text-white hover:bg-[#4269D6] active:bg-[#1A41AB] bg-blue min-w h-8 py-0 px-4"
69
+ data-component-type="button"
70
+ role="button"
71
+ tabindex="0"
72
+ type="button"
59
73
  >
60
- Hide
61
- </span>
62
- </button>
74
+ <span
75
+ class="items-center inline-flex font-semibold whitespace-nowrap text-button"
76
+ >
77
+ Hide
78
+ </span>
79
+ </button>
80
+ </div>
63
81
  </div>
64
- <div
65
- data-testid="sentinelEnd"
82
+ <span
83
+ data-base-ui-focus-guard=""
84
+ data-base-ui-inert=""
85
+ data-type="inside"
86
+ role="button"
87
+ style="clip-path: inset(50%); overflow: hidden; white-space: nowrap; border: 0px; padding: 0px; width: 1px; height: 1px; margin: -1px; position: fixed; top: 0px; left: 0px;"
66
88
  tabindex="0"
67
89
  />
68
90
  </div>
91
+ <span
92
+ data-base-ui-focus-guard=""
93
+ data-base-ui-inert=""
94
+ data-type="outside"
95
+ role="button"
96
+ style="clip-path: inset(50%); overflow: hidden; white-space: nowrap; border: 0px; padding: 0px; width: 1px; height: 1px; margin: -1px; position: fixed; top: 0px; left: 0px;"
97
+ tabindex="0"
98
+ />
99
+ <span
100
+ aria-owns=":r2:"
101
+ data-base-ui-inert=""
102
+ style="clip-path: inset(50%); position: fixed; top: 0px; left: 0px;"
103
+ />
104
+ <span
105
+ data-base-ui-focus-guard=""
106
+ data-base-ui-inert=""
107
+ data-type="outside"
108
+ role="button"
109
+ style="clip-path: inset(50%); overflow: hidden; white-space: nowrap; border: 0px; padding: 0px; width: 1px; height: 1px; margin: -1px; position: fixed; top: 0px; left: 0px;"
110
+ tabindex="0"
111
+ />
69
112
  </div>
70
113
  </div>
71
114
  </body>
@@ -102,6 +145,7 @@ exports[`Modal useModal opens and closes modal 2`] = `
102
145
  exports[`Modal useModal shows multiple modals at the same time 1`] = `
103
146
  <body>
104
147
  <div
148
+ data-base-ui-inert=""
105
149
  id="modal-root"
106
150
  />
107
151
  <div>
@@ -110,8 +154,8 @@ exports[`Modal useModal shows multiple modals at the same time 1`] = `
110
154
  >
111
155
  <button
112
156
  aria-disabled="false"
113
- aria-hidden="true"
114
157
  class="base-Button text-lg inline-flex items-center justify-center select-none appearance-none m-0 relative normal-case align-middle transition-colors duration-350 ease-out shrink-0 outline-hidden [[data-component-type="button"]+&]:ml cursor-pointer no-underline hover:no-underline rounded-sm shadow-none focus-visible:shadow-[0_0_0_3px_rgba(32,78,207,0.48)] focus-within:shadow-[0_0_0_3px_rgba(32,78,207,0.48)] border-none text-white visited:text-white hover:bg-[#4269D6] active:bg-[#1A41AB] bg-blue min-w h-8 py-0 px-4"
158
+ data-base-ui-inert=""
115
159
  data-component-type="button"
116
160
  role="button"
117
161
  tabindex="0"
@@ -123,10 +167,31 @@ exports[`Modal useModal shows multiple modals at the same time 1`] = `
123
167
  Show first
124
168
  </span>
125
169
  </button>
170
+ <span
171
+ data-base-ui-focus-guard=""
172
+ data-base-ui-inert=""
173
+ data-type="outside"
174
+ role="button"
175
+ style="clip-path: inset(50%); overflow: hidden; white-space: nowrap; border: 0px; padding: 0px; width: 1px; height: 1px; margin: -1px; position: fixed; top: 0px; left: 0px;"
176
+ tabindex="0"
177
+ />
178
+ <span
179
+ aria-owns=":r7:"
180
+ data-base-ui-inert=""
181
+ style="clip-path: inset(50%); position: fixed; top: 0px; left: 0px;"
182
+ />
183
+ <span
184
+ data-base-ui-focus-guard=""
185
+ data-base-ui-inert=""
186
+ data-type="outside"
187
+ role="button"
188
+ style="clip-path: inset(50%); overflow: hidden; white-space: nowrap; border: 0px; padding: 0px; width: 1px; height: 1px; margin: -1px; position: fixed; top: 0px; left: 0px;"
189
+ tabindex="0"
190
+ />
126
191
  <button
127
192
  aria-disabled="false"
128
- aria-hidden="true"
129
193
  class="base-Button text-lg inline-flex items-center justify-center select-none appearance-none m-0 relative normal-case align-middle transition-colors duration-350 ease-out shrink-0 outline-hidden [[data-component-type="button"]+&]:ml cursor-pointer no-underline hover:no-underline rounded-sm shadow-none focus-visible:shadow-[0_0_0_3px_rgba(32,78,207,0.48)] focus-within:shadow-[0_0_0_3px_rgba(32,78,207,0.48)] border-none text-white visited:text-white hover:bg-[#4269D6] active:bg-[#1A41AB] bg-blue min-w h-8 py-0 px-4"
194
+ data-base-ui-inert=""
130
195
  data-component-type="button"
131
196
  role="button"
132
197
  tabindex="0"
@@ -139,62 +204,125 @@ exports[`Modal useModal shows multiple modals at the same time 1`] = `
139
204
  </span>
140
205
  </button>
141
206
  <div
142
- aria-hidden="true"
143
- class="base-Modal fixed z-modal inset-0 flex flex-col text-lg leading-[normal] justify-center items-center"
144
- role="presentation"
207
+ data-base-ui-inert=""
208
+ data-base-ui-portal=""
209
+ id=":r7:"
145
210
  >
146
211
  <div
147
- aria-hidden="true"
148
- class="opacity-0 transition-opacity fixed -z inset-0 bg-black -webkit-tap-highlight-color bg-black/50"
149
- style="transition-duration: 300ms; opacity: 1;"
212
+ class="fixed z-modal inset-0 bg-black/50 transition-opacity data-starting-style:opacity data-ending-style:opacity"
213
+ data-base-ui-inert=""
214
+ data-open=""
215
+ data-starting-style=""
216
+ role="presentation"
217
+ style="user-select: none; transition-duration: 300ms;"
150
218
  />
151
- <div
152
- data-testid="sentinelStart"
219
+ <span
220
+ data-base-ui-focus-guard=""
221
+ data-base-ui-inert=""
222
+ data-type="inside"
223
+ role="button"
224
+ style="clip-path: inset(50%); overflow: hidden; white-space: nowrap; border: 0px; padding: 0px; width: 1px; height: 1px; margin: -1px; position: fixed; top: 0px; left: 0px;"
153
225
  tabindex="0"
154
226
  />
155
227
  <div
156
- class="bg-white shadow-2 duration-300 delay-0 opacity-0 transition-opacity outline-hidden overflow-y flex flex-col m-4 sm:h-auto sm:m-8 max-w-[calc(100%_ sm:max-w-[calc(100%_ rounded-md w-[40.625rem] relative max-h-[calc(100%_ sm:max-h-[calc(100%_"
228
+ class="fixed z-modal inset-0 flex flex-col text-lg leading-[normal] justify-center items-center transition-opacity data-starting-style:opacity data-ending-style:opacity"
229
+ data-base-ui-focusable=""
230
+ data-open=""
231
+ data-starting-style=""
232
+ id=":r3:"
157
233
  role="dialog"
158
- style="transition-duration: 300ms; opacity: 1;"
234
+ style="--nested-dialogs: 0; transition-duration: 300ms;"
159
235
  tabindex="-1"
160
236
  >
161
- <p>
162
- First modal content
163
- </p>
237
+ <div
238
+ class="bg-white shadow-2 transition-shadow duration-300 delay-0 outline-hidden overflow-y flex flex-col m-4 sm:h-auto sm:m-8 max-w-[calc(100%_ sm:max-w-[calc(100%_ rounded-md w-[40.625rem] relative max-h-[calc(100%_ sm:max-h-[calc(100%_"
239
+ role="dialog"
240
+ tabindex="-1"
241
+ >
242
+ <p>
243
+ First modal content
244
+ </p>
245
+ </div>
164
246
  </div>
165
- <div
166
- data-testid="sentinelEnd"
247
+ <span
248
+ data-base-ui-focus-guard=""
249
+ data-base-ui-inert=""
250
+ data-type="inside"
251
+ role="button"
252
+ style="clip-path: inset(50%); overflow: hidden; white-space: nowrap; border: 0px; padding: 0px; width: 1px; height: 1px; margin: -1px; position: fixed; top: 0px; left: 0px;"
167
253
  tabindex="0"
168
254
  />
169
255
  </div>
170
256
  <div
171
- class="base-Modal fixed z-modal inset-0 flex flex-col text-lg leading-[normal] justify-center items-center"
172
- role="presentation"
257
+ data-base-ui-portal=""
258
+ id=":r8:"
173
259
  >
174
260
  <div
175
- aria-hidden="true"
176
- class="opacity-0 transition-opacity fixed -z inset-0 bg-black -webkit-tap-highlight-color bg-black/50"
177
- style="transition-duration: 300ms; opacity: 1;"
261
+ class="fixed z-modal inset-0 bg-black/50 transition-opacity data-starting-style:opacity data-ending-style:opacity"
262
+ data-base-ui-inert=""
263
+ data-open=""
264
+ data-starting-style=""
265
+ role="presentation"
266
+ style="user-select: none; transition-duration: 300ms;"
178
267
  />
179
- <div
180
- data-testid="sentinelStart"
268
+ <span
269
+ data-base-ui-focus-guard=""
270
+ data-base-ui-inert=""
271
+ data-type="inside"
272
+ role="button"
273
+ style="clip-path: inset(50%); overflow: hidden; white-space: nowrap; border: 0px; padding: 0px; width: 1px; height: 1px; margin: -1px; position: fixed; top: 0px; left: 0px;"
181
274
  tabindex="0"
182
275
  />
183
276
  <div
184
- class="bg-white shadow-2 duration-300 delay-0 opacity-0 transition-opacity outline-hidden overflow-y flex flex-col m-4 sm:h-auto sm:m-8 max-w-[calc(100%_ sm:max-w-[calc(100%_ rounded-md w-[40.625rem] relative max-h-[calc(100%_ sm:max-h-[calc(100%_"
277
+ class="fixed z-modal inset-0 flex flex-col text-lg leading-[normal] justify-center items-center transition-opacity data-starting-style:opacity data-ending-style:opacity"
278
+ data-base-ui-focusable=""
279
+ data-open=""
280
+ data-starting-style=""
281
+ id=":r5:"
185
282
  role="dialog"
186
- style="transition-duration: 300ms; opacity: 1;"
283
+ style="--nested-dialogs: 0; transition-duration: 300ms;"
187
284
  tabindex="-1"
188
285
  >
189
- <p>
190
- Second modal content
191
- </p>
286
+ <div
287
+ class="bg-white shadow-2 transition-shadow duration-300 delay-0 outline-hidden overflow-y flex flex-col m-4 sm:h-auto sm:m-8 max-w-[calc(100%_ sm:max-w-[calc(100%_ rounded-md w-[40.625rem] relative max-h-[calc(100%_ sm:max-h-[calc(100%_"
288
+ role="dialog"
289
+ tabindex="-1"
290
+ >
291
+ <p>
292
+ Second modal content
293
+ </p>
294
+ </div>
192
295
  </div>
193
- <div
194
- data-testid="sentinelEnd"
296
+ <span
297
+ data-base-ui-focus-guard=""
298
+ data-base-ui-inert=""
299
+ data-type="inside"
300
+ role="button"
301
+ style="clip-path: inset(50%); overflow: hidden; white-space: nowrap; border: 0px; padding: 0px; width: 1px; height: 1px; margin: -1px; position: fixed; top: 0px; left: 0px;"
195
302
  tabindex="0"
196
303
  />
197
304
  </div>
305
+ <span
306
+ data-base-ui-focus-guard=""
307
+ data-base-ui-inert=""
308
+ data-type="outside"
309
+ role="button"
310
+ style="clip-path: inset(50%); overflow: hidden; white-space: nowrap; border: 0px; padding: 0px; width: 1px; height: 1px; margin: -1px; position: fixed; top: 0px; left: 0px;"
311
+ tabindex="0"
312
+ />
313
+ <span
314
+ aria-owns=":r8:"
315
+ data-base-ui-inert=""
316
+ style="clip-path: inset(50%); position: fixed; top: 0px; left: 0px;"
317
+ />
318
+ <span
319
+ data-base-ui-focus-guard=""
320
+ data-base-ui-inert=""
321
+ data-type="outside"
322
+ role="button"
323
+ style="clip-path: inset(50%); overflow: hidden; white-space: nowrap; border: 0px; padding: 0px; width: 1px; height: 1px; margin: -1px; position: fixed; top: 0px; left: 0px;"
324
+ tabindex="0"
325
+ />
198
326
  </div>
199
327
  </div>
200
328
  </body>
@@ -1,9 +1,5 @@
1
1
  import React from 'react'
2
- import {
3
- render,
4
- fireEvent,
5
- waitForElementToBeRemoved,
6
- } from '@toptal/picasso-test-utils'
2
+ import { render, fireEvent, waitFor } from '@toptal/picasso-test-utils'
7
3
  import { Button } from '@toptal/picasso-button'
8
4
  import { Modal } from '@toptal/picasso-modal'
9
5
 
@@ -47,7 +43,7 @@ describe('Modal', () => {
47
43
  const hideModalButton = getByText('Hide')
48
44
 
49
45
  fireEvent.click(hideModalButton)
50
- await waitForElementToBeRemoved(() => getByText('Hide'))
46
+ await waitFor(() => expect(queryByText('Hide')).toBeFalsy())
51
47
 
52
48
  expect(queryByText('Modal content')).toBeFalsy()
53
49
  expect(baseElement).toMatchSnapshot()
@@ -2,10 +2,9 @@ import type { ReactElement, ReactNode } from 'react'
2
2
  import React from 'react'
3
3
  import cx from 'classnames'
4
4
  import type { BaseProps } from '@toptal/picasso-shared'
5
- import type { Theme } from '@material-ui/core/styles'
6
- import { makeStyles } from '@material-ui/core/styles'
5
+ import { twMerge } from '@toptal/picasso-tailwind-merge'
7
6
 
8
- import styles from './styles'
7
+ import { createRotate180ClassNames } from './styles'
9
8
 
10
9
  export interface Props extends BaseProps {
11
10
  /** Flag for transition execution. */
@@ -14,18 +13,11 @@ export interface Props extends BaseProps {
14
13
  children: ReactNode
15
14
  }
16
15
 
17
- const useStyles = makeStyles<Theme>(styles, {
18
- name: 'Rotate180',
19
- })
20
-
21
16
  export const Rotate180 = (props: Props) => {
22
17
  const { children, style, className, on, ...rest } = props
23
- const classes = useStyles()
24
18
 
25
19
  const childProps = {
26
- className: cx(className, classes.transition, {
27
- [classes.rotate180]: on,
28
- }),
20
+ className: twMerge(cx(createRotate180ClassNames(on)), className),
29
21
  style,
30
22
  ...rest,
31
23
  }
@@ -6,7 +6,7 @@ exports[`Rotate180 render with transformation 1`] = `
6
6
  class="Picasso-root"
7
7
  >
8
8
  <div
9
- class="Rotate180-transition Rotate180-rotate180"
9
+ class="transition-transform duration-150 ease-in rotate-180"
10
10
  >
11
11
  Rotating component
12
12
  </div>
@@ -20,7 +20,7 @@ exports[`Rotate180 render without transformation 1`] = `
20
20
  class="Picasso-root"
21
21
  >
22
22
  <div
23
- class="Rotate180-transition"
23
+ class="transition-transform duration-150 ease-in"
24
24
  >
25
25
  Rotating component
26
26
  </div>
@@ -1,11 +1,6 @@
1
- import { createStyles } from '@material-ui/core/styles'
2
-
3
- export default () =>
4
- createStyles({
5
- transition: {
6
- transition: 'transform 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms',
7
- },
8
- rotate180: {
9
- transform: 'rotate(180deg)',
10
- },
11
- })
1
+ export const createRotate180ClassNames = (on: boolean): string[] => [
2
+ 'transition-transform',
3
+ 'duration-150',
4
+ 'ease-in-out',
5
+ ...(on ? ['rotate-180'] : []),
6
+ ]
@@ -1 +1,9 @@
1
- export { default as capitalize } from '@material-ui/core/utils/capitalize'
1
+ // Not equivalent to `text-transform: capitalize` — only the first letter of
2
+ // the whole string is uppercased, not the first letter of each word.
3
+ export const capitalize = (string: string): string => {
4
+ if (typeof string !== 'string') {
5
+ throw new Error('Picasso: capitalize(string) expects a string argument.')
6
+ }
7
+
8
+ return string.charAt(0).toUpperCase() + string.slice(1)
9
+ }
@@ -30,7 +30,8 @@ export {
30
30
  type OverridableComponent,
31
31
  } from '@toptal/picasso-shared'
32
32
 
33
- export { default as ClickAwayListener } from '@material-ui/core/ClickAwayListener'
33
+ export { default as ClickAwayListener } from './ClickAwayListener'
34
+ export type { ClickAwayListenerProps } from './ClickAwayListener'
34
35
 
35
36
  export { capitalize } from './capitalize'
36
37
  export { default as disableUnsupportedProps } from './disable-unsupported-props'