ehscan-react-components 0.1.23 → 0.1.25

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 CHANGED
@@ -3,9 +3,29 @@
3
3
  - Button
4
4
  - Window
5
5
  - TextArea
6
+ - TextAreaDropDown
6
7
 
7
8
  # Styling
8
9
 
10
+ - TextAreaDropDown
11
+
12
+ | Variable | Fallback / Default |
13
+ | ---------------------------------- | ----------------------------------- |
14
+ | `--ext-textarea-box-bck-clr` | `lightgray` |
15
+ | `--ext-textarea-box-border-radius` | `10px` |
16
+ | `--ext-dropdown-border-radius` | `20px` |
17
+ | `--input-txt-size` | *(not explicitly set, optional)* |
18
+ | `--d-font-weight` | *(not explicitly set, optional)* |
19
+ | `--input-clr` | `black` |
20
+ | `--textarea-tag-bck-clr` | `white` (some places `transparent`) |
21
+ | `--textarea-tag-clr` | `darkblue` (some places `white`) |
22
+ | `--d-input-placeholder-clr` | `black` |
23
+ | `--d-input-bck-clr` | `transparent` |
24
+ | `--dropdown-item-bck-clr` | `wheat` |
25
+ | `--dropdown-amount-row-bck-clr` | `yellow` |
26
+ | `--animate-s` | `.5s` |
27
+
28
+
9
29
  ## Base Button Variables
10
30
 
11
31
  | Variable | Default/Fallback |
@@ -96,19 +116,3 @@
96
116
 
97
117
  All notable changes to this project will be documented in this file.
98
118
  ---
99
-
100
-
101
- ## [1.0.5] - 2027-11-11
102
- ### Fixed
103
- - Setter now supports functional update (like React’s setState)
104
-
105
- ## [1.0.4] - 2027-10-22
106
- ### Added
107
- - Added UseClickSetter
108
- - Only Clicking purpose
109
-
110
- ## [1.0.3] - 2025-10-22
111
- ### Fixed
112
- - Optimized listener notifications:
113
- - Only listeners subscribed to a changed or removed key are notified.
114
- - Previously, all listeners were notified on every state change.
@@ -1,3 +1,4 @@
1
1
  export { Button } from './Button';
2
2
  export { Window } from './Window';
3
3
  export { TextArea } from './TextArea';
4
+ export { TextAreaDropDown } from './TextAreaDropDown';
@@ -2,3 +2,4 @@
2
2
  export { Button } from './Button';
3
3
  export { Window } from './Window';
4
4
  export { TextArea } from './TextArea';
