@peassoft/mnr-web-ui-kit 2.2.1 → 2.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.
- package/dist/input-field/index.d.ts +19 -2
- package/dist/input-field/index.js +30 -6
- package/dist/input-field/styles.css +25 -3
- package/dist/plain-select/icons.d.ts +3 -0
- package/dist/plain-select/icons.js +39 -0
- package/dist/plain-select/index.js +2 -4
- package/dist/plain-select/styles.css +9 -5
- package/package.json +2 -2
- package/dist/plain-select/icon.d.ts +0 -6
- package/dist/plain-select/icon.js +0 -17
|
@@ -1,15 +1,32 @@
|
|
|
1
1
|
import { type JSX } from 'react';
|
|
2
2
|
import './styles.css';
|
|
3
3
|
type Props = {
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* Type of the inner input element
|
|
6
|
+
*
|
|
7
|
+
* @default text
|
|
8
|
+
*/
|
|
5
9
|
type?: 'text' | 'email' | 'password';
|
|
6
10
|
/** Label */
|
|
7
11
|
label: string;
|
|
12
|
+
/**
|
|
13
|
+
* Description text placed under the input field. Can be used to provide additional
|
|
14
|
+
* information about the input field, for example, about the expected format of the value.
|
|
15
|
+
*/
|
|
16
|
+
description?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Whether the input field is required. If true, an asterisk will be displayed next to the label.
|
|
19
|
+
*/
|
|
20
|
+
required?: boolean;
|
|
8
21
|
/** autocomplete attribute */
|
|
9
22
|
autocompleteAttribute?: string;
|
|
10
23
|
/** disabled attribule */
|
|
11
24
|
disabled?: boolean;
|
|
12
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* Width in any CSS length value
|
|
27
|
+
*
|
|
28
|
+
* @default 100%
|
|
29
|
+
*/
|
|
13
30
|
width?: string;
|
|
14
31
|
/** Error message */
|
|
15
32
|
errorMessage?: string;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState, useCallback, useEffect } from 'react';
|
|
2
|
+
import { useState, useCallback, useMemo, useEffect, useId } from 'react';
|
|
3
3
|
import './styles.css';
|
|
4
4
|
import processKeyDown from './process-key-down.js';
|
|
5
5
|
export function InputField(props) {
|
|
6
6
|
const {
|
|
7
7
|
type = 'text',
|
|
8
8
|
label,
|
|
9
|
+
description,
|
|
10
|
+
required,
|
|
9
11
|
autocompleteAttribute,
|
|
10
12
|
disabled = false,
|
|
11
13
|
width = '100%',
|
|
@@ -18,6 +20,14 @@ export function InputField(props) {
|
|
|
18
20
|
onBlur
|
|
19
21
|
} = props;
|
|
20
22
|
const [isCapslockOn, setIsCapslockOn] = useState(false);
|
|
23
|
+
const descriptionId = useId();
|
|
24
|
+
const errorMessageId = useId();
|
|
25
|
+
const inputDescribedByAttribute = useMemo(() => {
|
|
26
|
+
let returnValue = '';
|
|
27
|
+
if (errorMessage) returnValue = errorMessageId;
|
|
28
|
+
if (description) returnValue += ` ${descriptionId}`;
|
|
29
|
+
return returnValue || undefined;
|
|
30
|
+
}, [errorMessage, description, errorMessageId, descriptionId]);
|
|
21
31
|
const handleChange = useCallback(e => onChange(e.target.value), [onChange]);
|
|
22
32
|
const handleKeyDown = useCallback(e => processKeyDown(e, onTab, onShiftTab, onBlur), [onTab, onShiftTab, onBlur]);
|
|
23
33
|
useEffect(() => {
|
|
@@ -52,9 +62,13 @@ export function InputField(props) {
|
|
|
52
62
|
},
|
|
53
63
|
children: [_jsxs("label", {
|
|
54
64
|
className: 'uikit_InputField_innerCont',
|
|
55
|
-
children: [
|
|
65
|
+
children: [_jsxs("span", {
|
|
56
66
|
className: 'uikit_InputField_label',
|
|
57
|
-
children: label
|
|
67
|
+
children: [label, required && _jsx("span", {
|
|
68
|
+
className: 'uikit_InputField_required',
|
|
69
|
+
"aria-hidden": 'true',
|
|
70
|
+
children: "\u00A0*"
|
|
71
|
+
})]
|
|
58
72
|
}), _jsx("input", {
|
|
59
73
|
ref: ref,
|
|
60
74
|
className: 'uikit_InputField_input',
|
|
@@ -62,6 +76,8 @@ export function InputField(props) {
|
|
|
62
76
|
autoComplete: autocompleteAttribute,
|
|
63
77
|
disabled: disabled,
|
|
64
78
|
value: value,
|
|
79
|
+
"aria-describedby": inputDescribedByAttribute,
|
|
80
|
+
"aria-required": required || undefined,
|
|
65
81
|
onChange: handleChange,
|
|
66
82
|
onKeyDown: handleKeyDown,
|
|
67
83
|
onBlur: onBlur || undefined
|
|
@@ -79,9 +95,17 @@ export function InputField(props) {
|
|
|
79
95
|
}), _jsx("span", {
|
|
80
96
|
children: "CapsLock"
|
|
81
97
|
})]
|
|
82
|
-
}),
|
|
83
|
-
|
|
84
|
-
children: errorMessage
|
|
98
|
+
}), _jsx("div", {
|
|
99
|
+
"aria-live": 'assertive',
|
|
100
|
+
children: !!errorMessage && _jsx("div", {
|
|
101
|
+
className: 'uikit_InputField_errorMsg',
|
|
102
|
+
id: errorMessageId,
|
|
103
|
+
children: errorMessage
|
|
104
|
+
})
|
|
105
|
+
}), !!description && _jsx("div", {
|
|
106
|
+
className: 'uikit_InputField_description',
|
|
107
|
+
id: descriptionId,
|
|
108
|
+
children: description
|
|
85
109
|
})]
|
|
86
110
|
});
|
|
87
111
|
}
|
|
@@ -11,13 +11,23 @@
|
|
|
11
11
|
.uikit_InputField_label {
|
|
12
12
|
display: block;
|
|
13
13
|
margin-bottom: 0.25em;
|
|
14
|
-
color: #
|
|
14
|
+
color: #737373;
|
|
15
15
|
width: 100%;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
@media (prefers-color-scheme: dark) {
|
|
19
19
|
.uikit_InputField_label {
|
|
20
|
-
color: #
|
|
20
|
+
color: #acacac;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.uikit_InputField_required {
|
|
25
|
+
color: #a7241b;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@media (prefers-color-scheme: dark) {
|
|
29
|
+
.uikit_InputField_required {
|
|
30
|
+
color: #fb827a;
|
|
21
31
|
}
|
|
22
32
|
}
|
|
23
33
|
|
|
@@ -63,7 +73,7 @@
|
|
|
63
73
|
|
|
64
74
|
@media (prefers-color-scheme: dark) {
|
|
65
75
|
.uikit_InputField_capslockMsg {
|
|
66
|
-
color: #
|
|
76
|
+
color: #acacac;
|
|
67
77
|
}
|
|
68
78
|
}
|
|
69
79
|
|
|
@@ -89,3 +99,15 @@
|
|
|
89
99
|
color: #fb827a;
|
|
90
100
|
}
|
|
91
101
|
}
|
|
102
|
+
|
|
103
|
+
.uikit_InputField_description {
|
|
104
|
+
color: #737373;
|
|
105
|
+
font-size: 0.85rem;
|
|
106
|
+
margin-top: 0.2em;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@media (prefers-color-scheme: dark) {
|
|
110
|
+
.uikit_InputField_description {
|
|
111
|
+
color: #acacac;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
export function UncheckedIcon() {
|
|
3
|
+
return _jsx("svg", {
|
|
4
|
+
width: '24',
|
|
5
|
+
height: '24',
|
|
6
|
+
viewBox: '0 0 24 24',
|
|
7
|
+
fill: 'none',
|
|
8
|
+
stroke: 'currentColor',
|
|
9
|
+
strokeWidth: '1',
|
|
10
|
+
strokeLinecap: 'round',
|
|
11
|
+
strokeLinejoin: 'round',
|
|
12
|
+
className: 'uikit_PlainSelect_icon uikit_PlainSelect_uncheckedIcon',
|
|
13
|
+
children: _jsx("rect", {
|
|
14
|
+
width: '18',
|
|
15
|
+
height: '18',
|
|
16
|
+
x: '3',
|
|
17
|
+
y: '3',
|
|
18
|
+
rx: '2'
|
|
19
|
+
})
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
export function CheckedIcon() {
|
|
23
|
+
return _jsxs("svg", {
|
|
24
|
+
width: '24',
|
|
25
|
+
height: '24',
|
|
26
|
+
viewBox: '0 0 24 24',
|
|
27
|
+
fill: 'none',
|
|
28
|
+
stroke: 'currentColor',
|
|
29
|
+
strokeWidth: '2',
|
|
30
|
+
strokeLinecap: 'round',
|
|
31
|
+
strokeLinejoin: 'round',
|
|
32
|
+
className: 'uikit_PlainSelect_icon uikit_PlainSelect_checkedIcon',
|
|
33
|
+
children: [_jsx("path", {
|
|
34
|
+
d: 'M21 10.656V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h12.344'
|
|
35
|
+
}), _jsx("path", {
|
|
36
|
+
d: 'm9 11 3 3L22 4'
|
|
37
|
+
})]
|
|
38
|
+
});
|
|
39
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useId, useCallback, useState, useMemo, useLayoutEffect, createRef } from 'react';
|
|
3
3
|
import './styles.css';
|
|
4
|
-
import
|
|
4
|
+
import { UncheckedIcon, CheckedIcon } from './icons.js';
|
|
5
5
|
/**
|
|
6
6
|
* Select element implementing Listbox pattern. Presents a list of options and allows
|
|
7
7
|
* a user to select one or more of them.
|
|
@@ -177,9 +177,7 @@ export function PlainSelect(props) {
|
|
|
177
177
|
tabIndex: multiple && currFocusedIdx === idx ? 0 : -1,
|
|
178
178
|
onClick: () => handleItemClick(item.id),
|
|
179
179
|
onKeyDown: multiple ? handleMultiSelectKeyDown : undefined,
|
|
180
|
-
children: [_jsx(
|
|
181
|
-
selected: isSelected
|
|
182
|
-
}), _jsxs("div", {
|
|
180
|
+
children: [isSelected ? _jsx(CheckedIcon, {}) : _jsx(UncheckedIcon, {}), _jsxs("div", {
|
|
183
181
|
className: 'uikit_PlainSelect_itemContent',
|
|
184
182
|
children: [_jsx("div", {
|
|
185
183
|
children: item.title
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
.uikit_PlainSelect_label {
|
|
2
2
|
margin: 0;
|
|
3
|
-
color: #
|
|
3
|
+
color: #737373;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
@media (prefers-color-scheme: dark) {
|
|
7
7
|
.uikit_PlainSelect_label {
|
|
8
|
-
color: #
|
|
8
|
+
color: #acacac;
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
|
|
@@ -37,8 +37,12 @@
|
|
|
37
37
|
flex-shrink: 0;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
.
|
|
41
|
-
|
|
40
|
+
.uikit_PlainSelect_uncheckedIcon {
|
|
41
|
+
color: #767676;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.uikit_PlainSelect_checkedIcon {
|
|
45
|
+
color: #337e33;
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
.uikit_PlainSelect_itemContent {
|
|
@@ -51,6 +55,6 @@
|
|
|
51
55
|
|
|
52
56
|
.uikit_PlainSelect_description {
|
|
53
57
|
margin-top: 0.5em;
|
|
54
|
-
color: #
|
|
58
|
+
color: #737373;
|
|
55
59
|
font-size: 87.5%;
|
|
56
60
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peassoft/mnr-web-ui-kit",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Peassoft web UI kit for MNR web applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"react-dom": "^19.0.0",
|
|
47
47
|
"storybook": "^10.1.4",
|
|
48
48
|
"stylelint": "^17.0.0",
|
|
49
|
-
"typescript": "^
|
|
49
|
+
"typescript": "^6.0.2",
|
|
50
50
|
"vitest": "^4.0.7"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
export default function Icon(props) {
|
|
3
|
-
const {
|
|
4
|
-
selected
|
|
5
|
-
} = props;
|
|
6
|
-
const className = 'uikit_PlainSelect_icon' + (selected ? '' : ' uikit_PlainSelect_icon--hidden');
|
|
7
|
-
return _jsx("svg", {
|
|
8
|
-
className: className,
|
|
9
|
-
width: '24',
|
|
10
|
-
height: '24',
|
|
11
|
-
viewBox: '0 0 24 24',
|
|
12
|
-
children: _jsx("path", {
|
|
13
|
-
d: 'M9 16.172l10.594-10.594 1.406 1.406-12 12-5.578-5.578 1.406-1.406z',
|
|
14
|
-
fill: '#24b23e'
|
|
15
|
-
})
|
|
16
|
-
});
|
|
17
|
-
}
|