mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Compare commits
5 Commits
v5.0.130
...
fix/depend
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a4cd9b6069 | ||
![]() |
3ad7585f92 | ||
![]() |
acb69c447d | ||
![]() |
fa928b35cb | ||
![]() |
67810b79ce |
@@ -58,7 +58,7 @@ describe('gdjs.TextInputRuntimeObject (using a PixiJS RuntimeGame with DOM eleme
|
||||
});
|
||||
};
|
||||
|
||||
it('creates the DOM element', async () => {
|
||||
const setupObjectAndGetDomElementContainer = async () => {
|
||||
const runtimeGame = await gdjs.getPixiRuntimeGameWithAssets();
|
||||
const runtimeScene = new gdjs.RuntimeScene(runtimeGame);
|
||||
loadScene(runtimeScene);
|
||||
@@ -70,10 +70,6 @@ describe('gdjs.TextInputRuntimeObject (using a PixiJS RuntimeGame with DOM eleme
|
||||
const object = makeTextInputRuntimeObject(runtimeScene);
|
||||
runtimeScene.addObject(object);
|
||||
|
||||
// Check the default size.
|
||||
expect(object.getWidth()).to.be(300);
|
||||
expect(object.getHeight()).to.be(30);
|
||||
|
||||
// Check that the DOM element was created
|
||||
const gameDomElementContainer = runtimeGame
|
||||
.getRenderer()
|
||||
@@ -83,6 +79,20 @@ describe('gdjs.TextInputRuntimeObject (using a PixiJS RuntimeGame with DOM eleme
|
||||
'Expected getDomElementContainer to return a valid container.'
|
||||
);
|
||||
|
||||
return { runtimeScene, gameDomElementContainer, object };
|
||||
};
|
||||
|
||||
it('creates the DOM element', async () => {
|
||||
const {
|
||||
runtimeScene,
|
||||
gameDomElementContainer,
|
||||
object,
|
||||
} = await setupObjectAndGetDomElementContainer();
|
||||
|
||||
// Check the default size.
|
||||
expect(object.getWidth()).to.be(300);
|
||||
expect(object.getHeight()).to.be(30);
|
||||
|
||||
expect(gameDomElementContainer.hasChildNodes()).to.be(true);
|
||||
|
||||
const inputElement = gameDomElementContainer.querySelector('input');
|
||||
@@ -98,25 +108,11 @@ describe('gdjs.TextInputRuntimeObject (using a PixiJS RuntimeGame with DOM eleme
|
||||
});
|
||||
|
||||
it('destroys the DOM element when the scene is paused/resumed/stopped', async () => {
|
||||
const runtimeGame = await gdjs.getPixiRuntimeGameWithAssets();
|
||||
const runtimeScene = new gdjs.RuntimeScene(runtimeGame);
|
||||
loadScene(runtimeScene);
|
||||
|
||||
// Make sure the renderer is created (to test the real DOM element creation/update)
|
||||
const gameContainer = document.createElement('div');
|
||||
runtimeGame.getRenderer().createStandardCanvas(gameContainer);
|
||||
|
||||
const object = makeTextInputRuntimeObject(runtimeScene);
|
||||
runtimeScene.addObject(object);
|
||||
|
||||
// Check that the DOM element was created
|
||||
const gameDomElementContainer = runtimeGame
|
||||
.getRenderer()
|
||||
.getDomElementContainer();
|
||||
if (!gameDomElementContainer)
|
||||
throw new Error(
|
||||
'Expected getDomElementContainer to return a valid container.'
|
||||
);
|
||||
const {
|
||||
runtimeScene,
|
||||
gameDomElementContainer,
|
||||
object,
|
||||
} = await setupObjectAndGetDomElementContainer();
|
||||
|
||||
expect(gameDomElementContainer.querySelector('input')).not.to.be(null);
|
||||
|
||||
@@ -129,28 +125,17 @@ describe('gdjs.TextInputRuntimeObject (using a PixiJS RuntimeGame with DOM eleme
|
||||
|
||||
runtimeScene.unloadScene();
|
||||
expect(gameDomElementContainer.querySelector('input')).to.be(null);
|
||||
|
||||
// Clean up - not mandatory but to avoid overloading the testing browser.
|
||||
runtimeScene.unloadScene();
|
||||
});
|
||||
|
||||
it('changes the DOM element when the object type is updated', async () => {
|
||||
const runtimeGame = await gdjs.getPixiRuntimeGameWithAssets();
|
||||
const runtimeScene = new gdjs.RuntimeScene(runtimeGame);
|
||||
loadScene(runtimeScene);
|
||||
|
||||
// Make sure the renderer is created (to test the real DOM element creation/update)
|
||||
const gameContainer = document.createElement('div');
|
||||
runtimeGame.getRenderer().createStandardCanvas(gameContainer);
|
||||
|
||||
const object = makeTextInputRuntimeObject(runtimeScene);
|
||||
runtimeScene.addObject(object);
|
||||
|
||||
// Check that the DOM element was created
|
||||
const gameDomElementContainer = runtimeGame
|
||||
.getRenderer()
|
||||
.getDomElementContainer();
|
||||
if (!gameDomElementContainer)
|
||||
throw new Error(
|
||||
'Expected getDomElementContainer to return a valid container.'
|
||||
);
|
||||
const {
|
||||
runtimeScene,
|
||||
gameDomElementContainer,
|
||||
object,
|
||||
} = await setupObjectAndGetDomElementContainer();
|
||||
|
||||
expect(gameDomElementContainer.querySelector('input')).not.to.be(null);
|
||||
|
||||
@@ -171,25 +156,11 @@ describe('gdjs.TextInputRuntimeObject (using a PixiJS RuntimeGame with DOM eleme
|
||||
});
|
||||
|
||||
it('hides the DOM element when the object or layer is hidden', async () => {
|
||||
const runtimeGame = await gdjs.getPixiRuntimeGameWithAssets();
|
||||
const runtimeScene = new gdjs.RuntimeScene(runtimeGame);
|
||||
loadScene(runtimeScene);
|
||||
|
||||
// Make sure the renderer is created (to test the real DOM element creation/update)
|
||||
const gameContainer = document.createElement('div');
|
||||
runtimeGame.getRenderer().createStandardCanvas(gameContainer);
|
||||
|
||||
const object = makeTextInputRuntimeObject(runtimeScene);
|
||||
runtimeScene.addObject(object);
|
||||
|
||||
// Check that the DOM element was created
|
||||
const gameDomElementContainer = runtimeGame
|
||||
.getRenderer()
|
||||
.getDomElementContainer();
|
||||
if (!gameDomElementContainer)
|
||||
throw new Error(
|
||||
'Expected getDomElementContainer to return a valid container.'
|
||||
);
|
||||
const {
|
||||
runtimeScene,
|
||||
gameDomElementContainer,
|
||||
object,
|
||||
} = await setupObjectAndGetDomElementContainer();
|
||||
|
||||
const inputElement = gameDomElementContainer.querySelector('input');
|
||||
if (!inputElement) throw new Error('Expected input element to be found');
|
||||
@@ -224,25 +195,11 @@ describe('gdjs.TextInputRuntimeObject (using a PixiJS RuntimeGame with DOM eleme
|
||||
});
|
||||
|
||||
it('hides the DOM element when the object is far from the camera', async () => {
|
||||
const runtimeGame = await gdjs.getPixiRuntimeGameWithAssets();
|
||||
const runtimeScene = new gdjs.RuntimeScene(runtimeGame);
|
||||
loadScene(runtimeScene);
|
||||
|
||||
// Make sure the renderer is created (to test the real DOM element creation/update)
|
||||
const gameContainer = document.createElement('div');
|
||||
runtimeGame.getRenderer().createStandardCanvas(gameContainer);
|
||||
|
||||
const object = makeTextInputRuntimeObject(runtimeScene);
|
||||
runtimeScene.addObject(object);
|
||||
|
||||
// Check that the DOM element was created
|
||||
const gameDomElementContainer = runtimeGame
|
||||
.getRenderer()
|
||||
.getDomElementContainer();
|
||||
if (!gameDomElementContainer)
|
||||
throw new Error(
|
||||
'Expected getDomElementContainer to return a valid container.'
|
||||
);
|
||||
const {
|
||||
runtimeScene,
|
||||
gameDomElementContainer,
|
||||
object,
|
||||
} = await setupObjectAndGetDomElementContainer();
|
||||
|
||||
const inputElement = gameDomElementContainer.querySelector('input');
|
||||
if (!inputElement) throw new Error('Expected input element to be found');
|
||||
|
@@ -105,7 +105,9 @@ void DeclareTopDownMovementBehaviorExtension(gd::PlatformExtension& extension) {
|
||||
"res/conditions/keyboard.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "TopDownMovementBehavior")
|
||||
.AddParameter("string", _("Key"))
|
||||
.AddParameter("stringWithSelector",
|
||||
_("Key"),
|
||||
"[\"Left\", \"Right\", \"Up\", \"Down\"]")
|
||||
.MarkAsAdvanced()
|
||||
.SetFunctionName("SimulateControl")
|
||||
.SetIncludeFile(
|
||||
|
22
GDevelop.js/package-lock.json
generated
22
GDevelop.js/package-lock.json
generated
@@ -1214,9 +1214,9 @@
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
},
|
||||
"parse5": {
|
||||
@@ -8019,8 +8019,8 @@
|
||||
"dev": true
|
||||
},
|
||||
"webidl-tools": {
|
||||
"version": "git://github.com/4ian/webidl-tools.git#87247d37944d9cfdecb4f73da93289929b4077df",
|
||||
"from": "git://github.com/4ian/webidl-tools.git#87247d37944d9cfdecb4f73da93289929b4077df",
|
||||
"version": "github:4ian/webidl-tools#348f9c03afc9d8f278efccdd74543e265a41fd11",
|
||||
"from": "github:4ian/webidl-tools#348f9c03afc9d8f278efccdd74543e265a41fd11",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cheerio": "^0.20.0",
|
||||
@@ -8032,13 +8032,13 @@
|
||||
"stream-concat": "^0.1.0",
|
||||
"vinyl": "^1.1.1",
|
||||
"vinyl-fs": "^2.4.2",
|
||||
"webidl2": "git://github.com/markandrus/webidl2.js.git#e470735423d73fbbc20d472d9e0174592b80a463",
|
||||
"webidl2": "github:markandrus/webidl2.js#e470735423d73fbbc20d472d9e0174592b80a463",
|
||||
"winston": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"webidl2": {
|
||||
"version": "git://github.com/markandrus/webidl2.js.git#e470735423d73fbbc20d472d9e0174592b80a463",
|
||||
"from": "git://github.com/markandrus/webidl2.js.git#e470735423d73fbbc20d472d9e0174592b80a463",
|
||||
"version": "github:markandrus/webidl2.js#e470735423d73fbbc20d472d9e0174592b80a463",
|
||||
"from": "github:markandrus/webidl2.js#e470735423d73fbbc20d472d9e0174592b80a463",
|
||||
"dev": true
|
||||
},
|
||||
"whatwg-encoding": {
|
||||
@@ -8129,9 +8129,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"winston": {
|
||||
"version": "2.4.4",
|
||||
"resolved": "https://registry.npmjs.org/winston/-/winston-2.4.4.tgz",
|
||||
"integrity": "sha512-NBo2Pepn4hK4V01UfcWcDlmiVTs7VTB1h7bgnB0rgP146bYhMxX0ypCz3lBOfNxCO4Zuek7yeT+y/zM1OfMw4Q==",
|
||||
"version": "2.4.5",
|
||||
"resolved": "https://registry.npmjs.org/winston/-/winston-2.4.5.tgz",
|
||||
"integrity": "sha512-TWoamHt5yYvsMarGlGEQE59SbJHqGsZV8/lwC+iCcGeAe0vUaOh+Lv6SYM17ouzC/a/LB1/hz/7sxFBtlu1l4A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async": "~1.0.0",
|
||||
|
@@ -33,7 +33,7 @@
|
||||
"grunt-string-replace": "^1.3.1",
|
||||
"jest": "^23.5.0",
|
||||
"shelljs": "^0.8.4",
|
||||
"webidl-tools": "git://github.com/4ian/webidl-tools.git#87247d37944d9cfdecb4f73da93289929b4077df"
|
||||
"webidl-tools": "github:4ian/webidl-tools#348f9c03afc9d8f278efccdd74543e265a41fd11"
|
||||
},
|
||||
"jest": {
|
||||
"testEnvironment": "node",
|
||||
|
@@ -122,6 +122,10 @@
|
||||
"Trans"
|
||||
],
|
||||
"message": "Please import Trans from @lingui/macro"
|
||||
},
|
||||
{
|
||||
"name": "prop-types",
|
||||
"message": "Don't import anything from prop-types - use Flow/TypeScript types instead."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@ import {
|
||||
import RaisedButton from '../UI/RaisedButton';
|
||||
import { ColumnStackLayout } from '../UI/Layout';
|
||||
import {
|
||||
shouldBrowsePrevious,
|
||||
shouldCloseOrCancel,
|
||||
shouldValidate,
|
||||
} from '../UI/KeyboardShortcuts/InteractionKeys';
|
||||
@@ -37,6 +38,7 @@ type Props = {|
|
||||
export type SearchPanelInterface = {|
|
||||
focus: () => void,
|
||||
markSearchResultsDirty: () => void,
|
||||
isSearchOngoing: () => boolean,
|
||||
|};
|
||||
|
||||
const SearchPanel = (
|
||||
@@ -54,19 +56,6 @@ const SearchPanel = (
|
||||
) => {
|
||||
const searchTextField = React.useRef<?TextField>(null);
|
||||
|
||||
const focusSearchField = React.useCallback((): void => {
|
||||
if (searchTextField.current) searchTextField.current.focus();
|
||||
}, []);
|
||||
|
||||
const markSearchResultsDirty = React.useCallback((): void => {
|
||||
setSearchResultsDirty(true);
|
||||
}, []);
|
||||
|
||||
React.useImperativeHandle(ref, () => ({
|
||||
focus: focusSearchField,
|
||||
markSearchResultsDirty,
|
||||
}));
|
||||
|
||||
const [searchText, setSearchText] = React.useState<string>('');
|
||||
const [replaceText, setReplaceText] = React.useState<string>('');
|
||||
const [matchCase, setMatchCase] = React.useState<boolean>(false);
|
||||
@@ -89,6 +78,27 @@ const SearchPanel = (
|
||||
'search-and-replace' | 'search-in-event-sentences'
|
||||
>('search-and-replace');
|
||||
|
||||
const isSearchOngoing = React.useCallback(
|
||||
(): boolean => {
|
||||
return !!searchText && !searchResultsDirty;
|
||||
},
|
||||
[searchText, searchResultsDirty]
|
||||
);
|
||||
|
||||
const focusSearchField = React.useCallback((): void => {
|
||||
if (searchTextField.current) searchTextField.current.focus();
|
||||
}, []);
|
||||
|
||||
const markSearchResultsDirty = React.useCallback((): void => {
|
||||
setSearchResultsDirty(true);
|
||||
}, []);
|
||||
|
||||
React.useImperativeHandle(ref, () => ({
|
||||
isSearchOngoing,
|
||||
focus: focusSearchField,
|
||||
markSearchResultsDirty,
|
||||
}));
|
||||
|
||||
React.useEffect(
|
||||
() => {
|
||||
setSearchResultsDirty(true);
|
||||
@@ -171,7 +181,9 @@ const SearchPanel = (
|
||||
setSearchText(searchText);
|
||||
}}
|
||||
onKeyPress={event => {
|
||||
if (shouldValidate(event)) {
|
||||
if (shouldBrowsePrevious(event)) {
|
||||
onGoToPreviousSearchResult();
|
||||
} else if (shouldValidate(event)) {
|
||||
if (!searchResultsDirty) {
|
||||
onGoToNextSearchResult();
|
||||
} else {
|
||||
|
@@ -317,6 +317,14 @@ export class EventsSheetComponentWithoutHandle extends React.Component<
|
||||
_toggleSearchPanel = () => {
|
||||
this.setState(
|
||||
state => {
|
||||
if (
|
||||
state.showSearchPanel &&
|
||||
this._searchPanel &&
|
||||
this._searchPanel.isSearchOngoing()
|
||||
) {
|
||||
this._searchPanel.focus();
|
||||
return;
|
||||
}
|
||||
const show = !state.showSearchPanel;
|
||||
if (!show) {
|
||||
if (this._eventSearcher) this._eventSearcher.reset();
|
||||
|
@@ -528,7 +528,7 @@ const PropertiesEditor = ({
|
||||
|
||||
if (!!additionalText) {
|
||||
return (
|
||||
<Line alignItems="baseline">
|
||||
<Line alignItems="baseline" key={`section-title-${field.name}`}>
|
||||
<Text displayInlineAsSpan>{field.name}</Text>
|
||||
<Spacer />
|
||||
<Text
|
||||
@@ -540,7 +540,7 @@ const PropertiesEditor = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<Line>
|
||||
<Line key={`section-title-${field.name}`}>
|
||||
<Text displayInlineAsSpan>{field.name}</Text>
|
||||
</Line>
|
||||
);
|
||||
|
@@ -19,6 +19,13 @@ export const shouldValidate = (event: SupportedEvent) => {
|
||||
return event.key === 'Enter';
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the user asked to go to previous match.
|
||||
*/
|
||||
export const shouldBrowsePrevious = (event: SupportedEvent) => {
|
||||
return event.shiftKey && event.key === 'Enter';
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the user asked to activate something.
|
||||
*/
|
||||
|
@@ -10,7 +10,7 @@ import { Line, Column } from '../UI/Grid';
|
||||
import RaisedButton from '../UI/RaisedButton';
|
||||
|
||||
type Props = {|
|
||||
onAdd: () => void,
|
||||
onAdd: ?() => void,
|
||||
onCopy: () => void,
|
||||
hasSelection: boolean,
|
||||
onPaste: () => void,
|
||||
@@ -46,12 +46,14 @@ const EditVariableRow = ({
|
||||
</Column>
|
||||
|
||||
<Column>
|
||||
<RaisedButton
|
||||
primary
|
||||
label={<Trans>Add</Trans>}
|
||||
onClick={onAdd}
|
||||
icon={<Add />}
|
||||
/>
|
||||
{onAdd ? (
|
||||
<RaisedButton
|
||||
primary
|
||||
label={<Trans>Add</Trans>}
|
||||
onClick={onAdd}
|
||||
icon={<Add />}
|
||||
/>
|
||||
) : null}
|
||||
</Column>
|
||||
</Line>
|
||||
);
|
||||
|
@@ -430,30 +430,20 @@ export default class VariablesList extends React.Component<Props, State> {
|
||||
return (
|
||||
<Column noMargin expand useFullHeight>
|
||||
{allVariables.length ? (
|
||||
<React.Fragment>
|
||||
<ScrollView autoHideScrollbar>
|
||||
<SortableVariablesListBody
|
||||
variablesContainer={this.props.variablesContainer}
|
||||
onSortEnd={({ oldIndex, newIndex }) => {
|
||||
this.props.variablesContainer.move(oldIndex, newIndex);
|
||||
this.forceUpdate();
|
||||
}}
|
||||
helperClass="sortable-helper"
|
||||
useDragHandle
|
||||
lockToContainerEdges
|
||||
>
|
||||
{allVariables}
|
||||
</SortableVariablesListBody>
|
||||
</ScrollView>
|
||||
<EditVariableRow
|
||||
onAdd={this.addVariable}
|
||||
onCopy={this.copySelection}
|
||||
onPaste={this.paste}
|
||||
onDeleteSelection={this.deleteSelection}
|
||||
hasSelection={hasSelection(this.state.selectedVariables)}
|
||||
hasClipboard={Clipboard.has(CLIPBOARD_KIND)}
|
||||
/>
|
||||
</React.Fragment>
|
||||
<ScrollView autoHideScrollbar>
|
||||
<SortableVariablesListBody
|
||||
variablesContainer={this.props.variablesContainer}
|
||||
onSortEnd={({ oldIndex, newIndex }) => {
|
||||
this.props.variablesContainer.move(oldIndex, newIndex);
|
||||
this.forceUpdate();
|
||||
}}
|
||||
helperClass="sortable-helper"
|
||||
useDragHandle
|
||||
lockToContainerEdges
|
||||
>
|
||||
{allVariables}
|
||||
</SortableVariablesListBody>
|
||||
</ScrollView>
|
||||
) : this.props.emptyPlaceholderTitle &&
|
||||
this.props.emptyPlaceholderDescription &&
|
||||
this.props.helpPagePath ? (
|
||||
@@ -467,6 +457,14 @@ export default class VariablesList extends React.Component<Props, State> {
|
||||
/>
|
||||
</Column>
|
||||
) : null}
|
||||
<EditVariableRow
|
||||
onAdd={allVariables.length ? this.addVariable : null}
|
||||
onCopy={this.copySelection}
|
||||
onPaste={this.paste}
|
||||
onDeleteSelection={this.deleteSelection}
|
||||
hasSelection={hasSelection(this.state.selectedVariables)}
|
||||
hasClipboard={Clipboard.has(CLIPBOARD_KIND)}
|
||||
/>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
@@ -1,3 +1,4 @@
|
||||
// @flow
|
||||
import * as React from 'react';
|
||||
|
||||
const style = {
|
||||
@@ -7,8 +8,10 @@ const style = {
|
||||
type Props = {
|
||||
children: React.Node,
|
||||
height: number | string,
|
||||
alignItems?: 'center',
|
||||
justifyContent?: 'center',
|
||||
};
|
||||
|
||||
export default ({ children, height }: Props) => (
|
||||
<div style={{ ...style, height }}>{children}</div>
|
||||
export default ({ children, height, alignItems, justifyContent }: Props) => (
|
||||
<div style={{ ...style, height, alignItems, justifyContent }}>{children}</div>
|
||||
);
|
||||
|
@@ -6,6 +6,7 @@ import muiDecorator from '../ThemeDecorator';
|
||||
import paperDecorator from '../PaperDecorator';
|
||||
|
||||
import { EmptyPlaceholder } from '../../UI/EmptyPlaceholder';
|
||||
import FixedHeightFlexContainer from '../FixedHeightFlexContainer';
|
||||
|
||||
export default {
|
||||
title: 'UI Building Blocks/EmptyPlaceholder',
|
||||
@@ -13,11 +14,17 @@ export default {
|
||||
decorators: [paperDecorator, muiDecorator],
|
||||
};
|
||||
export const Default = () => (
|
||||
<EmptyPlaceholder
|
||||
title="Add your first event"
|
||||
description="You can use events to create cause and effect."
|
||||
actionLabel="Add something"
|
||||
helpPagePath="/objects/tiled_sprite"
|
||||
onAdd={action('onAdd')}
|
||||
/>
|
||||
<FixedHeightFlexContainer
|
||||
height={500}
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
>
|
||||
<EmptyPlaceholder
|
||||
title="Add your first event"
|
||||
description="You can use events to create cause and effect."
|
||||
actionLabel="Add something"
|
||||
helpPagePath="/objects/tiled_sprite"
|
||||
onAdd={action('onAdd')}
|
||||
/>
|
||||
</FixedHeightFlexContainer>
|
||||
);
|
||||
|
Reference in New Issue
Block a user