ehscan-react-components 0.1.17 → 0.1.18

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
@@ -1,5 +1,9 @@
1
1
  # ehscan-react-components
2
2
 
3
+ - Button
4
+ - Window
5
+ - TextArea
6
+
3
7
  # Styling
4
8
 
5
9
  ## Base Button Variables
@@ -1,2 +1,3 @@
1
1
  export { Button } from './Button';
2
2
  export { Window } from './Window';
3
+ export { TextArea } from './TextArea';
@@ -1,5 +1,4 @@
1
- // export const ExtButton = () => {
2
- // return <Button />
3
- // }
1
+ // ehscan-react-components entries
4
2
  export { Button } from './Button';
5
3
  export { Window } from './Window';
4
+ export { TextArea } from './TextArea';
@@ -0,0 +1,14 @@
1
+ import './style/input.css';
2
+ interface Props {
3
+ id?: string;
4
+ tabIndex?: number;
5
+ editable?: boolean;
6
+ label?: string;
7
+ required?: boolean;
8
+ value: string;
9
+ onChange: (value: string) => void;
10
+ placeholder?: string;
11
+ maxLength?: number;
12
+ }
13
+ export declare const TextArea: React.FC<Props>;
14
+ export {};
@@ -0,0 +1,44 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useLayoutEffect, useRef, useState, useCallback, useId } from "react";
3
+ import './style/input.css';
4
+ export const TextArea = ({ id, tabIndex, label, value, editable = true, required = false, onChange, placeholder, maxLength = 500, }) => {
5
+ const textareaRef = useRef(null);
6
+ const [charCount, setCharCount] = useState(value.length);
7
+ const generatedId = useId(); // unique fallback for aria linking
8
+ const textareaId = id || `textarea-${generatedId}`;
9
+ // 🔧 Resize and update char count whenever value changes
10
+ useLayoutEffect(() => {
11
+ setHeight();
12
+ setCharCount(value.length);
13
+ }, [value]);
14
+ const setHeight = () => {
15
+ const el = textareaRef.current;
16
+ if (!el)
17
+ return;
18
+ el.style.height = "auto";
19
+ el.style.height = `${Math.max(el.scrollHeight, 20)}px`;
20
+ };
21
+ const handleInputChange = useCallback((event) => {
22
+ const newValue = event.target.value;
23
+ onChange(newValue);
24
+ setCharCount(newValue.length);
25
+ }, [onChange]);
26
+ const handleFocus = useCallback(() => {
27
+ const el = textareaRef.current;
28
+ if (!el)
29
+ return;
30
+ requestAnimationFrame(() => {
31
+ el.focus({ preventScroll: true });
32
+ el.scrollIntoView({ behavior: "smooth", block: "center" });
33
+ });
34
+ setHeight();
35
+ }, []);
36
+ const clear = useCallback(() => {
37
+ onChange("");
38
+ setCharCount(0);
39
+ if (textareaRef.current) {
40
+ textareaRef.current.style.height = "auto";
41
+ }
42
+ }, [onChange]);
43
+ return (_jsxs("div", { className: "ext-textarea-wrapper", 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("button", { type: "button", className: "form-container-clear", onClick: clear, "aria-label": `Clear ${label !== null && label !== void 0 ? label : "text area"}`, children: "clear" }))] })] })), _jsx("div", { className: "ext-textarea-box", children: _jsx("textarea", { id: textareaId, tabIndex: tabIndex, ref: textareaRef, value: value !== null && value !== void 0 ? value : "", placeholder: placeholder !== null && placeholder !== void 0 ? placeholder : "...", maxLength: maxLength, onChange: handleInputChange, onFocus: handleFocus, onBlur: setHeight, className: `ext-textarea${required && value === "" ? " highlight" : ""}`, rows: 1, spellCheck: false, readOnly: !editable, "aria-required": required, "aria-label": label }) })] }));
44
+ };
@@ -0,0 +1,155 @@
1
+ /* textarea */
2
+
3
+ .ext-textarea-wrapper {
4
+ position: relative;
5
+ display: flex;
6
+ flex-direction: column;
7
+ gap: 10px;
8
+ }
9
+
10
+ .ext-textarea-lable {
11
+ padding: 5px 0 0 10px;
12
+ display: flex;
13
+ flex-direction: row;
14
+ gap: 10px;
15
+ }
16
+
17
+ .ext-textarea-lable-title {
18
+ flex: 1;
19
+ }
20
+
21
+ .ext-textarea-lable-btn {
22
+ background-color: aquamarine;
23
+ display: flex;
24
+ gap: 10px;
25
+ }
26
+
27
+ .ext-textarea-box {
28
+ background-color: blueviolet;
29
+ border-radius: 10px;
30
+ display: flex;
31
+ position: relative;
32
+ }
33
+
34
+ input,
35
+ textarea {
36
+ height: 100%;
37
+ font-family: Arial, sans-serif;
38
+ font-family: Inter, sans-serif;
39
+ font-style: normal;
40
+ font-weight: 400;
41
+ font-optical-sizing: auto;
42
+ -webkit-font-smoothing: antialiased;
43
+ text-rendering: optimizelegibility;
44
+ letter-spacing: 0.072px;
45
+ overflow: hidden;
46
+ }
47
+
48
+ input::placeholder,
49
+ textarea::placeholder {
50
+ color: red;
51
+ opacity: 1;
52
+ font-size: 12;
53
+ font-weight: 300;
54
+ padding: 0
55
+ }
56
+
57
+ input[type="text"],
58
+ input[type="email"],
59
+ textarea {
60
+ color: var(--input-clr);
61
+ text-align: var(--input-align);
62
+ background-color: var(--d-input-bck-clr);
63
+ outline: none;
64
+ border: none;
65
+ }
66
+
67
+ textarea {
68
+ resize: none;
69
+ overflow: hidden;
70
+ min-height: 30px;
71
+ }
72
+
73
+ input:-webkit-autofill,
74
+ input:-webkit-autofill:hover,
75
+ input:-webkit-autofill:focus,
76
+ input:-webkit-autofill:active {
77
+ -webkit-box-shadow: 0 0 0px 1000px transparent inset !important;
78
+ box-shadow: 0 0 0px 1000px transparent inset !important;
79
+ -webkit-text-fill-color: var(--input-clr);
80
+ background-clip: padding-box !important;
81
+ transition: background-color 9999s ease-in-out 0s;
82
+ }
83
+
84
+ /* 🌐 Wrapper */
85
+ .ext-textarea-wrapper {
86
+ display: flex;
87
+ flex-direction: column;
88
+ gap: 4px;
89
+ }
90
+
91
+ /* 🏷️ Label Area */
92
+ .ext-textarea-label {
93
+ display: flex;
94
+ justify-content: center;
95
+ align-items:center;
96
+ }
97
+
98
+ /* 🏷️ Label Title */
99
+ .ext-textarea-label-title {
100
+ flex: 1;
101
+ color: darkblue;
102
+ font-weight: 800;
103
+ }
104
+
105
+ /* ⚙️ Label Controls (counter + clear) */
106
+ .ext-textarea-label-btns {
107
+ display: flex;
108
+ align-items: center;
109
+ gap: 8px;
110
+ }
111
+
112
+ /* 🔢 Character Count */
113
+ .form-container-count {
114
+ font-size: 0.85rem;
115
+ color: #666;
116
+ }
117
+
118
+ /* ❌ Clear Button */
119
+ .form-container-clear {
120
+ border: none;
121
+ background: none;
122
+ color: #007aff;
123
+ cursor: pointer;
124
+ font-size: 0.85rem;
125
+ }
126
+
127
+ /* ✏️ Textarea Box */
128
+ .ext-textarea-box {
129
+ width: 100%;
130
+ }
131
+
132
+ .ext-textarea {
133
+ font-size: var(--input-txt-size);
134
+ border: none;
135
+ outline: none;
136
+ width: 100%;
137
+ font-weight: var(--d-font-weight);
138
+ display: grid;
139
+ justify-content: left;
140
+ align-items: center;
141
+ background-color: transparent;
142
+ color: var(--input-clr);
143
+ box-sizing: border-box;
144
+ resize: none;
145
+ overflow: hidden;
146
+ padding: 10px;
147
+ line-height: 1.5;
148
+ }
149
+
150
+ /* Required Highlight */
151
+ .ext-textarea.highlight {
152
+ border-color: green;
153
+ border-width: 3px;
154
+ border-style: solid;
155
+ }
@@ -7,7 +7,6 @@
7
7
  --ext-window-shadow: rgba(50, 50, 93, 0.25) 0px 13px 27px -5px, rgba(0, 0, 0, 0.3) 0px 8px 16px -8px;
