react-validate-component 0.2.0 → 0.4.0

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,210 @@
1
+ .invalid {
2
+ border: 2px solid red;
3
+ outline: none;
4
+ }
5
+ .invalid:focus,
6
+ .invalid:focus-visible,
7
+ .invalid:focus-within {
8
+ border: 2px solid red;
9
+ }
10
+
11
+ /* vType === 'outer' */
12
+ .vinput {
13
+ display: flex;
14
+ }
15
+ .vinput-top-left {
16
+ flex-direction: column-reverse;
17
+ align-items: flex-start;
18
+ justify-content: center;
19
+ }
20
+ .vinput-top {
21
+ flex-direction: column-reverse;
22
+ align-items: center;
23
+ justify-content: center;
24
+ }
25
+ .vinput-top-right {
26
+ flex-direction: column-reverse;
27
+ align-items: flex-end;
28
+ justify-content: center;
29
+ }
30
+ .vinput-center-left {
31
+ flex-direction: row-reverse;
32
+ align-items: center;
33
+ justify-content: center;
34
+ }
35
+ .vinput-center-right {
36
+ align-items: center;
37
+ justify-content: center;
38
+ }
39
+ .vinput-bottom-left {
40
+ flex-direction: column;
41
+ align-items: flex-start;
42
+ justify-content: center;
43
+ }
44
+ .vinput-bottom {
45
+ flex-direction: column;
46
+ align-items: center;
47
+ justify-content: center;
48
+ }
49
+ .vinput-bottom-right {
50
+ flex-direction: column;
51
+ align-items: flex-end;
52
+ justify-content: center;
53
+ }
54
+
55
+ /* vType === 'inner' */
56
+ .innerMessage {
57
+ position: absolute;
58
+ font-size: 12px;
59
+ margin: 0;
60
+ padding: 2px 5px;
61
+ display: flex;
62
+ }
63
+ .innerMessage-top-left {
64
+ align-items: flex-start;
65
+ justify-content: flex-start;
66
+ }
67
+ .innerMessage-top {
68
+ align-items: flex-start;
69
+ justify-content: center;
70
+ }
71
+ .innerMessage-top-right {
72
+ align-items: flex-start;
73
+ justify-content: flex-end;
74
+ }
75
+ .innerMessage-center-left {
76
+ align-items: center;
77
+ justify-content: flex-start;
78
+ }
79
+ .innerMessage-center {
80
+ align-items: center;
81
+ justify-content: center;
82
+ }
83
+ .innerMessage-center-right {
84
+ align-items: center;
85
+ justify-content: flex-end;
86
+ }
87
+ .innerMessage-bottom-left {
88
+ align-items: flex-end;
89
+ justify-content: flex-start;
90
+ }
91
+ .innerMessage-bottom {
92
+ align-items: flex-end;
93
+ justify-content: center;
94
+ }
95
+ .innerMessage-bottom-right {
96
+ align-items: flex-end;
97
+ justify-content: flex-end;
98
+ }
99
+
100
+ /* vType === 'tooltip' */
101
+ .tooltipMessage {
102
+ position: absolute;
103
+ margin: 0;
104
+ padding: 10px 20px;
105
+ border: 1px solid transparent;
106
+ border-radius: 10px;
107
+ background-color: black;
108
+ }
109
+ p[class*='tooltipMessage-top'] {
110
+ transform: translateY(calc(-100% - 10px));
111
+ }
112
+ p[class*='tooltipMessage-top']::after {
113
+ content: '';
114
+ position: absolute;
115
+ bottom: 0;
116
+ border: 10px solid transparent;
117
+ border-top-color: black;
118
+ border-bottom: 0;
119
+ margin-bottom: -11px;
120
+ }
121
+ .vinput.tooltipMessage-top-left {
122
+ justify-content: flex-start;
123
+ }
124
+ p.tooltipMessage-top-left::after {
125
+ left: 3%;
126
+ }
127
+ .vinput.tooltipMessage-top {
128
+ justify-content: center;
129
+ }
130
+ p.tooltipMessage-top::after {
131
+ left: 44%;
132
+ }
133
+ .tooltipMessage-top-right {
134
+ justify-content: flex-end;
135
+ }
136
+ p.tooltipMessage-top-right::after {
137
+ left: 87%;
138
+ }
139
+ p[class*='tooltipMessage-center'] {
140
+ /* transform: translateY(calc(-100% - 10px)); */
141
+ }
142
+ p[class*='tooltipMessage-center']::after {
143
+ content: '';
144
+ position: absolute;
145
+ border: 10px solid transparent;
146
+ }
147
+ .vinput.tooltipMessage-center-right {
148
+ justify-content: flex-end;
149
+ }
150
+ p.tooltipMessage-center-right {
151
+ transform: translateX(calc(100% + 10px));
152
+ }
153
+ p.tooltipMessage-center-right::after {
154
+ border-right-color: black;
155
+ left: -10%;
156
+ }
157
+ .vinput.tooltipMessage-center-left {
158
+ justify-content: flex-start;
159
+ }
160
+ p.tooltipMessage-center-left {
161
+ transform: translateX(calc(-100% - 10px));
162
+ }
163
+ p.tooltipMessage-center-left::after {
164
+ border-left-color: black;
165
+ left: 100%;
166
+ }
167
+
168
+ p[class*='tooltipMessage-bottom'] {
169
+ transform: translateY(calc(120% + 10px));
170
+ }
171
+ p[class*='tooltipMessage-bottom']::after {
172
+ content: '';
173
+ position: absolute;
174
+ top: 0;
175
+ border: 10px solid transparent;
176
+ border-bottom-color: black;
177
+ border-top: 0;
178
+ margin-top: -11px;
179
+ }
180
+ .vinput.tooltipMessage-bottom-left {
181
+ justify-content: flex-start;
182
+ }
183
+ p.tooltipMessage-bottom-left::after {
184
+ left: 3%;
185
+ }
186
+ .vinput.tooltipMessage-bottom {
187
+ justify-content: center;
188
+ }
189
+ p.tooltipMessage-bottom::after {
190
+ left: 44%;
191
+ }
192
+ .tooltipMessage-bottom-right {
193
+ justify-content: flex-end;
194
+ }
195
+ p.tooltipMessage-bottom-right::after {
196
+ left: 87%;
197
+ }
198
+
199
+ .animateMessage {
200
+ animation: fade-in 1s ease-in-out;
201
+ }
202
+
203
+ @keyframes fade-in {
204
+ 0% {
205
+ opacity: 0;
206
+ }
207
+ 100% {
208
+ opacity: 1;
209
+ }
210
+ }
@@ -1,5 +1,92 @@
1
1
  import React from 'react';
