gbs-add-block 0.0.2 → 0.0.4

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.
Files changed (37) hide show
  1. package/package.json +9 -9
  2. package/index.js +0 -127
  3. package/source/components/button/index.tsx +0 -25
  4. package/source/components/checkbox/index.tsx +0 -9
  5. package/source/components/darkmode/index.tsx +0 -48
  6. package/source/components/datepicker/DatePickerHelper.ts +0 -42
  7. package/source/components/datepicker/index.tsx +0 -258
  8. package/source/components/datepicker/types.ts +0 -9
  9. package/source/components/dialog/index.tsx +0 -44
  10. package/source/components/dialog/types.ts +0 -12
  11. package/source/components/grid/FilterPopup.tsx +0 -85
  12. package/source/components/grid/Grid.tsx +0 -615
  13. package/source/components/grid/GridHelperFunctions.ts +0 -218
  14. package/source/components/grid/index.tsx +0 -26
  15. package/source/components/grid/type.ts +0 -28
  16. package/source/components/input/index.tsx +0 -105
  17. package/source/components/input/types.ts +0 -9
  18. package/source/components/modal/index.tsx +0 -58
  19. package/source/components/modal/types.ts +0 -11
  20. package/source/components/multiselect/index.tsx +0 -213
  21. package/source/components/multiselect/types.ts +0 -14
  22. package/source/components/select/index.tsx +0 -220
  23. package/source/components/select/types.ts +0 -13
  24. package/source/components/spinner/Stroke.tsx +0 -89
  25. package/source/components/spinner/index.tsx +0 -54
  26. package/source/components/spinner/types.ts +0 -9
  27. package/source/components/toast/Toast.tsx +0 -61
  28. package/source/components/toast/index.tsx +0 -36
  29. package/source/components/toast/toastAtom.ts +0 -23
  30. package/source/components/toast/types.ts +0 -24
  31. package/source/components/toast/useToast.ts +0 -24
  32. package/source/fallback/index.tsx +0 -11
  33. package/source/icon/Icon.tsx +0 -55
  34. package/source/icon/iconPaths.ts +0 -92
  35. package/source/index.ts +0 -15
  36. package/source/types.ts +0 -108
  37. package/source/utils.ts +0 -10
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
- "name": "gbs-add-block",
3
- "version": "0.0.2",
4
- "description": "React Component Library",
2
+ "name": "gbs-add-block",
3
+ "version": "0.0.4",
4
+ "main": "bin/index.js",
5
5
  "files": [
6
- "index.js",
7
- "source"
6
+ "bin",
7
+ "components",
8
+ "src",
9
+ "utils.ts",
10
+ "icon"
8
11
  ],
9
- "engines": {
10
- "node": ">=17"
11
- },
12
12
  "bin": {
13
- "gbs-add-block": "./index.js"
13
+ "gbs-add-block": "./bin/index.js"
14
14
  },
