@eccenca/gui-elements 23.0.0-rc.6 → 23.0.0-rc.7
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/CHANGELOG.md +3 -1
- package/dist/cjs/cmem/markdown/Markdown.js +14 -2
- package/dist/cjs/cmem/markdown/Markdown.js.map +1 -1
- package/dist/cjs/cmem/react-flow/ReactFlow/ReactFlow.js +0 -4
- package/dist/cjs/cmem/react-flow/ReactFlow/ReactFlow.js.map +1 -1
- package/dist/cjs/components/Accordion/Accordion.js +7 -2
- package/dist/cjs/components/Accordion/Accordion.js.map +1 -1
- package/dist/cjs/components/Accordion/AccordionItem.js.map +1 -1
- package/dist/cjs/components/AutoSuggestion/AutoSuggestion.js +59 -33
- package/dist/cjs/components/AutoSuggestion/AutoSuggestion.js.map +1 -1
- package/dist/cjs/components/AutoSuggestion/AutoSuggestionList.js +10 -1
- package/dist/cjs/components/AutoSuggestion/AutoSuggestionList.js.map +1 -1
- package/dist/cjs/components/AutoSuggestion/SingleLineCodeEditor.js +10 -4
- package/dist/cjs/components/AutoSuggestion/SingleLineCodeEditor.js.map +1 -1
- package/dist/cjs/components/AutocompleteField/AutoCompleteField.js +13 -8
- package/dist/cjs/components/AutocompleteField/AutoCompleteField.js.map +1 -1
- package/dist/cjs/components/Button/Button.js.map +1 -1
- package/dist/cjs/components/Checkbox/Checkbox.js +1 -0
- package/dist/cjs/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/cjs/components/Form/FieldItem.js.map +1 -1
- package/dist/cjs/components/Menu/Menu.js +2 -2
- package/dist/cjs/components/Menu/Menu.js.map +1 -1
- package/dist/cjs/components/Menu/MenuDivider.js +2 -2
- package/dist/cjs/components/Menu/MenuDivider.js.map +1 -1
- package/dist/cjs/components/Menu/MenuItem.js +5 -3
- package/dist/cjs/components/Menu/MenuItem.js.map +1 -1
- package/dist/cjs/components/MultiSelect/MultiSelect.js +17 -4
- package/dist/cjs/components/MultiSelect/MultiSelect.js.map +1 -1
- package/dist/cjs/components/Pagination/Pagination.js.map +1 -1
- package/dist/cjs/components/RadioButton/RadioButton.js +1 -0
- package/dist/cjs/components/RadioButton/RadioButton.js.map +1 -1
- package/dist/cjs/components/Separation/Spacing.js +4 -1
- package/dist/cjs/components/Separation/Spacing.js.map +1 -1
- package/dist/cjs/components/Spinner/Spinner.js +3 -3
- package/dist/cjs/components/Spinner/Spinner.js.map +1 -1
- package/dist/cjs/components/Switch/Switch.js.map +1 -1
- package/dist/cjs/extensions/react-flow/edges/EdgeDefault.js.map +1 -1
- package/dist/esm/cmem/markdown/Markdown.js +13 -2
- package/dist/esm/cmem/markdown/Markdown.js.map +1 -1
- package/dist/esm/cmem/react-flow/ReactFlow/ReactFlow.js +0 -4
- package/dist/esm/cmem/react-flow/ReactFlow/ReactFlow.js.map +1 -1
- package/dist/esm/components/Accordion/Accordion.js +8 -3
- package/dist/esm/components/Accordion/Accordion.js.map +1 -1
- package/dist/esm/components/Accordion/AccordionItem.js +1 -1
- package/dist/esm/components/Accordion/AccordionItem.js.map +1 -1
- package/dist/esm/components/AutoSuggestion/AutoSuggestion.js +71 -45
- package/dist/esm/components/AutoSuggestion/AutoSuggestion.js.map +1 -1
- package/dist/esm/components/AutoSuggestion/AutoSuggestionList.js +11 -2
- package/dist/esm/components/AutoSuggestion/AutoSuggestionList.js.map +1 -1
- package/dist/esm/components/AutoSuggestion/SingleLineCodeEditor.js +11 -5
- package/dist/esm/components/AutoSuggestion/SingleLineCodeEditor.js.map +1 -1
- package/dist/esm/components/AutocompleteField/AutoCompleteField.js +19 -14
- package/dist/esm/components/AutocompleteField/AutoCompleteField.js.map +1 -1
- package/dist/esm/components/Button/Button.js.map +1 -1
- package/dist/esm/components/Checkbox/Checkbox.js +1 -0
- package/dist/esm/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/esm/components/Form/FieldItem.js.map +1 -1
- package/dist/esm/components/Menu/Menu.js +3 -3
- package/dist/esm/components/Menu/Menu.js.map +1 -1
- package/dist/esm/components/Menu/MenuDivider.js +3 -3
- package/dist/esm/components/Menu/MenuDivider.js.map +1 -1
- package/dist/esm/components/Menu/MenuItem.js +5 -3
- package/dist/esm/components/Menu/MenuItem.js.map +1 -1
- package/dist/esm/components/MultiSelect/MultiSelect.js +22 -9
- package/dist/esm/components/MultiSelect/MultiSelect.js.map +1 -1
- package/dist/esm/components/Pagination/Pagination.js +1 -1
- package/dist/esm/components/Pagination/Pagination.js.map +1 -1
- package/dist/esm/components/RadioButton/RadioButton.js +2 -1
- package/dist/esm/components/RadioButton/RadioButton.js.map +1 -1
- package/dist/esm/components/Separation/Spacing.js +4 -1
- package/dist/esm/components/Separation/Spacing.js.map +1 -1
- package/dist/esm/components/Spinner/Spinner.js +3 -4
- package/dist/esm/components/Spinner/Spinner.js.map +1 -1
- package/dist/esm/components/Switch/Switch.js +1 -1
- package/dist/esm/components/Switch/Switch.js.map +1 -1
- package/dist/esm/extensions/react-flow/edges/EdgeDefault.js.map +1 -1
- package/dist/types/cmem/markdown/Markdown.d.ts +3 -2
- package/dist/types/cmem/react-flow/ReactFlow/ReactFlow.d.ts +1 -1
- package/dist/types/components/Accordion/Accordion.d.ts +12 -1
- package/dist/types/components/Accordion/AccordionItem.d.ts +21 -6
- package/dist/types/components/AutoSuggestion/AutoSuggestionList.d.ts +4 -2
- package/dist/types/components/AutocompleteField/AutoCompleteField.d.ts +5 -0
- package/dist/types/components/Button/Button.d.ts +1 -1
- package/dist/types/components/Checkbox/Checkbox.d.ts +4 -1
- package/dist/types/components/Form/FieldItem.d.ts +32 -2
- package/dist/types/components/Menu/Menu.d.ts +4 -1
- package/dist/types/components/Menu/MenuDivider.d.ts +4 -1
- package/dist/types/components/Menu/MenuItem.d.ts +5 -2
- package/dist/types/components/Pagination/Pagination.d.ts +9 -5
- package/dist/types/components/RadioButton/RadioButton.d.ts +4 -1
- package/dist/types/components/Separation/Spacing.d.ts +17 -3
- package/dist/types/components/Spinner/Spinner.d.ts +38 -5
- package/dist/types/components/Switch/Switch.d.ts +6 -3
- package/dist/types/extensions/react-flow/edges/EdgeDefault.d.ts +15 -0
- package/package.json +4 -6
- package/src/cmem/markdown/Markdown.tsx +5 -4
- package/src/cmem/react-flow/ReactFlow/ReactFlow.stories.tsx +15 -86
- package/src/cmem/react-flow/ReactFlow/ReactFlow.tsx +1 -5
- package/src/components/Accordion/Accordion.tsx +33 -3
- package/src/components/Accordion/AccordionItem.tsx +23 -33
- package/src/components/Accordion/Stories/Accordion.stories.tsx +33 -0
- package/src/components/Accordion/Stories/AccordionItem.stories.tsx +27 -0
- package/src/components/Accordion/accordion.scss +20 -1
- package/src/components/AutoSuggestion/AutoSuggestion.tsx +73 -39
- package/src/components/AutoSuggestion/AutoSuggestionList.tsx +15 -2
- package/src/components/AutoSuggestion/SingleLineCodeEditor.tsx +17 -9
- package/src/components/AutoSuggestion/tests/AutoSuggestionList.test.tsx +9 -7
- package/src/components/AutocompleteField/AutoCompleteField.tsx +19 -6
- package/src/components/AutocompleteField/autoCompleteFieldUtils.tsx +1 -1
- package/src/components/AutocompleteField/stories/AutoCompleteField.stories.tsx +1 -1
- package/src/components/Button/Button.stories.tsx +1 -107
- package/src/components/Button/Button.tsx +2 -2
- package/src/components/Card/stories/Card.stories.tsx +2 -21
- package/src/components/Checkbox/Checkbox.tsx +9 -2
- package/src/components/Checkbox/Stories/Checkbox.stories.tsx +30 -0
- package/src/components/Checkbox/checkbox.scss +4 -0
- package/src/components/ContextOverlay/ContextMenu.stories.tsx +2 -2
- package/src/components/Dialog/stories/Modal.stories.tsx +1 -61
- package/src/components/Dialog/stories/SimpleDialog.stories.tsx +1 -2
- package/src/components/Form/FieldItem.tsx +32 -2
- package/src/components/Form/Stories/FieldItem.stories.tsx +27 -0
- package/src/components/Form/Stories/FieldItemRow.stories.tsx +31 -0
- package/src/components/Label/Label.stories.tsx +1 -1
- package/src/components/Menu/Menu.tsx +21 -3
- package/src/components/Menu/MenuDivider.tsx +20 -3
- package/src/components/Menu/MenuItem.tsx +13 -10
- package/src/components/Menu/Stories/Menu.stories.tsx +31 -0
- package/src/components/Menu/Stories/MenuItem.stories.tsx +25 -0
- package/src/components/MultiSelect/MultiSelect.stories.tsx +2 -21
- package/src/components/MultiSelect/MultiSelect.tsx +22 -5
- package/src/components/Notification/Notification.stories.tsx +1 -29
- package/src/components/Pagination/Pagination.tsx +13 -6
- package/src/components/Pagination/Stories/Pagination.stories.tsx +32 -0
- package/src/components/Pagination/pagination.scss +2 -2
- package/src/components/ProgressBar/Stories/ProgressBar.stories.tsx +25 -0
- package/src/components/RadioButton/RadioButton.tsx +9 -2
- package/src/components/RadioButton/Stories/RadioButton.stories.tsx +30 -0
- package/src/components/Select/Select.stories.tsx +1 -1
- package/src/components/Separation/Spacing.tsx +17 -4
- package/src/components/Separation/Stories/Spacing.stories.tsx +25 -0
- package/src/components/Spinner/Spinner.tsx +39 -7
- package/src/components/Spinner/Stories/spinner.stories.tsx +26 -0
- package/src/components/Switch/Stories/Switch.stories.tsx +27 -0
- package/src/components/Switch/Switch.tsx +9 -3
- package/src/components/Tabs/stories/Tab.stories.tsx +1 -32
- package/src/components/Tabs/stories/Tabs.stories.tsx +1 -39
- package/src/components/Tag/Tag.stories.tsx +1 -9
- package/src/components/TextField/stories/TextArea.stories.tsx +10 -25
- package/src/components/TextField/stories/TextField.stories.tsx +2 -73
- package/src/extensions/react-flow/edges/EdgeDefault.tsx +19 -0
- package/src/extensions/react-flow/edges/stories/EdgeDefault.stories.tsx +121 -0
- package/src/extensions/react-flow/nodes/stories/NodeContent.stories.tsx +1 -1
- package/dist/cjs/cmem/react-flow/configuration/customLabel.js +0 -13
- package/dist/cjs/cmem/react-flow/configuration/customLabel.js.map +0 -1
- package/dist/cjs/cmem/react-flow/configuration/inverseEdge.js +0 -13
- package/dist/cjs/cmem/react-flow/configuration/inverseEdge.js.map +0 -1
- package/dist/esm/cmem/react-flow/configuration/customLabel.js +0 -10
- package/dist/esm/cmem/react-flow/configuration/customLabel.js.map +0 -1
- package/dist/esm/cmem/react-flow/configuration/inverseEdge.js +0 -10
- package/dist/esm/cmem/react-flow/configuration/inverseEdge.js.map +0 -1
- package/dist/types/cmem/react-flow/configuration/customLabel.d.ts +0 -8
- package/dist/types/cmem/react-flow/configuration/inverseEdge.d.ts +0 -8
- package/src/cmem/react-flow/configuration/customLabel.ts +0 -11
- package/src/cmem/react-flow/configuration/inverseEdge.ts +0 -11
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, {useEffect, useMemo, useState} from "react";
|
|
2
|
-
import CodeMirror from "codemirror";
|
|
2
|
+
import CodeMirror, {Position} from "codemirror";
|
|
3
3
|
import {FieldItem, IconButton, Spinner, Toolbar, ToolbarSection, ContextOverlay} from "./../../";
|
|
4
4
|
import {Classes as BlueprintClassNames} from "@blueprintjs/core";
|
|
5
5
|
import { CLASSPREFIX as eccgui } from "../../configuration/constants";
|
|
@@ -111,6 +111,13 @@ export interface IProps {
|
|
|
111
111
|
validationRequestDelay?: number
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
// Meta data regarding a request
|
|
115
|
+
interface RequestMetaData {
|
|
116
|
+
requestId: string | undefined
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
type HorizontalShiftCallbackFunction = (shift: number) => any
|
|
120
|
+
|
|
114
121
|
/** Input component that allows partial, fine-grained auto-completion, i.e. of sub-strings of the input string.
|
|
115
122
|
* This is comparable to a one line code editor. */
|
|
116
123
|
const AutoSuggestion = ({
|
|
@@ -132,20 +139,22 @@ const AutoSuggestion = ({
|
|
|
132
139
|
autoCompletionRequestDelay = 1000,
|
|
133
140
|
validationRequestDelay = 200
|
|
134
141
|
}: IProps) => {
|
|
135
|
-
const
|
|
136
|
-
const
|
|
137
|
-
const
|
|
142
|
+
const value = React.useRef<string>(initialValue)
|
|
143
|
+
const cursorPosition = React.useRef(0);
|
|
144
|
+
const horizontalShiftSubscriber = React.useRef<HorizontalShiftCallbackFunction | undefined>(undefined)
|
|
138
145
|
const [shouldShowDropdown, setShouldShowDropdown] = React.useState(false);
|
|
139
146
|
const [suggestions, setSuggestions] = React.useState<ISuggestionWithReplacementInfo[]>([]);
|
|
140
147
|
const [suggestionsPending, setSuggestionsPending] = React.useState(false);
|
|
148
|
+
const suggestionRequestData = React.useRef<RequestMetaData>({requestId: undefined})
|
|
141
149
|
const [pathValidationPending, setPathValidationPending] = React.useState(false)
|
|
150
|
+
const validationRequestData = React.useRef<RequestMetaData>({requestId: undefined})
|
|
142
151
|
const [, setErrorMarkers] = React.useState<CodeMirror.TextMarker[]>([]);
|
|
143
152
|
const [validationResponse, setValidationResponse] = useState<IValidationResult | undefined>(undefined)
|
|
144
153
|
const [suggestionResponse, setSuggestionResponse] = useState<IPartialAutoCompleteResult | undefined>(undefined)
|
|
145
154
|
// The element that should be used for replacement highlighting
|
|
146
155
|
const [highlightedElement, setHighlightedElement] = useState<ISuggestionWithReplacementInfo | undefined>(undefined)
|
|
147
156
|
const [editorInstance, setEditorInstance] = React.useState<CodeMirror.Editor>();
|
|
148
|
-
const
|
|
157
|
+
const isFocused = React.useRef(false);
|
|
149
158
|
/** Mutable editor state, since this needs to be current in scope of the SingleLineEditorComponent. */
|
|
150
159
|
const [editorState] = React.useState<{
|
|
151
160
|
index: number,
|
|
@@ -155,7 +164,7 @@ const AutoSuggestion = ({
|
|
|
155
164
|
}>({index: 0, suggestions: [], dropdownShown: false})
|
|
156
165
|
/** This is for the AutoSuggestionList component in order to re-render. */
|
|
157
166
|
const [focusedIndex, setFocusedIndex] = React.useState(0)
|
|
158
|
-
const
|
|
167
|
+
const selectedTextRanges = React.useRef<IRange[]>([])
|
|
159
168
|
|
|
160
169
|
const pathIsValid = validationResponse?.valid ?? true;
|
|
161
170
|
|
|
@@ -170,8 +179,10 @@ const AutoSuggestion = ({
|
|
|
170
179
|
}, [editorInstance, editorState])
|
|
171
180
|
|
|
172
181
|
React.useEffect(() => {
|
|
173
|
-
|
|
174
|
-
|
|
182
|
+
if(initialValue != null) {
|
|
183
|
+
editorInstance?.setValue(initialValue)
|
|
184
|
+
}
|
|
185
|
+
}, [initialValue, editorInstance])
|
|
175
186
|
|
|
176
187
|
React.useEffect(() => {
|
|
177
188
|
editorState.dropdownShown = shouldShowDropdown
|
|
@@ -181,7 +192,7 @@ const AutoSuggestion = ({
|
|
|
181
192
|
useEffect(() => {
|
|
182
193
|
if (highlightedElement && editorInstance) {
|
|
183
194
|
const { from, length } = highlightedElement;
|
|
184
|
-
if(length > 0 && selectedTextRanges.length === 0) {
|
|
195
|
+
if(length > 0 && selectedTextRanges.current.length === 0) {
|
|
185
196
|
const to = from + length;
|
|
186
197
|
const marker = editorInstance.markText(
|
|
187
198
|
{line: 0, ch: from},
|
|
@@ -216,7 +227,8 @@ const AutoSuggestion = ({
|
|
|
216
227
|
return []
|
|
217
228
|
})
|
|
218
229
|
}
|
|
219
|
-
|
|
230
|
+
const isValid = validationResponse?.valid === undefined || validationResponse.valid
|
|
231
|
+
onInputChecked && onInputChecked(isValid)
|
|
220
232
|
}, [validationResponse?.valid, validationResponse?.parseError, editorInstance, onInputChecked]);
|
|
221
233
|
|
|
222
234
|
/** generate suggestions and also populate the replacement indexes dict */
|
|
@@ -245,9 +257,10 @@ const AutoSuggestion = ({
|
|
|
245
257
|
}, [suggestionResponse, editorState]);
|
|
246
258
|
|
|
247
259
|
const asyncCheckInput = useMemo(() => async (inputString: string) => {
|
|
248
|
-
if(!checkInput) {
|
|
260
|
+
if(!checkInput || inputString !== value.current || validationRequestData.current.requestId === inputString) {
|
|
249
261
|
return
|
|
250
262
|
}
|
|
263
|
+
validationRequestData.current.requestId = inputString
|
|
251
264
|
setPathValidationPending(true)
|
|
252
265
|
try {
|
|
253
266
|
const result: IValidationResult | undefined = await checkInput(inputString)
|
|
@@ -266,10 +279,17 @@ const AutoSuggestion = ({
|
|
|
266
279
|
)
|
|
267
280
|
|
|
268
281
|
const asyncHandleEditorInputChange = useMemo(() => async (inputString: string, cursorPosition: number) => {
|
|
282
|
+
const requestId = `${inputString} ${cursorPosition}`
|
|
283
|
+
if(requestId === suggestionRequestData.current.requestId) {
|
|
284
|
+
return
|
|
285
|
+
}
|
|
286
|
+
suggestionRequestData.current.requestId = requestId
|
|
269
287
|
setSuggestionsPending(true)
|
|
270
288
|
try {
|
|
271
289
|
const result: IPartialAutoCompleteResult | undefined = await fetchSuggestions(inputString, cursorPosition)
|
|
272
|
-
|
|
290
|
+
if(value.current === inputString) {
|
|
291
|
+
setSuggestionResponse(result)
|
|
292
|
+
}
|
|
273
293
|
} catch(e) {
|
|
274
294
|
setSuggestionResponse(undefined)
|
|
275
295
|
// TODO: Error handling
|
|
@@ -283,29 +303,24 @@ const AutoSuggestion = ({
|
|
|
283
303
|
[asyncHandleEditorInputChange, autoCompletionRequestDelay]
|
|
284
304
|
)
|
|
285
305
|
|
|
286
|
-
React.useEffect(() => {
|
|
287
|
-
if (isFocused) {
|
|
288
|
-
setShouldShowDropdown(true);
|
|
289
|
-
handleEditorInputChange(value, cursorPosition)
|
|
290
|
-
return handleEditorInputChange.cancel
|
|
291
|
-
}
|
|
292
|
-
return;
|
|
293
|
-
}, [cursorPosition, value, isFocused, handleEditorInputChange]);
|
|
294
|
-
|
|
295
|
-
// Trigger input validation
|
|
296
|
-
useEffect(() => {
|
|
297
|
-
checkValuePathValidity(value)
|
|
298
|
-
return checkValuePathValidity.cancel
|
|
299
|
-
}, [value, checkValuePathValidity])
|
|
300
|
-
|
|
301
306
|
const handleChange = (val: string) => {
|
|
302
|
-
|
|
307
|
+
value.current = val
|
|
308
|
+
checkValuePathValidity.cancel()
|
|
309
|
+
checkValuePathValidity(value.current)
|
|
303
310
|
onChange(val)
|
|
304
311
|
};
|
|
305
312
|
|
|
306
|
-
const handleCursorChange = (pos:
|
|
307
|
-
|
|
308
|
-
|
|
313
|
+
const handleCursorChange = (pos: Position, coords: any, scrollinfo: any) => {
|
|
314
|
+
cursorPosition.current = pos.ch;
|
|
315
|
+
// cursor change is fired after onChange, so we put the auto-complete logic here
|
|
316
|
+
if (isFocused.current) {
|
|
317
|
+
setShouldShowDropdown(true);
|
|
318
|
+
handleEditorInputChange.cancel()
|
|
319
|
+
handleEditorInputChange(value.current, cursorPosition.current)
|
|
320
|
+
}
|
|
321
|
+
horizontalShiftSubscriber.current && horizontalShiftSubscriber.current(
|
|
322
|
+
Math.min(coords.left, Math.max(coords.left - scrollinfo.left, 0))
|
|
323
|
+
)
|
|
309
324
|
};
|
|
310
325
|
|
|
311
326
|
const handleInputEditorKeyPress = (event: KeyboardEvent) => {
|
|
@@ -333,15 +348,26 @@ const AutoSuggestion = ({
|
|
|
333
348
|
};
|
|
334
349
|
|
|
335
350
|
const handleInputEditorClear = () => {
|
|
336
|
-
|
|
337
|
-
|
|
351
|
+
editorInstance?.setValue("")
|
|
352
|
+
cursorPosition.current = 0
|
|
353
|
+
handleChange("")
|
|
338
354
|
editorInstance?.focus();
|
|
339
355
|
};
|
|
340
356
|
|
|
341
357
|
const handleInputFocus = (focusState: boolean) => {
|
|
342
358
|
onFocusChange && onFocusChange(focusState)
|
|
343
|
-
setIsFocused(focusState)
|
|
344
359
|
focusState ? setShouldShowDropdown(true) : closeDropDown()
|
|
360
|
+
if(!isFocused.current && focusState) {
|
|
361
|
+
// Just got focus
|
|
362
|
+
// Clear suggestions and repeat suggestion request, something else might have changed while this component was not focused
|
|
363
|
+
setSuggestions([])
|
|
364
|
+
suggestionRequestData.current.requestId = undefined
|
|
365
|
+
isFocused.current = focusState
|
|
366
|
+
handleEditorInputChange.cancel()
|
|
367
|
+
handleEditorInputChange(value.current, cursorPosition.current)
|
|
368
|
+
} else {
|
|
369
|
+
isFocused.current = focusState
|
|
370
|
+
}
|
|
345
371
|
};
|
|
346
372
|
|
|
347
373
|
//keyboard handlers
|
|
@@ -390,7 +416,15 @@ const AutoSuggestion = ({
|
|
|
390
416
|
setHighlightedElement(item)
|
|
391
417
|
}, [])
|
|
392
418
|
|
|
393
|
-
const
|
|
419
|
+
const onSelection = React.useMemo(() => (ranges: IRange[]) => {
|
|
420
|
+
selectedTextRanges.current = ranges
|
|
421
|
+
}, [])
|
|
422
|
+
|
|
423
|
+
const subscribeToHorizontalShift = React.useMemo(() => (callback: HorizontalShiftCallbackFunction) => {
|
|
424
|
+
horizontalShiftSubscriber.current = callback
|
|
425
|
+
}, [])
|
|
426
|
+
|
|
427
|
+
const hasError = !!value.current && !pathIsValid && !pathValidationPending;
|
|
394
428
|
const autoSuggestionInput = (
|
|
395
429
|
<div id={id} className={`${eccgui}-autosuggestion`}>
|
|
396
430
|
<div className={`${eccgui}-autosuggestion__inputfield ${BlueprintClassNames.INPUT_GROUP} ${BlueprintClassNames.FILL} ${hasError ? BlueprintClassNames.INTENT_DANGER : ""}`}>
|
|
@@ -404,7 +438,7 @@ const AutoSuggestion = ({
|
|
|
404
438
|
content={(
|
|
405
439
|
<AutoSuggestionList
|
|
406
440
|
id={id+"__dropdown"}
|
|
407
|
-
|
|
441
|
+
registerForHorizontalShift={subscribeToHorizontalShift}
|
|
408
442
|
loading={suggestionsPending}
|
|
409
443
|
options={suggestions}
|
|
410
444
|
isOpen={!suggestionsPending && shouldShowDropdown}
|
|
@@ -419,16 +453,16 @@ const AutoSuggestion = ({
|
|
|
419
453
|
setEditorInstance={setEditorInstance}
|
|
420
454
|
onChange={handleChange}
|
|
421
455
|
onCursorChange={handleCursorChange}
|
|
422
|
-
initialValue={
|
|
456
|
+
initialValue={initialValue}
|
|
423
457
|
onFocusChange={handleInputFocus}
|
|
424
458
|
onKeyDown={handleInputEditorKeyPress}
|
|
425
459
|
enableTab={useTabForCompletions}
|
|
426
460
|
placeholder={placeholder}
|
|
427
|
-
onSelection={
|
|
461
|
+
onSelection={onSelection}
|
|
428
462
|
showScrollBar={showScrollBar}
|
|
429
463
|
/>
|
|
430
464
|
</ContextOverlay>
|
|
431
|
-
{!!value && (
|
|
465
|
+
{!!value.current && (
|
|
432
466
|
<span className={BlueprintClassNames.INPUT_ACTION}>
|
|
433
467
|
<IconButton
|
|
434
468
|
data-test-id={"value-path-clear-btn"}
|
|
@@ -24,13 +24,16 @@ export interface IDropdownProps extends Omit<React.HTMLAttributes<HTMLDivElement
|
|
|
24
24
|
isOpen: boolean;
|
|
25
25
|
// If the drop down should show a loading state
|
|
26
26
|
loading?: boolean;
|
|
27
|
-
|
|
27
|
+
// Register for changes in horizontal shift
|
|
28
|
+
registerForHorizontalShift?: (callback: HorizontalShiftCallbackFunction) => any
|
|
28
29
|
// The item from the drop down that is active
|
|
29
30
|
currentlyFocusedIndex: number;
|
|
30
31
|
// Callback indicating what item should currently being highlighted, i.e. is either active or is hovered over
|
|
31
32
|
itemToHighlight: (item: ISuggestionWithReplacementInfo | undefined) => any;
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
type HorizontalShiftCallbackFunction = (shift: number) => any
|
|
36
|
+
|
|
34
37
|
const ListItem = ({ item }: any, ref: any) => {
|
|
35
38
|
const listItem = (
|
|
36
39
|
<OverviewItem densityHigh={true}>
|
|
@@ -76,7 +79,7 @@ export const AutoSuggestionList = ({
|
|
|
76
79
|
options,
|
|
77
80
|
loading,
|
|
78
81
|
onItemSelectionChange,
|
|
79
|
-
|
|
82
|
+
registerForHorizontalShift,
|
|
80
83
|
currentlyFocusedIndex,
|
|
81
84
|
itemToHighlight,
|
|
82
85
|
style,
|
|
@@ -85,6 +88,7 @@ export const AutoSuggestionList = ({
|
|
|
85
88
|
const [hoveredItem, setHoveredItem] = React.useState<
|
|
86
89
|
ISuggestionWithReplacementInfo | undefined
|
|
87
90
|
>(undefined);
|
|
91
|
+
const [left, setLeft] = React.useState(0)
|
|
88
92
|
// Refs of list items
|
|
89
93
|
const [refs] = React.useState<React.RefObject<Element>[]>([])
|
|
90
94
|
const dropdownRef = React.useRef<HTMLDivElement>(null);
|
|
@@ -95,6 +99,15 @@ export const AutoSuggestionList = ({
|
|
|
95
99
|
return refs[index];
|
|
96
100
|
};
|
|
97
101
|
|
|
102
|
+
React.useEffect(() => {
|
|
103
|
+
if(registerForHorizontalShift) {
|
|
104
|
+
const callback = (shift: number) => {
|
|
105
|
+
setTimeout(() => setLeft(shift), 1)
|
|
106
|
+
}
|
|
107
|
+
registerForHorizontalShift(callback)
|
|
108
|
+
}
|
|
109
|
+
}, [registerForHorizontalShift])
|
|
110
|
+
|
|
98
111
|
React.useEffect(() => {
|
|
99
112
|
const listIndexNode = refs[currentlyFocusedIndex];
|
|
100
113
|
if (dropdownRef?.current && listIndexNode?.current) {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import "codemirror/addon/display/placeholder.js"
|
|
2
2
|
import "codemirror/mode/sparql/sparql.js";
|
|
3
3
|
import React from "react";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import {UnControlled as UnControlledEditor} from "react-codemirror2";
|
|
5
|
+
import {Classes as BlueprintClassNames} from "@blueprintjs/core";
|
|
6
6
|
import {Editor as CodeMirrorEditor} from "codemirror";
|
|
7
|
-
import {
|
|
7
|
+
import {CLASSPREFIX as eccgui} from "../../configuration/constants";
|
|
8
8
|
|
|
9
9
|
export interface IEditorProps {
|
|
10
10
|
// Is called with the editor instance that allows access via the CodeMirror API
|
|
@@ -51,9 +51,9 @@ const SingleLineCodeEditor = ({
|
|
|
51
51
|
}: IEditorProps) => {
|
|
52
52
|
return (
|
|
53
53
|
<div className={`${eccgui}-singlelinecodeeditor ${BlueprintClassNames.INPUT}`}>
|
|
54
|
-
<
|
|
55
|
-
editorDidMount={(editor) => {
|
|
56
|
-
editor.on("beforeChange", (_, change) => {
|
|
54
|
+
<UnControlledEditor
|
|
55
|
+
editorDidMount={(editor: any) => {
|
|
56
|
+
editor.on("beforeChange", (_: any, change: any) => {
|
|
57
57
|
// Prevent the user from entering new-line characters, since this is supposed to be a one-line editor.
|
|
58
58
|
const newText = change.text.join("").replace(/\n/g, "");
|
|
59
59
|
//failing unexpectedly during undo and redo
|
|
@@ -89,10 +89,18 @@ const SingleLineCodeEditor = ({
|
|
|
89
89
|
editor.getScrollInfo()
|
|
90
90
|
);
|
|
91
91
|
}}
|
|
92
|
-
onBeforeChange={(_editor, _data, value) => {
|
|
93
|
-
|
|
94
|
-
|
|
92
|
+
onBeforeChange={(_editor, _data, value, next) => {
|
|
93
|
+
// Remove entered new lines
|
|
94
|
+
const trimmedValue = value.replace(/[\r\n]/g, "");
|
|
95
|
+
if (trimmedValue !== value) {
|
|
96
|
+
_editor.setValue(trimmedValue)
|
|
97
|
+
}
|
|
98
|
+
next()
|
|
95
99
|
}}
|
|
100
|
+
onChange={(_editor, _data, value) => {
|
|
101
|
+
onChange(value);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
96
104
|
onKeyDown={(_, event) => onKeyDown(event)}
|
|
97
105
|
/>
|
|
98
106
|
</div>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import '@testing-library/jest-dom'
|
|
3
|
-
import {fireEvent, render} from '@testing-library/react'
|
|
3
|
+
import {fireEvent, render, waitFor} from '@testing-library/react'
|
|
4
4
|
import {CLASSPREFIX as eccgui} from "../../../configuration/constants";
|
|
5
5
|
import {AutoSuggestionList, IDropdownProps} from '../AutoSuggestionList'
|
|
6
6
|
|
|
@@ -10,7 +10,6 @@ describe("Dropdown list", () => {
|
|
|
10
10
|
props = {
|
|
11
11
|
currentlyFocusedIndex: 0,
|
|
12
12
|
loading: false,
|
|
13
|
-
left:0,
|
|
14
13
|
isOpen: false,
|
|
15
14
|
options: [],
|
|
16
15
|
itemToHighlight: () => {},
|
|
@@ -62,18 +61,21 @@ describe("Dropdown list", () => {
|
|
|
62
61
|
expect(dropdownItems.length).toBe(2)
|
|
63
62
|
})
|
|
64
63
|
|
|
65
|
-
it("should move horizontally for every cursor movement", () => {
|
|
64
|
+
it("should move horizontally for every cursor movement", async () => {
|
|
65
|
+
const offset = 10
|
|
66
66
|
props = {
|
|
67
67
|
...props,
|
|
68
68
|
options: mockOptions,
|
|
69
69
|
loading: false,
|
|
70
70
|
isOpen: true,
|
|
71
|
-
|
|
71
|
+
registerForHorizontalShift: (callback => callback(offset)),
|
|
72
72
|
}
|
|
73
73
|
const {container} = render(<AutoSuggestionList {...props} />)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
await waitFor(() => {
|
|
75
|
+
const parentDiv:HTMLElement = container.querySelector(`.${eccgui}-autosuggestion__dropdown`)!!
|
|
76
|
+
const leftOffset = Number(parentDiv.style.left.replace(/px$/,""));
|
|
77
|
+
expect(leftOffset).toBe(offset)
|
|
78
|
+
})
|
|
77
79
|
})
|
|
78
80
|
|
|
79
81
|
it("should have one active item at a time", () => {
|
|
@@ -143,6 +143,12 @@ export interface IAutoCompleteFieldProps<T extends any, UPDATE_VALUE extends any
|
|
|
143
143
|
|
|
144
144
|
/** If an error occurs during the auto-completion request, the error details will be prefixed with this string. */
|
|
145
145
|
requestErrorPrefix?: string
|
|
146
|
+
|
|
147
|
+
/** Creates a backdrop when the popover is shown that captures outside clicks in order to close the popover.
|
|
148
|
+
* This is needed if other components on the same page are swallowing events, e.g. the react-flow canvas.
|
|
149
|
+
* hasBackDrop should then be set to true in these cases otherwise the popover won't close when clicking those other components.
|
|
150
|
+
**/
|
|
151
|
+
hasBackDrop?: boolean
|
|
146
152
|
}
|
|
147
153
|
|
|
148
154
|
AutoCompleteField.defaultProps = {
|
|
@@ -181,6 +187,7 @@ export function AutoCompleteField<T extends any, UPDATE_VALUE extends any>(props
|
|
|
181
187
|
resetQueryToValue,
|
|
182
188
|
itemValueString,
|
|
183
189
|
requestErrorPrefix = "",
|
|
190
|
+
hasBackDrop = false,
|
|
184
191
|
...otherProps
|
|
185
192
|
} = props;
|
|
186
193
|
const [selectedItem, setSelectedItem] = useState<T | undefined>(initialValue);
|
|
@@ -188,7 +195,8 @@ export function AutoCompleteField<T extends any, UPDATE_VALUE extends any>(props
|
|
|
188
195
|
const [listLoading, setListLoading] = useState<boolean>(false);
|
|
189
196
|
|
|
190
197
|
const [query, setQuery] = useState<string>("");
|
|
191
|
-
|
|
198
|
+
// If the input field has focus
|
|
199
|
+
const [inputHasFocus, setInputHasFocus] = useState<boolean>(false);
|
|
192
200
|
const [highlightingEnabled, setHighlightingEnabled] = useState<boolean>(true);
|
|
193
201
|
const [requestError, setRequestError] = useState<string | undefined>(undefined)
|
|
194
202
|
|
|
@@ -226,7 +234,7 @@ export function AutoCompleteField<T extends any, UPDATE_VALUE extends any>(props
|
|
|
226
234
|
);
|
|
227
235
|
|
|
228
236
|
useEffect(() => {
|
|
229
|
-
if (!disabled && !readOnly &&
|
|
237
|
+
if (!disabled && !readOnly && inputHasFocus) {
|
|
230
238
|
setListLoading(true);
|
|
231
239
|
const timeout: number = window.setTimeout(async () => {
|
|
232
240
|
fetchQueryResults(query);
|
|
@@ -239,18 +247,18 @@ export function AutoCompleteField<T extends any, UPDATE_VALUE extends any>(props
|
|
|
239
247
|
return;
|
|
240
248
|
},
|
|
241
249
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
242
|
-
[
|
|
250
|
+
[inputHasFocus, query]
|
|
243
251
|
);
|
|
244
252
|
|
|
245
253
|
const fieldWidthLimits = elementWidth(fieldRef);
|
|
246
254
|
|
|
247
255
|
// We need to fire some actions when the auto-complete widget gets or loses focus
|
|
248
256
|
const handleOnFocusIn = () => {
|
|
249
|
-
|
|
257
|
+
setInputHasFocus(true);
|
|
250
258
|
};
|
|
251
259
|
|
|
252
260
|
const handleOnFocusOut = () => {
|
|
253
|
-
|
|
261
|
+
setInputHasFocus(false);
|
|
254
262
|
};
|
|
255
263
|
|
|
256
264
|
// On popover close reset query to selected item
|
|
@@ -384,6 +392,8 @@ export function AutoCompleteField<T extends any, UPDATE_VALUE extends any>(props
|
|
|
384
392
|
onClosed: onPopoverClose,
|
|
385
393
|
...otherProps.contextOverlayProps,
|
|
386
394
|
...preventOverlayOnReadonly,
|
|
395
|
+
// Needed to capture clicks outside of the popover, e.g. in order to close it.
|
|
396
|
+
hasBackdrop: hasBackDrop
|
|
387
397
|
}
|
|
388
398
|
if(selectedItem !== undefined) {
|
|
389
399
|
// Makes sure that even when an empty string is selected, the placeholder won't be shown.
|
|
@@ -409,7 +419,10 @@ export function AutoCompleteField<T extends any, UPDATE_VALUE extends any>(props
|
|
|
409
419
|
className={`${eccgui}-autocompletefield__input`}
|
|
410
420
|
disabled={disabled}
|
|
411
421
|
// Need to display error messages in list
|
|
412
|
-
items={requestError ?
|
|
422
|
+
items={requestError ?
|
|
423
|
+
[requestError as T] :
|
|
424
|
+
filtered
|
|
425
|
+
}
|
|
413
426
|
initialContent={onlyDropdownWithQuery ? null : undefined}
|
|
414
427
|
inputValueRenderer={selectedItem !== undefined ? itemValueRenderer : () => ""}
|
|
415
428
|
itemRenderer={requestError ? requestErrorRenderer : optionRenderer}
|
|
@@ -17,7 +17,7 @@ export const createNewItemRendererFactory = (
|
|
|
17
17
|
let textElement = itemTextRenderer(query, modifiers.styleWidth)
|
|
18
18
|
if(typeof textElement === "string") {
|
|
19
19
|
textElement = <OverflowText style={modifiers.styleWidth}>
|
|
20
|
-
{`Create option '${query}'`}
|
|
20
|
+
{textElement.trim() !== "" ? textElement : `Create option '${query}'`}
|
|
21
21
|
</OverflowText>
|
|
22
22
|
}
|
|
23
23
|
return (
|
|
@@ -6,7 +6,7 @@ import {extractSearchWords, matchesAllWords} from "../../Typography/Highlighter"
|
|
|
6
6
|
import {createNewItemRendererFactory} from "../autoCompleteFieldUtils";
|
|
7
7
|
|
|
8
8
|
const AutoCompleteFieldStory: ComponentMeta<typeof AutoCompleteField> = {
|
|
9
|
-
title: "
|
|
9
|
+
title: "Forms/AutoCompleteField",
|
|
10
10
|
component: AutoCompleteField,
|
|
11
11
|
argTypes: {
|
|
12
12
|
},
|
|
@@ -1,125 +1,19 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { ComponentStory, ComponentMeta } from "@storybook/react";
|
|
3
|
-
|
|
4
|
-
import Button from "./Button";
|
|
5
|
-
import Icon from "../Icon/Icon";
|
|
6
|
-
import Spacing from "../Separation/Spacing";
|
|
3
|
+
import { Button, Icon, Spacing} from "../../../index";
|
|
7
4
|
|
|
8
5
|
export default {
|
|
9
6
|
title: "Components/Button",
|
|
10
7
|
component: Button,
|
|
11
8
|
argTypes: {
|
|
12
|
-
active: {
|
|
13
|
-
description: "Button will display in an active state.",
|
|
14
|
-
control: "boolean",
|
|
15
|
-
table: {
|
|
16
|
-
defaultValue: { summary: false },
|
|
17
|
-
type: { summary: "boolean" },
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
className: {
|
|
21
|
-
description: "A space-delimited list of class names.",
|
|
22
|
-
control: "text",
|
|
23
|
-
table: {
|
|
24
|
-
defaultValue: { summary: undefined },
|
|
25
|
-
type: { summary: "string" },
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
disabled: {
|
|
29
|
-
description: "Whether this action is non-interactive and the button is not usable.",
|
|
30
|
-
control: "boolean",
|
|
31
|
-
table: {
|
|
32
|
-
defaultValue: { summary: false },
|
|
33
|
-
type: { summary: "boolean" },
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
minimal: {
|
|
37
|
-
description: "Whether this button should use minimal styles.",
|
|
38
|
-
control: "boolean",
|
|
39
|
-
table: {
|
|
40
|
-
defaultValue: { summary: false },
|
|
41
|
-
type: { summary: "boolean" },
|
|
42
|
-
}
|
|
43
|
-
},
|
|
44
|
-
outlined: {
|
|
45
|
-
description: "Whether this button should use outlined styles.",
|
|
46
|
-
control: "boolean",
|
|
47
|
-
table: {
|
|
48
|
-
defaultValue: { summary: false },
|
|
49
|
-
type: { summary: "boolean" },
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
text: {
|
|
53
|
-
description: "Action text. Can be any single React renderable. Can be used as alternative to include `children` elements.",
|
|
54
|
-
control: "text",
|
|
55
|
-
table: {
|
|
56
|
-
defaultValue: { summary: undefined },
|
|
57
|
-
type: { summary: "React.ReactNode" },
|
|
58
|
-
}
|
|
59
|
-
},
|
|
60
|
-
type: {
|
|
61
|
-
description: "HTML type attribute of button. Note that this prop has no effect on buttons with `href` property set.",
|
|
62
|
-
control: "text",
|
|
63
|
-
table: {
|
|
64
|
-
defaultValue: { summary: "button" },
|
|
65
|
-
type: { summary: "button | reset | submit" },
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
loading: {
|
|
69
|
-
description: "Button is displayed disabled and contains a spinner instead of its contents.",
|
|
70
|
-
control: "boolean",
|
|
71
|
-
table: {
|
|
72
|
-
defaultValue: { summary: false },
|
|
73
|
-
type: { summary: "boolean" },
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
|
-
fill: {
|
|
77
|
-
description: "Whether this button should expand to fill its container.",
|
|
78
|
-
control: "boolean",
|
|
79
|
-
table: {
|
|
80
|
-
defaultValue: { summary: false },
|
|
81
|
-
type: { summary: "boolean" },
|
|
82
|
-
}
|
|
83
|
-
},
|
|
84
|
-
large: {
|
|
85
|
-
description: "Whether this button should use large styles.",
|
|
86
|
-
control: "boolean",
|
|
87
|
-
table: {
|
|
88
|
-
defaultValue: { summary: false },
|
|
89
|
-
type: { summary: "boolean" },
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
small: {
|
|
93
|
-
description: "Whether this button should use small styles",
|
|
94
|
-
control: "boolean",
|
|
95
|
-
table: {
|
|
96
|
-
defaultValue: { summary: false },
|
|
97
|
-
type: { summary: "boolean" },
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
9
|
icon: {
|
|
101
|
-
description: "Left aligned icon, can be a canonical icon name or an `Icon` element.",
|
|
102
10
|
control: { disable: true, },
|
|
103
|
-
table: {
|
|
104
|
-
defaultValue: { summary: undefined },
|
|
105
|
-
type: { summary: "Icon | string" },
|
|
106
|
-
}
|
|
107
11
|
},
|
|
108
12
|
rightIcon: {
|
|
109
|
-
description: "Right aligned icon, can be a canonical icon name or an `Icon` element.",
|
|
110
13
|
control: { disable: true, },
|
|
111
|
-
table: {
|
|
112
|
-
defaultValue: { summary: undefined },
|
|
113
|
-
type: { summary: "Icon | string" },
|
|
114
|
-
}
|
|
115
14
|
},
|
|
116
15
|
onClick: {
|
|
117
|
-
description: "Click event handler.",
|
|
118
16
|
action: "clicked",
|
|
119
|
-
table: {
|
|
120
|
-
defaultValue: { summary: undefined },
|
|
121
|
-
type: { summary: "(event: MouseEvent<HTMLElement>) => void" },
|
|
122
|
-
}
|
|
123
17
|
},
|
|
124
18
|
},
|
|
125
19
|
} as ComponentMeta<typeof Button>;
|
|
@@ -13,7 +13,7 @@ import {ValidIconName} from "../Icon/canonicalIconNames";
|
|
|
13
13
|
|
|
14
14
|
export type AnchorOrButtonProps = Omit<BlueprintButtonProps, "elementRef" | "icon" | "rightIcon"> | Omit<BlueprintAnchorButtonProps, "elementRef" | "icon" | "rightIcon">;
|
|
15
15
|
|
|
16
|
-
export interface ButtonProps extends React.HTMLAttributes<
|
|
16
|
+
export interface ButtonProps extends React.HTMLAttributes<HTMLButtonElement | HTMLAnchorElement> {
|
|
17
17
|
/**
|
|
18
18
|
* Always use this when the button triggers an affirmative action, e.g. confirm a process.
|
|
19
19
|
* The button is displayed with primary color scheme.
|
|
@@ -100,7 +100,7 @@ function Button({
|
|
|
100
100
|
break;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
let ButtonType = restProps.href ? BlueprintAnchorButton : BlueprintButton;
|
|
103
|
+
let ButtonType: any = restProps.href ? BlueprintAnchorButton : BlueprintButton;
|
|
104
104
|
|
|
105
105
|
const button = (
|
|
106
106
|
<ButtonType
|
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
CardTitle,
|
|
9
9
|
CardOptions,
|
|
10
10
|
CardActions,
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
Divider,
|
|
12
|
+
} from "../../../../index";
|
|
13
13
|
|
|
14
14
|
import { Default as CardHeaderExample } from "./CardHeader.stories";
|
|
15
15
|
import { Default as CardContentExample } from "./CardContent.stories";
|
|
@@ -29,28 +29,9 @@ export default {
|
|
|
29
29
|
argTypes: {
|
|
30
30
|
elevation: {
|
|
31
31
|
control: { type: "number", min: 0, max: 4 },
|
|
32
|
-
description: "Intensity of the drop shadow beneath the card. At elevation 0, no drop shadow is applied.",
|
|
33
|
-
table: {
|
|
34
|
-
type: { summary: "number: 0 to 5" },
|
|
35
|
-
defaultValue: { summary: 1 },
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
interactive: {
|
|
39
|
-
control: "boolean",
|
|
40
|
-
description: "Card responds to user interactions, hovering over the card will increase the card's elevation and change the mouse cursor to a pointer. Is set automatically to `true` if an `onClick` handler is available.",
|
|
41
|
-
table: {
|
|
42
|
-
type: { summary: "boolean" },
|
|
43
|
-
defaultValue: { summary: false },
|
|
44
|
-
}
|
|
45
32
|
},
|
|
46
33
|
onClick: {
|
|
47
34
|
...helpersArgTypes.handlerOnClick,
|
|
48
|
-
description: "Callback invoked when the card is clicked.",
|
|
49
|
-
defaultValue: null,
|
|
50
|
-
table: {
|
|
51
|
-
type: { summary: "(e: MouseEvent<HTMLDivElement>) => void" },
|
|
52
|
-
defaultValue: { summary: undefined },
|
|
53
|
-
}
|
|
54
35
|
},
|
|
55
36
|
children: {
|
|
56
37
|
control: "none",
|