@scm-manager/ui-components 2.29.1 → 2.29.2-20220017-180458
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scm-manager/ui-components",
|
|
3
|
-
"version": "2.29.
|
|
3
|
+
"version": "2.29.2-20220017-180458",
|
|
4
4
|
"description": "UI Components for SCM-Manager and its plugins",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"files": [
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"@scm-manager/jest-preset": "^2.13.0",
|
|
26
26
|
"@scm-manager/prettier-config": "^2.10.1",
|
|
27
27
|
"@scm-manager/tsconfig": "^2.12.0",
|
|
28
|
-
"@scm-manager/ui-tests": "^2.29.
|
|
28
|
+
"@scm-manager/ui-tests": "^2.29.2-20220017-180458",
|
|
29
29
|
"@storybook/addon-actions": "^6.3.12",
|
|
30
30
|
"@storybook/addon-storyshots": "^6.3.12",
|
|
31
31
|
"@storybook/builder-webpack5": "^6.3.12",
|
|
@@ -65,9 +65,9 @@
|
|
|
65
65
|
"worker-plugin": "^3.2.0"
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"@scm-manager/ui-api": "^2.29.
|
|
69
|
-
"@scm-manager/ui-extensions": "^2.29.
|
|
70
|
-
"@scm-manager/ui-types": "^2.29.
|
|
68
|
+
"@scm-manager/ui-api": "^2.29.2-20220017-180458",
|
|
69
|
+
"@scm-manager/ui-extensions": "^2.29.2-20220017-180458",
|
|
70
|
+
"@scm-manager/ui-types": "^2.29.2-20220017-180458",
|
|
71
71
|
"classnames": "^2.2.6",
|
|
72
72
|
"date-fns": "^2.4.1",
|
|
73
73
|
"deepmerge": "^4.2.2",
|
package/src/Autocomplete.tsx
CHANGED
|
@@ -37,8 +37,11 @@ type Props = {
|
|
|
37
37
|
placeholder: string;
|
|
38
38
|
loadingMessage: string;
|
|
39
39
|
noOptionsMessage: string;
|
|
40
|
+
errorMessage?: string;
|
|
41
|
+
informationMessage?: string;
|
|
40
42
|
creatable?: boolean;
|
|
41
43
|
className?: string;
|
|
44
|
+
disabled?: boolean;
|
|
42
45
|
};
|
|
43
46
|
|
|
44
47
|
type State = {};
|
|
@@ -78,52 +81,51 @@ class Autocomplete extends React.Component<Props, State> {
|
|
|
78
81
|
loadingMessage,
|
|
79
82
|
noOptionsMessage,
|
|
80
83
|
loadSuggestions,
|
|
84
|
+
errorMessage,
|
|
85
|
+
informationMessage,
|
|
81
86
|
creatable,
|
|
82
|
-
className
|
|
87
|
+
className,
|
|
88
|
+
disabled
|
|
83
89
|
} = this.props;
|
|
84
90
|
|
|
91
|
+
const asyncProps = {
|
|
92
|
+
className: "autocomplete-entry",
|
|
93
|
+
classNamePrefix: "autocomplete-entry",
|
|
94
|
+
cacheOptions: true,
|
|
95
|
+
loadOptions: loadSuggestions,
|
|
96
|
+
onChange: this.handleInputChange,
|
|
97
|
+
value,
|
|
98
|
+
placeholder,
|
|
99
|
+
loadingMessage: () => loadingMessage,
|
|
100
|
+
noOptionsMessage: () => noOptionsMessage,
|
|
101
|
+
isDisabled: disabled,
|
|
102
|
+
"aria-label": helpText || label
|
|
103
|
+
};
|
|
104
|
+
|
|
85
105
|
return (
|
|
86
106
|
<div className={classNames("field", className)}>
|
|
87
107
|
<LabelWithHelpIcon label={label} helpText={helpText} />
|
|
88
108
|
<div className="control">
|
|
89
109
|
{creatable ? (
|
|
90
110
|
<AsyncCreatable
|
|
91
|
-
|
|
92
|
-
classNamePrefix="autocomplete-entry"
|
|
93
|
-
cacheOptions
|
|
94
|
-
loadOptions={loadSuggestions}
|
|
95
|
-
onChange={this.handleInputChange}
|
|
96
|
-
value={value}
|
|
97
|
-
placeholder={placeholder}
|
|
98
|
-
loadingMessage={() => loadingMessage}
|
|
99
|
-
noOptionsMessage={() => noOptionsMessage}
|
|
111
|
+
{...asyncProps}
|
|
100
112
|
isValidNewOption={this.isValidNewOption}
|
|
101
|
-
onCreateOption={
|
|
113
|
+
onCreateOption={newValue => {
|
|
102
114
|
this.selectValue({
|
|
103
|
-
label:
|
|
115
|
+
label: newValue,
|
|
104
116
|
value: {
|
|
105
|
-
id:
|
|
106
|
-
displayName:
|
|
117
|
+
id: newValue,
|
|
118
|
+
displayName: newValue
|
|
107
119
|
}
|
|
108
120
|
});
|
|
109
121
|
}}
|
|
110
|
-
aria-label={helpText || label}
|
|
111
122
|
/>
|
|
112
123
|
) : (
|
|
113
|
-
<Async
|
|
114
|
-
className="autocomplete-entry"
|
|
115
|
-
classNamePrefix="autocomplete-entry"
|
|
116
|
-
cacheOptions
|
|
117
|
-
loadOptions={loadSuggestions}
|
|
118
|
-
onChange={this.handleInputChange}
|
|
119
|
-
value={value}
|
|
120
|
-
placeholder={placeholder}
|
|
121
|
-
loadingMessage={() => loadingMessage}
|
|
122
|
-
noOptionsMessage={() => noOptionsMessage}
|
|
123
|
-
aria-label={helpText || label}
|
|
124
|
-
/>
|
|
124
|
+
<Async {...asyncProps} />
|
|
125
125
|
)}
|
|
126
126
|
</div>
|
|
127
|
+
{errorMessage ? <p className="help is-danger">{errorMessage}</p> : null}
|
|
128
|
+
{informationMessage ? <p className="help is-info">{informationMessage}</p> : null}
|
|
127
129
|
</div>
|
|
128
130
|
);
|
|
129
131
|
}
|
|
@@ -19219,6 +19219,10 @@ exports[`Storyshots Modal/Modal With form elements 1`] = `null`;
|
|
|
19219
19219
|
|
|
19220
19220
|
exports[`Storyshots Modal/Modal With long tooltips 1`] = `null`;
|
|
19221
19221
|
|
|
19222
|
+
exports[`Storyshots Modal/Modal With overflow 1`] = `null`;
|
|
19223
|
+
|
|
19224
|
+
exports[`Storyshots Modal/Modal With overflow and footer 1`] = `null`;
|
|
19225
|
+
|
|
19222
19226
|
exports[`Storyshots Notification Closeable 1`] = `
|
|
19223
19227
|
<div
|
|
19224
19228
|
className="Notificationstories__Wrapper-sc-8fx7tr-0 gJPbVB"
|
|
@@ -32,6 +32,8 @@ import ExternalLink from "../navigation/ExternalLink";
|
|
|
32
32
|
import { Radio, Textarea, InputField } from "../forms";
|
|
33
33
|
import { ButtonGroup, Button } from "../buttons";
|
|
34
34
|
import Notification from "../Notification";
|
|
35
|
+
import { Autocomplete } from "../index";
|
|
36
|
+
import { SelectValue } from "@scm-manager/ui-types";
|
|
35
37
|
|
|
36
38
|
const TopAndBottomMargin = styled.div`
|
|
37
39
|
margin: 0.75rem 0; // only for aesthetic reasons
|
|
@@ -51,7 +53,9 @@ const text = `Mind-paralyzing change needed improbability vortex machine sorts s
|
|
|
51
53
|
ordinary mob.`;
|
|
52
54
|
|
|
53
55
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
54
|
-
const doNothing = () => {
|
|
56
|
+
const doNothing = () => {
|
|
57
|
+
// nothing to do
|
|
58
|
+
};
|
|
55
59
|
const withFormElementsBody = (
|
|
56
60
|
<>
|
|
57
61
|
<RadioList>
|
|
@@ -71,8 +75,21 @@ const withFormElementsFooter = (
|
|
|
71
75
|
</ButtonGroup>
|
|
72
76
|
);
|
|
73
77
|
|
|
78
|
+
const loadSuggestions: (p: string) => Promise<SelectValue[]> = () =>
|
|
79
|
+
new Promise(resolve => {
|
|
80
|
+
setTimeout(() => {
|
|
81
|
+
resolve([
|
|
82
|
+
{ value: { id: "trillian", displayName: "Tricia McMillan" }, label: "Tricia McMillan" },
|
|
83
|
+
{ value: { id: "zaphod", displayName: "Zaphod Beeblebrox" }, label: "Zaphod Beeblebrox" },
|
|
84
|
+
{ value: { id: "ford", displayName: "Ford Prefect" }, label: "Ford Prefect" },
|
|
85
|
+
{ value: { id: "dent", displayName: "Arthur Dent" }, label: "Arthur Dent" },
|
|
86
|
+
{ value: { id: "marvin", displayName: "Marvin" }, label: "Marvin the Paranoid Android " }
|
|
87
|
+
]);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
74
91
|
storiesOf("Modal/Modal", module)
|
|
75
|
-
.addDecorator(
|
|
92
|
+
.addDecorator(story => <MemoryRouter initialEntries={["/"]}>{story()}</MemoryRouter>)
|
|
76
93
|
.add("Default", () => (
|
|
77
94
|
<NonCloseableModal>
|
|
78
95
|
<p>{text}</p>
|
|
@@ -104,7 +121,7 @@ storiesOf("Modal/Modal", module)
|
|
|
104
121
|
This story exists because we had a problem, that long tooltips causes a horizontal scrollbar on the modal.
|
|
105
122
|
</Notification>
|
|
106
123
|
<hr />
|
|
107
|
-
<p>The following elements will have a
|
|
124
|
+
<p>The following elements will have a very long help text, which has triggered the scrollbar in the past.</p>
|
|
108
125
|
<hr />
|
|
109
126
|
<TopAndBottomMargin>
|
|
110
127
|
<Checkbox label="Checkbox" checked={true} helpText={text} />
|
|
@@ -211,10 +228,47 @@ storiesOf("Modal/Modal", module)
|
|
|
211
228
|
</p>
|
|
212
229
|
</div>
|
|
213
230
|
</NonCloseableModal>
|
|
214
|
-
))
|
|
231
|
+
))
|
|
232
|
+
.add("With overflow", () => {
|
|
233
|
+
return (
|
|
234
|
+
<NonCloseableModal overflowVisible={true}>
|
|
235
|
+
<h1 className="title">Please Select</h1>
|
|
236
|
+
<Autocomplete
|
|
237
|
+
valueSelected={() => {
|
|
238
|
+
// nothing to do
|
|
239
|
+
}}
|
|
240
|
+
loadSuggestions={loadSuggestions}
|
|
241
|
+
/>
|
|
242
|
+
</NonCloseableModal>
|
|
243
|
+
);
|
|
244
|
+
})
|
|
245
|
+
.add("With overflow and footer", () => {
|
|
246
|
+
return (
|
|
247
|
+
<NonCloseableModal overflowVisible={true} footer={withFormElementsFooter}>
|
|
248
|
+
<h1 className="title">Please Select</h1>
|
|
249
|
+
<Autocomplete
|
|
250
|
+
valueSelected={() => {
|
|
251
|
+
// nothing to do
|
|
252
|
+
}}
|
|
253
|
+
loadSuggestions={loadSuggestions}
|
|
254
|
+
/>
|
|
255
|
+
</NonCloseableModal>
|
|
256
|
+
);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
type NonCloseableModalProps = { overflowVisible?: boolean; footer?: any };
|
|
215
260
|
|
|
216
|
-
const NonCloseableModal: FC = ({ children }) => {
|
|
217
|
-
return
|
|
261
|
+
const NonCloseableModal: FC<NonCloseableModalProps> = ({ overflowVisible, footer, children }) => {
|
|
262
|
+
return (
|
|
263
|
+
<Modal
|
|
264
|
+
body={children}
|
|
265
|
+
closeFunction={doNothing}
|
|
266
|
+
active={true}
|
|
267
|
+
title={"Hitchhiker Modal"}
|
|
268
|
+
overflowVisible={overflowVisible}
|
|
269
|
+
footer={footer}
|
|
270
|
+
/>
|
|
271
|
+
);
|
|
218
272
|
};
|
|
219
273
|
|
|
220
274
|
const CloseableModal: FC = ({ children }) => {
|
package/src/modals/Modal.tsx
CHANGED
|
@@ -42,10 +42,24 @@ type Props = {
|
|
|
42
42
|
headColor?: string;
|
|
43
43
|
headTextColor?: string;
|
|
44
44
|
size?: ModalSize;
|
|
45
|
+
overflowVisible?: boolean;
|
|
45
46
|
};
|
|
46
47
|
|
|
47
|
-
const SizedModal = styled.div<{ size?: ModalSize }>`
|
|
48
|
+
const SizedModal = styled.div<{ size?: ModalSize; overflow: string }>`
|
|
48
49
|
width: ${props => (props.size ? `${modalSizes[props.size]}%` : "640px")};
|
|
50
|
+
overflow: ${props => props.overflow};
|
|
51
|
+
`;
|
|
52
|
+
|
|
53
|
+
const DivWithOptionalOverflow = styled.div<{ overflow: string; borderBottomRadius: string }>`
|
|
54
|
+
overflow: ${props => props.overflow};
|
|
55
|
+
border-bottom-left-radius: ${props => props.borderBottomRadius};
|
|
56
|
+
border-bottom-right-radius: ${props => props.borderBottomRadius};
|
|
57
|
+
`;
|
|
58
|
+
|
|
59
|
+
const SectionWithOptionalOverflow = styled.section<{ overflow: string; borderBottomRadius: string }>`
|
|
60
|
+
overflow: ${props => props.overflow};
|
|
61
|
+
border-bottom-left-radius: ${props => props.borderBottomRadius};
|
|
62
|
+
border-bottom-right-radius: ${props => props.borderBottomRadius};
|
|
49
63
|
`;
|
|
50
64
|
|
|
51
65
|
export const Modal: FC<Props> = ({
|
|
@@ -57,7 +71,8 @@ export const Modal: FC<Props> = ({
|
|
|
57
71
|
className,
|
|
58
72
|
headColor = "secondary-less",
|
|
59
73
|
headTextColor = "secondary-most",
|
|
60
|
-
size
|
|
74
|
+
size,
|
|
75
|
+
overflowVisible
|
|
61
76
|
}) => {
|
|
62
77
|
const portalRootElement = usePortalRootElement("modalsRoot");
|
|
63
78
|
const initialFocusRef = useRef(null);
|
|
@@ -85,18 +100,29 @@ export const Modal: FC<Props> = ({
|
|
|
85
100
|
}
|
|
86
101
|
};
|
|
87
102
|
|
|
103
|
+
const overflowAttribute = overflowVisible ? "visible" : "auto";
|
|
104
|
+
const borderBottomRadiusAttribute = overflowVisible && !footer ? "inherit" : "unset";
|
|
105
|
+
|
|
88
106
|
const modalElement = (
|
|
89
|
-
<
|
|
107
|
+
<DivWithOptionalOverflow
|
|
108
|
+
className={classNames("modal", className, isActive)}
|
|
109
|
+
ref={trapRef}
|
|
110
|
+
onKeyDown={onKeyDown}
|
|
111
|
+
overflow={overflowAttribute}
|
|
112
|
+
borderBottomRadius={borderBottomRadiusAttribute}
|
|
113
|
+
>
|
|
90
114
|
<div className="modal-background" onClick={closeFunction} />
|
|
91
|
-
<SizedModal className="modal-card" size={size}>
|
|
115
|
+
<SizedModal className="modal-card" size={size} overflow={overflowAttribute}>
|
|
92
116
|
<header className={classNames("modal-card-head", `has-background-${headColor}`)}>
|
|
93
117
|
<h2 className={`modal-card-title m-0 has-text-${headTextColor}`}>{title}</h2>
|
|
94
118
|
<button className="delete" aria-label="close" onClick={closeFunction} ref={initialFocusRef} autoFocus />
|
|
95
119
|
</header>
|
|
96
|
-
<
|
|
120
|
+
<SectionWithOptionalOverflow className="modal-card-body" overflow={overflowAttribute} borderBottomRadius={borderBottomRadiusAttribute}>
|
|
121
|
+
{body}
|
|
122
|
+
</SectionWithOptionalOverflow>
|
|
97
123
|
{showFooter}
|
|
98
124
|
</SizedModal>
|
|
99
|
-
</
|
|
125
|
+
</DivWithOptionalOverflow>
|
|
100
126
|
);
|
|
101
127
|
|
|
102
128
|
return ReactDOM.createPortal(modalElement, portalRootElement);
|