Completely updated React, fixed #11, (hopefully)
This commit is contained in:
322
goTorrentWebUI/node_modules/react-grid-layout/build/ReactGridLayout.js.flow
generated
vendored
322
goTorrentWebUI/node_modules/react-grid-layout/build/ReactGridLayout.js.flow
generated
vendored
@@ -1,16 +1,37 @@
|
||||
// @flow
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import isEqual from 'lodash.isequal';
|
||||
import classNames from 'classnames';
|
||||
import {autoBindHandlers, bottom, childrenEqual, cloneLayoutItem, compact, getLayoutItem, moveElement,
|
||||
synchronizeLayoutWithChildren, validateLayout, getFirstCollision} from './utils';
|
||||
import GridItem from './GridItem';
|
||||
import type {ChildrenArray as ReactChildrenArray, Element as ReactElement} from 'react';
|
||||
const noop = function() {};
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import isEqual from "lodash.isequal";
|
||||
import classNames from "classnames";
|
||||
import {
|
||||
autoBindHandlers,
|
||||
bottom,
|
||||
childrenEqual,
|
||||
cloneLayoutItem,
|
||||
compact,
|
||||
getLayoutItem,
|
||||
moveElement,
|
||||
synchronizeLayoutWithChildren,
|
||||
validateLayout,
|
||||
getAllCollisions,
|
||||
noop
|
||||
} from "./utils";
|
||||
import GridItem from "./GridItem";
|
||||
import type {
|
||||
ChildrenArray as ReactChildrenArray,
|
||||
Element as ReactElement
|
||||
} from "react";
|
||||
|
||||
// Types
|
||||
import type {EventCallback, CompactType, GridResizeEvent, GridDragEvent, Layout, LayoutItem} from './utils';
|
||||
import type {
|
||||
EventCallback,
|
||||
CompactType,
|
||||
GridResizeEvent,
|
||||
GridDragEvent,
|
||||
Layout,
|
||||
LayoutItem
|
||||
} from "./utils";
|
||||
|
||||
type State = {
|
||||
activeDrag: ?LayoutItem,
|
||||
layout: Layout,
|
||||
@@ -29,10 +50,10 @@ export type Props = {
|
||||
draggableCancel: string,
|
||||
draggableHandle: string,
|
||||
verticalCompact: boolean,
|
||||
compactType: ?('horizontal' | 'vertical'),
|
||||
compactType: ?("horizontal" | "vertical"),
|
||||
layout: Layout,
|
||||
margin: [number, number],
|
||||
containerPadding: [number, number],
|
||||
containerPadding: [number, number] | null,
|
||||
rowHeight: number,
|
||||
maxRows: number,
|
||||
isDraggable: boolean,
|
||||
@@ -41,14 +62,14 @@ export type Props = {
|
||||
useCSSTransforms: boolean,
|
||||
|
||||
// Callbacks
|
||||
onLayoutChange: (Layout) => void,
|
||||
onLayoutChange: Layout => void,
|
||||
onDrag: EventCallback,
|
||||
onDragStart: EventCallback,
|
||||
onDragStop: EventCallback,
|
||||
onResize: EventCallback,
|
||||
onResizeStart: EventCallback,
|
||||
onResizeStop: EventCallback,
|
||||
children: ReactChildrenArray<ReactElement<any>>,
|
||||
children: ReactChildrenArray<ReactElement<any>>
|
||||
};
|
||||
// End Types
|
||||
|
||||
@@ -83,23 +104,28 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
||||
draggableHandle: PropTypes.string,
|
||||
|
||||
// Deprecated
|
||||
verticalCompact: function(props) {
|
||||
if (props.verticalCompact === false && process.env.NODE_ENV !== 'production') {
|
||||
console.warn( // eslint-disable-line no-console
|
||||
'`verticalCompact` on <ReactGridLayout> is deprecated and will be removed soon. ' +
|
||||
'Use `compactType`: "horizontal" | "vertical" | null.');
|
||||
verticalCompact: function(props: Props) {
|
||||
if (
|
||||
props.verticalCompact === false &&
|
||||
process.env.NODE_ENV !== "production"
|
||||
) {
|
||||
console.warn(
|
||||
// eslint-disable-line no-console
|
||||
"`verticalCompact` on <ReactGridLayout> is deprecated and will be removed soon. " +
|
||||
'Use `compactType`: "horizontal" | "vertical" | null.'
|
||||
);
|
||||
}
|
||||
},
|
||||
// Choose vertical or hotizontal compaction
|
||||
compactType: PropTypes.oneOf(['vertical', 'horizontal']),
|
||||
compactType: PropTypes.oneOf(["vertical", "horizontal"]),
|
||||
|
||||
// layout is an array of object with the format:
|
||||
// {x: Number, y: Number, w: Number, h: Number, i: String}
|
||||
layout: function (props) {
|
||||
layout: function(props: Props) {
|
||||
var layout = props.layout;
|
||||
// I hope you're setting the data-grid property on the grid items
|
||||
if (layout === undefined) return;
|
||||
validateLayout(layout, 'layout');
|
||||
validateLayout(layout, "layout");
|
||||
},
|
||||
|
||||
//
|
||||
@@ -155,14 +181,18 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
||||
//
|
||||
|
||||
// Children must not have duplicate keys.
|
||||
children: function (props, propName, _componentName) {
|
||||
children: function(props: Props, propName: string) {
|
||||
var children = props[propName];
|
||||
|
||||
// Check children keys for duplicates. Throw if found.
|
||||
var keys = {};
|
||||
React.Children.forEach(children, function (child) {
|
||||
React.Children.forEach(children, function(child) {
|
||||
if (keys[child.key]) {
|
||||
throw new Error("Duplicate child key \"" + child.key + "\" found! This will cause problems in ReactGridLayout.");
|
||||
throw new Error(
|
||||
'Duplicate child key "' +
|
||||
child.key +
|
||||
'" found! This will cause problems in ReactGridLayout.'
|
||||
);
|
||||
}
|
||||
keys[child.key] = true;
|
||||
});
|
||||
@@ -172,7 +202,11 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
||||
static defaultProps = {
|
||||
autoSize: true,
|
||||
cols: 12,
|
||||
className: '',
|
||||
className: "",
|
||||
style: {},
|
||||
draggableHandle: "",
|
||||
draggableCancel: "",
|
||||
containerPadding: null,
|
||||
rowHeight: 150,
|
||||
maxRows: Infinity, // infinite vertical growth
|
||||
layout: [],
|
||||
@@ -181,7 +215,7 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
||||
isResizable: true,
|
||||
useCSSTransforms: true,
|
||||
verticalCompact: true,
|
||||
compactType: 'vertical',
|
||||
compactType: "vertical",
|
||||
preventCollision: false,
|
||||
onLayoutChange: noop,
|
||||
onDragStart: noop,
|
||||
@@ -194,22 +228,33 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
||||
|
||||
state: State = {
|
||||
activeDrag: null,
|
||||
layout: synchronizeLayoutWithChildren(this.props.layout, this.props.children, this.props.cols,
|
||||
// Legacy support for verticalCompact: false
|
||||
this.compactType()),
|
||||
layout: synchronizeLayoutWithChildren(
|
||||
this.props.layout,
|
||||
this.props.children,
|
||||
this.props.cols,
|
||||
// Legacy support for verticalCompact: false
|
||||
this.compactType()
|
||||
),
|
||||
mounted: false,
|
||||
oldDragItem: null,
|
||||
oldLayout: null,
|
||||
oldResizeItem: null,
|
||||
oldResizeItem: null
|
||||
};
|
||||
|
||||
constructor(props: Props, context: any): void {
|
||||
super(props, context);
|
||||
autoBindHandlers(this, ['onDragStart', 'onDrag', 'onDragStop', 'onResizeStart', 'onResize', 'onResizeStop']);
|
||||
autoBindHandlers(this, [
|
||||
"onDragStart",
|
||||
"onDrag",
|
||||
"onDragStop",
|
||||
"onResizeStart",
|
||||
"onResize",
|
||||
"onResizeStop"
|
||||
]);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setState({mounted: true});
|
||||
this.setState({ mounted: true });
|
||||
// Possibly call back with layout on mount. This should be done after correcting the layout width
|
||||
// to ensure we don't rerender with the wrong width.
|
||||
this.onLayoutMaybeChanged(this.state.layout, this.props.layout);
|
||||
@@ -219,23 +264,28 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
||||
let newLayoutBase;
|
||||
// Legacy support for compactType
|
||||
// Allow parent to set layout directly.
|
||||
if (!isEqual(nextProps.layout, this.props.layout) || nextProps.compactType !== this.props.compactType) {
|
||||
if (
|
||||
!isEqual(nextProps.layout, this.props.layout) ||
|
||||
nextProps.compactType !== this.props.compactType
|
||||
) {
|
||||
newLayoutBase = nextProps.layout;
|
||||
}
|
||||
|
||||
// If children change, also regenerate the layout. Use our state
|
||||
// as the base in case because it may be more up to date than
|
||||
// what is in props.
|
||||
else if (!childrenEqual(this.props.children, nextProps.children)) {
|
||||
} else if (!childrenEqual(this.props.children, nextProps.children)) {
|
||||
// If children change, also regenerate the layout. Use our state
|
||||
// as the base in case because it may be more up to date than
|
||||
// what is in props.
|
||||
newLayoutBase = this.state.layout;
|
||||
}
|
||||
|
||||
// We need to regenerate the layout.
|
||||
if (newLayoutBase) {
|
||||
const newLayout = synchronizeLayoutWithChildren(newLayoutBase, nextProps.children,
|
||||
nextProps.cols, this.compactType(nextProps));
|
||||
const newLayout = synchronizeLayoutWithChildren(
|
||||
newLayoutBase,
|
||||
nextProps.children,
|
||||
nextProps.cols,
|
||||
this.compactType(nextProps)
|
||||
);
|
||||
const oldLayout = this.state.layout;
|
||||
this.setState({layout: newLayout});
|
||||
this.setState({ layout: newLayout });
|
||||
this.onLayoutMaybeChanged(newLayout, oldLayout);
|
||||
}
|
||||
}
|
||||
@@ -247,8 +297,15 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
||||
containerHeight() {
|
||||
if (!this.props.autoSize) return;
|
||||
const nbRow = bottom(this.state.layout);
|
||||
const containerPaddingY = this.props.containerPadding ? this.props.containerPadding[1] : this.props.margin[1];
|
||||
return nbRow * this.props.rowHeight + (nbRow - 1) * this.props.margin[1] + containerPaddingY * 2 + 'px';
|
||||
const containerPaddingY = this.props.containerPadding
|
||||
? this.props.containerPadding[1]
|
||||
: this.props.margin[1];
|
||||
return (
|
||||
nbRow * this.props.rowHeight +
|
||||
(nbRow - 1) * this.props.margin[1] +
|
||||
containerPaddingY * 2 +
|
||||
"px"
|
||||
);
|
||||
}
|
||||
|
||||
compactType(props: ?Object): CompactType {
|
||||
@@ -264,14 +321,17 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
||||
* @param {Event} e The mousedown event
|
||||
* @param {Element} node The current dragging DOM element
|
||||
*/
|
||||
onDragStart(i:string, x:number, y:number, {e, node}: GridDragEvent) {
|
||||
const {layout} = this.state;
|
||||
onDragStart(i: string, x: number, y: number, { e, node }: GridDragEvent) {
|
||||
const { layout } = this.state;
|
||||
var l = getLayoutItem(layout, i);
|
||||
if (!l) return;
|
||||
|
||||
this.setState({oldDragItem: cloneLayoutItem(l), oldLayout: this.state.layout});
|
||||
this.setState({
|
||||
oldDragItem: cloneLayoutItem(l),
|
||||
oldLayout: this.state.layout
|
||||
});
|
||||
|
||||
this.props.onDragStart(layout, l, l, null, e, node);
|
||||
return this.props.onDragStart(layout, l, l, null, e, node);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -282,21 +342,35 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
||||
* @param {Event} e The mousedown event
|
||||
* @param {Element} node The current dragging DOM element
|
||||
*/
|
||||
onDrag(i:string, x:number, y:number, {e, node}: GridDragEvent) {
|
||||
const {oldDragItem} = this.state;
|
||||
let {layout} = this.state;
|
||||
const {cols} = this.props;
|
||||
onDrag(i: string, x: number, y: number, { e, node }: GridDragEvent) {
|
||||
const { oldDragItem } = this.state;
|
||||
let { layout } = this.state;
|
||||
const { cols } = this.props;
|
||||
var l = getLayoutItem(layout, i);
|
||||
if (!l) return;
|
||||
|
||||
// Create placeholder (display only)
|
||||
var placeholder = {
|
||||
w: l.w, h: l.h, x: l.x, y: l.y, placeholder: true, i: i
|
||||
w: l.w,
|
||||
h: l.h,
|
||||
x: l.x,
|
||||
y: l.y,
|
||||
placeholder: true,
|
||||
i: i
|
||||
};
|
||||
|
||||
// Move the element to the dragged location.
|
||||
const isUserAction = true;
|
||||
layout = moveElement(layout, l, x, y, isUserAction, this.props.preventCollision, this.compactType(), cols);
|
||||
layout = moveElement(
|
||||
layout,
|
||||
l,
|
||||
x,
|
||||
y,
|
||||
isUserAction,
|
||||
this.props.preventCollision,
|
||||
this.compactType(),
|
||||
cols
|
||||
);
|
||||
|
||||
this.props.onDrag(layout, oldDragItem, l, placeholder, e, node);
|
||||
|
||||
@@ -314,27 +388,36 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
||||
* @param {Event} e The mousedown event
|
||||
* @param {Element} node The current dragging DOM element
|
||||
*/
|
||||
onDragStop(i:string, x:number, y:number, {e, node}: GridDragEvent) {
|
||||
const {oldDragItem} = this.state;
|
||||
let {layout} = this.state;
|
||||
const {cols, preventCollision} = this.props;
|
||||
onDragStop(i: string, x: number, y: number, { e, node }: GridDragEvent) {
|
||||
const { oldDragItem } = this.state;
|
||||
let { layout } = this.state;
|
||||
const { cols, preventCollision } = this.props;
|
||||
const l = getLayoutItem(layout, i);
|
||||
if (!l) return;
|
||||
|
||||
// Move the element here
|
||||
const isUserAction = true;
|
||||
layout = moveElement(layout, l, x, y, isUserAction, preventCollision, this.compactType(), cols);
|
||||
layout = moveElement(
|
||||
layout,
|
||||
l,
|
||||
x,
|
||||
y,
|
||||
isUserAction,
|
||||
preventCollision,
|
||||
this.compactType(),
|
||||
cols
|
||||
);
|
||||
|
||||
this.props.onDragStop(layout, oldDragItem, l, null, e, node);
|
||||
|
||||
// Set state
|
||||
const newLayout = compact(layout, this.compactType(), cols);
|
||||
const {oldLayout} = this.state;
|
||||
const { oldLayout } = this.state;
|
||||
this.setState({
|
||||
activeDrag: null,
|
||||
layout: newLayout,
|
||||
oldDragItem: null,
|
||||
oldLayout: null,
|
||||
oldLayout: null
|
||||
});
|
||||
|
||||
this.onLayoutMaybeChanged(newLayout, oldLayout);
|
||||
@@ -347,8 +430,8 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
||||
}
|
||||
}
|
||||
|
||||
onResizeStart(i:string, w:number, h:number, {e, node}: GridResizeEvent) {
|
||||
const {layout} = this.state;
|
||||
onResizeStart(i: string, w: number, h: number, { e, node }: GridResizeEvent) {
|
||||
const { layout } = this.state;
|
||||
var l = getLayoutItem(layout, i);
|
||||
if (!l) return;
|
||||
|
||||
@@ -360,24 +443,47 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
||||
this.props.onResizeStart(layout, l, l, null, e, node);
|
||||
}
|
||||
|
||||
onResize(i:string, w:number, h:number, {e, node}: GridResizeEvent) {
|
||||
const {layout, oldResizeItem} = this.state;
|
||||
const {cols, preventCollision} = this.props;
|
||||
var l = getLayoutItem(layout, i);
|
||||
onResize(i: string, w: number, h: number, { e, node }: GridResizeEvent) {
|
||||
const { layout, oldResizeItem } = this.state;
|
||||
const { cols, preventCollision } = this.props;
|
||||
const l: ?LayoutItem = getLayoutItem(layout, i);
|
||||
if (!l) return;
|
||||
|
||||
// Short circuit if there is a collision in no rearrangement mode.
|
||||
if (preventCollision && getFirstCollision(layout, {...l, w, h})) {
|
||||
return;
|
||||
// Something like quad tree should be used
|
||||
// to find collisions faster
|
||||
let hasCollisions;
|
||||
if (preventCollision) {
|
||||
const collisions = getAllCollisions(layout, { ...l, w, h }).filter((layoutItem) => layoutItem.i !== l.i);
|
||||
hasCollisions = collisions.length > 0;
|
||||
|
||||
// If we're colliding, we need adjust the placeholder.
|
||||
if (hasCollisions) {
|
||||
// adjust w && h to maximum allowed space
|
||||
let leastX = Infinity, leastY = Infinity;
|
||||
collisions.forEach((layoutItem) => {
|
||||
if (layoutItem.x > l.x) leastX = Math.min(leastX, layoutItem.x);
|
||||
if (layoutItem.y > l.y) leastY = Math.min(leastY, layoutItem.y);
|
||||
});
|
||||
|
||||
if (Number.isFinite(leastX)) l.w = leastX - l.x;
|
||||
if (Number.isFinite(leastY)) l.h = leastY - l.y;
|
||||
}
|
||||
}
|
||||
|
||||
// Set new width and height.
|
||||
l.w = w;
|
||||
l.h = h;
|
||||
if (!hasCollisions) {
|
||||
// Set new width and height.
|
||||
l.w = w;
|
||||
l.h = h;
|
||||
}
|
||||
|
||||
// Create placeholder element (display only)
|
||||
var placeholder = {
|
||||
w: w, h: h, x: l.x, y: l.y, static: true, i: i
|
||||
w: l.w,
|
||||
h: l.h,
|
||||
x: l.x,
|
||||
y: l.y,
|
||||
static: true,
|
||||
i: i
|
||||
};
|
||||
|
||||
this.props.onResize(layout, oldResizeItem, l, placeholder, e, node);
|
||||
@@ -389,16 +495,16 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
||||
});
|
||||
}
|
||||
|
||||
onResizeStop(i:string, w:number, h:number, {e, node}: GridResizeEvent) {
|
||||
const {layout, oldResizeItem} = this.state;
|
||||
const {cols} = this.props;
|
||||
onResizeStop(i: string, w: number, h: number, { e, node }: GridResizeEvent) {
|
||||
const { layout, oldResizeItem } = this.state;
|
||||
const { cols } = this.props;
|
||||
var l = getLayoutItem(layout, i);
|
||||
|
||||
this.props.onResizeStop(layout, oldResizeItem, l, null, e, node);
|
||||
|
||||
// Set state
|
||||
const newLayout = compact(layout, this.compactType(), cols);
|
||||
const {oldLayout} = this.state;
|
||||
const { oldLayout } = this.state;
|
||||
this.setState({
|
||||
activeDrag: null,
|
||||
layout: newLayout,
|
||||
@@ -414,9 +520,17 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
||||
* @return {Element} Placeholder div.
|
||||
*/
|
||||
placeholder(): ?ReactElement<any> {
|
||||
const {activeDrag} = this.state;
|
||||
const { activeDrag } = this.state;
|
||||
if (!activeDrag) return null;
|
||||
const {width, cols, margin, containerPadding, rowHeight, maxRows, useCSSTransforms} = this.props;
|
||||
const {
|
||||
width,
|
||||
cols,
|
||||
margin,
|
||||
containerPadding,
|
||||
rowHeight,
|
||||
maxRows,
|
||||
useCSSTransforms
|
||||
} = this.props;
|
||||
|
||||
// {...this.state.activeDrag} is pretty slow, actually
|
||||
return (
|
||||
@@ -435,7 +549,8 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
||||
rowHeight={rowHeight}
|
||||
isDraggable={false}
|
||||
isResizable={false}
|
||||
useCSSTransforms={useCSSTransforms}>
|
||||
useCSSTransforms={useCSSTransforms}
|
||||
>
|
||||
<div />
|
||||
</GridItem>
|
||||
);
|
||||
@@ -447,17 +562,31 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
||||
* @return {Element} Element wrapped in draggable and properly placed.
|
||||
*/
|
||||
processGridItem(child: ReactElement<any>): ?ReactElement<any> {
|
||||
if (!child.key) return;
|
||||
if (!child || !child.key) return;
|
||||
const l = getLayoutItem(this.state.layout, String(child.key));
|
||||
if (!l) return null;
|
||||
const {width, cols, margin, containerPadding, rowHeight,
|
||||
maxRows, isDraggable, isResizable, useCSSTransforms,
|
||||
draggableCancel, draggableHandle} = this.props;
|
||||
const {mounted} = this.state;
|
||||
const {
|
||||
width,
|
||||
cols,
|
||||
margin,
|
||||
containerPadding,
|
||||
rowHeight,
|
||||
maxRows,
|
||||
isDraggable,
|
||||
isResizable,
|
||||
useCSSTransforms,
|
||||
draggableCancel,
|
||||
draggableHandle
|
||||
} = this.props;
|
||||
const { mounted } = this.state;
|
||||
|
||||
// Parse 'static'. Any properties defined directly on the grid item will take precedence.
|
||||
const draggable = Boolean(!l.static && isDraggable && (l.isDraggable || l.isDraggable == null));
|
||||
const resizable = Boolean(!l.static && isResizable && (l.isResizable || l.isResizable == null));
|
||||
const draggable = Boolean(
|
||||
!l.static && isDraggable && (l.isDraggable || l.isDraggable == null)
|
||||
);
|
||||
const resizable = Boolean(
|
||||
!l.static && isResizable && (l.isResizable || l.isResizable == null)
|
||||
);
|
||||
|
||||
return (
|
||||
<GridItem
|
||||
@@ -479,7 +608,6 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
||||
isResizable={resizable}
|
||||
useCSSTransforms={useCSSTransforms && mounted}
|
||||
usePercentages={!mounted}
|
||||
|
||||
w={l.w}
|
||||
h={l.h}
|
||||
x={l.x}
|
||||
@@ -490,26 +618,26 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
||||
maxH={l.maxH}
|
||||
maxW={l.maxW}
|
||||
static={l.static}
|
||||
>
|
||||
>
|
||||
{child}
|
||||
</GridItem>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {className, style} = this.props;
|
||||
const { className, style } = this.props;
|
||||
|
||||
const mergedClassName = classNames("react-grid-layout", className);
|
||||
const mergedStyle = {
|
||||
height: this.containerHeight(),
|
||||
...style
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={classNames('react-grid-layout', className)} style={mergedStyle}>
|
||||
{
|
||||
// $FlowIgnore: Appears to think map calls back w/array
|
||||
React.Children.map(this.props.children, (child) => this.processGridItem(child))
|
||||
}
|
||||
<div className={mergedClassName} style={mergedStyle}>
|
||||
{React.Children.map(this.props.children, child =>
|
||||
this.processGridItem(child)
|
||||
)}
|
||||
{this.placeholder()}
|
||||
</div>
|
||||
);
|
||||
|
Reference in New Issue
Block a user