@trackunit/react-drawer 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/README.md +21 -0
  2. package/index.cjs.d.ts +1 -0
  3. package/index.cjs.js +443 -0
  4. package/index.esm.d.ts +1 -0
  5. package/index.esm.js +437 -0
  6. package/package.json +21 -0
  7. package/src/components/Drawer/Drawer.d.ts +57 -0
  8. package/src/components/Drawer/Drawer.stories.d.ts +12 -0
  9. package/src/components/Drawer/Drawer.variants.d.ts +7 -0
  10. package/src/components/DrawerToggle/DrawerToggle.d.ts +19 -0
  11. package/src/components/Overlay/Overlay.d.ts +14 -0
  12. package/src/components/SwipeableDrawer/DrawerPuller.d.ts +10 -0
  13. package/src/components/SwipeableDrawer/SwipeableDrawer.d.ts +15 -0
  14. package/src/components/index.d.ts +3 -0
  15. package/src/hooks/index.d.ts +1 -0
  16. package/src/hooks/useSwipeHandlers.d.ts +23 -0
  17. package/src/index.d.ts +1 -0
  18. package/src/translation.d.ts +33 -0
  19. package/src/types.d.ts +2 -0
  20. package/translation.cjs.js +7 -0
  21. package/translation.cjs10.js +7 -0
  22. package/translation.cjs11.js +7 -0
  23. package/translation.cjs12.js +7 -0
  24. package/translation.cjs13.js +7 -0
  25. package/translation.cjs14.js +7 -0
  26. package/translation.cjs15.js +7 -0
  27. package/translation.cjs16.js +7 -0
  28. package/translation.cjs17.js +7 -0
  29. package/translation.cjs2.js +7 -0
  30. package/translation.cjs3.js +7 -0
  31. package/translation.cjs4.js +7 -0
  32. package/translation.cjs5.js +7 -0
  33. package/translation.cjs6.js +7 -0
  34. package/translation.cjs7.js +7 -0
  35. package/translation.cjs8.js +7 -0
  36. package/translation.cjs9.js +7 -0
  37. package/translation.esm.js +5 -0
  38. package/translation.esm10.js +5 -0
  39. package/translation.esm11.js +5 -0
  40. package/translation.esm12.js +5 -0
  41. package/translation.esm13.js +5 -0
  42. package/translation.esm14.js +5 -0
  43. package/translation.esm15.js +5 -0
  44. package/translation.esm16.js +5 -0
  45. package/translation.esm17.js +5 -0
  46. package/translation.esm2.js +5 -0
  47. package/translation.esm3.js +5 -0
  48. package/translation.esm4.js +5 -0
  49. package/translation.esm5.js +5 -0
  50. package/translation.esm6.js +5 -0
  51. package/translation.esm7.js +5 -0
  52. package/translation.esm8.js +5 -0
  53. package/translation.esm9.js +5 -0
