Compare commits

...

8 Commits

Author SHA1 Message Date
HarelM 732581c39e More components migration 2023-12-21 13:30:19 +02:00
HarelM f435ab79c1 More components migration 2023-12-21 13:14:34 +02:00
HarelM 50226a9b2e Fix build 2023-12-21 12:00:19 +02:00
HarelM e5688fd9a5 More components migration 2023-12-21 11:58:20 +02:00
HarelM 0e39476bd9 Migrate block and field doc label 2023-12-21 10:39:54 +02:00
HarelM 19fc3970a9 Migrate more components 2023-12-21 10:27:54 +02:00
HarelM 1a09de238a Fix typescript error 2023-12-21 09:24:59 +02:00
HarelM 66a0ee5d4e Initial migration of jsx files 2023-12-21 09:23:06 +02:00
38 changed files with 507 additions and 406 deletions
+75
View File
@@ -67,11 +67,16 @@
"@storybook/react": "^7.6.5", "@storybook/react": "^7.6.5",
"@storybook/react-vite": "^7.6.5", "@storybook/react-vite": "^7.6.5",
"@storybook/theming": "^7.6.5", "@storybook/theming": "^7.6.5",
"@types/color": "^3.0.6",
"@types/cors": "^2.8.17", "@types/cors": "^2.8.17",
"@types/lodash.isequal": "^4.5.8", "@types/lodash.isequal": "^4.5.8",
"@types/lodash.throttle": "^4.1.9", "@types/lodash.throttle": "^4.1.9",
"@types/react": "^16.14.52", "@types/react": "^16.14.52",
"@types/react-aria-modal": "^4.0.9",
"@types/react-autocomplete": "^1.8.9",
"@types/react-color": "^3.0.10",
"@types/react-dom": "^16.9.24", "@types/react-dom": "^16.9.24",
"@types/react-icon-base": "^2.1.6",
"@types/uuid": "^9.0.7", "@types/uuid": "^9.0.7",
"@vitejs/plugin-react": "^4.2.0", "@vitejs/plugin-react": "^4.2.0",
"cors": "^2.8.5", "cors": "^2.8.5",
@@ -4583,6 +4588,30 @@
"@types/chai": "*" "@types/chai": "*"
} }
}, },
"node_modules/@types/color": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/@types/color/-/color-3.0.6.tgz",
"integrity": "sha512-NMiNcZFRUAiUUCCf7zkAelY8eV3aKqfbzyFQlXpPIEeoNDbsEHGpb854V3gzTsGKYj830I5zPuOwU/TP5/cW6A==",
"dev": true,
"dependencies": {
"@types/color-convert": "*"
}
},
"node_modules/@types/color-convert": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/color-convert/-/color-convert-2.0.3.tgz",
"integrity": "sha512-2Q6wzrNiuEvYxVQqhh7sXM2mhIhvZR/Paq4FdsQkOMgWsCIkKvSGj8Le1/XalulrmgOzPMqNa0ix+ePY4hTrfg==",
"dev": true,
"dependencies": {
"@types/color-name": "*"
}
},
"node_modules/@types/color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha512-87W6MJCKZYDhLAx/J1ikW8niMvmGRyY+rpUxWpL1cO7F8Uu5CHuQoFv+R0/L5pgNdW4jTyda42kv60uwVIPjLw==",
"dev": true
},
"node_modules/@types/connect": { "node_modules/@types/connect": {
"version": "3.4.38", "version": "3.4.38",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
@@ -4831,6 +4860,34 @@
"csstype": "^3.0.2" "csstype": "^3.0.2"
} }
}, },
"node_modules/@types/react-aria-modal": {
"version": "4.0.9",
"resolved": "https://registry.npmjs.org/@types/react-aria-modal/-/react-aria-modal-4.0.9.tgz",
"integrity": "sha512-H8SU5QoB+1ldMGYRHNm1MXfzD5oD+ZdYTrwVzT+KEiFrkTqQG2QdwVc6Ro4/RixnU4LNtMpvF5HKAIfzzGJGjw==",
"dev": true,
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/react-autocomplete": {
"version": "1.8.9",
"resolved": "https://registry.npmjs.org/@types/react-autocomplete/-/react-autocomplete-1.8.9.tgz",
"integrity": "sha512-Il8qJEKvPU0uW+HOPiRHIKxGF61RM6cM5tEnZDmM5ek78OK5kfv04AZbNyqdPsuTnwp8HIRgBnQH2RhgKILjcg==",
"dev": true,
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/react-color": {
"version": "3.0.10",
"resolved": "https://registry.npmjs.org/@types/react-color/-/react-color-3.0.10.tgz",
"integrity": "sha512-6K5BAn3zyd8lW8UbckIAVeXGxR82Za9jyGD2DBEynsa7fKaguLDVtjfypzs7fgEV7bULgs7uhds8A8v1wABTvQ==",
"dev": true,
"dependencies": {
"@types/react": "*",
"@types/reactcss": "*"
}
},
"node_modules/@types/react-dom": { "node_modules/@types/react-dom": {
"version": "16.9.24", "version": "16.9.24",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.24.tgz", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.24.tgz",
@@ -4840,6 +4897,24 @@
"@types/react": "^16" "@types/react": "^16"
} }
}, },
"node_modules/@types/react-icon-base": {
"version": "2.1.6",
"resolved": "https://registry.npmjs.org/@types/react-icon-base/-/react-icon-base-2.1.6.tgz",
"integrity": "sha512-ebbN1JjCm6RxBd3HdI1+8VCdiOI4qMjnl9DIHWJFrB/eYLF4mzIgdL34PIqCJBLY3vlwil9v6IHQvzsa8vgMsg==",
"dev": true,
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/reactcss": {
"version": "1.2.11",
"resolved": "https://registry.npmjs.org/@types/reactcss/-/reactcss-1.2.11.tgz",
"integrity": "sha512-0fFy0ubuPlhksId8r9V8nsLcxBAPQnn15g/ERAElgE9L6rOquMj2CapsxqfyBuHlkp0/ndEUVnkYI7MkTtkGpw==",
"dev": true,
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/resolve": { "node_modules/@types/resolve": {
"version": "1.20.6", "version": "1.20.6",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz",
+5
View File
@@ -96,11 +96,16 @@
"@storybook/react": "^7.6.5", "@storybook/react": "^7.6.5",
"@storybook/react-vite": "^7.6.5", "@storybook/react-vite": "^7.6.5",
"@storybook/theming": "^7.6.5", "@storybook/theming": "^7.6.5",
"@types/color": "^3.0.6",
"@types/cors": "^2.8.17", "@types/cors": "^2.8.17",
"@types/lodash.isequal": "^4.5.8", "@types/lodash.isequal": "^4.5.8",
"@types/lodash.throttle": "^4.1.9", "@types/lodash.throttle": "^4.1.9",
"@types/react": "^16.14.52", "@types/react": "^16.14.52",
"@types/react-aria-modal": "^4.0.9",
"@types/react-autocomplete": "^1.8.9",
"@types/react-color": "^3.0.10",
"@types/react-dom": "^16.9.24", "@types/react-dom": "^16.9.24",
"@types/react-icon-base": "^2.1.6",
"@types/uuid": "^9.0.7", "@types/uuid": "^9.0.7",
"@vitejs/plugin-react": "^4.2.0", "@vitejs/plugin-react": "^4.2.0",
"cors": "^2.8.5", "cors": "^2.8.5",
@@ -1,40 +1,43 @@
import React from 'react' import React, {SyntheticEvent} from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames' import classnames from 'classnames'
import FieldDocLabel from './FieldDocLabel' import FieldDocLabel from './FieldDocLabel'
import Doc from './Doc' import Doc from './Doc'
/** Wrap a component with a label */ type BlockProps = {
export default class Block extends React.Component { "data-wd-key"?: string
static propTypes = { label?: string
"data-wd-key": PropTypes.string, action?: React.ReactElement
label: PropTypes.oneOfType([ style?: object
PropTypes.string, onChange?(...args: unknown[]): unknown
PropTypes.element, fieldSpec?: object
]), wideMode?: boolean
action: PropTypes.element, error?: unknown[]
children: PropTypes.node.isRequired, };
style: PropTypes.object,
onChange: PropTypes.func,
fieldSpec: PropTypes.object,
wideMode: PropTypes.bool,
error: PropTypes.array,
}
constructor (props) { type BlockState = {
showDoc: boolean
};
/** Wrap a component with a label */
export default class Block extends React.Component<BlockProps, BlockState> {
_blockEl: HTMLDivElement | null = null;
constructor (props: BlockProps) {
super(props); super(props);
this.state = { this.state = {
showDoc: false, showDoc: false,
} }
} }
onChange(e) { onChange(e: React.BaseSyntheticEvent<Event, HTMLInputElement, HTMLInputElement>) {
const value = e.target.value const value = e.target.value
return this.props.onChange(value === "" ? undefined : value) if (this.props.onChange) {
return this.props.onChange(value === "" ? undefined : value)
}
} }
onToggleDoc = (val) => { onToggleDoc = (val: boolean) => {
this.setState({ this.setState({
showDoc: val showDoc: val
}); });
@@ -46,20 +49,17 @@ export default class Block extends React.Component {
* causing the picker to reopen. This causes a scenario where the picker can * causing the picker to reopen. This causes a scenario where the picker can
* never be closed once open. * never be closed once open.
*/ */
onLabelClick = (event) => { onLabelClick = (event: SyntheticEvent<any, any>) => {
const el = event.nativeEvent.target; const el = event.nativeEvent.target;
const nativeEvent = event.nativeEvent; const contains = this._blockEl?.contains(el);
const contains = this._blockEl.contains(el);
if (event.nativeEvent.target.nodeName !== "INPUT" && !contains) { if (event.nativeEvent.target.nodeName !== "INPUT" && !contains) {
event.stopPropagation(); event.stopPropagation();
} }
event.preventDefault(); event.preventDefault();
} }
render() { render() {
const errors = [].concat(this.props.error || []);
return <label style={this.props.style} return <label style={this.props.style}
data-wd-key={this.props["data-wd-key"]} data-wd-key={this.props["data-wd-key"]}
className={classnames({ className={classnames({
@@ -1,24 +1,33 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
export default class Doc extends React.Component { const headers = {
static propTypes = { js: "JS",
fieldSpec: PropTypes.object.isRequired, android: "Android",
ios: "iOS",
macos: "macOS",
};
type DocProps = {
fieldSpec: {
doc?: string
values?: {
[key: string]: {
doc?: string
}
}
'sdk-support'?: {
[key: string]: typeof headers
}
} }
};
export default class Doc extends React.Component<DocProps> {
render () { render () {
const {fieldSpec} = this.props; const {fieldSpec} = this.props;
const {doc, values} = fieldSpec; const {doc, values} = fieldSpec;
const sdkSupport = fieldSpec['sdk-support']; const sdkSupport = fieldSpec['sdk-support'];
const headers = {
js: "JS",
android: "Android",
ios: "iOS",
macos: "macOS",
};
const renderValues = ( const renderValues = (
!!values && !!values &&
// HACK: Currently we merge additional values into the style spec, so this is required // HACK: Currently we merge additional values into the style spec, so this is required
@@ -61,10 +70,9 @@ export default class Doc extends React.Component {
return ( return (
<tr key={key}> <tr key={key}>
<td>{key}</td> <td>{key}</td>
{Object.keys(headers).map(k => { {Object.keys(headers).map((k) => {
const value = supportObj[k];
if (supportObj.hasOwnProperty(k)) { if (supportObj.hasOwnProperty(k)) {
return <td key={k}>{supportObj[k]}</td>; return <td key={k}>{supportObj[k as keyof typeof headers]}</td>;
} }
else { else {
return <td key={k}>no</td>; return <td key={k}>no</td>;
@@ -80,4 +88,4 @@ export default class Doc extends React.Component {
</> </>
); );
} }
} }
@@ -1,26 +1,27 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import {MdInfoOutline, MdHighlightOff} from 'react-icons/md' import {MdInfoOutline, MdHighlightOff} from 'react-icons/md'
export default class FieldDocLabel extends React.Component { type FieldDocLabelProps = {
static propTypes = { label: object | string | undefined
label: PropTypes.oneOfType([ fieldSpec?: {
PropTypes.object, doc?: string
PropTypes.string
]).isRequired,
fieldSpec: PropTypes.object,
onToggleDoc: PropTypes.func,
} }
onToggleDoc?(...args: unknown[]): unknown
};
constructor (props) { type FieldDocLabelState = {
open: boolean
};
export default class FieldDocLabel extends React.Component<FieldDocLabelProps, FieldDocLabelState> {
constructor (props: FieldDocLabelProps) {
super(props); super(props);
this.state = { this.state = {
open: false, open: false,
} }
} }
onToggleDoc = (open) => { onToggleDoc = (open: boolean) => {
this.setState({ this.setState({
open, open,
}, () => { }, () => {
-20
View File
@@ -1,20 +0,0 @@
import React from 'react'
import PropTypes from 'prop-types'
import InputEnum from './InputEnum'
import Block from './Block';
import Fieldset from './Fieldset';
export default class FieldEnum extends React.Component {
static propTypes = {
...InputEnum.propTypes,
}
render() {
const {props} = this;
return <Fieldset label={props.label}>
<InputEnum {...props} />
</Fieldset>
}
}
+17
View File
@@ -0,0 +1,17 @@
import React from 'react'
import InputEnum, {InputEnumProps} from './InputEnum'
import Fieldset from './Fieldset';
type FieldEnumProps = InputEnumProps & { label : string };
export default class FieldEnum extends React.Component<FieldEnumProps> {
render() {
const {props} = this;
return <Fieldset label={props.label}>
<InputEnum {...props} />
</Fieldset>
}
}
@@ -1,18 +1,17 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import {latest} from '@maplibre/maplibre-gl-style-spec' import {latest} from '@maplibre/maplibre-gl-style-spec'
import Block from './Block' import Block from './Block'
import InputString from './InputString' import InputString from './InputString'
export default class FieldId extends React.Component { type FieldIdProps = {
static propTypes = { value: string
value: PropTypes.string.isRequired, wdKey: string
wdKey: PropTypes.string.isRequired, onChange(...args: unknown[]): unknown
onChange: PropTypes.func.isRequired, error?: unknown[]
error: PropTypes.object, };
}
export default class FieldId extends React.Component<FieldIdProps> {
render() { render() {
return <Block label={"ID"} fieldSpec={latest.layer.id} return <Block label={"ID"} fieldSpec={latest.layer.id}
data-wd-key={this.props.wdKey} data-wd-key={this.props.wdKey}
-20
View File
@@ -1,20 +0,0 @@
import React from 'react'
import PropTypes from 'prop-types'
import Block from './Block'
import InputString from './InputString'
export default class FieldString extends React.Component {
static propTypes = {
...InputString.propTypes,
name: PropTypes.string,
}
render() {
const {props} = this;
return <Block label={props.label}>
<InputString {...props} />
</Block>
}
}
+18
View File
@@ -0,0 +1,18 @@
import React from 'react'
import Block from './Block'
import InputString, {InputStringProps} from './InputString'
type FieldStringProps = InputStringProps & {
name?: string
label?: string
};
export default class FieldString extends React.Component<FieldStringProps> {
render() {
const {props} = this;
return <Block label={props.label}>
<InputString {...props} />
</Block>
}
}
@@ -1,20 +1,19 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import {latest} from '@maplibre/maplibre-gl-style-spec' import {latest} from '@maplibre/maplibre-gl-style-spec'
import Block from './Block' import Block from './Block'
import InputSelect from './InputSelect' import InputSelect from './InputSelect'
import InputString from './InputString' import InputString from './InputString'
export default class FieldType extends React.Component { type FieldTypeProps = {
static propTypes = { value: string
value: PropTypes.string.isRequired, wdKey?: string
wdKey: PropTypes.string, onChange(...args: unknown[]): unknown
onChange: PropTypes.func.isRequired, error?: unknown[] | undefined
error: PropTypes.object, disabled?: boolean
disabled: PropTypes.bool, };
}
export default class FieldType extends React.Component<FieldTypeProps> {
static defaultProps = { static defaultProps = {
disabled: false, disabled: false,
} }
-22
View File
@@ -1,22 +0,0 @@
import React, {Fragment} from 'react'
import PropTypes from 'prop-types'
import InputUrl from './InputUrl'
import Block from './Block'
export default class FieldUrl extends React.Component {
static propTypes = {
...InputUrl.propTypes,
}
render () {
const {props} = this;
return (
<Block label={this.props.label}>
<InputUrl {...props} />
</Block>
);
}
}
+22
View File
@@ -0,0 +1,22 @@
import React from 'react'
import InputUrl, {FieldUrlProps as InputUrlProps} from './InputUrl'
import Block from './Block'
type FieldUrlProps = InputUrlProps & {
label: string;
};
export default class FieldUrl extends React.Component<FieldUrlProps> {
render () {
const {props} = this;
return (
<Block label={this.props.label}>
<InputUrl {...props} />
</Block>
);
}
}
@@ -1,13 +1,23 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import FieldDocLabel from './FieldDocLabel' import FieldDocLabel from './FieldDocLabel'
import Doc from './Doc' import Doc from './Doc'
type FieldsetProps = {
label: string,
fieldSpec?: { doc?: string },
action?: string,
};
type FieldsetState = {
showDoc: boolean
};
let IDX = 0; let IDX = 0;
export default class Fieldset extends React.Component { export default class Fieldset extends React.Component<FieldsetProps, FieldsetState> {
constructor (props) { _labelId: string;
constructor (props: FieldsetProps) {
super(props); super(props);
this._labelId = `fieldset_label_${(IDX++)}`; this._labelId = `fieldset_label_${(IDX++)}`;
this.state = { this.state = {
@@ -15,15 +25,13 @@ export default class Fieldset extends React.Component {
} }
} }
onToggleDoc = (val) => { onToggleDoc = (val: boolean) => {
this.setState({ this.setState({
showDoc: val showDoc: val
}); });
} }
render () { render () {
const {props} = this;
return <div className="maputnik-input-block" role="group" aria-labelledby={this._labelId}> return <div className="maputnik-input-block" role="group" aria-labelledby={this._labelId}>
{this.props.fieldSpec && {this.props.fieldSpec &&
<div className="maputnik-input-block-label"> <div className="maputnik-input-block-label">
@@ -36,14 +44,14 @@ export default class Fieldset extends React.Component {
} }
{!this.props.fieldSpec && {!this.props.fieldSpec &&
<div className="maputnik-input-block-label"> <div className="maputnik-input-block-label">
{props.label} {this.props.label}
</div> </div>
} }
<div className="maputnik-input-block-action"> <div className="maputnik-input-block-action">
{this.props.action} {this.props.action}
</div> </div>
<div className="maputnik-input-block-content"> <div className="maputnik-input-block-content">
{props.children} {this.props.children}
</div> </div>
{this.props.fieldSpec && {this.props.fieldSpec &&
<div <div
@@ -1,14 +1,12 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import InputButton from './InputButton' import InputButton from './InputButton'
import {MdDelete} from 'react-icons/md' import {MdDelete} from 'react-icons/md'
export default class FilterEditorBlock extends React.Component { type FilterEditorBlockProps = {
static propTypes = { onDelete(...args: unknown[]): unknown
onDelete: PropTypes.func.isRequired, };
children: PropTypes.element.isRequired,
}
export default class FilterEditorBlock extends React.Component<FilterEditorBlockProps> {
render() { render() {
return <div className="maputnik-filter-editor-block"> return <div className="maputnik-filter-editor-block">
<div className="maputnik-filter-editor-block-action"> <div className="maputnik-filter-editor-block-action">
@@ -1,19 +1,18 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import IconLine from './IconLine.jsx' import IconLine from './IconLine'
import IconFill from './IconFill.jsx' import IconFill from './IconFill'
import IconSymbol from './IconSymbol.jsx' import IconSymbol from './IconSymbol'
import IconBackground from './IconBackground.jsx' import IconBackground from './IconBackground'
import IconCircle from './IconCircle.jsx' import IconCircle from './IconCircle'
import IconMissing from './IconMissing.jsx' import IconMissing from './IconMissing'
export default class IconLayer extends React.Component { type IconLayerProps = {
static propTypes = { type: string
type: PropTypes.string.isRequired, style?: object
style: PropTypes.object, };
}
export default class IconLayer extends React.Component<IconLayerProps> {
render() { render() {
const iconProps = { style: this.props.style } const iconProps = { style: this.props.style }
switch(this.props.type) { switch(this.props.type) {
@@ -1,24 +1,29 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import InputString from './InputString' import InputString from './InputString'
import InputNumber from './InputNumber' import InputNumber from './InputNumber'
export default class FieldArray extends React.Component { type FieldArrayProps = {
static propTypes = { value: string[]
value: PropTypes.array, type?: string
type: PropTypes.string, length?: number
length: PropTypes.number, default?: string[] | number[]
default: PropTypes.array, onChange?(...args: unknown[]): unknown
onChange: PropTypes.func, 'aria-label'?: string
'aria-label': PropTypes.string, label?: string
} };
type FieldArrayState = {
value: string[] | number[]
initialPropsValue: unknown[]
}
export default class FieldArray extends React.Component<FieldArrayProps, FieldArrayState> {
static defaultProps = { static defaultProps = {
value: [], value: [],
default: [], default: [],
} }
constructor (props) { constructor (props: FieldArrayProps) {
super(props); super(props);
this.state = { this.state = {
value: this.props.value.slice(0), value: this.props.value.slice(0),
@@ -27,8 +32,8 @@ export default class FieldArray extends React.Component {
}; };
} }
static getDerivedStateFromProps(props, state) { static getDerivedStateFromProps(props: FieldArrayProps, state: FieldArrayState) {
const value = []; const value: any[] = [];
const initialPropsValue = state.initialPropsValue.slice(0); const initialPropsValue = state.initialPropsValue.slice(0);
Array(props.length).fill(null).map((_, i) => { Array(props.length).fill(null).map((_, i) => {
@@ -47,24 +52,24 @@ export default class FieldArray extends React.Component {
}; };
} }
isComplete (value) { isComplete(value: unknown[]) {
return Array(this.props.length).fill(null).every((_, i) => { return Array(this.props.length).fill(null).every((_, i) => {
const val = value[i] const val = value[i]
return !(val === undefined || val === ""); return !(val === undefined || val === "");
}); });
} }
changeValue(idx, newValue) { changeValue(idx: number, newValue: string) {
const value = this.state.value.slice(0); const value = this.state.value.slice(0);
value[idx] = newValue; value[idx] = newValue;
this.setState({ this.setState({
value, value,
}, () => { }, () => {
if (this.isComplete(value)) { if (this.isComplete(value) && this.props.onChange) {
this.props.onChange(value); this.props.onChange(value);
} }
else { else if (this.props.onChange){
// Unset until complete // Unset until complete
this.props.onChange(undefined); this.props.onChange(undefined);
} }
@@ -85,8 +90,8 @@ export default class FieldArray extends React.Component {
if(this.props.type === 'number') { if(this.props.type === 'number') {
return <InputNumber return <InputNumber
key={i} key={i}
default={containsValues ? undefined : this.props.default[i]} default={containsValues || !this.props.default ? undefined : this.props.default[i] as number}
value={value[i]} value={value[i] as number}
required={containsValues ? true : false} required={containsValues ? true : false}
onChange={this.changeValue.bind(this, i)} onChange={this.changeValue.bind(this, i)}
aria-label={this.props['aria-label'] || this.props.label} aria-label={this.props['aria-label'] || this.props.label}
@@ -94,8 +99,8 @@ export default class FieldArray extends React.Component {
} else { } else {
return <InputString return <InputString
key={i} key={i}
default={containsValues ? undefined : this.props.default[i]} default={containsValues || !this.props.default ? undefined : this.props.default[i] as string}
value={value[i]} value={value[i] as string}
required={containsValues ? true : false} required={containsValues ? true : false}
onChange={this.changeValue.bind(this, i)} onChange={this.changeValue.bind(this, i)}
aria-label={this.props['aria-label'] || this.props.label} aria-label={this.props['aria-label'] || this.props.label}
@@ -1,24 +1,25 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames' import classnames from 'classnames'
import Autocomplete from 'react-autocomplete' import Autocomplete from 'react-autocomplete'
const MAX_HEIGHT = 140; const MAX_HEIGHT = 140;
export default class InputAutocomplete extends React.Component { type InputAutocompleteProps = {
static propTypes = { value?: string
value: PropTypes.string, options: any[]
options: PropTypes.array, onChange(...args: unknown[]): unknown
onChange: PropTypes.func, keepMenuWithinWindowBounds?: boolean
keepMenuWithinWindowBounds: PropTypes.bool, 'aria-label'?: string
'aria-label': PropTypes.string, };
}
export default class InputAutocomplete extends React.Component<InputAutocompleteProps> {
state = { state = {
maxHeight: MAX_HEIGHT maxHeight: MAX_HEIGHT
} }
autocompleteMenuEl: HTMLDivElement | null = null;
static defaultProps = { static defaultProps = {
onChange: () => {}, onChange: () => {},
options: [], options: [],
@@ -26,7 +27,7 @@ export default class InputAutocomplete extends React.Component {
calcMaxHeight() { calcMaxHeight() {
if(this.props.keepMenuWithinWindowBounds) { if(this.props.keepMenuWithinWindowBounds) {
const maxHeight = window.innerHeight - this.autocompleteMenuEl.getBoundingClientRect().top; const maxHeight = window.innerHeight - this.autocompleteMenuEl!.getBoundingClientRect().top;
const limitedMaxHeight = Math.min(maxHeight, MAX_HEIGHT); const limitedMaxHeight = Math.min(maxHeight, MAX_HEIGHT);
if(limitedMaxHeight != this.state.maxHeight) { if(limitedMaxHeight != this.state.maxHeight) {
@@ -45,7 +46,7 @@ export default class InputAutocomplete extends React.Component {
this.calcMaxHeight(); this.calcMaxHeight();
} }
onChange (v) { onChange(v: string) {
this.props.onChange(v === "" ? undefined : v); this.props.onChange(v === "" ? undefined : v);
} }
@@ -64,7 +65,7 @@ export default class InputAutocomplete extends React.Component {
}} }}
wrapperProps={{ wrapperProps={{
className: "maputnik-autocomplete", className: "maputnik-autocomplete",
style: null style: {}
}} }}
inputProps={{ inputProps={{
'aria-label': this.props['aria-label'], 'aria-label': this.props['aria-label'],
@@ -75,11 +76,12 @@ export default class InputAutocomplete extends React.Component {
items={this.props.options} items={this.props.options}
getItemValue={(item) => item[0]} getItemValue={(item) => item[0]}
onSelect={v => this.onChange(v)} onSelect={v => this.onChange(v)}
onChange={(e, v) => this.onChange(v)} onChange={(_e, v) => this.onChange(v)}
shouldItemRender={(item, value="") => { shouldItemRender={(item, value="") => {
if (typeof(value) === "string") { if (typeof(value) === "string") {
return item[0].toLowerCase().indexOf(value.toLowerCase()) > -1 return item[0].toLowerCase().indexOf(value.toLowerCase()) > -1
} }
return false
}} }}
renderItem={(item, isHighlighted) => ( renderItem={(item, isHighlighted) => (
<div <div
@@ -1,21 +1,20 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames' import classnames from 'classnames'
export default class InputButton extends React.Component { type InputButtonProps = {
static propTypes = { "data-wd-key"?: string
"data-wd-key": PropTypes.string, "aria-label"?: string
"aria-label": PropTypes.string, onClick?(...args: unknown[]): unknown
onClick: PropTypes.func, style?: object
style: PropTypes.object, className?: string
className: PropTypes.string, children?: React.ReactNode
children: PropTypes.node, disabled?: boolean
disabled: PropTypes.bool, type?: typeof HTMLButtonElement.prototype.type
type: PropTypes.string, id?: string
id: PropTypes.string, title?: string
title: PropTypes.string, };
}
export default class InputButton extends React.Component<InputButtonProps> {
render() { render() {
return <button return <button
id={this.props.id} id={this.props.id}
@@ -31,5 +30,4 @@ export default class InputButton extends React.Component {
{this.props.children} {this.props.children}
</button> </button>
} }
} }
@@ -1,13 +1,12 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
export default class InputCheckbox extends React.Component { type InputCheckboxProps = {
static propTypes = { value?: boolean
value: PropTypes.bool, style?: object
style: PropTypes.object, onChange(...args: unknown[]): unknown
onChange: PropTypes.func, };
}
export default class InputCheckbox extends React.Component<InputCheckboxProps> {
static defaultProps = { static defaultProps = {
value: false, value: false,
} }
@@ -35,5 +34,4 @@ export default class InputCheckbox extends React.Component {
</div> </div>
</div> </div>
} }
} }
@@ -1,36 +1,37 @@
import React from 'react' import React from 'react'
import Color from 'color' import Color from 'color'
import ChromePicker from 'react-color/lib/components/chrome/Chrome' import ChromePicker from 'react-color/lib/components/chrome/Chrome'
import PropTypes from 'prop-types' import {ColorResult} from 'react-color';
import lodash from 'lodash'; import lodash from 'lodash';
function formatColor(color) { function formatColor(color: ColorResult): string {
const rgb = color.rgb const rgb = color.rgb
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${rgb.a})` return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${rgb.a})`
} }
/*** Number fields with support for min, max and units and documentation*/ type InputColorProps = {
export default class InputColor extends React.Component { onChange(...args: unknown[]): unknown
static propTypes = { name?: string
onChange: PropTypes.func.isRequired, value?: string
name: PropTypes.string, doc?: string
value: PropTypes.string, style?: object
doc: PropTypes.string, default?: string
style: PropTypes.object, 'aria-label'?: string
default: PropTypes.string, };
'aria-label': PropTypes.string,
}
/*** Number fields with support for min, max and units and documentation*/
export default class InputColor extends React.Component<InputColorProps> {
state = { state = {
pickerOpened: false pickerOpened: false
} }
colorInput: HTMLInputElement | null = null;
constructor () { constructor (props: InputColorProps) {
super(); super(props);
this.onChangeNoCheck = lodash.throttle(this.onChangeNoCheck, 1000/30); this.onChangeNoCheck = lodash.throttle(this.onChangeNoCheck, 1000/30);
} }
onChangeNoCheck (v) { onChangeNoCheck(v: string) {
this.props.onChange(v); this.props.onChange(v);
} }
@@ -68,31 +69,31 @@ export default class InputColor extends React.Component {
} }
} }
onChange (v) { onChange (v: string) {
this.props.onChange(v === "" ? undefined : v); this.props.onChange(v === "" ? undefined : v);
} }
render() { render() {
const offset = this.calcPickerOffset() const offset = this.calcPickerOffset()
var currentColor = this.color.object() const currentColor = this.color.object();
currentColor = { const currentChromeColor = {
r: currentColor.r, r: currentColor.r,
g: currentColor.g, g: currentColor.g,
b: currentColor.b, b: currentColor.b,
// Rename alpha -> a for ChromePicker // Rename alpha -> a for ChromePicker
a: currentColor.alpha a: currentColor.alpha!
} }
const picker = <div const picker = <div
className="maputnik-color-picker-offset" className="maputnik-color-picker-offset"
style={{ style={{
position: 'fixed', position: 'fixed',
zIndex: 1, zIndex: 1,
left: offset.left, left: offset.left,
top: offset.top, top: offset.top,
}}> }}>
<ChromePicker <ChromePicker
color={currentColor} color={currentChromeColor}
onChange={c => this.onChangeNoCheck(formatColor(c))} onChange={c => this.onChangeNoCheck(formatColor(c))}
/> />
<div <div
@@ -1,10 +1,9 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import InputSelect from './InputSelect' import InputSelect from './InputSelect'
import InputMultiInput from './InputMultiInput' import InputMultiInput from './InputMultiInput'
function optionsLabelLength(options) { function optionsLabelLength(options: any[]) {
let sum = 0; let sum = 0;
options.forEach(([_, label]) => { options.forEach(([_, label]) => {
sum += label.length sum += label.length
@@ -13,18 +12,20 @@ function optionsLabelLength(options) {
} }
export default class InputEnum extends React.Component { export type InputEnumProps = {
static propTypes = { "data-wd-key"?: string
"data-wd-key": PropTypes.string, value?: string
value: PropTypes.string, style?: object
style: PropTypes.object, default?: string
default: PropTypes.string, name: string
name: PropTypes.string, onChange(...args: unknown[]): unknown
onChange: PropTypes.func, options: any[]
options: PropTypes.array, 'aria-label'?: string
'aria-label': PropTypes.string, label?: string
} };
export default class InputEnum extends React.Component<InputEnumProps> {
render() { render() {
const {options, value, onChange, name, label} = this.props; const {options, value, onChange, name, label} = this.props;
@@ -32,14 +33,14 @@ export default class InputEnum extends React.Component {
return <InputMultiInput return <InputMultiInput
name={name} name={name}
options={options} options={options}
value={value || this.props.default} value={(value || this.props.default)!}
onChange={onChange} onChange={onChange}
aria-label={this.props['aria-label'] || label} aria-label={this.props['aria-label'] || label}
/> />
} else { } else {
return <InputSelect return <InputSelect
options={options} options={options}
value={value || this.props.default} value={(value || this.props.default)!}
onChange={onChange} onChange={onChange}
aria-label={this.props['aria-label'] || label} aria-label={this.props['aria-label'] || label}
/> />
@@ -1,17 +1,17 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import InputAutocomplete from './InputAutocomplete' import InputAutocomplete from './InputAutocomplete'
export default class FieldFont extends React.Component { type FieldFontProps = {
static propTypes = { name: string
value: PropTypes.array, value?: string[]
default: PropTypes.array, default?: string[]
fonts: PropTypes.array, fonts?: unknown[]
style: PropTypes.object, style?: object
onChange: PropTypes.func.isRequired, onChange(...args: unknown[]): unknown
'aria-label': PropTypes.string, 'aria-label'?: string
} };
export default class FieldFont extends React.Component<FieldFontProps> {
static defaultProps = { static defaultProps = {
fonts: [] fonts: []
} }
@@ -28,7 +28,7 @@ export default class FieldFont extends React.Component {
} }
} }
changeFont(idx, newValue) { changeFont(idx: number, newValue: string) {
const changedValues = this.values.slice(0) const changedValues = this.values.slice(0)
changedValues[idx] = newValue changedValues[idx] = newValue
const filteredValues = changedValues const filteredValues = changedValues
@@ -46,7 +46,7 @@ export default class FieldFont extends React.Component {
<InputAutocomplete <InputAutocomplete
aria-label={this.props['aria-label'] || this.props.name} aria-label={this.props['aria-label'] || this.props.name}
value={value} value={value}
options={this.props.fonts.map(f => [f, f])} options={this.props.fonts?.map(f => [f, f])}
onChange={this.changeFont.bind(this, i)} onChange={this.changeFont.bind(this, i)}
/> />
</li> </li>
@@ -1,16 +1,15 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames' import classnames from 'classnames'
import InputButton from './InputButton'
export default class InputMultiInput extends React.Component { type InputMultiInputProps = {
static propTypes = { name: string
name: PropTypes.string.isRequired, value: string
value: PropTypes.string.isRequired, options: any[]
options: PropTypes.array.isRequired, onChange(...args: unknown[]): unknown
onChange: PropTypes.func.isRequired, 'aria-label'?: string
} };
export default class InputMultiInput extends React.Component<InputMultiInputProps> {
render() { render() {
let options = this.props.options let options = this.props.options
if(options.length > 0 && !Array.isArray(options[0])) { if(options.length > 0 && !Array.isArray(options[0])) {
@@ -25,7 +24,7 @@ export default class InputMultiInput extends React.Component {
> >
<input type="radio" <input type="radio"
name={this.props.name} name={this.props.name}
onChange={e => this.props.onChange(val)} onChange={_e => this.props.onChange(val)}
value={val} value={val}
checked={val === selectedValue} checked={val === selectedValue}
/> />
@@ -1,27 +1,35 @@
import React from 'react' import React, { BaseSyntheticEvent } from 'react'
import PropTypes from 'prop-types'
let IDX = 0; let IDX = 0;
export default class InputNumber extends React.Component { type InputNumberProps = {
static propTypes = { value?: number
value: PropTypes.number, default?: number
default: PropTypes.number, min?: number
min: PropTypes.number, max?: number
max: PropTypes.number, onChange?(...args: unknown[]): unknown
onChange: PropTypes.func, allowRange?: boolean
allowRange: PropTypes.bool, rangeStep?: number
rangeStep: PropTypes.number, wdKey?: string
wdKey: PropTypes.string, required?: boolean
required: PropTypes.bool, "aria-label"?: string
"aria-label": PropTypes.string, };
}
type InputNumberState = {
uuid: number
editing: boolean
editingRange?: boolean
value?: number
dirtyValue?: number
}
export default class InputNumber extends React.Component<InputNumberProps, InputNumberState> {
static defaultProps = { static defaultProps = {
rangeStep: 1 rangeStep: 1
} }
_keyboardEvent: boolean = false;
constructor(props) { constructor(props: InputNumberProps) {
super(props) super(props)
this.state = { this.state = {
uuid: IDX++, uuid: IDX++,
@@ -31,7 +39,7 @@ export default class InputNumber extends React.Component {
} }
} }
static getDerivedStateFromProps(props, state) { static getDerivedStateFromProps(props: InputNumberProps, state: InputNumberState) {
if (!state.editing && props.value !== state.value) { if (!state.editing && props.value !== state.value) {
return { return {
value: props.value, value: props.value,
@@ -41,16 +49,15 @@ export default class InputNumber extends React.Component {
return null; return null;
} }
changeValue(newValue) { changeValue(newValue: number | string | undefined) {
const value = (newValue === "" || newValue === undefined) ? const value = (newValue === "" || newValue === undefined) ?
undefined : undefined : +newValue;
parseFloat(newValue);
const hasChanged = this.props.value !== value; const hasChanged = this.props.value !== value;
if(this.isValid(value) && hasChanged) { if(this.isValid(value) && hasChanged) {
this.props.onChange(value) if (this.props.onChange) this.props.onChange(value)
this.setState({ this.setState({
value: newValue, value: value,
}); });
} }
else if (!this.isValid(value) && hasChanged) { else if (!this.isValid(value) && hasChanged) {
@@ -60,25 +67,25 @@ export default class InputNumber extends React.Component {
} }
this.setState({ this.setState({
dirtyValue: newValue === "" ? undefined : newValue, dirtyValue: newValue === "" ? undefined : value,
}) })
} }
isValid(v) { isValid(v: number | string | undefined) {
if (v === undefined) { if (v === undefined) {
return true; return true;
} }
const value = parseFloat(v) const value = +v;
if(isNaN(value)) { if(isNaN(value)) {
return false return false
} }
if(!isNaN(this.props.min) && value < this.props.min) { if(!isNaN(this.props.min!) && value < this.props.min!) {
return false return false
} }
if(!isNaN(this.props.max) && value > this.props.max) { if(!isNaN(this.props.max!) && value > this.props.max!) {
return false return false
} }
@@ -88,7 +95,7 @@ export default class InputNumber extends React.Component {
resetValue = () => { resetValue = () => {
this.setState({editing: false}); this.setState({editing: false});
// Reset explicitly to default value if value has been cleared // Reset explicitly to default value if value has been cleared
if(this.state.value === "") { if(!this.state.value) {
return; return;
} }
@@ -104,8 +111,8 @@ export default class InputNumber extends React.Component {
} }
} }
onChangeRange = (e) => { onChangeRange = (e: BaseSyntheticEvent<Event, HTMLInputElement, HTMLInputElement>) => {
let value = parseFloat(e.target.value, 10); let value = parseFloat(e.target.value);
const step = this.props.rangeStep; const step = this.props.rangeStep;
let dirtyValue = value; let dirtyValue = value;
@@ -119,11 +126,11 @@ export default class InputNumber extends React.Component {
// for example we might go from 13 to 13.23, however because we know // for example we might go from 13 to 13.23, however because we know
// that came from a keyboard event we always want to increase by a // that came from a keyboard event we always want to increase by a
// single step value. // single step value.
if (value < this.state.dirtyValue) { if (value < this.state.dirtyValue!) {
value = this.state.value - step; value = this.state.value! - step;
} }
else { else {
value = this.state.value + step value = this.state.value! + step
} }
dirtyValue = value; dirtyValue = value;
} }
@@ -140,10 +147,10 @@ export default class InputNumber extends React.Component {
this._keyboardEvent = false; this._keyboardEvent = false;
// Clamp between min/max // Clamp between min/max
value = Math.max(this.props.min, Math.min(this.props.max, value)); value = Math.max(this.props.min!, Math.min(this.props.max!, value));
this.setState({value, dirtyValue}); this.setState({value, dirtyValue});
this.props.onChange(value); if (this.props.onChange) this.props.onChange(value);
} }
render() { render() {
@@ -196,15 +203,15 @@ export default class InputNumber extends React.Component {
type="text" type="text"
spellCheck="false" spellCheck="false"
className="maputnik-number" className="maputnik-number"
placeholder={this.props.default} placeholder={this.props.default?.toString()}
value={inputValue === undefined ? "" : inputValue} value={inputValue === undefined ? "" : inputValue}
onFocus={e => { onFocus={_e => {
this.setState({editing: true}); this.setState({editing: true});
}} }}
onChange={e => { onChange={e => {
this.changeValue(e.target.value); this.changeValue(e.target.value);
}} }}
onBlur={e => { onBlur={_e => {
this.setState({editing: false}); this.setState({editing: false});
this.resetValue() this.resetValue()
}} }}
@@ -218,7 +225,7 @@ export default class InputNumber extends React.Component {
aria-label={this.props['aria-label']} aria-label={this.props['aria-label']}
spellCheck="false" spellCheck="false"
className="maputnik-number" className="maputnik-number"
placeholder={this.props.default} placeholder={this.props.default?.toString()}
value={value === undefined ? "" : value} value={value === undefined ? "" : value}
onChange={e => this.changeValue(e.target.value)} onChange={e => this.changeValue(e.target.value)}
onFocus={() => { onFocus={() => {
@@ -1,22 +1,20 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
export default class InputSelect extends React.Component {
static propTypes = {
value: PropTypes.string.isRequired,
"data-wd-key": PropTypes.string,
options: PropTypes.array.isRequired,
style: PropTypes.object,
onChange: PropTypes.func.isRequired,
title: PropTypes.string,
'aria-label': PropTypes.string,
}
type InputSelectProps = {
value: string
"data-wd-key"?: string
options: [string, any][] | string[]
style?: object
onChange(...args: unknown[]): unknown
title?: string
'aria-label'?: string
};
export default class InputSelect extends React.Component<InputSelectProps> {
render() { render() {
let options = this.props.options let options = this.props.options;
if(options.length > 0 && !Array.isArray(options[0])) { if(options.length > 0 && !Array.isArray(options[0])) {
options = options.map(v => [v, v]) options = options.map((v) => [v, v]) as [string, any][];
} }
return <select return <select
@@ -1,26 +1,30 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
export default class InputString extends React.Component { export type InputStringProps = {
static propTypes = { "data-wd-key"?: string
"data-wd-key": PropTypes.string, value?: string
value: PropTypes.string, style?: object
style: PropTypes.object, default?: string
default: PropTypes.string, onChange?(...args: unknown[]): unknown
onChange: PropTypes.func, onInput(...args: unknown[]): unknown
onInput: PropTypes.func, multi?: boolean
multi: PropTypes.bool, required?: boolean
required: PropTypes.bool, disabled?: boolean
disabled: PropTypes.bool, spellCheck?: boolean
spellCheck: PropTypes.bool, 'aria-label'?: string
'aria-label': PropTypes.string, };
}
type InputStringState = {
editing: boolean
value?: string
}
export default class InputString extends React.Component<InputStringProps, InputStringState> {
static defaultProps = { static defaultProps = {
onInput: () => {}, onInput: () => {},
} }
constructor(props) { constructor(props: InputStringProps) {
super(props) super(props)
this.state = { this.state = {
editing: false, editing: false,
@@ -28,7 +32,7 @@ export default class InputString extends React.Component {
} }
} }
static getDerivedStateFromProps(props, state) { static getDerivedStateFromProps(props: InputStringProps, state: InputStringState) {
if (!state.editing) { if (!state.editing) {
return { return {
value: props.value value: props.value
@@ -68,7 +72,7 @@ export default class InputString extends React.Component {
style: this.props.style, style: this.props.style,
value: this.state.value === undefined ? "" : this.state.value, value: this.state.value === undefined ? "" : this.state.value,
placeholder: this.props.default, placeholder: this.props.default,
onChange: e => { onChange: (e: React.BaseSyntheticEvent<Event, HTMLInputElement, HTMLInputElement>) => {
this.setState({ this.setState({
editing: true, editing: true,
value: e.target.value value: e.target.value
@@ -79,11 +83,11 @@ export default class InputString extends React.Component {
onBlur: () => { onBlur: () => {
if(this.state.value!==this.props.value) { if(this.state.value!==this.props.value) {
this.setState({editing: false}); this.setState({editing: false});
this.props.onChange(this.state.value); if (this.props.onChange) this.props.onChange(this.state.value);
} }
}, },
onKeyDown: (e) => { onKeyDown: (e) => {
if (e.keyCode === 13) { if (e.keyCode === 13 && this.props.onChange) {
this.props.onChange(this.state.value); this.props.onChange(this.state.value);
} }
}, },
@@ -1,16 +1,15 @@
import React, {Fragment} from 'react' import React from 'react'
import PropTypes from 'prop-types'
import InputString from './InputString' import InputString from './InputString'
import SmallError from './SmallError' import SmallError from './SmallError'
function validate (url) { function validate(url: string) {
if (url === "") { if (url === "") {
return; return;
} }
let error; let error;
const getProtocol = (url) => { const getProtocol = (url: string) => {
try { try {
const urlObj = new URL(url); const urlObj = new URL(url);
return urlObj.protocol; return urlObj.protocol;
@@ -48,38 +47,42 @@ function validate (url) {
return error; return error;
} }
export default class FieldUrl extends React.Component { export type FieldUrlProps = {
static propTypes = { "data-wd-key"?: string
"data-wd-key": PropTypes.string, value: string
value: PropTypes.string, style?: object
style: PropTypes.object, default?: string
default: PropTypes.string, onChange(...args: unknown[]): unknown
onChange: PropTypes.func, onInput(...args: unknown[]): unknown
onInput: PropTypes.func, multi?: boolean
multi: PropTypes.bool, required?: boolean
required: PropTypes.bool, 'aria-label'?: string
'aria-label': PropTypes.string, };
}
type FieldUrlState = {
error?: React.ReactNode
}
export default class FieldUrl extends React.Component<FieldUrlProps, FieldUrlState> {
static defaultProps = { static defaultProps = {
onInput: () => {}, onInput: () => {},
} }
constructor (props) { constructor (props: FieldUrlProps) {
super(props); super(props);
this.state = { this.state = {
error: validate(props.value) error: validate(props.value)
}; };
} }
onInput = (url) => { onInput = (url: string) => {
this.setState({ this.setState({
error: validate(url) error: validate(url)
}); });
this.props.onInput(url); this.props.onInput(url);
} }
onChange = (url) => { onChange = (url: string) => {
this.setState({ this.setState({
error: validate(url) error: validate(url)
}); });
@@ -1,22 +1,21 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import {MdClose} from 'react-icons/md' import {MdClose} from 'react-icons/md'
import AriaModal from 'react-aria-modal' import AriaModal from 'react-aria-modal'
import classnames from 'classnames'; import classnames from 'classnames';
export default class Modal extends React.Component { type ModalProps = {
static propTypes = { "data-wd-key"?: string
"data-wd-key": PropTypes.string, isOpen: boolean
isOpen: PropTypes.bool.isRequired, title: string
title: PropTypes.string.isRequired, onOpenToggle(...args: unknown[]): unknown
onOpenToggle: PropTypes.func.isRequired, underlayClickExits?: boolean
children: PropTypes.node, underlayProps?: any
underlayClickExits: PropTypes.bool, className?: string
underlayProps: PropTypes.object, };
className: PropTypes.string,
}
export default class Modal extends React.Component<ModalProps> {
static defaultProps = { static defaultProps = {
underlayClickExits: true underlayClickExits: true
} }
@@ -24,7 +23,7 @@ export default class Modal extends React.Component {
// See <https://github.com/maputnik/editor/issues/416> // See <https://github.com/maputnik/editor/issues/416>
onClose = () => { onClose = () => {
if (document.activeElement) { if (document.activeElement) {
document.activeElement.blur(); (document.activeElement as HTMLElement).blur();
} }
setTimeout(() => { setTimeout(() => {
@@ -37,6 +36,7 @@ export default class Modal extends React.Component {
return <AriaModal return <AriaModal
titleText={this.props.title} titleText={this.props.title}
underlayClickExits={this.props.underlayClickExits} underlayClickExits={this.props.underlayClickExits}
// @ts-ignore
underlayProps={this.props.underlayProps} underlayProps={this.props.underlayProps}
data-wd-key={this.props["data-wd-key"]} data-wd-key={this.props["data-wd-key"]}
verticallyCenter={true} verticallyCenter={true}
-15
View File
@@ -1,15 +0,0 @@
import React from 'react'
import PropTypes from 'prop-types'
export default class ScrollContainer extends React.Component {
static propTypes = {
children: PropTypes.node
}
render() {
return <div className="maputnik-scroll-container">
{this.props.children}
</div>
}
}
+14
View File
@@ -0,0 +1,14 @@
import React from 'react'
type ScrollContainerProps = {
children?: React.ReactNode
};
export default class ScrollContainer extends React.Component<ScrollContainerProps> {
render() {
return <div className="maputnik-scroll-container">
{this.props.children}
</div>
}
}
@@ -1,13 +1,13 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import './SmallError.scss'; import './SmallError.scss';
export default class SmallError extends React.Component { type SmallErrorProps = {
static propTypes = { children?: React.ReactNode
children: PropTypes.node, };
}
export default class SmallError extends React.Component<SmallErrorProps> {
render () { render () {
return ( return (
<div className="SmallError"> <div className="SmallError">
@@ -15,5 +15,4 @@ export default class SmallError extends React.Component {
</div> </div>
); );
} }
} }