@launchpad-ui/drawer 0.4.2 → 0.4.4

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/Drawer.d.ts CHANGED
@@ -8,7 +8,7 @@ type DrawerProps = {
8
8
  theme?: 'dark' | 'default';
9
9
  hideCancel?: boolean;
10
10
  };
11
- declare const Drawer: ({ className, children, onCancel, size, "data-test-id": testId, theme, hideCancel, }: DrawerProps) => JSX.Element;
11
+ declare const Drawer: (props: DrawerProps) => JSX.Element;
12
12
  export { Drawer };
13
13
  export type { DrawerProps };
14
14
  //# sourceMappingURL=Drawer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Drawer.d.ts","sourceRoot":"","sources":["../src/Drawer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAc,SAAS,EAAE,MAAM,OAAO,CAAC;AAoCnD,KAAK,WAAW,GAAG;IACjB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,IAAI,IAAI,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IACxD,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,QAAA,MAAM,MAAM,wFAQT,WAAW,gBAgFb,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,CAAC;AAClB,YAAY,EAAE,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"Drawer.d.ts","sourceRoot":"","sources":["../src/Drawer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAc,SAAS,EAAE,MAAM,OAAO,CAAC;AAqCnD,KAAK,WAAW,GAAG;IACjB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,IAAI,IAAI,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IACxD,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,QAAA,MAAM,MAAM,UAAW,WAAW,gBAIjC,CAAC;AA8GF,OAAO,EAAE,MAAM,EAAE,CAAC;AAClB,YAAY,EAAE,WAAW,EAAE,CAAC"}
