gd-ui-library 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +122 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +96 -0
- package/dist/index.js.map +1 -0
- package/package.json +25 -0
- package/rollup.config.js +29 -0
- package/src/components/Button/Button.tsx +70 -0
- package/src/components/Input/Input.tsx +117 -0
- package/src/index.ts +1 -0
- package/src/lib/utils.ts +5 -0
- package/src/utils/cn.ts +5 -0
- package/tsconfig.json +16 -0
- package/tsup.config.ts +10 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
|
|
19
|
+
// src/index.ts
|
|
20
|
+
var index_exports = {};
|
|
21
|
+
__export(index_exports, {
|
|
22
|
+
Input: () => Input
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(index_exports);
|
|
25
|
+
|
|
26
|
+
// src/components/Input/Input.tsx
|
|
27
|
+
var import_react = require("react");
|
|
28
|
+
|
|
29
|
+
// src/utils/cn.ts
|
|
30
|
+
var import_clsx = require("clsx");
|
|
31
|
+
function cn(...inputs) {
|
|
32
|
+
return (0, import_clsx.clsx)(inputs);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// src/components/Input/Input.tsx
|
|
36
|
+
var import_lucide_react = require("lucide-react");
|
|
37
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
38
|
+
var Input = (0, import_react.forwardRef)(({
|
|
39
|
+
label,
|
|
40
|
+
error,
|
|
41
|
+
description,
|
|
42
|
+
required,
|
|
43
|
+
leftIcon,
|
|
44
|
+
rightIcon,
|
|
45
|
+
size = "md",
|
|
46
|
+
variant = "default",
|
|
47
|
+
className,
|
|
48
|
+
disabled,
|
|
49
|
+
id,
|
|
50
|
+
...props
|
|
51
|
+
}, ref) => {
|
|
52
|
+
const inputId = id || `input-${Math.random().toString(36).substr(2, 9)}`;
|
|
53
|
+
const sizeClasses = {
|
|
54
|
+
sm: "h-8 text-xs px-3 py-1",
|
|
55
|
+
md: "h-10 text-sm px-4 py-2",
|
|
56
|
+
lg: "h-12 text-base px-5 py-3"
|
|
57
|
+
}[size];
|
|
58
|
+
const variantClasses = {
|
|
59
|
+
default: "border border-gray-300 bg-white focus:border-blue-500 focus:ring-2 focus:ring-blue-200",
|
|
60
|
+
filled: "bg-gray-100 border border-transparent focus:bg-white focus:border-blue-500 focus:ring-2 focus:ring-blue-200",
|
|
61
|
+
unstyled: "border-none bg-transparent p-0 focus:ring-0"
|
|
62
|
+
}[variant];
|
|
63
|
+
const errorClasses = error ? "border-red-500 focus:border-red-500 focus:ring-red-200" : "";
|
|
64
|
+
const disabledClasses = disabled ? "bg-gray-100 cursor-not-allowed opacity-60" : "";
|
|
65
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "w-full", children: [
|
|
66
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
67
|
+
"label",
|
|
68
|
+
{
|
|
69
|
+
htmlFor: inputId,
|
|
70
|
+
className: cn(
|
|
71
|
+
"block text-sm font-medium mb-1.5",
|
|
72
|
+
disabled ? "text-gray-400 cursor-not-allowed" : "text-gray-700"
|
|
73
|
+
),
|
|
74
|
+
children: [
|
|
75
|
+
label,
|
|
76
|
+
required && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-red-500 ml-1", children: "*" })
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
),
|
|
80
|
+
description && !error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs text-gray-500 mb-2", children: description }),
|
|
81
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative", children: [
|
|
82
|
+
leftIcon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: cn(
|
|
83
|
+
"absolute left-3 top-1/2 -translate-y-1/2",
|
|
84
|
+
error ? "text-red-500" : "text-gray-400"
|
|
85
|
+
), children: leftIcon }),
|
|
86
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
87
|
+
"input",
|
|
88
|
+
{
|
|
89
|
+
ref,
|
|
90
|
+
id: inputId,
|
|
91
|
+
disabled,
|
|
92
|
+
"aria-invalid": !!error,
|
|
93
|
+
className: cn(
|
|
94
|
+
"w-full rounded-md transition-all duration-150 outline-none",
|
|
95
|
+
sizeClasses,
|
|
96
|
+
variantClasses,
|
|
97
|
+
errorClasses,
|
|
98
|
+
disabledClasses,
|
|
99
|
+
leftIcon && "pl-10",
|
|
100
|
+
rightIcon && "pr-10",
|
|
101
|
+
className
|
|
102
|
+
),
|
|
103
|
+
...props
|
|
104
|
+
}
|
|
105
|
+
),
|
|
106
|
+
rightIcon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: cn(
|
|
107
|
+
"absolute right-3 top-1/2 -translate-y-1/2",
|
|
108
|
+
error ? "text-red-500" : "text-gray-400"
|
|
109
|
+
), children: rightIcon })
|
|
110
|
+
] }),
|
|
111
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "flex items-center gap-1 mt-1.5 text-xs text-red-500", children: [
|
|
112
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.AlertCircle, { className: "w-3.5 h-3.5" }),
|
|
113
|
+
error
|
|
114
|
+
] })
|
|
115
|
+
] });
|
|
116
|
+
});
|
|
117
|
+
Input.displayName = "Input";
|
|
118
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
119
|
+
0 && (module.exports = {
|
|
120
|
+
Input
|
|
121
|
+
});
|
|
122
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/components/Input/Input.tsx","../src/utils/cn.ts"],"sourcesContent":["export * from \"./components/Input/Input\"; ","import React, { forwardRef } from 'react';\r\nimport { cn } from '../../utils/cn';\r\nimport { AlertCircle } from 'lucide-react';\r\n\r\nexport interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> {\r\n label?: string;\r\n error?: string;\r\n description?: string;\r\n required?: boolean;\r\n leftIcon?: React.ReactNode;\r\n rightIcon?: React.ReactNode;\r\n size?: 'sm' | 'md' | 'lg';\r\n variant?: 'default' | 'filled' | 'unstyled';\r\n}\r\n\r\nexport const Input = forwardRef<HTMLInputElement, InputProps>(({\r\n label,\r\n error,\r\n description,\r\n required,\r\n leftIcon,\r\n rightIcon,\r\n size = 'md',\r\n variant = 'default',\r\n className,\r\n disabled,\r\n id,\r\n ...props\r\n}, ref) => {\r\n const inputId = id || `input-${Math.random().toString(36).substr(2, 9)}`; \r\n const sizeClasses = {\r\n sm: 'h-8 text-xs px-3 py-1',\r\n md: 'h-10 text-sm px-4 py-2',\r\n lg: 'h-12 text-base px-5 py-3',\r\n }[size];\r\n const variantClasses = {\r\n default: 'border border-gray-300 bg-white focus:border-blue-500 focus:ring-2 focus:ring-blue-200',\r\n filled: 'bg-gray-100 border border-transparent focus:bg-white focus:border-blue-500 focus:ring-2 focus:ring-blue-200',\r\n unstyled: 'border-none bg-transparent p-0 focus:ring-0',\r\n }[variant];\r\n const errorClasses = error\r\n ? 'border-red-500 focus:border-red-500 focus:ring-red-200'\r\n : '';\r\n const disabledClasses = disabled\r\n ? 'bg-gray-100 cursor-not-allowed opacity-60'\r\n : '';\r\n return (\r\n <div className=\"w-full\">\r\n {/* Label */}\r\n {label && (\r\n <label\r\n htmlFor={inputId}\r\n className={cn(\r\n \"block text-sm font-medium mb-1.5\",\r\n disabled ? \"text-gray-400 cursor-not-allowed\" : \"text-gray-700\"\r\n )}\r\n >\r\n {label}\r\n {required && <span className=\"text-red-500 ml-1\">*</span>}\r\n </label>\r\n )}\r\n {/* Description */}\r\n {description && !error && (\r\n <p className=\"text-xs text-gray-500 mb-2\">{description}</p>\r\n )}\r\n {/* Input Container */}\r\n <div className=\"relative\">\r\n {/* Left Icon */}\r\n {leftIcon && (\r\n <span className={cn(\r\n \"absolute left-3 top-1/2 -translate-y-1/2\",\r\n error ? \"text-red-500\" : \"text-gray-400\"\r\n )}>\r\n {leftIcon}\r\n </span>\r\n )}\r\n {/* Input */}\r\n <input\r\n ref={ref}\r\n id={inputId}\r\n disabled={disabled}\r\n aria-invalid={!!error}\r\n className={cn(\r\n \"w-full rounded-md transition-all duration-150 outline-none\",\r\n sizeClasses,\r\n variantClasses,\r\n errorClasses,\r\n disabledClasses,\r\n leftIcon && \"pl-10\",\r\n rightIcon && \"pr-10\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n {/* Right Icon */}\r\n {rightIcon && (\r\n <span className={cn(\r\n \"absolute right-3 top-1/2 -translate-y-1/2\",\r\n error ? \"text-red-500\" : \"text-gray-400\"\r\n )}>\r\n {rightIcon}\r\n </span>\r\n )}\r\n </div>\r\n\r\n {/* Error Message */}\r\n {error && (\r\n <p className=\"flex items-center gap-1 mt-1.5 text-xs text-red-500\">\r\n <AlertCircle className=\"w-3.5 h-3.5\" />\r\n {error}\r\n </p>\r\n )}\r\n </div>\r\n );\r\n});\r\n\r\nInput.displayName = 'Input';","import { clsx, type ClassValue } from \"clsx\"\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return clsx(inputs)\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,mBAAkC;;;ACAlC,kBAAsC;AAE/B,SAAS,MAAM,QAAsB;AAC1C,aAAO,kBAAK,MAAM;AACpB;;;ADFA,0BAA4B;AAgDpB;AAnCD,IAAM,YAAQ,yBAAyC,CAAC;AAAA,EAC7D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAG,QAAQ;AACT,QAAM,UAAU,MAAM,SAAS,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC,CAAC;AACtE,QAAM,cAAc;AAAA,IAClB,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,EACN,EAAE,IAAI;AACN,QAAM,iBAAiB;AAAA,IACrB,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ,EAAE,OAAO;AACT,QAAM,eAAe,QACjB,2DACA;AACJ,QAAM,kBAAkB,WACpB,8CACA;AACJ,SACE,6CAAC,SAAI,WAAU,UAEZ;AAAA,aACC;AAAA,MAAC;AAAA;AAAA,QACC,SAAS;AAAA,QACT,WAAW;AAAA,UACT;AAAA,UACA,WAAW,qCAAqC;AAAA,QAClD;AAAA,QAEC;AAAA;AAAA,UACA,YAAY,4CAAC,UAAK,WAAU,qBAAoB,eAAC;AAAA;AAAA;AAAA,IACpD;AAAA,IAGD,eAAe,CAAC,SACf,4CAAC,OAAE,WAAU,8BAA8B,uBAAY;AAAA,IAGzD,6CAAC,SAAI,WAAU,YAEZ;AAAA,kBACC,4CAAC,UAAK,WAAW;AAAA,QACf;AAAA,QACA,QAAQ,iBAAiB;AAAA,MAC3B,GACG,oBACH;AAAA,MAGF;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,IAAI;AAAA,UACJ;AAAA,UACA,gBAAc,CAAC,CAAC;AAAA,UAChB,WAAW;AAAA,YACT;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,YAAY;AAAA,YACZ,aAAa;AAAA,YACb;AAAA,UACF;AAAA,UACC,GAAG;AAAA;AAAA,MACN;AAAA,MAEC,aACC,4CAAC,UAAK,WAAW;AAAA,QACf;AAAA,QACA,QAAQ,iBAAiB;AAAA,MAC3B,GACG,qBACH;AAAA,OAEJ;AAAA,IAGC,SACC,6CAAC,OAAE,WAAU,uDACX;AAAA,kDAAC,mCAAY,WAAU,eAAc;AAAA,MACpC;AAAA,OACH;AAAA,KAEJ;AAEJ,CAAC;AAED,MAAM,cAAc;","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> {
|
|
4
|
+
label?: string;
|
|
5
|
+
error?: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
required?: boolean;
|
|
8
|
+
leftIcon?: React.ReactNode;
|
|
9
|
+
rightIcon?: React.ReactNode;
|
|
10
|
+
size?: 'sm' | 'md' | 'lg';
|
|
11
|
+
variant?: 'default' | 'filled' | 'unstyled';
|
|
12
|
+
}
|
|
13
|
+
declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
|
|
14
|
+
|
|
15
|
+
export { Input, type InputProps };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> {
|
|
4
|
+
label?: string;
|
|
5
|
+
error?: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
required?: boolean;
|
|
8
|
+
leftIcon?: React.ReactNode;
|
|
9
|
+
rightIcon?: React.ReactNode;
|
|
10
|
+
size?: 'sm' | 'md' | 'lg';
|
|
11
|
+
variant?: 'default' | 'filled' | 'unstyled';
|
|
12
|
+
}
|
|
13
|
+
declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
|
|
14
|
+
|
|
15
|
+
export { Input, type InputProps };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// src/components/Input/Input.tsx
|
|
2
|
+
import { forwardRef } from "react";
|
|
3
|
+
|
|
4
|
+
// src/utils/cn.ts
|
|
5
|
+
import { clsx } from "clsx";
|
|
6
|
+
function cn(...inputs) {
|
|
7
|
+
return clsx(inputs);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// src/components/Input/Input.tsx
|
|
11
|
+
import { AlertCircle } from "lucide-react";
|
|
12
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
13
|
+
var Input = forwardRef(({
|
|
14
|
+
label,
|
|
15
|
+
error,
|
|
16
|
+
description,
|
|
17
|
+
required,
|
|
18
|
+
leftIcon,
|
|
19
|
+
rightIcon,
|
|
20
|
+
size = "md",
|
|
21
|
+
variant = "default",
|
|
22
|
+
className,
|
|
23
|
+
disabled,
|
|
24
|
+
id,
|
|
25
|
+
...props
|
|
26
|
+
}, ref) => {
|
|
27
|
+
const inputId = id || `input-${Math.random().toString(36).substr(2, 9)}`;
|
|
28
|
+
const sizeClasses = {
|
|
29
|
+
sm: "h-8 text-xs px-3 py-1",
|
|
30
|
+
md: "h-10 text-sm px-4 py-2",
|
|
31
|
+
lg: "h-12 text-base px-5 py-3"
|
|
32
|
+
}[size];
|
|
33
|
+
const variantClasses = {
|
|
34
|
+
default: "border border-gray-300 bg-white focus:border-blue-500 focus:ring-2 focus:ring-blue-200",
|
|
35
|
+
filled: "bg-gray-100 border border-transparent focus:bg-white focus:border-blue-500 focus:ring-2 focus:ring-blue-200",
|
|
36
|
+
unstyled: "border-none bg-transparent p-0 focus:ring-0"
|
|
37
|
+
}[variant];
|
|
38
|
+
const errorClasses = error ? "border-red-500 focus:border-red-500 focus:ring-red-200" : "";
|
|
39
|
+
const disabledClasses = disabled ? "bg-gray-100 cursor-not-allowed opacity-60" : "";
|
|
40
|
+
return /* @__PURE__ */ jsxs("div", { className: "w-full", children: [
|
|
41
|
+
label && /* @__PURE__ */ jsxs(
|
|
42
|
+
"label",
|
|
43
|
+
{
|
|
44
|
+
htmlFor: inputId,
|
|
45
|
+
className: cn(
|
|
46
|
+
"block text-sm font-medium mb-1.5",
|
|
47
|
+
disabled ? "text-gray-400 cursor-not-allowed" : "text-gray-700"
|
|
48
|
+
),
|
|
49
|
+
children: [
|
|
50
|
+
label,
|
|
51
|
+
required && /* @__PURE__ */ jsx("span", { className: "text-red-500 ml-1", children: "*" })
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
),
|
|
55
|
+
description && !error && /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mb-2", children: description }),
|
|
56
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
57
|
+
leftIcon && /* @__PURE__ */ jsx("span", { className: cn(
|
|
58
|
+
"absolute left-3 top-1/2 -translate-y-1/2",
|
|
59
|
+
error ? "text-red-500" : "text-gray-400"
|
|
60
|
+
), children: leftIcon }),
|
|
61
|
+
/* @__PURE__ */ jsx(
|
|
62
|
+
"input",
|
|
63
|
+
{
|
|
64
|
+
ref,
|
|
65
|
+
id: inputId,
|
|
66
|
+
disabled,
|
|
67
|
+
"aria-invalid": !!error,
|
|
68
|
+
className: cn(
|
|
69
|
+
"w-full rounded-md transition-all duration-150 outline-none",
|
|
70
|
+
sizeClasses,
|
|
71
|
+
variantClasses,
|
|
72
|
+
errorClasses,
|
|
73
|
+
disabledClasses,
|
|
74
|
+
leftIcon && "pl-10",
|
|
75
|
+
rightIcon && "pr-10",
|
|
76
|
+
className
|
|
77
|
+
),
|
|
78
|
+
...props
|
|
79
|
+
}
|
|
80
|
+
),
|
|
81
|
+
rightIcon && /* @__PURE__ */ jsx("span", { className: cn(
|
|
82
|
+
"absolute right-3 top-1/2 -translate-y-1/2",
|
|
83
|
+
error ? "text-red-500" : "text-gray-400"
|
|
84
|
+
), children: rightIcon })
|
|
85
|
+
] }),
|
|
86
|
+
error && /* @__PURE__ */ jsxs("p", { className: "flex items-center gap-1 mt-1.5 text-xs text-red-500", children: [
|
|
87
|
+
/* @__PURE__ */ jsx(AlertCircle, { className: "w-3.5 h-3.5" }),
|
|
88
|
+
error
|
|
89
|
+
] })
|
|
90
|
+
] });
|
|
91
|
+
});
|
|
92
|
+
Input.displayName = "Input";
|
|
93
|
+
export {
|
|
94
|
+
Input
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/Input/Input.tsx","../src/utils/cn.ts"],"sourcesContent":["import React, { forwardRef } from 'react';\r\nimport { cn } from '../../utils/cn';\r\nimport { AlertCircle } from 'lucide-react';\r\n\r\nexport interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> {\r\n label?: string;\r\n error?: string;\r\n description?: string;\r\n required?: boolean;\r\n leftIcon?: React.ReactNode;\r\n rightIcon?: React.ReactNode;\r\n size?: 'sm' | 'md' | 'lg';\r\n variant?: 'default' | 'filled' | 'unstyled';\r\n}\r\n\r\nexport const Input = forwardRef<HTMLInputElement, InputProps>(({\r\n label,\r\n error,\r\n description,\r\n required,\r\n leftIcon,\r\n rightIcon,\r\n size = 'md',\r\n variant = 'default',\r\n className,\r\n disabled,\r\n id,\r\n ...props\r\n}, ref) => {\r\n const inputId = id || `input-${Math.random().toString(36).substr(2, 9)}`; \r\n const sizeClasses = {\r\n sm: 'h-8 text-xs px-3 py-1',\r\n md: 'h-10 text-sm px-4 py-2',\r\n lg: 'h-12 text-base px-5 py-3',\r\n }[size];\r\n const variantClasses = {\r\n default: 'border border-gray-300 bg-white focus:border-blue-500 focus:ring-2 focus:ring-blue-200',\r\n filled: 'bg-gray-100 border border-transparent focus:bg-white focus:border-blue-500 focus:ring-2 focus:ring-blue-200',\r\n unstyled: 'border-none bg-transparent p-0 focus:ring-0',\r\n }[variant];\r\n const errorClasses = error\r\n ? 'border-red-500 focus:border-red-500 focus:ring-red-200'\r\n : '';\r\n const disabledClasses = disabled\r\n ? 'bg-gray-100 cursor-not-allowed opacity-60'\r\n : '';\r\n return (\r\n <div className=\"w-full\">\r\n {/* Label */}\r\n {label && (\r\n <label\r\n htmlFor={inputId}\r\n className={cn(\r\n \"block text-sm font-medium mb-1.5\",\r\n disabled ? \"text-gray-400 cursor-not-allowed\" : \"text-gray-700\"\r\n )}\r\n >\r\n {label}\r\n {required && <span className=\"text-red-500 ml-1\">*</span>}\r\n </label>\r\n )}\r\n {/* Description */}\r\n {description && !error && (\r\n <p className=\"text-xs text-gray-500 mb-2\">{description}</p>\r\n )}\r\n {/* Input Container */}\r\n <div className=\"relative\">\r\n {/* Left Icon */}\r\n {leftIcon && (\r\n <span className={cn(\r\n \"absolute left-3 top-1/2 -translate-y-1/2\",\r\n error ? \"text-red-500\" : \"text-gray-400\"\r\n )}>\r\n {leftIcon}\r\n </span>\r\n )}\r\n {/* Input */}\r\n <input\r\n ref={ref}\r\n id={inputId}\r\n disabled={disabled}\r\n aria-invalid={!!error}\r\n className={cn(\r\n \"w-full rounded-md transition-all duration-150 outline-none\",\r\n sizeClasses,\r\n variantClasses,\r\n errorClasses,\r\n disabledClasses,\r\n leftIcon && \"pl-10\",\r\n rightIcon && \"pr-10\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n {/* Right Icon */}\r\n {rightIcon && (\r\n <span className={cn(\r\n \"absolute right-3 top-1/2 -translate-y-1/2\",\r\n error ? \"text-red-500\" : \"text-gray-400\"\r\n )}>\r\n {rightIcon}\r\n </span>\r\n )}\r\n </div>\r\n\r\n {/* Error Message */}\r\n {error && (\r\n <p className=\"flex items-center gap-1 mt-1.5 text-xs text-red-500\">\r\n <AlertCircle className=\"w-3.5 h-3.5\" />\r\n {error}\r\n </p>\r\n )}\r\n </div>\r\n );\r\n});\r\n\r\nInput.displayName = 'Input';","import { clsx, type ClassValue } from \"clsx\"\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return clsx(inputs)\r\n}\r\n"],"mappings":";AAAA,SAAgB,kBAAkB;;;ACAlC,SAAS,YAA6B;AAE/B,SAAS,MAAM,QAAsB;AAC1C,SAAO,KAAK,MAAM;AACpB;;;ADFA,SAAS,mBAAmB;AAgDpB,SAQe,KARf;AAnCD,IAAM,QAAQ,WAAyC,CAAC;AAAA,EAC7D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAG,QAAQ;AACT,QAAM,UAAU,MAAM,SAAS,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC,CAAC;AACtE,QAAM,cAAc;AAAA,IAClB,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,EACN,EAAE,IAAI;AACN,QAAM,iBAAiB;AAAA,IACrB,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ,EAAE,OAAO;AACT,QAAM,eAAe,QACjB,2DACA;AACJ,QAAM,kBAAkB,WACpB,8CACA;AACJ,SACE,qBAAC,SAAI,WAAU,UAEZ;AAAA,aACC;AAAA,MAAC;AAAA;AAAA,QACC,SAAS;AAAA,QACT,WAAW;AAAA,UACT;AAAA,UACA,WAAW,qCAAqC;AAAA,QAClD;AAAA,QAEC;AAAA;AAAA,UACA,YAAY,oBAAC,UAAK,WAAU,qBAAoB,eAAC;AAAA;AAAA;AAAA,IACpD;AAAA,IAGD,eAAe,CAAC,SACf,oBAAC,OAAE,WAAU,8BAA8B,uBAAY;AAAA,IAGzD,qBAAC,SAAI,WAAU,YAEZ;AAAA,kBACC,oBAAC,UAAK,WAAW;AAAA,QACf;AAAA,QACA,QAAQ,iBAAiB;AAAA,MAC3B,GACG,oBACH;AAAA,MAGF;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,IAAI;AAAA,UACJ;AAAA,UACA,gBAAc,CAAC,CAAC;AAAA,UAChB,WAAW;AAAA,YACT;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,YAAY;AAAA,YACZ,aAAa;AAAA,YACb;AAAA,UACF;AAAA,UACC,GAAG;AAAA;AAAA,MACN;AAAA,MAEC,aACC,oBAAC,UAAK,WAAW;AAAA,QACf;AAAA,QACA,QAAQ,iBAAiB;AAAA,MAC3B,GACG,qBACH;AAAA,OAEJ;AAAA,IAGC,SACC,qBAAC,OAAE,WAAU,uDACX;AAAA,0BAAC,eAAY,WAAU,eAAc;AAAA,MACpC;AAAA,OACH;AAAA,KAEJ;AAEJ,CAAC;AAED,MAAM,cAAc;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gd-ui-library",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "tsup",
|
|
8
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [],
|
|
11
|
+
"author": "",
|
|
12
|
+
"license": "ISC",
|
|
13
|
+
"type": "commonjs",
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/react": "^19.2.14",
|
|
16
|
+
"@types/react-dom": "^19.2.3",
|
|
17
|
+
"react": "^19.2.4",
|
|
18
|
+
"tsup": "^8.5.1",
|
|
19
|
+
"typescript": "^5.9.3"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"clsx": "^2.1.1",
|
|
23
|
+
"lucide-react": "^0.575.0"
|
|
24
|
+
}
|
|
25
|
+
}
|
package/rollup.config.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// rollup.config.js
|
|
2
|
+
import typescript from '@rollup/plugin-typescript';
|
|
3
|
+
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
|
|
4
|
+
import commonjs from '@rollup/plugin-commonjs';
|
|
5
|
+
import resolve from '@rollup/plugin-node-resolve';
|
|
6
|
+
import pkg from './package.json';
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
input: 'src/index.ts',
|
|
10
|
+
output: [
|
|
11
|
+
{
|
|
12
|
+
file: pkg.main,
|
|
13
|
+
format: 'cjs',
|
|
14
|
+
sourcemap: true
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
file: pkg.module,
|
|
18
|
+
format: 'esm',
|
|
19
|
+
sourcemap: true
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
plugins: [
|
|
23
|
+
peerDepsExternal(),
|
|
24
|
+
resolve(),
|
|
25
|
+
commonjs(),
|
|
26
|
+
typescript({ tsconfig: './tsconfig.json' })
|
|
27
|
+
],
|
|
28
|
+
external: ['react', 'react-dom']
|
|
29
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import React, { ButtonHTMLAttributes, forwardRef } from "react";
|
|
2
|
+
import { cn } from "../../utils/cn";
|
|
3
|
+
|
|
4
|
+
export interface ButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'size'> {
|
|
5
|
+
label?: string;
|
|
6
|
+
error?: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
required?: boolean;
|
|
9
|
+
leftIcon?: React.ReactNode;
|
|
10
|
+
rightIcon?: React.ReactNode;
|
|
11
|
+
size?: 'sm' | 'md' | 'lg';
|
|
12
|
+
variant?: 'default' | 'filled' | 'unstyled';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
16
|
+
({
|
|
17
|
+
className,
|
|
18
|
+
label,
|
|
19
|
+
error,
|
|
20
|
+
description,
|
|
21
|
+
required,
|
|
22
|
+
leftIcon,
|
|
23
|
+
rightIcon,
|
|
24
|
+
size = 'md',
|
|
25
|
+
variant = 'default',
|
|
26
|
+
children,
|
|
27
|
+
...props
|
|
28
|
+
}, ref) => {
|
|
29
|
+
// Base styles
|
|
30
|
+
const baseStyles = "inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none";
|
|
31
|
+
|
|
32
|
+
// Size variants
|
|
33
|
+
const sizeStyles = {
|
|
34
|
+
sm: "px-3 py-1.5 text-sm rounded-md",
|
|
35
|
+
md: "px-4 py-2 text-sm rounded-md",
|
|
36
|
+
lg: "px-6 py-3 text-base rounded-lg"
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// Style variants
|
|
40
|
+
const variantStyles = {
|
|
41
|
+
default: "bg-white text-gray-900 border border-gray-300 hover:bg-gray-50 focus:ring-blue-500",
|
|
42
|
+
filled: "bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500",
|
|
43
|
+
unstyled: ""
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<button
|
|
48
|
+
ref={ref}
|
|
49
|
+
className={cn(
|
|
50
|
+
baseStyles,
|
|
51
|
+
sizeStyles[size],
|
|
52
|
+
variantStyles[variant],
|
|
53
|
+
error && "border-red-500 focus:ring-red-500",
|
|
54
|
+
className
|
|
55
|
+
)}
|
|
56
|
+
aria-invalid={!!error}
|
|
57
|
+
aria-describedby={description ? `${props.id}-description` : undefined}
|
|
58
|
+
{...props}
|
|
59
|
+
>
|
|
60
|
+
{leftIcon && <span className="mr-2">{leftIcon}</span>}
|
|
61
|
+
{label || children}
|
|
62
|
+
{rightIcon && <span className="ml-2">{rightIcon}</span>}
|
|
63
|
+
{required && <span className="ml-1 text-red-500">*</span>}
|
|
64
|
+
{error && <span className="sr-only">{error}</span>}
|
|
65
|
+
</button>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
Button.displayName = "Button";
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import { cn } from '../../utils/cn';
|
|
3
|
+
import { AlertCircle } from 'lucide-react';
|
|
4
|
+
|
|
5
|
+
export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> {
|
|
6
|
+
label?: string;
|
|
7
|
+
error?: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
required?: boolean;
|
|
10
|
+
leftIcon?: React.ReactNode;
|
|
11
|
+
rightIcon?: React.ReactNode;
|
|
12
|
+
size?: 'sm' | 'md' | 'lg';
|
|
13
|
+
variant?: 'default' | 'filled' | 'unstyled';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const Input = forwardRef<HTMLInputElement, InputProps>(({
|
|
17
|
+
label,
|
|
18
|
+
error,
|
|
19
|
+
description,
|
|
20
|
+
required,
|
|
21
|
+
leftIcon,
|
|
22
|
+
rightIcon,
|
|
23
|
+
size = 'md',
|
|
24
|
+
variant = 'default',
|
|
25
|
+
className,
|
|
26
|
+
disabled,
|
|
27
|
+
id,
|
|
28
|
+
...props
|
|
29
|
+
}, ref) => {
|
|
30
|
+
const inputId = id || `input-${Math.random().toString(36).substr(2, 9)}`;
|
|
31
|
+
const sizeClasses = {
|
|
32
|
+
sm: 'h-8 text-xs px-3 py-1',
|
|
33
|
+
md: 'h-10 text-sm px-4 py-2',
|
|
34
|
+
lg: 'h-12 text-base px-5 py-3',
|
|
35
|
+
}[size];
|
|
36
|
+
const variantClasses = {
|
|
37
|
+
default: 'border border-gray-300 bg-white focus:border-blue-500 focus:ring-2 focus:ring-blue-200',
|
|
38
|
+
filled: 'bg-gray-100 border border-transparent focus:bg-white focus:border-blue-500 focus:ring-2 focus:ring-blue-200',
|
|
39
|
+
unstyled: 'border-none bg-transparent p-0 focus:ring-0',
|
|
40
|
+
}[variant];
|
|
41
|
+
const errorClasses = error
|
|
42
|
+
? 'border-red-500 focus:border-red-500 focus:ring-red-200'
|
|
43
|
+
: '';
|
|
44
|
+
const disabledClasses = disabled
|
|
45
|
+
? 'bg-gray-100 cursor-not-allowed opacity-60'
|
|
46
|
+
: '';
|
|
47
|
+
return (
|
|
48
|
+
<div className="w-full">
|
|
49
|
+
{/* Label */}
|
|
50
|
+
{label && (
|
|
51
|
+
<label
|
|
52
|
+
htmlFor={inputId}
|
|
53
|
+
className={cn(
|
|
54
|
+
"block text-sm font-medium mb-1.5",
|
|
55
|
+
disabled ? "text-gray-400 cursor-not-allowed" : "text-gray-700"
|
|
56
|
+
)}
|
|
57
|
+
>
|
|
58
|
+
{label}
|
|
59
|
+
{required && <span className="text-red-500 ml-1">*</span>}
|
|
60
|
+
</label>
|
|
61
|
+
)}
|
|
62
|
+
{/* Description */}
|
|
63
|
+
{description && !error && (
|
|
64
|
+
<p className="text-xs text-gray-500 mb-2">{description}</p>
|
|
65
|
+
)}
|
|
66
|
+
{/* Input Container */}
|
|
67
|
+
<div className="relative">
|
|
68
|
+
{/* Left Icon */}
|
|
69
|
+
{leftIcon && (
|
|
70
|
+
<span className={cn(
|
|
71
|
+
"absolute left-3 top-1/2 -translate-y-1/2",
|
|
72
|
+
error ? "text-red-500" : "text-gray-400"
|
|
73
|
+
)}>
|
|
74
|
+
{leftIcon}
|
|
75
|
+
</span>
|
|
76
|
+
)}
|
|
77
|
+
{/* Input */}
|
|
78
|
+
<input
|
|
79
|
+
ref={ref}
|
|
80
|
+
id={inputId}
|
|
81
|
+
disabled={disabled}
|
|
82
|
+
aria-invalid={!!error}
|
|
83
|
+
className={cn(
|
|
84
|
+
"w-full rounded-md transition-all duration-150 outline-none",
|
|
85
|
+
sizeClasses,
|
|
86
|
+
variantClasses,
|
|
87
|
+
errorClasses,
|
|
88
|
+
disabledClasses,
|
|
89
|
+
leftIcon && "pl-10",
|
|
90
|
+
rightIcon && "pr-10",
|
|
91
|
+
className
|
|
92
|
+
)}
|
|
93
|
+
{...props}
|
|
94
|
+
/>
|
|
95
|
+
{/* Right Icon */}
|
|
96
|
+
{rightIcon && (
|
|
97
|
+
<span className={cn(
|
|
98
|
+
"absolute right-3 top-1/2 -translate-y-1/2",
|
|
99
|
+
error ? "text-red-500" : "text-gray-400"
|
|
100
|
+
)}>
|
|
101
|
+
{rightIcon}
|
|
102
|
+
</span>
|
|
103
|
+
)}
|
|
104
|
+
</div>
|
|
105
|
+
|
|
106
|
+
{/* Error Message */}
|
|
107
|
+
{error && (
|
|
108
|
+
<p className="flex items-center gap-1 mt-1.5 text-xs text-red-500">
|
|
109
|
+
<AlertCircle className="w-3.5 h-3.5" />
|
|
110
|
+
{error}
|
|
111
|
+
</p>
|
|
112
|
+
)}
|
|
113
|
+
</div>
|
|
114
|
+
);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
Input.displayName = 'Input';
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./components/Input/Input";
|
package/src/lib/utils.ts
ADDED
package/src/utils/cn.ts
ADDED
package/tsconfig.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"jsx": "react-jsx",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"target": "ESNext",
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"emitDeclarationOnly": true,
|
|
8
|
+
"outDir": "dist",
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"allowJs": true,
|
|
11
|
+
"moduleResolution": "node",
|
|
12
|
+
"skipLibCheck": true,
|
|
13
|
+
"forceConsistentCasingInFileNames": true
|
|
14
|
+
},
|
|
15
|
+
"include": ["src"]
|
|
16
|
+
}
|