@axinom/mosaic-ui 0.31.0-rc.9 → 0.32.0-rc.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/components/DynamicDataList/DynamicListDataEntry/Renderers/createInputRenderer/createInputRenderer.d.ts.map +1 -1
- package/dist/components/DynamicDataList/DynamicListDataEntry/Renderers/renderers.model.d.ts +5 -4
- package/dist/components/DynamicDataList/DynamicListDataEntry/Renderers/renderers.model.d.ts.map +1 -1
- package/dist/components/DynamicDataList/index.d.ts +1 -1
- package/dist/components/DynamicDataList/index.d.ts.map +1 -1
- package/dist/components/EmptyStation/EmptyStation.d.ts +1 -1
- package/dist/components/EmptyStation/EmptyStation.d.ts.map +1 -1
- package/dist/components/Explorer/Explorer.d.ts.map +1 -1
- package/dist/components/FormElements/Checkbox/Checkbox.d.ts.map +1 -1
- package/dist/components/FormElements/CustomTags/CustomTags.d.ts.map +1 -1
- package/dist/components/FormElements/DateTimeField/DateTimeText.d.ts.map +1 -1
- package/dist/components/FormElements/DateTimeField/DateTimeTextField.d.ts.map +1 -1
- package/dist/components/FormElements/Form.models.d.ts +4 -4
- package/dist/components/FormElements/Form.models.d.ts.map +1 -1
- package/dist/components/FormElements/FormElementContainer/FormElementContainer.d.ts.map +1 -1
- package/dist/components/FormElements/MaskedSingleLineText/MaskedSingleLineText.d.ts +20 -0
- package/dist/components/FormElements/MaskedSingleLineText/MaskedSingleLineText.d.ts.map +1 -0
- package/dist/components/FormElements/MaskedSingleLineText/MaskedSingleLineTextField.d.ts +15 -0
- package/dist/components/FormElements/MaskedSingleLineText/MaskedSingleLineTextField.d.ts.map +1 -0
- package/dist/components/FormElements/Radio/Radio.d.ts +1 -0
- package/dist/components/FormElements/Radio/Radio.d.ts.map +1 -1
- package/dist/components/FormElements/SingleLineText/SingleLineText.d.ts +5 -2
- package/dist/components/FormElements/SingleLineText/SingleLineText.d.ts.map +1 -1
- package/dist/components/FormElements/ToggleButton/ToggleButton.d.ts.map +1 -1
- package/dist/components/FormElements/index.d.ts +1 -0
- package/dist/components/FormElements/index.d.ts.map +1 -1
- package/dist/components/FormStation/FormStation.d.ts.map +1 -1
- package/dist/components/PageHeader/PageHeaderAction/PageHeaderAction.d.ts.map +1 -1
- package/dist/components/Utils/Postgraphile/index.d.ts +3 -3
- package/dist/components/Utils/Postgraphile/index.d.ts.map +1 -1
- package/dist/components/Utils/Transformers/Timestamp.d.ts.map +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/helpers/utils.d.ts +8 -0
- package/dist/helpers/utils.d.ts.map +1 -1
- package/dist/index.es.js +4 -3
- package/dist/index.es.js.map +1 -0
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -0
- package/package.json +4 -3
- package/src/components/Actions/Action/Action.spec.tsx +2 -2
- package/src/components/Actions/Action/Action.tsx +1 -1
- package/src/components/DynamicDataList/DynamicListDataEntry/DynamicListDataEntry.scss +5 -1
- package/src/components/DynamicDataList/DynamicListDataEntry/Renderers/createInputRenderer/createInputRenderer.scss +0 -45
- package/src/components/DynamicDataList/DynamicListDataEntry/Renderers/createInputRenderer/createInputRenderer.spec.tsx +3 -61
- package/src/components/DynamicDataList/DynamicListDataEntry/Renderers/createInputRenderer/createInputRenderer.tsx +14 -15
- package/src/components/DynamicDataList/DynamicListDataEntry/Renderers/createSelectRenderer/createSelectRenderer.scss +2 -2
- package/src/components/DynamicDataList/DynamicListDataEntry/Renderers/renderers.model.ts +6 -4
- package/src/components/DynamicDataList/index.ts +2 -2
- package/src/components/EmptyStation/EmptyStation.spec.tsx +1 -1
- package/src/components/EmptyStation/EmptyStation.tsx +1 -1
- package/src/components/Explorer/Explorer.tsx +2 -2
- package/src/components/FormElements/Checkbox/Checkbox.scss +4 -1
- package/src/components/FormElements/Checkbox/Checkbox.tsx +1 -1
- package/src/components/FormElements/CustomTags/CustomTags.scss +0 -2
- package/src/components/FormElements/CustomTags/CustomTags.tsx +10 -4
- package/src/components/FormElements/DateTimeField/DateTimeText.tsx +1 -0
- package/src/components/FormElements/DateTimeField/DateTimeTextField.tsx +1 -2
- package/src/components/FormElements/Form.models.ts +4 -4
- package/src/components/FormElements/FormElementContainer/FormElementContainer.scss +6 -1
- package/src/components/FormElements/FormElementContainer/FormElementContainer.tsx +8 -1
- package/src/components/FormElements/MaskedSingleLineText/MaskedSingleLineText.spec.tsx +19 -0
- package/src/components/FormElements/MaskedSingleLineText/MaskedSingleLineText.stories.tsx +65 -0
- package/src/components/FormElements/MaskedSingleLineText/MaskedSingleLineText.tsx +60 -0
- package/src/components/FormElements/MaskedSingleLineText/MaskedSingleLineTextField.tsx +37 -0
- package/src/components/FormElements/Radio/Radio.scss +4 -0
- package/src/components/FormElements/Radio/Radio.spec.tsx +1 -1
- package/src/components/FormElements/Radio/Radio.tsx +30 -24
- package/src/components/FormElements/Select/Select.scss +10 -3
- package/src/components/FormElements/SingleLineText/SingleLineText.scss +1 -0
- package/src/components/FormElements/SingleLineText/SingleLineText.spec.tsx +2 -32
- package/src/components/FormElements/SingleLineText/SingleLineText.stories.tsx +9 -1
- package/src/components/FormElements/SingleLineText/SingleLineText.tsx +24 -32
- package/src/components/FormElements/Tags/Tags.scss +8 -1
- package/src/components/FormElements/ToggleButton/ToggleButton.scss +3 -2
- package/src/components/FormElements/ToggleButton/ToggleButton.tsx +1 -1
- package/src/components/FormElements/index.ts +1 -0
- package/src/components/FormStation/FormStation.stories.tsx +9 -0
- package/src/components/FormStation/FormStation.tsx +1 -1
- package/src/components/PageHeader/PageHeaderAction/PageHeaderAction.spec.tsx +1 -1
- package/src/components/PageHeader/PageHeaderAction/PageHeaderAction.tsx +1 -1
- package/src/components/Utils/Postgraphile/index.ts +3 -3
- package/src/components/Utils/Transformers/Timestamp.spec.ts +2 -2
- package/src/components/Utils/Transformers/Timestamp.ts +5 -1
- package/src/components/index.ts +1 -1
- package/src/helpers/utils.ts +17 -0
- package/src/styles/variables.scss +1 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { useField } from 'formik';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { useFormikError } from '../useFormikError';
|
|
4
|
+
import {
|
|
5
|
+
MaskedSingleLineText,
|
|
6
|
+
MaskedSingleLineTextProps,
|
|
7
|
+
} from './MaskedSingleLineText';
|
|
8
|
+
/**
|
|
9
|
+
* This component should be used to render a Masked TextBox inside a Formik form.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* <Field
|
|
13
|
+
* name="title"
|
|
14
|
+
* label="Title"
|
|
15
|
+
* as={MaskedSingleLineTextField}
|
|
16
|
+
mask={'00:00:00.000'},
|
|
17
|
+
placeholderChar={'0'}, />
|
|
18
|
+
*/
|
|
19
|
+
export const MaskedSingleLineTextField: React.FC<
|
|
20
|
+
Omit<MaskedSingleLineTextProps, 'error'>
|
|
21
|
+
> = (props) => {
|
|
22
|
+
const error = useFormikError(props.name);
|
|
23
|
+
|
|
24
|
+
const [, meta, helpers] = useField(props.name);
|
|
25
|
+
|
|
26
|
+
const handleChange = (value: string): void => {
|
|
27
|
+
helpers.setValue(value);
|
|
28
|
+
|
|
29
|
+
if (value === meta.initialValue) {
|
|
30
|
+
helpers.setTouched(false);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<MaskedSingleLineText {...props} onChange={handleChange} error={error} />
|
|
36
|
+
);
|
|
37
|
+
};
|
|
@@ -224,7 +224,7 @@ describe('Radio', () => {
|
|
|
224
224
|
expect(confirmation.exists()).toBe(true);
|
|
225
225
|
|
|
226
226
|
expect(radioSVG.at(0).hasClass('hasConfirm')).toBe(true);
|
|
227
|
-
expect(radioSVG.at(0).hasClass('unSelectable')).toBe(
|
|
227
|
+
expect(radioSVG.at(0).hasClass('unSelectable')).toBe(true);
|
|
228
228
|
expect(radioSVG.at(1).hasClass('hasConfirm')).toBe(false);
|
|
229
229
|
expect(radioSVG.at(1).hasClass('unSelectable')).toBe(true);
|
|
230
230
|
expect(radioSVG.at(2).hasClass('hasConfirm')).toBe(false);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import clsx from 'clsx';
|
|
2
2
|
import React, { useRef, useState } from 'react';
|
|
3
3
|
import {
|
|
4
|
-
ConfirmDialog,
|
|
5
4
|
ConfirmationConfig,
|
|
6
5
|
ConfirmationMode,
|
|
6
|
+
ConfirmDialog,
|
|
7
7
|
} from '../../ConfirmDialog';
|
|
8
8
|
import { BaseFormControl, BaseInputEvents } from '../Form.models';
|
|
9
9
|
import { FormElementContainer } from '../FormElementContainer';
|
|
@@ -31,6 +31,8 @@ interface RadioButtonProps {
|
|
|
31
31
|
inputValue?: string | number;
|
|
32
32
|
/** The new value currently stored as the confirmation dialog is rendered */
|
|
33
33
|
confirmValue?: string | number;
|
|
34
|
+
|
|
35
|
+
disabled?: boolean;
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
export const RadioButton: React.FC<RadioButtonProps> = ({
|
|
@@ -38,27 +40,27 @@ export const RadioButton: React.FC<RadioButtonProps> = ({
|
|
|
38
40
|
hasError,
|
|
39
41
|
inputValue,
|
|
40
42
|
confirmValue,
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
String(inputValue) !== String(confirmValue)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
43
|
+
disabled = false,
|
|
44
|
+
}) => (
|
|
45
|
+
<svg
|
|
46
|
+
className={clsx(classes.buttonContainer, {
|
|
47
|
+
[classes.checked]: checked,
|
|
48
|
+
[classes.hasError]: hasError,
|
|
49
|
+
[classes.hasConfirm]:
|
|
50
|
+
confirmValue !== undefined &&
|
|
51
|
+
String(inputValue) === String(confirmValue),
|
|
52
|
+
[classes.unSelectable]:
|
|
53
|
+
(confirmValue !== undefined &&
|
|
54
|
+
String(inputValue) !== String(confirmValue)) ||
|
|
55
|
+
disabled,
|
|
56
|
+
})}
|
|
57
|
+
preserveAspectRatio="xMidYMid meet"
|
|
58
|
+
viewBox="0 0 34 34"
|
|
59
|
+
>
|
|
60
|
+
<circle className={classes.radioOutline} cx="17" cy="17" r="15" />
|
|
61
|
+
<circle className={classes.radioDot} cx="17" cy="17" r="10" />
|
|
62
|
+
</svg>
|
|
63
|
+
);
|
|
62
64
|
|
|
63
65
|
/**
|
|
64
66
|
* Radio input form control
|
|
@@ -108,7 +110,7 @@ export const Radio: React.FC<RadioProps> = ({
|
|
|
108
110
|
currentTarget: { value: confirmValue as unknown as string },
|
|
109
111
|
} as React.ChangeEvent<HTMLInputElement>;
|
|
110
112
|
|
|
111
|
-
onChange && onChange(confirmed as React.
|
|
113
|
+
onChange && onChange(confirmed as React.ChangeEvent<HTMLInputElement>);
|
|
112
114
|
|
|
113
115
|
setConfirmation(false);
|
|
114
116
|
ref.current = undefined;
|
|
@@ -156,12 +158,16 @@ export const Radio: React.FC<RadioProps> = ({
|
|
|
156
158
|
onBlur={onBlur}
|
|
157
159
|
onFocus={onFocus}
|
|
158
160
|
/>
|
|
159
|
-
<label
|
|
161
|
+
<label
|
|
162
|
+
htmlFor={radioId}
|
|
163
|
+
className={clsx({ [classes.disabled]: disabled })}
|
|
164
|
+
>
|
|
160
165
|
<RadioButton
|
|
161
166
|
checked={checked}
|
|
162
167
|
hasError={errorMsg !== undefined}
|
|
163
168
|
inputValue={val}
|
|
164
169
|
confirmValue={confirmValue}
|
|
170
|
+
disabled={disabled}
|
|
165
171
|
/>
|
|
166
172
|
{labe}
|
|
167
173
|
</label>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
@import '../../../styles/common.scss';
|
|
2
2
|
|
|
3
3
|
@function svg-arrow-glyph($color) {
|
|
4
|
-
@return url('data:image/svg+xml;utf8,<svg stroke="'
|
|
4
|
+
@return url('data:image/svg+xml;utf8,<svg stroke="' + $color + '" version="1.1" xmlns="http://www.w3.org/2000/svg" width="40px" height="20px" viewBox="0 0 40 40"><path vector-effect="non-scaling-stroke" fill="none" stroke-width="2" d="M38.5,9.5L20,30.5L1.5,9.5" /></svg>');
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
.container {
|
|
@@ -37,6 +37,13 @@
|
|
|
37
37
|
border: 1px solid
|
|
38
38
|
var(--input-invalid-border-color, $input-invalid-border-color);
|
|
39
39
|
}
|
|
40
|
+
|
|
41
|
+
&:disabled {
|
|
42
|
+
cursor: default;
|
|
43
|
+
background-image: svg-arrow-glyph(
|
|
44
|
+
var(--select-arrow-color, encodecolor($select-disabled-arrow-color))
|
|
45
|
+
);
|
|
46
|
+
}
|
|
40
47
|
}
|
|
41
48
|
|
|
42
49
|
select,
|
|
@@ -47,8 +54,8 @@
|
|
|
47
54
|
text-overflow: ellipsis;
|
|
48
55
|
}
|
|
49
56
|
|
|
50
|
-
select:hover,
|
|
51
|
-
select:focus {
|
|
57
|
+
select:hover:enabled,
|
|
58
|
+
select:focus:enabled {
|
|
52
59
|
border: 1px solid var(--input-hover-color, $input-hover-color);
|
|
53
60
|
box-shadow: 0 0 0 2px var(--input-hover-color, $input-hover-color);
|
|
54
61
|
|
|
@@ -38,25 +38,6 @@ describe('TextField', () => {
|
|
|
38
38
|
expect(spy).toHaveBeenCalledWith({ target: { value: mockValueUpdated } });
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
it(`defaults to an empty string if prop value is 'null'`, () => {
|
|
42
|
-
// @ts-expect-error intentional null value
|
|
43
|
-
const wrapper = shallow(<SingleLineText name={'test-name'} value={null} />);
|
|
44
|
-
|
|
45
|
-
const input = wrapper.find('input');
|
|
46
|
-
|
|
47
|
-
expect(input.prop('value')).toBe('');
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it(`defaults to an empty string if prop value is 'undefined'`, () => {
|
|
51
|
-
const wrapper = shallow(
|
|
52
|
-
<SingleLineText name={'test-name'} value={undefined} />,
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
const input = wrapper.find('input');
|
|
56
|
-
|
|
57
|
-
expect(input.prop('value')).toBe('');
|
|
58
|
-
});
|
|
59
|
-
|
|
60
41
|
it('uses optional props when passed in', () => {
|
|
61
42
|
const mockProps = {
|
|
62
43
|
autoComplete: 'on',
|
|
@@ -124,9 +105,9 @@ describe('TextField', () => {
|
|
|
124
105
|
<SingleLineText name={'test-pwd'} type="password" isSet={true} />,
|
|
125
106
|
);
|
|
126
107
|
|
|
127
|
-
const input = wrapper.find('input');
|
|
108
|
+
const input = wrapper.find('input').getDOMNode<HTMLInputElement>();
|
|
128
109
|
|
|
129
|
-
expect(input.
|
|
110
|
+
expect(input.value).toBe(dummyPwd);
|
|
130
111
|
});
|
|
131
112
|
|
|
132
113
|
it('when user changes the value it should be displayed, when type is password', () => {
|
|
@@ -152,15 +133,4 @@ describe('TextField', () => {
|
|
|
152
133
|
}),
|
|
153
134
|
);
|
|
154
135
|
});
|
|
155
|
-
|
|
156
|
-
it('renders an empty string if value is not provided, when type is password', () => {
|
|
157
|
-
const initialVal = undefined;
|
|
158
|
-
const wrapper = mount(
|
|
159
|
-
<SingleLineText name={'test-pwd'} type="password" value={initialVal} />,
|
|
160
|
-
);
|
|
161
|
-
|
|
162
|
-
const input = wrapper.find('input');
|
|
163
|
-
|
|
164
|
-
expect(input.prop('value')).toBe('');
|
|
165
|
-
});
|
|
166
136
|
});
|
|
@@ -15,8 +15,16 @@ const groups = createGroups({
|
|
|
15
15
|
'inlineMode',
|
|
16
16
|
'name',
|
|
17
17
|
'id',
|
|
18
|
+
'innerRef',
|
|
19
|
+
],
|
|
20
|
+
Content: [
|
|
21
|
+
'label',
|
|
22
|
+
'placeholder',
|
|
23
|
+
'error',
|
|
24
|
+
'tooltipContent',
|
|
25
|
+
'value',
|
|
26
|
+
'defaultValue',
|
|
18
27
|
],
|
|
19
|
-
Content: ['label', 'placeholder', 'error', 'tooltipContent', 'value'],
|
|
20
28
|
Styling: ['className'],
|
|
21
29
|
Events: ['onChange', 'onBlur', 'onFocus'],
|
|
22
30
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import clsx from 'clsx';
|
|
2
|
-
import React, { ChangeEvent,
|
|
2
|
+
import React, { ChangeEvent, InputHTMLAttributes, useEffect } from 'react';
|
|
3
|
+
import { executeIfRefAvailable } from '../../../helpers/utils';
|
|
3
4
|
import { BaseFormControl, BaseInputEvents } from '../Form.models';
|
|
4
5
|
import { FormElementContainer } from '../FormElementContainer';
|
|
5
6
|
import classes from './SingleLineText.scss';
|
|
@@ -16,13 +17,17 @@ export interface SingleLineTextProps extends BaseFormControl, BaseInputEvents {
|
|
|
16
17
|
*/
|
|
17
18
|
isSet?: boolean;
|
|
18
19
|
/** Current value the form control has */
|
|
19
|
-
value?:
|
|
20
|
+
value?: InputHTMLAttributes<HTMLInputElement>['value'];
|
|
21
|
+
/** Default value for the form control */
|
|
22
|
+
defaultValue?: InputHTMLAttributes<HTMLInputElement>['defaultValue'];
|
|
20
23
|
/** Input placeholder */
|
|
21
24
|
placeholder?: string;
|
|
22
25
|
/** Whether or not the control should start focused (default: false) */
|
|
23
26
|
autoFocus?: boolean;
|
|
24
27
|
/** Whether or not the control supports auto complete */
|
|
25
28
|
autoComplete?: 'on' | 'off';
|
|
29
|
+
|
|
30
|
+
innerRef?: React.RefObject<HTMLInputElement>;
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
/**
|
|
@@ -40,6 +45,8 @@ export const SingleLineText: React.FC<SingleLineTextProps> = ({
|
|
|
40
45
|
error,
|
|
41
46
|
autoFocus = false,
|
|
42
47
|
autoComplete,
|
|
48
|
+
innerRef = React.createRef(),
|
|
49
|
+
defaultValue,
|
|
43
50
|
onChange,
|
|
44
51
|
onBlur,
|
|
45
52
|
onFocus,
|
|
@@ -47,47 +54,30 @@ export const SingleLineText: React.FC<SingleLineTextProps> = ({
|
|
|
47
54
|
...rest
|
|
48
55
|
}) => {
|
|
49
56
|
const errorMsg: string | undefined = error;
|
|
50
|
-
const [val, setVal] = useState(value ?? '');
|
|
51
|
-
const [isDirty, setDirty] = useState(false);
|
|
52
57
|
const DUMMY_PWD = '0000000000';
|
|
53
58
|
const isPasswordField = type === 'password' ? true : false;
|
|
54
59
|
|
|
55
60
|
useEffect(() => {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
} else if (!isSet) {
|
|
61
|
-
setVal('');
|
|
62
|
-
} else {
|
|
63
|
-
setVal(DUMMY_PWD);
|
|
64
|
-
}
|
|
65
|
-
} else {
|
|
66
|
-
setVal(value as string);
|
|
61
|
+
if (isPasswordField && isSet) {
|
|
62
|
+
executeIfRefAvailable(innerRef, (input) => {
|
|
63
|
+
input.value = DUMMY_PWD;
|
|
64
|
+
});
|
|
67
65
|
}
|
|
68
|
-
}, [
|
|
69
|
-
|
|
70
|
-
const handlePwdChange = (e: ChangeEvent<HTMLInputElement>): void => {
|
|
71
|
-
// For type === password, once user changed the pwd, show the actual value entered by the user.
|
|
72
|
-
setDirty(true);
|
|
73
|
-
setVal(e.target.value);
|
|
74
|
-
onChange && onChange(e);
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
const handleTextChange = (e: ChangeEvent<HTMLInputElement>): void => {
|
|
78
|
-
setVal(e.target.value);
|
|
79
|
-
onChange && onChange(e);
|
|
80
|
-
};
|
|
66
|
+
}, [innerRef, isPasswordField, isSet]);
|
|
81
67
|
|
|
82
68
|
const onFocusWrapper = (e: ChangeEvent<HTMLInputElement>): void => {
|
|
83
69
|
if (type === 'password' && isSet && !value) {
|
|
84
|
-
|
|
70
|
+
executeIfRefAvailable(innerRef, (input) => {
|
|
71
|
+
input.value = '';
|
|
72
|
+
});
|
|
85
73
|
}
|
|
86
74
|
onFocus?.(e);
|
|
87
75
|
};
|
|
88
76
|
const onBlurWrapper = (e: ChangeEvent<HTMLInputElement>): void => {
|
|
89
77
|
if (type === 'password' && isSet && !value) {
|
|
90
|
-
|
|
78
|
+
executeIfRefAvailable(innerRef, (input) => {
|
|
79
|
+
input.value = DUMMY_PWD;
|
|
80
|
+
});
|
|
91
81
|
}
|
|
92
82
|
onBlur?.(e);
|
|
93
83
|
};
|
|
@@ -108,12 +98,14 @@ export const SingleLineText: React.FC<SingleLineTextProps> = ({
|
|
|
108
98
|
id={id}
|
|
109
99
|
name={name}
|
|
110
100
|
type={type}
|
|
111
|
-
|
|
101
|
+
ref={innerRef}
|
|
102
|
+
value={value}
|
|
103
|
+
defaultValue={defaultValue}
|
|
112
104
|
disabled={disabled}
|
|
113
105
|
placeholder={placeholder}
|
|
114
106
|
autoFocus={autoFocus}
|
|
115
107
|
autoComplete={autoComplete}
|
|
116
|
-
onChange={
|
|
108
|
+
onChange={onChange}
|
|
117
109
|
onBlur={onBlurWrapper}
|
|
118
110
|
onFocus={onFocusWrapper}
|
|
119
111
|
/>
|
|
@@ -72,6 +72,13 @@
|
|
|
72
72
|
border: 1px solid
|
|
73
73
|
var(--input-invalid-border-color, $input-invalid-border-color);
|
|
74
74
|
}
|
|
75
|
+
|
|
76
|
+
&:disabled {
|
|
77
|
+
cursor: default;
|
|
78
|
+
background-image: svg-arrow-glyph(
|
|
79
|
+
var(--select-arrow-color, encodecolor($select-disabled-arrow-color))
|
|
80
|
+
);
|
|
81
|
+
}
|
|
75
82
|
}
|
|
76
83
|
|
|
77
84
|
select,
|
|
@@ -82,7 +89,7 @@
|
|
|
82
89
|
text-overflow: ellipsis;
|
|
83
90
|
}
|
|
84
91
|
|
|
85
|
-
select:hover {
|
|
92
|
+
select:hover:enabled {
|
|
86
93
|
border: 1px solid var(--input-hover-color, $input-hover-color);
|
|
87
94
|
box-shadow: 0 0 0 2px var(--input-hover-color, $input-hover-color);
|
|
88
95
|
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
background-color: white;
|
|
17
17
|
cursor: pointer;
|
|
18
18
|
|
|
19
|
-
&:hover {
|
|
19
|
+
&:hover:enabled {
|
|
20
|
+
transition: box-shadow 0.15s ease-in-out 0s;
|
|
20
21
|
box-shadow: 0 0 0 2px $blue;
|
|
21
22
|
}
|
|
22
23
|
|
|
@@ -65,7 +66,7 @@
|
|
|
65
66
|
}
|
|
66
67
|
|
|
67
68
|
&:disabled {
|
|
68
|
-
cursor:
|
|
69
|
+
cursor: default;
|
|
69
70
|
opacity: 0.5;
|
|
70
71
|
}
|
|
71
72
|
|
|
@@ -3,9 +3,9 @@ import React, { useEffect, useState } from 'react';
|
|
|
3
3
|
import { noop } from '../../../helpers/utils';
|
|
4
4
|
import { BaseButtonOptions } from '../../Buttons/Button.model';
|
|
5
5
|
import {
|
|
6
|
-
ConfirmDialog,
|
|
7
6
|
ConfirmationConfig,
|
|
8
7
|
ConfirmationMode,
|
|
8
|
+
ConfirmDialog,
|
|
9
9
|
} from '../../ConfirmDialog';
|
|
10
10
|
import { BaseFormControl } from '../Form.models';
|
|
11
11
|
import { FormElementContainer } from '../FormElementContainer';
|
|
@@ -29,6 +29,7 @@ export {
|
|
|
29
29
|
export { FormikDebug } from './FormikDebug/FormikDebug';
|
|
30
30
|
export { GenericField, GenericFieldProps } from './GenericField/GenericField';
|
|
31
31
|
export { LinkField, LinkFieldProps } from './Link/LinkField';
|
|
32
|
+
export { MaskedSingleLineText } from './MaskedSingleLineText/MaskedSingleLineText';
|
|
32
33
|
export { Radio, RadioProps } from './Radio/Radio';
|
|
33
34
|
export { RadioField } from './Radio/RadioField';
|
|
34
35
|
export { ReadOnlyField, ReadOnlyFieldProps } from './ReadOnly/ReadOnlyField';
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
} from '../FormElements';
|
|
23
23
|
import { CheckboxField } from '../FormElements/Checkbox/CheckboxField';
|
|
24
24
|
import { DynamicDataListField } from '../FormElements/DynamicDataListControl/DynamicDataListField';
|
|
25
|
+
import { MaskedSingleLineTextField } from '../FormElements/MaskedSingleLineText/MaskedSingleLineTextField';
|
|
25
26
|
import { InfoPanel, Paragraph, Section } from '../InfoPanel';
|
|
26
27
|
import { ErrorType } from '../models';
|
|
27
28
|
import { Details, DetailsProps } from './Details/Details';
|
|
@@ -129,6 +130,7 @@ interface DetailsValues {
|
|
|
129
130
|
released?: string;
|
|
130
131
|
list?: DynamicListStoryData[];
|
|
131
132
|
archived?: boolean;
|
|
133
|
+
timestamp?: string;
|
|
132
134
|
}
|
|
133
135
|
|
|
134
136
|
export const Extended: StoryObj<typeof Details> = (() => {
|
|
@@ -167,6 +169,7 @@ export const Extended: StoryObj<typeof Details> = (() => {
|
|
|
167
169
|
released: '2020-04-03T00:00:00.000+00:00',
|
|
168
170
|
list: listData,
|
|
169
171
|
archived: false,
|
|
172
|
+
timestamp: '00:00:00.001',
|
|
170
173
|
},
|
|
171
174
|
},
|
|
172
175
|
infoPanel: (
|
|
@@ -279,6 +282,12 @@ export const Extended: StoryObj<typeof Details> = (() => {
|
|
|
279
282
|
as={DynamicDataListField}
|
|
280
283
|
/>
|
|
281
284
|
<Field name="archived" label="Set Archived" as={CheckboxField} />
|
|
285
|
+
<Field
|
|
286
|
+
name="timestamp"
|
|
287
|
+
label="Timestamp"
|
|
288
|
+
mask="00:00:00.000"
|
|
289
|
+
as={MaskedSingleLineTextField}
|
|
290
|
+
/>
|
|
282
291
|
</>
|
|
283
292
|
),
|
|
284
293
|
},
|
|
@@ -22,12 +22,12 @@ import { Actions, ActionsProps } from '../Actions';
|
|
|
22
22
|
import { isNavigationAction } from '../Actions/Action/Action';
|
|
23
23
|
import { IconName } from '../Icons';
|
|
24
24
|
import { MessageBar } from '../MessageBar';
|
|
25
|
+
import { ErrorType, StationError, StationMessage } from '../models';
|
|
25
26
|
import {
|
|
26
27
|
PageHeader,
|
|
27
28
|
PageHeaderActionType,
|
|
28
29
|
PageHeaderProps,
|
|
29
30
|
} from '../PageHeader';
|
|
30
|
-
import { ErrorType, StationError, StationMessage } from '../models';
|
|
31
31
|
import { FormActionData, InitialFormData } from './FormStation.models';
|
|
32
32
|
import classes from './FormStation.scss';
|
|
33
33
|
import { SaveOnNavigate } from './SaveOnNavigate/SaveOnNavigate';
|
|
@@ -3,7 +3,7 @@ import React from 'react';
|
|
|
3
3
|
import { act } from 'react-dom/test-utils';
|
|
4
4
|
import { noop } from '../../../helpers/utils';
|
|
5
5
|
import { TextButton } from '../../Buttons';
|
|
6
|
-
import {
|
|
6
|
+
import { ConfirmationConfig, ConfirmDialog } from '../../ConfirmDialog';
|
|
7
7
|
import { IconName } from '../../Icons';
|
|
8
8
|
import {
|
|
9
9
|
PageHeaderAction,
|
|
@@ -2,9 +2,9 @@ import clsx from 'clsx';
|
|
|
2
2
|
import React, { useEffect, useState } from 'react';
|
|
3
3
|
import { noop } from '../../../helpers/utils';
|
|
4
4
|
import {
|
|
5
|
-
ConfirmDialog,
|
|
6
5
|
ConfirmationConfig,
|
|
7
6
|
ConfirmationMode,
|
|
7
|
+
ConfirmDialog,
|
|
8
8
|
useConfirmationDelay,
|
|
9
9
|
} from '../../ConfirmDialog';
|
|
10
10
|
import { IconName, Icons } from '../../Icons';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export * from './CreateConnectionRenderer';
|
|
2
2
|
export * from './FilterTransformer';
|
|
3
|
-
export * from './RangeTransformer';
|
|
4
|
-
export * from './SortTransformer';
|
|
5
|
-
export * from './UpdateGQLFragmentGenerator';
|
|
6
3
|
export * from './generateArrayMutations';
|
|
7
4
|
export * from './getArrayDiff';
|
|
8
5
|
export * from './getFormDiff';
|
|
6
|
+
export * from './RangeTransformer';
|
|
7
|
+
export * from './SortTransformer';
|
|
8
|
+
export * from './UpdateGQLFragmentGenerator';
|
|
@@ -13,7 +13,11 @@ export const formatSecondsToTimestamp: TransformerFunction<
|
|
|
13
13
|
number,
|
|
14
14
|
Timestamp
|
|
15
15
|
> = (timeInSeconds?: number | null): Timestamp => {
|
|
16
|
-
if (
|
|
16
|
+
if (
|
|
17
|
+
timeInSeconds === null ||
|
|
18
|
+
timeInSeconds === undefined ||
|
|
19
|
+
typeof timeInSeconds !== 'number'
|
|
20
|
+
) {
|
|
17
21
|
return TIMESTAMP_DEFAULT;
|
|
18
22
|
}
|
|
19
23
|
|
package/src/components/index.ts
CHANGED
|
@@ -19,8 +19,8 @@ export * from './List';
|
|
|
19
19
|
export * from './Loaders';
|
|
20
20
|
export * from './MessageBar';
|
|
21
21
|
export * from './Modal';
|
|
22
|
+
export * from './models';
|
|
22
23
|
export * from './NavigationAwareStation';
|
|
23
24
|
export * from './PageHeader';
|
|
24
25
|
export * from './ProgressBar';
|
|
25
26
|
export * from './Utils';
|
|
26
|
-
export * from './models';
|
package/src/helpers/utils.ts
CHANGED
|
@@ -11,6 +11,7 @@ export function noop(): void {}
|
|
|
11
11
|
*/
|
|
12
12
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
13
13
|
export const assertNever = (_type: never): void => {
|
|
14
|
+
// eslint-disable-next-line no-console
|
|
14
15
|
console.error(`Switch was not exhaustive`);
|
|
15
16
|
};
|
|
16
17
|
|
|
@@ -25,3 +26,19 @@ export type Maybe<T> = T | null;
|
|
|
25
26
|
export type Nullable<T> = {
|
|
26
27
|
[P in keyof T]: T[P] | null;
|
|
27
28
|
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Checks if the ref is available before executing the provided function.
|
|
32
|
+
* @param ref Mutable Ref Object to check
|
|
33
|
+
* @param fn Function to execute
|
|
34
|
+
* @param args Arguments for the function
|
|
35
|
+
*/
|
|
36
|
+
export const executeIfRefAvailable = async <U, T = never>(
|
|
37
|
+
ref: React.RefObject<U>,
|
|
38
|
+
fn: (arg0: U, ...args: T[]) => void,
|
|
39
|
+
...args: T[]
|
|
40
|
+
): Promise<void> => {
|
|
41
|
+
if (ref.current) {
|
|
42
|
+
fn(ref.current, ...args);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
@@ -182,6 +182,7 @@ $tag-font-color: $dark-gray;
|
|
|
182
182
|
$tag-background-color: $light-gray-2;
|
|
183
183
|
$form-error-color: $red;
|
|
184
184
|
$select-arrow-color: $blue;
|
|
185
|
+
$select-disabled-arrow-color: $light-gray;
|
|
185
186
|
$label-font-size: 16px;
|
|
186
187
|
$file-upload-progress: $blue;
|
|
187
188
|
$file-upload-progress-background: $light-gray-2;
|