march-ui 0.0.4 → 0.0.6
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/Form/index.css +1 -0
- package/Form/index.jsx +7 -1
- package/README.md +1 -0
- package/Select/colors.css +96 -0
- package/Select/index.css +192 -0
- package/Select/index.d.ts +3 -0
- package/Select/index.jsx +195 -0
- package/Tabs/index.jsx +2 -1
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +1 -1
package/Form/index.css
CHANGED
package/Form/index.jsx
CHANGED
|
@@ -50,7 +50,13 @@ const Form = ({ attrs }) => {
|
|
|
50
50
|
}
|
|
51
51
|
return {
|
|
52
52
|
view({ attrs, children }) {
|
|
53
|
-
const {
|
|
53
|
+
const {
|
|
54
|
+
icon,
|
|
55
|
+
title,
|
|
56
|
+
onsubmit: onsubmitNext,
|
|
57
|
+
submit, beforeSubmit, afterSubmit, onerror, // internal usage only
|
|
58
|
+
...attributes
|
|
59
|
+
} = {
|
|
54
60
|
method: 'POST',
|
|
55
61
|
enctype: 'multipart/form-data',
|
|
56
62
|
...attrs
|
package/README.md
CHANGED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
html {
|
|
2
|
+
|
|
3
|
+
/* light theme */
|
|
4
|
+
|
|
5
|
+
--theme-light-select-foreground-color: var(--theme-light-foreground-color);
|
|
6
|
+
--theme-light-select-background-color: hsl(0,0%,95%);
|
|
7
|
+
--theme-light-select-border-color: hsl(0,0%,60%);
|
|
8
|
+
--theme-light-select-icon-color: hsl(0,0%,50%);
|
|
9
|
+
--theme-light-select-foreground-color-focused: var(--theme-light-foreground-color);
|
|
10
|
+
--theme-light-select-background-color-focused: hsl(0,0%,97%);
|
|
11
|
+
--theme-light-select-border-color-focused: hsl(0,0%,27%);
|
|
12
|
+
--theme-light-select-icon-color-focused: hsl(0,0%,25%);
|
|
13
|
+
--theme-light-select-foreground-color-disabled: hsl(0,0%,60%);
|
|
14
|
+
--theme-light-select-background-color-disabled: hsl(0,0%,97%);
|
|
15
|
+
--theme-light-select-border-color-disabled: hsl(0,0%,85%);
|
|
16
|
+
--theme-light-select-icon-color-disabled: hsl(0,0%,65%);
|
|
17
|
+
|
|
18
|
+
/* dark theme */
|
|
19
|
+
|
|
20
|
+
--theme-dark-select-foreground-color: var(--theme-dark-foreground-color);
|
|
21
|
+
--theme-dark-select-background-color: hsl(0,0%,16%);
|
|
22
|
+
--theme-dark-select-border-color: hsl(0,0%,33%);
|
|
23
|
+
--theme-dark-select-icon-color: hsl(0,0%,50%);
|
|
24
|
+
--theme-dark-select-foreground-color-focused: var(--theme-dark-foreground-color);
|
|
25
|
+
--theme-dark-select-background-color-focused: hsl(0,0%,18%);
|
|
26
|
+
--theme-dark-select-border-color-focused: hsl(0,0%,47%);
|
|
27
|
+
--theme-dark-select-icon-color-focused: hsl(0,0%,75%);
|
|
28
|
+
--theme-dark-select-foreground-color-disabled: hsl(0,0%,50%);
|
|
29
|
+
--theme-dark-select-background-color-disabled: hsl(0,0%,18%);
|
|
30
|
+
--theme-dark-select-border-color-disabled: hsl(0,0%,25%);
|
|
31
|
+
--theme-dark-select-icon-color-disabled: hsl(0,0%,30%);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.theme--light {
|
|
35
|
+
--select-foreground-color: var(--theme-light-select-foreground-color);
|
|
36
|
+
--select-background-color: var(--theme-light-select-background-color);
|
|
37
|
+
--select-border-color: var(--theme-light-select-border-color);
|
|
38
|
+
--select-icon-color: var(--theme-light-select-icon-color);
|
|
39
|
+
--select-foreground-color-focused: var(--theme-light-select-foreground-color-focused);
|
|
40
|
+
--select-background-color-focused: var(--theme-light-select-background-color-focused);
|
|
41
|
+
--select-border-color-focused: var(--theme-light-select-border-color-focused);
|
|
42
|
+
--select-icon-color-focused: var(--theme-light-select-icon-color-focused);
|
|
43
|
+
--select-foreground-color-disabled: var(--theme-light-select-foreground-color-disabled);
|
|
44
|
+
--select-background-color-disabled: var(--theme-light-select-background-color-disabled);
|
|
45
|
+
--select-border-color-disabled: var(--theme-light-select-border-color-disabled);
|
|
46
|
+
--select-icon-color-disabled: var(--theme-light-select-icon-color-disabled);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.theme--dark {
|
|
50
|
+
--select-foreground-color: var(--theme-dark-select-foreground-color);
|
|
51
|
+
--select-background-color: var(--theme-dark-select-background-color);
|
|
52
|
+
--select-border-color: var(--theme-dark-select-border-color);
|
|
53
|
+
--select-icon-color: var(--theme-dark-select-icon-color);
|
|
54
|
+
--select-foreground-color-focused: var(--theme-dark-select-foreground-color-focused);
|
|
55
|
+
--select-background-color-focused: var(--theme-dark-select-background-color-focused);
|
|
56
|
+
--select-border-color-focused: var(--theme-dark-select-border-color-focused);
|
|
57
|
+
--select-icon-color-focused: var(--theme-dark-select-icon-color-focused);
|
|
58
|
+
--select-foreground-color-disabled: var(--theme-dark-select-foreground-color-disabled);
|
|
59
|
+
--select-background-color-disabled: var(--theme-dark-select-background-color-disabled);
|
|
60
|
+
--select-border-color-disabled: var(--theme-dark-select-border-color-disabled);
|
|
61
|
+
--select-icon-color-disabled: var(--theme-dark-select-icon-color-disabled);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@media (prefers-color-scheme: light) {
|
|
65
|
+
html {
|
|
66
|
+
--select-foreground-color: var(--theme-light-select-foreground-color);
|
|
67
|
+
--select-background-color: var(--theme-light-select-background-color);
|
|
68
|
+
--select-border-color: var(--theme-light-select-border-color);
|
|
69
|
+
--select-icon-color: var(--theme-light-select-icon-color);
|
|
70
|
+
--select-foreground-color-focused: var(--theme-light-select-foreground-color-focused);
|
|
71
|
+
--select-background-color-focused: var(--theme-light-select-background-color-focused);
|
|
72
|
+
--select-border-color-focused: var(--theme-light-select-border-color-focused);
|
|
73
|
+
--select-icon-color-focused: var(--theme-light-select-icon-color-focused);
|
|
74
|
+
--select-foreground-color-disabled: var(--theme-light-select-foreground-color-disabled);
|
|
75
|
+
--select-background-color-disabled: var(--theme-light-select-background-color-disabled);
|
|
76
|
+
--select-border-color-disabled: var(--theme-light-select-border-color-disabled);
|
|
77
|
+
--select-icon-color-disabled: var(--theme-light-select-icon-color-disabled);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@media (prefers-color-scheme: dark) {
|
|
82
|
+
html {
|
|
83
|
+
--select-foreground-color: var(--theme-dark-select-foreground-color);
|
|
84
|
+
--select-background-color: var(--theme-dark-select-background-color);
|
|
85
|
+
--select-border-color: var(--theme-dark-select-border-color);
|
|
86
|
+
--select-icon-color: var(--theme-dark-select-icon-color);
|
|
87
|
+
--select-foreground-color-focused: var(--theme-dark-select-foreground-color-focused);
|
|
88
|
+
--select-background-color-focused: var(--theme-dark-select-background-color-focused);
|
|
89
|
+
--select-border-color-focused: var(--theme-dark-select-border-color-focused);
|
|
90
|
+
--select-icon-color-focused: var(--theme-dark-select-icon-color-focused);
|
|
91
|
+
--select-foreground-color-disabled: var(--theme-dark-select-foreground-color-disabled);
|
|
92
|
+
--select-background-color-disabled: var(--theme-dark-select-background-color-disabled);
|
|
93
|
+
--select-border-color-disabled: var(--theme-dark-select-border-color-disabled);
|
|
94
|
+
--select-icon-color-disabled: var(--theme-dark-select-icon-color-disabled);
|
|
95
|
+
}
|
|
96
|
+
}
|
package/Select/index.css
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
.select {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
width: 100%;
|
|
5
|
+
max-width: 24em;
|
|
6
|
+
box-sizing: border-box;
|
|
7
|
+
gap: 0.25em;
|
|
8
|
+
-webkit-tap-highlight-color: transparent;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.select__field {
|
|
12
|
+
display: flex;
|
|
13
|
+
flex-direction: row;
|
|
14
|
+
gap: 0.5em;
|
|
15
|
+
padding-left: 0.5em;
|
|
16
|
+
padding-right: 0.5em;
|
|
17
|
+
min-height: 3em;
|
|
18
|
+
border-radius: 0.5em;
|
|
19
|
+
box-sizing: border-box;
|
|
20
|
+
border: 1px solid var(--select-border-color);
|
|
21
|
+
background-color: var(--select-background-color);
|
|
22
|
+
color: var(--select-foreground-color);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.select--readonly {
|
|
26
|
+
pointer-events: none;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.select--disabled {
|
|
30
|
+
pointer-events: none;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.select--disabled > .select__field {
|
|
34
|
+
border-color: var(--select-border-color-disabled);
|
|
35
|
+
background-color: var(--select-background-color-disabled);
|
|
36
|
+
color: var(--select-foreground-color-disabled);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.select--disabled .select__icon > *,
|
|
40
|
+
.select--disabled .select__state > * {
|
|
41
|
+
color: var(--select-icon-color-disabled);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.select--focused > .select__field {
|
|
45
|
+
border-color: var(--select-border-color-focused);
|
|
46
|
+
background-color: var(--select-background-color-focused);
|
|
47
|
+
color: var(--select-foreground-color-focused);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.select--focused > .select__title {
|
|
51
|
+
opacity: 1;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.select--focused > .select__hint {
|
|
55
|
+
opacity: 0.75;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.select__icon,
|
|
59
|
+
.select__state {
|
|
60
|
+
box-sizing: border-box;
|
|
61
|
+
flex-shrink: 0;
|
|
62
|
+
flex-grow: 0;
|
|
63
|
+
display: flex;
|
|
64
|
+
align-items: center;
|
|
65
|
+
justify-content: center;
|
|
66
|
+
color: var(--select-icon-color);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.select__state {
|
|
70
|
+
display: none;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.select__icon > *,
|
|
74
|
+
.select__state > * {
|
|
75
|
+
font-size: 1.5em;
|
|
76
|
+
color: inherit;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.select__input {
|
|
80
|
+
box-sizing: border-box;
|
|
81
|
+
width: 100%;
|
|
82
|
+
flex-shrink: 1;
|
|
83
|
+
flex-grow: 1;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.select__input select {
|
|
87
|
+
display: block;
|
|
88
|
+
border: 0;
|
|
89
|
+
outline: 0;
|
|
90
|
+
padding: 0;
|
|
91
|
+
background-color: transparent;
|
|
92
|
+
font-family: inherit;
|
|
93
|
+
font-size: inherit;
|
|
94
|
+
width: 100%;
|
|
95
|
+
height: 100%;
|
|
96
|
+
appearance: none;
|
|
97
|
+
cursor: text;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.select__input option {
|
|
101
|
+
color: var(--select-foreground-color);
|
|
102
|
+
background-color: var(--select-background-color);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.select__input option[selected], .select__input option[selected]:hover {
|
|
106
|
+
color: var(--select-foreground-color-focused);
|
|
107
|
+
background-color: var(--select-background-color-focused);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.select__hint {
|
|
111
|
+
font-size: 0.85em;
|
|
112
|
+
opacity: 0.5;
|
|
113
|
+
padding-left: 0.5em;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.select__hint--invisible {
|
|
117
|
+
display: none;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.select__title {
|
|
121
|
+
opacity: 0.75;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.select.select--required > .select__title::after {
|
|
125
|
+
content: '*';
|
|
126
|
+
color: var(--error-color);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.select__state--loading {
|
|
130
|
+
animation-name: spin;
|
|
131
|
+
animation-iteration-count: infinite;
|
|
132
|
+
animation-duration: 0.25s;
|
|
133
|
+
animation-timing-function: linear;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.select--valid .select__state--valid {
|
|
137
|
+
display: flex;
|
|
138
|
+
color: var(--success-color);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.select--invalid .select__state--invalid {
|
|
142
|
+
display: flex;
|
|
143
|
+
color: var(--error-color);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.select--loading .select__state--loading {
|
|
147
|
+
display: flex;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.select--valid .select__input,
|
|
151
|
+
.select--valid .select__title,
|
|
152
|
+
.select--valid .select__hint {
|
|
153
|
+
color: var(--success-color);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.select--valid .select__field {
|
|
157
|
+
border-color: var(--success-color);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.select--focused.select--valid .select__input,
|
|
161
|
+
.select--focused.select--valid .select__title,
|
|
162
|
+
.select--focused.select--valid .select__hint {
|
|
163
|
+
color: var(--success-color-focused);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.select--focused.select--valid .select__field {
|
|
167
|
+
border-color: var(--success-color-focused);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.select--invalid .select__input,
|
|
171
|
+
.select--invalid .select__title,
|
|
172
|
+
.select--invalid .select__hint {
|
|
173
|
+
color: var(--error-color);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.select.select--invalid .select__field {
|
|
177
|
+
border-color: var(--error-color);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.select--focused.select--invalid .select__input,
|
|
181
|
+
.select--focused.select--invalid .select__title,
|
|
182
|
+
.select--focused.select--invalid .select__hint {
|
|
183
|
+
color: var(--error-color-focused);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.select--focused.select.select--invalid .select__field {
|
|
187
|
+
border-color: var(--error-color-focused);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.select--focused .select__icon > svg {
|
|
191
|
+
color: var(--select-icon-color-focused);
|
|
192
|
+
}
|
package/Select/index.jsx
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import './index.css'
|
|
2
|
+
import './colors.css'
|
|
3
|
+
import classNames from 'classnames'
|
|
4
|
+
|
|
5
|
+
marchUI.Select = {
|
|
6
|
+
messages: {
|
|
7
|
+
invalidValue: 'Invalid value',
|
|
8
|
+
pleaseWait: 'Please wait...'
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const doNothing = () => {}
|
|
13
|
+
|
|
14
|
+
const defaultAttributes = {
|
|
15
|
+
selected: '',
|
|
16
|
+
items: [],
|
|
17
|
+
onblur: doNothing,
|
|
18
|
+
onfocus: doNothing,
|
|
19
|
+
oninput: doNothing,
|
|
20
|
+
onerror: doNothing,
|
|
21
|
+
validityDelay: 0,
|
|
22
|
+
validate: inputElement => {
|
|
23
|
+
inputElement.setCustomValidity('')
|
|
24
|
+
return { valid: inputElement.checkValidity() }
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const Select = ({ attrs }) => {
|
|
29
|
+
let {
|
|
30
|
+
focused, state, hint,
|
|
31
|
+
onblur, onfocus, oninput, onerror,
|
|
32
|
+
validityDelay, validate, novalidate
|
|
33
|
+
} = {
|
|
34
|
+
...defaultAttributes,
|
|
35
|
+
...attrs
|
|
36
|
+
}
|
|
37
|
+
let timeoutId
|
|
38
|
+
let validationRequestId = 0
|
|
39
|
+
let validationProcess = false
|
|
40
|
+
const validateAsync = (requestId, inputElement) => () => {
|
|
41
|
+
Promise.resolve(validate(inputElement))
|
|
42
|
+
.then(result => {
|
|
43
|
+
if (validationRequestId === requestId) { // response is actual
|
|
44
|
+
const { valid, message } = result
|
|
45
|
+
state = valid ? 'valid' : 'invalid'
|
|
46
|
+
if (message !== undefined) {
|
|
47
|
+
inputElement.setCustomValidity(message)
|
|
48
|
+
hint = message
|
|
49
|
+
} else if (valid) {
|
|
50
|
+
inputElement.setCustomValidity('')
|
|
51
|
+
hint = undefined
|
|
52
|
+
}
|
|
53
|
+
m.redraw()
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
.catch(error => {
|
|
57
|
+
state = 'invalid'
|
|
58
|
+
onerror(error)
|
|
59
|
+
m.redraw()
|
|
60
|
+
})
|
|
61
|
+
.finally(() => {
|
|
62
|
+
validationProcess = false
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
const validateInput = (inputElement, useRedraw) => {
|
|
66
|
+
if (!novalidate && !validationProcess) {
|
|
67
|
+
validationProcess = true
|
|
68
|
+
const prevState = state
|
|
69
|
+
state = 'loading'
|
|
70
|
+
hint = undefined
|
|
71
|
+
if (prevState !== state && useRedraw && validityDelay > 0) {
|
|
72
|
+
m.redraw()
|
|
73
|
+
}
|
|
74
|
+
const requestId = ++ validationRequestId
|
|
75
|
+
clearTimeout(timeoutId)
|
|
76
|
+
if (validityDelay > 0) {
|
|
77
|
+
timeoutId = setTimeout(
|
|
78
|
+
validateAsync(requestId, inputElement),
|
|
79
|
+
validityDelay
|
|
80
|
+
)
|
|
81
|
+
} else {
|
|
82
|
+
validateAsync(requestId, inputElement)()
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const onblurHandler = evt => {
|
|
87
|
+
focused = false
|
|
88
|
+
return onblur(evt)
|
|
89
|
+
}
|
|
90
|
+
const onfocusHandler = evt => {
|
|
91
|
+
focused = true
|
|
92
|
+
return onfocus(evt)
|
|
93
|
+
}
|
|
94
|
+
const oninputHandler = evt => {
|
|
95
|
+
const result = oninput(evt)
|
|
96
|
+
validateInput(evt.target)
|
|
97
|
+
return result
|
|
98
|
+
}
|
|
99
|
+
const subscriptions = {}
|
|
100
|
+
const onFormValid = () => {
|
|
101
|
+
state = 'valid'
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
onremove() {
|
|
105
|
+
Object.values(subscriptions)
|
|
106
|
+
.forEach(unsubscribe => unsubscribe())
|
|
107
|
+
},
|
|
108
|
+
onupdate({ dom }) {
|
|
109
|
+
const inputElement = dom.querySelector('select')
|
|
110
|
+
if (state === 'valid') {
|
|
111
|
+
inputElement.setCustomValidity('')
|
|
112
|
+
} else if (state === 'invalid') {
|
|
113
|
+
inputElement.setCustomValidity(hint || marchUI.Select.messages.invalidValue)
|
|
114
|
+
} else if (state === 'loading') {
|
|
115
|
+
inputElement.setCustomValidity(marchUI.Select.messages.pleaseWait)
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
view({ attrs }) {
|
|
119
|
+
const {
|
|
120
|
+
title, iconLeft, iconRight, hint: hintNext, required, readonly, disabled,
|
|
121
|
+
onblur: onblurNext, onfocus: onfocusNext, oninput: oninputNext,
|
|
122
|
+
validate: validateNext, pattern,
|
|
123
|
+
state: stateNext,
|
|
124
|
+
items, selected,
|
|
125
|
+
formRef,
|
|
126
|
+
...rest
|
|
127
|
+
} = {
|
|
128
|
+
...defaultAttributes,
|
|
129
|
+
...attrs
|
|
130
|
+
}
|
|
131
|
+
onblur = onblurNext
|
|
132
|
+
onfocus = onfocusNext
|
|
133
|
+
oninput = oninputNext
|
|
134
|
+
validate = validateNext
|
|
135
|
+
if (stateNext !== undefined) {
|
|
136
|
+
state = stateNext
|
|
137
|
+
}
|
|
138
|
+
if (hintNext !== undefined) {
|
|
139
|
+
hint = hintNext
|
|
140
|
+
}
|
|
141
|
+
const classes = classNames('select', {
|
|
142
|
+
'select--focused': focused,
|
|
143
|
+
'select--required': required,
|
|
144
|
+
'select--readonly': readonly,
|
|
145
|
+
'select--disabled': disabled,
|
|
146
|
+
'select--invalid': state === 'invalid',
|
|
147
|
+
'select--valid': state === 'valid',
|
|
148
|
+
'select--loading': state === 'loading'
|
|
149
|
+
})
|
|
150
|
+
const attributes = {
|
|
151
|
+
...(required ? { required } : {}),
|
|
152
|
+
...(readonly ? { readonly } : {}),
|
|
153
|
+
...(disabled ? { disabled } : {}),
|
|
154
|
+
...rest
|
|
155
|
+
}
|
|
156
|
+
if (formRef) {
|
|
157
|
+
subscriptions.formValid = formRef.subscribe('formValid', onFormValid)
|
|
158
|
+
}
|
|
159
|
+
return (
|
|
160
|
+
<label class={classes}>
|
|
161
|
+
{title && <div class="select__title">{title}</div>}
|
|
162
|
+
<div class="select__field">
|
|
163
|
+
{iconLeft && <div class="select__icon">{iconLeft}</div>}
|
|
164
|
+
<div class="select__input">
|
|
165
|
+
<select {...attributes}
|
|
166
|
+
onblur={onblurHandler}
|
|
167
|
+
onfocus={onfocusHandler}
|
|
168
|
+
oninput={oninputHandler}
|
|
169
|
+
>
|
|
170
|
+
{items.map(item => (
|
|
171
|
+
<option value={item.value} selected={item.value === selected}>
|
|
172
|
+
{item.name}
|
|
173
|
+
</option>
|
|
174
|
+
))}
|
|
175
|
+
</select>
|
|
176
|
+
</div>
|
|
177
|
+
<div class="select__state select__state--valid">
|
|
178
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M21 7L9 19l-5.5-5.5l1.41-1.41L9 16.17L19.59 5.59z"/></svg>
|
|
179
|
+
</div>
|
|
180
|
+
<div class="select__state select__state--invalid">
|
|
181
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M11 15h2v2h-2zm0-8h2v6h-2zm1-5C6.47 2 2 6.5 2 12a10 10 0 0 0 10 10a10 10 0 0 0 10-10A10 10 0 0 0 12 2m0 18a8 8 0 0 1-8-8a8 8 0 0 1 8-8a8 8 0 0 1 8 8a8 8 0 0 1-8 8"/></svg>
|
|
182
|
+
</div>
|
|
183
|
+
<div class="select__state select__state--loading">
|
|
184
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M12 4V2A10 10 0 0 0 2 12h2a8 8 0 0 1 8-8"/></svg>
|
|
185
|
+
</div>
|
|
186
|
+
{iconRight && <div class="select__icon">{iconRight}</div>}
|
|
187
|
+
</div>
|
|
188
|
+
{hint && <div class="select__hint">{hint}</div>}
|
|
189
|
+
</label>
|
|
190
|
+
)
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export default Select
|
package/Tabs/index.jsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import './index.css'
|
|
2
2
|
import './colors.css'
|
|
3
3
|
import classNames from 'classnames'
|
|
4
|
+
import Tab from '../Tab'
|
|
4
5
|
|
|
5
6
|
const Tabs = ({ attrs }) => {
|
|
6
7
|
let { active } = attrs
|
|
@@ -11,7 +12,7 @@ const Tabs = ({ attrs }) => {
|
|
|
11
12
|
}
|
|
12
13
|
return {
|
|
13
14
|
view({ attrs: { active: activeNext, onchange, ...attributes }, children }) {
|
|
14
|
-
const tabs = children.filter(({ tag
|
|
15
|
+
const tabs = children.filter(({ tag }) => tag === Tab)
|
|
15
16
|
.map((tab, i) => {
|
|
16
17
|
const { key, attrs: { title } } = tab
|
|
17
18
|
tab.attrs = { ...tab.attrs, ...attributes }
|
package/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export type { MenuItem } from './MenuItem/index.d.ts'
|
|
|
7
7
|
export type { Notice } from './Notice/index.d.ts'
|
|
8
8
|
export type { Splitter } from './Splitter/index.d.ts'
|
|
9
9
|
export type { TextField } from './TextField/index.d.ts'
|
|
10
|
+
export type { Select } from './Select/index.d.ts'
|
|
10
11
|
export type { ThemeToggler } from './ThemeToggler/index.d.ts'
|
|
11
12
|
export type { Tab } from './Tab/index.d.ts'
|
|
12
13
|
export type { Tabs } from './Tabs/index.d.ts'
|
package/index.js
CHANGED
|
@@ -8,6 +8,7 @@ export { default as MenuItem } from './MenuItem'
|
|
|
8
8
|
export { default as Notice } from './Notice'
|
|
9
9
|
export { default as Splitter } from './Splitter'
|
|
10
10
|
export { default as TextField } from './TextField'
|
|
11
|
+
export { default as Select } from './Select'
|
|
11
12
|
export { default as ThemeToggler } from './ThemeToggler'
|
|
12
13
|
export { default as Tab } from './Tab'
|
|
13
14
|
export { default as Tabs } from './Tabs'
|