diff --git a/package-lock.json b/package-lock.json
index 3d7401c..66138b5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1211,6 +1211,66 @@
"node": ">=14.0.0"
}
},
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": {
+ "version": "1.5.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/wasi-threads": "1.1.0",
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": {
+ "version": "1.5.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
+ "version": "1.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": {
+ "version": "1.0.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "^1.5.0",
+ "@emnapi/runtime": "^1.5.0",
+ "@tybys/wasm-util": "^0.10.1"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": {
+ "version": "0.10.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": {
+ "version": "2.8.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "0BSD",
+ "optional": true
+ },
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
"version": "4.1.14",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.14.tgz",
diff --git a/src/app/components/FormInput/DatePicker.jsx b/src/app/components/FormInput/DatePicker.jsx
new file mode 100644
index 0000000..3a3451f
--- /dev/null
+++ b/src/app/components/FormInput/DatePicker.jsx
@@ -0,0 +1,23 @@
+import React, { useState } from "react";
+
+export const DatePicker = ({ label = "Select Date", onChange }) => {
+ const [date, setDate] = useState("");
+
+ const handleChange = (e) => {
+ setDate(e.target.value);
+ if (onChange) onChange(e.target.value);
+ };
+
+ return (
+
+
+
+ {date &&
Selected Date: {date}
}
+
+ );
+};
diff --git a/src/app/components/FormInput/FileUpload.jsx b/src/app/components/FormInput/FileUpload.jsx
new file mode 100644
index 0000000..df3fb85
--- /dev/null
+++ b/src/app/components/FormInput/FileUpload.jsx
@@ -0,0 +1,45 @@
+import React, { useState } from "react";
+
+export const FileUpload = ({ onFileSelect }) => {
+ const [file, setFile] = useState(null);
+
+ const handleFile = (file) => {
+ setFile(file);
+ if (onFileSelect) onFileSelect(file);
+ };
+
+ const handleDrop = (e) => {
+ e.preventDefault();
+ handleFile(e.dataTransfer.files[0]);
+ };
+
+ const handleChange = (e) => {
+ handleFile(e.target.files[0]);
+ };
+
+ return (
+
+
+
+ );
+};
diff --git a/src/app/components/FormInput/FormValidation.jsx b/src/app/components/FormInput/FormValidation.jsx
new file mode 100644
index 0000000..ba426b5
--- /dev/null
+++ b/src/app/components/FormInput/FormValidation.jsx
@@ -0,0 +1,33 @@
+import React, { useState } from "react";
+
+export const FormValidation = ({ minLength = 3, onSubmit }) => {
+ const [value, setValue] = useState("");
+ const [error, setError] = useState("");
+
+ const handleSubmit = (e) => {
+ e.preventDefault();
+ if (value.trim() === "") {
+ setError("Field cannot be empty");
+ } else if (value.length < minLength) {
+ setError(`Minimum ${minLength} characters required`);
+ } else {
+ setError("");
+ if (onSubmit) onSubmit(value);
+ alert("Form submitted: " + value);
+ }
+ };
+
+ return (
+
+ );
+};
diff --git a/src/app/components/FormInput/Slider.jsx b/src/app/components/FormInput/Slider.jsx
new file mode 100644
index 0000000..fc59b45
--- /dev/null
+++ b/src/app/components/FormInput/Slider.jsx
@@ -0,0 +1,24 @@
+import React, { useState } from "react";
+
+export const Slider = ({ min = 0, max = 100, step = 1, onChange }) => {
+ const [value, setValue] = useState((min + max) / 2);
+
+ const handleChange = (e) => {
+ setValue(e.target.value);
+ if (onChange) onChange(e.target.value);
+ };
+
+ return (
+
+ );
+};
diff --git a/src/app/components/page.jsx b/src/app/components/page.jsx
index 566a5d8..3d75511 100644
--- a/src/app/components/page.jsx
+++ b/src/app/components/page.jsx
@@ -1,9 +1,9 @@
"use client";
-import React, { useState, useEffect } from 'react'
-import { Search, X } from 'lucide-react'
+import React, { useState, useEffect } from "react";
+import { Search, X } from "lucide-react";
-import { useAnalytics } from '../context/AnalyticsContext'
-import { useTheme } from '../context/ThemeContext'
+import { useAnalytics } from "../context/AnalyticsContext";
+import { useTheme } from "../context/ThemeContext";
// Button Imports
// import PrimaryButton from '@/components/buttons/PrimaryButton'
// import SecondaryButton from '@/components/buttons/SecondaryButton'
@@ -53,11 +53,17 @@ import Pagination from "./navigation/Pagination";
import UserCard from "@/app/components/cards/UserCard";
import RainbowButton from "@/app/components/buttons/RainbowButton";
+// form Input
+
+import { DatePicker } from "./FormInput/DatePicker";
+import { FileUpload } from "./FormInput/FileUpload";
+import { FormValidation } from "./FormInput/FormValidation";
+import { Slider } from "./FormInput/Slider";
export default function Page() {
// Search and Filter State
- const [searchTerm, setSearchTerm] = useState('');
- const [filterType, setFilterType] = useState('all');
+ const [searchTerm, setSearchTerm] = useState("");
+ const [filterType, setFilterType] = useState("all");
// Analytics
@@ -68,7 +74,7 @@ export default function Page() {
// Track page view - only once on mount
useEffect(() => {
- trackComponentView('ComponentsPage');
+ trackComponentView("ComponentsPage");
}, []); // Empty dependency array to run only once
// Inputs
@@ -76,8 +82,6 @@ export default function Page() {
const [selectValue, setSelectValue] = React.useState("");
const [checkboxValue, setCheckboxValue] = React.useState(false);
-
-
// Data
const selectOptions = [
{ value: "option1", label: "Option 1" },
@@ -108,11 +112,129 @@ export default function Page() {
{ label: "Breadcrumb" },
];
-
-
// All components with search data
const allComponents = {
buttons: [
+ {
+ name: "Primary Button",
+ component: Primary,
+ keywords: ["primary", "main", "action", "cta"],
+ desc: "Used for Main Actions",
+ },
+ {
+ name: "Secondary Button",
+ component: Secondary,
+ keywords: ["secondary", "alternate"],
+ desc: "Used for secondary Actions",
+ },
+ {
+ name: "Ghost Button",
+ component: Ghost,
+ keywords: ["ghost", "transparent", "subtle"],
+ desc: "Used for minimal actions",
+ },
+ {
+ name: "Outline Button",
+ component: Outline,
+ keywords: ["outline", "border", "stroke"],
+ desc: "Used for gives outline",
+ },
+ {
+ name: "Danger Button",
+ component: Danger,
+ keywords: ["danger", "error", "delete", "warning", "red"],
+ desc: "Used for destructive actions",
+ },
+ {
+ name: "Success Button",
+ component: Success,
+ keywords: ["success", "confirm", "done", "green"],
+ desc: "Used for success actions",
+ },
+ {
+ name: "Icon Button",
+ component: ★,
+ keywords: ["icon", "star", "symbol"],
+ desc: "Used for icons",
+ },
+ {
+ name: "Rainbow Button",
+ component: Rainbow,
+ keywords: ["rainbow", "action", "colorful"],
+ desc: "Used for call to actions",
+ },
+ ],
+ cards: [
+ {
+ name: "Simple Card",
+ component: (
+
+ ),
+ keywords: ["simple", "basic", "minimal"],
+ },
+ {
+ name: "Image Card",
+ component: (
+
+ ),
+ keywords: ["image", "picture", "visual"],
+ },
+ {
+ name: "Feature Card",
+ component: (
+
+ ),
+ keywords: ["feature", "highlight", "benefit"],
+ },
+ {
+ name: "Pricing Card",
+ component: (
+
+ ),
+ keywords: ["pricing", "plan", "subscription", "price"],
+ },
+ {
+ name: "Data Card",
+ component: (
+
+ ),
+ keywords: ["data", "stats", "analytics", "metrics"],
+ },
+ ],
+ inputs: [
+ {
+ name: "Text Input",
+ component: ,
+ keywords: ["text", "input", "field", "form"],
+ },
+ {
+ name: "Select",
+ component: ,
+ keywords: ["select", "dropdown", "options", "choice"],
+ },
+ {
+ name: "Checkbox",
+ component: (
+ {}}
+ />
+ ),
+ keywords: ["checkbox", "check", "toggle", "boolean"],
+ },
+
{ name: 'Primary Button', component: Primary, keywords: ['primary', 'main', 'action', 'cta'], desc: "Used for Main Actions" },
{ name: 'Secondary Button', component: Secondary, keywords: ['secondary', 'alternate'], desc: "Used for secondary Actions" },
{ name: 'Ghost Button', component: Ghost, keywords: ['ghost', 'transparent', 'subtle'], desc: "Used for minimal actions" },
@@ -134,12 +256,27 @@ export default function Page() {
{ name: 'Text Input', component: , keywords: ['text', 'input', 'field', 'form'] },
{ name: 'Select', component: , keywords: ['select', 'dropdown', 'options', 'choice'] },
{ name: 'Checkbox', component: { }} />, keywords: ['checkbox', 'check', 'toggle', 'boolean'] }
+
],
navigation: [
- { name: 'Breadcrumb', component: , keywords: ['breadcrumb', 'navigation', 'path', 'hierarchy'] },
- { name: 'Tabs', component: , keywords: ['tabs', 'navigation', 'switch', 'toggle'] },
- { name: 'Pagination', component: , keywords: ['pagination', 'pages', 'navigation', 'paging'] }
- ]
+ {
+ name: "Breadcrumb",
+ component: ,
+ keywords: ["breadcrumb", "navigation", "path", "hierarchy"],
+ },
+ {
+ name: "Tabs",
+ component: ,
+ keywords: ["tabs", "navigation", "switch", "toggle"],
+ },
+ {
+ name: "Pagination",
+ component: (
+
+ ),
+ keywords: ["pagination", "pages", "navigation", "paging"],
+ },
+ ],
};
// Filter logic
@@ -147,7 +284,7 @@ export default function Page() {
let components = {};
// Apply type filter
- if (filterType === 'all') {
+ if (filterType === "all") {
components = allComponents;
} else {
components = { [filterType]: allComponents[filterType] };
@@ -156,10 +293,13 @@ export default function Page() {
// Apply search filter
if (searchTerm) {
const filtered = {};
- Object.keys(components).forEach(type => {
- const matchedComponents = components[type].filter(comp =>
- comp.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
- comp.keywords.some(keyword => keyword.toLowerCase().includes(searchTerm.toLowerCase()))
+ Object.keys(components).forEach((type) => {
+ const matchedComponents = components[type].filter(
+ (comp) =>
+ comp.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
+ comp.keywords.some((keyword) =>
+ keyword.toLowerCase().includes(searchTerm.toLowerCase())
+ )
);
if (matchedComponents.length > 0) {
filtered[type] = matchedComponents;
@@ -172,7 +312,10 @@ export default function Page() {
};
const filteredComponents = getFilteredComponents();
- const totalResults = Object.values(filteredComponents).reduce((total, components) => total + components.length, 0);
+ const totalResults = Object.values(filteredComponents).reduce(
+ (total, components) => total + components.length,
+ 0
+ );
return (
@@ -202,7 +345,7 @@ export default function Page() {
/>
{searchTerm && (
);
-}
\ No newline at end of file
+}