2
+ import styles from './index.module.css';
3
+ import { VTEXT_PARAMS } from './vEmail';
2
4
 
3
- export function vEmail() {
4
- return <input type="email" />;
5
+ export function VEmail({
6
+ vState = false,
7
+ vType = 'outer',
8
+ vClassName = '',
9
+ vShowMessage = false,
10
+ vMessage = '',
11
+ vLocateMessage = 'bottom',
12
+ vMessageClass = '',
13
+ vIsAnimate = false,
14
+ props = {},
15
+ }: VTEXT_PARAMS) {
16
+ switch (vType) {
17
+ case 'outer':
18
+ return (
19
+ <div
20
+ className={`${styles.vinput} ${styles[`vinput-${vLocateMessage}`]}`}
21
+ >
22
+ <input
23
+ type="email"
24
+ {...props}
25
+ defaultValue={props?.defaultValue ?? ''}
26
+ className={`${props?.className} ${
27
+ vState ? vClassName || styles.invalid : ''
28
+ }`}
29
+ ></input>
30
+ {vState && vShowMessage ? (
31
+ <p
32
+ className={`${vMessageClass} ${
33
+ vIsAnimate ? styles.animateMessage : ''
34
+ }`}
35
+ >
36
+ {vMessage}
37
+ </p>
38
+ ) : null}
39
+ </div>
40
+ );
41
+ case 'inner':
42
+ return (
43
+ <div className={styles.vinput}>
44
+ <input
45
+ type="email"
46
+ {...props}
47
+ defaultValue={props?.defaultValue ?? ''}
48
+ className={`${props?.className} ${
49
+ vState ? vClassName || styles.invalid : ''
50
+ }`}
51
+ ></input>
52
+ {vState && vShowMessage ? (
53
+ <p
54
+ className={`${vMessageClass} ${styles.innerMessage} ${
55
+ styles[`innerMessage-${vLocateMessage}`]
56
+ } ${vIsAnimate ? styles.animateMessage : ''}`}
57
+ >
58
+ {vMessage}
59
+ </p>
60
+ ) : null}
61
+ </div>
62
+ );
63
+ case 'tooltip':
64
+ return (
65
+ <div
66
+ className={`${styles.vinput} ${
67
+ styles[`tooltipMessage-${vLocateMessage}`]
68
+ }`}
69
+ >
70
+ <input
71
+ type="email"
72
+ {...props}
73
+ defaultValue={props?.defaultValue ?? ''}
74
+ className={`${props?.className} ${
75
+ vState ? vClassName || styles.invalid : ''
76
+ }`}
77
+ ></input>
78
+ {vState && vShowMessage ? (
79
+ <p
80
+ className={`${vMessageClass} ${styles.tooltipMessage} ${
81
+ styles[`tooltipMessage-${vLocateMessage}`]
82
+ } ${vIsAnimate ? styles.animateMessage : ''}`}
83
+ >
84
+ {vMessage}
85
+ </p>
86
+ ) : null}
87
+ </div>
88
+ );
89
+ default:
90
+ return <div></div>;
91
+ }
5
92
  }
@@ -0,0 +1,24 @@
1
+ import propsType from '../types/vprops';
2
+
3
+ // VText 파라미터
4
+ export interface VTEXT_PARAMS {
5
+ readonly vState: boolean; // 유효성 상태 값
6
+ readonly vType: // 유효성 메시지를 출력할 타입
7
+ 'inner' | 'outer' | 'tooltip';
8
+ vClassName?: string; // 유효성 입힐 class 명
9
+ readonly vShowMessage: boolean; // 유효성 메시지 출력할지
10
+ vMessage?: string; // 유효성 메시지
11
+ vLocateMessage?: // 유효성 메시지를 element 어디에 붙일지
12
+ | 'top-left'
13
+ | 'top'
14
+ | 'top-right'
15
+ | 'center-left'
16
+ | 'center'
17
+ | 'center-right'
18
+ | 'bottom-left'
19
+ | 'bottom'
20
+ | 'bottom-right';
21
+ vMessageClass?: string; // 유효성 메시지에 입힐 class 명
22
+ vIsAnimate?: boolean; // 유효성 메시지 출력 시 애니메이션 적용할지
23
+ props?: propsType; // 기타 옵션
24
+ }
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
2
 
3
- export function vRadio() {
3
+ export function VRadio() {
4
4
  return <input type="radio" />;
5
5
  }
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
2
 
3
- export function vRange() {
3
+ export function VRange() {
4
4
  return <input type="range" />;
5
5
  }
@@ -0,0 +1,210 @@
1
+ .invalid {
2
+ border: 2px solid red;
3
+ outline: none;
4
+ }
5
+ .invalid:focus,
6
+ .invalid:focus-visible,
7
+ .invalid:focus-within {
8
+ border: 2px solid red;
9
+ }
10
+
11
+ /* vType === 'outer' */
12
+ .vinput {
13
+ display: flex;
14
+ }
15
+ .vinput-top-left {
16
+ flex-direction: column-reverse;
17
+ align-items: flex-start;
18
+ justify-content: center;
19
+ }
20
+ .vinput-top {
21
+ flex-direction: column-reverse;
22
+ align-items: center;
23
+ justify-content: center;
24
+ }
25
+ .vinput-top-right {
26
+ flex-direction: column-reverse;
27
+ align-items: flex-end;
28
+ justify-content: center;
29
+ }
30
+ .vinput-center-left {
31
+ flex-direction: row-reverse;
32
+ align-items: center;
33
+ justify-content: center;
34
+ }
35
+ .vinput-center-right {
36
+ align-items: center;
37
+ justify-content: center;
38
+ }
39
+ .vinput-bottom-left {
40
+ flex-direction: column;
41
+ align-items: flex-start;
42
+ justify-content: center;
43
+ }
44
+ .vinput-bottom {
45
+ flex-direction: column;
46
+ align-items: center;
47
+ justify-content: center;
48
+ }
49
+ .vinput-bottom-right {
50
+ flex-direction: column;
51
+ align-items: flex-end;
52
+ justify-content: center;
53
+ }
54
+
55
+ /* vType === 'inner' */
56
+ .innerMessage {
57
+ position: absolute;
58
+ font-size: 12px;
59
+ margin: 0;
60
+ padding: 2px 5px;
61
+ display: flex;
62
+ }
63
+ .innerMessage-top-left {
64
+ align-items: flex-start;
65
+ justify-content: flex-start;
66
+ }
67
+ .innerMessage-top {
68
+ align-items: flex-start;
69
+ justify-content: center;
70
+ }
71
+ .innerMessage-top-right {
72
+ align-items: flex-start;
73
+ justify-content: flex-end;
74
+ }
75
+ .innerMessage-center-left {
76
+ align-items: center;
77
+ justify-content: flex-start;
78
+ }
79
+ .innerMessage-center {
80
+ align-items: center;
81
+ justify-content: center;
82
+ }
83
+ .innerMessage-center-right {
84
+ align-items: center;
85
+ justify-content: flex-end;
86
+ }
87
+ .innerMessage-bottom-left {
88
+ align-items: flex-end;
89
+ justify-content: flex-start;
90
+ }
91
+ .innerMessage-bottom {
92
+ align-items: flex-end;
93
+ justify-content: center;
94
+ }
95
+ .innerMessage-bottom-right {
96
+ align-items: flex-end;
97
+ justify-content: flex-end;
98
+ }
99
+
100
+ /* vType === 'tooltip' */
101
+ .tooltipMessage {
102
+ position: absolute;
103
+ margin: 0;
104
+ padding: 10px 20px;
105
+ border: 1px solid transparent;
106
+ border-radius: 10px;
107
+ background-color: black;
108
+ }
109
+ p[class*='tooltipMessage-top'] {
110
+ transform: translateY(calc(-100% - 10px));
111
+ }
112
+ p[class*='tooltipMessage-top']::after {
113
+ content: '';
114
+ position: absolute;
115
+ bottom: 0;
116
+ border: 10px solid transparent;
117
+ border-top-color: black;
118
+ border-bottom: 0;
119
+ margin-bottom: -11px;
120
+ }
121
+ .vinput.tooltipMessage-top-left {
122
+ justify-content: flex-start;
123
+ }
124
+ p.tooltipMessage-top-left::after {
125
+ left: 3%;
126
+ }
127
+ .vinput.tooltipMessage-top {
128
+ justify-content: center;
129
+ }
130
+ p.tooltipMessage-top::after {
131
+ left: 44%;
132
+ }
133
+ .tooltipMessage-top-right {
134
+ justify-content: flex-end;
135
+ }
136
+ p.tooltipMessage-top-right::after {
137
+ left: 87%;
138
+ }
139
+ p[class*='tooltipMessage-center'] {
140
+ /* transform: translateY(calc(-100% - 10px)); */
141
+ }
142
+ p[class*='tooltipMessage-center']::after {
143
+ content: '';
144
+ position: absolute;
145
+ border: 10px solid transparent;
146
+ }
147
+ .vinput.tooltipMessage-center-right {
148
+ justify-content: flex-end;
149
+ }
150
+ p.tooltipMessage-center-right {
151
+ transform: translateX(calc(100% + 10px));
152
+ }
153
+ p.tooltipMessage-center-right::after {
154
+ border-right-color: black;
155
+ left: -10%;
156
+ }
157
+ .vinput.tooltipMessage-center-left {
158
+ justify-content: flex-start;
159
+ }
160
+ p.tooltipMessage-center-left {
161
+ transform: translateX(calc(-100% - 10px));
162
+ }
163
+ p.tooltipMessage-center-left::after {
164
+ border-left-color: black;
165
+ left: 100%;
166
+ }
167
+
168
+ p[class*='tooltipMessage-bottom'] {
169
+ transform: translateY(calc(120% + 10px));
170
+ }
171
+ p[class*='tooltipMessage-bottom']::after {
172
+ content: '';
173
+ position: absolute;
174
+ top: 0;
175
+ border: 10px solid transparent;
176
+ border-bottom-color: black;
177
+ border-top: 0;
178
+ margin-top: -11px;
179
+ }
180
+ .vinput.tooltipMessage-bottom-left {
181
+ justify-content: flex-start;
182
+ }
183
+ p.tooltipMessage-bottom-left::after {
184
+ left: 3%;
185
+ }
186
+ .vinput.tooltipMessage-bottom {
187
+ justify-content: center;
188
+ }
189
+ p.tooltipMessage-bottom::after {
190
+ left: 44%;
191
+ }
192
+ .tooltipMessage-bottom-right {
193
+ justify-content: flex-end;
194
+ }
195
+ p.tooltipMessage-bottom-right::after {
196
+ left: 87%;
197
+ }
198
+
199
+ .animateMessage {
200
+ animation: fade-in 1s ease-in-out;
201
+ }
202
+
203
+ @keyframes fade-in {
204
+ 0% {
205
+ opacity: 0;
206
+ }
207
+ 100% {
208
+ opacity: 1;
209
+ }
210
+ }
@@ -1,5 +1,92 @@
1
1
  import React from 'react';
2
+ import styles from './index.module.css';
3
+ import { VTEXT_PARAMS } from './vURL';
2
4
 
3
- export function vURL() {
4
- return <input type="url" />;
5
+ export function VURL({
6
+ vState = false,
7
+ vType = 'outer',
8
+ vClassName = '',
9
+ vShowMessage = false,
10
+ vMessage = '',
11
+ vLocateMessage = 'bottom',
12
+ vMessageClass = '',
13
+ vIsAnimate = false,
14
+ props = {},
15
+ }: VTEXT_PARAMS) {
16
+ switch (vType) {
17
+ case 'outer':
18
+ return (
19
+ <div
20
+ className={`${styles.vinput} ${styles[`vinput-${vLocateMessage}`]}`}
21
+ >
22
+ <input
23
+ type="url"
24
+ {...props}
25
+ defaultValue={props?.defaultValue ?? ''}
26
+ className={`${props?.className} ${
27
+ vState ? vClassName || styles.invalid : ''
28
+ }`}
29
+ ></input>
30
+ {vState && vShowMessage ? (
31
+ <p
32
+ className={`${vMessageClass} ${
33
+ vIsAnimate ? styles.animateMessage : ''
34
+ }`}
35
+ >
36
+ {vMessage}
37
+ </p>
38
+ ) : null}
39
+ </div>
40
+ );
41
+ case 'inner':
42
+ return (
43
+ <div className={styles.vinput}>
44
+ <input
45
+ type="url"
46
+ {...props}
47
+ defaultValue={props?.defaultValue ?? ''}
48
+ className={`${props?.className} ${
49
+ vState ? vClassName || styles.invalid : ''
50
+ }`}
51
+ ></input>
52
+ {vState && vShowMessage ? (
53
+ <p
54
+ className={`${vMessageClass} ${styles.innerMessage} ${
55
+ styles[`innerMessage-${vLocateMessage}`]
56
+ } ${vIsAnimate ? styles.animateMessage : ''}`}
57
+ >
58
+ {vMessage}
59
+ </p>
60
+ ) : null}
61
+ </div>
62
+ );
63
+ case 'tooltip':
64
+ return (
65
+ <div
66
+ className={`${styles.vinput} ${
67
+ styles[`tooltipMessage-${vLocateMessage}`]
68
+ }`}
69
+ >
70
+ <input
71
+ type="url"
72
+ {...props}
73
+ defaultValue={props?.defaultValue ?? ''}
74
+ className={`${props?.className} ${
75
+ vState ? vClassName || styles.invalid : ''
76
+ }`}
77
+ ></input>
78
+ {vState && vShowMessage ? (
79
+ <p
80
+ className={`${vMessageClass} ${styles.tooltipMessage} ${
81
+ styles[`tooltipMessage-${vLocateMessage}`]
82
+ } ${vIsAnimate ? styles.animateMessage : ''}`}
83
+ >
84
+ {vMessage}
85
+ </p>
86
+ ) : null}
87
+ </div>
88
+ );
89
+ default:
90
+ return <div></div>;
91
+ }
5
92
  }
@@ -0,0 +1,24 @@
1
+ import propsType from '../types/vprops';
2
+
3
+ // VText 파라미터
4
+ export interface VTEXT_PARAMS {
5
+ readonly vState: boolean; // 유효성 상태 값
6
+ readonly vType: // 유효성 메시지를 출력할 타입
7
+ 'inner' | 'outer' | 'tooltip';
8
+ vClassName?: string; // 유효성 입힐 class 명
9
+ readonly vShowMessage: boolean; // 유효성 메시지 출력할지
10
+ vMessage?: string; // 유효성 메시지
11
+ vLocateMessage?: // 유효성 메시지를 element 어디에 붙일지
12
+ | 'top-left'
13
+ | 'top'
14
+ | 'top-right'
15
+ | 'center-left'
16
+ | 'center'
17
+ | 'center-right'
18
+ | 'bottom-left'
19
+ | 'bottom'
20
+ | 'bottom-right';
21
+ vMessageClass?: string; // 유효성 메시지에 입힐 class 명
22
+ vIsAnimate?: boolean; // 유효성 메시지 출력 시 애니메이션 적용할지
23
+ props?: propsType; // 기타 옵션
24
+ }