warqadui 0.0.8 → 0.0.11
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/{packages/ui/dist → dist}/index.d.mts +100 -12
- package/{packages/ui/dist → dist}/index.d.ts +100 -12
- package/dist/index.js +3276 -0
- package/dist/index.mjs +3237 -0
- package/dist/styles.js +26 -0
- package/dist/styles.mjs +24 -0
- package/package.json +60 -10
- package/.vscode/settings.json +0 -3
- package/apps/dev-app/.env +0 -1
- package/apps/dev-app/errors.log +0 -0
- package/apps/dev-app/index.html +0 -12
- package/apps/dev-app/node_modules/.vite/deps/@tanstack_react-table.js +0 -3254
- package/apps/dev-app/node_modules/.vite/deps/@tanstack_react-table.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/_metadata.json +0 -166
- package/apps/dev-app/node_modules/.vite/deps/antd.js +0 -108982
- package/apps/dev-app/node_modules/.vite/deps/antd.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/axios.js +0 -2751
- package/apps/dev-app/node_modules/.vite/deps/axios.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/chunk-5OG7DCD7.js +0 -41
- package/apps/dev-app/node_modules/.vite/deps/chunk-5OG7DCD7.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/chunk-DC5AMYBS.js +0 -39
- package/apps/dev-app/node_modules/.vite/deps/chunk-DC5AMYBS.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/chunk-DKXRQMOD.js +0 -135
- package/apps/dev-app/node_modules/.vite/deps/chunk-DKXRQMOD.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/chunk-EL47BWQR.js +0 -37
- package/apps/dev-app/node_modules/.vite/deps/chunk-EL47BWQR.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/chunk-HHL3MHGV.js +0 -288
- package/apps/dev-app/node_modules/.vite/deps/chunk-HHL3MHGV.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/chunk-IGGUWUPT.js +0 -60
- package/apps/dev-app/node_modules/.vite/deps/chunk-IGGUWUPT.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/chunk-IGXZPJXT.js +0 -928
- package/apps/dev-app/node_modules/.vite/deps/chunk-IGXZPJXT.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/chunk-L2GCM37S.js +0 -21628
- package/apps/dev-app/node_modules/.vite/deps/chunk-L2GCM37S.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/chunk-M7DZDBHW.js +0 -14
- package/apps/dev-app/node_modules/.vite/deps/chunk-M7DZDBHW.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/chunk-S54SBVCU.js +0 -1906
- package/apps/dev-app/node_modules/.vite/deps/chunk-S54SBVCU.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/chunk-WFNHCR67.js +0 -21
- package/apps/dev-app/node_modules/.vite/deps/chunk-WFNHCR67.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/clsx.js +0 -10
- package/apps/dev-app/node_modules/.vite/deps/clsx.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/dayjs.js +0 -6
- package/apps/dev-app/node_modules/.vite/deps/dayjs.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/dayjs_plugin_customParseFormat.js +0 -6
- package/apps/dev-app/node_modules/.vite/deps/dayjs_plugin_customParseFormat.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/framer-motion.js +0 -12388
- package/apps/dev-app/node_modules/.vite/deps/framer-motion.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/html2canvas-pro.js +0 -9713
- package/apps/dev-app/node_modules/.vite/deps/html2canvas-pro.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/html2canvas.esm-IYRWPPEI.js +0 -7808
- package/apps/dev-app/node_modules/.vite/deps/html2canvas.esm-IYRWPPEI.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/index.es-3WTXOFZ2.js +0 -10392
- package/apps/dev-app/node_modules/.vite/deps/index.es-3WTXOFZ2.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/jspdf.js +0 -14806
- package/apps/dev-app/node_modules/.vite/deps/jspdf.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/lucide-react.js +0 -31586
- package/apps/dev-app/node_modules/.vite/deps/lucide-react.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/package.json +0 -3
- package/apps/dev-app/node_modules/.vite/deps/purify.es-JNLDEIMX.js +0 -1029
- package/apps/dev-app/node_modules/.vite/deps/purify.es-JNLDEIMX.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/react-dom.js +0 -7
- package/apps/dev-app/node_modules/.vite/deps/react-dom.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/react-dom_client.js +0 -8
- package/apps/dev-app/node_modules/.vite/deps/react-dom_client.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/react-hook-form.js +0 -2233
- package/apps/dev-app/node_modules/.vite/deps/react-hook-form.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/react-phone-number-input.js +0 -9307
- package/apps/dev-app/node_modules/.vite/deps/react-phone-number-input.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/react-router-dom.js +0 -14234
- package/apps/dev-app/node_modules/.vite/deps/react-router-dom.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/react.js +0 -6
- package/apps/dev-app/node_modules/.vite/deps/react.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/react_jsx-dev-runtime.js +0 -913
- package/apps/dev-app/node_modules/.vite/deps/react_jsx-dev-runtime.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/react_jsx-runtime.js +0 -7
- package/apps/dev-app/node_modules/.vite/deps/react_jsx-runtime.js.map +0 -7
- package/apps/dev-app/node_modules/.vite/deps/tailwind-merge.js +0 -2534
- package/apps/dev-app/node_modules/.vite/deps/tailwind-merge.js.map +0 -7
- package/apps/dev-app/node_modules/tailwindcss/LICENSE +0 -21
- package/apps/dev-app/node_modules/tailwindcss/README.md +0 -36
- package/apps/dev-app/node_modules/tailwindcss/dist/chunk-L5IEUH3R.mjs +0 -38
- package/apps/dev-app/node_modules/tailwindcss/dist/chunk-UWKE2Z6N.mjs +0 -1
- package/apps/dev-app/node_modules/tailwindcss/dist/chunk-X4GG3EDV.mjs +0 -1
- package/apps/dev-app/node_modules/tailwindcss/dist/colors-C__qRT83.d.ts +0 -347
- package/apps/dev-app/node_modules/tailwindcss/dist/colors.d.mts +0 -347
- package/apps/dev-app/node_modules/tailwindcss/dist/colors.d.ts +0 -5
- package/apps/dev-app/node_modules/tailwindcss/dist/colors.js +0 -1
- package/apps/dev-app/node_modules/tailwindcss/dist/colors.mjs +0 -1
- package/apps/dev-app/node_modules/tailwindcss/dist/default-theme.d.mts +0 -1199
- package/apps/dev-app/node_modules/tailwindcss/dist/default-theme.d.ts +0 -1199
- package/apps/dev-app/node_modules/tailwindcss/dist/default-theme.js +0 -1
- package/apps/dev-app/node_modules/tailwindcss/dist/default-theme.mjs +0 -1
- package/apps/dev-app/node_modules/tailwindcss/dist/flatten-color-palette.d.mts +0 -6
- package/apps/dev-app/node_modules/tailwindcss/dist/flatten-color-palette.d.ts +0 -6
- package/apps/dev-app/node_modules/tailwindcss/dist/flatten-color-palette.js +0 -3
- package/apps/dev-app/node_modules/tailwindcss/dist/flatten-color-palette.mjs +0 -1
- package/apps/dev-app/node_modules/tailwindcss/dist/lib.d.mts +0 -378
- package/apps/dev-app/node_modules/tailwindcss/dist/lib.d.ts +0 -3
- package/apps/dev-app/node_modules/tailwindcss/dist/lib.js +0 -38
- package/apps/dev-app/node_modules/tailwindcss/dist/lib.mjs +0 -1
- package/apps/dev-app/node_modules/tailwindcss/dist/plugin.d.mts +0 -11
- package/apps/dev-app/node_modules/tailwindcss/dist/plugin.d.ts +0 -134
- package/apps/dev-app/node_modules/tailwindcss/dist/plugin.js +0 -1
- package/apps/dev-app/node_modules/tailwindcss/dist/plugin.mjs +0 -1
- package/apps/dev-app/node_modules/tailwindcss/dist/resolve-config-B4yBzhca.d.ts +0 -29
- package/apps/dev-app/node_modules/tailwindcss/dist/resolve-config-QUZ9b-Gn.d.mts +0 -190
- package/apps/dev-app/node_modules/tailwindcss/dist/types-CJYAW1ql.d.mts +0 -128
- package/apps/dev-app/node_modules/tailwindcss/index.css +0 -944
- package/apps/dev-app/node_modules/tailwindcss/package.json +0 -89
- package/apps/dev-app/node_modules/tailwindcss/preflight.css +0 -393
- package/apps/dev-app/node_modules/tailwindcss/theme.css +0 -510
- package/apps/dev-app/node_modules/tailwindcss/utilities.css +0 -1
- package/apps/dev-app/package.json +0 -34
- package/apps/dev-app/src/App.tsx +0 -74
- package/apps/dev-app/src/index.css +0 -18
- package/apps/dev-app/src/main.tsx +0 -18
- package/apps/dev-app/src/pages/Buttons.tsx +0 -122
- package/apps/dev-app/src/pages/DataTable.tsx +0 -208
- package/apps/dev-app/src/pages/Fields.tsx +0 -342
- package/apps/dev-app/src/pages/Modals.tsx +0 -151
- package/apps/dev-app/src/pages/Spins.tsx +0 -161
- package/apps/dev-app/ts_errors.txt +0 -0
- package/apps/dev-app/tsconfig.json +0 -25
- package/apps/dev-app/tsconfig.node.json +0 -10
- package/apps/dev-app/vite.config.ts +0 -11
- package/packages/ui/dist/index.js +0 -2296
- package/packages/ui/dist/index.mjs +0 -2249
- package/packages/ui/dist/styles.js +0 -26
- package/packages/ui/dist/styles.mjs +0 -24
- package/packages/ui/log.txt +0 -0
- package/packages/ui/package.json +0 -70
- package/packages/ui/postcss.config.js +0 -6
- package/packages/ui/src/components/Button.tsx +0 -85
- package/packages/ui/src/components/Card.tsx +0 -97
- package/packages/ui/src/components/CodeBlock.tsx +0 -53
- package/packages/ui/src/components/DashboardLayout.tsx +0 -442
- package/packages/ui/src/components/Fields/Input.tsx +0 -191
- package/packages/ui/src/components/Fields/PhoneInput.tsx +0 -134
- package/packages/ui/src/components/Fields/date.tsx +0 -165
- package/packages/ui/src/components/Fields/index.tsx +0 -17
- package/packages/ui/src/components/Fields/searchApi.tsx +0 -479
- package/packages/ui/src/components/Fields/select.tsx +0 -131
- package/packages/ui/src/components/Fields/textArea.tsx +0 -121
- package/packages/ui/src/components/LoadingBox.tsx +0 -11
- package/packages/ui/src/components/PageHeader.tsx +0 -34
- package/packages/ui/src/components/ThemeToggle.tsx +0 -35
- package/packages/ui/src/components/modal/Modal.tsx +0 -81
- package/packages/ui/src/components/spins/ClassicSpin.tsx +0 -18
- package/packages/ui/src/components/spins/LoadingSpin.tsx +0 -45
- package/packages/ui/src/components/spins/OverlaySpin.tsx +0 -10
- package/packages/ui/src/components/spins/index.tsx +0 -13
- package/packages/ui/src/components/tables/DataTable.tsx +0 -261
- package/packages/ui/src/components/tables/index.ts +0 -1
- package/packages/ui/src/hooks/Fetches/useApis.tsx +0 -197
- package/packages/ui/src/hooks/ThemeContext.tsx +0 -56
- package/packages/ui/src/hooks/useModal.tsx +0 -38
- package/packages/ui/src/hooks/useTheme.ts +0 -34
- package/packages/ui/src/index.ts +0 -24
- package/packages/ui/src/providers/WarqadProvider.tsx +0 -69
- package/packages/ui/src/styles.css +0 -26
- package/packages/ui/src/utils/cn.ts +0 -6
- package/packages/ui/src/utils/pdf.ts +0 -171
- package/packages/ui/tailwind.config.js +0 -13
- package/packages/ui/tsconfig.json +0 -17
- package/packages/ui/warqad-ui-0.0.1.tgz +0 -0
- package/packages/ui/warqadui-0.0.3.tgz +0 -0
- package/warqad-ui-0.0.1.tgz +0 -0
- /package/{packages/ui/dist → dist}/styles.d.mts +0 -0
- /package/{packages/ui/dist → dist}/styles.d.ts +0 -0
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { forwardRef, useState } from "react";
|
|
2
|
-
import { useWarqadConfig } from "../../providers/WarqadProvider";
|
|
3
|
-
import {
|
|
4
|
-
Controller,
|
|
5
|
-
type FieldValues,
|
|
6
|
-
type Path,
|
|
7
|
-
type UseFormReturn,
|
|
8
|
-
} from "react-hook-form";
|
|
9
|
-
|
|
10
|
-
export interface TextareaProps<T extends FieldValues> extends Omit<
|
|
11
|
-
React.TextareaHTMLAttributes<HTMLTextAreaElement>,
|
|
12
|
-
"name" | "form"
|
|
13
|
-
> {
|
|
14
|
-
label: string;
|
|
15
|
-
error?: string;
|
|
16
|
-
containerClassName?: string;
|
|
17
|
-
name?: Path<T>;
|
|
18
|
-
form?: UseFormReturn<T>;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export const Textarea = forwardRef(
|
|
22
|
-
<T extends FieldValues>(
|
|
23
|
-
{
|
|
24
|
-
label,
|
|
25
|
-
error,
|
|
26
|
-
containerClassName = "",
|
|
27
|
-
name,
|
|
28
|
-
form,
|
|
29
|
-
onFocus,
|
|
30
|
-
onBlur,
|
|
31
|
-
className = "",
|
|
32
|
-
...props
|
|
33
|
-
}: TextareaProps<T>,
|
|
34
|
-
ref: React.ForwardedRef<HTMLTextAreaElement>,
|
|
35
|
-
) => {
|
|
36
|
-
const [isFocused, setIsFocused] = useState(false);
|
|
37
|
-
const { theme } = useWarqadConfig();
|
|
38
|
-
const primaryColor = theme?.primaryColor;
|
|
39
|
-
|
|
40
|
-
let message = error;
|
|
41
|
-
if (form && name) {
|
|
42
|
-
const {
|
|
43
|
-
formState: { errors },
|
|
44
|
-
} = form;
|
|
45
|
-
const errorObj = name
|
|
46
|
-
.split(".")
|
|
47
|
-
.reduce((acc: any, current: string) => acc?.[current], errors);
|
|
48
|
-
message = (errorObj as any)?.message;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const renderInput = (
|
|
52
|
-
inputProps: any,
|
|
53
|
-
ref: React.Ref<HTMLTextAreaElement> | undefined,
|
|
54
|
-
) => (
|
|
55
|
-
<div className={`space-y-2 group ${containerClassName}`}>
|
|
56
|
-
<label
|
|
57
|
-
htmlFor={props.id}
|
|
58
|
-
className={`block capitalize text-xs font-medium transition-colors duration-200`}
|
|
59
|
-
style={{ color: isFocused ? primaryColor : undefined }}
|
|
60
|
-
>
|
|
61
|
-
{label}
|
|
62
|
-
{props.required && <span className="text-red-500 ml-1">*</span>}
|
|
63
|
-
</label>
|
|
64
|
-
<div className="relative">
|
|
65
|
-
<textarea
|
|
66
|
-
ref={ref}
|
|
67
|
-
onFocus={(e) => {
|
|
68
|
-
setIsFocused(true);
|
|
69
|
-
onFocus?.(e);
|
|
70
|
-
}}
|
|
71
|
-
onBlur={(e) => {
|
|
72
|
-
setIsFocused(false);
|
|
73
|
-
onBlur?.(e);
|
|
74
|
-
}}
|
|
75
|
-
className={`block w-full px-3 py-3 rounded-lg border-gray-200 dark:border-zinc-800 bg-gray-50 dark:bg-zinc-900/50 text-gray-900 dark:text-white placeholder-gray-400 focus:bg-white dark:focus:bg-zinc-900 outline-none transition-all duration-200 border min-h-[100px] resize-none text-sm ${className}`}
|
|
76
|
-
style={{
|
|
77
|
-
borderColor: isFocused ? primaryColor : undefined,
|
|
78
|
-
boxShadow: isFocused
|
|
79
|
-
? `${primaryColor}33 0px 0px 0px 2px`
|
|
80
|
-
: undefined,
|
|
81
|
-
}}
|
|
82
|
-
{...props}
|
|
83
|
-
{...inputProps}
|
|
84
|
-
/>
|
|
85
|
-
</div>
|
|
86
|
-
{message && (
|
|
87
|
-
<p className="text-sm text-red-600 dark:text-red-400">{message}</p>
|
|
88
|
-
)}
|
|
89
|
-
</div>
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
if (form && name) {
|
|
93
|
-
return (
|
|
94
|
-
<Controller
|
|
95
|
-
control={form.control}
|
|
96
|
-
name={name}
|
|
97
|
-
render={({ field: { onChange, value, ref: fieldRef, onBlur } }) =>
|
|
98
|
-
renderInput(
|
|
99
|
-
{
|
|
100
|
-
value: value || "", // Ensure controlled input doesn't warn about uncontrolled
|
|
101
|
-
onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
102
|
-
onChange(e);
|
|
103
|
-
props.onChange?.(e);
|
|
104
|
-
},
|
|
105
|
-
onBlur: () => {
|
|
106
|
-
onBlur();
|
|
107
|
-
// props.onBlur?.(undefined as any);
|
|
108
|
-
},
|
|
109
|
-
},
|
|
110
|
-
fieldRef,
|
|
111
|
-
)
|
|
112
|
-
}
|
|
113
|
-
/>
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
return renderInput({}, ref);
|
|
118
|
-
},
|
|
119
|
-
) as <T extends FieldValues>(
|
|
120
|
-
props: TextareaProps<T> & { ref?: React.ForwardedRef<HTMLTextAreaElement> },
|
|
121
|
-
) => React.ReactElement;
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { cn } from "../utils/cn";
|
|
3
|
-
|
|
4
|
-
interface PageHeaderProps {
|
|
5
|
-
title: string;
|
|
6
|
-
description?: string;
|
|
7
|
-
children?: React.ReactNode;
|
|
8
|
-
className?: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const PageHeader = ({
|
|
12
|
-
title,
|
|
13
|
-
description,
|
|
14
|
-
children,
|
|
15
|
-
className,
|
|
16
|
-
}: PageHeaderProps) => {
|
|
17
|
-
return (
|
|
18
|
-
<div className={cn("space-y-2 mb-8", className)}>
|
|
19
|
-
<div className="flex items-center justify-between">
|
|
20
|
-
<h1 className="text-3xl font-bold text-gray-900 dark:text-white tracking-tight">
|
|
21
|
-
{title}
|
|
22
|
-
</h1>
|
|
23
|
-
{children}
|
|
24
|
-
</div>
|
|
25
|
-
{description && (
|
|
26
|
-
<p className="text-gray-500 dark:text-gray-400 max-w-2xl leading-relaxed">
|
|
27
|
-
{description}
|
|
28
|
-
</p>
|
|
29
|
-
)}
|
|
30
|
-
</div>
|
|
31
|
-
);
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export default PageHeader;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { Sun, Moon } from "lucide-react";
|
|
3
|
-
import { cn } from "../utils/cn";
|
|
4
|
-
import { useTheme } from "../hooks/ThemeContext";
|
|
5
|
-
|
|
6
|
-
export const ThemeToggle: React.FC<{ className?: string }> = ({
|
|
7
|
-
className,
|
|
8
|
-
}) => {
|
|
9
|
-
const { isDarkMode, toggleTheme } = useTheme();
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<button
|
|
13
|
-
onClick={toggleTheme}
|
|
14
|
-
className={cn(
|
|
15
|
-
"p-2 rounded-lg transition-all duration-200",
|
|
16
|
-
"text-slate-500 hover:text-blue-600 hover:bg-slate-100",
|
|
17
|
-
"dark:text-yellow-400 dark:hover:text-yellow-300 dark:hover:bg-slate-800",
|
|
18
|
-
className,
|
|
19
|
-
)}
|
|
20
|
-
aria-label="Toggle dark mode"
|
|
21
|
-
>
|
|
22
|
-
{isDarkMode ? (
|
|
23
|
-
<Sun
|
|
24
|
-
size={20}
|
|
25
|
-
className="stroke-2 transition-transform duration-300 rotate-0 scale-100"
|
|
26
|
-
/>
|
|
27
|
-
) : (
|
|
28
|
-
<Moon
|
|
29
|
-
size={20}
|
|
30
|
-
className="stroke-2 transition-transform duration-300 rotate-0 scale-100"
|
|
31
|
-
/>
|
|
32
|
-
)}
|
|
33
|
-
</button>
|
|
34
|
-
);
|
|
35
|
-
};
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { X } from "lucide-react";
|
|
3
|
-
import { motion, AnimatePresence } from "framer-motion";
|
|
4
|
-
import { ClassicSpin } from "../spins";
|
|
5
|
-
|
|
6
|
-
export interface ModalProps {
|
|
7
|
-
isOpen: boolean;
|
|
8
|
-
onClose: () => void;
|
|
9
|
-
title: string;
|
|
10
|
-
children: React.ReactNode;
|
|
11
|
-
isLoading?: boolean;
|
|
12
|
-
width?: number;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export const Modal: React.FC<ModalProps> = ({
|
|
16
|
-
isOpen,
|
|
17
|
-
onClose,
|
|
18
|
-
title,
|
|
19
|
-
children,
|
|
20
|
-
isLoading = false,
|
|
21
|
-
width = 500,
|
|
22
|
-
}) => {
|
|
23
|
-
return (
|
|
24
|
-
<AnimatePresence>
|
|
25
|
-
{isOpen && (
|
|
26
|
-
<div className="fixed inset-0 z-[1000] flex items-center justify-center p-4 sm:p-6">
|
|
27
|
-
{/* Backdrop */}
|
|
28
|
-
<motion.div
|
|
29
|
-
initial={{ opacity: 0 }}
|
|
30
|
-
animate={{ opacity: 1 }}
|
|
31
|
-
exit={{ opacity: 0 }}
|
|
32
|
-
onClick={isLoading ? undefined : onClose}
|
|
33
|
-
className="fixed inset-0 bg-black/40 backdrop-blur-sm transition-all"
|
|
34
|
-
/>
|
|
35
|
-
|
|
36
|
-
{/* Modal Content */}
|
|
37
|
-
<motion.div
|
|
38
|
-
initial={{ opacity: 0, scale: 0.95, y: 10 }}
|
|
39
|
-
animate={{ opacity: 1, scale: 1, y: 0 }}
|
|
40
|
-
exit={{ opacity: 0, scale: 0.95, y: 10 }}
|
|
41
|
-
transition={{ type: "spring", duration: 0.3 }}
|
|
42
|
-
style={{ maxWidth: width }}
|
|
43
|
-
className="w-full bg-white dark:bg-zinc-900 rounded-[2rem] shadow-2xl border border-gray-200 dark:border-white/5 overflow-hidden relative z-10 flex flex-col max-h-[90vh]"
|
|
44
|
-
>
|
|
45
|
-
{/* Header */}
|
|
46
|
-
<div className="px-8 py-5 border-b border-gray-100 dark:border-white/5 flex items-center justify-between bg-white/50 dark:bg-zinc-900/50 backdrop-blur-xl sticky top-0 z-20">
|
|
47
|
-
<h3 className="text-xl font-bold text-gray-900 dark:text-white tracking-tight">
|
|
48
|
-
{title}
|
|
49
|
-
</h3>
|
|
50
|
-
<button
|
|
51
|
-
onClick={onClose}
|
|
52
|
-
disabled={isLoading}
|
|
53
|
-
className="p-2 -mr-2 rounded-full text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-100 dark:hover:bg-white/5 transition-all disabled:opacity-50"
|
|
54
|
-
>
|
|
55
|
-
<X size={20} />
|
|
56
|
-
</button>
|
|
57
|
-
</div>
|
|
58
|
-
|
|
59
|
-
{/* Glowing Top accent */}
|
|
60
|
-
<div className="absolute top-0 left-0 right-0 h-1 bg-gradient-to-r from-blue-500 via-indigo-600 to-purple-500 opacity-60" />
|
|
61
|
-
|
|
62
|
-
{/* Body */}
|
|
63
|
-
<div className="p-8 overflow-y-auto relative flex-1">
|
|
64
|
-
{/* Loading Overlay */}
|
|
65
|
-
{isLoading && <ClassicSpin />}
|
|
66
|
-
<div
|
|
67
|
-
className={
|
|
68
|
-
isLoading
|
|
69
|
-
? "opacity-20 blur-sm transition-all"
|
|
70
|
-
: "transition-all"
|
|
71
|
-
}
|
|
72
|
-
>
|
|
73
|
-
{children}
|
|
74
|
-
</div>
|
|
75
|
-
</div>
|
|
76
|
-
</motion.div>
|
|
77
|
-
</div>
|
|
78
|
-
)}
|
|
79
|
-
</AnimatePresence>
|
|
80
|
-
);
|
|
81
|
-
};
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { Loader2 } from "lucide-react";
|
|
3
|
-
|
|
4
|
-
export const ClassicSpin = ({ msg = "Please wait..." }: { msg?: string }) => {
|
|
5
|
-
return (
|
|
6
|
-
<div className="absolute inset-0 z-50 flex flex-col items-center justify-center bg-white/30 dark:bg-zinc-900/30 backdrop-blur-[0.5px] transition-all duration-200">
|
|
7
|
-
<div className="flex flex-col items-center justify-center p-6 bg-white dark:bg-zinc-800 rounded-2xl shadow-2xl border border-gray-100 dark:border-zinc-700 animate-in zoom-in-95 duration-200">
|
|
8
|
-
<div className="relative">
|
|
9
|
-
<div className="absolute inset-0 bg-indigo-500 blur-lg opacity-20 animate-pulse"></div>
|
|
10
|
-
<Loader2 className="h-8 w-8 animate-spin text-indigo-600 dark:text-indigo-400 relative z-10" />
|
|
11
|
-
</div>
|
|
12
|
-
<p className="mt-3 text-sm font-medium text-gray-900 dark:text-white">
|
|
13
|
-
{msg}
|
|
14
|
-
</p>
|
|
15
|
-
</div>
|
|
16
|
-
</div>
|
|
17
|
-
);
|
|
18
|
-
};
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { cn } from "../../utils/cn";
|
|
3
|
-
|
|
4
|
-
export interface LoadingSpinProps {
|
|
5
|
-
className?: string;
|
|
6
|
-
size?: "sm" | "md" | "lg";
|
|
7
|
-
color?: string;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const LoadingSpin = ({
|
|
11
|
-
className,
|
|
12
|
-
size = "md",
|
|
13
|
-
color = "text-current",
|
|
14
|
-
}: LoadingSpinProps) => {
|
|
15
|
-
const sizeClasses = {
|
|
16
|
-
sm: "h-4 w-4",
|
|
17
|
-
md: "h-6 w-6",
|
|
18
|
-
lg: "h-10 w-10",
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
return (
|
|
22
|
-
<svg
|
|
23
|
-
className={cn("animate-spin", sizeClasses[size], color, className)}
|
|
24
|
-
fill="none"
|
|
25
|
-
viewBox="0 0 24 24"
|
|
26
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
27
|
-
>
|
|
28
|
-
<circle
|
|
29
|
-
className="opacity-25"
|
|
30
|
-
cx="12"
|
|
31
|
-
cy="12"
|
|
32
|
-
r="10"
|
|
33
|
-
stroke="currentColor"
|
|
34
|
-
strokeWidth="4"
|
|
35
|
-
/>
|
|
36
|
-
<path
|
|
37
|
-
className="opacity-75"
|
|
38
|
-
fill="currentColor"
|
|
39
|
-
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
40
|
-
/>
|
|
41
|
-
</svg>
|
|
42
|
-
);
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export default LoadingSpin;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export const OverlaySpin = ({ msg = "Processing..." }: { msg?: string }) => (
|
|
2
|
-
<div className="absolute inset-0 bg-white/50 dark:bg-black/50 backdrop-blur-[1px] z-50 flex items-center justify-center rounded-xl transition-all duration-300">
|
|
3
|
-
<div className="flex flex-col items-center gap-2 bg-white dark:bg-zinc-800 p-4 rounded-xl shadow-xl border border-gray-100 dark:border-zinc-700">
|
|
4
|
-
<div className="w-6 h-6 border-2 border-blue-600 border-t-transparent rounded-full animate-spin"></div>
|
|
5
|
-
<span className="text-xs font-medium text-gray-500 animate-pulse">
|
|
6
|
-
{msg}
|
|
7
|
-
</span>
|
|
8
|
-
</div>
|
|
9
|
-
</div>
|
|
10
|
-
);
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { ClassicSpin } from "./ClassicSpin";
|
|
2
|
-
import { OverlaySpin } from "./OverlaySpin";
|
|
3
|
-
import { LoadingSpin } from "./LoadingSpin";
|
|
4
|
-
|
|
5
|
-
export { ClassicSpin, OverlaySpin, LoadingSpin };
|
|
6
|
-
|
|
7
|
-
const Spins = {
|
|
8
|
-
ClassicSpin,
|
|
9
|
-
OverlaySpin,
|
|
10
|
-
LoadingSpin,
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export default Spins;
|
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
import { useState, useMemo, useEffect } from "react";
|
|
2
|
-
import {
|
|
3
|
-
useReactTable,
|
|
4
|
-
getCoreRowModel,
|
|
5
|
-
getPaginationRowModel,
|
|
6
|
-
getSortedRowModel,
|
|
7
|
-
getFilteredRowModel,
|
|
8
|
-
flexRender,
|
|
9
|
-
type ColumnDef,
|
|
10
|
-
type SortingState,
|
|
11
|
-
type ColumnFiltersState,
|
|
12
|
-
type VisibilityState,
|
|
13
|
-
} from "@tanstack/react-table";
|
|
14
|
-
import { ChevronDown, Search } from "lucide-react";
|
|
15
|
-
import Fields from "../Fields";
|
|
16
|
-
import { useWarqadConfig } from "../../providers/WarqadProvider";
|
|
17
|
-
|
|
18
|
-
interface DataTableProps<TData, TValue> {
|
|
19
|
-
columns: ColumnDef<TData, TValue>[];
|
|
20
|
-
data: TData[];
|
|
21
|
-
isLoading?: boolean;
|
|
22
|
-
pageRows?: number;
|
|
23
|
-
searchPlaceholder?: string;
|
|
24
|
-
className?: string;
|
|
25
|
-
onChange?: (state: {
|
|
26
|
-
pagination: {
|
|
27
|
-
pageIndex: number;
|
|
28
|
-
pageSize: number;
|
|
29
|
-
pageCount: number;
|
|
30
|
-
};
|
|
31
|
-
sorting: SortingState;
|
|
32
|
-
columnFilters: ColumnFiltersState;
|
|
33
|
-
globalFilter: string;
|
|
34
|
-
selectedRows: TData[];
|
|
35
|
-
filteredData: TData[];
|
|
36
|
-
}) => void;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function DataTable<TData, TValue>({
|
|
40
|
-
columns,
|
|
41
|
-
data,
|
|
42
|
-
isLoading = false,
|
|
43
|
-
pageRows,
|
|
44
|
-
searchPlaceholder = "Search all columns...",
|
|
45
|
-
className = "",
|
|
46
|
-
onChange,
|
|
47
|
-
}: DataTableProps<TData, TValue>) {
|
|
48
|
-
const { theme } = useWarqadConfig();
|
|
49
|
-
const primaryColor = theme?.primaryColor;
|
|
50
|
-
const [sorting, setSorting] = useState<SortingState>([]);
|
|
51
|
-
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
|
|
52
|
-
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
|
|
53
|
-
const [rowSelection, setRowSelection] = useState({});
|
|
54
|
-
const [globalFilter, setGlobalFilter] = useState("");
|
|
55
|
-
|
|
56
|
-
const table = useReactTable({
|
|
57
|
-
data,
|
|
58
|
-
columns,
|
|
59
|
-
onSortingChange: setSorting,
|
|
60
|
-
onColumnFiltersChange: setColumnFilters,
|
|
61
|
-
getCoreRowModel: getCoreRowModel(),
|
|
62
|
-
getPaginationRowModel: pageRows ? getPaginationRowModel() : undefined,
|
|
63
|
-
getSortedRowModel: getSortedRowModel(),
|
|
64
|
-
getFilteredRowModel: getFilteredRowModel(),
|
|
65
|
-
onColumnVisibilityChange: setColumnVisibility,
|
|
66
|
-
onRowSelectionChange: setRowSelection,
|
|
67
|
-
onGlobalFilterChange: setGlobalFilter,
|
|
68
|
-
globalFilterFn: "includesString",
|
|
69
|
-
state: {
|
|
70
|
-
sorting,
|
|
71
|
-
columnFilters,
|
|
72
|
-
columnVisibility,
|
|
73
|
-
rowSelection,
|
|
74
|
-
globalFilter,
|
|
75
|
-
...(pageRows ? { pagination: { pageSize: pageRows, pageIndex: 0 } } : {}),
|
|
76
|
-
},
|
|
77
|
-
manualPagination: false,
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
// Unified effect to handle all state changes
|
|
81
|
-
useEffect(() => {
|
|
82
|
-
if (onChange) {
|
|
83
|
-
onChange({
|
|
84
|
-
pagination: {
|
|
85
|
-
pageIndex: table.getState().pagination.pageIndex,
|
|
86
|
-
pageSize: table.getState().pagination.pageSize,
|
|
87
|
-
pageCount: table.getPageCount(),
|
|
88
|
-
},
|
|
89
|
-
sorting,
|
|
90
|
-
columnFilters,
|
|
91
|
-
globalFilter,
|
|
92
|
-
selectedRows: table
|
|
93
|
-
.getSelectedRowModel()
|
|
94
|
-
.rows.map((row) => row.original),
|
|
95
|
-
filteredData: table
|
|
96
|
-
.getFilteredRowModel()
|
|
97
|
-
.rows.map((row) => row.original),
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
}, [
|
|
101
|
-
sorting,
|
|
102
|
-
columnFilters,
|
|
103
|
-
globalFilter,
|
|
104
|
-
rowSelection,
|
|
105
|
-
table,
|
|
106
|
-
onChange,
|
|
107
|
-
table.getState().pagination.pageIndex,
|
|
108
|
-
table.getState().pagination.pageSize,
|
|
109
|
-
]);
|
|
110
|
-
|
|
111
|
-
return (
|
|
112
|
-
<div className={`space-y-4 w-full ${className}`}>
|
|
113
|
-
{/* Search and Column Visibility Header */}
|
|
114
|
-
<div className="flex items-center justify-between gap-4">
|
|
115
|
-
<div className="flex-1 max-w-sm">
|
|
116
|
-
<Fields.Input
|
|
117
|
-
label="Search"
|
|
118
|
-
placeholder={searchPlaceholder}
|
|
119
|
-
value={globalFilter}
|
|
120
|
-
onChange={(e: any) => setGlobalFilter(e.target.value)}
|
|
121
|
-
icon={<Search size={16} />}
|
|
122
|
-
className="!h-9"
|
|
123
|
-
/>
|
|
124
|
-
</div>
|
|
125
|
-
|
|
126
|
-
<div className="flex items-center gap-2">
|
|
127
|
-
<div className="relative group">
|
|
128
|
-
<button className="flex items-center gap-2 px-3 h-9 rounded-lg border border-gray-200 dark:border-zinc-800 bg-white dark:bg-zinc-900 text-sm font-medium text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-zinc-800 transition-colors">
|
|
129
|
-
Columns
|
|
130
|
-
<ChevronDown size={14} className="text-gray-400" />
|
|
131
|
-
</button>
|
|
132
|
-
|
|
133
|
-
<div className="absolute right-0 top-full mt-2 w-48 py-1 bg-white dark:bg-zinc-900 border border-gray-200 dark:border-zinc-800 rounded-lg shadow-xl opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all z-50">
|
|
134
|
-
{table
|
|
135
|
-
.getAllColumns()
|
|
136
|
-
.filter((column: any) => column.getCanHide())
|
|
137
|
-
.map((column: any) => (
|
|
138
|
-
<label
|
|
139
|
-
key={column.id}
|
|
140
|
-
className="flex items-center gap-2 px-3 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-zinc-800 cursor-pointer capitalize"
|
|
141
|
-
>
|
|
142
|
-
<input
|
|
143
|
-
type="checkbox"
|
|
144
|
-
checked={column.getIsVisible()}
|
|
145
|
-
onChange={(e: any) =>
|
|
146
|
-
column.toggleVisibility(!!e.target.checked)
|
|
147
|
-
}
|
|
148
|
-
className="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
|
|
149
|
-
style={{ accentColor: primaryColor }}
|
|
150
|
-
/>
|
|
151
|
-
{column.id}
|
|
152
|
-
</label>
|
|
153
|
-
))}
|
|
154
|
-
</div>
|
|
155
|
-
</div>
|
|
156
|
-
</div>
|
|
157
|
-
</div>
|
|
158
|
-
|
|
159
|
-
{/* Table Container */}
|
|
160
|
-
<div className="rounded-lg border border-gray-200 dark:border-zinc-800 bg-white dark:bg-zinc-950 overflow-hidden relative">
|
|
161
|
-
<div className="overflow-x-auto">
|
|
162
|
-
<table className="w-full text-left border-collapse">
|
|
163
|
-
<thead className="bg-gray-50/50 dark:bg-zinc-900/50 border-b border-gray-200 dark:border-zinc-800">
|
|
164
|
-
{table.getHeaderGroups().map((headerGroup: any) => (
|
|
165
|
-
<tr key={headerGroup.id}>
|
|
166
|
-
{headerGroup.headers.map((header: any) => (
|
|
167
|
-
<th
|
|
168
|
-
key={header.id}
|
|
169
|
-
className="px-4 py-3 text-[13px] font-semibold text-gray-900 dark:text-zinc-100 text-left"
|
|
170
|
-
>
|
|
171
|
-
{header.isPlaceholder
|
|
172
|
-
? null
|
|
173
|
-
: flexRender(
|
|
174
|
-
header.column.columnDef.header,
|
|
175
|
-
header.getContext(),
|
|
176
|
-
)}
|
|
177
|
-
</th>
|
|
178
|
-
))}
|
|
179
|
-
</tr>
|
|
180
|
-
))}
|
|
181
|
-
</thead>
|
|
182
|
-
<tbody className="divide-y divide-gray-200 dark:divide-zinc-800">
|
|
183
|
-
{isLoading ? (
|
|
184
|
-
Array.from({ length: pageRows || 5 }).map((_, i) => (
|
|
185
|
-
<tr
|
|
186
|
-
key={`skeleton-${i}`}
|
|
187
|
-
className="border-b border-gray-100 dark:border-zinc-800/50"
|
|
188
|
-
>
|
|
189
|
-
{columns.map((_, j) => (
|
|
190
|
-
<td key={`skeleton-cell-${j}`} className="px-4 py-4">
|
|
191
|
-
<div className="h-4 bg-gray-100 dark:bg-zinc-800 rounded animate-pulse w-full"></div>
|
|
192
|
-
</td>
|
|
193
|
-
))}
|
|
194
|
-
</tr>
|
|
195
|
-
))
|
|
196
|
-
) : table.getRowModel().rows?.length ? (
|
|
197
|
-
table.getRowModel().rows.map((row: any) => (
|
|
198
|
-
<tr
|
|
199
|
-
key={row.id}
|
|
200
|
-
className="hover:bg-gray-50/50 dark:hover:bg-zinc-900/50 transition-colors"
|
|
201
|
-
data-state={row.getIsSelected() && "selected"}
|
|
202
|
-
>
|
|
203
|
-
{row.getVisibleCells().map((cell: any) => (
|
|
204
|
-
<td
|
|
205
|
-
key={cell.id}
|
|
206
|
-
className="px-4 py-3 text-sm text-gray-700 dark:text-gray-200"
|
|
207
|
-
>
|
|
208
|
-
{flexRender(
|
|
209
|
-
cell.column.columnDef.cell,
|
|
210
|
-
cell.getContext(),
|
|
211
|
-
)}
|
|
212
|
-
</td>
|
|
213
|
-
))}
|
|
214
|
-
</tr>
|
|
215
|
-
))
|
|
216
|
-
) : (
|
|
217
|
-
<tr>
|
|
218
|
-
<td
|
|
219
|
-
colSpan={columns.length}
|
|
220
|
-
className="h-32 text-center text-sm text-gray-500"
|
|
221
|
-
>
|
|
222
|
-
No results found.
|
|
223
|
-
</td>
|
|
224
|
-
</tr>
|
|
225
|
-
)}
|
|
226
|
-
</tbody>
|
|
227
|
-
</table>
|
|
228
|
-
</div>
|
|
229
|
-
</div>
|
|
230
|
-
|
|
231
|
-
{/* Footer / Pagination */}
|
|
232
|
-
<div className="flex items-center justify-between px-2">
|
|
233
|
-
<div className="flex-1 text-xs text-gray-500">
|
|
234
|
-
{table.getFilteredSelectedRowModel().rows.length} of{" "}
|
|
235
|
-
{table.getFilteredRowModel().rows.length} row(s) selected.
|
|
236
|
-
</div>
|
|
237
|
-
|
|
238
|
-
{pageRows && table.getPageCount() > 1 && (
|
|
239
|
-
<div className="flex items-center gap-2">
|
|
240
|
-
<button
|
|
241
|
-
onClick={() => table.previousPage()}
|
|
242
|
-
disabled={!table.getCanPreviousPage()}
|
|
243
|
-
className="p-1 px-3 rounded-md border border-gray-200 dark:border-zinc-800 text-sm disabled:opacity-50 disabled:cursor-not-allowed hover:bg-gray-50 dark:hover:bg-zinc-800 transition-colors"
|
|
244
|
-
>
|
|
245
|
-
Previous
|
|
246
|
-
</button>
|
|
247
|
-
<button
|
|
248
|
-
onClick={() => table.nextPage()}
|
|
249
|
-
disabled={!table.getCanNextPage()}
|
|
250
|
-
className="p-1 px-3 rounded-md border border-gray-200 dark:border-zinc-800 text-sm disabled:opacity-50 disabled:cursor-not-allowed hover:bg-gray-50 dark:hover:bg-zinc-800 transition-colors"
|
|
251
|
-
>
|
|
252
|
-
Next
|
|
253
|
-
</button>
|
|
254
|
-
</div>
|
|
255
|
-
)}
|
|
256
|
-
</div>
|
|
257
|
-
</div>
|
|
258
|
-
);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
export default DataTable;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./DataTable";
|