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.
@@ -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
- };