gbs-add-block 0.0.39 → 0.0.41
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 +3 -3
- package/index.js +149 -137
- package/package.json +1 -1
- package/source/components/datepicker/index.tsx +1 -1
- package/source/components/input/index.tsx +1 -1
- package/source/components/materialInput/index.tsx +3 -3
- package/source/components/modal/index.tsx +114 -70
- package/source/components/modal/types.ts +5 -3
- package/source/components/multiselect/index.tsx +55 -111
- package/source/components/select/Select.tsx +176 -0
- package/source/components/select/types.ts +1 -1
- package/source/components/spinner/index.tsx +1 -1
- package/source/components/toast/Toast.tsx +3 -3
- package/source/components/toast/ToastContext.tsx +43 -0
- package/source/components/toast/index.tsx +2 -3
- package/source/components/toast/useToast.ts +2 -2
- package/source/globalStyle.ts +4 -0
- package/source/hooks/SelectionHooks/type.ts +4 -0
- package/source/hooks/SelectionHooks/useClickOutside.ts +22 -0
- package/source/hooks/SelectionHooks/useMultiSelectState.ts +64 -0
- package/source/hooks/SelectionHooks/useSelectData.ts +58 -0
- package/source/hooks/SelectionHooks/useSelectState.ts +36 -0
- package/source/components/select/index.tsx +0 -233
- package/source/components/toast/toastAtom.ts +0 -23
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { useState, useCallback } from "react";
|
|
2
|
+
import type { ItemsProps } from "./type";
|
|
3
|
+
|
|
4
|
+
export const useSelectState = (initialSelectedItem?: string) => {
|
|
5
|
+
const [showPopover, setShowPopover] = useState(false);
|
|
6
|
+
const [workingDataSource, setWorkingDataSource] = useState<ItemsProps[]>([]);
|
|
7
|
+
const [searchTerm, setSearchTerm] = useState("");
|
|
8
|
+
const [selectedItem, setSelectedItem] = useState<string | undefined>(
|
|
9
|
+
initialSelectedItem
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
const togglePopover = useCallback((e: React.MouseEvent) => {
|
|
13
|
+
e.stopPropagation();
|
|
14
|
+
setShowPopover((prev) => !prev);
|
|
15
|
+
}, []);
|
|
16
|
+
|
|
17
|
+
const clearSelected = useCallback(() => {
|
|
18
|
+
setSelectedItem(undefined);
|
|
19
|
+
setShowPopover(false);
|
|
20
|
+
setSearchTerm("");
|
|
21
|
+
return "";
|
|
22
|
+
}, []);
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
showPopover,
|
|
26
|
+
setShowPopover,
|
|
27
|
+
workingDataSource,
|
|
28
|
+
setWorkingDataSource,
|
|
29
|
+
searchTerm,
|
|
30
|
+
setSearchTerm,
|
|
31
|
+
selectedItem,
|
|
32
|
+
setSelectedItem,
|
|
33
|
+
togglePopover,
|
|
34
|
+
clearSelected,
|
|
35
|
+
};
|
|
36
|
+
};
|
|
@@ -1,233 +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, {
|
|
9
|
-
forwardRef,
|
|
10
|
-
memo,
|
|
11
|
-
useCallback,
|
|
12
|
-
useEffect,
|
|
13
|
-
useImperativeHandle,
|
|
14
|
-
useMemo,
|
|
15
|
-
useRef,
|
|
16
|
-
useState,
|
|
17
|
-
} from "react";
|
|
18
|
-
import Icon from "../icon/Icon";
|
|
19
|
-
import { check, search, upDown, x } from "../icon/iconPaths";
|
|
20
|
-
import { getSourceData } from "../utils";
|
|
21
|
-
import type { ItemsProps, SelectHandle, SelectProps } from "./types";
|
|
22
|
-
import { selectStyle } from "./style";
|
|
23
|
-
import { popUp, primary } from "../globalStyle";
|
|
24
|
-
|
|
25
|
-
const Select = forwardRef<SelectHandle, SelectProps>((props, ref) => {
|
|
26
|
-
const {
|
|
27
|
-
id = "",
|
|
28
|
-
name = "",
|
|
29
|
-
placeholder = "Select an Item...",
|
|
30
|
-
items,
|
|
31
|
-
lazy = false,
|
|
32
|
-
showSearch = true,
|
|
33
|
-
onSelect,
|
|
34
|
-
selectedItem: initialSelectedItem,
|
|
35
|
-
error = undefined,
|
|
36
|
-
onFiltering,
|
|
37
|
-
} = props;
|
|
38
|
-
|
|
39
|
-
const [showPopover, setShowPopover] = useState(false);
|
|
40
|
-
const [workingDataSource, setWorkingDataSource] = useState<ItemsProps[]>([]);
|
|
41
|
-
const [searchTerm, setSearchTerm] = useState("");
|
|
42
|
-
const [selectedItem, setSelectedItem] = useState<string | undefined>(
|
|
43
|
-
initialSelectedItem
|
|
44
|
-
);
|
|
45
|
-
const inputRef = useRef<HTMLInputElement>(null);
|
|
46
|
-
const selectRef = useRef<HTMLDivElement>(null);
|
|
47
|
-
|
|
48
|
-
// This will close the popup if clicked outside of the component
|
|
49
|
-
const handleClickOutside = useCallback((event: MouseEvent) => {
|
|
50
|
-
if (
|
|
51
|
-
selectRef.current &&
|
|
52
|
-
!selectRef.current.contains(event.target as Node)
|
|
53
|
-
) {
|
|
54
|
-
setShowPopover(false);
|
|
55
|
-
}
|
|
56
|
-
}, []);
|
|
57
|
-
|
|
58
|
-
// This will close the popup if clicked outside of the component
|
|
59
|
-
useEffect(() => {
|
|
60
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
61
|
-
return () => {
|
|
62
|
-
document.removeEventListener("mousedown", handleClickOutside);
|
|
63
|
-
};
|
|
64
|
-
}, [handleClickOutside]);
|
|
65
|
-
|
|
66
|
-
// Focus to input feild when popup opens
|
|
67
|
-
useEffect(() => {
|
|
68
|
-
if (showPopover) {
|
|
69
|
-
inputRef.current?.focus();
|
|
70
|
-
}
|
|
71
|
-
}, [showPopover]);
|
|
72
|
-
|
|
73
|
-
// Handles if items is an API URL
|
|
74
|
-
const getSelectItems = useCallback(async (itemsApi: string) => {
|
|
75
|
-
const itemsData = await getSourceData(itemsApi);
|
|
76
|
-
setWorkingDataSource(itemsData.sourcedata);
|
|
77
|
-
}, []);
|
|
78
|
-
|
|
79
|
-
useEffect(() => {
|
|
80
|
-
if (Array.isArray(items)) {
|
|
81
|
-
setWorkingDataSource(items);
|
|
82
|
-
} else if (typeof items === "string") {
|
|
83
|
-
getSelectItems(items);
|
|
84
|
-
}
|
|
85
|
-
}, [items, getSelectItems]);
|
|
86
|
-
|
|
87
|
-
useEffect(() => {
|
|
88
|
-
setSelectedItem(initialSelectedItem);
|
|
89
|
-
}, [initialSelectedItem]);
|
|
90
|
-
|
|
91
|
-
//Sets if a default value is passed
|
|
92
|
-
const selectedDisplay = useMemo(() => {
|
|
93
|
-
if (selectedItem && workingDataSource.length > 0) {
|
|
94
|
-
const selected = workingDataSource.find(
|
|
95
|
-
(item) => item.value === selectedItem
|
|
96
|
-
);
|
|
97
|
-
return selected ? selected.label : "";
|
|
98
|
-
}
|
|
99
|
-
return "";
|
|
100
|
-
}, [selectedItem, workingDataSource]);
|
|
101
|
-
|
|
102
|
-
// Toggles Popover
|
|
103
|
-
const togglePopover = useCallback((e: React.MouseEvent) => {
|
|
104
|
-
e.stopPropagation();
|
|
105
|
-
setShowPopover((prev) => !prev);
|
|
106
|
-
}, []);
|
|
107
|
-
|
|
108
|
-
// Handles Selection of items
|
|
109
|
-
const handleSelect = useCallback(
|
|
110
|
-
(value: string) => {
|
|
111
|
-
setSelectedItem(value);
|
|
112
|
-
setShowPopover(false);
|
|
113
|
-
setSearchTerm("");
|
|
114
|
-
if (onSelect) onSelect(value);
|
|
115
|
-
},
|
|
116
|
-
[onSelect]
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
// Clears Selection
|
|
120
|
-
const clearSelected = useCallback(() => {
|
|
121
|
-
setSelectedItem(undefined);
|
|
122
|
-
if (onSelect) onSelect("");
|
|
123
|
-
setShowPopover(false);
|
|
124
|
-
setSearchTerm("");
|
|
125
|
-
}, [onSelect]);
|
|
126
|
-
|
|
127
|
-
// Filtering logic
|
|
128
|
-
const filteredItems = useMemo(() => {
|
|
129
|
-
if (!searchTerm || lazy) return workingDataSource;
|
|
130
|
-
return workingDataSource.filter((item) =>
|
|
131
|
-
Object.values(item).some((val) =>
|
|
132
|
-
val.toString().toLowerCase().includes(searchTerm.toLowerCase())
|
|
133
|
-
)
|
|
134
|
-
);
|
|
135
|
-
}, [workingDataSource, searchTerm, lazy]);
|
|
136
|
-
|
|
137
|
-
// Making Select Functions Accessible in Paren
|
|
138
|
-
useImperativeHandle(ref, () => ({
|
|
139
|
-
workingDataSource,
|
|
140
|
-
items,
|
|
141
|
-
clearSelected,
|
|
142
|
-
togglePopover,
|
|
143
|
-
getSelectItems,
|
|
144
|
-
selectedDisplay,
|
|
145
|
-
selected: selectedItem,
|
|
146
|
-
}));
|
|
147
|
-
|
|
148
|
-
return (
|
|
149
|
-
<div className="relative w-96" ref={selectRef} id={id}>
|
|
150
|
-
<div className="w-full relative">
|
|
151
|
-
<button
|
|
152
|
-
className={`${error ? primary["error-border"] : "border"} ${
|
|
153
|
-
selectStyle["select-button"]
|
|
154
|
-
}`}
|
|
155
|
-
onClick={togglePopover}
|
|
156
|
-
type="button"
|
|
157
|
-
>
|
|
158
|
-
{selectedDisplay || placeholder}
|
|
159
|
-
<Icon
|
|
160
|
-
elements={upDown}
|
|
161
|
-
svgClass="h-4 w-4 stroke-gray-500 fill-none dark:stroke-white"
|
|
162
|
-
/>
|
|
163
|
-
</button>
|
|
164
|
-
{selectedDisplay && (
|
|
165
|
-
<button
|
|
166
|
-
className={selectStyle["selectedDisplay-Button"]}
|
|
167
|
-
onClick={clearSelected}
|
|
168
|
-
>
|
|
169
|
-
<Icon
|
|
170
|
-
elements={x}
|
|
171
|
-
svgClass="h-4 w-4 stroke-gray-500 fill-none dark:stroke-white"
|
|
172
|
-
/>
|
|
173
|
-
</button>
|
|
174
|
-
)}
|
|
175
|
-
<p className={primary["error-primary"]}>{error && error}</p>
|
|
176
|
-
</div>
|
|
177
|
-
|
|
178
|
-
{/* Hidden input to integrate with the form */}
|
|
179
|
-
<input type="hidden" name={name} value={selectedItem || ""} readOnly />
|
|
180
|
-
|
|
181
|
-
{showPopover && (
|
|
182
|
-
<div className={popUp["pop-up-style"]}>
|
|
183
|
-
{showSearch && (
|
|
184
|
-
<div className={selectStyle["input-parent"]}>
|
|
185
|
-
<Icon
|
|
186
|
-
elements={search}
|
|
187
|
-
svgClass="stroke-gray-500 fill-none dark:stroke-white"
|
|
188
|
-
/>
|
|
189
|
-
<input
|
|
190
|
-
autoComplete="off"
|
|
191
|
-
type="text"
|
|
192
|
-
name="search"
|
|
193
|
-
id="search"
|
|
194
|
-
placeholder="Search a value"
|
|
195
|
-
className="w-full outline-none dark:bg-black"
|
|
196
|
-
ref={inputRef}
|
|
197
|
-
value={searchTerm}
|
|
198
|
-
onChange={(e) => {
|
|
199
|
-
setSearchTerm(e.target.value);
|
|
200
|
-
if (onFiltering) onFiltering(e.target.value);
|
|
201
|
-
}}
|
|
202
|
-
/>
|
|
203
|
-
</div>
|
|
204
|
-
)}
|
|
205
|
-
{filteredItems.length > 0 ? (
|
|
206
|
-
filteredItems.map(({ value, label }) => (
|
|
207
|
-
<button
|
|
208
|
-
key={value}
|
|
209
|
-
className={selectStyle["filter-button"]}
|
|
210
|
-
onClick={() => handleSelect(value)}
|
|
211
|
-
>
|
|
212
|
-
<Icon
|
|
213
|
-
elements={check}
|
|
214
|
-
svgClass={`h-4 w-4 fill-none ${
|
|
215
|
-
selectedItem === value ? "stroke-gray-500" : ""
|
|
216
|
-
}`}
|
|
217
|
-
/>
|
|
218
|
-
{label}
|
|
219
|
-
</button>
|
|
220
|
-
))
|
|
221
|
-
) : (
|
|
222
|
-
<div className="text-sm text-center">No Data Found</div>
|
|
223
|
-
)}
|
|
224
|
-
</div>
|
|
225
|
-
)}
|
|
226
|
-
</div>
|
|
227
|
-
);
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
Select.displayName = "Select";
|
|
231
|
-
|
|
232
|
-
const MemoizedSelect = memo(Select);
|
|
233
|
-
export { MemoizedSelect as Select };
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { atom, useAtom } from "jotai";
|
|
2
|
-
import { Toast } from "./types";
|
|
3
|
-
|
|
4
|
-
export const toastsAtom = atom<Toast[]>([]);
|
|
5
|
-
|
|
6
|
-
export const useToastStore = () => {
|
|
7
|
-
const [toasts, setToasts] = useAtom(toastsAtom);
|
|
8
|
-
|
|
9
|
-
const addToast = (toast: Omit<Toast, "id">) => {
|
|
10
|
-
const id = Math.floor(Math.random() * 10000);
|
|
11
|
-
const newToast = { ...toast, id };
|
|
12
|
-
setToasts((prev) => [newToast, ...prev]);
|
|
13
|
-
if (toast.timeout) {
|
|
14
|
-
setTimeout(() => dismissToast(id), toast.timeout);
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const dismissToast = (id: number) => {
|
|
19
|
-
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
return { toasts, addToast, dismissToast };
|
|
23
|
-
};
|