@faststore/ui 2.0.54-alpha.0 → 2.0.56-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -25,8 +25,6 @@ export { default as SearchInput } from './components/molecules/SearchInput';
25
25
  export type { SearchInputProps, SearchInputRef, } from './components/molecules/SearchInput';
26
26
  export { default as Carousel } from './components/molecules/Carousel';
27
27
  export type { CarouselProps } from './components/molecules/Carousel';
28
- export { default as Modal } from './components/molecules/Modal';
29
- export type { ModalProps } from './components/molecules/Modal';
30
28
  export { default as Banner, BannerContent, BannerImage, BannerLink, } from './components/molecules/Banner';
31
29
  export type { BannerProps, BannerContentProps, BannerImageProps, BannerLinkProps, } from './components/molecules/Banner';
32
30
  export { default as PaymentMethods } from './components/molecules/PaymentMethods';
package/dist/index.js CHANGED
@@ -14,7 +14,6 @@ export { default as CartItem, CartItemActions, CartItemContent, CartItemImage, C
14
14
  export { default as Bullets } from './components/molecules/Bullets';
15
15
  export { default as SearchInput } from './components/molecules/SearchInput';
16
16
  export { default as Carousel } from './components/molecules/Carousel';
17
- export { default as Modal } from './components/molecules/Modal';
18
17
  export { default as Banner, BannerContent, BannerImage, BannerLink, } from './components/molecules/Banner';
19
18
  export { default as PaymentMethods } from './components/molecules/PaymentMethods';
20
19
  export { default as Breadcrumb } from './components/molecules/Breadcrumb';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAA;AAErC,QAAQ;AACR,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAG/D,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AAGjE,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AAGjE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAGnE,YAAY;AACZ,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,oCAAoC,CAAA;AAG3E,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,qCAAqC,CAAA;AAG7E,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,qCAAqC,CAAA;AAG7E,OAAO,EACL,OAAO,IAAI,WAAW,EACtB,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,oCAAoC,CAAA;AAQ3C,OAAO,EACL,OAAO,IAAI,IAAI,EACf,SAAS,EACT,WAAW,EACX,WAAW,GACZ,MAAM,6BAA6B,CAAA;AAQpC,OAAO,EACL,OAAO,IAAI,QAAQ,EACnB,eAAe,EACf,eAAe,EACf,aAAa,EACb,cAAc,EACd,eAAe,EACf,aAAa,GACd,MAAM,iCAAiC,CAAA;AAWxC,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,gCAAgC,CAAA;AAGnE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,oCAAoC,CAAA;AAM3E,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAGrE,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,8BAA8B,CAAA;AAG/D,OAAO,EACL,OAAO,IAAI,MAAM,EACjB,aAAa,EACb,WAAW,EACX,UAAU,GACX,MAAM,+BAA+B,CAAA;AAQtC,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,uCAAuC,CAAA;AAGjF,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,mCAAmC,CAAA;AAGzE,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,6BAA6B,CAAA;AAG7D,YAAY;AACZ,OAAO,EACL,OAAO,IAAI,UAAU,EACrB,eAAe,EACf,iBAAiB,GAClB,MAAM,mCAAmC,CAAA;AAO1C,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAA;AAG1D,QAAQ;AACR,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAA;AAErC,QAAQ;AACR,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAG/D,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AAGjE,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AAGjE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAGnE,YAAY;AACZ,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,oCAAoC,CAAA;AAG3E,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,qCAAqC,CAAA;AAG7E,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,qCAAqC,CAAA;AAG7E,OAAO,EACL,OAAO,IAAI,WAAW,EACtB,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,oCAAoC,CAAA;AAQ3C,OAAO,EACL,OAAO,IAAI,IAAI,EACf,SAAS,EACT,WAAW,EACX,WAAW,GACZ,MAAM,6BAA6B,CAAA;AAQpC,OAAO,EACL,OAAO,IAAI,QAAQ,EACnB,eAAe,EACf,eAAe,EACf,aAAa,EACb,cAAc,EACd,eAAe,EACf,aAAa,GACd,MAAM,iCAAiC,CAAA;AAWxC,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,gCAAgC,CAAA;AAGnE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,oCAAoC,CAAA;AAM3E,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAGrE,OAAO,EACL,OAAO,IAAI,MAAM,EACjB,aAAa,EACb,WAAW,EACX,UAAU,GACX,MAAM,+BAA+B,CAAA;AAQtC,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,uCAAuC,CAAA;AAGjF,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,mCAAmC,CAAA;AAGzE,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,6BAA6B,CAAA;AAG7D,YAAY;AACZ,OAAO,EACL,OAAO,IAAI,UAAU,EACrB,eAAe,EACf,iBAAiB,GAClB,MAAM,mCAAmC,CAAA;AAO1C,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAA;AAG1D,QAAQ;AACR,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,mBAAmB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@faststore/ui",
3
- "version": "2.0.54-alpha.0",
3
+ "version": "2.0.56-alpha.0",
4
4
  "description": "A lightweight, framework agnostic component library for React",
5
5
  "author": "emersonlaurentino",
6
6
  "license": "MIT",
@@ -59,5 +59,5 @@
59
59
  "node": "16.18.0",
60
60
  "yarn": "1.19.1"
61
61
  },