@@ -1,5 +1,5 @@
1
- import type { HTMLAttributes } from 'react';
2
- type DrawerHeaderProps = HTMLAttributes<HTMLDivElement> & {
1
+ import type { ComponentProps } from 'react';
2
+ type DrawerHeaderProps = ComponentProps<'div'> & {
3
3
  closeable?: boolean;
4
4
  titleID?: string;
5
5
  titleClassName?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"DrawerHeader.d.ts","sourceRoot":"","sources":["../src/DrawerHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAI5C,KAAK,iBAAiB,GAAG,cAAc,CAAC,cAAc,CAAC,GAAG;IACxD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,IAAI,IAAI,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,QAAA,MAAM,YAAY,sFAOf,iBAAiB,gBAQnB,CAAC;AAEF,OAAO,EAAE,YAAY,EAAE,CAAC;AACxB,YAAY,EAAE,iBAAiB,EAAE,CAAC"}
1
+ {"version":3,"file":"DrawerHeader.d.ts","sourceRoot":"","sources":["../src/DrawerHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAI5C,KAAK,iBAAiB,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG;IAC/C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,IAAI,IAAI,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,QAAA,MAAM,YAAY,sFAOf,iBAAiB,gBAQnB,CAAC;AAEF,OAAO,EAAE,YAAY,EAAE,CAAC;AACxB,YAAY,EAAE,iBAAiB,EAAE,CAAC"}
package/dist/index.es.js CHANGED
@@ -4,10 +4,11 @@ import { FocusTrap } from "@launchpad-ui/focus-trap";
4
4
  import { Close } from "@launchpad-ui/icons";
5
5
  import { Portal } from "@launchpad-ui/portal";
6
6
  import { Progress } from "@launchpad-ui/progress";
7
+ import { useFocusWithin } from "@react-aria/interactions";
7
8
  import { usePreventScroll } from "@react-aria/overlays";
8
9
  import { cx } from "classix";
9
10
  import { LazyMotion, m } from "framer-motion";
10
- import { useRef, useEffect, Suspense } from "react";
11
+ import { useRef, useState, useEffect, Suspense } from "react";
11
12
  import { jsx, jsxs } from "react/jsx-runtime";
12
13
  const DRAWER_LABELLED_BY = "drawer-title";
13
14
  const drawer = "_drawer_b2us9_12";
@@ -62,7 +63,12 @@ const loadFeatures = () => import(
62
63
  /* webpackExports: "domAnimation" */
63
64
  "framer-motion"
64
65
  ).then((res) => res.domAnimation);
65
- const Drawer = ({
66
+ const Drawer = (props) => /* @__PURE__ */ jsx(Portal, {
67
+ children: /* @__PURE__ */ jsx(DrawerContainer, {
68
+ ...props
69
+ })
70
+ });
71
+ const DrawerContainer = ({
66
72
  className,
67
73
  children,
68
74
  onCancel,
@@ -72,77 +78,94 @@ const Drawer = ({
72
78
  hideCancel = false
73
79
  }) => {
74
80
  const ref = useRef(null);
81
+ const [isFocusWithin, setIsFocusWithin] = useState(false);
82
+ const {
83
+ focusWithinProps
84
+ } = useFocusWithin({
85
+ onFocusWithinChange: (isFocusWithin2) => setIsFocusWithin(isFocusWithin2)
86
+ });
75
87
  usePreventScroll();
76
88
  useEffect(() => {
77
89
  const handleEscape = (event) => {
78
90
  event.stopImmediatePropagation();
79
91
  const latest = [...document.querySelectorAll("[data-drawer]")].pop();
80
- if (event.key === "Escape" && latest === ref.current) {
92
+ if (event.key === "Escape" && latest === ref.current && isFocusWithin) {
81
93
  close();
82
94
  }
83
95
  };
96
+ const addOverlayAndEventHandler = () => {
97
+ document.body.classList.add("has-overlay");
98
+ document.addEventListener("keydown", handleEscape);
99
+ };
100
+ const removeOverlayAndEventHandler = () => {
101
+ document.body.classList.remove("has-overlay");
102
+ document.removeEventListener("keydown", handleEscape);
103
+ };
84
104
  const close = () => {
85
105
  onCancel == null ? void 0 : onCancel();
86
106
  };
87
- document.body.classList.add("has-overlay");
88
- document.addEventListener("keydown", handleEscape);
107
+ if (isFocusWithin) {
108
+ addOverlayAndEventHandler();
109
+ }
110
+ if (!isFocusWithin) {
111
+ removeOverlayAndEventHandler();
112
+ }
89
113
  return () => {
90
- document.body.classList.remove("has-overlay");
91
- document.removeEventListener("keydown", handleEscape);
114
+ removeOverlayAndEventHandler();
92
115
  };
93
- }, [onCancel, testId]);
116
+ }, [onCancel, testId, isFocusWithin]);
94
117
  const handleOverlayClick = (event) => {
95
118
  if (event.target === event.currentTarget) {
96
119
  onCancel && onCancel();
97
120
  }
98
121
  };
99
- return /* @__PURE__ */ jsx(Portal, {
100
- children: /* @__PURE__ */ jsx(LazyMotion, {
101
- strict: true,
102
- features: loadFeatures,
103
- children: /* @__PURE__ */ jsx("div", {
104
- className: cx(styles.drawer, styles[size], className),
105
- "data-drawer": true,
106
- "data-test-id": testId,
107
- ref,
108
- children: /* @__PURE__ */ jsx(m.div, {
109
- initial: "hidden",
110
- animate: "visible",
111
- variants: overlay,
112
- transition: {
113
- duration: 0.15
114
- },
115
- role: "presentation",
116
- className: styles.overlay,
117
- onMouseDown: handleOverlayClick,
118
- children: /* @__PURE__ */ jsx(FocusTrap, {
119
- autoFocus: true,
120
- restoreFocus: true,
121
- children: /* @__PURE__ */ jsxs(m.div, {
122
- initial: "hidden",
123
- animate: "visible",
124
- variants: slideRight,
125
- role: "dialog",
126
- "aria-labelledby": DRAWER_LABELLED_BY,
127
- "aria-modal": true,
128
- className: styles.content,
129
- tabIndex: -1,
130
- ...theme ? {
131
- "data-theme": theme
132
- } : {},
133
- children: [!hideCancel && /* @__PURE__ */ jsx(IconButton, {
134
- "aria-label": "close",
135
- icon: /* @__PURE__ */ jsx(Close, {
136
- size: "medium"
137
- }),
138
- className: styles.closeButton,
139
- onClick: onCancel,
140
- "data-test-id": "drawer-close-button"
141
- }), /* @__PURE__ */ jsx(Suspense, {
142
- fallback: /* @__PURE__ */ jsx(Progress, {}),
143
- children
144
- })]
145
- })
122
+ return /* @__PURE__ */ jsx(LazyMotion, {
123
+ strict: true,
124
+ features: loadFeatures,
125
+ children: /* @__PURE__ */ jsx("div", {
126
+ ...focusWithinProps,
127
+ className: cx(styles.drawer, styles[size], className),
128
+ "data-drawer": true,
129
+ "data-test-id": testId,
130
+ ref,
131
+ children: /* @__PURE__ */ jsx(m.div, {
132
+ initial: "hidden",
133
+ animate: "visible",
134
+ variants: overlay,
135
+ transition: {
136
+ duration: 0.15
137
+ },
138
+ role: "presentation",
139
+ className: styles.overlay,
140
+ onMouseDown: handleOverlayClick,
141
+ children: /* @__PURE__ */ jsx(FocusTrap, {
142
+ autoFocus: true,
143
+ restoreFocus: true,
144
+ children: /* @__PURE__ */ jsxs(m.div, {
145
+ initial: "hidden",
146
+ animate: "visible",
147
+ variants: slideRight,
148
+ role: "dialog",
149
+ "aria-labelledby": DRAWER_LABELLED_BY,
150
+ "aria-describedby": DRAWER_LABELLED_BY,
151
+ "aria-modal": true,
152
+ className: styles.content,
153
+ tabIndex: -1,
154
+ ...theme ? {
155
+ "data-theme": theme
156
+ } : {},
157
+ children: [!hideCancel && /* @__PURE__ */ jsx(IconButton, {
158
+ "aria-label": "close",
159
+ icon: /* @__PURE__ */ jsx(Close, {
160
+ size: "medium"
161
+ }),
162
+ className: styles.closeButton,
163
+ onClick: onCancel,
164
+ "data-test-id": "drawer-close-button"
165
+ }), /* @__PURE__ */ jsx(Suspense, {
166
+ fallback: /* @__PURE__ */ jsx(Progress, {}),
167
+ children
168
+ })]
146
169
  })
147
170
  })
148
171
  })
@@ -1 +1 @@
1
- {"version":3,"file":"index.es.js","sources":["../src/constants.ts","../src/Drawer.tsx","../src/DrawerHeader.tsx"],"sourcesContent":["export const DRAWER_LABELLED_BY = 'drawer-title';\n","import type { Variants } from 'framer-motion';\nimport type { MouseEvent, ReactNode } from 'react';\n\nimport { IconButton } from '@launchpad-ui/button';\nimport { FocusTrap } from '@launchpad-ui/focus-trap';\nimport { Close } from '@launchpad-ui/icons';\nimport { Portal } from '@launchpad-ui/portal';\nimport { Progress } from '@launchpad-ui/progress';\nimport { usePreventScroll } from '@react-aria/overlays';\nimport { cx } from 'classix';\nimport { LazyMotion, m } from 'framer-motion';\nimport { Suspense, useEffect, useRef } from 'react';\n\nimport { DRAWER_LABELLED_BY } from './constants';\nimport styles from './styles/Drawer.module.css';\n\nconst overlay: Variants = {\n visible: { opacity: 1, transition: { duration: 0.15 } },\n hidden: { opacity: 0 },\n};\n\nconst slideRight: Variants = {\n hidden: { opacity: 0, x: '25%' },\n visible: {\n opacity: 1,\n x: '0%',\n transition: { type: 'spring', delay: 0.15, duration: 0.2, bounce: 0 },\n },\n};\n\nconst loadFeatures = () =>\n import(\n /* webpackChunkName: \"lp-drawer-framer-features\" */\n /* webpackExports: \"domAnimation\" */\n 'framer-motion'\n ).then((res) => res.domAnimation);\n\ntype DrawerProps = {\n children?: ReactNode;\n className?: string;\n onCancel?(): void;\n 'data-test-id'?: string;\n size?: 'small' | 'medium' | 'large' | 'xLarge' | 'full';\n theme?: 'dark' | 'default';\n hideCancel?: boolean;\n};\n\nconst Drawer = ({\n className,\n children,\n onCancel,\n size = 'small',\n 'data-test-id': testId = 'drawer',\n theme,\n hideCancel = false,\n}: DrawerProps) => {\n const ref = useRef<HTMLDivElement>(null);\n\n usePreventScroll();\n\n useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n event.stopImmediatePropagation();\n const latest = [...document.querySelectorAll('[data-drawer]')].pop();\n if (event.key === 'Escape' && latest === ref.current) {\n close();\n }\n };\n\n const close = () => {\n onCancel?.();\n };\n\n document.body.classList.add('has-overlay');\n document.addEventListener('keydown', handleEscape);\n\n return () => {\n document.body.classList.remove('has-overlay');\n document.removeEventListener('keydown', handleEscape);\n };\n }, [onCancel, testId]);\n\n const handleOverlayClick = (event: MouseEvent<HTMLDivElement>) => {\n if (event.target === event.currentTarget) {\n onCancel && onCancel();\n }\n };\n\n return (\n <Portal>\n <LazyMotion strict features={loadFeatures}>\n <div\n className={cx(styles.drawer, styles[size], className)}\n data-drawer\n data-test-id={testId}\n ref={ref}\n >\n <m.div\n initial=\"hidden\"\n animate=\"visible\"\n variants={overlay}\n transition={{ duration: 0.15 }}\n role=\"presentation\"\n className={styles.overlay}\n onMouseDown={handleOverlayClick}\n >\n <FocusTrap autoFocus restoreFocus>\n <m.div\n initial=\"hidden\"\n animate=\"visible\"\n variants={slideRight}\n role=\"dialog\"\n aria-labelledby={DRAWER_LABELLED_BY}\n aria-modal\n className={styles.content}\n tabIndex={-1}\n {...(theme ? { 'data-theme': theme } : {})}\n >\n {!hideCancel && (\n <IconButton\n aria-label=\"close\"\n icon={<Close size=\"medium\" />}\n className={styles.closeButton}\n onClick={onCancel}\n data-test-id=\"drawer-close-button\"\n />\n )}\n <Suspense fallback={<Progress />}>{children}</Suspense>\n </m.div>\n </FocusTrap>\n </m.div>\n </div>\n </LazyMotion>\n </Portal>\n );\n};\n\nexport { Drawer };\nexport type { DrawerProps };\n","import type { HTMLAttributes } from 'react';\n\nimport { DRAWER_LABELLED_BY } from './constants';\n\ntype DrawerHeaderProps = HTMLAttributes<HTMLDivElement> & {\n closeable?: boolean;\n titleID?: string;\n titleClassName?: string;\n onClose?(): void;\n 'data-test-id'?: string;\n};\n\nconst DrawerHeader = ({\n className,\n children,\n titleID,\n titleClassName,\n 'data-test-id': testId = 'drawer-header',\n ...rest\n}: DrawerHeaderProps) => {\n return (\n <div data-test-id={testId} className={className} {...rest}>\n <h2 id={DRAWER_LABELLED_BY} className={titleClassName}>\n {children}\n </h2>\n </div>\n );\n};\n\nexport { DrawerHeader };\nexport type { DrawerHeaderProps };\n"],"names":["overlay","visible","opacity","transition","duration","hidden","slideRight","x","type","delay","bounce","loadFeatures","then","res","domAnimation","Drawer","className","children","onCancel","size","testId","theme","hideCancel","ref","useRef","useEffect","handleEscape","event","stopImmediatePropagation","latest","document","querySelectorAll","pop","key","current","close","body","classList","add","addEventListener","remove","removeEventListener","handleOverlayClick","target","currentTarget","Portal","LazyMotion","strict","features","cx","styles","drawer","m","div","initial","animate","variants","role","onMouseDown","FocusTrap","autoFocus","restoreFocus","DRAWER_LABELLED_BY","content","tabIndex","IconButton","icon","Close","closeButton","onClick","_jsx","Suspense","fallback","Progress","DrawerHeader","titleID","titleClassName","rest","id"],"mappings":"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"}
1
+ {"version":3,"file":"index.es.js","sources":["../src/constants.ts","../src/Drawer.tsx","../src/DrawerHeader.tsx"],"sourcesContent":["export const DRAWER_LABELLED_BY = 'drawer-title';\n","import type { Variants } from 'framer-motion';\nimport type { MouseEvent, ReactNode } from 'react';\n\nimport { IconButton } from '@launchpad-ui/button';\nimport { FocusTrap } from '@launchpad-ui/focus-trap';\nimport { Close } from '@launchpad-ui/icons';\nimport { Portal } from '@launchpad-ui/portal';\nimport { Progress } from '@launchpad-ui/progress';\nimport { useFocusWithin } from '@react-aria/interactions';\nimport { usePreventScroll } from '@react-aria/overlays';\nimport { cx } from 'classix';\nimport { LazyMotion, m } from 'framer-motion';\nimport { useState, Suspense, useEffect, useRef } from 'react';\n\nimport { DRAWER_LABELLED_BY } from './constants';\nimport styles from './styles/Drawer.module.css';\n\nconst overlay: Variants = {\n visible: { opacity: 1, transition: { duration: 0.15 } },\n hidden: { opacity: 0 },\n};\n\nconst slideRight: Variants = {\n hidden: { opacity: 0, x: '25%' },\n visible: {\n opacity: 1,\n x: '0%',\n transition: { type: 'spring', delay: 0.15, duration: 0.2, bounce: 0 },\n },\n};\n\nconst loadFeatures = () =>\n import(\n /* webpackChunkName: \"lp-drawer-framer-features\" */\n /* webpackExports: \"domAnimation\" */\n 'framer-motion'\n ).then((res) => res.domAnimation);\n\ntype DrawerProps = {\n children?: ReactNode;\n className?: string;\n onCancel?(): void;\n 'data-test-id'?: string;\n size?: 'small' | 'medium' | 'large' | 'xLarge' | 'full';\n theme?: 'dark' | 'default';\n hideCancel?: boolean;\n};\n\nconst Drawer = (props: DrawerProps) => (\n <Portal>\n <DrawerContainer {...props} />\n </Portal>\n);\n\nconst DrawerContainer = ({\n className,\n children,\n onCancel,\n size = 'small',\n 'data-test-id': testId = 'drawer',\n theme,\n hideCancel = false,\n}: DrawerProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const [isFocusWithin, setIsFocusWithin] = useState(false);\n const { focusWithinProps } = useFocusWithin({\n onFocusWithinChange: (isFocusWithin) => setIsFocusWithin(isFocusWithin),\n });\n\n usePreventScroll();\n\n useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n event.stopImmediatePropagation();\n const latest = [...document.querySelectorAll('[data-drawer]')].pop();\n if (event.key === 'Escape' && latest === ref.current && isFocusWithin) {\n close();\n }\n };\n\n const addOverlayAndEventHandler = () => {\n document.body.classList.add('has-overlay');\n document.addEventListener('keydown', handleEscape);\n };\n\n const removeOverlayAndEventHandler = () => {\n document.body.classList.remove('has-overlay');\n document.removeEventListener('keydown', handleEscape);\n };\n\n const close = () => {\n onCancel?.();\n };\n\n if (isFocusWithin) {\n addOverlayAndEventHandler();\n }\n\n if (!isFocusWithin) {\n removeOverlayAndEventHandler();\n }\n\n return () => {\n removeOverlayAndEventHandler();\n };\n }, [onCancel, testId, isFocusWithin]);\n\n const handleOverlayClick = (event: MouseEvent<HTMLDivElement>) => {\n if (event.target === event.currentTarget) {\n onCancel && onCancel();\n }\n };\n\n return (\n <LazyMotion strict features={loadFeatures}>\n <div\n {...focusWithinProps}\n className={cx(styles.drawer, styles[size], className)}\n data-drawer\n data-test-id={testId}\n ref={ref}\n >\n <m.div\n initial=\"hidden\"\n animate=\"visible\"\n variants={overlay}\n transition={{ duration: 0.15 }}\n role=\"presentation\"\n className={styles.overlay}\n onMouseDown={handleOverlayClick}\n >\n <FocusTrap autoFocus restoreFocus>\n <m.div\n initial=\"hidden\"\n animate=\"visible\"\n variants={slideRight}\n role=\"dialog\"\n aria-labelledby={DRAWER_LABELLED_BY}\n aria-describedby={DRAWER_LABELLED_BY}\n aria-modal\n className={styles.content}\n tabIndex={-1}\n {...(theme ? { 'data-theme': theme } : {})}\n >\n {!hideCancel && (\n <IconButton\n aria-label=\"close\"\n icon={<Close size=\"medium\" />}\n className={styles.closeButton}\n onClick={onCancel}\n data-test-id=\"drawer-close-button\"\n />\n )}\n <Suspense fallback={<Progress />}>{children}</Suspense>\n </m.div>\n </FocusTrap>\n </m.div>\n </div>\n </LazyMotion>\n );\n};\n\nexport { Drawer };\nexport type { DrawerProps };\n","import type { ComponentProps } from 'react';\n\nimport { DRAWER_LABELLED_BY } from './constants';\n\ntype DrawerHeaderProps = ComponentProps<'div'> & {\n closeable?: boolean;\n titleID?: string;\n titleClassName?: string;\n onClose?(): void;\n 'data-test-id'?: string;\n};\n\nconst DrawerHeader = ({\n className,\n children,\n titleID,\n titleClassName,\n 'data-test-id': testId = 'drawer-header',\n ...rest\n}: DrawerHeaderProps) => {\n return (\n <div data-test-id={testId} className={className} {...rest}>\n <h2 id={DRAWER_LABELLED_BY} className={titleClassName}>\n {children}\n </h2>\n </div>\n );\n};\n\nexport { DrawerHeader };\nexport type { DrawerHeaderProps };\n"],"names":["overlay","visible","opacity","transition","duration","hidden","slideRight","x","type","delay","bounce","loadFeatures","then","res","domAnimation","Drawer","props","_jsx","Portal","children","DrawerContainer","className","onCancel","size","testId","theme","hideCancel","ref","useRef","isFocusWithin","setIsFocusWithin","useState","focusWithinProps","useFocusWithin","onFocusWithinChange","useEffect","handleEscape","event","stopImmediatePropagation","latest","document","querySelectorAll","pop","key","current","addOverlayAndEventHandler","body","classList","add","addEventListener","removeOverlayAndEventHandler","remove","removeEventListener","close","handleOverlayClick","target","currentTarget","LazyMotion","strict","features","cx","styles","drawer","m","div","initial","animate","variants","role","onMouseDown","FocusTrap","autoFocus","restoreFocus","DRAWER_LABELLED_BY","content","tabIndex","IconButton","icon","Close","closeButton","onClick","Suspense","fallback","Progress","DrawerHeader","titleID","titleClassName","rest","id"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -6,6 +6,7 @@ const focusTrap = require("@launchpad-ui/focus-trap");
6
6
  const icons = require("@launchpad-ui/icons");
7
7
  const portal = require("@launchpad-ui/portal");
8
8
  const progress = require("@launchpad-ui/progress");
9
+ const interactions = require("@react-aria/interactions");
9
10
  const overlays = require("@react-aria/overlays");
10
11
  const classix = require("classix");
11
12
  const framerMotion = require("framer-motion");
@@ -80,7 +81,12 @@ const slideRight = {
80
81
  const loadFeatures = () => Promise.resolve().then(() => /* @__PURE__ */ _interopNamespace(require(
81
82
  "framer-motion"
82
83
  ))).then((res) => res.domAnimation);
83
- const Drawer = ({
84
+ const Drawer = (props) => /* @__PURE__ */ jsxRuntime.jsx(portal.Portal, {
85
+ children: /* @__PURE__ */ jsxRuntime.jsx(DrawerContainer, {
86
+ ...props
87
+ })
88
+ });
89
+ const DrawerContainer = ({
84
90
  className,
85
91
  children,
86
92
  onCancel,
@@ -90,77 +96,94 @@ const Drawer = ({
90
96
  hideCancel = false
91
97
  }) => {
92
98
  const ref = react.useRef(null);
99
+ const [isFocusWithin, setIsFocusWithin] = react.useState(false);
100
+ const {
101
+ focusWithinProps
102
+ } = interactions.useFocusWithin({
103
+ onFocusWithinChange: (isFocusWithin2) => setIsFocusWithin(isFocusWithin2)
104
+ });
93
105
  overlays.usePreventScroll();
94
106
  react.useEffect(() => {
95
107
  const handleEscape = (event) => {
96
108
  event.stopImmediatePropagation();
97
109
  const latest = [...document.querySelectorAll("[data-drawer]")].pop();
98
- if (event.key === "Escape" && latest === ref.current) {
110
+ if (event.key === "Escape" && latest === ref.current && isFocusWithin) {
99
111
  close();
100
112
  }
101
113
  };
114
+ const addOverlayAndEventHandler = () => {
115
+ document.body.classList.add("has-overlay");
116
+ document.addEventListener("keydown", handleEscape);
117
+ };
118
+ const removeOverlayAndEventHandler = () => {
119
+ document.body.classList.remove("has-overlay");
120
+ document.removeEventListener("keydown", handleEscape);
121
+ };
102
122
  const close = () => {
103
123
  onCancel == null ? void 0 : onCancel();
104
124
  };
105
- document.body.classList.add("has-overlay");
106
- document.addEventListener("keydown", handleEscape);
125
+ if (isFocusWithin) {
126
+ addOverlayAndEventHandler();
127
+ }
128
+ if (!isFocusWithin) {
129
+ removeOverlayAndEventHandler();
130
+ }
107
131
  return () => {
108
- document.body.classList.remove("has-overlay");
109
- document.removeEventListener("keydown", handleEscape);
132
+ removeOverlayAndEventHandler();
110
133
  };
111
- }, [onCancel, testId]);
134
+ }, [onCancel, testId, isFocusWithin]);
112
135
  const handleOverlayClick = (event) => {
113
136
  if (event.target === event.currentTarget) {
114
137
  onCancel && onCancel();
115
138
  }
116
139
  };
117
- return /* @__PURE__ */ jsxRuntime.jsx(portal.Portal, {
118
- children: /* @__PURE__ */ jsxRuntime.jsx(framerMotion.LazyMotion, {
119
- strict: true,
120
- features: loadFeatures,
121
- children: /* @__PURE__ */ jsxRuntime.jsx("div", {
122
- className: classix.cx(styles.drawer, styles[size], className),
123
- "data-drawer": true,
124
- "data-test-id": testId,
125
- ref,
126
- children: /* @__PURE__ */ jsxRuntime.jsx(framerMotion.m.div, {
127
- initial: "hidden",
128
- animate: "visible",
129
- variants: overlay,
130
- transition: {
131
- duration: 0.15
132
- },
133
- role: "presentation",
134
- className: styles.overlay,
135
- onMouseDown: handleOverlayClick,
136
- children: /* @__PURE__ */ jsxRuntime.jsx(focusTrap.FocusTrap, {
137
- autoFocus: true,
138
- restoreFocus: true,
139
- children: /* @__PURE__ */ jsxRuntime.jsxs(framerMotion.m.div, {
140
- initial: "hidden",
141
- animate: "visible",
142
- variants: slideRight,
143
- role: "dialog",
144
- "aria-labelledby": DRAWER_LABELLED_BY,
145
- "aria-modal": true,
146
- className: styles.content,
147
- tabIndex: -1,
148
- ...theme ? {
149
- "data-theme": theme
150
- } : {},
151
- children: [!hideCancel && /* @__PURE__ */ jsxRuntime.jsx(button.IconButton, {
152
- "aria-label": "close",
153
- icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Close, {
154
- size: "medium"
155
- }),
156
- className: styles.closeButton,
157
- onClick: onCancel,
158
- "data-test-id": "drawer-close-button"
159
- }), /* @__PURE__ */ jsxRuntime.jsx(react.Suspense, {
160
- fallback: /* @__PURE__ */ jsxRuntime.jsx(progress.Progress, {}),
161
- children
162
- })]
163
- })
140
+ return /* @__PURE__ */ jsxRuntime.jsx(framerMotion.LazyMotion, {
141
+ strict: true,
142
+ features: loadFeatures,
143
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", {
144
+ ...focusWithinProps,
145
+ className: classix.cx(styles.drawer, styles[size], className),
146
+ "data-drawer": true,
147
+ "data-test-id": testId,
148
+ ref,
149
+ children: /* @__PURE__ */ jsxRuntime.jsx(framerMotion.m.div, {
150
+ initial: "hidden",
151
+ animate: "visible",
152
+ variants: overlay,
153
+ transition: {
154
+ duration: 0.15
155
+ },
156
+ role: "presentation",
157
+ className: styles.overlay,
158
+ onMouseDown: handleOverlayClick,
159
+ children: /* @__PURE__ */ jsxRuntime.jsx(focusTrap.FocusTrap, {
160
+ autoFocus: true,
161
+ restoreFocus: true,
162
+ children: /* @__PURE__ */ jsxRuntime.jsxs(framerMotion.m.div, {
163
+ initial: "hidden",
164
+ animate: "visible",
165
+ variants: slideRight,
166
+ role: "dialog",
167
+ "aria-labelledby": DRAWER_LABELLED_BY,
168
+ "aria-describedby": DRAWER_LABELLED_BY,
169
+ "aria-modal": true,
170
+ className: styles.content,
171
+ tabIndex: -1,
172
+ ...theme ? {
173
+ "data-theme": theme
174
+ } : {},
175
+ children: [!hideCancel && /* @__PURE__ */ jsxRuntime.jsx(button.IconButton, {
176
+ "aria-label": "close",
177
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Close, {
178
+ size: "medium"
179
+ }),
180
+ className: styles.closeButton,
181
+ onClick: onCancel,
182
+ "data-test-id": "drawer-close-button"
183
+ }), /* @__PURE__ */ jsxRuntime.jsx(react.Suspense, {
184
+ fallback: /* @__PURE__ */ jsxRuntime.jsx(progress.Progress, {}),
185
+ children
186
+ })]
164
187
  })
165
188
  })
166
189
  })
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/constants.ts","../src/Drawer.tsx","../src/DrawerHeader.tsx"],"sourcesContent":["export const DRAWER_LABELLED_BY = 'drawer-title';\n","import type { Variants } from 'framer-motion';\nimport type { MouseEvent, ReactNode } from 'react';\n\nimport { IconButton } from '@launchpad-ui/button';\nimport { FocusTrap } from '@launchpad-ui/focus-trap';\nimport { Close } from '@launchpad-ui/icons';\nimport { Portal } from '@launchpad-ui/portal';\nimport { Progress } from '@launchpad-ui/progress';\nimport { usePreventScroll } from '@react-aria/overlays';\nimport { cx } from 'classix';\nimport { LazyMotion, m } from 'framer-motion';\nimport { Suspense, useEffect, useRef } from 'react';\n\nimport { DRAWER_LABELLED_BY } from './constants';\nimport styles from './styles/Drawer.module.css';\n\nconst overlay: Variants = {\n visible: { opacity: 1, transition: { duration: 0.15 } },\n hidden: { opacity: 0 },\n};\n\nconst slideRight: Variants = {\n hidden: { opacity: 0, x: '25%' },\n visible: {\n opacity: 1,\n x: '0%',\n transition: { type: 'spring', delay: 0.15, duration: 0.2, bounce: 0 },\n },\n};\n\nconst loadFeatures = () =>\n import(\n /* webpackChunkName: \"lp-drawer-framer-features\" */\n /* webpackExports: \"domAnimation\" */\n 'framer-motion'\n ).then((res) => res.domAnimation);\n\ntype DrawerProps = {\n children?: ReactNode;\n className?: string;\n onCancel?(): void;\n 'data-test-id'?: string;\n size?: 'small' | 'medium' | 'large' | 'xLarge' | 'full';\n theme?: 'dark' | 'default';\n hideCancel?: boolean;\n};\n\nconst Drawer = ({\n className,\n children,\n onCancel,\n size = 'small',\n 'data-test-id': testId = 'drawer',\n theme,\n hideCancel = false,\n}: DrawerProps) => {\n const ref = useRef<HTMLDivElement>(null);\n\n usePreventScroll();\n\n useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n event.stopImmediatePropagation();\n const latest = [...document.querySelectorAll('[data-drawer]')].pop();\n if (event.key === 'Escape' && latest === ref.current) {\n close();\n }\n };\n\n const close = () => {\n onCancel?.();\n };\n\n document.body.classList.add('has-overlay');\n document.addEventListener('keydown', handleEscape);\n\n return () => {\n document.body.classList.remove('has-overlay');\n document.removeEventListener('keydown', handleEscape);\n };\n }, [onCancel, testId]);\n\n const handleOverlayClick = (event: MouseEvent<HTMLDivElement>) => {\n if (event.target === event.currentTarget) {\n onCancel && onCancel();\n }\n };\n\n return (\n <Portal>\n <LazyMotion strict features={loadFeatures}>\n <div\n className={cx(styles.drawer, styles[size], className)}\n data-drawer\n data-test-id={testId}\n ref={ref}\n >\n <m.div\n initial=\"hidden\"\n animate=\"visible\"\n variants={overlay}\n transition={{ duration: 0.15 }}\n role=\"presentation\"\n className={styles.overlay}\n onMouseDown={handleOverlayClick}\n >\n <FocusTrap autoFocus restoreFocus>\n <m.div\n initial=\"hidden\"\n animate=\"visible\"\n variants={slideRight}\n role=\"dialog\"\n aria-labelledby={DRAWER_LABELLED_BY}\n aria-modal\n className={styles.content}\n tabIndex={-1}\n {...(theme ? { 'data-theme': theme } : {})}\n >\n {!hideCancel && (\n <IconButton\n aria-label=\"close\"\n icon={<Close size=\"medium\" />}\n className={styles.closeButton}\n onClick={onCancel}\n data-test-id=\"drawer-close-button\"\n />\n )}\n <Suspense fallback={<Progress />}>{children}</Suspense>\n </m.div>\n </FocusTrap>\n </m.div>\n </div>\n </LazyMotion>\n </Portal>\n );\n};\n\nexport { Drawer };\nexport type { DrawerProps };\n","import type { HTMLAttributes } from 'react';\n\nimport { DRAWER_LABELLED_BY } from './constants';\n\ntype DrawerHeaderProps = HTMLAttributes<HTMLDivElement> & {\n closeable?: boolean;\n titleID?: string;\n titleClassName?: string;\n onClose?(): void;\n 'data-test-id'?: string;\n};\n\nconst DrawerHeader = ({\n className,\n children,\n titleID,\n titleClassName,\n 'data-test-id': testId = 'drawer-header',\n ...rest\n}: DrawerHeaderProps) => {\n return (\n <div data-test-id={testId} className={className} {...rest}>\n <h2 id={DRAWER_LABELLED_BY} className={titleClassName}>\n {children}\n </h2>\n </div>\n );\n};\n\nexport { DrawerHeader };\nexport type { DrawerHeaderProps };\n"],"names":["overlay","visible","opacity","transition","duration","hidden","slideRight","x","type","delay","bounce","loadFeatures","then","res","domAnimation","Drawer","className","children","onCancel","size","testId","theme","hideCancel","ref","useRef","usePreventScroll","useEffect","handleEscape","event","stopImmediatePropagation","latest","document","querySelectorAll","pop","key","current","close","body","classList","add","addEventListener","remove","removeEventListener","handleOverlayClick","target","currentTarget","Portal","LazyMotion","strict","features","cx","styles","drawer","m","div","initial","animate","variants","role","onMouseDown","FocusTrap","autoFocus","restoreFocus","DRAWER_LABELLED_BY","content","tabIndex","IconButton","icon","Close","closeButton","onClick","_jsx","Suspense","fallback","Progress","DrawerHeader","titleID","titleClassName","rest","id"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/constants.ts","../src/Drawer.tsx","../src/DrawerHeader.tsx"],"sourcesContent":["export const DRAWER_LABELLED_BY = 'drawer-title';\n","import type { Variants } from 'framer-motion';\nimport type { MouseEvent, ReactNode } from 'react';\n\nimport { IconButton } from '@launchpad-ui/button';\nimport { FocusTrap } from '@launchpad-ui/focus-trap';\nimport { Close } from '@launchpad-ui/icons';\nimport { Portal } from '@launchpad-ui/portal';\nimport { Progress } from '@launchpad-ui/progress';\nimport { useFocusWithin } from '@react-aria/interactions';\nimport { usePreventScroll } from '@react-aria/overlays';\nimport { cx } from 'classix';\nimport { LazyMotion, m } from 'framer-motion';\nimport { useState, Suspense, useEffect, useRef } from 'react';\n\nimport { DRAWER_LABELLED_BY } from './constants';\nimport styles from './styles/Drawer.module.css';\n\nconst overlay: Variants = {\n visible: { opacity: 1, transition: { duration: 0.15 } },\n hidden: { opacity: 0 },\n};\n\nconst slideRight: Variants = {\n hidden: { opacity: 0, x: '25%' },\n visible: {\n opacity: 1,\n x: '0%',\n transition: { type: 'spring', delay: 0.15, duration: 0.2, bounce: 0 },\n },\n};\n\nconst loadFeatures = () =>\n import(\n /* webpackChunkName: \"lp-drawer-framer-features\" */\n /* webpackExports: \"domAnimation\" */\n 'framer-motion'\n ).then((res) => res.domAnimation);\n\ntype DrawerProps = {\n children?: ReactNode;\n className?: string;\n onCancel?(): void;\n 'data-test-id'?: string;\n size?: 'small' | 'medium' | 'large' | 'xLarge' | 'full';\n theme?: 'dark' | 'default';\n hideCancel?: boolean;\n};\n\nconst Drawer = (props: DrawerProps) => (\n <Portal>\n <DrawerContainer {...props} />\n </Portal>\n);\n\nconst DrawerContainer = ({\n className,\n children,\n onCancel,\n size = 'small',\n 'data-test-id': testId = 'drawer',\n theme,\n hideCancel = false,\n}: DrawerProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const [isFocusWithin, setIsFocusWithin] = useState(false);\n const { focusWithinProps } = useFocusWithin({\n onFocusWithinChange: (isFocusWithin) => setIsFocusWithin(isFocusWithin),\n });\n\n usePreventScroll();\n\n useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n event.stopImmediatePropagation();\n const latest = [...document.querySelectorAll('[data-drawer]')].pop();\n if (event.key === 'Escape' && latest === ref.current && isFocusWithin) {\n close();\n }\n };\n\n const addOverlayAndEventHandler = () => {\n document.body.classList.add('has-overlay');\n document.addEventListener('keydown', handleEscape);\n };\n\n const removeOverlayAndEventHandler = () => {\n document.body.classList.remove('has-overlay');\n document.removeEventListener('keydown', handleEscape);\n };\n\n const close = () => {\n onCancel?.();\n };\n\n if (isFocusWithin) {\n addOverlayAndEventHandler();\n }\n\n if (!isFocusWithin) {\n removeOverlayAndEventHandler();\n }\n\n return () => {\n removeOverlayAndEventHandler();\n };\n }, [onCancel, testId, isFocusWithin]);\n\n const handleOverlayClick = (event: MouseEvent<HTMLDivElement>) => {\n if (event.target === event.currentTarget) {\n onCancel && onCancel();\n }\n };\n\n return (\n <LazyMotion strict features={loadFeatures}>\n <div\n {...focusWithinProps}\n className={cx(styles.drawer, styles[size], className)}\n data-drawer\n data-test-id={testId}\n ref={ref}\n >\n <m.div\n initial=\"hidden\"\n animate=\"visible\"\n variants={overlay}\n transition={{ duration: 0.15 }}\n role=\"presentation\"\n className={styles.overlay}\n onMouseDown={handleOverlayClick}\n >\n <FocusTrap autoFocus restoreFocus>\n <m.div\n initial=\"hidden\"\n animate=\"visible\"\n variants={slideRight}\n role=\"dialog\"\n aria-labelledby={DRAWER_LABELLED_BY}\n aria-describedby={DRAWER_LABELLED_BY}\n aria-modal\n className={styles.content}\n tabIndex={-1}\n {...(theme ? { 'data-theme': theme } : {})}\n >\n {!hideCancel && (\n <IconButton\n aria-label=\"close\"\n icon={<Close size=\"medium\" />}\n className={styles.closeButton}\n onClick={onCancel}\n data-test-id=\"drawer-close-button\"\n />\n )}\n <Suspense fallback={<Progress />}>{children}</Suspense>\n </m.div>\n </FocusTrap>\n </m.div>\n </div>\n </LazyMotion>\n );\n};\n\nexport { Drawer };\nexport type { DrawerProps };\n","import type { ComponentProps } from 'react';\n\nimport { DRAWER_LABELLED_BY } from './constants';\n\ntype DrawerHeaderProps = ComponentProps<'div'> & {\n closeable?: boolean;\n titleID?: string;\n titleClassName?: string;\n onClose?(): void;\n 'data-test-id'?: string;\n};\n\nconst DrawerHeader = ({\n className,\n children,\n titleID,\n titleClassName,\n 'data-test-id': testId = 'drawer-header',\n ...rest\n}: DrawerHeaderProps) => {\n return (\n <div data-test-id={testId} className={className} {...rest}>\n <h2 id={DRAWER_LABELLED_BY} className={titleClassName}>\n {children}\n </h2>\n </div>\n );\n};\n\nexport { DrawerHeader };\nexport type { DrawerHeaderProps };\n"],"names":["overlay","visible","opacity","transition","duration","hidden","slideRight","x","type","delay","bounce","loadFeatures","then","res","domAnimation","Drawer","props","_jsx","Portal","children","DrawerContainer","className","onCancel","size","testId","theme","hideCancel","ref","useRef","isFocusWithin","setIsFocusWithin","useState","focusWithinProps","useFocusWithin","onFocusWithinChange","usePreventScroll","useEffect","handleEscape","event","stopImmediatePropagation","latest","document","querySelectorAll","pop","key","current","addOverlayAndEventHandler","body","classList","add","addEventListener","removeOverlayAndEventHandler","remove","removeEventListener","close","handleOverlayClick","target","currentTarget","LazyMotion","strict","features","cx","styles","drawer","m","div","initial","animate","variants","role","onMouseDown","FocusTrap","autoFocus","restoreFocus","DRAWER_LABELLED_BY","content","tabIndex","IconButton","icon","Close","closeButton","onClick","Suspense","fallback","Progress","DrawerHeader","titleID","titleClassName","rest","id"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@launchpad-ui/drawer",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "status": "alpha",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -26,13 +26,14 @@
26
26
  },
27
27
  "source": "src/index.ts",
28
28
  "dependencies": {
29
+ "@react-aria/interactions": "3.14.0",
29
30
  "@react-aria/overlays": "3.12.1",
30
31
  "classix": "2.1.17",
31
32
  "framer-motion": "9.0.3",
32
- "@launchpad-ui/button": "~0.8.12",
33
+ "@launchpad-ui/button": "~0.8.13",
33
34
  "@launchpad-ui/focus-trap": "~0.1.6",
34
35
  "@launchpad-ui/icons": "~0.8.6",
35
- "@launchpad-ui/portal": "~0.1.2",
36
+ "@launchpad-ui/portal": "~0.1.3",
36
37
  "@launchpad-ui/progress": "~0.5.25",
37
38
  "@launchpad-ui/tokens": "~0.5.6"
38
39
  },