8
8
  --ext-window-opacity: 0;
9
9
  --ext-window-transition: opacity 0.4s ease-in-out; */
10
-
11
10
  background-color: var(--ext-window-bck-color, white);
12
11
  position: absolute;
13
12
  width: var(--ext-window-width, 400px);
@@ -25,37 +24,16 @@
25
24
 
26
25
  /* Header */
27
26
  .ext-window-header {
28
- --ext-window-header-bck-color: var(--ext-window-bck-color, white);
29
27
  border-radius: var(--ext-window-border-radius, 12px) var(--ext-window-border-radius, 12px) 0 0;
30
- background-color: var(--ext-window-header-bck-color);
28
+ background-color: var(--ext-window-header-bck-color, white);
31
29
  height: var(--ext-window-header-height, 50px);
32
30
  cursor: pointer;
33
31
  }
34
32
 
35
- .ext-window-header-title {
36
- flex: 1;
37
- display: flex;
38
- align-items: center;
39
- line-height: 1.4;
40
- padding: 5px 0 2px 0;
41
- cursor: move;
42
- }
43
-
44
- .ext-window-header-close {
45
- display: flex;
46
- align-items: center;
47
- justify-content: center;
48
- background-color: var(--ext-window-close-bck, aqua);
49
- width: 40px;
50
- height: 40px;
51
- border-radius: var(--ext-window-border-radius, 12px);
52
- cursor: pointer;
53
- }
54
-
55
33
  /* Body */
56
34
  .ext-window-body {
57
35
  background-color: var(--ext-window-body-bck, transparent);
58
- min-height: var(--ext-window-min-height, 300px);
36
+ min-height: var(--ext-window-min-height, 200px);
59
37
  overflow: auto;
60
38
  }
61
39
 
@@ -63,12 +41,11 @@
63
41
  .ext-window-footer {
64
42
  background-color: var(--ext-window-footer-bck, transparent);
65
43
  height: var(--ext-window-footer-height, 50px);
66
-
67
44
  }
68
45
 
69
46
  /* Scrollbars for WebKit */
70
47
  ._ewb::-webkit-scrollbar {
71
- width: 0;
48
+ width: 6px;
72
49
  background-color: var(--ext-window-bck-color, white);
73
50
  }
74
51
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ehscan-react-components",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
4
4
  "description": "components",
5
5
  "main": "dist/Components.js",
6
6
  "types": "dist/Components.d.ts",