62
- "gitHead": "7173ea0bec153905a6b800d002401b5c27fd3213"
62
+ "gitHead": "6afa204ec28032832e3867f805fbc5bcbbed4aab"
63
63
  }
@@ -0,0 +1,97 @@
1
+ [data-fs-modal] {
2
+ // --------------------------------------------------------
3
+ // Design Tokens for Modal
4
+ // --------------------------------------------------------
5
+
6
+ // Default properties
7
+ --fs-modal-position-top : 30vh;
8
+ --fs-modal-position-right : var(--fs-spacing-4);
9
+ --fs-modal-position-left : var(--fs-spacing-4);
10
+ --fs-modal-max-width : calc(var(--fs-grid-breakpoint-desktop) / 3);
11
+ --fs-modal-min-height : var(--fs-spacing-5);
12
+ --fs-modal-margin : auto;
13
+ --fs-modal-background-color : var(--fs-color-body-bkg);
14
+ --fs-modal-border-radius : var(--fs-border-radius);
15
+
16
+ --fs-modal-width-tablet : calc(100vw / 3);
17
+ --fs-modal-min-width-tablet : calc(var(--fs-grid-breakpoint-desktop) / 3);
18
+
19
+ --fs-modal-transition-timing : var(--fs-transition-timing);
20
+ --fs-modal-transition-property : transform;
21
+ --fs-modal-transition-in-function : ease-in;
22
+ --fs-modal-transition-out-function : ease-in;
23
+
24
+ // Header
25
+ --fs-modal-header-padding : var(--fs-spacing-4) var(--fs-spacing-7) var(--fs-spacing-4) var(--fs-spacing-4);
26
+
27
+ // Header Title
28
+ --fs-modal-header-title-margin-bottom : .625rem;
29
+ --fs-modal-header-title-size : var(--fs-text-size-lead);
30
+ --fs-modal-header-title-weight : var(--fs-text-weight-bold);
31
+ --fs-modal-header-title-line-height : 1.2;
32
+
33
+ // Header Description
34
+ --fs-modal-header-description-size : var(--fs-text-size-body);
35
+ --fs-modal-header-description-line-height : 1.5;
36
+ --fs-modal-header-description-color : var(--fs-color-text-light);
37
+
38
+ // Header Close Button
39
+ --fs-modal-header-close-button-position-top : 0;
40
+ --fs-modal-header-close-button-position-right : 0;
41
+
42
+ // Body
43
+ --fs-modal-body-padding : var(--fs-spacing-1) var(--fs-spacing-4) var(--fs-spacing-5);
44
+
45
+ position: fixed;
46
+ top: var(--fs-modal-position-top);
47
+ right: var(--fs-modal-position-right);
48
+ left: var(--fs-modal-position-left);
49
+ max-width: var(--fs-modal-max-width);
50
+ min-height: var(--fs-modal-min-height);
51
+ margin: var(--fs-modal-margin);
52
+ background-color: var(--fs-modal-background-color);
53
+ border-radius: var(--fs-modal-border-radius);
54
+
55
+ @include media(">=tablet") {
56
+ width: var(--fs-modal-width-tablet);
57
+ min-width: var(--fs-modal-min-width-tablet);
58
+ }
59
+
60
+ &[data-fs-modal-state="in"] {
61
+ transition: var(--fs-modal-transition-property) var(--fs-modal-transition-timing) var(--fs-modal-transition-in-function);
62
+ transform: translate3d(0, 0, 0);
63
+ }
64
+
65
+ &[data-fs-modal-state="out"] {
66
+ transition: var(--fs-modal-transition-property) var(--fs-modal-transition-timing) var(--fs-modal-transition-in-function);
67
+ transform: translate3d(0, 50%, 0);
68
+ }
69
+
70
+ [data-fs-modal-header] {
71
+ position: relative;
72
+ padding: var(--fs-modal-header-padding);
73
+
74
+ [data-fs-modal-header-title] {
75
+ margin-bottom: var(--fs-modal-header-title-margin-bottom);
76
+ font-size: var(--fs-modal-header-title-size);
77
+ font-weight: var(--fs-modal-header-title-weight);
78
+ line-height: var(--fs-modal-header-title-line-height);
79
+ }
80
+
81
+ [data-fs-modal-header-description] {
82
+ font-size: var(--fs-modal-header-description-size);
83
+ line-height: var(--fs-modal-header-description-line-height);
84
+ color: var(--fs-modal-header-description-color);
85
+ }
86
+
87
+ [data-fs-modal-header-close-button] {
88
+ position: absolute;
89
+ top: var(--fs-modal-header-close-button-position-top);
90
+ right: var(--fs-modal-header-close-button-position-right);
91
+ }
92
+ }
93
+
94
+ [data-fs-modal-body] {
95
+ padding: var(--fs-modal-body-padding);
96
+ }
97
+ }
package/src/index.ts CHANGED
@@ -80,9 +80,6 @@ export type {
80
80
  export { default as Carousel } from './components/molecules/Carousel'
81
81
  export type { CarouselProps } from './components/molecules/Carousel'
82
82
 
83
- export { default as Modal } from './components/molecules/Modal'
84
- export type { ModalProps } from './components/molecules/Modal'
85
-
86
83
  export {
87
84
  default as Banner,
88
85
  BannerContent,
@@ -24,6 +24,7 @@
24
24
  @import "../components/molecules/Gift/styles";
25
25
  @import "../components/molecules/InputField/styles";
26
26
  @import "../components/molecules/LinkButton/styles";
27
+ @import "../components/molecules/Modal/styles";
27
28
  @import "../components/molecules/QuantitySelector/styles";
28
29
  @import "../components/molecules/RadioField/styles";
29
30
  @import "../components/molecules/Rating/styles";
@@ -1,25 +0,0 @@
1
- import type { AriaAttributes, KeyboardEvent, MouseEvent, PropsWithChildren } from 'react';
2
- import React from 'react';
3
- import type { ModalContentProps } from './ModalContent';
4
- export interface ModalProps extends ModalContentProps {
5
- /**
6
- * ID to find this component in testing tools (e.g.: cypress, testing library, and jest).
7
- */
8
- testId?: string;
9
- /**
10
- * Identifies the element (or elements) that labels the current element.
11
- * @see aria-labelledby https://www.w3.org/TR/wai-aria-1.1/#aria-labelledby
12
- */
13
- 'aria-labelledby'?: AriaAttributes['aria-label'];
14
- /**
15
- * This function is called whenever the user hits "Escape" or clicks outside
16
- * the dialog.
17
- */
18
- onDismiss?: (event: MouseEvent | KeyboardEvent) => void;
19
- /**
20
- * Controls whether or not the dialog is open.
21
- */
22
- isOpen: boolean;
23
- }
24
- declare const Modal: ({ isOpen, children, onDismiss, testId, ...otherProps }: PropsWithChildren<ModalProps>) => React.ReactPortal | null;
25
- export default Modal;
@@ -1,31 +0,0 @@
1
- import React from 'react';
2
- import { createPortal } from 'react-dom';
3
- import { Overlay } from '@faststore/components';
4
- import ModalContent from './ModalContent';
5
- /*
6
- * This component is based on @reach/dialog.
7
- * https://github.com/reach/reach-ui/blob/main/packages/dialog/src/index.tsx
8
- * https://reach.tech/dialog
9
- */
10
- const Modal = ({ isOpen, children, onDismiss, testId = 'store-modal', ...otherProps }) => {
11
- const handleBackdropClick = (event) => {
12
- if (event.defaultPrevented) {
13
- return;
14
- }
15
- event.stopPropagation();
16
- onDismiss?.(event);
17
- };
18
- const handleBackdropKeyDown = (event) => {
19
- if (event.key !== 'Escape' || event.defaultPrevented) {
20
- return;
21
- }
22
- event.stopPropagation();
23
- onDismiss?.(event);
24
- };
25
- return isOpen
26
- ? createPortal(React.createElement(Overlay, { onClick: handleBackdropClick, onKeyDown: handleBackdropKeyDown },
27
- React.createElement(ModalContent, { ...otherProps, testId: testId }, children)), document.body)
28
- : null;
29
- };
30
- export default Modal;
31
- //# sourceMappingURL=Modal.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Modal.js","sourceRoot":"","sources":["../../../../src/components/molecules/Modal/Modal.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAExC,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAA;AAE/C,OAAO,YAAY,MAAM,gBAAgB,CAAA;AAwBzC;;;;GAIG;AAEH,MAAM,KAAK,GAAG,CAAC,EACb,MAAM,EACN,QAAQ,EACR,SAAS,EACT,MAAM,GAAG,aAAa,EACtB,GAAG,UAAU,EACiB,EAAE,EAAE;IAClC,MAAM,mBAAmB,GAAG,CAAC,KAAiB,EAAE,EAAE;QAChD,IAAI,KAAK,CAAC,gBAAgB,EAAE;YAC1B,OAAM;SACP;QAED,KAAK,CAAC,eAAe,EAAE,CAAA;QACvB,SAAS,EAAE,CAAC,KAAK,CAAC,CAAA;IACpB,CAAC,CAAA;IAED,MAAM,qBAAqB,GAAG,CAAC,KAAoB,EAAE,EAAE;QACrD,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,gBAAgB,EAAE;YACpD,OAAM;SACP;QAED,KAAK,CAAC,eAAe,EAAE,CAAA;QACvB,SAAS,EAAE,CAAC,KAAK,CAAC,CAAA;IACpB,CAAC,CAAA;IAED,OAAO,MAAM;QACX,CAAC,CAAC,YAAY,CACV,oBAAC,OAAO,IACN,OAAO,EAAE,mBAAmB,EAC5B,SAAS,EAAE,qBAAqB;YAEhC,oBAAC,YAAY,OAAK,UAAU,EAAE,MAAM,EAAE,MAAM,IACzC,QAAQ,CACI,CACP,EACV,QAAQ,CAAC,IAAI,CACd;QACH,CAAC,CAAC,IAAI,CAAA;AACV,CAAC,CAAA;AAED,eAAe,KAAK,CAAA"}
@@ -1,10 +0,0 @@
1
- import type { DetailedHTMLProps, HTMLAttributes, RefObject } from 'react';
2
- interface ModalContentPureProps extends Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, 'ref'> {
3
- beforeElementRef: RefObject<HTMLDivElement>;
4
- trapFocusRef: RefObject<HTMLDivElement>;
5
- afterElementRef: RefObject<HTMLDivElement>;
6
- testId?: string;
7
- }
8
- export type ModalContentProps = Omit<ModalContentPureProps, 'trapFocusRef' | 'onClick' | 'beforeElementRef' | 'afterElementRef'>;
9
- declare const ModalContent: ({ children, ...otherProps }: ModalContentProps) => JSX.Element;
10
- export default ModalContent;
@@ -1,23 +0,0 @@
1
- import React, { useRef } from 'react';
2
- import useTrapFocus from './useTrapFocus';
3
- const ModalContentPure = ({ beforeElementRef, trapFocusRef, afterElementRef, testId = 'store-modal-content', children, ...otherProps }) => {
4
- return (React.createElement(React.Fragment, null,
5
- React.createElement("div", { ref: beforeElementRef, "data-testid": "beforeElement", tabIndex: 0, "aria-hidden": "true" }),
6
- React.createElement("div", { "data-fs-modal-content": true, "data-testid": testId, ref: trapFocusRef, "aria-modal": "true", role: "dialog", tabIndex: -1, ...otherProps }, children),
7
- React.createElement("div", { ref: afterElementRef, "data-testid": "afterElement", tabIndex: 0, "aria-hidden": "true" })));
8
- };
9
- const ModalContent = ({ children, ...otherProps }) => {
10
- const trapFocusRef = useRef(null);
11
- const beforeElementRef = useRef(null);
12
- const afterElementRef = useRef(null);
13
- useTrapFocus({
14
- beforeElementRef,
15
- trapFocusRef,
16
- afterElementRef,
17
- });
18
- return (React.createElement(ModalContentPure, { ...otherProps, trapFocusRef: trapFocusRef, beforeElementRef: beforeElementRef, afterElementRef: afterElementRef, onClick: (event) => {
19
- event.stopPropagation();
20
- } }, children));
21
- };
22
- export default ModalContent;
23
- //# sourceMappingURL=ModalContent.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ModalContent.js","sourceRoot":"","sources":["../../../../src/components/molecules/Modal/ModalContent.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAErC,OAAO,YAAY,MAAM,gBAAgB,CAAA;AAazC,MAAM,gBAAgB,GAAG,CAAC,EACxB,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,MAAM,GAAG,qBAAqB,EAC9B,QAAQ,EACR,GAAG,UAAU,EACS,EAAE,EAAE;IAC1B,OAAO,CACL;QACE,6BACE,GAAG,EAAE,gBAAgB,iBACT,eAAe,EAC3B,QAAQ,EAAE,CAAC,iBACC,MAAM,GAClB;QACF,2EAEe,MAAM,EACnB,GAAG,EAAE,YAAY,gBACN,MAAM,EACjB,IAAI,EAAC,QAAQ,EACb,QAAQ,EAAE,CAAC,CAAC,KACR,UAAU,IAEb,QAAQ,CACL;QACN,6BACE,GAAG,EAAE,eAAe,iBACR,cAAc,EAC1B,QAAQ,EAAE,CAAC,iBACC,MAAM,GAClB,CACD,CACJ,CAAA;AACH,CAAC,CAAA;AAOD,MAAM,YAAY,GAAG,CAAC,EAAE,QAAQ,EAAE,GAAG,UAAU,EAAqB,EAAE,EAAE;IACtE,MAAM,YAAY,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAA;IACjD,MAAM,gBAAgB,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAA;IACrD,MAAM,eAAe,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAA;IAEpD,YAAY,CAAC;QACX,gBAAgB;QAChB,YAAY;QACZ,eAAe;KAChB,CAAC,CAAA;IAEF,OAAO,CACL,oBAAC,gBAAgB,OACX,UAAU,EACd,YAAY,EAAE,YAAY,EAC1B,gBAAgB,EAAE,gBAAgB,EAClC,eAAe,EAAE,eAAe,EAChC,OAAO,EAAE,CAAC,KAAiB,EAAE,EAAE;YAC7B,KAAK,CAAC,eAAe,EAAE,CAAA;QACzB,CAAC,IAEA,QAAQ,CACQ,CACpB,CAAA;AACH,CAAC,CAAA;AAED,eAAe,YAAY,CAAA"}
@@ -1,2 +0,0 @@
1
- export { default } from './Modal';
2
- export type { ModalProps } from './Modal';
@@ -1,2 +0,0 @@
1
- export { default } from './Modal';
2
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/molecules/Modal/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA"}
@@ -1,8 +0,0 @@
1
- import type { RefObject } from 'react';
2
- interface TrapFocusParams {
3
- beforeElementRef: RefObject<HTMLElement>;
4
- trapFocusRef: RefObject<HTMLElement>;
5
- afterElementRef: RefObject<HTMLElement>;
6
- }
7
- declare const useTrapFocus: ({ trapFocusRef, beforeElementRef, afterElementRef, }: TrapFocusParams) => void;
8
- export default useTrapFocus;
@@ -1,76 +0,0 @@
1
- import { useEffect, useRef } from 'react';
2
- import { tabbable } from 'tabbable';
3
- /*
4
- * Element that will maintain the focus inside trapFocusRef, focus the first element,
5
- * and focus back on the element that was in focus when useTrapFocus was triggered.
6
- *
7
- * Inspired by Reakit useTrapFocus https://github.com/reakit/reakit/blob/a211d94da9f3b683182568a56479b91afb1b85ae/packages/reakit/src/Dialog/__utils/useFocusTrap.ts
8
- */
9
- const useTrapFocus = ({ trapFocusRef, beforeElementRef, afterElementRef, }) => {
10
- const tabbableNodesRef = useRef();
11
- const nodeToRestoreRef = useRef(document.hasFocus() ? document.activeElement : null);
12
- // Focus back on the element that was focused when useTrapFocus is triggered.
13
- useEffect(() => {
14
- const nodeToRestore = nodeToRestoreRef.current;
15
- return () => {
16
- nodeToRestore?.focus();
17
- };
18
- }, [nodeToRestoreRef]);
19
- // Set focus on first tabbable element
20
- useEffect(() => {
21
- if (!trapFocusRef.current) {
22
- return;
23
- }
24
- if (!tabbableNodesRef.current) {
25
- tabbableNodesRef.current = tabbable(trapFocusRef.current);
26
- }
27
- const [firstTabbable] = tabbableNodesRef.current;
28
- if (!firstTabbable) {
29
- trapFocusRef.current.focus();
30
- return;
31
- }
32
- firstTabbable.focus();
33
- }, [trapFocusRef]);
34
- // Handle loop focus. Set keydown and focusin event listeners
35
- useEffect(() => {
36
- if (!trapFocusRef.current ||
37
- !beforeElementRef.current ||
38
- !afterElementRef.current) {
39
- return;
40
- }
41
- const beforeElement = beforeElementRef.current;
42
- const afterElement = afterElementRef.current;
43
- const trapFocus = trapFocusRef.current;
44
- const handleLoopFocus = (nativeEvent) => {
45
- if (!document.hasFocus()) {
46
- return;
47
- }
48
- tabbableNodesRef.current = tabbable(trapFocusRef.current);
49
- if (!tabbableNodesRef.current.length) {
50
- trapFocus.focus();
51
- }
52
- /*
53
- * Handle loop focus from beforeElementRef. This node can only be focused if the user press shift tab.
54
- * It will focus the last element of the trapFocusRef.
55
- */
56
- if (nativeEvent.target === beforeElement) {
57
- tabbableNodesRef.current[tabbableNodesRef.current.length - 1]?.focus();
58
- }
59
- /*
60
- * Handle loop focus from afterElementRef. This node can only be focused if the user press tab.
61
- * It will focus the first element of the trapFocusRef.
62
- */
63
- if (nativeEvent.target === afterElement) {
64
- tabbableNodesRef.current[0]?.focus();
65
- }
66
- };
67
- beforeElement?.addEventListener('focusin', handleLoopFocus);
68
- afterElement?.addEventListener('focusin', handleLoopFocus);
69
- return () => {
70
- beforeElement?.removeEventListener('focusin', handleLoopFocus);
71
- afterElement?.removeEventListener('focusin', handleLoopFocus);
72
- };
73
- }, [tabbableNodesRef, afterElementRef, beforeElementRef, trapFocusRef]);
74
- };
75
- export default useTrapFocus;
76
- //# sourceMappingURL=useTrapFocus.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useTrapFocus.js","sourceRoot":"","sources":["../../../../src/components/molecules/Modal/useTrapFocus.ts"],"names":[],"mappings":"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"}
@@ -1,82 +0,0 @@
1
- import type {
2
- AriaAttributes,
3
- KeyboardEvent,
4
- MouseEvent,
5
- PropsWithChildren,
6
- } from 'react'
7
- import React from 'react'
8
- import { createPortal } from 'react-dom'
9
-
10
- import { Overlay } from '@faststore/components'
11
- import type { ModalContentProps } from './ModalContent'
12
- import ModalContent from './ModalContent'
13
-
14
- export interface ModalProps extends ModalContentProps {
15
- /**
16
- * ID to find this component in testing tools (e.g.: cypress, testing library, and jest).
17
- */
18
- testId?: string
19
- /**
20
- * Identifies the element (or elements) that labels the current element.
21
- * @see aria-labelledby https://www.w3.org/TR/wai-aria-1.1/#aria-labelledby
22
- */
23
- 'aria-labelledby'?: AriaAttributes['aria-label']
24
-
25
- /**
26
- * This function is called whenever the user hits "Escape" or clicks outside
27
- * the dialog.
28
- */
29
- onDismiss?: (event: MouseEvent | KeyboardEvent) => void
30
- /**
31
- * Controls whether or not the dialog is open.
32
- */
33
- isOpen: boolean
34
- }
35
-
36
- /*
37
- * This component is based on @reach/dialog.
38
- * https://github.com/reach/reach-ui/blob/main/packages/dialog/src/index.tsx
39
- * https://reach.tech/dialog
40
- */
41
-
42
- const Modal = ({
43
- isOpen,
44
- children,
45
- onDismiss,
46
- testId = 'store-modal',
47
- ...otherProps
48
- }: PropsWithChildren<ModalProps>) => {
49
- const handleBackdropClick = (event: MouseEvent) => {
50
- if (event.defaultPrevented) {
51
- return
52
- }
53
-
54
- event.stopPropagation()
55
- onDismiss?.(event)
56
- }
57
-
58
- const handleBackdropKeyDown = (event: KeyboardEvent) => {
59
- if (event.key !== 'Escape' || event.defaultPrevented) {
60
- return
61
- }
62
-
63
- event.stopPropagation()
64
- onDismiss?.(event)
65
- }
66
-
67
- return isOpen
68
- ? createPortal(
69
- <Overlay
70
- onClick={handleBackdropClick}
71
- onKeyDown={handleBackdropKeyDown}
72
- >
73
- <ModalContent {...otherProps} testId={testId}>
74
- {children}
75
- </ModalContent>
76
- </Overlay>,
77
- document.body
78
- )
79
- : null
80
- }
81
-
82
- export default Modal
@@ -1,90 +0,0 @@
1
- import type {
2
- DetailedHTMLProps,
3
- HTMLAttributes,
4
- MouseEvent,
5
- RefObject,
6
- } from 'react'
7
- import React, { useRef } from 'react'
8
-
9
- import useTrapFocus from './useTrapFocus'
10
-
11
- interface ModalContentPureProps
12
- extends Omit<
13
- DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>,
14
- 'ref'
15
- > {
16
- beforeElementRef: RefObject<HTMLDivElement>
17
- trapFocusRef: RefObject<HTMLDivElement>
18
- afterElementRef: RefObject<HTMLDivElement>
19
- testId?: string
20
- }
21
-
22
- const ModalContentPure = ({
23
- beforeElementRef,
24
- trapFocusRef,
25
- afterElementRef,
26
- testId = 'store-modal-content',
27
- children,
28
- ...otherProps
29
- }: ModalContentPureProps) => {
30
- return (
31
- <>
32
- <div
33
- ref={beforeElementRef}
34
- data-testid="beforeElement"
35
- tabIndex={0}
36
- aria-hidden="true"
37
- />
38
- <div
39
- data-fs-modal-content
40
- data-testid={testId}
41
- ref={trapFocusRef}
42
- aria-modal="true"
43
- role="dialog"
44
- tabIndex={-1}
45
- {...otherProps}
46
- >
47
- {children}
48
- </div>
49
- <div
50
- ref={afterElementRef}
51
- data-testid="afterElement"
52
- tabIndex={0}
53
- aria-hidden="true"
54
- />
55
- </>
56
- )
57
- }
58
-
59
- export type ModalContentProps = Omit<
60
- ModalContentPureProps,
61
- 'trapFocusRef' | 'onClick' | 'beforeElementRef' | 'afterElementRef'
62
- >
63
-
64
- const ModalContent = ({ children, ...otherProps }: ModalContentProps) => {
65
- const trapFocusRef = useRef<HTMLDivElement>(null)
66
- const beforeElementRef = useRef<HTMLDivElement>(null)
67
- const afterElementRef = useRef<HTMLDivElement>(null)
68
-
69
- useTrapFocus({
70
- beforeElementRef,
71
- trapFocusRef,
72
- afterElementRef,
73
- })
74
-
75
- return (
76
- <ModalContentPure
77
- {...otherProps}
78
- trapFocusRef={trapFocusRef}
79
- beforeElementRef={beforeElementRef}
80
- afterElementRef={afterElementRef}
81
- onClick={(event: MouseEvent) => {
82
- event.stopPropagation()
83
- }}
84
- >
85
- {children}
86
- </ModalContentPure>
87
- )
88
- }
89
-
90
- export default ModalContent
@@ -1,2 +0,0 @@
1
- export { default } from './Modal'
2
- export type { ModalProps } from './Modal'
@@ -1,110 +0,0 @@
1
- import { useEffect, useRef } from 'react'
2
- import type { RefObject } from 'react'
3
- import type { FocusableElement } from 'tabbable'
4
- import { tabbable } from 'tabbable'
5
-
6
- interface TrapFocusParams {
7
- beforeElementRef: RefObject<HTMLElement>
8
- trapFocusRef: RefObject<HTMLElement>
9
- afterElementRef: RefObject<HTMLElement>
10
- }
11
-
12
- /*
13
- * Element that will maintain the focus inside trapFocusRef, focus the first element,
14
- * and focus back on the element that was in focus when useTrapFocus was triggered.
15
- *
16
- * Inspired by Reakit useTrapFocus https://github.com/reakit/reakit/blob/a211d94da9f3b683182568a56479b91afb1b85ae/packages/reakit/src/Dialog/__utils/useFocusTrap.ts
17
- */
18
- const useTrapFocus = ({
19
- trapFocusRef,
20
- beforeElementRef,
21
- afterElementRef,
22
- }: TrapFocusParams) => {
23
- const tabbableNodesRef = useRef<FocusableElement[]>()
24
- const nodeToRestoreRef = useRef<HTMLElement | null>(
25
- document.hasFocus() ? (document.activeElement as HTMLElement) : null
26
- )
27
-
28
- // Focus back on the element that was focused when useTrapFocus is triggered.
29
- useEffect(() => {
30
- const nodeToRestore = nodeToRestoreRef.current
31
-
32
- return () => {
33
- nodeToRestore?.focus()
34
- }
35
- }, [nodeToRestoreRef])
36
-
37
- // Set focus on first tabbable element
38
- useEffect(() => {
39
- if (!trapFocusRef.current) {
40
- return
41
- }
42
-
43
- if (!tabbableNodesRef.current) {
44
- tabbableNodesRef.current = tabbable(trapFocusRef.current)
45
- }
46
-
47
- const [firstTabbable] = tabbableNodesRef.current
48
-
49
- if (!firstTabbable) {
50
- trapFocusRef.current.focus()
51
-
52
- return
53
- }
54
-
55
- firstTabbable.focus()
56
- }, [trapFocusRef])
57
-
58
- // Handle loop focus. Set keydown and focusin event listeners
59
- useEffect(() => {
60
- if (
61
- !trapFocusRef.current ||
62
- !beforeElementRef.current ||
63
- !afterElementRef.current
64
- ) {
65
- return
66
- }
67
-
68
- const beforeElement = beforeElementRef.current
69
- const afterElement = afterElementRef.current
70
- const trapFocus = trapFocusRef.current
71
-
72
- const handleLoopFocus = (nativeEvent: FocusEvent) => {
73
- if (!document.hasFocus()) {
74
- return
75
- }
76
-
77
- tabbableNodesRef.current = tabbable(trapFocusRef.current!)
78
-
79
- if (!tabbableNodesRef.current.length) {
80
- trapFocus.focus()
81
- }
82
-
83
- /*
84
- * Handle loop focus from beforeElementRef. This node can only be focused if the user press shift tab.
85
- * It will focus the last element of the trapFocusRef.
86
- */
87
- if (nativeEvent.target === beforeElement) {
88
- tabbableNodesRef.current[tabbableNodesRef.current.length - 1]?.focus()
89
- }
90
-
91
- /*
92
- * Handle loop focus from afterElementRef. This node can only be focused if the user press tab.
93
- * It will focus the first element of the trapFocusRef.
94
- */
95
- if (nativeEvent.target === afterElement) {
96
- tabbableNodesRef.current[0]?.focus()
97
- }
98
- }
99
-
100
- beforeElement?.addEventListener('focusin', handleLoopFocus)
101
- afterElement?.addEventListener('focusin', handleLoopFocus)
102
-
103
- return () => {
104
- beforeElement?.removeEventListener('focusin', handleLoopFocus)
105
- afterElement?.removeEventListener('focusin', handleLoopFocus)
106
- }
107
- }, [tabbableNodesRef, afterElementRef, beforeElementRef, trapFocusRef])
108
- }
109
-
110
- export default useTrapFocus