@stackshift-ui/dialog 1.0.0-beta.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.
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@stackshift-ui/dialog",
3
+ "description": "A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.",
4
+ "version": "1.0.0-beta.1",
5
+ "private": false,
6
+ "sideEffects": false,
7
+ "main": "./dist/index.js",
8
+ "module": "./dist/index.mjs",
9
+ "types": "./dist/index.d.ts",
10
+ "files": [
11
+ "dist/**",
12
+ "src"
13
+ ],
14
+ "author": "WebriQ <info@webriq.com>",
15
+ "devDependencies": {
16
+ "@testing-library/jest-dom": "^6.5.0",
17
+ "@testing-library/react": "^16.0.1",
18
+ "@testing-library/user-event": "^14.6.1",
19
+ "@types/node": "^22.7.0",
20
+ "@types/react": "^18.3.9",
21
+ "@types/react-dom": "^18.3.0",
22
+ "@vitejs/plugin-react": "^4.3.1",
23
+ "@vitest/coverage-v8": "^2.1.1",
24
+ "esbuild-plugin-rdi": "^0.0.0",
25
+ "esbuild-plugin-react18": "^0.2.5",
26
+ "esbuild-plugin-react18-css": "^0.0.4",
27
+ "jsdom": "^25.0.1",
28
+ "react": "^18.3.1",
29
+ "react-dom": "^18.3.1",
30
+ "tsup": "^8.3.0",
31
+ "typescript": "^5.6.2",
32
+ "vite-tsconfig-paths": "^5.0.1",
33
+ "vitest": "^2.1.1",
34
+ "@stackshift-ui/eslint-config": "6.0.10",
35
+ "@stackshift-ui/typescript-config": "6.0.10"
36
+ },
37
+ "dependencies": {
38
+ "@radix-ui/react-dialog": "^1.1.14",
39
+ "classnames": "^2.5.1",
40
+ "lucide-react": "^0.468.0",
41
+ "@stackshift-ui/scripts": "6.1.0-beta.0",
42
+ "@stackshift-ui/system": "6.1.0-beta.0"
43
+ },
44
+ "peerDependencies": {
45
+ "@stackshift-ui/system": ">=6.1.0-beta.0",
46
+ "@types/react": "16.8 - 19",
47
+ "next": "10 - 14",
48
+ "react": "16.8 - 19",
49
+ "react-dom": "16.8 - 19"
50
+ },
51
+ "peerDependenciesMeta": {
52
+ "next": {
53
+ "optional": true
54
+ }
55
+ },
56
+ "scripts": {
57
+ "build": "tsup && tsc -p tsconfig-build.json",
58
+ "clean": "rm -rf dist",
59
+ "dev": "tsup --watch && tsc -p tsconfig-build.json -w",
60
+ "typecheck": "tsc --noEmit",
61
+ "lint": "eslint src/",
62
+ "test": "vitest run --coverage"
63
+ }
64
+ }
@@ -0,0 +1,88 @@
1
+ import { cleanup, render, screen, waitFor } from "@testing-library/react";
2
+ import userEvent from "@testing-library/user-event";
3
+ import { afterEach, describe, test } from "vitest";
4
+ import {
5
+ Dialog,
6
+ DialogContent,
7
+ DialogDescription,
8
+ DialogHeader,
9
+ DialogTitle,
10
+ DialogTrigger,
11
+ } from "./dialog";
12
+
13
+ describe.concurrent("dialog", () => {
14
+ afterEach(cleanup);
15
+
16
+ test("Dummy test - test if renders without errors", async ({ expect }) => {
17
+ const clx = "my-class";
18
+
19
+ const user = userEvent.setup();
20
+
21
+ const { unmount } = render(
22
+ <Dialog>
23
+ <DialogTrigger asChild data-testid="dialog-trigger-1">
24
+ <button>Open Dialog</button>
25
+ </DialogTrigger>
26
+ <DialogContent data-testid="dialog-container-1" className={clx}>
27
+ <DialogHeader>
28
+ <DialogTitle>Dialog Title</DialogTitle>
29
+ <DialogDescription>Dialog Description</DialogDescription>
30
+ </DialogHeader>
31
+ </DialogContent>
32
+ </Dialog>,
33
+ );
34
+
35
+ const trigger = screen.getByTestId("dialog-trigger-1");
36
+ expect(trigger).toBeInTheDocument();
37
+
38
+ await user.click(trigger);
39
+
40
+ const dialog = await screen.findByTestId("dialog-container-1");
41
+
42
+ expect(dialog).toBeInTheDocument();
43
+
44
+ unmount();
45
+ });
46
+
47
+ test("Common: Dialog - test if closes when clicking outside", async ({ expect }) => {
48
+ const user = userEvent.setup();
49
+ const { unmount } = render(
50
+ <>
51
+ <button data-testid="outside-button">Outside Button</button>
52
+ <Dialog>
53
+ <DialogTrigger asChild data-testid="dialog-trigger">
54
+ <button>Open Dialog</button>
55
+ </DialogTrigger>
56
+ <DialogContent data-testid="dialog-container">
57
+ <DialogHeader>
58
+ <DialogTitle>Dialog Title</DialogTitle>
59
+ <DialogDescription>Dialog Description</DialogDescription>
60
+ </DialogHeader>
61
+ </DialogContent>
62
+ </Dialog>
63
+ </>,
64
+ );
65
+
66
+ const outsideButton = screen.getByTestId("outside-button");
67
+ expect(outsideButton).toBeInTheDocument();
68
+
69
+ const trigger = screen.getByTestId("dialog-trigger");
70
+ expect(trigger).toBeInTheDocument();
71
+
72
+ await user.click(trigger);
73
+
74
+ await waitFor(() => {
75
+ const dialog = screen.getByTestId("dialog-container");
76
+ expect(dialog).toBeInTheDocument();
77
+ });
78
+
79
+ await user.click(outsideButton);
80
+
81
+ waitFor(() => {
82
+ const dialog = screen.queryByTestId("dialog-container");
83
+ expect(dialog).not.toBeInTheDocument();
84
+ });
85
+
86
+ unmount();
87
+ });
88
+ });
package/src/dialog.tsx ADDED
@@ -0,0 +1,172 @@
1
+ "use client";
2
+
3
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
4
+ import { XIcon } from "lucide-react";
5
+ import * as React from "react";
6
+
7
+ import { cn, DefaultComponent, useStackShiftUIComponents } from "@stackshift-ui/system";
8
+
9
+ const displayName = "Dialog";
10
+ const displayNameTrigger = "DialogTrigger";
11
+ const displayNamePortal = "DialogPortal";
12
+ const displayNameClose = "DialogClose";
13
+ const displayNameOverlay = "DialogOverlay";
14
+ const displayNameContent = "DialogContent";
15
+ const displayNameHeader = "DialogHeader";
16
+ const displayNameFooter = "DialogFooter";
17
+ const displayNameTitle = "DialogTitle";
18
+ const displayNameDescription = "DialogDescription";
19
+
20
+ function Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) {
21
+ const { [displayName]: Component = DefaultComponent } = useStackShiftUIComponents();
22
+
23
+ return <Component as={DialogPrimitive.Root} data-slot="dialog" {...props} />;
24
+ }
25
+ Dialog.displayName = displayName;
26
+
27
+ function DialogTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
28
+ const { [displayNameTrigger]: Component = DefaultComponent } = useStackShiftUIComponents();
29
+
30
+ return <Component as={DialogPrimitive.Trigger} data-slot="dialog-trigger" {...props} />;
31
+ }
32
+ DialogTrigger.displayName = displayNameTrigger;
33
+
34
+ function DialogPortal({ ...props }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
35
+ const { [displayNamePortal]: Component = DefaultComponent } = useStackShiftUIComponents();
36
+
37
+ return <Component as={DialogPrimitive.Portal} data-slot="dialog-portal" {...props} />;
38
+ }
39
+ DialogPortal.displayName = displayNamePortal;
40
+
41
+ function DialogClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>) {
42
+ const { [displayNameClose]: Component = DefaultComponent } = useStackShiftUIComponents();
43
+
44
+ return <Component as={DialogPrimitive.Close} data-slot="dialog-close" {...props} />;
45
+ }
46
+ DialogClose.displayName = displayNameClose;
47
+
48
+ function DialogOverlay({
49
+ className,
50
+ ...props
51
+ }: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
52
+ const { [displayNameOverlay]: Component = DefaultComponent } = useStackShiftUIComponents();
53
+
54
+ return (
55
+ <Component
56
+ as={DialogPrimitive.Overlay}
57
+ data-slot="dialog-overlay"
58
+ className={cn(
59
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
60
+ className,
61
+ )}
62
+ {...props}
63
+ />
64
+ );
65
+ }
66
+ DialogOverlay.displayName = displayNameOverlay;
67
+
68
+ function DialogContent({
69
+ className,
70
+ children,
71
+ showCloseButton = true,
72
+ ...props
73
+ }: React.ComponentProps<typeof DialogPrimitive.Content> & {
74
+ showCloseButton?: boolean;
75
+ }) {
76
+ const { [displayNameContent]: Component = DefaultComponent } = useStackShiftUIComponents();
77
+
78
+ return (
79
+ <DialogPortal data-slot="dialog-portal">
80
+ <DialogOverlay />
81
+ <Component
82
+ as={DialogPrimitive.Content}
83
+ data-slot="dialog-content"
84
+ className={cn(
85
+ "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
86
+ className,
87
+ )}
88
+ {...props}>
89
+ {children}
90
+ {showCloseButton && (
91
+ <DialogPrimitive.Close
92
+ data-slot="dialog-close"
93
+ className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4">
94
+ <XIcon />
95
+ <span className="sr-only">Close</span>
96
+ </DialogPrimitive.Close>
97
+ )}
98
+ </Component>
99
+ </DialogPortal>
100
+ );
101
+ }
102
+ DialogContent.displayName = displayNameContent;
103
+
104
+ function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
105
+ const { [displayNameHeader]: Component = DefaultComponent } = useStackShiftUIComponents();
106
+
107
+ return (
108
+ <Component
109
+ data-slot="dialog-header"
110
+ className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
111
+ {...props}
112
+ />
113
+ );
114
+ }
115
+ DialogHeader.displayName = displayNameHeader;
116
+
117
+ function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
118
+ const { [displayNameFooter]: Component = DefaultComponent } = useStackShiftUIComponents();
119
+
120
+ return (
121
+ <Component
122
+ data-slot="dialog-footer"
123
+ className={cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className)}
124
+ {...props}
125
+ />
126
+ );
127
+ }
128
+ DialogFooter.displayName = displayNameFooter;
129
+
130
+ function DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) {
131
+ const { [displayNameTitle]: Component = DefaultComponent } = useStackShiftUIComponents();
132
+
133
+ return (
134
+ <Component
135
+ as={DialogPrimitive.Title}
136
+ data-slot="dialog-title"
137
+ className={cn("text-lg leading-none font-semibold", className)}
138
+ {...props}
139
+ />
140
+ );
141
+ }
142
+ DialogTitle.displayName = displayNameTitle;
143
+
144
+ function DialogDescription({
145
+ className,
146
+ ...props
147
+ }: React.ComponentProps<typeof DialogPrimitive.Description>) {
148
+ const { [displayNameDescription]: Component = DefaultComponent } = useStackShiftUIComponents();
149
+
150
+ return (
151
+ <Component
152
+ as={DialogPrimitive.Description}
153
+ data-slot="dialog-description"
154
+ className={cn("text-muted-foreground text-sm", className)}
155
+ {...props}
156
+ />
157
+ );
158
+ }
159
+ DialogDescription.displayName = displayNameDescription;
160
+
161
+ export {
162
+ Dialog,
163
+ DialogClose,
164
+ DialogContent,
165
+ DialogDescription,
166
+ DialogFooter,
167
+ DialogHeader,
168
+ DialogOverlay,
169
+ DialogPortal,
170
+ DialogTitle,
171
+ DialogTrigger,
172
+ };
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ "use client";
2
+
3
+ // component exports
4
+ export * from "./dialog";
@@ -0,0 +1,4 @@
1
+ import '@testing-library/jest-dom';
2
+
3
+ export { };
4
+