15
15
  "scripts": {
16
16
  "test": "echo \"Error: no test specified\" && exit 1"
package/index.js DELETED
@@ -1,127 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const fs = require("fs-extra");
4
- const path = require("path");
5
- const readline = require("readline");
6
-
7
- const COMPONENTS = [
8
- "Select",
9
- "Grid",
10
- "MultiSelect",
11
- "Button",
12
- "DatePicker",
13
- "Checkbox",
14
- "DarkMode",
15
- "Dialog",
16
- "Input",
17
- "Modal",
18
- "Spinner",
19
- "Toast",
20
- ];
21
-
22
- // Use __dirname to get the directory where the script is located
23
- const PACKAGE_ROOT = path.join(__dirname, "..");
24
- const SOURCE_PATH = path.join(PACKAGE_ROOT, "components");
25
- const DEST_PATH = path.join(process.cwd(), "src", "component-lib");
26
-
27
- const rl = readline.createInterface({
28
- input: process.stdin,
29
- output: process.stdout,
30
- });
31
-
32
- let isFirstCopy = true;
33
-
34
- function listComponents() {
35
- console.log("Available components:");
36
- COMPONENTS.forEach((component, index) => {
37
- console.log(`${index + 1}. ${component}`);
38
- });
39
- }
40
-
41
- function copyCommonFiles() {
42
- // Copy utils.ts
43
- const utilsSrc = path.join(PACKAGE_ROOT, "utils.ts");
44
- const utilsDest = path.join(DEST_PATH, "utils.ts");
45
- if (fs.existsSync(utilsSrc)) {
46
- fs.copySync(utilsSrc, utilsDest, { overwrite: true });
47
- console.log(`utils.ts copied successfully to ${utilsDest}`);
48
- } else {
49
- console.warn(`utils.ts not found at ${utilsSrc}`);
50
- }
51
-
52
- // Copy icon folder
53
- const iconSrc = path.join(PACKAGE_ROOT, "icon");
54
- const iconDest = path.join(DEST_PATH, "icon");
55
- if (fs.existsSync(iconSrc)) {
56
- fs.copySync(iconSrc, iconDest, { overwrite: true });
57
- console.log(`icon folder copied successfully to ${iconDest}`);
58
- } else {
59
- console.warn(`icon folder not found at ${iconSrc}`);
60
- }
61
- }
62
-
63
- function copyComponent(component) {
64
- const componentSrc = path.join(SOURCE_PATH, component.toLowerCase());
65
- const componentDest = path.join(DEST_PATH, component.toLowerCase());
66
-
67
- if (!fs.existsSync(componentSrc)) {
68
- console.error(
69
- `Component ${component} not found in source directory: ${componentSrc}`
70
- );
71
- return false;
72
- }
73
-
74
- fs.copySync(componentSrc, componentDest, { overwrite: true });
75
- console.log(`Component ${component} copied successfully to ${componentDest}`);
76
-
77
- if (isFirstCopy) {
78
- copyCommonFiles();
79
- isFirstCopy = false;
80
- }
81
-
82
- return true;
83
- }
84
-
85
- function promptForComponent() {
86
- listComponents();
87
- rl.question(
88
- 'Enter the number of the component you want to copy (or "q" to quit): ',
89
- (answer) => {
90
- if (answer.toLowerCase() === "q") {
91
- rl.close();
92
- return;
93
- }
94
-
95
- const index = parseInt(answer) - 1;
96
- if (isNaN(index) || index < 0 || index >= COMPONENTS.length) {
97
- console.log("Invalid selection. Please try again.");
98
- promptForComponent();
99
- return;
100
- }
101
-
102
- const selectedComponent = COMPONENTS[index];
103
- const success = copyComponent(selectedComponent);
104
-
105
- if (success) {
106
- rl.question(
107
- "Do you want to copy another component? (y/n): ",
108
- (answer) => {
109
- if (answer.toLowerCase() === "y") {
110
- promptForComponent();
111
- } else {
112
- rl.close();
113
- }
114
- }
115
- );
116
- } else {
117
- promptForComponent();
118
- }
119
- }
120
- );
121
- }
122
-
123
- // Ensure the destination directory exists
124
- fs.ensureDirSync(DEST_PATH);
125
-
126
- // Start the component selection process
127
- promptForComponent();
@@ -1,25 +0,0 @@
1
- /**
2
- * Copyright (c) Grampro Business Services and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- import React, { ButtonHTMLAttributes } from "react";
9
-
10
- interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
11
- children?: any;
12
- buttonClass?: string;
13
- }
14
-
15
- export const Button = ({
16
- children,
17
- buttonClass = "px-2 py-1 bg-black text-white rounded-md hover:bg-gray-700",
18
- ...props
19
- }: ButtonProps) => {
20
- return (
21
- <button className={buttonClass} {...props}>
22
- {children}
23
- </button>
24
- );
25
- };
@@ -1,9 +0,0 @@
1
- import React, { InputHTMLAttributes } from "react";
2
-
3
- export const Checkbox = ({
4
- ...props
5
- }: InputHTMLAttributes<HTMLInputElement>) => {
6
- return (
7
- <input type="checkbox" className="w-5 h-5 cursor-pointer" {...props} />
8
- );
9
- };
@@ -1,48 +0,0 @@
1
- import React, { useEffect } from "react";
2
- import Icon from "../icon/Icon";
3
- import { moon, sun } from "../icon/iconPaths";
4
-
5
- export const DarkMode = () => {
6
- const [dark, setDark] = React.useState(false);
7
-
8
- useEffect(() => {
9
- // Check for user's preference in localStorage or system preference
10
- const isDarkMode =
11
- localStorage.getItem("darkMode") === "true" ||
12
- (!("darkMode" in localStorage) &&
13
- window.matchMedia("(prefers-color-scheme: dark)").matches);
14
- setDark(isDarkMode);
15
- updateDarkMode(isDarkMode);
16
- }, []);
17
-
18
- const updateDarkMode = (isDark: boolean) => {
19
- if (isDark) {
20
- document.documentElement.classList.add("dark");
21
- } else {
22
- document.documentElement.classList.remove("dark");
23
- }
24
- localStorage.setItem("darkMode", isDark.toString());
25
- };
26
-
27
- const darkModeHandler = () => {
28
- const newDarkMode = !dark;
29
- setDark(newDarkMode);
30
- updateDarkMode(newDarkMode);
31
- };
32
-
33
- return (
34
- <button onClick={darkModeHandler}>
35
- {dark ? (
36
- <Icon
37
- elements={sun}
38
- svgClass={"stroke-gray-500 fill-none dark:stroke-white"}
39
- />
40
- ) : (
41
- <Icon
42
- elements={moon}
43
- svgClass={"stroke-black fill-none dark:stroke-white"}
44
- />
45
- )}
46
- </button>
47
- );
48
- }
@@ -1,42 +0,0 @@
1
- const getDaysInMonth = (year: any, month: any) => {
2
- return new Date(year, month + 1, 0).getDate();
3
- };
4
-
5
- export const generateCalendarHelper = (year: any, month: any) => {
6
- const daysInMonth = getDaysInMonth(year, month);
7
- const firstDay = new Date(year, month, 1).getDay();
8
- const weeks = [];
9
- let day = 1;
10
-
11
- for (let i = 0; i < 6; i++) {
12
- const week = [];
13
- for (let j = 0; j < 7; j++) {
14
- if (i === 0 && j < firstDay) {
15
- week.push(null);
16
- } else if (day > daysInMonth) {
17
- week.push(null);
18
- } else {
19
- const date = new Date(year, month, day);
20
- week.push(date);
21
- day++;
22
- }
23
- }
24
- weeks.push(week);
25
- }
26
- return weeks;
27
- };
28
-
29
- export const months = [
30
- 'January',
31
- 'February',
32
- 'March',
33
- 'April',
34
- 'May',
35
- 'June',
36
- 'July',
37
- 'August',
38
- 'September',
39
- 'October',
40
- 'November',
41
- 'December'
42
- ];
@@ -1,258 +0,0 @@
1
- /**
2
- * Copyright (c) Grampro Business Services and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- import React, { useState, useEffect, useRef } from "react";
9
- import { generateCalendarHelper, months } from "./DatePickerHelper";
10
- import Icon from "../icon/Icon";
11
- import { calender, down, leftArrows, rightArrows } from "../icon/iconPaths";
12
- import type { DatePickerProps } from "./types";
13
-
14
- export const DatePicker = ({
15
- placeholder = undefined,
16
- selectedDate: initialSelectedDate = new Date(),
17
- minDate = null,
18
- maxDate = null,
19
- yearLimitStart = 50,
20
- yearLimitEnd = 30,
21
- onDateChange,
22
- }: DatePickerProps) => {
23
- const [showDatepicker, setShowDatepicker] = useState(false);
24
- const [showYearMonthPicker, setShowYearMonthPicker] = useState(false);
25
- const [currentMonth, setCurrentMonth] = useState(new Date().getMonth());
26
- const [currentYear, setCurrentYear] = useState(new Date().getFullYear());
27
- const [days, setDays] = useState<any>([]);
28
- const [selectedDate, setSelectedDate] = useState(initialSelectedDate);
29
-
30
- const dateRef = useRef<HTMLDivElement>(null);
31
- const today = new Date();
32
-
33
- // This will helps to close the popup when clicked outside of datepicker component
34
- useEffect(() => {
35
- function handleClickOutside(event: MouseEvent) {
36
- if (dateRef.current && !dateRef.current.contains(event.target as Node)) {
37
- setShowDatepicker(false);
38
- }
39
- }
40
-
41
- document.addEventListener("mousedown", handleClickOutside);
42
- return () => {
43
- document.removeEventListener("mousedown", handleClickOutside);
44
- };
45
- }, []);
46
-
47
- useEffect(() => {
48
- setDays(generateCalendarHelper(currentYear, currentMonth));
49
- }, [currentYear, currentMonth]);
50
-
51
- // DatePicker Toggler
52
- const toggleDatepicker = () => {
53
- setShowDatepicker(!showDatepicker);
54
- setShowYearMonthPicker(false);
55
- };
56
-
57
- // YearMonthPicker Toggler
58
- const toggleYearMonthPicker = () => {
59
- setShowYearMonthPicker(!showYearMonthPicker);
60
- };
61
-
62
- const selectDate = (date: any) => {
63
- setSelectedDate(date);
64
- setShowDatepicker(false);
65
- if (onDateChange) onDateChange(date);
66
- };
67
-
68
- const selectYearMonth = (year: any, month: any) => {
69
- setCurrentYear(year);
70
- setCurrentMonth(month);
71
- setShowYearMonthPicker(false);
72
- setDays(generateCalendarHelper(year, month));
73
- };
74
-
75
- // *** DatePicker navigation starts here
76
- const prevMonth = () => {
77
- if (currentMonth === 0) {
78
- setCurrentMonth(11);
79
- setCurrentYear(currentYear - 1);
80
- } else {
81
- setCurrentMonth(currentMonth - 1);
82
- }
83
- };
84
-
85
- const nextMonth = () => {
86
- if (currentMonth === 11) {
87
- setCurrentMonth(0);
88
- setCurrentYear(currentYear + 1);
89
- } else {
90
- setCurrentMonth(currentMonth + 1);
91
- }
92
- };
93
-
94
- const goToToday = () => {
95
- setCurrentMonth(today.getMonth());
96
- setCurrentYear(today.getFullYear());
97
- setSelectedDate(new Date());
98
- if (onDateChange) onDateChange(new Date());
99
- };
100
- // DatePicker navigation ends here ***
101
-
102
- const years = Array.from(
103
- { length: yearLimitEnd },
104
- (_, i) => currentYear - yearLimitStart + i
105
- );
106
-
107
- return (
108
- <div className="relative inline-block w-80 dark:bg-black" ref={dateRef}>
109
- <button
110
- onClick={toggleDatepicker}
111
- className="border p-2 rounded w-full flex gap-2 items-center justify-center dark:text-white"
112
- >
113
- <Icon
114
- elements={calender}
115
- svgClass={"stroke-black fill-none dark:stroke-white"}
116
- />
117
- {placeholder ? (
118
- <span className="text-gray-500">{placeholder}</span>
119
- ) : (
120
- selectedDate.toLocaleDateString()
121
- )}
122
- </button>
123
-
124
- {showDatepicker && (
125
- <div className="absolute z-10 bg-white border border-gray-300 shadow-lg mt-1 w-full rounded dark:bg-black dark:text-white px-2">
126
- <div className="flex justify-between items-center p-2">
127
- <button
128
- onClick={prevMonth}
129
- className="text-gray-500 hover:text-gray-700 w-8 h-8 rounded-full flex items-center justify-center hover:bg-gray-100"
130
- >
131
- <Icon
132
- elements={leftArrows}
133
- svgClass={"stroke-gray-500 fill-none dark:stroke-white"}
134
- />
135
- </button>
136
- <div className="flex items-center space-x-2">
137
- <span className="text-md font-semibold">
138
- {new Date(currentYear, currentMonth).toLocaleString("default", {
139
- month: "long",
140
- })}{" "}
141
- {currentYear}
142
- </span>
143
- <button onClick={toggleYearMonthPicker} className="">
144
- <Icon
145
- elements={down}
146
- svgClass={"stroke-black fill-none dark:stroke-white"}
147
- />
148
- </button>
149
- </div>
150
- <button
151
- onClick={nextMonth}
152
- className="text-gray-500 hover:text-gray-700 w-8 h-8 rounded-full flex items-center justify-center hover:bg-gray-100"
153
- >
154
- <Icon
155
- elements={rightArrows}
156
- svgClass={"stroke-black fill-none dark:stroke-white"}
157
- />
158
- </button>
159
- </div>
160
- {showYearMonthPicker ? (
161
- <div className="flex p-2 h-[224px] scrollbar">
162
- <div className="w-1/2 pr-1">
163
- <h3 className="text-sm font-semibold mb-1">Month</h3>
164
- <div className="overflow-y-auto h-[200px] scrollbar-thin scrollbar-thumb-gray-300 scrollbar-track-gray-100 scrollbar">
165
- {months.map((month, index) => (
166
- <button
167
- key={month}
168
- onClick={() => selectYearMonth(currentYear, index)}
169
- className={`w-full text-left p-2 cursor-pointer rounded hover:bg-gray-200 transition duration-150 ease-in-out ${
170
- index === currentMonth
171
- ? "bg-blue-500 text-white hover:bg-blue-600"
172
- : ""
173
- }`}
174
- >
175
- {month}
176
- </button>
177
- ))}
178
- </div>
179
- </div>
180
- <div className="w-1/2 pl-1">
181
- <h3 className="text-sm font-semibold mb-1">Year</h3>
182
- <div className="overflow-y-auto h-[200px] scrollbar-thin scrollbar-thumb-gray-300 scrollbar-track-gray-100 scrollbar">
183
- {years.map((year) => (
184
- <button
185
- key={year}
186
- onClick={() => selectYearMonth(year, currentMonth)}
187
- className={`w-full text-left p-2 cursor-pointer rounded hover:bg-gray-200 transition duration-150 ease-in-out ${
188
- year === currentYear
189
- ? "bg-blue-500 text-white hover:bg-blue-600"
190
- : ""
191
- }`}
192
- >
193
- {year}
194
- </button>
195
- ))}
196
- </div>
197
- </div>
198
- </div>
199
- ) : (
200
- <div className="grid grid-cols-7 gap-1 p-2">
201
- {["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => (
202
- <div key={day} className="text-center font-bold text-sm p-1">
203
- {day}
204
- </div>
205
- ))}
206
- {days.flat().map((day: any, index: any) => {
207
- if (!day) {
208
- return (
209
- <div key={index} className="text-center p-1 w-8 h-8"></div>
210
- );
211
- }
212
- const isDisabled: any =
213
- (minDate && day < minDate) || (maxDate && day > maxDate);
214
- const isSelected =
215
- day.getDate() === selectedDate.getDate() &&
216
- day.getMonth() === selectedDate.getMonth() &&
217
- day.getFullYear() === selectedDate.getFullYear();
218
-
219
- return (
220
- <button
221
- key={index}
222
- onClick={() => !isDisabled && selectDate(day)}
223
- disabled={isDisabled}
224
- className={`text-center p-1 w-8 h-8 cursor-pointer rounded-full hover:bg-gray-200 transition duration-150 ease-in-out ${
225
- isSelected
226
- ? "bg-blue-500 text-white hover:bg-blue-600"
227
- : ""
228
- } ${
229
- isDisabled
230
- ? "bg-gray-100 text-gray-400 cursor-not-allowed"
231
- : "hover:bg-gray-200"
232
- }`}
233
- >
234
- {day.getDate()}
235
- </button>
236
- );
237
- })}
238
- </div>
239
- )}
240
- <div className="px-2 py-2 flex justify-between mb-8">
241
- <button
242
- onClick={goToToday}
243
- className="text-blue-500 hover:text-blue-600 transition duration-150 ease-in-out"
244
- >
245
- Today
246
- </button>
247
- <button
248
- onClick={toggleDatepicker}
249
- className="text-gray-500 hover:text-gray-600 transition duration-150 ease-in-out"
250
- >
251
- Close
252
- </button>
253
- </div>
254
- </div>
255
- )}
256
- </div>
257
- );
258
- };
@@ -1,9 +0,0 @@
1
- export type DatePickerProps = {
2
- placeholder?: string | undefined;
3
- selectedDate?: Date;
4
- minDate?: Date | null;
5
- maxDate?: Date | null;
6
- yearLimitStart?: number;
7
- yearLimitEnd?: number;
8
- onDateChange?: any;
9
- };
@@ -1,44 +0,0 @@
1
- /**
2
- * Copyright (c) Grampro Business Services and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- import React from "react";
9
- import { twMerge } from "tailwind-merge";
10
- import type { DialogProps } from "./types";
11
-
12
- export const Dialog = ({
13
- showDialog = false,
14
- dialogMessage = "Are you sure?",
15
- dialogActionOne = "OK",
16
- dialogActionTwo = "Cancel",
17
- onDialogActionOneClick,
18
- onDialogActionTwoClick,
19
- dialogClass = "bg-white p-4 rounded-lg shadow-lg w-96",
20
- dialogContentClass = "text-lg",
21
- dialogActionOneStyle = "bg-black hover:bg-black text-white font-bold px-2 py-1 rounded mt-4",
22
- dialogActionTwoStyle = "border text-black font-bold px-2 py-1 rounded mt-4 ml-2",
23
- }: DialogProps) => {
24
- if (!showDialog) return null;
25
- return (
26
- <div
27
- className={twMerge(
28
- dialogClass,
29
- "fixed top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"
30
- )}
31
- role="dialog"
32
- aria-modal="true"
33
- aria-labelledby="dialog-title"
34
- >
35
- <p className={dialogContentClass}>{dialogMessage}</p>
36
- <button className={dialogActionOneStyle} onClick={onDialogActionOneClick}>
37
- {dialogActionOne}
38
- </button>
39
- <button className={dialogActionTwoStyle} onClick={onDialogActionTwoClick}>
40
- {dialogActionTwo}
41
- </button>
42
- </div>
43
- );
44
- };
@@ -1,12 +0,0 @@
1
- export type DialogProps = {
2
- showDialog?: boolean;
3
- dialogMessage?: string;
4
- dialogActionOne?: string;
5
- dialogActionTwo?: string;
6
- onDialogActionOneClick?: () => void;
7
- onDialogActionTwoClick?: () => void;
8
- dialogClass?: string;
9
- dialogContentClass?: string;
10
- dialogActionOneStyle?: string;
11
- dialogActionTwoStyle?: string;
12
- };
@@ -1,85 +0,0 @@
1
- import React from "react";
2
- import { useState } from "react";
3
-
4
- export default function FilterPopup({ show, columnHeader, filterAction }: any) {
5
- const [filterValue, setFilterValue] = useState("");
6
- const [filterType, setFilterType] = useState("contains");
7
- const [isFilterActive, setIsFilterActive] = useState(false);
8
-
9
- const handleFilterInput = (e: any) => {
10
- const filterKeyword = e.target.value;
11
- setFilterValue(filterKeyword);
12
- };
13
-
14
- const onCancel = () => {
15
- filterAction({ type: "cancel" });
16
- };
17
-
18
- const applyFilter = () => {
19
- filterAction({
20
- type: "applyFilter",
21
- filterValue,
22
- filterType,
23
- columnHeader,
24
- });
25
- show = false;
26
- setIsFilterActive(true);
27
- };
28
-
29
- const clearFilter = () => {
30
- setIsFilterActive(false);
31
- filterAction({ type: "clearFilter", columnHeader });
32
- };
33
-
34
- return (
35
- show && (
36
- <div
37
- className="absolute bg-gray-100 p-2 border z-50 mt-48 flex items-end flex-col shadow-lg gap-2 rounded-md dark:bg-gray-700"
38
- role="dialog"
39
- >
40
- <select
41
- name={`${columnHeader}-filter`}
42
- id={`${columnHeader}-filter-id`}
43
- className="w-full p-2 rounded-lg dark:bg-gray-600"
44
- value={filterType}
45
- onChange={(e: any) => {
46
- setFilterType(e.target.value);
47
- }}
48
- >
49
- <option value="contains">Contains</option>
50
- <option value="starts_with">Starts With</option>
51
- <option value="ends_with">Ends With</option>
52
- </select>
53
- <input
54
- type="text"
55
- placeholder="Enter filter value"
56
- className="rounded-lg p-2 text-sm dark:bg-gray-600"
57
- value={filterValue}
58
- onInput={handleFilterInput}
59
- />
60
- <div className="mt-2">
61
- <button
62
- className="text-xs bg-red-600 text-white p-1 rounded-lg hover:bg-red-600"
63
- onClick={onCancel}
64
- >
65
- Cancel
66
- </button>
67
- {isFilterActive && (
68
- <button
69
- className="text-xs bg-black text-white p-1 rounded-lg dark:bg-white dark:text-white"
70
- onClick={clearFilter}
71
- >
72
- Clear Filter
73
- </button>
74
- )}
75
- <button
76
- className="text-xs bg-black text-white p-1 rounded-lg dark:bg-white dark:text-black"
77
- onClick={applyFilter}
78
- >
79
- Apply Filter
80
- </button>
81
- </div>
82
- </div>
83
- )
84
- );
85
- }