naria-ui 0.1.2 → 0.1.5
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/README.md +46 -0
- package/package.json +49 -16
- package/app/globals.css +0 -0
- package/app/layout.tsx +0 -32
- package/app/page.module.css +0 -0
- package/app/page.tsx +0 -10
- package/components/button/Button.tsx +0 -28
- package/components/button/index.tsx +0 -5
- package/components/drawer/Drawer.tsx +0 -98
- package/components/index.ts +0 -2
- package/components/input/Input.tsx +0 -89
- package/components/lib-file-uploader/LibFileUploader.tsx +0 -124
- package/components/lib-pagination/LibPagination.tsx +0 -198
- package/components/modal/Modal.tsx +0 -88
- package/components/select/Select.tsx +0 -210
- package/components/tabs/LibTabs.tsx +0 -31
- package/components/textarea/Textarea.tsx +0 -87
- package/eslint.config.mjs +0 -25
- package/index.ts +0 -1
- package/next.config.ts +0 -7
- package/public/file.svg +0 -1
- package/public/globe.svg +0 -1
- package/public/next.svg +0 -1
- package/public/vercel.svg +0 -1
- package/public/window.svg +0 -1
- package/tsconfig.json +0 -27
package/README.md
CHANGED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Getting Started with Create React App
|
|
2
|
+
|
|
3
|
+
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
|
4
|
+
|
|
5
|
+
## Available Scripts
|
|
6
|
+
|
|
7
|
+
In the project directory, you can run:
|
|
8
|
+
|
|
9
|
+
### `npm start`
|
|
10
|
+
|
|
11
|
+
Runs the app in the development mode.\
|
|
12
|
+
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
|
|
13
|
+
|
|
14
|
+
The page will reload if you make edits.\
|
|
15
|
+
You will also see any lint errors in the console.
|
|
16
|
+
|
|
17
|
+
### `npm test`
|
|
18
|
+
|
|
19
|
+
Launches the test runner in the interactive watch mode.\
|
|
20
|
+
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
|
21
|
+
|
|
22
|
+
### `npm run build`
|
|
23
|
+
|
|
24
|
+
Builds the app for production to the `build` folder.\
|
|
25
|
+
It correctly bundles React in production mode and optimizes the build for the best performance.
|
|
26
|
+
|
|
27
|
+
The build is minified and the filenames include the hashes.\
|
|
28
|
+
Your app is ready to be deployed!
|
|
29
|
+
|
|
30
|
+
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
|
31
|
+
|
|
32
|
+
### `npm run eject`
|
|
33
|
+
|
|
34
|
+
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
|
|
35
|
+
|
|
36
|
+
If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
|
37
|
+
|
|
38
|
+
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
|
|
39
|
+
|
|
40
|
+
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
|
|
41
|
+
|
|
42
|
+
## Learn More
|
|
43
|
+
|
|
44
|
+
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
|
45
|
+
|
|
46
|
+
To learn React, check out the [React documentation](https://reactjs.org/).
|
package/package.json
CHANGED
|
@@ -1,25 +1,58 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "naria-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"private": false,
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"
|
|
5
|
+
"author": "",
|
|
6
|
+
"license": "ISC",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
}
|
|
10
16
|
},
|
|
11
17
|
"dependencies": {
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
18
|
+
"@testing-library/dom": "^10.4.1",
|
|
19
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
20
|
+
"@testing-library/react": "^16.3.0",
|
|
21
|
+
"@testing-library/user-event": "^13.5.0",
|
|
22
|
+
"@types/jest": "^27.5.2",
|
|
23
|
+
"@types/node": "^16.18.126",
|
|
24
|
+
"@types/react": "^19.2.2",
|
|
25
|
+
"@types/react-dom": "^19.2.2",
|
|
26
|
+
"react": "^19.2.0",
|
|
27
|
+
"react-dom": "^19.2.0",
|
|
28
|
+
"react-scripts": "5.0.1",
|
|
29
|
+
"typescript": "^4.9.5",
|
|
30
|
+
"web-vitals": "^2.1.4"
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"start": "react-scripts start",
|
|
34
|
+
"build": "react-scripts build",
|
|
35
|
+
"test": "react-scripts test",
|
|
36
|
+
"eject": "react-scripts eject"
|
|
37
|
+
},
|
|
38
|
+
"eslintConfig": {
|
|
39
|
+
"extends": [
|
|
40
|
+
"react-app",
|
|
41
|
+
"react-app/jest"
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
"browserslist": {
|
|
45
|
+
"production": [
|
|
46
|
+
">0.2%",
|
|
47
|
+
"not dead",
|
|
48
|
+
"not op_mini all"
|
|
49
|
+
],
|
|
50
|
+
"development": [
|
|
51
|
+
"last 1 chrome version",
|
|
52
|
+
"last 1 firefox version",
|
|
53
|
+
"last 1 safari version"
|
|
54
|
+
]
|
|
15
55
|
},
|
|
16
56
|
"devDependencies": {
|
|
17
|
-
"typescript": "^5",
|
|
18
|
-
"@types/node": "^20",
|
|
19
|
-
"@types/react": "^19",
|
|
20
|
-
"@types/react-dom": "^19",
|
|
21
|
-
"eslint": "^9",
|
|
22
|
-
"eslint-config-next": "15.5.6",
|
|
23
|
-
"@eslint/eslintrc": "^3"
|
|
24
57
|
}
|
|
25
58
|
}
|
package/app/globals.css
DELETED
|
File without changes
|
package/app/layout.tsx
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import type { Metadata } from "next";
|
|
2
|
-
import { Geist, Geist_Mono } from "next/font/google";
|
|
3
|
-
import "./globals.css";
|
|
4
|
-
|
|
5
|
-
const geistSans = Geist({
|
|
6
|
-
variable: "--font-geist-sans",
|
|
7
|
-
subsets: ["latin"],
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
const geistMono = Geist_Mono({
|
|
11
|
-
variable: "--font-geist-mono",
|
|
12
|
-
subsets: ["latin"],
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
export const metadata: Metadata = {
|
|
16
|
-
title: "Create Next App",
|
|
17
|
-
description: "Generated by create next app",
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export default function RootLayout({
|
|
21
|
-
children,
|
|
22
|
-
}: Readonly<{
|
|
23
|
-
children: React.ReactNode;
|
|
24
|
-
}>) {
|
|
25
|
-
return (
|
|
26
|
-
<html lang="en">
|
|
27
|
-
<body className={`${geistSans.variable} ${geistMono.variable}`}>
|
|
28
|
-
{children}
|
|
29
|
-
</body>
|
|
30
|
-
</html>
|
|
31
|
-
);
|
|
32
|
-
}
|
package/app/page.module.css
DELETED
|
File without changes
|
package/app/page.tsx
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
import React, {FC} from "react";
|
|
3
|
-
|
|
4
|
-
export interface ButtonProps extends React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement> {
|
|
5
|
-
type?: "button" | "submit";
|
|
6
|
-
classNames?: string;
|
|
7
|
-
value: string;
|
|
8
|
-
theme?: "btn-primary" | "btn-secondary" | "btn-success" | "btn-warning" | "btn-info-light" | "btn-danger-light" | "btn-info-link" | "btn-outline-secondary" | "btn-outline-primary" | "btn-secondary-light";
|
|
9
|
-
size?: "btn-md" | "btn-sm";
|
|
10
|
-
isLoading?: boolean;
|
|
11
|
-
isDisabled?: boolean;
|
|
12
|
-
icon?: HTMLElement | undefined;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const Button: FC<ButtonProps> = ({
|
|
16
|
-
type = "button", classNames = "",
|
|
17
|
-
value, theme = "btn-primary", size = "btn-md",
|
|
18
|
-
icon = undefined,
|
|
19
|
-
isLoading = false, isDisabled = false, ...otherProps
|
|
20
|
-
}) => {
|
|
21
|
-
return (
|
|
22
|
-
<button type={type} disabled={isDisabled} {...otherProps}
|
|
23
|
-
className={`flex items-center gap-1.5 justify-center rounded-lg w-full ${theme} ${size} ${classNames}`}
|
|
24
|
-
>{isLoading ? <></> : undefined}{icon}{value}</button>
|
|
25
|
-
);
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export default Button;
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
import {FC, forwardRef, useEffect, useImperativeHandle, useState} from "react";
|
|
3
|
-
import {useWidth} from '@/hooks/use-width';
|
|
4
|
-
import {useRouter} from 'next/navigation';
|
|
5
|
-
|
|
6
|
-
export interface LibDrawerProps {
|
|
7
|
-
children?: React.ReactNode;
|
|
8
|
-
size?: string;
|
|
9
|
-
position?: "TOP" | "RIGHT" | "LEFT" | "BOTTOM";
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface LibDrawerRef {
|
|
13
|
-
onToggle: () => void;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const Drawer = forwardRef<LibDrawerRef, LibDrawerProps>(({size, children, position = "TOP"}, ref) => {
|
|
17
|
-
useImperativeHandle(ref, () => ({
|
|
18
|
-
onToggle: () => onToggle(),
|
|
19
|
-
}));
|
|
20
|
-
const getDeviceWidth = useWidth();
|
|
21
|
-
const router = useRouter();
|
|
22
|
-
const [isShow, setIsShow] = useState(false);
|
|
23
|
-
const onToggle = () => {
|
|
24
|
-
setIsShow(!isShow);
|
|
25
|
-
}
|
|
26
|
-
const onToggleEvent = (e) => {
|
|
27
|
-
if (e?.target?.className.toString()?.includes('backdrop')) {
|
|
28
|
-
onToggle()
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
const getPosition = () => {
|
|
32
|
-
if (position === "TOP") {
|
|
33
|
-
return `top-0 ${getDeviceWidth < 1024 ? '' : 'rounded-b-xl'}`
|
|
34
|
-
}
|
|
35
|
-
if (position === "BOTTOM") {
|
|
36
|
-
return `bottom-0 ${getDeviceWidth < 1024 ? '' : 'rounded-t-xl'}`
|
|
37
|
-
}
|
|
38
|
-
if (position === "LEFT") {
|
|
39
|
-
return `left-0 ${getDeviceWidth < 1024 ? '' : 'rounded-r-xl'}`
|
|
40
|
-
}
|
|
41
|
-
if (position === "RIGHT") {
|
|
42
|
-
return `right-0 ${getDeviceWidth < 1024 ? '' : 'rounded-l-xl'}`
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
useEffect(() => {
|
|
47
|
-
const handlePopState = () => {
|
|
48
|
-
setIsShow(false);
|
|
49
|
-
};
|
|
50
|
-
window.addEventListener('popstate', handlePopState);
|
|
51
|
-
return () => {
|
|
52
|
-
window.removeEventListener('popstate', handlePopState);
|
|
53
|
-
};
|
|
54
|
-
}, []);
|
|
55
|
-
|
|
56
|
-
useEffect(() => {
|
|
57
|
-
if (getDeviceWidth < 1024) {
|
|
58
|
-
if (isShow) {
|
|
59
|
-
router.push('#drawer');
|
|
60
|
-
} else {
|
|
61
|
-
if (window.location.hash && !document.referrer.includes('#')) {
|
|
62
|
-
router.back();
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
if (isShow) {
|
|
67
|
-
document.body.style.overflow = 'hidden';
|
|
68
|
-
} else {
|
|
69
|
-
document.body.style.overflow = 'auto';
|
|
70
|
-
}
|
|
71
|
-
}, [isShow]);
|
|
72
|
-
|
|
73
|
-
return (
|
|
74
|
-
<>
|
|
75
|
-
{isShow ?
|
|
76
|
-
(
|
|
77
|
-
<div
|
|
78
|
-
className={`backdrop bg-dark-100/20 backdrop-blur-sm fixed lg:place-items-center lg:grid right-0 top-0 left-0 bottom-0 w-full h-full z-40 duration-200 transition-opacity ${isShow ? "opacity-1" : "opacity-0 hidden pointer-events-none"}`}
|
|
79
|
-
onClick={onToggleEvent}>
|
|
80
|
-
<div
|
|
81
|
-
className={`absolute z-50 transform p-3 md:p-5 bg-grey-100 shadow-xl transition-opacity
|
|
82
|
-
${getPosition()}
|
|
83
|
-
duration-200 h-full w-full lg:h-auto ${size ? size : "max-w-lg"}
|
|
84
|
-
${isShow ? "opacity-1" : "opacity-0 pointer-events-none"}`}>
|
|
85
|
-
<div
|
|
86
|
-
className="overflow-y-auto max-h-[calc(100vh-60px)] md:max-h-[calc(100vh-90px)] h-full">
|
|
87
|
-
{children}
|
|
88
|
-
</div>
|
|
89
|
-
</div>
|
|
90
|
-
</div>
|
|
91
|
-
) : undefined
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
</>
|
|
95
|
-
);
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
export default Drawer;
|
package/components/index.ts
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
import {FC} from "react";
|
|
3
|
-
|
|
4
|
-
export interface props {
|
|
5
|
-
type?: string;
|
|
6
|
-
classNames?: string;
|
|
7
|
-
placeholder: string;
|
|
8
|
-
label: string;
|
|
9
|
-
theme?: "secondary";
|
|
10
|
-
size?: "md" | "sm";
|
|
11
|
-
hasError?: string | null;
|
|
12
|
-
register?: any;
|
|
13
|
-
name?: string;
|
|
14
|
-
isDisabled?: boolean;
|
|
15
|
-
autocomplete?: boolean;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const themes = {
|
|
19
|
-
secondary: {
|
|
20
|
-
input: `border
|
|
21
|
-
bg-transparent
|
|
22
|
-
placeholder:text-secondary-400
|
|
23
|
-
outline-1
|
|
24
|
-
outline-primary-100
|
|
25
|
-
border-secondary-300
|
|
26
|
-
rounded-md
|
|
27
|
-
hover:not:border-primary-100
|
|
28
|
-
focus:outline
|
|
29
|
-
focus:border-primary-100
|
|
30
|
-
|
|
31
|
-
disabled:text-secondary-100
|
|
32
|
-
disabled:border-secondary-500`,
|
|
33
|
-
|
|
34
|
-
label: `text-dark-100
|
|
35
|
-
peer-focus:text-primary-100
|
|
36
|
-
peer-focus:scale-90
|
|
37
|
-
|
|
38
|
-
peer-disabled:text-secondary-400`
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const sizes = {
|
|
43
|
-
sm: {
|
|
44
|
-
input: "text-xs px-2 py-1",
|
|
45
|
-
label: `px-1 text-xs `,
|
|
46
|
-
},
|
|
47
|
-
md: {
|
|
48
|
-
input: "text-sm px-3 py-2",
|
|
49
|
-
label: `px-1 text-xs`,
|
|
50
|
-
},
|
|
51
|
-
}
|
|
52
|
-
const Input: FC<props> = ({
|
|
53
|
-
type = "text", placeholder, classNames = "",
|
|
54
|
-
label, theme = "secondary", size = "md", hasError,
|
|
55
|
-
register, name, isDisabled = false, autocomplete = false,
|
|
56
|
-
...otherProps
|
|
57
|
-
}) => {
|
|
58
|
-
return (
|
|
59
|
-
<div>
|
|
60
|
-
<label
|
|
61
|
-
htmlFor={name}
|
|
62
|
-
className={`cursor-text transition-all duration-200
|
|
63
|
-
transform ${themes[theme].label} ${sizes[size].label}
|
|
64
|
-
${hasError && "!text-danger-100"}`}>
|
|
65
|
-
{label}
|
|
66
|
-
<input
|
|
67
|
-
disabled={isDisabled}
|
|
68
|
-
autoComplete = {autocomplete ? "on" : "off"}
|
|
69
|
-
id={name}
|
|
70
|
-
{...register}
|
|
71
|
-
{...otherProps}
|
|
72
|
-
type={type}
|
|
73
|
-
name={name}
|
|
74
|
-
className={`mt-1 w-full bg-white transition duration-200 ease ${themes[theme].input} ${sizes[size].input}
|
|
75
|
-
${hasError && "!border-danger-100 focus:border-danger-100 outline-danger-100"} ${classNames}`}
|
|
76
|
-
placeholder={placeholder}
|
|
77
|
-
/>
|
|
78
|
-
</label>
|
|
79
|
-
{
|
|
80
|
-
hasError &&
|
|
81
|
-
<p className="text-xs mt-1 text-danger-100">{hasError}</p>
|
|
82
|
-
}
|
|
83
|
-
</div>
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
);
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
export default Input;
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
import {FC, useEffect, useRef, useState} from "react";
|
|
3
|
-
import CloudArrowUp from '@/assets/icons/cloud-arrow-up.svg'
|
|
4
|
-
import LibButton from "@/components/lib/lib-button/LibButton";
|
|
5
|
-
import convertFileSize from "@/utils/convert-file-size";
|
|
6
|
-
import Loading from "@/components/shared/loading/Loading";
|
|
7
|
-
|
|
8
|
-
export interface props {
|
|
9
|
-
isLoading: boolean;
|
|
10
|
-
onFileChange?: any;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const LibFileUploader: FC<props> = ({isLoading = true, onFileChange}) => {
|
|
14
|
-
const labelRef = useRef(null);
|
|
15
|
-
const [isDragging, setIsDragging] = useState(false);
|
|
16
|
-
const [selectedFile, setSelectedFile] = useState(null);
|
|
17
|
-
|
|
18
|
-
const handleDragEnter = (e) => {
|
|
19
|
-
e.preventDefault();
|
|
20
|
-
setIsDragging(true);
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const handleDragLeave = (e) => {
|
|
24
|
-
e.preventDefault();
|
|
25
|
-
setIsDragging(false);
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const handleDragOver = (e) => {
|
|
29
|
-
e.preventDefault();
|
|
30
|
-
setIsDragging(true);
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const handleDrop = (e) => {
|
|
34
|
-
e.preventDefault();
|
|
35
|
-
if (isLoading) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
setIsDragging(false);
|
|
39
|
-
const file = e?.target?.files ? e?.target?.files[0] : e?.dataTransfer?.files[0];
|
|
40
|
-
if (file) {
|
|
41
|
-
setSelectedFile(file);
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
const onCancel = () => {
|
|
45
|
-
setSelectedFile(null)
|
|
46
|
-
}
|
|
47
|
-
const onUpload = () => {
|
|
48
|
-
onFileChange(selectedFile)
|
|
49
|
-
}
|
|
50
|
-
useEffect(() => {
|
|
51
|
-
if(!isLoading) {
|
|
52
|
-
setSelectedFile(null);
|
|
53
|
-
}
|
|
54
|
-
}, [isLoading])
|
|
55
|
-
return (
|
|
56
|
-
|
|
57
|
-
<div className="relative border border-dashed border-secondary-100/40 rounded-2xl overflow-hidden">
|
|
58
|
-
<label
|
|
59
|
-
ref={labelRef}
|
|
60
|
-
className={`py-10 px-6 block ${isDragging ? 'border-secondary-100/100 bg-secondary-100/5' : ''}`}
|
|
61
|
-
onDragEnter={handleDragEnter}
|
|
62
|
-
onDragLeave={handleDragLeave}
|
|
63
|
-
onDragOver={handleDragOver}
|
|
64
|
-
onDrop={handleDrop}
|
|
65
|
-
>
|
|
66
|
-
<div className="flex flex-col md:flex-row justify-center items-center gap-16">
|
|
67
|
-
<div className="flex gap-5 items-center flex-col md:flex-row">
|
|
68
|
-
<CloudArrowUp className="w-10 mt-2.5 shrink-0"/>
|
|
69
|
-
<div>
|
|
70
|
-
<p className="text-base font-bold">جهت انتخاب فایل کلیک کرده یا فایل مورد نظر را اینجا رها
|
|
71
|
-
کنید.</p>
|
|
72
|
-
<p className="text-sm text-secondary-100 mt-2">فایلهای قابل انتخاب: PNG، JPEG، MP4</p>
|
|
73
|
-
<p className="text-sm text-secondary-100 mt-2">حداکثر حجم مجاز: 2 مگابایت</p>
|
|
74
|
-
</div>
|
|
75
|
-
</div>
|
|
76
|
-
|
|
77
|
-
<input type="file" accept="image/png, image/jpeg, image/jpg, video/mp4"
|
|
78
|
-
value=""
|
|
79
|
-
onChange={handleDrop} className="hidden"/>
|
|
80
|
-
<div className="sm:max-w-[120px] w-full">
|
|
81
|
-
<LibButton theme="btn-info-light" onClick={() => labelRef.current.click()} value="انتخاب فایل"/>
|
|
82
|
-
</div>
|
|
83
|
-
|
|
84
|
-
</div>
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
</label>
|
|
88
|
-
{
|
|
89
|
-
selectedFile && !isLoading ? (
|
|
90
|
-
<div className="absolute bg-light-100 top-0 right-0 w-full h-full flex items-center">
|
|
91
|
-
<div className="text-sm mx-auto w-full max-w-[250px]">
|
|
92
|
-
<p className="flex gap-1"><span className="text-secondary-100 shrink-0">نام فایل:</span>
|
|
93
|
-
<span
|
|
94
|
-
className="inline-block ltr text-ellipsis overflow-hidden truncate">{selectedFile?.name}</span>
|
|
95
|
-
</p>
|
|
96
|
-
<p><span
|
|
97
|
-
className="text-secondary-100">حجم فایل:</span> {convertFileSize(selectedFile?.size)}
|
|
98
|
-
</p>
|
|
99
|
-
<div className="flex mt-4 gap-2">
|
|
100
|
-
|
|
101
|
-
<div className="grow">
|
|
102
|
-
<LibButton value="انصراف" size="btn-sm" theme="btn-danger-light" onClick={onCancel}/>
|
|
103
|
-
</div>
|
|
104
|
-
<div className="grow">
|
|
105
|
-
<LibButton value="تایید" size="btn-sm" theme="btn-success" onClick={onUpload}/>
|
|
106
|
-
</div>
|
|
107
|
-
</div>
|
|
108
|
-
</div>
|
|
109
|
-
</div>
|
|
110
|
-
) : undefined
|
|
111
|
-
}
|
|
112
|
-
{
|
|
113
|
-
selectedFile && isLoading ? (
|
|
114
|
-
<div className="absolute bg-light-100 top-0 right-0 w-full h-full flex items-center gap-3 justify-center">
|
|
115
|
-
<Loading size="w-6.5 h-6.5" /> <span>در حال بارگزاری...</span>
|
|
116
|
-
</div>
|
|
117
|
-
) : undefined
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
</div>
|
|
121
|
-
);
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
export default LibFileUploader;
|
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
import {FC, useEffect, useState} from "react";
|
|
3
|
-
import ArrowRight from "@/assets/icons/angle-right.svg";
|
|
4
|
-
import ArrowLeft from "@/assets/icons/angle-left.svg";
|
|
5
|
-
import {generateUuid} from '@/utils/generate-uuid';
|
|
6
|
-
|
|
7
|
-
export interface props {
|
|
8
|
-
theme?: "primary" | "secondary" | "warning" | "infoLight" | "dangerLight" | "infoLink" | "outlineSecondary" | "outlinePrimary";
|
|
9
|
-
activeTheme?: "primary" | "secondary" | "warning" | "infoLight" | "dangerLight" | "infoLink" | "outlineSecondary" | "outlinePrimary";
|
|
10
|
-
size?: "md" | "sm";
|
|
11
|
-
totalCount: number;
|
|
12
|
-
pageSize: number;
|
|
13
|
-
onPageChange: any;
|
|
14
|
-
selectedPage?: any;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const sizes = {
|
|
18
|
-
sm: "text-xs h-8 min-w-8",
|
|
19
|
-
md: "text-sm h-10 min-w-10"
|
|
20
|
-
}
|
|
21
|
-
const sizesArrow = {
|
|
22
|
-
sm: "w-2.5",
|
|
23
|
-
md: "w8"
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export const buttonThemes = {
|
|
27
|
-
primary: `border border-transparent bg-primary-100 text-white hover:bg-primary-200 focus:bg-primary-200 disabled:bg-grey-200 disabled:text-grey-300 disabled:cursor-not-allowed`,
|
|
28
|
-
secondary: `border border-transparent bg-secondary-100 text-white hover:bg-secondary-200 focus:bg-secondary-200 disabled:bg-grey-200 disabled:text-grey-300 disabled:cursor-not-allowed`,
|
|
29
|
-
success: `border border-transparent bg-success-100 text-white hover:bg-success-200 focus:bg-success-200 disabled:bg-grey-200 disabled:text-grey-300 disabled:cursor-not-allowed`,
|
|
30
|
-
warning: `border border-transparent bg-warning-100 text-dark-100 hover:bg-warning-200 focus:bg-warning-200 disabled:bg-grey-200 disabled:text-grey-300 disabled:cursor-not-allowed`,
|
|
31
|
-
infoLight: `border border-transparent bg-info-100/10 text-info-100 hover:brightness-80 focus:brightness-80 hover:border-info-100 focus:border-info-100 disabled:bg-grey-200 disabled:text-grey-300 disabled:cursor-not-allowed`,
|
|
32
|
-
dangerLight: `border border-transparent bg-danger-300 text-danger-100 hover:bg-danger-400 focus:bg-danger-400 hover:border-danger-100 focus:border-danger-100 disabled:bg-grey-200 disabled:text-grey-300 disabled:cursor-not-allowed`,
|
|
33
|
-
infoLink: `text-info-100 hover:text-info-200 focus:text-info-200 disabled:text-grey-300 disabled:cursor-not-allowed`,
|
|
34
|
-
outlinePrimary: `border border-primary-100 text-primary-100 hover:bg-primary-300 focus:bg-primary-300 disabled:text-grey-300 disabled:cursor-not-allowed`,
|
|
35
|
-
outlineSecondary: `border border-secondary-100 text-secondary-100 enabled:hover:bg-grey-200 focus:bg-grey-200 disabled:text-grey-300 disabled:border-grey-200 disabled:fill-grey-200 disabled:cursor-not-allowed`,
|
|
36
|
-
}
|
|
37
|
-
export const activeThemes = {
|
|
38
|
-
primary: `border border-transparent bg-primary-100 text-white hover:bg-primary-200 focus:bg-primary-200 disabled:bg-grey-200 disabled:text-grey-300 disabled:cursor-not-allowed`,
|
|
39
|
-
secondary: `border border-transparent bg-secondary-100 text-white hover:bg-secondary-200 focus:bg-secondary-200 disabled:bg-grey-200 disabled:text-grey-300 disabled:cursor-not-allowed`,
|
|
40
|
-
success: `border border-transparent bg-success-100 text-white hover:bg-success-200 focus:bg-success-200 disabled:bg-grey-200 disabled:text-grey-300 disabled:cursor-not-allowed`,
|
|
41
|
-
warning: `border border-transparent bg-warning-100 !text-dark-100 hover:bg-warning-200 focus:bg-warning-200 disabled:bg-grey-200 disabled:text-grey-300 disabled:cursor-not-allowed`,
|
|
42
|
-
infoLight: `border border-transparent bg-info-100/10 text-info-100 hover:brightness-80 focus:brightness-80 hover:border-info-100 focus:border-info-100 disabled:bg-grey-200 disabled:text-grey-300 disabled:cursor-not-allowed`,
|
|
43
|
-
dangerLight: `border border-transparent bg-danger-300 text-danger-100 hover:bg-danger-400 focus:bg-danger-400 hover:border-danger-100 focus:border-danger-100 disabled:bg-grey-200 disabled:text-grey-300 disabled:cursor-not-allowed`,
|
|
44
|
-
infoLink: `text-info-100 hover:text-info-200 focus:text-info-200 disabled:text-grey-300 disabled:cursor-not-allowed`,
|
|
45
|
-
outlinePrimary: `transition duration-200 ease border border-primary-100 text-primary-100 hover:bg-primary-300 focus:bg-primary-300 disabled:text-grey-300 disabled:cursor-not-allowed`,
|
|
46
|
-
outlineSecondary: `border border-secondary-100 text-secondary-100 hover:bg-grey-200 focus:bg-grey-200 disabled:text-grey-300 disabled:cursor-not-allowed`,
|
|
47
|
-
}
|
|
48
|
-
export const dotsThemes = {
|
|
49
|
-
outlineSecondary: `text-secondary-100`,
|
|
50
|
-
}
|
|
51
|
-
export const arrowThemes = {
|
|
52
|
-
outlineSecondary: `fill-secondary-100`,
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const LibPagination: FC<props> = ({
|
|
56
|
-
totalCount,
|
|
57
|
-
pageSize,
|
|
58
|
-
onPageChange,
|
|
59
|
-
selectedPage,
|
|
60
|
-
activeTheme = "primary",
|
|
61
|
-
theme = "primary",
|
|
62
|
-
size = "md"
|
|
63
|
-
}) => {
|
|
64
|
-
const [selected, setSelected] = useState(1);
|
|
65
|
-
const [pagesCount, setPagesCount] = useState(1);
|
|
66
|
-
const [list, setList] = useState([]);
|
|
67
|
-
const onPaginationClicked = (item: number) => {
|
|
68
|
-
setSelected(item);
|
|
69
|
-
onPageChange(+item);
|
|
70
|
-
};
|
|
71
|
-
useEffect(() => {
|
|
72
|
-
onPagesCountHandler();
|
|
73
|
-
}, [totalCount]);
|
|
74
|
-
useEffect(() => {
|
|
75
|
-
setSelected(1);
|
|
76
|
-
onPagesCountHandler();
|
|
77
|
-
}, [pageSize]);
|
|
78
|
-
const onPagesCountHandler = () => {
|
|
79
|
-
const totalPages =
|
|
80
|
-
totalCount < pageSize ? 1 : Math.ceil(totalCount / pageSize);
|
|
81
|
-
setPagesCount(totalPages);
|
|
82
|
-
};
|
|
83
|
-
useEffect(() => {
|
|
84
|
-
generatePages();
|
|
85
|
-
}, [selected, pagesCount, totalCount]);
|
|
86
|
-
useEffect(() => {
|
|
87
|
-
if (selectedPage) {
|
|
88
|
-
setSelected(selectedPage);
|
|
89
|
-
}
|
|
90
|
-
}, [selectedPage]);
|
|
91
|
-
|
|
92
|
-
const generatePages = () => {
|
|
93
|
-
const list: any = [];
|
|
94
|
-
if (totalCount > 0) {
|
|
95
|
-
list.push(
|
|
96
|
-
<button
|
|
97
|
-
className={`rounded-lg flex items-center justify-center ${buttonThemes[theme]} ${sizes[size]} ${arrowThemes[theme]}`}
|
|
98
|
-
disabled={selected === 1}
|
|
99
|
-
onClick={() => onPaginationClicked(selected - 1)}
|
|
100
|
-
key={generateUuid()}>
|
|
101
|
-
<ArrowRight className={`${sizesArrow[size]}`}/>
|
|
102
|
-
</button>
|
|
103
|
-
);
|
|
104
|
-
if (pagesCount <= 5) {
|
|
105
|
-
for (let i = 1; i <= pagesCount; i++) {
|
|
106
|
-
list.push(
|
|
107
|
-
<button
|
|
108
|
-
className={`rounded-lg flex items-center justify-center ${sizes[size]} ${selected === i ? activeThemes[activeTheme] : buttonThemes[theme]}`}
|
|
109
|
-
|
|
110
|
-
onClick={() => onPaginationClicked(i)}
|
|
111
|
-
key={generateUuid()}
|
|
112
|
-
>
|
|
113
|
-
{i}
|
|
114
|
-
</button>
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
|
-
} else {
|
|
118
|
-
if (selected > pagesCount - 3) {
|
|
119
|
-
list.push(
|
|
120
|
-
<button
|
|
121
|
-
className={`rounded-lg flex items-center justify-center ${sizes[size]} ${selected === 1 ? activeThemes[activeTheme] : buttonThemes[theme]}`}
|
|
122
|
-
onClick={() => onPaginationClicked(1)}
|
|
123
|
-
key={generateUuid()}
|
|
124
|
-
>
|
|
125
|
-
{1}
|
|
126
|
-
</button>
|
|
127
|
-
);
|
|
128
|
-
list.push(
|
|
129
|
-
<div
|
|
130
|
-
className={`rounded-lg flex items-center justify-center ${dotsThemes[theme]} ${sizes[size]}`}
|
|
131
|
-
key={generateUuid()}>
|
|
132
|
-
...
|
|
133
|
-
</div>
|
|
134
|
-
);
|
|
135
|
-
for (let i = pagesCount - 3; i <= pagesCount; i++) {
|
|
136
|
-
list.push(
|
|
137
|
-
<button
|
|
138
|
-
className={`rounded-lg flex items-center justify-center ${sizes[size]} ${selected === i ? activeThemes[activeTheme] : buttonThemes[theme]}`}
|
|
139
|
-
onClick={() => onPaginationClicked(i)}
|
|
140
|
-
key={generateUuid()}
|
|
141
|
-
>
|
|
142
|
-
{i}
|
|
143
|
-
</button>
|
|
144
|
-
);
|
|
145
|
-
}
|
|
146
|
-
} else {
|
|
147
|
-
const maxPage = selected < 3 ? 4 : selected + 2;
|
|
148
|
-
const fromPage = selected < 3 ? 1 : selected - 1;
|
|
149
|
-
for (let i = fromPage; i <= maxPage; i++) {
|
|
150
|
-
list.push(
|
|
151
|
-
<button
|
|
152
|
-
className={`rounded-lg flex items-center justify-center ${sizes[size]} ${selected === i ? activeThemes[activeTheme] : buttonThemes[theme]}`}
|
|
153
|
-
onClick={() => onPaginationClicked(i)}
|
|
154
|
-
key={generateUuid()}
|
|
155
|
-
>
|
|
156
|
-
{i}
|
|
157
|
-
</button>
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
list.push(
|
|
161
|
-
<div
|
|
162
|
-
className={`rounded-lg flex items-center justify-center ${dotsThemes[theme]} ${sizes[size]}`}
|
|
163
|
-
key={generateUuid()}>
|
|
164
|
-
...
|
|
165
|
-
</div>
|
|
166
|
-
);
|
|
167
|
-
list.push(
|
|
168
|
-
<button
|
|
169
|
-
className={`rounded-lg flex items-center justify-center ${sizes[size]} ${selected === pagesCount ? activeThemes[activeTheme] : buttonThemes[theme]}`}
|
|
170
|
-
onClick={() => onPaginationClicked(pagesCount)}
|
|
171
|
-
key={generateUuid()}
|
|
172
|
-
>
|
|
173
|
-
{pagesCount}
|
|
174
|
-
</button>
|
|
175
|
-
);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
list.push(
|
|
179
|
-
<button
|
|
180
|
-
className={`rounded-lg flex items-center justify-center ${buttonThemes[theme]} ${sizes[size]} ${arrowThemes[theme]}`}
|
|
181
|
-
disabled={selected === pagesCount}
|
|
182
|
-
onClick={() => onPaginationClicked(selected + 1)}
|
|
183
|
-
key={generateUuid()}
|
|
184
|
-
>
|
|
185
|
-
<ArrowLeft className={`${sizesArrow[size]}`}/>
|
|
186
|
-
</button>
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
setList(list);
|
|
190
|
-
};
|
|
191
|
-
return (
|
|
192
|
-
<div className="flex items-center justify-center rounded-xl gap-2">
|
|
193
|
-
{list}
|
|
194
|
-
</div>
|
|
195
|
-
);
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
export default LibPagination;
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
import {FC, forwardRef, useEffect, useImperativeHandle, useState} from "react";
|
|
3
|
-
import Close from '@/assets/icons/close.svg'
|
|
4
|
-
import {useWidth} from '@/hooks/use-width';
|
|
5
|
-
import {addNavigation, onHashChanges, removeNavigation} from "@/utils/navigator/navigator-v2";
|
|
6
|
-
|
|
7
|
-
export interface LibModalProps {
|
|
8
|
-
title?: string;
|
|
9
|
-
children?: React.ReactNode;
|
|
10
|
-
size?: string;
|
|
11
|
-
height?: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface LibModalRef {
|
|
15
|
-
open: () => void;
|
|
16
|
-
close: () => void;
|
|
17
|
-
toggle: () => void;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const Modal = forwardRef<LibModalRef, LibModalProps>(({title, size, height, children}, ref) => {
|
|
21
|
-
const getDeviceWidth = useWidth();
|
|
22
|
-
const isHashChanged = onHashChanges();
|
|
23
|
-
const [isShow, setIsShow] = useState(false);
|
|
24
|
-
|
|
25
|
-
const open = () => setIsShow(true);
|
|
26
|
-
const close = () => setIsShow(false);
|
|
27
|
-
const toggle = () => setIsShow((v) => !v);
|
|
28
|
-
|
|
29
|
-
useImperativeHandle(ref, () => ({open, close, toggle}), []);
|
|
30
|
-
|
|
31
|
-
const onBackdropClick = (e: React.MouseEvent<HTMLDivElement>) => {
|
|
32
|
-
if (e.currentTarget === e.target) close();
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
useEffect(() => {
|
|
36
|
-
if (isHashChanged) {
|
|
37
|
-
close();
|
|
38
|
-
}
|
|
39
|
-
}, [isHashChanged])
|
|
40
|
-
|
|
41
|
-
useEffect(() => {
|
|
42
|
-
if (getDeviceWidth < 1024) {
|
|
43
|
-
if (isShow) {
|
|
44
|
-
addNavigation()
|
|
45
|
-
} else {
|
|
46
|
-
removeNavigation();
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
document.body.style.overflow = isShow ? "hidden" : "auto";
|
|
50
|
-
return () => {
|
|
51
|
-
document.body.style.overflow = "auto";
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
}, [isShow]);
|
|
55
|
-
|
|
56
|
-
return isShow ? (
|
|
57
|
-
<div
|
|
58
|
-
className={`backdrop bg-dark-100/30 fixed items-end justify-center px-4 md:px-10 lg:px-0
|
|
59
|
-
lg:place-items-center flex right-0 top-0 left-0 bottom-0 w-full h-full z-50 duration-200 transition-opacity ${
|
|
60
|
-
isShow ? "opacity-1" : "opacity-0 hidden pointer-events-none"
|
|
61
|
-
}`}
|
|
62
|
-
onClick={onBackdropClick}
|
|
63
|
-
>
|
|
64
|
-
<div
|
|
65
|
-
className={`transform p-3 md:p-5 rounded-t-2xl lg:rounded-2xl bg-grey-100 shadow-xl transition-opacity
|
|
66
|
-
duration-200 lg:h-auto w-full ${
|
|
67
|
-
size || " lg:max-w-2xl"
|
|
68
|
-
} ${isShow ? "opacity-1" : "opacity-0 pointer-events-none"} ${
|
|
69
|
-
getDeviceWidth < 1024 ? `${height ? height : "h-[90vh]"} animate-drawer-bottom-to-top` : `${height ? height : "h-full"} animate-fade-in-translate-y`
|
|
70
|
-
}`}
|
|
71
|
-
>
|
|
72
|
-
<div className="flex items-center justify-between">
|
|
73
|
-
<div className="font-bold text-base lg:text-lg">{title ?? ""}</div>
|
|
74
|
-
<button className="inline-block" onClick={close}>
|
|
75
|
-
<Close className="w-6"/>
|
|
76
|
-
</button>
|
|
77
|
-
</div>
|
|
78
|
-
<div
|
|
79
|
-
className="h-full overflow-y-auto mt-3 md:mt-5 max-h-[calc(100%-40px)] lg:max-h-[calc(100vh-90px)]">
|
|
80
|
-
{children}
|
|
81
|
-
</div>
|
|
82
|
-
</div>
|
|
83
|
-
</div>
|
|
84
|
-
) : <></>;
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
Modal.displayName = "LibModal";
|
|
88
|
-
export default Modal;
|
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
import {FC, useEffect, useState} from "react";
|
|
3
|
-
import AngleDown from "@/assets/icons/angle-down.svg";
|
|
4
|
-
import Close from '@/assets/icons/close.svg';
|
|
5
|
-
import Loading from '@/components/shared/loading/Loading';
|
|
6
|
-
import {useWidth} from '@/hooks/use-width';
|
|
7
|
-
import {useRouter} from 'next/navigation';
|
|
8
|
-
|
|
9
|
-
export interface props {
|
|
10
|
-
list?: any[];
|
|
11
|
-
label?: string;
|
|
12
|
-
title: string;
|
|
13
|
-
value?: string;
|
|
14
|
-
api?: any;
|
|
15
|
-
maxHeight?: string;
|
|
16
|
-
theme?: "secondary";
|
|
17
|
-
hasError?: string | null;
|
|
18
|
-
size?: "md" | "sm";
|
|
19
|
-
onSelectChange?: any;
|
|
20
|
-
selected?: any;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const themes = {
|
|
24
|
-
secondary: {
|
|
25
|
-
input: `border
|
|
26
|
-
bg-transparent
|
|
27
|
-
placeholder:text-secondary-400
|
|
28
|
-
outline-1
|
|
29
|
-
outline-primary-100
|
|
30
|
-
border-secondary-300
|
|
31
|
-
rounded-md
|
|
32
|
-
hover:not:border-primary-100
|
|
33
|
-
focus:outline
|
|
34
|
-
focus:border-primary-100
|
|
35
|
-
|
|
36
|
-
disabled:text-secondary-100
|
|
37
|
-
disabled:border-secondary-500`,
|
|
38
|
-
|
|
39
|
-
label: `text-dark-100
|
|
40
|
-
peer-focus:text-primary-100
|
|
41
|
-
peer-focus:scale-90
|
|
42
|
-
|
|
43
|
-
peer-disabled:text-secondary-400`
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
const sizes = {
|
|
47
|
-
sm: {
|
|
48
|
-
input: "text-xs px-2 py-1",
|
|
49
|
-
label: `px-1 text-xs `,
|
|
50
|
-
},
|
|
51
|
-
md: {
|
|
52
|
-
input: "text-sm px-3 py-2.5",
|
|
53
|
-
label: `px-1 text-xs`,
|
|
54
|
-
},
|
|
55
|
-
}
|
|
56
|
-
const Select: FC<props> = ({
|
|
57
|
-
list, label, hasError,
|
|
58
|
-
title, value, api,
|
|
59
|
-
maxHeight = "max-h-64", theme = "secondary", size = "md",
|
|
60
|
-
onSelectChange,
|
|
61
|
-
selected
|
|
62
|
-
}) => {
|
|
63
|
-
const getDeviceWidth = useWidth();
|
|
64
|
-
const router = useRouter();
|
|
65
|
-
const [isShow, setIsShow] = useState(false);
|
|
66
|
-
const [isLoading, setIsLoading] = useState(true);
|
|
67
|
-
const [localSelected, setLocalSelected] = useState(null);
|
|
68
|
-
const [localList, setLocalList] = useState(null);
|
|
69
|
-
useEffect(() => {
|
|
70
|
-
if (api) {
|
|
71
|
-
setIsLoading(true);
|
|
72
|
-
api().then((res) => {
|
|
73
|
-
setIsLoading(false);
|
|
74
|
-
setLocalList(res?.data?.message ? [] : res.data);
|
|
75
|
-
})
|
|
76
|
-
}
|
|
77
|
-
}, [api]);
|
|
78
|
-
useEffect(() => {
|
|
79
|
-
if (getDeviceWidth < 1024) {
|
|
80
|
-
|
|
81
|
-
if (isShow) {
|
|
82
|
-
router.push('#select');
|
|
83
|
-
document.body.style.overflow = 'hidden';
|
|
84
|
-
} else {
|
|
85
|
-
|
|
86
|
-
if (window.location.hash && !document.referrer.includes('#')) {
|
|
87
|
-
router.back();
|
|
88
|
-
}
|
|
89
|
-
document.body.style.overflow = 'auto';
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}, [isShow]);
|
|
93
|
-
|
|
94
|
-
useEffect(() => {
|
|
95
|
-
const handlePopState = () => {
|
|
96
|
-
setIsShow(false);
|
|
97
|
-
};
|
|
98
|
-
window.addEventListener('popstate', handlePopState);
|
|
99
|
-
return () => {
|
|
100
|
-
window.removeEventListener('popstate', handlePopState);
|
|
101
|
-
};
|
|
102
|
-
}, []);
|
|
103
|
-
|
|
104
|
-
useEffect(() => {
|
|
105
|
-
if (label?.length) {
|
|
106
|
-
setLocalSelected(localList?.find(item => item[label] === selected));
|
|
107
|
-
} else {
|
|
108
|
-
setLocalSelected(selected);
|
|
109
|
-
}
|
|
110
|
-
}, [selected, localList]);
|
|
111
|
-
|
|
112
|
-
const onToggle = () => {
|
|
113
|
-
setIsShow(prevState => !prevState);
|
|
114
|
-
}
|
|
115
|
-
const onToggleEvent = (e) => {
|
|
116
|
-
if (e?.target?.className.toString()?.includes('backdropSelect')) {
|
|
117
|
-
onToggle()
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
const onSelect = (item) => {
|
|
121
|
-
setLocalSelected(item);
|
|
122
|
-
onToggle();
|
|
123
|
-
onSelectChange(item);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const getActiveClass = (item) => {
|
|
127
|
-
if (!localSelected) {
|
|
128
|
-
return "";
|
|
129
|
-
}
|
|
130
|
-
if (label?.length && item[label] === localSelected[label]) {
|
|
131
|
-
return "bg-grey-100"
|
|
132
|
-
}
|
|
133
|
-
if (item === localSelected) {
|
|
134
|
-
return "bg-grey-100"
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
return (
|
|
138
|
-
<div className="relative">
|
|
139
|
-
<label
|
|
140
|
-
className={`cursor-pointer
|
|
141
|
-
${hasError && "!text-danger-100"}`}>
|
|
142
|
-
<span className={`${themes[theme].label} ${sizes[size].label}`}>{title}</span>
|
|
143
|
-
<button type="button"
|
|
144
|
-
className={`relative z-20 flex items-center mt-1 text-base justify-between gap-2 w-full ${localSelected ? "text-dark-100" : "text-grey-300"} ${themes[theme].input} ${sizes[size].input} ${hasError && "!border-danger-100 focus:border-danger-100 outline-danger-100"}`}
|
|
145
|
-
onClick={onToggle}>
|
|
146
|
-
{
|
|
147
|
-
localSelected ? (
|
|
148
|
-
value?.length ? localSelected[value] : localSelected
|
|
149
|
-
) : "انتخاب"
|
|
150
|
-
} <AngleDown
|
|
151
|
-
className={`w-4 h-4 transition ease duration-200 ${!isShow ? "rotate-0" : "rotate-180"}`}/>
|
|
152
|
-
</button>
|
|
153
|
-
</label>
|
|
154
|
-
|
|
155
|
-
{
|
|
156
|
-
isShow ? (
|
|
157
|
-
<div
|
|
158
|
-
className={`overflow-hidden ${getDeviceWidth < 1024 ? "fixed top-0 right-0 h-full w-full z-40" : ""}`}>
|
|
159
|
-
<div
|
|
160
|
-
className={`flex flex-col w-full z-40 bg-light-100 w-full shadow-lg border border-secondary-300 ${getDeviceWidth < 1024 ? "relative h-full pt-1 pb-5 px-5" : `animate-fade-in-translate-y mt-1 rounded-lg absolute ${maxHeight}`} overflow-auto`}>
|
|
161
|
-
{
|
|
162
|
-
api && isLoading ? (
|
|
163
|
-
<div className="py-10 flex justify-center">
|
|
164
|
-
<Loading size="w-7 h-7"/>
|
|
165
|
-
</div>
|
|
166
|
-
) : (
|
|
167
|
-
<>
|
|
168
|
-
{
|
|
169
|
-
getDeviceWidth < 1024 ? (
|
|
170
|
-
<div className="sticky top-0 text-left">
|
|
171
|
-
<button className="p-3" onClick={onToggle}>
|
|
172
|
-
<Close className="w-6"/>
|
|
173
|
-
</button>
|
|
174
|
-
</div>
|
|
175
|
-
) : undefined
|
|
176
|
-
}
|
|
177
|
-
{
|
|
178
|
-
localList?.map((item, index) => {
|
|
179
|
-
return (
|
|
180
|
-
<>
|
|
181
|
-
<button type="button" onClick={() => onSelect(item)} key={index}
|
|
182
|
-
className={`text-right py-2.5 px-4 text-base hover:bg-grey-100 rounded-lg ${getActiveClass(item)}`}>
|
|
183
|
-
{value?.length ? item[value] : item}
|
|
184
|
-
</button>
|
|
185
|
-
</>
|
|
186
|
-
)
|
|
187
|
-
})
|
|
188
|
-
}
|
|
189
|
-
</>
|
|
190
|
-
)
|
|
191
|
-
}
|
|
192
|
-
</div>
|
|
193
|
-
<div
|
|
194
|
-
className={`backdropSelect fixed top-0 left-0 bottom-0 w-full h-full z-30`}
|
|
195
|
-
onClick={onToggleEvent}>
|
|
196
|
-
|
|
197
|
-
</div>
|
|
198
|
-
</div>
|
|
199
|
-
) : undefined
|
|
200
|
-
}
|
|
201
|
-
{
|
|
202
|
-
hasError &&
|
|
203
|
-
<p className="text-xs mt-1 text-danger-100">{hasError}</p>
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
</div>
|
|
207
|
-
);
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
export default Select;
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
import {FC, useEffect, useRef, useState} from "react";
|
|
3
|
-
|
|
4
|
-
interface TabType {
|
|
5
|
-
name: string;
|
|
6
|
-
label: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export interface props {
|
|
10
|
-
tabs: TabType[],
|
|
11
|
-
onTabEmit?: any,
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const LibTabs: FC<props> = ({tabs, onTabEmit}) => {
|
|
15
|
-
const [isActive, setIsActive] = useState(0);
|
|
16
|
-
const onTabClicked = (item: TabType, index: number) => {
|
|
17
|
-
setIsActive(index)
|
|
18
|
-
onTabEmit(item)
|
|
19
|
-
}
|
|
20
|
-
return (
|
|
21
|
-
<div className="flex border-2 border-primary-100 rounded-lg overflow-hidden divide-x-2 divide-x-reverse divide-primary-100">
|
|
22
|
-
{
|
|
23
|
-
tabs.map((item: TabType, index: number) => {
|
|
24
|
-
return <button className={`transition font-bold grow p-2 ${isActive === index ? "bg-primary-100 text-light-100" : ""}`} key = {index} onClick={() => onTabClicked(item, index)}>{item.label}</button>
|
|
25
|
-
})
|
|
26
|
-
}
|
|
27
|
-
</div>
|
|
28
|
-
);
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export default LibTabs;
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
import {FC} from "react";
|
|
3
|
-
|
|
4
|
-
export interface props {
|
|
5
|
-
classNames?: string;
|
|
6
|
-
placeholder: string;
|
|
7
|
-
label: string;
|
|
8
|
-
theme?: "secondary";
|
|
9
|
-
size?: "md" | "sm";
|
|
10
|
-
hasError?: string | null;
|
|
11
|
-
register?: any;
|
|
12
|
-
name?: string;
|
|
13
|
-
isDisabled?: boolean;
|
|
14
|
-
rows?: number;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const themes = {
|
|
18
|
-
secondary: {
|
|
19
|
-
input: `border
|
|
20
|
-
bg-transparent
|
|
21
|
-
placeholder:text-secondary-400
|
|
22
|
-
outline-1
|
|
23
|
-
outline-primary-100
|
|
24
|
-
border-secondary-300
|
|
25
|
-
rounded-md
|
|
26
|
-
hover:not:border-primary-100
|
|
27
|
-
focus:outline
|
|
28
|
-
focus:border-primary-100
|
|
29
|
-
|
|
30
|
-
disabled:text-secondary-100
|
|
31
|
-
disabled:border-secondary-500`,
|
|
32
|
-
|
|
33
|
-
label: `text-dark-100
|
|
34
|
-
peer-focus:text-primary-100
|
|
35
|
-
peer-focus:scale-90
|
|
36
|
-
|
|
37
|
-
peer-disabled:text-secondary-400`
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const sizes = {
|
|
42
|
-
sm: {
|
|
43
|
-
input: "text-xs px-2 py-1",
|
|
44
|
-
label: `px-1 text-xs `,
|
|
45
|
-
},
|
|
46
|
-
md: {
|
|
47
|
-
input: "text-sm px-3 py-2",
|
|
48
|
-
label: `px-1 text-xs`,
|
|
49
|
-
},
|
|
50
|
-
}
|
|
51
|
-
const Textarea: FC<props> = ({
|
|
52
|
-
rows = 3, placeholder, classNames = "",
|
|
53
|
-
label, theme = "secondary", size = "md", hasError,
|
|
54
|
-
register, name, isDisabled = false,
|
|
55
|
-
...otherProps
|
|
56
|
-
}) => {
|
|
57
|
-
return (
|
|
58
|
-
<div>
|
|
59
|
-
<label
|
|
60
|
-
htmlFor={name}
|
|
61
|
-
className={`cursor-text transition-all duration-200
|
|
62
|
-
transform ${themes[theme].label} ${sizes[size].label}
|
|
63
|
-
${hasError && "!text-danger-100"}`}>
|
|
64
|
-
{label}
|
|
65
|
-
<textarea
|
|
66
|
-
disabled={isDisabled}
|
|
67
|
-
rows={rows}
|
|
68
|
-
id={name}
|
|
69
|
-
{...register}
|
|
70
|
-
{...otherProps}
|
|
71
|
-
name={name}
|
|
72
|
-
className={`mt-1 w-full bg-white transition duration-200 ease ${themes[theme].input} ${sizes[size].input}
|
|
73
|
-
${hasError && "!border-danger-100 focus:border-danger-100 outline-danger-100"} ${classNames}`}
|
|
74
|
-
placeholder={placeholder}
|
|
75
|
-
/>
|
|
76
|
-
</label>
|
|
77
|
-
{
|
|
78
|
-
hasError &&
|
|
79
|
-
<p className="text-xs mt-1 text-danger-100">{hasError}</p>
|
|
80
|
-
}
|
|
81
|
-
</div>
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
);
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
export default Textarea;
|
package/eslint.config.mjs
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { dirname } from "path";
|
|
2
|
-
import { fileURLToPath } from "url";
|
|
3
|
-
import { FlatCompat } from "@eslint/eslintrc";
|
|
4
|
-
|
|
5
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
-
const __dirname = dirname(__filename);
|
|
7
|
-
|
|
8
|
-
const compat = new FlatCompat({
|
|
9
|
-
baseDirectory: __dirname,
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
const eslintConfig = [
|
|
13
|
-
...compat.extends("next/core-web-vitals", "next/typescript"),
|
|
14
|
-
{
|
|
15
|
-
ignores: [
|
|
16
|
-
"node_modules/**",
|
|
17
|
-
".next/**",
|
|
18
|
-
"out/**",
|
|
19
|
-
"build/**",
|
|
20
|
-
"next-env.d.ts",
|
|
21
|
-
],
|
|
22
|
-
},
|
|
23
|
-
];
|
|
24
|
-
|
|
25
|
-
export default eslintConfig;
|
package/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
module.exports = require('./components');
|
package/next.config.ts
DELETED
package/public/file.svg
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>
|
package/public/globe.svg
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
|
package/public/next.svg
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
|
package/public/vercel.svg
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>
|
package/public/window.svg
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>
|
package/tsconfig.json
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2017",
|
|
4
|
-
"lib": ["dom", "dom.iterable", "esnext"],
|
|
5
|
-
"allowJs": true,
|
|
6
|
-
"skipLibCheck": true,
|
|
7
|
-
"strict": true,
|
|
8
|
-
"noEmit": true,
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"module": "esnext",
|
|
11
|
-
"moduleResolution": "bundler",
|
|
12
|
-
"resolveJsonModule": true,
|
|
13
|
-
"isolatedModules": true,
|
|
14
|
-
"jsx": "preserve",
|
|
15
|
-
"incremental": true,
|
|
16
|
-
"plugins": [
|
|
17
|
-
{
|
|
18
|
-
"name": "next"
|
|
19
|
-
}
|
|
20
|
-
],
|
|
21
|
-
"paths": {
|
|
22
|
-
"@/*": ["./*"]
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
|
-
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
26
|
-
"exclude": ["node_modules"]
|
|
27
|
-
}
|