mirror of
https://github.com/maputnik/editor.git
synced 2026-09-01 01:47:26 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 732581c39e | |||
| f435ab79c1 | |||
| 50226a9b2e | |||
| e5688fd9a5 | |||
| 0e39476bd9 | |||
| 19fc3970a9 | |||
| 1a09de238a | |||
| 66a0ee5d4e |
Generated
+75
@@ -67,11 +67,16 @@
|
||||
"@storybook/react": "^7.6.5",
|
||||
"@storybook/react-vite": "^7.6.5",
|
||||
"@storybook/theming": "^7.6.5",
|
||||
"@types/color": "^3.0.6",
|
||||
"@types/cors": "^2.8.17",
|
||||
"@types/lodash.isequal": "^4.5.8",
|
||||
"@types/lodash.throttle": "^4.1.9",
|
||||
"@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-icon-base": "^2.1.6",
|
||||
"@types/uuid": "^9.0.7",
|
||||
"@vitejs/plugin-react": "^4.2.0",
|
||||
"cors": "^2.8.5",
|
||||
@@ -4583,6 +4588,30 @@
|
||||
"@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": {
|
||||
"version": "3.4.38",
|
||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
|
||||
@@ -4831,6 +4860,34 @@
|
||||
"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": {
|
||||
"version": "16.9.24",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.24.tgz",
|
||||
@@ -4840,6 +4897,24 @@
|
||||
"@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": {
|
||||
"version": "1.20.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz",
|
||||
|
||||
@@ -96,11 +96,16 @@
|
||||
"@storybook/react": "^7.6.5",
|
||||
"@storybook/react-vite": "^7.6.5",
|
||||
"@storybook/theming": "^7.6.5",
|
||||
"@types/color": "^3.0.6",
|
||||
"@types/cors": "^2.8.17",
|
||||
"@types/lodash.isequal": "^4.5.8",
|
||||
"@types/lodash.throttle": "^4.1.9",
|
||||
"@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-icon-base": "^2.1.6",
|
||||
"@types/uuid": "^9.0.7",
|
||||
"@vitejs/plugin-react": "^4.2.0",
|
||||
"cors": "^2.8.5",
|
||||
|
||||
@@ -1,40 +1,43 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import React, {SyntheticEvent} from 'react'
|
||||
import classnames from 'classnames'
|
||||
import FieldDocLabel from './FieldDocLabel'
|
||||
import Doc from './Doc'
|
||||
|
||||
|
||||
/** Wrap a component with a label */
|
||||
export default class Block extends React.Component {
|
||||
static propTypes = {
|
||||
"data-wd-key": PropTypes.string,
|
||||
label: PropTypes.oneOfType([
|
||||
PropTypes.string,
|
||||
PropTypes.element,
|
||||
]),
|
||||
action: PropTypes.element,
|
||||
children: PropTypes.node.isRequired,
|
||||
style: PropTypes.object,
|
||||
onChange: PropTypes.func,
|
||||
fieldSpec: PropTypes.object,
|
||||
wideMode: PropTypes.bool,
|
||||
error: PropTypes.array,
|
||||
}
|
||||
type BlockProps = {
|
||||
"data-wd-key"?: string
|
||||
label?: string
|
||||
action?: React.ReactElement
|
||||
style?: object
|
||||
onChange?(...args: unknown[]): unknown
|
||||
fieldSpec?: object
|
||||
wideMode?: boolean
|
||||
error?: unknown[]
|
||||
};
|
||||
|
||||
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);
|
||||
this.state = {
|
||||
showDoc: false,
|
||||
}
|
||||
}
|
||||
|
||||
onChange(e) {
|
||||
onChange(e: React.BaseSyntheticEvent<Event, HTMLInputElement, HTMLInputElement>) {
|
||||
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({
|
||||
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
|
||||
* never be closed once open.
|
||||
*/
|
||||
onLabelClick = (event) => {
|
||||
onLabelClick = (event: SyntheticEvent<any, any>) => {
|
||||
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) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
event.preventDefault();
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
render() {
|
||||
const errors = [].concat(this.props.error || []);
|
||||
|
||||
return <label style={this.props.style}
|
||||
data-wd-key={this.props["data-wd-key"]}
|
||||
className={classnames({
|
||||
@@ -1,24 +1,33 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
export default class Doc extends React.Component {
|
||||
static propTypes = {
|
||||
fieldSpec: PropTypes.object.isRequired,
|
||||
const headers = {
|
||||
js: "JS",
|
||||
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 () {
|
||||
const {fieldSpec} = this.props;
|
||||
|
||||
const {doc, values} = fieldSpec;
|
||||
const sdkSupport = fieldSpec['sdk-support'];
|
||||
|
||||
const headers = {
|
||||
js: "JS",
|
||||
android: "Android",
|
||||
ios: "iOS",
|
||||
macos: "macOS",
|
||||
};
|
||||
|
||||
const renderValues = (
|
||||
!!values &&
|
||||
// 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 (
|
||||
<tr key={key}>
|
||||
<td>{key}</td>
|
||||
{Object.keys(headers).map(k => {
|
||||
const value = supportObj[k];
|
||||
{Object.keys(headers).map((k) => {
|
||||
if (supportObj.hasOwnProperty(k)) {
|
||||
return <td key={k}>{supportObj[k]}</td>;
|
||||
return <td key={k}>{supportObj[k as keyof typeof headers]}</td>;
|
||||
}
|
||||
else {
|
||||
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 PropTypes from 'prop-types'
|
||||
|
||||
import {MdInfoOutline, MdHighlightOff} from 'react-icons/md'
|
||||
|
||||
export default class FieldDocLabel extends React.Component {
|
||||
static propTypes = {
|
||||
label: PropTypes.oneOfType([
|
||||
PropTypes.object,
|
||||
PropTypes.string
|
||||
]).isRequired,
|
||||
fieldSpec: PropTypes.object,
|
||||
onToggleDoc: PropTypes.func,
|
||||
type FieldDocLabelProps = {
|
||||
label: object | string | undefined
|
||||
fieldSpec?: {
|
||||
doc?: string
|
||||
}
|
||||
onToggleDoc?(...args: unknown[]): unknown
|
||||
};
|
||||
|
||||
constructor (props) {
|
||||
type FieldDocLabelState = {
|
||||
open: boolean
|
||||
};
|
||||
|
||||
export default class FieldDocLabel extends React.Component<FieldDocLabelProps, FieldDocLabelState> {
|
||||
constructor (props: FieldDocLabelProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
open: false,
|
||||
}
|
||||
}
|
||||
|
||||
onToggleDoc = (open) => {
|
||||
onToggleDoc = (open: boolean) => {
|
||||
this.setState({
|
||||
open,
|
||||
}, () => {
|
||||
@@ -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>
|
||||
}
|
||||
}
|
||||
@@ -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 PropTypes from 'prop-types'
|
||||
|
||||
import {latest} from '@maplibre/maplibre-gl-style-spec'
|
||||
import Block from './Block'
|
||||
import InputString from './InputString'
|
||||
|
||||
export default class FieldId extends React.Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.string.isRequired,
|
||||
wdKey: PropTypes.string.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
error: PropTypes.object,
|
||||
}
|
||||
type FieldIdProps = {
|
||||
value: string
|
||||
wdKey: string
|
||||
onChange(...args: unknown[]): unknown
|
||||
error?: unknown[]
|
||||
};
|
||||
|
||||
export default class FieldId extends React.Component<FieldIdProps> {
|
||||
render() {
|
||||
return <Block label={"ID"} fieldSpec={latest.layer.id}
|
||||
data-wd-key={this.props.wdKey}
|
||||
@@ -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>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 PropTypes from 'prop-types'
|
||||
|
||||
import {latest} from '@maplibre/maplibre-gl-style-spec'
|
||||
import Block from './Block'
|
||||
import InputSelect from './InputSelect'
|
||||
import InputString from './InputString'
|
||||
|
||||
export default class FieldType extends React.Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.string.isRequired,
|
||||
wdKey: PropTypes.string,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
error: PropTypes.object,
|
||||
disabled: PropTypes.bool,
|
||||
}
|
||||
type FieldTypeProps = {
|
||||
value: string
|
||||
wdKey?: string
|
||||
onChange(...args: unknown[]): unknown
|
||||
error?: unknown[] | undefined
|
||||
disabled?: boolean
|
||||
};
|
||||
|
||||
export default class FieldType extends React.Component<FieldTypeProps> {
|
||||
static defaultProps = {
|
||||
disabled: false,
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 PropTypes from 'prop-types'
|
||||
import FieldDocLabel from './FieldDocLabel'
|
||||
import Doc from './Doc'
|
||||
|
||||
type FieldsetProps = {
|
||||
label: string,
|
||||
fieldSpec?: { doc?: string },
|
||||
action?: string,
|
||||
};
|
||||
|
||||
type FieldsetState = {
|
||||
showDoc: boolean
|
||||
};
|
||||
|
||||
let IDX = 0;
|
||||
|
||||
export default class Fieldset extends React.Component {
|
||||
constructor (props) {
|
||||
export default class Fieldset extends React.Component<FieldsetProps, FieldsetState> {
|
||||
_labelId: string;
|
||||
|
||||
constructor (props: FieldsetProps) {
|
||||
super(props);
|
||||
this._labelId = `fieldset_label_${(IDX++)}`;
|
||||
this.state = {
|
||||
@@ -15,15 +25,13 @@ export default class Fieldset extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
onToggleDoc = (val) => {
|
||||
onToggleDoc = (val: boolean) => {
|
||||
this.setState({
|
||||
showDoc: val
|
||||
});
|
||||
}
|
||||
|
||||
render () {
|
||||
const {props} = this;
|
||||
|
||||
return <div className="maputnik-input-block" role="group" aria-labelledby={this._labelId}>
|
||||
{this.props.fieldSpec &&
|
||||
<div className="maputnik-input-block-label">
|
||||
@@ -36,14 +44,14 @@ export default class Fieldset extends React.Component {
|
||||
}
|
||||
{!this.props.fieldSpec &&
|
||||
<div className="maputnik-input-block-label">
|
||||
{props.label}
|
||||
{this.props.label}
|
||||
</div>
|
||||
}
|
||||
<div className="maputnik-input-block-action">
|
||||
{this.props.action}
|
||||
</div>
|
||||
<div className="maputnik-input-block-content">
|
||||
{props.children}
|
||||
{this.props.children}
|
||||
</div>
|
||||
{this.props.fieldSpec &&
|
||||
<div
|
||||
@@ -1,14 +1,12 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import InputButton from './InputButton'
|
||||
import {MdDelete} from 'react-icons/md'
|
||||
|
||||
export default class FilterEditorBlock extends React.Component {
|
||||
static propTypes = {
|
||||
onDelete: PropTypes.func.isRequired,
|
||||
children: PropTypes.element.isRequired,
|
||||
}
|
||||
type FilterEditorBlockProps = {
|
||||
onDelete(...args: unknown[]): unknown
|
||||
};
|
||||
|
||||
export default class FilterEditorBlock extends React.Component<FilterEditorBlockProps> {
|
||||
render() {
|
||||
return <div className="maputnik-filter-editor-block">
|
||||
<div className="maputnik-filter-editor-block-action">
|
||||
@@ -1,19 +1,18 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import IconLine from './IconLine.jsx'
|
||||
import IconFill from './IconFill.jsx'
|
||||
import IconSymbol from './IconSymbol.jsx'
|
||||
import IconBackground from './IconBackground.jsx'
|
||||
import IconCircle from './IconCircle.jsx'
|
||||
import IconMissing from './IconMissing.jsx'
|
||||
import IconLine from './IconLine'
|
||||
import IconFill from './IconFill'
|
||||
import IconSymbol from './IconSymbol'
|
||||
import IconBackground from './IconBackground'
|
||||
import IconCircle from './IconCircle'
|
||||
import IconMissing from './IconMissing'
|
||||
|
||||
export default class IconLayer extends React.Component {
|
||||
static propTypes = {
|
||||
type: PropTypes.string.isRequired,
|
||||
style: PropTypes.object,
|
||||
}
|
||||
type IconLayerProps = {
|
||||
type: string
|
||||
style?: object
|
||||
};
|
||||
|
||||
export default class IconLayer extends React.Component<IconLayerProps> {
|
||||
render() {
|
||||
const iconProps = { style: this.props.style }
|
||||
switch(this.props.type) {
|
||||
@@ -1,24 +1,29 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import InputString from './InputString'
|
||||
import InputNumber from './InputNumber'
|
||||
|
||||
export default class FieldArray extends React.Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.array,
|
||||
type: PropTypes.string,
|
||||
length: PropTypes.number,
|
||||
default: PropTypes.array,
|
||||
onChange: PropTypes.func,
|
||||
'aria-label': PropTypes.string,
|
||||
}
|
||||
type FieldArrayProps = {
|
||||
value: string[]
|
||||
type?: string
|
||||
length?: number
|
||||
default?: string[] | number[]
|
||||
onChange?(...args: unknown[]): unknown
|
||||
'aria-label'?: string
|
||||
label?: string
|
||||
};
|
||||
|
||||
type FieldArrayState = {
|
||||
value: string[] | number[]
|
||||
initialPropsValue: unknown[]
|
||||
}
|
||||
|
||||
export default class FieldArray extends React.Component<FieldArrayProps, FieldArrayState> {
|
||||
static defaultProps = {
|
||||
value: [],
|
||||
default: [],
|
||||
}
|
||||
|
||||
constructor (props) {
|
||||
constructor (props: FieldArrayProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
value: this.props.value.slice(0),
|
||||
@@ -27,8 +32,8 @@ export default class FieldArray extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(props, state) {
|
||||
const value = [];
|
||||
static getDerivedStateFromProps(props: FieldArrayProps, state: FieldArrayState) {
|
||||
const value: any[] = [];
|
||||
const initialPropsValue = state.initialPropsValue.slice(0);
|
||||
|
||||
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) => {
|
||||
const val = value[i]
|
||||
return !(val === undefined || val === "");
|
||||
});
|
||||
}
|
||||
|
||||
changeValue(idx, newValue) {
|
||||
changeValue(idx: number, newValue: string) {
|
||||
const value = this.state.value.slice(0);
|
||||
value[idx] = newValue;
|
||||
|
||||
this.setState({
|
||||
value,
|
||||
}, () => {
|
||||
if (this.isComplete(value)) {
|
||||
if (this.isComplete(value) && this.props.onChange) {
|
||||
this.props.onChange(value);
|
||||
}
|
||||
else {
|
||||
else if (this.props.onChange){
|
||||
// Unset until complete
|
||||
this.props.onChange(undefined);
|
||||
}
|
||||
@@ -85,8 +90,8 @@ export default class FieldArray extends React.Component {
|
||||
if(this.props.type === 'number') {
|
||||
return <InputNumber
|
||||
key={i}
|
||||
default={containsValues ? undefined : this.props.default[i]}
|
||||
value={value[i]}
|
||||
default={containsValues || !this.props.default ? undefined : this.props.default[i] as number}
|
||||
value={value[i] as number}
|
||||
required={containsValues ? true : false}
|
||||
onChange={this.changeValue.bind(this, i)}
|
||||
aria-label={this.props['aria-label'] || this.props.label}
|
||||
@@ -94,8 +99,8 @@ export default class FieldArray extends React.Component {
|
||||
} else {
|
||||
return <InputString
|
||||
key={i}
|
||||
default={containsValues ? undefined : this.props.default[i]}
|
||||
value={value[i]}
|
||||
default={containsValues || !this.props.default ? undefined : this.props.default[i] as string}
|
||||
value={value[i] as string}
|
||||
required={containsValues ? true : false}
|
||||
onChange={this.changeValue.bind(this, i)}
|
||||
aria-label={this.props['aria-label'] || this.props.label}
|
||||
@@ -1,24 +1,25 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import classnames from 'classnames'
|
||||
import Autocomplete from 'react-autocomplete'
|
||||
|
||||
|
||||
const MAX_HEIGHT = 140;
|
||||
|
||||
export default class InputAutocomplete extends React.Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.string,
|
||||
options: PropTypes.array,
|
||||
onChange: PropTypes.func,
|
||||
keepMenuWithinWindowBounds: PropTypes.bool,
|
||||
'aria-label': PropTypes.string,
|
||||
}
|
||||
type InputAutocompleteProps = {
|
||||
value?: string
|
||||
options: any[]
|
||||
onChange(...args: unknown[]): unknown
|
||||
keepMenuWithinWindowBounds?: boolean
|
||||
'aria-label'?: string
|
||||
};
|
||||
|
||||
export default class InputAutocomplete extends React.Component<InputAutocompleteProps> {
|
||||
state = {
|
||||
maxHeight: MAX_HEIGHT
|
||||
}
|
||||
|
||||
autocompleteMenuEl: HTMLDivElement | null = null;
|
||||
|
||||
static defaultProps = {
|
||||
onChange: () => {},
|
||||
options: [],
|
||||
@@ -26,7 +27,7 @@ export default class InputAutocomplete extends React.Component {
|
||||
|
||||
calcMaxHeight() {
|
||||
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);
|
||||
|
||||
if(limitedMaxHeight != this.state.maxHeight) {
|
||||
@@ -45,7 +46,7 @@ export default class InputAutocomplete extends React.Component {
|
||||
this.calcMaxHeight();
|
||||
}
|
||||
|
||||
onChange (v) {
|
||||
onChange(v: string) {
|
||||
this.props.onChange(v === "" ? undefined : v);
|
||||
}
|
||||
|
||||
@@ -64,7 +65,7 @@ export default class InputAutocomplete extends React.Component {
|
||||
}}
|
||||
wrapperProps={{
|
||||
className: "maputnik-autocomplete",
|
||||
style: null
|
||||
style: {}
|
||||
}}
|
||||
inputProps={{
|
||||
'aria-label': this.props['aria-label'],
|
||||
@@ -75,11 +76,12 @@ export default class InputAutocomplete extends React.Component {
|
||||
items={this.props.options}
|
||||
getItemValue={(item) => item[0]}
|
||||
onSelect={v => this.onChange(v)}
|
||||
onChange={(e, v) => this.onChange(v)}
|
||||
onChange={(_e, v) => this.onChange(v)}
|
||||
shouldItemRender={(item, value="") => {
|
||||
if (typeof(value) === "string") {
|
||||
return item[0].toLowerCase().indexOf(value.toLowerCase()) > -1
|
||||
}
|
||||
return false
|
||||
}}
|
||||
renderItem={(item, isHighlighted) => (
|
||||
<div
|
||||
@@ -1,21 +1,20 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import classnames from 'classnames'
|
||||
|
||||
export default class InputButton extends React.Component {
|
||||
static propTypes = {
|
||||
"data-wd-key": PropTypes.string,
|
||||
"aria-label": PropTypes.string,
|
||||
onClick: PropTypes.func,
|
||||
style: PropTypes.object,
|
||||
className: PropTypes.string,
|
||||
children: PropTypes.node,
|
||||
disabled: PropTypes.bool,
|
||||
type: PropTypes.string,
|
||||
id: PropTypes.string,
|
||||
title: PropTypes.string,
|
||||
}
|
||||
type InputButtonProps = {
|
||||
"data-wd-key"?: string
|
||||
"aria-label"?: string
|
||||
onClick?(...args: unknown[]): unknown
|
||||
style?: object
|
||||
className?: string
|
||||
children?: React.ReactNode
|
||||
disabled?: boolean
|
||||
type?: typeof HTMLButtonElement.prototype.type
|
||||
id?: string
|
||||
title?: string
|
||||
};
|
||||
|
||||
export default class InputButton extends React.Component<InputButtonProps> {
|
||||
render() {
|
||||
return <button
|
||||
id={this.props.id}
|
||||
@@ -31,5 +30,4 @@ export default class InputButton extends React.Component {
|
||||
{this.props.children}
|
||||
</button>
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
export default class InputCheckbox extends React.Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.bool,
|
||||
style: PropTypes.object,
|
||||
onChange: PropTypes.func,
|
||||
}
|
||||
type InputCheckboxProps = {
|
||||
value?: boolean
|
||||
style?: object
|
||||
onChange(...args: unknown[]): unknown
|
||||
};
|
||||
|
||||
export default class InputCheckbox extends React.Component<InputCheckboxProps> {
|
||||
static defaultProps = {
|
||||
value: false,
|
||||
}
|
||||
@@ -35,5 +34,4 @@ export default class InputCheckbox extends React.Component {
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,36 +1,37 @@
|
||||
import React from 'react'
|
||||
import Color from 'color'
|
||||
import ChromePicker from 'react-color/lib/components/chrome/Chrome'
|
||||
import PropTypes from 'prop-types'
|
||||
import {ColorResult} from 'react-color';
|
||||
import lodash from 'lodash';
|
||||
|
||||
function formatColor(color) {
|
||||
function formatColor(color: ColorResult): string {
|
||||
const rgb = color.rgb
|
||||
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${rgb.a})`
|
||||
}
|
||||
|
||||
/*** Number fields with support for min, max and units and documentation*/
|
||||
export default class InputColor extends React.Component {
|
||||
static propTypes = {
|
||||
onChange: PropTypes.func.isRequired,
|
||||
name: PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
doc: PropTypes.string,
|
||||
style: PropTypes.object,
|
||||
default: PropTypes.string,
|
||||
'aria-label': PropTypes.string,
|
||||
}
|
||||
type InputColorProps = {
|
||||
onChange(...args: unknown[]): unknown
|
||||
name?: string
|
||||
value?: string
|
||||
doc?: string
|
||||
style?: object
|
||||
default?: string
|
||||
'aria-label'?: string
|
||||
};
|
||||
|
||||
/*** Number fields with support for min, max and units and documentation*/
|
||||
export default class InputColor extends React.Component<InputColorProps> {
|
||||
state = {
|
||||
pickerOpened: false
|
||||
}
|
||||
colorInput: HTMLInputElement | null = null;
|
||||
|
||||
constructor () {
|
||||
super();
|
||||
constructor (props: InputColorProps) {
|
||||
super(props);
|
||||
this.onChangeNoCheck = lodash.throttle(this.onChangeNoCheck, 1000/30);
|
||||
}
|
||||
|
||||
onChangeNoCheck (v) {
|
||||
onChangeNoCheck(v: string) {
|
||||
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);
|
||||
}
|
||||
|
||||
render() {
|
||||
const offset = this.calcPickerOffset()
|
||||
var currentColor = this.color.object()
|
||||
currentColor = {
|
||||
const currentColor = this.color.object();
|
||||
const currentChromeColor = {
|
||||
r: currentColor.r,
|
||||
g: currentColor.g,
|
||||
b: currentColor.b,
|
||||
// Rename alpha -> a for ChromePicker
|
||||
a: currentColor.alpha
|
||||
a: currentColor.alpha!
|
||||
}
|
||||
|
||||
const picker = <div
|
||||
className="maputnik-color-picker-offset"
|
||||
style={{
|
||||
position: 'fixed',
|
||||
zIndex: 1,
|
||||
position: 'fixed',
|
||||
zIndex: 1,
|
||||
left: offset.left,
|
||||
top: offset.top,
|
||||
}}>
|
||||
<ChromePicker
|
||||
color={currentColor}
|
||||
color={currentChromeColor}
|
||||
onChange={c => this.onChangeNoCheck(formatColor(c))}
|
||||
/>
|
||||
<div
|
||||
@@ -1,10 +1,9 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import InputSelect from './InputSelect'
|
||||
import InputMultiInput from './InputMultiInput'
|
||||
|
||||
|
||||
function optionsLabelLength(options) {
|
||||
function optionsLabelLength(options: any[]) {
|
||||
let sum = 0;
|
||||
options.forEach(([_, label]) => {
|
||||
sum += label.length
|
||||
@@ -13,18 +12,20 @@ function optionsLabelLength(options) {
|
||||
}
|
||||
|
||||
|
||||
export default class InputEnum extends React.Component {
|
||||
static propTypes = {
|
||||
"data-wd-key": PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
style: PropTypes.object,
|
||||
default: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
options: PropTypes.array,
|
||||
'aria-label': PropTypes.string,
|
||||
}
|
||||
export type InputEnumProps = {
|
||||
"data-wd-key"?: string
|
||||
value?: string
|
||||
style?: object
|
||||
default?: string
|
||||
name: string
|
||||
onChange(...args: unknown[]): unknown
|
||||
options: any[]
|
||||
'aria-label'?: string
|
||||
label?: string
|
||||
};
|
||||
|
||||
|
||||
export default class InputEnum extends React.Component<InputEnumProps> {
|
||||
render() {
|
||||
const {options, value, onChange, name, label} = this.props;
|
||||
|
||||
@@ -32,14 +33,14 @@ export default class InputEnum extends React.Component {
|
||||
return <InputMultiInput
|
||||
name={name}
|
||||
options={options}
|
||||
value={value || this.props.default}
|
||||
value={(value || this.props.default)!}
|
||||
onChange={onChange}
|
||||
aria-label={this.props['aria-label'] || label}
|
||||
/>
|
||||
} else {
|
||||
return <InputSelect
|
||||
options={options}
|
||||
value={value || this.props.default}
|
||||
value={(value || this.props.default)!}
|
||||
onChange={onChange}
|
||||
aria-label={this.props['aria-label'] || label}
|
||||
/>
|
||||
@@ -1,17 +1,17 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import InputAutocomplete from './InputAutocomplete'
|
||||
|
||||
export default class FieldFont extends React.Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.array,
|
||||
default: PropTypes.array,
|
||||
fonts: PropTypes.array,
|
||||
style: PropTypes.object,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
'aria-label': PropTypes.string,
|
||||
}
|
||||
type FieldFontProps = {
|
||||
name: string
|
||||
value?: string[]
|
||||
default?: string[]
|
||||
fonts?: unknown[]
|
||||
style?: object
|
||||
onChange(...args: unknown[]): unknown
|
||||
'aria-label'?: string
|
||||
};
|
||||
|
||||
export default class FieldFont extends React.Component<FieldFontProps> {
|
||||
static defaultProps = {
|
||||
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)
|
||||
changedValues[idx] = newValue
|
||||
const filteredValues = changedValues
|
||||
@@ -46,7 +46,7 @@ export default class FieldFont extends React.Component {
|
||||
<InputAutocomplete
|
||||
aria-label={this.props['aria-label'] || this.props.name}
|
||||
value={value}
|
||||
options={this.props.fonts.map(f => [f, f])}
|
||||
options={this.props.fonts?.map(f => [f, f])}
|
||||
onChange={this.changeFont.bind(this, i)}
|
||||
/>
|
||||
</li>
|
||||
@@ -1,16 +1,15 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import classnames from 'classnames'
|
||||
import InputButton from './InputButton'
|
||||
|
||||
export default class InputMultiInput extends React.Component {
|
||||
static propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
value: PropTypes.string.isRequired,
|
||||
options: PropTypes.array.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
}
|
||||
type InputMultiInputProps = {
|
||||
name: string
|
||||
value: string
|
||||
options: any[]
|
||||
onChange(...args: unknown[]): unknown
|
||||
'aria-label'?: string
|
||||
};
|
||||
|
||||
export default class InputMultiInput extends React.Component<InputMultiInputProps> {
|
||||
render() {
|
||||
let options = this.props.options
|
||||
if(options.length > 0 && !Array.isArray(options[0])) {
|
||||
@@ -25,7 +24,7 @@ export default class InputMultiInput extends React.Component {
|
||||
>
|
||||
<input type="radio"
|
||||
name={this.props.name}
|
||||
onChange={e => this.props.onChange(val)}
|
||||
onChange={_e => this.props.onChange(val)}
|
||||
value={val}
|
||||
checked={val === selectedValue}
|
||||
/>
|
||||
@@ -1,27 +1,35 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import React, { BaseSyntheticEvent } from 'react'
|
||||
|
||||
let IDX = 0;
|
||||
|
||||
export default class InputNumber extends React.Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.number,
|
||||
default: PropTypes.number,
|
||||
min: PropTypes.number,
|
||||
max: PropTypes.number,
|
||||
onChange: PropTypes.func,
|
||||
allowRange: PropTypes.bool,
|
||||
rangeStep: PropTypes.number,
|
||||
wdKey: PropTypes.string,
|
||||
required: PropTypes.bool,
|
||||
"aria-label": PropTypes.string,
|
||||
}
|
||||
type InputNumberProps = {
|
||||
value?: number
|
||||
default?: number
|
||||
min?: number
|
||||
max?: number
|
||||
onChange?(...args: unknown[]): unknown
|
||||
allowRange?: boolean
|
||||
rangeStep?: number
|
||||
wdKey?: string
|
||||
required?: boolean
|
||||
"aria-label"?: string
|
||||
};
|
||||
|
||||
type InputNumberState = {
|
||||
uuid: number
|
||||
editing: boolean
|
||||
editingRange?: boolean
|
||||
value?: number
|
||||
dirtyValue?: number
|
||||
}
|
||||
|
||||
export default class InputNumber extends React.Component<InputNumberProps, InputNumberState> {
|
||||
static defaultProps = {
|
||||
rangeStep: 1
|
||||
}
|
||||
_keyboardEvent: boolean = false;
|
||||
|
||||
constructor(props) {
|
||||
constructor(props: InputNumberProps) {
|
||||
super(props)
|
||||
this.state = {
|
||||
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) {
|
||||
return {
|
||||
value: props.value,
|
||||
@@ -41,16 +49,15 @@ export default class InputNumber extends React.Component {
|
||||
return null;
|
||||
}
|
||||
|
||||
changeValue(newValue) {
|
||||
changeValue(newValue: number | string | undefined) {
|
||||
const value = (newValue === "" || newValue === undefined) ?
|
||||
undefined :
|
||||
parseFloat(newValue);
|
||||
undefined : +newValue;
|
||||
|
||||
const hasChanged = this.props.value !== value;
|
||||
if(this.isValid(value) && hasChanged) {
|
||||
this.props.onChange(value)
|
||||
if (this.props.onChange) this.props.onChange(value)
|
||||
this.setState({
|
||||
value: newValue,
|
||||
value: value,
|
||||
});
|
||||
}
|
||||
else if (!this.isValid(value) && hasChanged) {
|
||||
@@ -60,25 +67,25 @@ export default class InputNumber extends React.Component {
|
||||
}
|
||||
|
||||
this.setState({
|
||||
dirtyValue: newValue === "" ? undefined : newValue,
|
||||
dirtyValue: newValue === "" ? undefined : value,
|
||||
})
|
||||
}
|
||||
|
||||
isValid(v) {
|
||||
isValid(v: number | string | undefined) {
|
||||
if (v === undefined) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const value = parseFloat(v)
|
||||
const value = +v;
|
||||
if(isNaN(value)) {
|
||||
return false
|
||||
}
|
||||
|
||||
if(!isNaN(this.props.min) && value < this.props.min) {
|
||||
if(!isNaN(this.props.min!) && value < this.props.min!) {
|
||||
return false
|
||||
}
|
||||
|
||||
if(!isNaN(this.props.max) && value > this.props.max) {
|
||||
if(!isNaN(this.props.max!) && value > this.props.max!) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -88,7 +95,7 @@ export default class InputNumber extends React.Component {
|
||||
resetValue = () => {
|
||||
this.setState({editing: false});
|
||||
// Reset explicitly to default value if value has been cleared
|
||||
if(this.state.value === "") {
|
||||
if(!this.state.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -104,8 +111,8 @@ export default class InputNumber extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
onChangeRange = (e) => {
|
||||
let value = parseFloat(e.target.value, 10);
|
||||
onChangeRange = (e: BaseSyntheticEvent<Event, HTMLInputElement, HTMLInputElement>) => {
|
||||
let value = parseFloat(e.target.value);
|
||||
const step = this.props.rangeStep;
|
||||
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
|
||||
// that came from a keyboard event we always want to increase by a
|
||||
// single step value.
|
||||
if (value < this.state.dirtyValue) {
|
||||
value = this.state.value - step;
|
||||
if (value < this.state.dirtyValue!) {
|
||||
value = this.state.value! - step;
|
||||
}
|
||||
else {
|
||||
value = this.state.value + step
|
||||
value = this.state.value! + step
|
||||
}
|
||||
dirtyValue = value;
|
||||
}
|
||||
@@ -140,10 +147,10 @@ export default class InputNumber extends React.Component {
|
||||
this._keyboardEvent = false;
|
||||
|
||||
// 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.props.onChange(value);
|
||||
if (this.props.onChange) this.props.onChange(value);
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -196,15 +203,15 @@ export default class InputNumber extends React.Component {
|
||||
type="text"
|
||||
spellCheck="false"
|
||||
className="maputnik-number"
|
||||
placeholder={this.props.default}
|
||||
placeholder={this.props.default?.toString()}
|
||||
value={inputValue === undefined ? "" : inputValue}
|
||||
onFocus={e => {
|
||||
onFocus={_e => {
|
||||
this.setState({editing: true});
|
||||
}}
|
||||
onChange={e => {
|
||||
this.changeValue(e.target.value);
|
||||
}}
|
||||
onBlur={e => {
|
||||
onBlur={_e => {
|
||||
this.setState({editing: false});
|
||||
this.resetValue()
|
||||
}}
|
||||
@@ -218,7 +225,7 @@ export default class InputNumber extends React.Component {
|
||||
aria-label={this.props['aria-label']}
|
||||
spellCheck="false"
|
||||
className="maputnik-number"
|
||||
placeholder={this.props.default}
|
||||
placeholder={this.props.default?.toString()}
|
||||
value={value === undefined ? "" : value}
|
||||
onChange={e => this.changeValue(e.target.value)}
|
||||
onFocus={() => {
|
||||
@@ -1,22 +1,20 @@
|
||||
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() {
|
||||
let options = this.props.options
|
||||
let options = this.props.options;
|
||||
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
|
||||
@@ -1,26 +1,30 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
export default class InputString extends React.Component {
|
||||
static propTypes = {
|
||||
"data-wd-key": PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
style: PropTypes.object,
|
||||
default: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
onInput: PropTypes.func,
|
||||
multi: PropTypes.bool,
|
||||
required: PropTypes.bool,
|
||||
disabled: PropTypes.bool,
|
||||
spellCheck: PropTypes.bool,
|
||||
'aria-label': PropTypes.string,
|
||||
}
|
||||
export type InputStringProps = {
|
||||
"data-wd-key"?: string
|
||||
value?: string
|
||||
style?: object
|
||||
default?: string
|
||||
onChange?(...args: unknown[]): unknown
|
||||
onInput(...args: unknown[]): unknown
|
||||
multi?: boolean
|
||||
required?: boolean
|
||||
disabled?: boolean
|
||||
spellCheck?: boolean
|
||||
'aria-label'?: string
|
||||
};
|
||||
|
||||
type InputStringState = {
|
||||
editing: boolean
|
||||
value?: string
|
||||
}
|
||||
|
||||
export default class InputString extends React.Component<InputStringProps, InputStringState> {
|
||||
static defaultProps = {
|
||||
onInput: () => {},
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
constructor(props: InputStringProps) {
|
||||
super(props)
|
||||
this.state = {
|
||||
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) {
|
||||
return {
|
||||
value: props.value
|
||||
@@ -68,7 +72,7 @@ export default class InputString extends React.Component {
|
||||
style: this.props.style,
|
||||
value: this.state.value === undefined ? "" : this.state.value,
|
||||
placeholder: this.props.default,
|
||||
onChange: e => {
|
||||
onChange: (e: React.BaseSyntheticEvent<Event, HTMLInputElement, HTMLInputElement>) => {
|
||||
this.setState({
|
||||
editing: true,
|
||||
value: e.target.value
|
||||
@@ -79,11 +83,11 @@ export default class InputString extends React.Component {
|
||||
onBlur: () => {
|
||||
if(this.state.value!==this.props.value) {
|
||||
this.setState({editing: false});
|
||||
this.props.onChange(this.state.value);
|
||||
if (this.props.onChange) this.props.onChange(this.state.value);
|
||||
}
|
||||
},
|
||||
onKeyDown: (e) => {
|
||||
if (e.keyCode === 13) {
|
||||
if (e.keyCode === 13 && this.props.onChange) {
|
||||
this.props.onChange(this.state.value);
|
||||
}
|
||||
},
|
||||
@@ -1,16 +1,15 @@
|
||||
import React, {Fragment} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import React from 'react'
|
||||
import InputString from './InputString'
|
||||
import SmallError from './SmallError'
|
||||
|
||||
|
||||
function validate (url) {
|
||||
function validate(url: string) {
|
||||
if (url === "") {
|
||||
return;
|
||||
}
|
||||
|
||||
let error;
|
||||
const getProtocol = (url) => {
|
||||
const getProtocol = (url: string) => {
|
||||
try {
|
||||
const urlObj = new URL(url);
|
||||
return urlObj.protocol;
|
||||
@@ -48,38 +47,42 @@ function validate (url) {
|
||||
return error;
|
||||
}
|
||||
|
||||
export default class FieldUrl extends React.Component {
|
||||
static propTypes = {
|
||||
"data-wd-key": PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
style: PropTypes.object,
|
||||
default: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
onInput: PropTypes.func,
|
||||
multi: PropTypes.bool,
|
||||
required: PropTypes.bool,
|
||||
'aria-label': PropTypes.string,
|
||||
}
|
||||
export type FieldUrlProps = {
|
||||
"data-wd-key"?: string
|
||||
value: string
|
||||
style?: object
|
||||
default?: string
|
||||
onChange(...args: unknown[]): unknown
|
||||
onInput(...args: unknown[]): unknown
|
||||
multi?: boolean
|
||||
required?: boolean
|
||||
'aria-label'?: string
|
||||
};
|
||||
|
||||
type FieldUrlState = {
|
||||
error?: React.ReactNode
|
||||
}
|
||||
|
||||
export default class FieldUrl extends React.Component<FieldUrlProps, FieldUrlState> {
|
||||
static defaultProps = {
|
||||
onInput: () => {},
|
||||
}
|
||||
|
||||
constructor (props) {
|
||||
constructor (props: FieldUrlProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
error: validate(props.value)
|
||||
};
|
||||
}
|
||||
|
||||
onInput = (url) => {
|
||||
onInput = (url: string) => {
|
||||
this.setState({
|
||||
error: validate(url)
|
||||
});
|
||||
this.props.onInput(url);
|
||||
}
|
||||
|
||||
onChange = (url) => {
|
||||
onChange = (url: string) => {
|
||||
this.setState({
|
||||
error: validate(url)
|
||||
});
|
||||
@@ -1,22 +1,21 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {MdClose} from 'react-icons/md'
|
||||
import AriaModal from 'react-aria-modal'
|
||||
import classnames from 'classnames';
|
||||
|
||||
|
||||
export default class Modal extends React.Component {
|
||||
static propTypes = {
|
||||
"data-wd-key": PropTypes.string,
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
onOpenToggle: PropTypes.func.isRequired,
|
||||
children: PropTypes.node,
|
||||
underlayClickExits: PropTypes.bool,
|
||||
underlayProps: PropTypes.object,
|
||||
className: PropTypes.string,
|
||||
}
|
||||
type ModalProps = {
|
||||
"data-wd-key"?: string
|
||||
isOpen: boolean
|
||||
title: string
|
||||
onOpenToggle(...args: unknown[]): unknown
|
||||
underlayClickExits?: boolean
|
||||
underlayProps?: any
|
||||
className?: string
|
||||
};
|
||||
|
||||
|
||||
export default class Modal extends React.Component<ModalProps> {
|
||||
static defaultProps = {
|
||||
underlayClickExits: true
|
||||
}
|
||||
@@ -24,7 +23,7 @@ export default class Modal extends React.Component {
|
||||
// See <https://github.com/maputnik/editor/issues/416>
|
||||
onClose = () => {
|
||||
if (document.activeElement) {
|
||||
document.activeElement.blur();
|
||||
(document.activeElement as HTMLElement).blur();
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
@@ -37,6 +36,7 @@ export default class Modal extends React.Component {
|
||||
return <AriaModal
|
||||
titleText={this.props.title}
|
||||
underlayClickExits={this.props.underlayClickExits}
|
||||
// @ts-ignore
|
||||
underlayProps={this.props.underlayProps}
|
||||
data-wd-key={this.props["data-wd-key"]}
|
||||
verticallyCenter={true}
|
||||
@@ -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>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 PropTypes from 'prop-types'
|
||||
import './SmallError.scss';
|
||||
|
||||
|
||||
export default class SmallError extends React.Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node,
|
||||
}
|
||||
type SmallErrorProps = {
|
||||
children?: React.ReactNode
|
||||
};
|
||||
|
||||
|
||||
export default class SmallError extends React.Component<SmallErrorProps> {
|
||||
render () {
|
||||
return (
|
||||
<div className="SmallError">
|
||||
@@ -15,5 +15,4 @@ export default class SmallError extends React.Component {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user