package/index.esm.js ADDED
@@ -0,0 +1,437 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { registerTranslations } from '@trackunit/i18n-library-translation';
3
+ import { useEffect, forwardRef, useState, useCallback, useRef, useMemo } from 'react';
4
+ import usePortal from 'react-useportal';
5
+ import { useViewportSize, Icon, useGeometry } from '@trackunit/react-components';
6
+ import { cvaMerge } from '@trackunit/css-class-variance-utilities';
7
+ import { useSwipeable } from 'react-swipeable';
8
+
9
+ var defaultTranslations = {
10
+
11
+ };
12
+
13
+ /** The translation namespace for this library */
14
+ const namespace = "react.react-drawer";
15
+ /**
16
+ * The TranslationResource for this Library.
17
+ * Holds lazy loaded imports for all languages supported by the library.
18
+ *
19
+ * This is used to register the translations for this library before initializing i18next.
20
+ */
21
+ const translations = {
22
+ ns: namespace,
23
+ default: defaultTranslations,
24
+ languages: {
25
+ de: () => import('./translation.esm.js'),
26
+ da: () => import('./translation.esm2.js'),
27
+ cs: () => import('./translation.esm3.js'),
28
+ nl: () => import('./translation.esm4.js'),
29
+ fr: () => import('./translation.esm5.js'),
30
+ fi: () => import('./translation.esm6.js'),
31
+ hu: () => import('./translation.esm7.js'),
32
+ it: () => import('./translation.esm8.js'),
33
+ nb: () => import('./translation.esm9.js'),
34
+ pl: () => import('./translation.esm10.js'),
35
+ pt: () => import('./translation.esm11.js'),
36
+ ru: () => import('./translation.esm12.js'),
37
+ ro: () => import('./translation.esm13.js'),
38
+ es: () => import('./translation.esm14.js'),
39
+ sv: () => import('./translation.esm15.js'),
40
+ ja: () => import('./translation.esm16.js'),
41
+ th: () => import('./translation.esm17.js'),
42
+ },
43
+ };
44
+ /**
45
+ * Registers the translations for this library
46
+ */
47
+ const setupLibraryTranslations = () => {
48
+ registerTranslations(translations);
49
+ };
50
+
51
+ /**
52
+ * Overlay Component
53
+ *
54
+ * @param {object} props - The Overlay component properties
55
+ * @param {boolean} props.open - Open status of the Overlay
56
+ * @param {Function} props.onClose - Callback function when Overlay is closed
57
+ * @returns {JSX.Element|null} The Overlay component
58
+ */
59
+ const Overlay = ({ open, onClose }) => {
60
+ useEffect(() => {
61
+ if (!onClose) {
62
+ return;
63
+ }
64
+ const handleEscape = (event) => {
65
+ if (event.key === "Escape") {
66
+ onClose();
67
+ }
68
+ };
69
+ if (open) {
70
+ window.addEventListener("keyup", handleEscape);
71
+ }
72
+ return () => {
73
+ window.removeEventListener("keyup", handleEscape);
74
+ };
75
+ }, [open, onClose]);
76
+ const handleClick = () => {
77
+ if (onClose) {
78
+ onClose();
79
+ }
80
+ };
81
+ return (jsx("div", { "aria-hidden": open, className: cvaOverlayContainer({ open }), "data-testid": "drawer-overlay", onClick: handleClick }));
82
+ };
83
+ const cvaOverlayContainer = cvaMerge([
84
+ "absolute",
85
+ "flex",
86
+ "items-center",
87
+ "justify-center",
88
+ "inset-0",
89
+ "bg-black/30",
90
+ "bg-opacity-50",
91
+ "transition-opacity",
92
+ "duration-200",
93
+ "ease-[cubic-bezier(0.32,0.72,0,1)]",
94
+ "opacity-0",
95
+ ], {
96
+ variants: {
97
+ open: {
98
+ true: "z-popover opacity-100",
99
+ false: "z-[-1] opacity-0",
100
+ },
101
+ },
102
+ });
103
+
104
+ const cvaDrawer = cvaMerge([
105
+ "z-toast",
106
+ "pointer-events-auto",
107
+ "absolute",
108
+ "transform",
109
+ "flex-col",
110
+ "transition-transform",
111
+ "duration-300",
112
+ "ease-[cubic-bezier(0.32,0.72,0,1)]",
113
+ ], {
114
+ variants: {
115
+ position: {
116
+ left: "left-0 top-0 h-full w-fit",
117
+ right: "right-0 top-0 h-full w-fit",
118
+ top: "left-0 top-0 h-fit w-full pb-2",
119
+ bottom: "bottom-0 left-0 right-0 max-h-screen w-full pt-3",
120
+ },
121
+ mode: {
122
+ open: "", // No additional classes needed; position determines translation
123
+ closed: "", // Translation handled in compoundVariants
124
+ },
125
+ },
126
+ compoundVariants: [
127
+ {
128
+ mode: "open",
129
+ position: "left",
130
+ className: "translate-x-0",
131
+ },
132
+ {
133
+ mode: "closed",
134
+ position: "left",
135
+ className: "-translate-x-full",
136
+ },
137
+ {
138
+ mode: "open",
139
+ position: "right",
140
+ className: "translate-x-0",
141
+ },
142
+ {
143
+ mode: "closed",
144
+ position: "right",
145
+ className: "translate-x-full",
146
+ },
147
+ {
148
+ mode: "open",
149
+ position: "top",
150
+ className: "translate-y-0",
151
+ },
152
+ {
153
+ mode: "closed",
154
+ position: "top",
155
+ className: "-translate-y-full",
156
+ },
157
+ {
158
+ mode: "open",
159
+ position: "bottom",
160
+ className: "translate-y-0",
161
+ },
162
+ {
163
+ mode: "closed",
164
+ position: "bottom",
165
+ className: "translate-y-full",
166
+ },
167
+ ],
168
+ defaultVariants: {
169
+ position: "left",
170
+ mode: "closed",
171
+ },
172
+ });
173
+ const cvaDrawerContent = cvaMerge(["flex", "h-full", "shadow-lg", "bg-white"], {
174
+ variants: {
175
+ position: {
176
+ left: " rounded-r-lg",
177
+ right: " rounded-l-lg",
178
+ top: " flex-col rounded-b-lg",
179
+ bottom: " max-h-[calc(100vh-10px)] flex-col rounded-t-lg sm:max-h-none",
180
+ },
181
+ },
182
+ });
183
+
184
+ const TRANSITION_DURATION = 100;
185
+ const DEFAULT_POSITION = "left";
186
+ const NOOP$1 = () => void 0;
187
+ /**
188
+ * Drawers components can be switched between open and closed states.
189
+ * They start closed but can be temporarily opened, appearing on top of other content until the user chooses a section.
190
+ * To close the drawer, users can either click outside of it or press the Esc key.
191
+ *
192
+ * @param {DrawerProps} props - The props for the Drawer component
193
+ * @returns {JSX.Element | null} Drawer component
194
+ */
195
+ const Drawer = forwardRef(({ open = false, // Default to closed
196
+ onClose = NOOP$1, hasOverlay = true, position = DEFAULT_POSITION, children, dataTestId, className, renderInPortal = false, keepMountedWhenClosed = false, containerClassName, ...others }, ref) => {
197
+ const { isSm } = useViewportSize();
198
+ const { Portal } = usePortal();
199
+ const shouldUsePortal = !isSm || renderInPortal;
200
+ const [shouldRender, setShouldRender] = useState(open);
201
+ const [mode, setMode] = useState(open ? "open" : "closed");
202
+ useEffect(() => {
203
+ if (open) {
204
+ setShouldRender(true);
205
+ setTimeout(() => setMode("open"), TRANSITION_DURATION);
206
+ }
207
+ else {
208
+ setMode("closed");
209
+ }
210
+ }, [open]);
211
+ const handleAnimationEnd = useCallback(() => {
212
+ if (mode === "closed") {
213
+ setShouldRender(false);
214
+ }
215
+ }, [mode, setShouldRender]);
216
+ if (!shouldRender && !keepMountedWhenClosed) {
217
+ return null;
218
+ }
219
+ const content = (jsxs("div", { className: containerClassName, children: [hasOverlay ? jsx(Overlay, { onClose: onClose, open: mode === "open" }) : null, jsx("div", { className: cvaDrawer({
220
+ mode,
221
+ position: position,
222
+ className,
223
+ }), "data-testid": dataTestId, onTransitionEnd: handleAnimationEnd, ref: ref, ...others, children: jsx("div", { className: cvaDrawerContent({ position }), children: children }) })] }));
224
+ return shouldUsePortal ? jsx(Portal, { children: content }) : content;
225
+ });
226
+ Drawer.displayName = "Drawer";
227
+
228
+ const NOOP = () => void 0;
229
+ const getIconName = (open, position) => {
230
+ switch (position) {
231
+ case "left":
232
+ return open ? "ChevronLeft" : "ChevronRight";
233
+ case "right":
234
+ return open ? "ChevronRight" : "ChevronLeft";
235
+ case "top":
236
+ return open ? "ChevronUp" : "ChevronDown";
237
+ case "bottom":
238
+ return open ? "ChevronDown" : "ChevronUp";
239
+ default:
240
+ return open ? "ChevronLeft" : "ChevronRight";
241
+ }
242
+ };
243
+ /**
244
+ * DrawerToggle is a React functional component that returns a button with a chevron icon.
245
+ * The direction of the chevron changes depending on the state of the 'open' prop and
246
+ * the side the button is positioned ('position' prop).
247
+ * The button might be disabled based on the 'disableButton' prop.
248
+ *
249
+ * @param {object} props - The properties passed to the component
250
+ * @param {boolean} props.open - Indicates if the button is in "open" state
251
+ * @param {Function} [props.onClick] - Optional callback function for when the button is clicked
252
+ * @param {DrawerPosition} props.position - The position of the button relative to its container
253
+ */
254
+ const DrawerToggle = ({ open, position, onClick = NOOP }) => {
255
+ const name = getIconName(open, position);
256
+ return (jsx("div", { className: cvaToggleContainer({ position }), children: jsx("button", { className: cvaDrawerToggle({ position }), "data-testid": "toggle-button", onClick: onClick, children: jsx(Icon, { name: name }) }) }));
257
+ };
258
+ const cvaDrawerToggle = cvaMerge([
259
+ "flex",
260
+ "cursor-pointer",
261
+ "items-center",
262
+ "justify-center",
263
+ "border-gray-300",
264
+ "bg-neutral-50",
265
+ "bg-center",
266
+ "bg-no-repeat",
267
+ "shadow-md",
268
+ ], {
269
+ variants: {
270
+ position: {
271
+ left: "h-12 w-6 rounded-r-lg",
272
+ right: "h-12 w-6 rounded-l-lg",
273
+ top: "h-6 w-12 rounded-b-lg",
274
+ bottom: "h-6 w-12 rounded-t-lg",
275
+ },
276
+ },
277
+ defaultVariants: {
278
+ position: "left",
279
+ },
280
+ });
281
+ const cvaToggleContainer = cvaMerge(["z-8", "absolute"], {
282
+ variants: {
283
+ position: {
284
+ left: "right-[-24px] top-[calc(50%-24px)]",
285
+ right: "left-[-24px] top-[calc(50%-24px)]",
286
+ top: "bottom-[-24px] left-[calc(50%-24px)]",
287
+ bottom: "left-[calc(50%-24px)] top-[-24px]",
288
+ },
289
+ },
290
+ defaultVariants: {
291
+ position: "left",
292
+ },
293
+ });
294
+
295
+ /**
296
+ * Retrieves the Y-axis translation value of a given HTML element.
297
+ *
298
+ * @param element - The HTML element for which to get the Y translation. If not provided or null, returns 0.
299
+ * @returns {number} - The Y translation value of the element. Returns 0 if the element is not provided or if the transform style is "none".
300
+ */
301
+ const getElementYTranslation = (element) => {
302
+ if (!element) {
303
+ return 0;
304
+ }
305
+ const style = window.getComputedStyle(element);
306
+ const transform = style.transform;
307
+ if (transform === "none") {
308
+ return 0;
309
+ }
310
+ const matrix = new DOMMatrix(transform);
311
+ return matrix.m42;
312
+ };
313
+ /**
314
+ * Hook for handling swipe events on the drawer.
315
+ */
316
+ const useSwipeHandlers = ({ ref, closingThreshold, onCloseGesture, onOpenGesture }) => {
317
+ const [isDragging, setIsDragging] = useState(false);
318
+ const [dragDistance, setDragDistance] = useState(0);
319
+ const currentY = useRef(0);
320
+ const currentHeight = useRef(0);
321
+ const geometry = useGeometry(ref);
322
+ const handlers = useSwipeable({
323
+ onTouchStartOrOnMouseDown: () => {
324
+ const y = getElementYTranslation(ref.current);
325
+ const height = geometry.height;
326
+ currentY.current = y;
327
+ currentHeight.current = height;
328
+ setDragDistance(y);
329
+ setIsDragging(true);
330
+ },
331
+ onSwiping: (e) => {
332
+ const newY = currentY.current + e.deltaY;
333
+ if (newY >= 0) {
334
+ setDragDistance(newY);
335
+ }
336
+ },
337
+ onSwipedDown: (e) => {
338
+ const threshold = currentHeight.current * closingThreshold;
339
+ if (e.absY > threshold && onCloseGesture) {
340
+ onCloseGesture();
341
+ }
342
+ setIsDragging(false);
343
+ setDragDistance(0);
344
+ },
345
+ onSwipedUp: (e) => {
346
+ const threshold = currentHeight.current * closingThreshold;
347
+ if (e.absY > threshold && onOpenGesture) {
348
+ onOpenGesture();
349
+ }
350
+ setIsDragging(false);
351
+ setDragDistance(0);
352
+ },
353
+ onSwiped: () => void 0,
354
+ trackMouse: true,
355
+ trackTouch: true,
356
+ preventScrollOnSwipe: true,
357
+ });
358
+ return { handlers, isDragging, dragDistance };
359
+ };
360
+
361
+ /**
362
+ * DrawerPuller is a React component that renders a puller element for a swipeable drawer.
363
+ *
364
+ * @param {CommonProps} props - The props for the DrawerPuller component.
365
+ * @param {string} [props.className] - Additional class names to apply to the puller element.
366
+ * @param {Ref<HTMLDivElement>} ref - The ref to be forwarded to the root div element.
367
+ * @returns {JSX.Element} The rendered DrawerPuller component.
368
+ */
369
+ const DrawerPuller = forwardRef(({ className, ...props }, ref) => {
370
+ return (jsx("div", { className: cvaPuller({ className }), "data-testid": "drawer-puller", ...props, ref: ref, children: jsx("div", { className: cvaPullerIcon() }) }));
371
+ });
372
+ DrawerPuller.displayName = "DrawerPuller";
373
+ const cvaPuller = cvaMerge(["pt-2", "pb-4", "flex", "items-center", "justify-center"]);
374
+ const cvaPullerIcon = cvaMerge(["block", "h-1", "w-8", "rounded-full", "bg-gray-400"]);
375
+
376
+ const CLOSING_THRESHOLD = 0.15;
377
+ /**
378
+ *
379
+ * SwipeableDrawer is a component that wraps the Drawer component to add swipeable functionality.
380
+ * It uses swipe handlers to detect swipe gestures for opening and closing the drawer.
381
+ * The component manages its docked state based on the open prop and keepMountedWhenClosed prop.
382
+ * It also applies styles dynamically based on whether the drawer is being dragged.
383
+ */
384
+ const SwipeableDrawer = ({ open, onClose, onOpenGesture, children, keepMountedWhenClosed, className, position = "bottom", ...others }) => {
385
+ const drawerRefs = useRef(null);
386
+ const [isDocked, setIsDocked] = useState(keepMountedWhenClosed && !open);
387
+ const { handlers, isDragging, dragDistance } = useSwipeHandlers({
388
+ ref: drawerRefs,
389
+ closingThreshold: CLOSING_THRESHOLD,
390
+ onCloseGesture: onClose,
391
+ onOpenGesture,
392
+ });
393
+ const drawerStyle = useMemo(() => isDragging
394
+ ? {
395
+ transform: `translateY(${dragDistance}px)`,
396
+ transition: "none",
397
+ }
398
+ : {}, [isDragging, dragDistance]);
399
+ useEffect(() => {
400
+ if (!keepMountedWhenClosed) {
401
+ return;
402
+ }
403
+ if (isDocked && open) {
404
+ setIsDocked(false);
405
+ }
406
+ else if (!isDocked && !open) {
407
+ setIsDocked(true);
408
+ }
409
+ }, [open, isDocked, keepMountedWhenClosed]);
410
+ useEffect(() => {
411
+ var _a, _b;
412
+ if (drawerRefs.current) {
413
+ drawerRefs.current.style.transform = (_a = drawerStyle.transform) !== null && _a !== void 0 ? _a : "";
414
+ drawerRefs.current.style.transition = (_b = drawerStyle.transition) !== null && _b !== void 0 ? _b : "";
415
+ }
416
+ }, [drawerStyle, drawerRefs]);
417
+ return (jsxs(Drawer, { className: cvaSwipeableDrawer({ docked: isDocked, className }), "data-docked": isDocked, keepMountedWhenClosed: keepMountedWhenClosed, onClose: onClose, open: open, position: position, ref: drawerRefs, ...others, children: [jsx(DrawerPuller, { ...handlers }), children] }));
418
+ };
419
+ const cvaSwipeableDrawer = cvaMerge([], {
420
+ variants: {
421
+ docked: {
422
+ true: "translate-y-[calc(100%-30px)]",
423
+ false: "",
424
+ },
425
+ },
426
+ });
427
+
428
+ /*
429
+ * ----------------------------
430
+ * | SETUP TRANSLATIONS START |
431
+ * ----------------------------
432
+ * This import and function call is needed to register translations for this library.
433
+ * Do not remove this if this library has translations.
434
+ */
435
+ setupLibraryTranslations();
436
+
437
+ export { Drawer, DrawerToggle, SwipeableDrawer, TRANSITION_DURATION, cvaSwipeableDrawer };
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "@trackunit/react-drawer",
3
+ "version": "0.0.1",
4
+ "repository": "https://github.com/Trackunit/manager",
5
+ "license": "SEE LICENSE IN LICENSE.txt",
6
+ "engines": {
7
+ "node": ">=20.x"
8
+ },
9
+ "dependencies": {
10
+ "@trackunit/css-class-variance-utilities": "*",
11
+ "@trackunit/react-components": "*",
12
+ "@trackunit/i18n-library-translation": "*",
13
+ "@trackunit/ui-icons": "*",
14
+ "react": "18.3.1",
15
+ "react-swipeable": "^7.0.1",
16
+ "react-useportal": "1.0.18"
17
+ },
18
+ "module": "./index.esm.js",
19
+ "main": "./index.cjs.js",
20
+ "types": "./index.esm.d.ts"
21
+ }
@@ -0,0 +1,57 @@
1
+ import { CommonProps } from "@trackunit/react-components";
2
+ import type { DrawerPosition } from "../../types";
3
+ export declare const TRANSITION_DURATION = 100;
4
+ export interface DrawerRefsHandle {
5
+ dialogRef: React.RefObject<HTMLDivElement>;
6
+ dialogContentRef: React.RefObject<HTMLDivElement>;
7
+ }
8
+ export interface DrawerProps extends CommonProps {
9
+ /**
10
+ * Specifies whether the sidebar drawer is open or not.
11
+ */
12
+ open?: boolean;
13
+ /**
14
+ * The handler for closing the drawer. If not provided, the drawer will dock when closed.=
15
+ */
16
+ onClose?: () => void;
17
+ /**
18
+ * Whether the drawer needs an overlay or not. Without the overlay, user will have to handle mechanism for closing the drawer.
19
+ * Default is true.
20
+ */
21
+ hasOverlay?: boolean;
22
+ /**
23
+ * The position of the drawer.
24
+ */
25
+ position?: DrawerPosition;
26
+ /**
27
+ * The child node that will be rendered inside the drawer.
28
+ */
29
+ children?: React.ReactNode;
30
+ /**
31
+ * Determines whether the drawer component should remain mounted in the DOM when it is closed.
32
+ * If set to true, the drawer will not be unmounted when closed
33
+ * Default is false.
34
+ */
35
+ keepMountedWhenClosed?: boolean;
36
+ /**
37
+ * Whether to render the drawer in a portal or not.
38
+ * Default is false.
39
+ * If true, the drawer will be rendered in a portal at the end of the document.
40
+ * This is useful when the drawer needs to be rendered on top of other elements.
41
+ * For example, when the drawer is used with a map component.
42
+ */
43
+ renderInPortal?: boolean;
44
+ /**
45
+ * The class name for the drawer container.
46
+ */
47
+ containerClassName?: string;
48
+ }
49
+ /**
50
+ * Drawers components can be switched between open and closed states.
51
+ * They start closed but can be temporarily opened, appearing on top of other content until the user chooses a section.
52
+ * To close the drawer, users can either click outside of it or press the Esc key.
53
+ *
54
+ * @param {DrawerProps} props - The props for the Drawer component
55
+ * @returns {JSX.Element | null} Drawer component
56
+ */
57
+ export declare const Drawer: import("react").ForwardRefExoticComponent<DrawerProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,12 @@
1
+ import { Meta, StoryObj } from "@storybook/react";
2
+ import { Drawer } from "./Drawer";
3
+ type Story = StoryObj<typeof Drawer>;
4
+ declare const meta: Meta<typeof Drawer>;
5
+ export default meta;
6
+ export declare const packageName: () => import("react/jsx-runtime").JSX.Element;
7
+ export declare const Default: Story;
8
+ export declare const InPortal: Story;
9
+ export declare const Toggleable: Story;
10
+ export declare const WithoutOverlay: Story;
11
+ export declare const Swipeable: Story;
12
+ export declare const SwipeableDocked: Story;
@@ -0,0 +1,7 @@
1
+ export declare const cvaDrawer: (props?: ({
2
+ position?: "left" | "right" | "top" | "bottom" | null | undefined;
3
+ mode?: "open" | "closed" | null | undefined;
4
+ } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
5
+ export declare const cvaDrawerContent: (props?: ({
6
+ position?: "left" | "right" | "top" | "bottom" | null | undefined;
7
+ } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
@@ -0,0 +1,19 @@
1
+ import { type DrawerPosition } from "../../types";
2
+ interface DrawerToggleProps {
3
+ open: boolean;
4
+ onClick?: (event: React.MouseEvent) => void;
5
+ position: DrawerPosition;
6
+ }
7
+ /**
8
+ * DrawerToggle is a React functional component that returns a button with a chevron icon.
9
+ * The direction of the chevron changes depending on the state of the 'open' prop and
10
+ * the side the button is positioned ('position' prop).
11
+ * The button might be disabled based on the 'disableButton' prop.
12
+ *
13
+ * @param {object} props - The properties passed to the component
14
+ * @param {boolean} props.open - Indicates if the button is in "open" state
15
+ * @param {Function} [props.onClick] - Optional callback function for when the button is clicked
16
+ * @param {DrawerPosition} props.position - The position of the button relative to its container
17
+ */
18
+ export declare const DrawerToggle: ({ open, position, onClick }: DrawerToggleProps) => import("react/jsx-runtime").JSX.Element;
19
+ export {};
@@ -0,0 +1,14 @@
1
+ interface OverlayProps {
2
+ open: boolean;
3
+ onClose?: () => void;
4
+ }
5
+ /**
6
+ * Overlay Component
7
+ *
8
+ * @param {object} props - The Overlay component properties
9
+ * @param {boolean} props.open - Open status of the Overlay
10
+ * @param {Function} props.onClose - Callback function when Overlay is closed
11
+ * @returns {JSX.Element|null} The Overlay component
12
+ */
13
+ export declare const Overlay: ({ open, onClose }: OverlayProps) => JSX.Element | null;
14
+ export {};
@@ -0,0 +1,10 @@
1
+ import { CommonProps } from "@trackunit/react-components";
2
+ /**
3
+ * DrawerPuller is a React component that renders a puller element for a swipeable drawer.
4
+ *
5
+ * @param {CommonProps} props - The props for the DrawerPuller component.
6
+ * @param {string} [props.className] - Additional class names to apply to the puller element.
7
+ * @param {Ref<HTMLDivElement>} ref - The ref to be forwarded to the root div element.
8
+ * @returns {JSX.Element} The rendered DrawerPuller component.
9
+ */
10
+ export declare const DrawerPuller: import("react").ForwardRefExoticComponent<CommonProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,15 @@
1
+ import { type DrawerProps } from "../Drawer/Drawer";
2
+ export interface SwipeableDrawerProps extends DrawerProps {
3
+ onOpenGesture?: () => void;
4
+ }
5
+ /**
6
+ *
7
+ * SwipeableDrawer is a component that wraps the Drawer component to add swipeable functionality.
8
+ * It uses swipe handlers to detect swipe gestures for opening and closing the drawer.
9
+ * The component manages its docked state based on the open prop and keepMountedWhenClosed prop.
10
+ * It also applies styles dynamically based on whether the drawer is being dragged.
11
+ */
12
+ export declare const SwipeableDrawer: ({ open, onClose, onOpenGesture, children, keepMountedWhenClosed, className, position, ...others }: SwipeableDrawerProps) => import("react/jsx-runtime").JSX.Element;
13
+ export declare const cvaSwipeableDrawer: (props?: ({
14
+ docked?: boolean | null | undefined;
15
+ } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
@@ -0,0 +1,3 @@
1
+ export * from "./Drawer/Drawer";
2
+ export * from "./DrawerToggle/DrawerToggle";
3
+ export * from "./SwipeableDrawer/SwipeableDrawer";
@@ -0,0 +1 @@
1
+ export * from "./useSwipeHandlers";
@@ -0,0 +1,23 @@
1
+ import { type RefObject } from "react";
2
+ interface UseSwipeHandlersProps {
3
+ ref: RefObject<HTMLDivElement>;
4
+ closingThreshold: number;
5
+ onCloseGesture?: () => void;
6
+ onOpenGesture?: () => void;
7
+ }
8
+ /**
9
+ * Retrieves the Y-axis translation value of a given HTML element.
10
+ *
11
+ * @param element - The HTML element for which to get the Y translation. If not provided or null, returns 0.
12
+ * @returns {number} - The Y translation value of the element. Returns 0 if the element is not provided or if the transform style is "none".
13
+ */
14
+ export declare const getElementYTranslation: (element?: HTMLElement | null) => number;
15
+ /**
16
+ * Hook for handling swipe events on the drawer.
17
+ */
18
+ export declare const useSwipeHandlers: ({ ref, closingThreshold, onCloseGesture, onOpenGesture }: UseSwipeHandlersProps) => {
19
+ handlers: import("react-swipeable").SwipeableHandlers;
20
+ isDragging: boolean;
21
+ dragDistance: number;
22
+ };
23
+ export {};
package/src/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./components";
@@ -0,0 +1,33 @@
1
+ import { NamespaceTransProps, TransForLibs, TranslationResource } from "@trackunit/i18n-library-translation";
2
+ import defaultTranslations from "./locales/en/translation.json";
3
+ /** A type for all available translation keys in this library */
4
+ export type TranslationKeys = keyof typeof defaultTranslations;
5
+ /** The translation namespace for this library */
6
+ export declare const namespace = "react.react-drawer";
7
+ /**
8
+ * The TranslationResource for this Library.
9
+ * Holds lazy loaded imports for all languages supported by the library.
10
+ *
11
+ * This is used to register the translations for this library before initializing i18next.
12
+ */
13
+ export declare const translations: TranslationResource<TranslationKeys>;
14
+ /**
15
+ * Local useTranslation for this specific library
16
+ */
17
+ export declare const useTranslation: () => [TransForLibs<never>, import("i18next").i18n, boolean] & {
18
+ t: TransForLibs<never>;
19
+ i18n: import("i18next").i18n;
20
+ ready: boolean;
21
+ };
22
+ /**
23
+ * Type of the t function for the local useTranslation for this specific library
24
+ */
25
+ export type TranslationFunction = TransForLibs<TranslationKeys>;
26
+ /**
27
+ * Trans for this specific library.
28
+ */
29
+ export declare const Trans: (props: NamespaceTransProps<TranslationKeys>) => import("react/jsx-runtime").JSX.Element;
30
+ /**
31
+ * Registers the translations for this library
32
+ */
33
+ export declare const setupLibraryTranslations: () => void;
package/src/types.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export type DrawerPosition = "left" | "right" | "top" | "bottom";
2
+ export type DrawerMode = "closed" | "open";