5
+ export { TextAreaDropDown } from './TextAreaDropDown';
@@ -0,0 +1,12 @@
1
+ export type DropDownHandle = {
2
+ calc: () => void;
3
+ };
4
+ type DropDownProps = {
5
+ openDropDown: boolean;
6
+ display: string[];
7
+ addItem: (index: number) => void;
8
+ searchTerm: string;
9
+ maxDropDownEntries?: number;
10
+ };
11
+ export declare const DropDown: import("react").ForwardRefExoticComponent<DropDownProps & import("react").RefAttributes<DropDownHandle>>;
12
+ export {};
@@ -0,0 +1,86 @@
1
+ import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useEffect, useState, useRef, forwardRef, useImperativeHandle } from "react";
3
+ export const DropDown = forwardRef(({ openDropDown, display, addItem, searchTerm, maxDropDownEntries }, ref) => {
4
+ const [position, setPosition] = useState({ top: 0, left: 0, width: 0, maxHeight: 0 });
5
+ const containerRef = useRef(null);
6
+ // Expose functions to parent
7
+ useImperativeHandle(ref, () => ({
8
+ calc: () => {
9
+ console.log("calc");
10
+ setTimeout(() => {
11
+ calcDropDown();
12
+ }, 50);
13
+ // parent will implement actual state change, this is just the hook
14
+ },
15
+ }));
16
+ const HighlightedText = ({ text, searchTerm, maxLength = 150 }) => {
17
+ if (!searchTerm) {
18
+ const sliced = text.slice(0, maxLength);
19
+ return (_jsxs("div", { children: [sliced, text.length > maxLength && '…'] }));
20
+ }
21
+ const searchWords = searchTerm
22
+ .toLowerCase()
23
+ .split(/\s+/)
24
+ .filter(Boolean);
25
+ if (searchWords.length === 0) {
26
+ return _jsx("div", { children: text.slice(0, maxLength) });
27
+ }
28
+ const lowerText = text.toLowerCase();
29
+ // Find first match position
30
+ let firstMatchIndex = -1;
31
+ for (let word of searchWords) {
32
+ const index = lowerText.indexOf(word);
33
+ if (index !== -1 && (firstMatchIndex === -1 || index < firstMatchIndex)) {
34
+ firstMatchIndex = index;
35
+ }
36
+ }
37
+ // Determine slice window
38
+ let sliceStart = 0;
39
+ let sliceEnd = maxLength;
40
+ if (firstMatchIndex > -1) {
41
+ const foundWord = searchWords.find(w => lowerText.includes(w));
42
+ if (firstMatchIndex > -1 && foundWord) {
43
+ const matchEnd = firstMatchIndex + foundWord.length;
44
+ // const matchEnd = firstMatchIndex + searchWords.find(w => lowerText.includes(w)).length;
45
+ if (matchEnd > maxLength) {
46
+ sliceEnd = Math.min(text.length, matchEnd);
47
+ sliceStart = sliceEnd - maxLength;
48
+ }
49
+ }
50
+ }
51
+ const displayText = text.slice(sliceStart, sliceEnd);
52
+ // Build a regex that matches all words
53
+ const highlightRegex = new RegExp(`(${searchWords.join('|')})`, 'gi');
54
+ const parts = displayText.split(highlightRegex);
55
+ return (_jsxs(_Fragment, { children: [sliceStart > 0 && '…', parts.map((part, i) => searchWords.includes(part.toLowerCase()) ? (_jsx("span", { className: "highlight-words", children: part }, i)) : (_jsx("span", { children: part }, i))), sliceEnd < text.length && '…'] }));
56
+ };
57
+ const calcDropDown = () => {
58
+ if (!(containerRef === null || containerRef === void 0 ? void 0 : containerRef.current))
59
+ return;
60
+ const rect = containerRef.current.getBoundingClientRect();
61
+ const distanceToBottom = window.innerHeight - rect.bottom;
62
+ setPosition({
63
+ top: rect.bottom - 5,
64
+ left: rect.left,
65
+ width: rect.width,
66
+ maxHeight: distanceToBottom - 50
67
+ });
68
+ };
69
+ useEffect(() => {
70
+ if (openDropDown && containerRef.current) {
71
+ calcDropDown();
72
+ }
73
+ ;
74
+ }, [openDropDown]);
75
+ const addDropDownItem = (index) => {
76
+ addItem(index);
77
+ setTimeout(() => {
78
+ calcDropDown();
79
+ }, 50);
80
+ };
81
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: "ext-window-dropdown-edge", ref: containerRef }), openDropDown && (_jsxs("div", { className: "ext-window-dropdown", style: {
82
+ top: position.top,
83
+ left: position.left,
84
+ width: position.width
85
+ }, children: [maxDropDownEntries !== undefined && (_jsxs("div", { className: "dropdown-amount-row", children: [display.length, " / ", maxDropDownEntries, " entries"] })), _jsx("div", { className: "ext-window-dropdown-wrapper _ewb", style: { maxHeight: `${position.maxHeight}px`, }, children: display.map((item, index) => (_jsx("div", { className: "dropdown-item", onClick: () => addDropDownItem(index), children: _jsx(HighlightedText, { text: item, searchTerm: searchTerm }) }, index))) })] }))] }));
86
+ });
@@ -0,0 +1,17 @@
1
+ import './style/input-dropdown.css';
2
+ type Action = "add" | "remove";
3
+ interface Props {
4
+ id?: string;
5
+ tabIndex?: number;
6
+ editable?: boolean;
7
+ label?: string;
8
+ required?: boolean;
9
+ value: string[];
10
+ dropdownValue: string[];
11
+ onChange: (value: string, action: Action) => void;
12
+ placeholder?: string;
13
+ maxLength?: number;
14
+ addClass?: string;
15
+ }
16
+ export declare const TextAreaDropDown: React.FC<Props>;
17
+ export default TextAreaDropDown;
@@ -0,0 +1,137 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
+ import { useRef, useState, useId, useEffect } from "react";
12
+ import { DropDown } from "./DropDown";
13
+ import './style/input-dropdown.css';
14
+ export const TextAreaDropDown = ({ id, tabIndex, label, value, editable = true, required = false, dropdownValue, onChange, placeholder, maxLength = 500, addClass, }) => {
15
+ const childRef = useRef(null);
16
+ const textareaRef = useRef(null);
17
+ const searchInput = useRef(null);
18
+ const [charCount, setCharCount] = useState(value.length);
19
+ const generatedId = useId(); // unique fallback for aria linking
20
+ const textareaId = id || `textarea-${generatedId}`;
21
+ const [openDropDown, setOpenDropDown] = useState(false);
22
+ const [maxDropDownEntries, setMaxDropDownEntries] = useState(undefined);
23
+ const [tags, setTags] = useState(undefined);
24
+ const [width, setWidth] = useState(0);
25
+ const [searchTerm, setSearchTerm] = useState('');
26
+ const [filterItems, setFilterItem] = useState([]);
27
+ useEffect(() => {
28
+ if (!width)
29
+ return;
30
+ setOpenDropDown(false);
31
+ }, [width]);
32
+ useEffect(() => {
33
+ if (!textareaRef.current)
34
+ return;
35
+ const handleResize = () => {
36
+ var _a;
37
+ const newWidth = (_a = textareaRef === null || textareaRef === void 0 ? void 0 : textareaRef.current) === null || _a === void 0 ? void 0 : _a.offsetWidth;
38
+ if (newWidth !== width) {
39
+ setWidth(newWidth);
40
+ }
41
+ };
42
+ // Initial check
43
+ handleResize();
44
+ // Listen to window resize
45
+ window.addEventListener('resize', handleResize);
46
+ return () => {
47
+ window.removeEventListener('resize', handleResize);
48
+ };
49
+ }, [maxDropDownEntries]);
50
+ useEffect(() => {
51
+ setTags(value);
52
+ setCharCount(value.length);
53
+ if (dropdownValue === undefined)
54
+ return;
55
+ setMaxDropDownEntries(dropdownValue.length);
56
+ }, [value]);
57
+ const handleKeyDown = (e) => {
58
+ if (newBtn && e.key === 'Enter' && searchTerm !== '') {
59
+ createItem();
60
+ return;
61
+ }
62
+ if (e.key === "Backspace" && searchTerm === "" && value.length > 0) {
63
+ if (tags === null || tags === void 0 ? void 0 : tags.length) {
64
+ removeTag(tags[tags.length - 1]);
65
+ }
66
+ }
67
+ };
68
+ useEffect(() => {
69
+ if (searchTerm === undefined || value === undefined)
70
+ return;
71
+ const dropDownEntry = dropdownValue.filter(tag => !value.includes(tag));
72
+ if (!searchTerm || searchTerm === '') {
73
+ setFilterItem(dropDownEntry);
74
+ return;
75
+ }
76
+ const filterAndProcessItems = () => __awaiter(void 0, void 0, void 0, function* () {
77
+ const searchWords = searchTerm
78
+ .toLowerCase()
79
+ .split(/\s+/) // split by whitespace
80
+ .filter(Boolean); // remove empty strings
81
+ const filtered = yield Promise.all(// some ✅ ANY search word should match (common) | All shall match -> every
82
+ dropDownEntry
83
+ .filter(item => searchWords.every(word => item.toLowerCase().includes(word.toLowerCase())))
84
+ .map((item) => __awaiter(void 0, void 0, void 0, function* () { return item; })));
85
+ setFilterItem(filtered);
86
+ });
87
+ filterAndProcessItems();
88
+ }, [searchTerm, value]);
89
+ const removeTag = (tagToRemove) => {
90
+ var _a;
91
+ onChange(tagToRemove, 'remove');
92
+ if (childRef.current)
93
+ (_a = childRef.current) === null || _a === void 0 ? void 0 : _a.calc();
94
+ };
95
+ const addItem = (entry) => {
96
+ var _a;
97
+ if (entry === undefined || !filterItems[entry])
98
+ return;
99
+ const newValue = filterItems[entry];
100
+ console.log(newValue);
101
+ onChange(newValue, 'add');
102
+ if (!searchInput.current)
103
+ return;
104
+ searchInput.current.focus();
105
+ if (childRef.current)
106
+ (_a = childRef.current) === null || _a === void 0 ? void 0 : _a.calc();
107
+ };
108
+ const createItem = () => {
109
+ var _a;
110
+ if (searchTerm === undefined || searchTerm === '')
111
+ return;
112
+ onChange(searchTerm, 'add');
113
+ if (!searchInput.current)
114
+ return;
115
+ searchInput.current.value = '';
116
+ searchInput.current.focus();
117
+ setSearchTerm("");
118
+ if (childRef.current)
119
+ (_a = childRef.current) === null || _a === void 0 ? void 0 : _a.calc();
120
+ };
121
+ const [newBtn, setNewBtn] = useState(false);
122
+ useEffect(() => {
123
+ if (searchTerm === undefined)
124
+ return;
125
+ if (dropdownValue.includes(searchTerm)) {
126
+ setNewBtn(false);
127
+ }
128
+ else {
129
+ if (searchTerm !== '')
130
+ setNewBtn(true);
131
+ }
132
+ }, [searchTerm]);
133
+ if (!tags)
134
+ return null;
135
+ return (_jsxs("div", { className: `ext-textarea-wrapper-dropdown ${addClass}`, ref: textareaRef, children: [label && (_jsxs("div", { className: "ext-textarea-label", children: [_jsxs("label", { className: "ext-textarea-label-title", htmlFor: textareaId, children: [label, " ", required && _jsx("span", { className: "required", children: "*" })] }), _jsxs("div", { className: "ext-textarea-label-btns", children: [editable && charCount > 0 && (_jsxs("div", { className: "form-container-count", children: [charCount, " / ", maxLength] })), editable && charCount > 0 && (_jsx("div", { className: "ext-textarea-svg-close", "aria-label": `Clear ${label !== null && label !== void 0 ? label : "text area"}` }))] })] })), _jsx("div", { className: `ext-textarea-box-dropdown${openDropDown ? ' open' : ''}`, onClick: () => setOpenDropDown(true), children: _jsxs("div", { className: "ext-textarea-dropdown-inner", children: [tags.map((item, index) => (_jsxs("div", { className: "textarea-tag loop", children: [_jsx("div", { children: item }), _jsx("div", { className: "textarea-tag-erase", onClick: () => removeTag(tags[index]), children: _jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [_jsx("line", { x1: "8", y1: "8", x2: "16", y2: "16", stroke: "#333", strokeWidth: "1", strokeLinecap: "round" }), _jsx("line", { x1: "16", y1: "8", x2: "8", y2: "16", stroke: "#333", strokeWidth: "1", strokeLinecap: "round" })] }) })] }, index))), _jsx("div", { className: "search-x-wrapper", children: _jsxs("div", { className: "search-x", children: [_jsx("div", { className: "search-x-input", children: _jsx("input", { type: "text", ref: searchInput, onFocus: () => setOpenDropDown(true), placeholder: "select or create new entry", value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), onKeyDown: handleKeyDown }) }), _jsx("div", { className: `search-x-btn${newBtn ? ' show' : ''}`, onClick: () => createItem(), children: newBtn && 'create new one' })] }) })] }) }), _jsx(DropDown, { ref: childRef, openDropDown: openDropDown, display: filterItems, addItem: addItem, maxDropDownEntries: maxDropDownEntries, searchTerm: searchTerm })] }));
136
+ };
137
+ export default TextAreaDropDown;
@@ -0,0 +1,374 @@
1
+ ._ewb:hover::-webkit-scrollbar-thumb {
2
+ background: #555;
3
+ width: 6px;
4
+ }
5
+
6
+ ._ewb::-webkit-scrollbar {
7
+ width: 6px;
8
+ background-color: var(--ext-textarea-box-bck-clr);
9
+ }
10
+
11
+ ._ewb:hover::-webkit-scrollbar {
12
+ width: 6px;
13
+ }
14
+
15
+ ._ewb::-webkit-scrollbar-thumb {
16
+ background-color: white;
17
+ border-radius: 12px;
18
+ }
19
+
20
+ input,
21
+ textarea,
22
+ .ext-textarea-wrapper-dropdown {
23
+ height: 100%;
24
+ font-family: Arial, sans-serif;
25
+ font-family: Inter, sans-serif;
26
+ font-style: normal;
27
+ font-weight: 400;
28
+ font-optical-sizing: auto;
29
+ -webkit-font-smoothing: antialiased;
30
+ text-rendering: optimizelegibility;
31
+ letter-spacing: 0.072px;
32
+ overflow: hidden;
33
+ }
34
+
35
+ input::placeholder,
36
+ textarea::placeholder {
37
+ color: var(--d-input-placeholder-clr, black);
38
+ opacity: 1;
39
+ font-size: 12;
40
+ font-weight: 300;
41
+ padding: 0
42
+ }
43
+
44
+ input[type="text"],
45
+ input[type="email"],
46
+ textarea {
47
+ color: var(--input-clr, black);
48
+ text-align: var(--input-align);
49
+ background-color: var(--d-input-bck-clr, transparent);
50
+ outline: none;
51
+ border: none;
52
+ }
53
+
54
+ textarea {
55
+ resize: none;
56
+ overflow: hidden;
57
+ min-height: 30px;
58
+ }
59
+
60
+ input:-webkit-autofill,
61
+ input:-webkit-autofill:hover,
62
+ input:-webkit-autofill:focus,
63
+ input:-webkit-autofill:active {
64
+ -webkit-box-shadow: 0 0 0px 1000px transparent inset !important;
65
+ box-shadow: 0 0 0px 1000px transparent inset !important;
66
+ -webkit-text-fill-color: var(--input-clr);
67
+ background-clip: padding-box !important;
68
+ transition: background-color 9999s ease-in-out 0s;
69
+ background-color: red;
70
+ }
71
+
72
+ /* textarea */
73
+ /* Main Wrapper */
74
+ .ext-textarea-wrapper-dropdown {
75
+ position: relative;
76
+ display: flex;
77
+ flex-direction: column;
78
+ gap: 10px;
79
+ }
80
+
81
+ .ext-textarea-lable {
82
+ padding: 5px 0 0 10px;
83
+ display: flex;
84
+ flex-direction: row;
85
+ gap: 10px;
86
+ }
87
+
88
+ .ext-textarea-lable-title {
89
+ flex: 1;
90
+ }
91
+
92
+ .ext-textarea-lable-btn {
93
+ background-color: aquamarine;
94
+ display: flex;
95
+ gap: 10px;
96
+ }
97
+
98
+ .ext-textarea-box,
99
+ .ext-textarea-box-dropdown {
100
+ width: 100%;
101
+ background-color: var(--ext-textarea-box-bck-clr, lightgray);
102
+ border-radius: var(--ext-textarea-box-border-radius, 10px);
103
+ display: flex;
104
+ position: relative;
105
+ --ext-dropdown-border-radius: 20px;
106
+ }
107
+
108
+ .ext-textarea-box-dropdown.open {
109
+ border-radius: var(--ext-textarea-box-border-radius) var(--ext-textarea-box-border-radius) var(--ext-dropdown-border-radius) var(--ext-dropdown-border-radius) ;
110
+ }
111
+
112
+ .ext-textarea-wrapper {
113
+ display: flex;
114
+ flex-direction: column;
115
+ gap: 4px;
116
+ }
117
+
118
+ .ext-textarea-label {
119
+ display: flex;
120
+ justify-content: center;
121
+ align-items: center;
122
+ }
123
+
124
+ .ext-textarea-label-title {
125
+ flex: 1;
126
+ color: darkblue;
127
+ font-weight: 800;
128
+ }
129
+
130
+ .ext-textarea-label-btns {
131
+ display: flex;
132
+ align-items: center;
133
+ gap: 8px;
134
+ }
135
+
136
+ .form-container-count {
137
+ font-size: 0.85rem;
138
+ color: #666;
139
+ }
140
+
141
+ .form-container-clear {
142
+ border: none;
143
+ background: none;
144
+ color: #007aff;
145
+ cursor: pointer;
146
+ font-size: 0.85rem;
147
+ }
148
+
149
+ .ext-textarea {
150
+ font-size: var(--input-txt-size);
151
+ border: none;
152
+ outline: none;
153
+ width: 100%;
154
+ font-weight: var(--d-font-weight);
155
+ display: grid;
156
+ justify-content: left;
157
+ align-items: center;
158
+ background-color: transparent;
159
+ color: var(--input-clr);
160
+ box-sizing: border-box;
161
+ resize: none;
162
+ overflow: hidden;
163
+ padding: 10px;
164
+ line-height: 1.5;
165
+ }
166
+
167
+ .ext-textarea.highlight {
168
+ border-color: green;
169
+ border-width: 3px;
170
+ border-style: solid;
171
+ }
172
+
173
+ .ext-textarea-svg-close {
174
+ background-color: #007aff;
175
+ border-radius: 50px;
176
+ display: flex;
177
+ align-items: center;
178
+ justify-content: center;
179
+ }
180
+
181
+
182
+ /* DropDown */
183
+
184
+ .ext-textarea-dropdown-inner {
185
+ font-size: var(--input-txt-size, 14px);
186
+ border: none;
187
+ outline: none;
188
+ width: 100%;
189
+ font-weight: var(--d-font-weight, 400);
190
+ justify-content: left;
191
+ align-items: center;
192
+ background-color: transparent;
193
+ color: var(--input-clr);
194
+ box-sizing: border-box;
195
+ resize: none;
196
+ overflow: hidden;
197
+ padding: 10px;
198
+ line-height: 1.5;
199
+ display: flex;
200
+ flex-wrap: wrap;
201
+ }
202
+
203
+ .textarea-tag {
204
+ display: flex;
205
+ width: fit-content;
206
+ position: relative;
207
+ float: left;
208
+ margin: 3px 0;
209
+ }
210
+
211
+ .textarea-tag.loop {
212
+ margin: 3px;
213
+ background-color: var(--textarea-tag-bck-clr, white);
214
+ color: var(--textarea-tag-clr, darkblue);
215
+ padding: 5px 7px;
216
+ border-radius: 6px;
217
+ font-size: 90%;
218
+ font-weight: 400;
219
+ line-height: 1.3;
220
+ text-overflow: ellipsis;
221
+ white-space: nowrap;
222
+ -webkit-box-orient: vertical;
223
+ overflow: hidden;
224
+ gap: 5px;
225
+ flex: 0 0 auto;
226
+ padding: 6px 10px;
227
+ border-radius: 6px;
228
+ align-items: center;
229
+ justify-content: center;
230
+ box-shadow: rgba(0, 0, 0, 0.04) 0px 3px 5px;
231
+ }
232
+
233
+ .textarea-tag-erase {
234
+ display: flex;
235
+ align-items: center;
236
+ justify-content: center;
237
+ border-radius: 50px;
238
+ }
239
+
240
+ .textarea-tag-erase:hover{
241
+ background-color: lightgray;
242
+ cursor: pointer;
243
+ }
244
+
245
+ .highlight-words {
246
+ background-color: yellow;
247
+ }
248
+
249
+ .ext-window-dropdown-edge {
250
+ height: 0;
251
+ width: 100%;
252
+ }
253
+
254
+ .ext-window-dropdown {
255
+ position: fixed;
256
+ background-color: white;
257
+ border: 1px solid #ccc;
258
+ border-radius: var(--ext-dropdown-border-radius);
259
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
260
+ transition: opacity 0.3s ease, max-height 0.2s ease;
261
+ opacity: 1;
262
+ z-index: 1000;
263
+ }
264
+
265
+ .ext-window-dropdown-wrapper {
266
+ padding: 10px;
267
+ display: flex;
268
+ flex-direction: column;
269
+ gap: 5px;
270
+ max-height: 200px;
271
+ overflow-y: auto;
272
+ }
273
+
274
+ .dropdown-item {
275
+ width: -webkit-fill-available;
276
+ font-weight: 300;
277
+ font-size: 90%;
278
+ background-color: var(--dropdown-item-bck-clr, wheat);
279
+ position: relative;
280
+ display: block;
281
+ padding: 5px 10px;
282
+ border-radius: 10px;
283
+ }
284
+
285
+ .dropdown-item:hover {
286
+ background-color: lightblue;
287
+ cursor: pointer;
288
+ }
289
+
290
+ .dropdown-amount-row {
291
+ width: -webkit-fill-available;
292
+ background-color: var(--dropdown-amount-row-bck-clr, yellow);
293
+ color: #007aff;
294
+ padding: 5px 10px;
295
+ text-align: end;
296
+ font-size: 80%;
297
+ font-weight: 600;
298
+ }
299
+
300
+ .textarea-tag.input {
301
+ height: 25px;
302
+ background-color: transparent;
303
+ border-radius: 10px;
304
+ padding: 0 0 2px 5px;
305
+ --input-clr: black;
306
+ }
307
+
308
+ .textarea-tag.btn {
309
+ background-color: #007aff;
310
+ color: white;
311
+ }
312
+
313
+ .search-x-wrapper {
314
+ position: relative;
315
+ float: left;
316
+ margin: 3px;
317
+ margin: 3px;
318
+ background-color: var(--textarea-tag-bck-clr, transparent);
319
+ gap: 10px;
320
+ flex: 1 1 auto;
321
+ }
322
+
323
+ .search-x {
324
+ display: grid;
325
+ grid-template-columns: 1fr auto;
326
+ align-items: center;
327
+ justify-content: center;
328
+ gap: 10px;
329
+ }
330
+
331
+ .search-x-input {
332
+ padding: 5px 7px;
333
+ background-color: transparent;
334
+ border: 1px dashed white;
335
+ border-radius: 4px;
336
+ }
337
+
338
+ .search-x-btn {
339
+ border-radius: 12px;
340
+ color: var(--textarea-tag-clr, white);
341
+ background-color: var(--textarea-tag-bck-clr, #007aff);
342
+ font-size: 90%;
343
+ font-weight: 500;
344
+ text-overflow: ellipsis;
345
+ white-space: nowrap;
346
+ -webkit-box-orient: vertical;
347
+ overflow: hidden;
348
+ width: fit-content;
349
+ height: 80%;
350
+ display: flex;
351
+ align-items: center;
352
+ justify-content: center;
353
+ padding: 0;
354
+ opacity: 0;
355
+ max-width: 0;
356
+ --animate-s: .5s;
357
+ transition: opacity var(--animate-s) ease, max-width var(--animate-s) ease, padding var(--animate-s);
358
+ }
359
+
360
+ .search-x-btn.show {
361
+ opacity: 1;
362
+ max-width: fit-content;
363
+ padding: 0 10px;
364
+ }
365
+
366
+ .search-x-btn:hover {
367
+ filter: brightness(1.1);
368
+ color: white;
369
+ cursor: pointer;
370
+ }
371
+
372
+ .search-x-input > input{
373
+ width: -webkit-fill-available;
374
+ }
@@ -1,5 +1,4 @@
1
1
  /* textarea */
2
-
3
2
  .ext-textarea-wrapper {
4
3
  position: relative;
5
4
  display: flex;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ehscan-react-components",
3
- "version": "0.1.23",
3
+ "version": "0.1.25",
4
4
  "description": "components",
5
5
  "main": "dist/Components.js",
6
6
  "types": "dist/Components.d.ts",