mirror of
https://github.com/a-nyx/maputnik-with-pmtiles.git
synced 2024-12-27 09:25:24 +01:00
Merge pull request #699 from orangemug/maintenance/component-refactor
Tidy of components + added storybook.js
This commit is contained in:
commit
b19eacf4f9
99 changed files with 5755 additions and 513 deletions
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
|
@ -93,6 +93,7 @@ jobs:
|
|||
${{ runner.os }}-node-
|
||||
- run: npm install
|
||||
- run: npm run build
|
||||
- run: npm run build-storybook
|
||||
- name: artifacts/editor
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
|
@ -104,6 +105,11 @@ jobs:
|
|||
with:
|
||||
name: editor-profiling
|
||||
path: build/profiling
|
||||
- name: artifacts/storybook
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: storybook
|
||||
path: build/storybook
|
||||
|
||||
# Build and upload desktop CLI artifacts
|
||||
- name: Set up Go
|
||||
|
|
25
.storybook/main.js
Normal file
25
.storybook/main.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
const rules = require('../config/webpack.rules');
|
||||
|
||||
module.exports = {
|
||||
stories: ['../stories/**/*.stories.js'],
|
||||
addons: [
|
||||
'@storybook/addon-actions',
|
||||
'@storybook/addon-links',
|
||||
'@storybook/addon-a11y/register',
|
||||
'@storybook/addon-storysource',
|
||||
],
|
||||
webpackFinal: async config => {
|
||||
// do mutation to the config
|
||||
console.log("config.module", config.module);
|
||||
|
||||
return {
|
||||
...config,
|
||||
module: {
|
||||
rules: [
|
||||
...config.module.rules,
|
||||
...rules,
|
||||
]
|
||||
}
|
||||
};
|
||||
},
|
||||
};
|
7
.storybook/manager.js
Normal file
7
.storybook/manager.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { addons } from '@storybook/addons';
|
||||
import { themes } from '@storybook/theming';
|
||||
import theme from './maputnik.theme';
|
||||
|
||||
addons.setConfig({
|
||||
theme: theme,
|
||||
});
|
8
.storybook/maputnik.theme.js
Normal file
8
.storybook/maputnik.theme.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
import { create } from '@storybook/theming/create';
|
||||
|
||||
export default create({
|
||||
base: 'light',
|
||||
|
||||
brandTitle: 'Maputnik',
|
||||
brandUrl: 'https://github.com/maputnik/editor',
|
||||
});
|
4614
package-lock.json
generated
4614
package-lock.json
generated
File diff suppressed because it is too large
Load diff
11
package.json
11
package.json
|
@ -13,7 +13,9 @@
|
|||
"start-prod": "webpack-dev-server --progress --profile --colors --config config/webpack.production.config.js",
|
||||
"lint-js": "eslint --ext js --ext jsx src test",
|
||||
"lint-css": "stylelint \"src/styles/*.scss\"",
|
||||
"lint": "npm run lint-js && npm run lint-css"
|
||||
"lint": "npm run lint-js && npm run lint-css",
|
||||
"storybook": "start-storybook -h 0.0.0.0 -p 6006",
|
||||
"build-storybook": "build-storybook -o build/storybook"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -119,6 +121,13 @@
|
|||
"@babel/preset-flow": "^7.0.0",
|
||||
"@babel/preset-react": "^7.6.3",
|
||||
"@mdi/js": "^5.0.45",
|
||||
"@storybook/addon-a11y": "^5.3.19",
|
||||
"@storybook/addon-actions": "^5.3.19",
|
||||
"@storybook/addon-links": "^5.3.19",
|
||||
"@storybook/addon-storysource": "^5.3.19",
|
||||
"@storybook/addons": "^5.3.19",
|
||||
"@storybook/react": "^5.3.19",
|
||||
"@storybook/theming": "^5.3.19",
|
||||
"@wdio/cli": "^6.1.14",
|
||||
"@wdio/local-runner": "^6.1.14",
|
||||
"@wdio/mocha-framework": "^6.1.14",
|
||||
|
|
|
@ -7,21 +7,21 @@ import {unset} from 'lodash'
|
|||
import arrayMove from 'array-move'
|
||||
import url from 'url'
|
||||
|
||||
import MapboxGlMap from './map/MapboxGlMap'
|
||||
import OpenLayersMap from './map/OpenLayersMap'
|
||||
import LayerList from './layers/LayerList'
|
||||
import LayerEditor from './layers/LayerEditor'
|
||||
import Toolbar from './Toolbar'
|
||||
import MapMapboxGl from './MapMapboxGl'
|
||||
import MapOpenLayers from './MapOpenLayers'
|
||||
import LayerList from './LayerList'
|
||||
import LayerEditor from './LayerEditor'
|
||||
import AppToolbar from './AppToolbar'
|
||||
import AppLayout from './AppLayout'
|
||||
import MessagePanel from './MessagePanel'
|
||||
import MessagePanel from './AppMessagePanel'
|
||||
|
||||
import SettingsModal from './modals/SettingsModal'
|
||||
import ExportModal from './modals/ExportModal'
|
||||
import SourcesModal from './modals/SourcesModal'
|
||||
import OpenModal from './modals/OpenModal'
|
||||
import ShortcutsModal from './modals/ShortcutsModal'
|
||||
import SurveyModal from './modals/SurveyModal'
|
||||
import DebugModal from './modals/DebugModal'
|
||||
import ModalSettings from './ModalSettings'
|
||||
import ModalExport from './ModalExport'
|
||||
import ModalSources from './ModalSources'
|
||||
import ModalOpen from './ModalOpen'
|
||||
import ModalShortcuts from './ModalShortcuts'
|
||||
import ModalSurvey from './ModalSurvey'
|
||||
import ModalDebug from './ModalDebug'
|
||||
|
||||
import { downloadGlyphsMetadata, downloadSpriteMetadata } from '../libs/metadata'
|
||||
import {latest, validate} from '@mapbox/mapbox-gl-style-spec'
|
||||
|
@ -36,7 +36,7 @@ import tokens from '../config/tokens.json'
|
|||
import isEqual from 'lodash.isequal'
|
||||
import Debug from '../libs/debug'
|
||||
import queryUtil from '../libs/query-util'
|
||||
import {formatLayerId} from './util/format';
|
||||
import {formatLayerId} from '../util/format';
|
||||
|
||||
import MapboxGl from 'mapbox-gl'
|
||||
|
||||
|
@ -668,14 +668,14 @@ export default class App extends React.Component {
|
|||
|
||||
// Check if OL code has been loaded?
|
||||
if(renderer === 'ol') {
|
||||
mapElement = <OpenLayersMap
|
||||
mapElement = <MapOpenLayers
|
||||
{...mapProps}
|
||||
onChange={this.onMapChange}
|
||||
debugToolbox={this.state.openlayersDebugOptions.debugToolbox}
|
||||
onLayerSelect={this.onLayerSelect}
|
||||
/>
|
||||
} else {
|
||||
mapElement = <MapboxGlMap {...mapProps}
|
||||
mapElement = <MapMapboxGl {...mapProps}
|
||||
onChange={this.onMapChange}
|
||||
options={this.state.mapboxGlDebugOptions}
|
||||
inspectModeEnabled={this.state.mapState === "inspect"}
|
||||
|
@ -741,7 +741,7 @@ export default class App extends React.Component {
|
|||
const selectedLayer = layers.length > 0 ? layers[this.state.selectedLayerIndex] : null
|
||||
const metadata = this.state.mapStyle.metadata || {}
|
||||
|
||||
const toolbar = <Toolbar
|
||||
const toolbar = <AppToolbar
|
||||
renderer={this._getRenderer()}
|
||||
mapState={this.state.mapState}
|
||||
mapStyle={this.state.mapStyle}
|
||||
|
@ -795,7 +795,7 @@ export default class App extends React.Component {
|
|||
|
||||
|
||||
const modals = <div>
|
||||
<DebugModal
|
||||
<ModalDebug
|
||||
renderer={this._getRenderer()}
|
||||
mapboxGlDebugOptions={this.state.mapboxGlDebugOptions}
|
||||
openlayersDebugOptions={this.state.openlayersDebugOptions}
|
||||
|
@ -805,12 +805,12 @@ export default class App extends React.Component {
|
|||
onOpenToggle={this.toggleModal.bind(this, 'debug')}
|
||||
mapView={this.state.mapView}
|
||||
/>
|
||||
<ShortcutsModal
|
||||
<ModalShortcuts
|
||||
ref={(el) => this.shortcutEl = el}
|
||||
isOpen={this.state.isOpen.shortcuts}
|
||||
onOpenToggle={this.toggleModal.bind(this, 'shortcuts')}
|
||||
/>
|
||||
<SettingsModal
|
||||
<ModalSettings
|
||||
mapStyle={this.state.mapStyle}
|
||||
onStyleChanged={this.onStyleChanged}
|
||||
onChangeMetadataProperty={this.onChangeMetadataProperty}
|
||||
|
@ -818,24 +818,24 @@ export default class App extends React.Component {
|
|||
onOpenToggle={this.toggleModal.bind(this, 'settings')}
|
||||
openlayersDebugOptions={this.state.openlayersDebugOptions}
|
||||
/>
|
||||
<ExportModal
|
||||
<ModalExport
|
||||
mapStyle={this.state.mapStyle}
|
||||
onStyleChanged={this.onStyleChanged}
|
||||
isOpen={this.state.isOpen.export}
|
||||
onOpenToggle={this.toggleModal.bind(this, 'export')}
|
||||
/>
|
||||
<OpenModal
|
||||
<ModalOpen
|
||||
isOpen={this.state.isOpen.open}
|
||||
onStyleOpen={this.openStyle}
|
||||
onOpenToggle={this.toggleModal.bind(this, 'open')}
|
||||
/>
|
||||
<SourcesModal
|
||||
<ModalSources
|
||||
mapStyle={this.state.mapStyle}
|
||||
onStyleChanged={this.onStyleChanged}
|
||||
isOpen={this.state.isOpen.sources}
|
||||
onOpenToggle={this.toggleModal.bind(this, 'sources')}
|
||||
/>
|
||||
<SurveyModal
|
||||
<ModalSurvey
|
||||
isOpen={this.state.isOpen.survey}
|
||||
onOpenToggle={this.toggleModal.bind(this, 'survey')}
|
||||
/>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {formatLayerId} from './util/format';
|
||||
import {formatLayerId} from '../util/format';
|
||||
|
||||
class MessagePanel extends React.Component {
|
||||
export default class AppMessagePanel extends React.Component {
|
||||
static propTypes = {
|
||||
errors: PropTypes.array,
|
||||
infos: PropTypes.array,
|
||||
|
@ -60,5 +60,3 @@ class MessagePanel extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
export default MessagePanel
|
|
@ -101,7 +101,7 @@ class ToolbarAction extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default class Toolbar extends React.Component {
|
||||
export default class AppToolbar extends React.Component {
|
||||
static propTypes = {
|
||||
mapStyle: PropTypes.object.isRequired,
|
||||
inspectModeEnabled: PropTypes.bool.isRequired,
|
|
@ -1,12 +1,12 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import classnames from 'classnames'
|
||||
import DocLabel from '../fields/DocLabel'
|
||||
import SpecDoc from './SpecDoc'
|
||||
import FieldDocLabel from './FieldDocLabel'
|
||||
import Doc from './Doc'
|
||||
|
||||
|
||||
/** Wrap a component with a label */
|
||||
class InputBlock extends React.Component {
|
||||
export default class Block extends React.Component {
|
||||
static propTypes = {
|
||||
"data-wd-key": PropTypes.string,
|
||||
label: PropTypes.oneOfType([
|
||||
|
@ -53,7 +53,7 @@ class InputBlock extends React.Component {
|
|||
>
|
||||
{this.props.fieldSpec &&
|
||||
<div className="maputnik-input-block-label">
|
||||
<DocLabel
|
||||
<FieldDocLabel
|
||||
label={this.props.label}
|
||||
onToggleDoc={this.onToggleDoc}
|
||||
fieldSpec={this.props.fieldSpec}
|
||||
|
@ -85,11 +85,10 @@ class InputBlock extends React.Component {
|
|||
className="maputnik-doc-inline"
|
||||
style={{display: this.state.showDoc ? '' : 'none'}}
|
||||
>
|
||||
<SpecDoc fieldSpec={this.props.fieldSpec} />
|
||||
<Doc fieldSpec={this.props.fieldSpec} />
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
export default InputBlock
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import InputBlock from '../inputs/InputBlock'
|
||||
import StringInput from '../inputs/StringInput'
|
||||
import Block from './Block'
|
||||
import FieldString from './FieldString'
|
||||
|
||||
class MetadataBlock extends React.Component {
|
||||
export default class BlockComment extends React.Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.string,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
|
@ -15,19 +15,18 @@ class MetadataBlock extends React.Component {
|
|||
doc: "Comments for the current layer. This is non-standard and not in the spec."
|
||||
};
|
||||
|
||||
return <InputBlock
|
||||
return <Block
|
||||
label={"Comments"}
|
||||
fieldSpec={fieldSpec}
|
||||
data-wd-key="layer-comment"
|
||||
>
|
||||
<StringInput
|
||||
<FieldString
|
||||
multi={true}
|
||||
value={this.props.value}
|
||||
onChange={this.props.onChange}
|
||||
default="Comment..."
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
}
|
||||
}
|
||||
|
||||
export default MetadataBlock
|
|
@ -2,10 +2,10 @@ import React from 'react'
|
|||
import PropTypes from 'prop-types'
|
||||
|
||||
import {latest} from '@mapbox/mapbox-gl-style-spec'
|
||||
import InputBlock from '../inputs/InputBlock'
|
||||
import StringInput from '../inputs/StringInput'
|
||||
import Block from './Block'
|
||||
import FieldString from './FieldString'
|
||||
|
||||
class LayerIdBlock extends React.Component {
|
||||
export default class BlockId extends React.Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.string.isRequired,
|
||||
wdKey: PropTypes.string.isRequired,
|
||||
|
@ -14,16 +14,15 @@ class LayerIdBlock extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
return <InputBlock label={"ID"} fieldSpec={latest.layer.id}
|
||||
return <Block label={"ID"} fieldSpec={latest.layer.id}
|
||||
data-wd-key={this.props.wdKey}
|
||||
error={this.props.error}
|
||||
>
|
||||
<StringInput
|
||||
<FieldString
|
||||
value={this.props.value}
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
}
|
||||
}
|
||||
|
||||
export default LayerIdBlock
|
|
@ -2,10 +2,10 @@ import React from 'react'
|
|||
import PropTypes from 'prop-types'
|
||||
|
||||
import {latest} from '@mapbox/mapbox-gl-style-spec'
|
||||
import InputBlock from '../inputs/InputBlock'
|
||||
import NumberInput from '../inputs/NumberInput'
|
||||
import Block from './Block'
|
||||
import FieldNumber from './FieldNumber'
|
||||
|
||||
class MaxZoomBlock extends React.Component {
|
||||
export default class BlockMaxZoom extends React.Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.number,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
|
@ -13,11 +13,11 @@ class MaxZoomBlock extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
return <InputBlock label={"Max Zoom"} fieldSpec={latest.layer.maxzoom}
|
||||
return <Block label={"Max Zoom"} fieldSpec={latest.layer.maxzoom}
|
||||
error={this.props.error}
|
||||
data-wd-key="max-zoom"
|
||||
>
|
||||
<NumberInput
|
||||
<FieldNumber
|
||||
allowRange={true}
|
||||
value={this.props.value}
|
||||
onChange={this.props.onChange}
|
||||
|
@ -25,8 +25,7 @@ class MaxZoomBlock extends React.Component {
|
|||
max={latest.layer.maxzoom.maximum}
|
||||
default={latest.layer.maxzoom.maximum}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
}
|
||||
}
|
||||
|
||||
export default MaxZoomBlock
|
|
@ -2,10 +2,10 @@ import React from 'react'
|
|||
import PropTypes from 'prop-types'
|
||||
|
||||
import {latest} from '@mapbox/mapbox-gl-style-spec'
|
||||
import InputBlock from '../inputs/InputBlock'
|
||||
import NumberInput from '../inputs/NumberInput'
|
||||
import Block from './Block'
|
||||
import FieldNumber from './FieldNumber'
|
||||
|
||||
class MinZoomBlock extends React.Component {
|
||||
export default class BlockMinZoom extends React.Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.number,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
|
@ -13,11 +13,11 @@ class MinZoomBlock extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
return <InputBlock label={"Min Zoom"} fieldSpec={latest.layer.minzoom}
|
||||
return <Block label={"Min Zoom"} fieldSpec={latest.layer.minzoom}
|
||||
error={this.props.error}
|
||||
data-wd-key="min-zoom"
|
||||
>
|
||||
<NumberInput
|
||||
<FieldNumber
|
||||
allowRange={true}
|
||||
value={this.props.value}
|
||||
onChange={this.props.onChange}
|
||||
|
@ -25,8 +25,7 @@ class MinZoomBlock extends React.Component {
|
|||
max={latest.layer.minzoom.maximum}
|
||||
default={latest.layer.minzoom.minimum}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
}
|
||||
}
|
||||
|
||||
export default MinZoomBlock
|
|
@ -2,10 +2,10 @@ import React from 'react'
|
|||
import PropTypes from 'prop-types'
|
||||
|
||||
import {latest} from '@mapbox/mapbox-gl-style-spec'
|
||||
import InputBlock from '../inputs/InputBlock'
|
||||
import AutocompleteInput from '../inputs/AutocompleteInput'
|
||||
import Block from './Block'
|
||||
import FieldAutocomplete from './FieldAutocomplete'
|
||||
|
||||
class LayerSourceBlock extends React.Component {
|
||||
export default class BlockSource extends React.Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.string,
|
||||
wdKey: PropTypes.string,
|
||||
|
@ -20,19 +20,18 @@ class LayerSourceBlock extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
return <InputBlock
|
||||
return <Block
|
||||
label={"Source"}
|
||||
fieldSpec={latest.layer.source}
|
||||
error={this.props.error}
|
||||
data-wd-key={this.props.wdKey}
|
||||
>
|
||||
<AutocompleteInput
|
||||
<FieldAutocomplete
|
||||
value={this.props.value}
|
||||
onChange={this.props.onChange}
|
||||
options={this.props.sourceIds.map(src => [src, src])}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
}
|
||||
}
|
||||
|
||||
export default LayerSourceBlock
|
|
@ -2,10 +2,10 @@ import React from 'react'
|
|||
import PropTypes from 'prop-types'
|
||||
|
||||
import {latest} from '@mapbox/mapbox-gl-style-spec'
|
||||
import InputBlock from '../inputs/InputBlock'
|
||||
import AutocompleteInput from '../inputs/AutocompleteInput'
|
||||
import Block from './Block'
|
||||
import FieldAutocomplete from './FieldAutocomplete'
|
||||
|
||||
class LayerSourceLayer extends React.Component {
|
||||
export default class BlockSourceLayer extends React.Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
|
@ -20,17 +20,16 @@ class LayerSourceLayer extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
return <InputBlock label={"Source Layer"} fieldSpec={latest.layer['source-layer']}
|
||||
return <Block label={"Source Layer"} fieldSpec={latest.layer['source-layer']}
|
||||
data-wd-key="layer-source-layer"
|
||||
>
|
||||
<AutocompleteInput
|
||||
<FieldAutocomplete
|
||||
keepMenuWithinWindowBounds={!!this.props.isFixed}
|
||||
value={this.props.value}
|
||||
onChange={this.props.onChange}
|
||||
options={this.props.sourceLayerIds.map(l => [l, l])}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
}
|
||||
}
|
||||
|
||||
export default LayerSourceLayer
|
|
@ -2,11 +2,11 @@ import React from 'react'
|
|||
import PropTypes from 'prop-types'
|
||||
|
||||
import {latest} from '@mapbox/mapbox-gl-style-spec'
|
||||
import InputBlock from '../inputs/InputBlock'
|
||||
import SelectInput from '../inputs/SelectInput'
|
||||
import StringInput from '../inputs/StringInput'
|
||||
import Block from './Block'
|
||||
import FieldSelect from './FieldSelect'
|
||||
import FieldString from './FieldString'
|
||||
|
||||
class LayerTypeBlock extends React.Component {
|
||||
export default class BlockType extends React.Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.string.isRequired,
|
||||
wdKey: PropTypes.string,
|
||||
|
@ -20,18 +20,18 @@ class LayerTypeBlock extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
return <InputBlock label={"Type"} fieldSpec={latest.layer.type}
|
||||
return <Block label={"Type"} fieldSpec={latest.layer.type}
|
||||
data-wd-key={this.props.wdKey}
|
||||
error={this.props.error}
|
||||
>
|
||||
{this.props.disabled &&
|
||||
<StringInput
|
||||
<FieldString
|
||||
value={this.props.value}
|
||||
disabled={true}
|
||||
/>
|
||||
}
|
||||
{!this.props.disabled &&
|
||||
<SelectInput
|
||||
<FieldSelect
|
||||
options={[
|
||||
['background', 'Background'],
|
||||
['fill', 'Fill'],
|
||||
|
@ -47,8 +47,7 @@ class LayerTypeBlock extends React.Component {
|
|||
value={this.props.value}
|
||||
/>
|
||||
}
|
||||
</InputBlock>
|
||||
</Block>
|
||||
}
|
||||
}
|
||||
|
||||
export default LayerTypeBlock
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Collapse from 'react-collapse'
|
||||
import Collapse as ReactCollapse from 'react-collapse'
|
||||
import accessibility from '../../libs/accessibility'
|
||||
|
||||
|
||||
export default class CollapseAlt extends React.Component {
|
||||
export default class Collapse extends React.Component {
|
||||
static propTypes = {
|
||||
isActive: PropTypes.bool.isRequired,
|
||||
children: PropTypes.element.isRequired
|
||||
|
@ -24,9 +24,9 @@ export default class CollapseAlt extends React.Component {
|
|||
}
|
||||
else {
|
||||
return (
|
||||
<Collapse isOpened={this.props.isActive}>
|
||||
<ReactCollapse isOpened={this.props.isActive}>
|
||||
{this.props.children}
|
||||
</Collapse>
|
||||
</ReactCollapse>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
export default class SpecDoc extends React.Component {
|
||||
export default class Doc extends React.Component {
|
||||
static propTypes = {
|
||||
fieldSpec: PropTypes.object.isRequired,
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import StringInput from './StringInput'
|
||||
import NumberInput from './NumberInput'
|
||||
import FieldString from './FieldString'
|
||||
import FieldNumber from './FieldNumber'
|
||||
|
||||
class ArrayInput extends React.Component {
|
||||
export default class FieldArray extends React.Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.array,
|
||||
type: PropTypes.string,
|
||||
|
@ -82,7 +82,7 @@ class ArrayInput extends React.Component {
|
|||
|
||||
const inputs = Array(this.props.length).fill(null).map((_, i) => {
|
||||
if(this.props.type === 'number') {
|
||||
return <NumberInput
|
||||
return <FieldNumber
|
||||
key={i}
|
||||
default={containsValues ? undefined : this.props.default[i]}
|
||||
value={value[i]}
|
||||
|
@ -90,7 +90,7 @@ class ArrayInput extends React.Component {
|
|||
onChange={this.changeValue.bind(this, i)}
|
||||
/>
|
||||
} else {
|
||||
return <StringInput
|
||||
return <FieldString
|
||||
key={i}
|
||||
default={containsValues ? undefined : this.props.default[i]}
|
||||
value={value[i]}
|
||||
|
@ -106,4 +106,3 @@ class ArrayInput extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default ArrayInput
|
|
@ -6,7 +6,7 @@ import Autocomplete from 'react-autocomplete'
|
|||
|
||||
const MAX_HEIGHT = 140;
|
||||
|
||||
class AutocompleteInput extends React.Component {
|
||||
export default class FieldAutocomplete extends React.Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.string,
|
||||
options: PropTypes.array,
|
||||
|
@ -95,4 +95,3 @@ class AutocompleteInput extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default AutocompleteInput
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
class CheckboxInput extends React.Component {
|
||||
export default class FieldCheckbox extends React.Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.bool,
|
||||
style: PropTypes.object,
|
||||
|
@ -32,4 +32,3 @@ class CheckboxInput extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default CheckboxInput
|
|
@ -10,7 +10,7 @@ function formatColor(color) {
|
|||
}
|
||||
|
||||
/*** Number fields with support for min, max and units and documentation*/
|
||||
class ColorField extends React.Component {
|
||||
export default class FieldColor extends React.Component {
|
||||
static propTypes = {
|
||||
onChange: PropTypes.func.isRequired,
|
||||
name: PropTypes.string,
|
||||
|
@ -130,4 +130,3 @@ class ColorField extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default ColorField
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
|
|||
|
||||
import {MdInfoOutline, MdHighlightOff} from 'react-icons/md'
|
||||
|
||||
export default class DocLabel extends React.Component {
|
||||
export default class FieldDocLabel extends React.Component {
|
||||
static propTypes = {
|
||||
label: PropTypes.oneOfType([
|
||||
PropTypes.object,
|
|
@ -1,16 +1,16 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import StringInput from './StringInput'
|
||||
import NumberInput from './NumberInput'
|
||||
import Button from '../Button'
|
||||
import FieldString from './FieldString'
|
||||
import FieldNumber from './FieldNumber'
|
||||
import Button from './Button'
|
||||
import {MdDelete} from 'react-icons/md'
|
||||
import DocLabel from '../fields/DocLabel'
|
||||
import EnumInput from '../inputs/SelectInput'
|
||||
import FieldDocLabel from './FieldDocLabel'
|
||||
import FieldEnum from './FieldEnum'
|
||||
import capitalize from 'lodash.capitalize'
|
||||
import UrlInput from '../inputs/UrlInput'
|
||||
import FieldUrl from './FieldUrl'
|
||||
|
||||
|
||||
class DynamicArrayInput extends React.Component {
|
||||
export default class FieldDynamicArray extends React.Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.array,
|
||||
type: PropTypes.string,
|
||||
|
@ -62,13 +62,13 @@ class DynamicArrayInput extends React.Component {
|
|||
const deleteValueBtn= <DeleteValueButton onClick={this.deleteValue.bind(this, i)} />
|
||||
let input;
|
||||
if(this.props.type === 'url') {
|
||||
input = <UrlInput
|
||||
input = <FieldUrl
|
||||
value={v}
|
||||
onChange={this.changeValue.bind(this, i)}
|
||||
/>
|
||||
}
|
||||
else if (this.props.type === 'number') {
|
||||
input = <NumberInput
|
||||
input = <FieldNumber
|
||||
value={v}
|
||||
onChange={this.changeValue.bind(this, i)}
|
||||
/>
|
||||
|
@ -76,14 +76,14 @@ class DynamicArrayInput extends React.Component {
|
|||
else if (this.props.type === 'enum') {
|
||||
const options = Object.keys(this.props.fieldSpec.values).map(v => [v, capitalize(v)]);
|
||||
|
||||
input = <EnumInput
|
||||
input = <FieldEnum
|
||||
options={options}
|
||||
value={v}
|
||||
onChange={this.changeValue.bind(this, i)}
|
||||
/>
|
||||
}
|
||||
else {
|
||||
input = <StringInput
|
||||
input = <FieldString
|
||||
value={v}
|
||||
onChange={this.changeValue.bind(this, i)}
|
||||
/>
|
||||
|
@ -126,7 +126,7 @@ class DeleteValueButton extends React.Component {
|
|||
onClick={this.props.onClick}
|
||||
title="Remove array item"
|
||||
>
|
||||
<DocLabel
|
||||
<FieldDocLabel
|
||||
label={<MdDelete />}
|
||||
doc={"Remove array item."}
|
||||
/>
|
||||
|
@ -134,4 +134,3 @@ class DeleteValueButton extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default DynamicArrayInput
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import SelectInput from '../inputs/SelectInput'
|
||||
import MultiButtonInput from '../inputs/MultiButtonInput'
|
||||
import FieldSelect from './FieldSelect'
|
||||
import FieldMultiInput from './FieldMultiInput'
|
||||
|
||||
|
||||
function optionsLabelLength(options) {
|
||||
|
@ -13,7 +13,7 @@ function optionsLabelLength(options) {
|
|||
}
|
||||
|
||||
|
||||
class EnumInput extends React.Component {
|
||||
export default class FieldEnum extends React.Component {
|
||||
static propTypes = {
|
||||
"data-wd-key": PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
|
@ -28,14 +28,14 @@ class EnumInput extends React.Component {
|
|||
const {options, value, onChange, name} = this.props;
|
||||
|
||||
if(options.length <= 3 && optionsLabelLength(options) <= 20) {
|
||||
return <MultiButtonInput
|
||||
return <FieldMultiInput
|
||||
name={name}
|
||||
options={options}
|
||||
value={value || this.props.default}
|
||||
onChange={onChange}
|
||||
/>
|
||||
} else {
|
||||
return <SelectInput
|
||||
return <FieldSelect
|
||||
options={options}
|
||||
value={value || this.props.default}
|
||||
onChange={onChange}
|
||||
|
@ -43,5 +43,3 @@ class EnumInput extends React.Component {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default EnumInput
|
|
@ -1,8 +1,8 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import AutocompleteInput from './AutocompleteInput'
|
||||
import FieldAutocomplete from './FieldAutocomplete'
|
||||
|
||||
class FontInput extends React.Component {
|
||||
export default class FieldFont extends React.Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.array,
|
||||
default: PropTypes.array,
|
||||
|
@ -39,7 +39,7 @@ class FontInput extends React.Component {
|
|||
|
||||
render() {
|
||||
const inputs = this.values.map((value, i) => {
|
||||
return <AutocompleteInput
|
||||
return <FieldAutocomplete
|
||||
key={i}
|
||||
value={value}
|
||||
options={this.props.fonts.map(f => [f, f])}
|
||||
|
@ -53,4 +53,3 @@ class FontInput extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default FontInput
|
|
@ -106,7 +106,7 @@ function getDataType (value, fieldSpec={}) {
|
|||
/** Supports displaying spec field for zoom function objects
|
||||
* https://www.mapbox.com/mapbox-gl-style-spec/#types-function-zoom-property
|
||||
*/
|
||||
export default class FunctionSpecProperty extends React.Component {
|
||||
export default class FieldFunction extends React.Component {
|
||||
static propTypes = {
|
||||
onChange: PropTypes.func.isRequired,
|
||||
fieldName: PropTypes.string.isRequired,
|
|
@ -2,8 +2,8 @@ import React from 'react'
|
|||
import PropTypes from 'prop-types'
|
||||
import classnames from 'classnames';
|
||||
|
||||
import InputBlock from '../inputs/InputBlock'
|
||||
import StringInput from '../inputs/StringInput'
|
||||
import Block from './Block'
|
||||
import FieldString from './FieldString'
|
||||
import CodeMirror from 'codemirror';
|
||||
|
||||
import 'codemirror/mode/javascript/javascript'
|
||||
|
@ -16,7 +16,7 @@ import stringifyPretty from 'json-stringify-pretty-compact'
|
|||
import '../util/codemirror-mgl';
|
||||
|
||||
|
||||
class JSONEditor extends React.Component {
|
||||
export default class FieldJsonEditor extends React.Component {
|
||||
static propTypes = {
|
||||
layer: PropTypes.any.isRequired,
|
||||
maxHeight: PropTypes.number,
|
||||
|
@ -173,4 +173,3 @@ class JSONEditor extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default JSONEditor
|
|
@ -1,9 +1,9 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import classnames from 'classnames'
|
||||
import Button from '../Button'
|
||||
import Button from './Button'
|
||||
|
||||
class MultiButtonInput extends React.Component {
|
||||
export default class FieldMultiInput extends React.Component {
|
||||
static propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
value: PropTypes.string.isRequired,
|
||||
|
@ -39,4 +39,3 @@ class MultiButtonInput extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default MultiButtonInput
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
|
|||
|
||||
let IDX = 0;
|
||||
|
||||
class NumberInput extends React.Component {
|
||||
export default class FieldNumber extends React.Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.number,
|
||||
default: PropTypes.number,
|
||||
|
@ -230,4 +230,3 @@ class NumberInput extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default NumberInput
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
class SelectInput extends React.Component {
|
||||
export default class FieldSelect extends React.Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.string.isRequired,
|
||||
"data-wd-key": PropTypes.string,
|
||||
|
@ -31,4 +31,3 @@ class SelectInput extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default SelectInput
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
class StringInput extends React.Component {
|
||||
export default class FieldString extends React.Component {
|
||||
static propTypes = {
|
||||
"data-wd-key": PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
|
@ -90,4 +90,3 @@ class StringInput extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default StringInput
|
|
@ -1,9 +1,9 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import AutocompleteInput from './AutocompleteInput'
|
||||
import FieldAutocomplete from './FieldAutocomplete'
|
||||
|
||||
|
||||
class IconInput extends React.Component {
|
||||
export default class FieldSymbol extends React.Component {
|
||||
static propTypes = {
|
||||
value: PropTypes.string,
|
||||
icons: PropTypes.array,
|
||||
|
@ -16,7 +16,7 @@ class IconInput extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
return <AutocompleteInput
|
||||
return <FieldAutocomplete
|
||||
value={this.props.value}
|
||||
options={this.props.icons.map(f => [f, f])}
|
||||
onChange={this.props.onChange}
|
||||
|
@ -25,4 +25,3 @@ class IconInput extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default IconInput
|
|
@ -1,7 +1,7 @@
|
|||
import React, {Fragment} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import StringInput from './StringInput'
|
||||
import SmallError from '../util/SmallError'
|
||||
import FieldString from './FieldString'
|
||||
import SmallError from './SmallError'
|
||||
|
||||
|
||||
function validate (url) {
|
||||
|
@ -48,7 +48,7 @@ function validate (url) {
|
|||
return error;
|
||||
}
|
||||
|
||||
class UrlInput extends React.Component {
|
||||
export default class FieldUrl extends React.Component {
|
||||
static propTypes = {
|
||||
"data-wd-key": PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
|
@ -88,7 +88,7 @@ class UrlInput extends React.Component {
|
|||
render () {
|
||||
return (
|
||||
<div>
|
||||
<StringInput
|
||||
<FieldString
|
||||
{...this.props}
|
||||
onInput={this.onInput}
|
||||
onChange={this.onChange}
|
||||
|
@ -99,4 +99,3 @@ class UrlInput extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default UrlInput
|
|
@ -1,17 +1,16 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { combiningFilterOps } from '../../libs/filterops.js'
|
||||
import { combiningFilterOps } from '../libs/filterops.js'
|
||||
import {mdiTableRowPlusAfter} from '@mdi/js';
|
||||
|
||||
import {latest, validate, migrate} from '@mapbox/mapbox-gl-style-spec'
|
||||
import DocLabel from '../fields/DocLabel'
|
||||
import SelectInput from '../inputs/SelectInput'
|
||||
import InputBlock from '../inputs/InputBlock'
|
||||
import FieldSelect from './FieldSelect'
|
||||
import Block from './Block'
|
||||
import SingleFilterEditor from './SingleFilterEditor'
|
||||
import FilterEditorBlock from './FilterEditorBlock'
|
||||
import Button from '../Button'
|
||||
import SpecDoc from '../inputs/SpecDoc'
|
||||
import ExpressionProperty from '../fields/_ExpressionProperty';
|
||||
import Button from './Button'
|
||||
import Doc from './Doc'
|
||||
import ExpressionProperty from './_ExpressionProperty';
|
||||
import {mdiFunctionVariant} from '@mdi/js';
|
||||
|
||||
|
||||
|
@ -94,7 +93,7 @@ function hasNestedCombiningFilter(filter) {
|
|||
return false
|
||||
}
|
||||
|
||||
export default class CombiningFilterEditor extends React.Component {
|
||||
export default class FilterEditor extends React.Component {
|
||||
static propTypes = {
|
||||
/** Properties of the vector layer and the available fields */
|
||||
properties: PropTypes.object,
|
||||
|
@ -244,18 +243,18 @@ export default class CombiningFilterEditor extends React.Component {
|
|||
|
||||
return (
|
||||
<>
|
||||
<InputBlock
|
||||
<Block
|
||||
key="top"
|
||||
fieldSpec={fieldSpec}
|
||||
label={"Filter"}
|
||||
action={actions}
|
||||
>
|
||||
<SelectInput
|
||||
<FieldSelect
|
||||
value={combiningOp}
|
||||
onChange={this.onFilterPartChanged.bind(this, 0)}
|
||||
options={[["all", "every filter matches"], ["none", "no filter matches"], ["any", "any filter matches"]]}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
{editorBlocks}
|
||||
<div
|
||||
key="buttons"
|
||||
|
@ -276,7 +275,7 @@ export default class CombiningFilterEditor extends React.Component {
|
|||
className="maputnik-doc-inline"
|
||||
style={{display: this.state.showDoc ? '' : 'none'}}
|
||||
>
|
||||
<SpecDoc fieldSpec={fieldSpec} />
|
||||
<Doc fieldSpec={fieldSpec} />
|
||||
</div>
|
||||
</>
|
||||
);
|
|
@ -1,9 +1,9 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Button from '../Button'
|
||||
import Button from './Button'
|
||||
import {MdDelete} from 'react-icons/md'
|
||||
|
||||
class FilterEditorBlock extends React.Component {
|
||||
export default class FilterEditorBlock extends React.Component {
|
||||
static propTypes = {
|
||||
onDelete: PropTypes.func.isRequired,
|
||||
children: PropTypes.element.isRequired,
|
||||
|
@ -27,4 +27,3 @@ class FilterEditorBlock extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default FilterEditorBlock
|
|
@ -2,7 +2,7 @@ import React from 'react'
|
|||
import IconBase from 'react-icon-base'
|
||||
|
||||
|
||||
export default class BackgroundIcon extends React.Component {
|
||||
export default class IconBackground extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<IconBase viewBox="0 0 20 20" {...this.props}>
|
|
@ -2,7 +2,7 @@ import React from 'react'
|
|||
import IconBase from 'react-icon-base'
|
||||
|
||||
|
||||
export default class FillIcon extends React.Component {
|
||||
export default class IconCircle extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<IconBase viewBox="0 0 20 20" {...this.props}>
|
|
@ -2,7 +2,7 @@ import React from 'react'
|
|||
import IconBase from 'react-icon-base'
|
||||
|
||||
|
||||
export default class FillIcon extends React.Component {
|
||||
export default class IconFill extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<IconBase viewBox="0 0 20 20" {...this.props}>
|
33
src/components/IconLayer.jsx
Normal file
33
src/components/IconLayer.jsx
Normal file
|
@ -0,0 +1,33 @@
|
|||
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'
|
||||
|
||||
export default class IconLayer extends React.Component {
|
||||
static propTypes = {
|
||||
type: PropTypes.string.isRequired,
|
||||
style: PropTypes.object,
|
||||
}
|
||||
|
||||
render() {
|
||||
const iconProps = { style: this.props.style }
|
||||
switch(this.props.type) {
|
||||
case 'fill-extrusion': return <IconBackground {...iconProps} />
|
||||
case 'raster': return <IconFill {...iconProps} />
|
||||
case 'hillshade': return <IconFill {...iconProps} />
|
||||
case 'heatmap': return <IconFill {...iconProps} />
|
||||
case 'fill': return <IconFill {...iconProps} />
|
||||
case 'background': return <IconBackground {...iconProps} />
|
||||
case 'line': return <IconLine {...iconProps} />
|
||||
case 'symbol': return <IconSymbol {...iconProps} />
|
||||
case 'circle': return <IconCircle {...iconProps} />
|
||||
default: return <IconMissing {...iconProps} />
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ import React from 'react'
|
|||
import IconBase from 'react-icon-base'
|
||||
|
||||
|
||||
export default class FillIcon extends React.Component {
|
||||
export default class IconLine extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<IconBase viewBox="0 0 20 20" {...this.props}>
|
|
@ -2,7 +2,7 @@ import React from 'react'
|
|||
import {MdPriorityHigh} from 'react-icons/md'
|
||||
|
||||
|
||||
export default class MissingIcon extends React.Component {
|
||||
export default class IconMissing extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<MdPriorityHigh {...this.props} />
|
|
@ -2,7 +2,7 @@ import React from 'react'
|
|||
import IconBase from 'react-icon-base'
|
||||
|
||||
|
||||
export default class SymbolIcon extends React.Component {
|
||||
export default class IconSymbol extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<IconBase viewBox="0 0 20 20" {...this.props}>
|
|
@ -2,23 +2,23 @@ import React from 'react'
|
|||
import PropTypes from 'prop-types'
|
||||
import { Wrapper, Button, Menu, MenuItem } from 'react-aria-menubutton'
|
||||
|
||||
import JSONEditor from './JSONEditor'
|
||||
import FilterEditor from '../filter/FilterEditor'
|
||||
import PropertyGroup from '../fields/PropertyGroup'
|
||||
import FieldJsonEditor from './FieldJsonEditor'
|
||||
import FilterEditor from './FilterEditor'
|
||||
import PropertyGroup from './PropertyGroup'
|
||||
import LayerEditorGroup from './LayerEditorGroup'
|
||||
import LayerTypeBlock from './LayerTypeBlock'
|
||||
import LayerIdBlock from './LayerIdBlock'
|
||||
import MinZoomBlock from './MinZoomBlock'
|
||||
import MaxZoomBlock from './MaxZoomBlock'
|
||||
import CommentBlock from './CommentBlock'
|
||||
import LayerSourceBlock from './LayerSourceBlock'
|
||||
import LayerSourceLayerBlock from './LayerSourceLayerBlock'
|
||||
import BlockType from './BlockType'
|
||||
import BlockId from './BlockId'
|
||||
import BlockMinZoom from './BlockMinZoom'
|
||||
import BlockMaxZoom from './BlockMaxZoom'
|
||||
import BlockComment from './BlockComment'
|
||||
import BlockSource from './BlockSource'
|
||||
import BlockSourceLayer from './BlockSourceLayer'
|
||||
import {Accordion} from 'react-accessible-accordion';
|
||||
|
||||
import {MdMoreVert} from 'react-icons/md'
|
||||
|
||||
import { changeType, changeProperty } from '../../libs/layer'
|
||||
import layout from '../../config/layout.json'
|
||||
import { changeType, changeProperty } from '../libs/layer'
|
||||
import layout from '../config/layout.json'
|
||||
import {formatLayerId} from '../util/format';
|
||||
|
||||
|
||||
|
@ -152,13 +152,13 @@ export default class LayerEditor extends React.Component {
|
|||
|
||||
switch(type) {
|
||||
case 'layer': return <div>
|
||||
<LayerIdBlock
|
||||
<BlockId
|
||||
value={this.props.layer.id}
|
||||
wdKey="layer-editor.layer-id"
|
||||
error={errorData.id}
|
||||
onChange={newId => this.props.onLayerIdChange(this.props.layerIndex, this.props.layer.id, newId)}
|
||||
/>
|
||||
<LayerTypeBlock
|
||||
<BlockType
|
||||
disabled={true}
|
||||
error={errorData.type}
|
||||
value={this.props.layer.type}
|
||||
|
@ -167,7 +167,7 @@ export default class LayerEditor extends React.Component {
|
|||
changeType(this.props.layer, newType)
|
||||
)}
|
||||
/>
|
||||
{this.props.layer.type !== 'background' && <LayerSourceBlock
|
||||
{this.props.layer.type !== 'background' && <BlockSource
|
||||
error={errorData.source}
|
||||
sourceIds={Object.keys(this.props.sources)}
|
||||
value={this.props.layer.source}
|
||||
|
@ -175,24 +175,24 @@ export default class LayerEditor extends React.Component {
|
|||
/>
|
||||
}
|
||||
{['background', 'raster', 'hillshade', 'heatmap'].indexOf(this.props.layer.type) < 0 &&
|
||||
<LayerSourceLayerBlock
|
||||
<BlockSourceLayer
|
||||
error={errorData['source-layer']}
|
||||
sourceLayerIds={sourceLayerIds}
|
||||
value={this.props.layer['source-layer']}
|
||||
onChange={v => this.changeProperty(null, 'source-layer', v)}
|
||||
/>
|
||||
}
|
||||
<MinZoomBlock
|
||||
<BlockMinZoom
|
||||
error={errorData.minzoom}
|
||||
value={this.props.layer.minzoom}
|
||||
onChange={v => this.changeProperty(null, 'minzoom', v)}
|
||||
/>
|
||||
<MaxZoomBlock
|
||||
<BlockMaxZoom
|
||||
error={errorData.maxzoom}
|
||||
value={this.props.layer.maxzoom}
|
||||
onChange={v => this.changeProperty(null, 'maxzoom', v)}
|
||||
/>
|
||||
<CommentBlock
|
||||
<BlockComment
|
||||
error={errorData.comment}
|
||||
value={comment}
|
||||
onChange={v => this.changeProperty('metadata', 'maputnik:comment', v == "" ? undefined : v)}
|
||||
|
@ -215,7 +215,7 @@ export default class LayerEditor extends React.Component {
|
|||
spec={this.props.spec}
|
||||
onChange={this.changeProperty.bind(this)}
|
||||
/>
|
||||
case 'jsoneditor': return <JSONEditor
|
||||
case 'jsoneditor': return <FieldJsonEditor
|
||||
layer={this.props.layer}
|
||||
onChange={(layer) => {
|
||||
this.props.onLayerChanged(
|
|
@ -5,7 +5,7 @@ import lodash from 'lodash';
|
|||
|
||||
import LayerListGroup from './LayerListGroup'
|
||||
import LayerListItem from './LayerListItem'
|
||||
import AddModal from '../modals/AddModal'
|
||||
import ModalAdd from './ModalAdd'
|
||||
|
||||
import {SortableContainer} from 'react-sortable-hoc';
|
||||
|
||||
|
@ -270,7 +270,7 @@ class LayerListContainer extends React.Component {
|
|||
aria-label="Layers list"
|
||||
ref={this.scrollContainerRef}
|
||||
>
|
||||
<AddModal
|
||||
<ModalAdd
|
||||
key={this.state.keys.add}
|
||||
layers={this.props.layers}
|
||||
sources={this.props.sources}
|
|
@ -4,13 +4,13 @@ import classnames from 'classnames'
|
|||
|
||||
import {MdContentCopy, MdVisibility, MdVisibilityOff, MdDelete} from 'react-icons/md'
|
||||
|
||||
import LayerIcon from '../icons/LayerIcon'
|
||||
import IconLayer from './IconLayer'
|
||||
import {SortableElement, SortableHandle} from 'react-sortable-hoc'
|
||||
|
||||
|
||||
const DraggableLabel = SortableHandle((props) => {
|
||||
return <div className="maputnik-layer-list-item-handle">
|
||||
<LayerIcon
|
||||
<IconLayer
|
||||
className="layer-handle__icon"
|
||||
type={props.layerType}
|
||||
/>
|
|
@ -3,16 +3,16 @@ import PropTypes from 'prop-types'
|
|||
import ReactDOM from 'react-dom'
|
||||
import MapboxGl from 'mapbox-gl'
|
||||
import MapboxInspect from 'mapbox-gl-inspect'
|
||||
import FeatureLayerPopup from './FeatureLayerPopup'
|
||||
import FeaturePropertyPopup from './FeaturePropertyPopup'
|
||||
import tokens from '../../config/tokens.json'
|
||||
import MapMapboxGlLayerPopup from './MapMapboxGlLayerPopup'
|
||||
import MapMapboxGlFeaturePropertyPopup from './MapMapboxGlFeaturePropertyPopup'
|
||||
import tokens from '../config/tokens.json'
|
||||
import colors from 'mapbox-gl-inspect/lib/colors'
|
||||
import Color from 'color'
|
||||
import ZoomControl from '../../libs/zoomcontrol'
|
||||
import { colorHighlightedLayer } from '../../libs/highlight'
|
||||
import ZoomControl from '../libs/zoomcontrol'
|
||||
import { colorHighlightedLayer } from '../libs/highlight'
|
||||
import 'mapbox-gl/dist/mapbox-gl.css'
|
||||
import '../../mapboxgl.css'
|
||||
import '../../libs/mapbox-rtl'
|
||||
import '../mapboxgl.css'
|
||||
import '../libs/mapbox-rtl'
|
||||
|
||||
|
||||
const IS_SUPPORTED = MapboxGl.supported();
|
||||
|
@ -52,7 +52,7 @@ function buildInspectStyle(originalMapStyle, coloredLayers, highlightedLayer) {
|
|||
return inspectStyle
|
||||
}
|
||||
|
||||
export default class MapboxGlMap extends React.Component {
|
||||
export default class MapMapboxGl extends React.Component {
|
||||
static propTypes = {
|
||||
onDataChange: PropTypes.func,
|
||||
onLayerSelect: PropTypes.func.isRequired,
|
||||
|
@ -175,9 +175,9 @@ export default class MapboxGlMap extends React.Component {
|
|||
buildInspectStyle: (originalMapStyle, coloredLayers) => buildInspectStyle(originalMapStyle, coloredLayers, this.props.highlightedLayer),
|
||||
renderPopup: features => {
|
||||
if(this.props.inspectModeEnabled) {
|
||||
return renderPopup(<FeaturePropertyPopup features={features} />, tmpNode);
|
||||
return renderPopup(<MapMapboxGlFeaturePropertyPopup features={features} />, tmpNode);
|
||||
} else {
|
||||
return renderPopup(<FeatureLayerPopup features={features} onLayerSelect={this.onLayerSelectById} zoom={this.state.zoom} />, tmpNode);
|
||||
return renderPopup(<MapMapboxGlLayerPopup features={features} onLayerSelect={this.onLayerSelectById} zoom={this.state.zoom} />, tmpNode);
|
||||
}
|
||||
}
|
||||
})
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import InputBlock from '../inputs/InputBlock'
|
||||
import StringInput from '../inputs/StringInput'
|
||||
import Block from './Block'
|
||||
import FieldString from './FieldString'
|
||||
|
||||
function displayValue(value) {
|
||||
if (typeof value === 'undefined' || value === null) return value;
|
||||
|
@ -15,24 +15,24 @@ function displayValue(value) {
|
|||
function renderProperties(feature) {
|
||||
return Object.keys(feature.properties).map(propertyName => {
|
||||
const property = feature.properties[propertyName]
|
||||
return <InputBlock key={propertyName} label={propertyName}>
|
||||
<StringInput value={displayValue(property)} style={{backgroundColor: 'transparent'}}/>
|
||||
</InputBlock>
|
||||
return <Block key={propertyName} label={propertyName}>
|
||||
<FieldString value={displayValue(property)} style={{backgroundColor: 'transparent'}}/>
|
||||
</Block>
|
||||
})
|
||||
}
|
||||
|
||||
function renderFeatureId(feature) {
|
||||
return <InputBlock key={"feature-id"} label={"feature_id"}>
|
||||
<StringInput value={displayValue(feature.id)} style={{backgroundColor: 'transparent'}} />
|
||||
</InputBlock>
|
||||
return <Block key={"feature-id"} label={"feature_id"}>
|
||||
<FieldString value={displayValue(feature.id)} style={{backgroundColor: 'transparent'}} />
|
||||
</Block>
|
||||
}
|
||||
|
||||
function renderFeature(feature, idx) {
|
||||
return <div key={`${feature.sourceLayer}-${idx}`}>
|
||||
<div className="maputnik-popup-layer-id">{feature.layer['source']}: {feature.layer['source-layer']}{feature.inspectModeCounter && <span> × {feature.inspectModeCounter}</span>}</div>
|
||||
<InputBlock key={"property-type"} label={"$type"}>
|
||||
<StringInput value={feature.geometry.type} style={{backgroundColor: 'transparent'}} />
|
||||
</InputBlock>
|
||||
<Block key={"property-type"} label={"$type"}>
|
||||
<FieldString value={feature.geometry.type} style={{backgroundColor: 'transparent'}} />
|
||||
</Block>
|
||||
{renderFeatureId(feature)}
|
||||
{renderProperties(feature)}
|
||||
</div>
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import LayerIcon from '../icons/LayerIcon'
|
||||
import IconLayer from './IconLayer'
|
||||
import {latest, expression, function as styleFunction} from '@mapbox/mapbox-gl-style-spec'
|
||||
|
||||
function groupFeaturesBySourceLayer(features) {
|
||||
|
@ -96,7 +96,7 @@ class FeatureLayerPopup extends React.Component {
|
|||
}}
|
||||
>
|
||||
{feature.layer.type &&
|
||||
<LayerIcon type={feature.layer.type} style={{
|
||||
<IconLayer type={feature.layer.type} style={{
|
||||
width: 14,
|
||||
height: 14,
|
||||
paddingRight: 3
|
|
@ -1,9 +1,9 @@
|
|||
import React from 'react'
|
||||
import {throttle} from 'lodash';
|
||||
import PropTypes from 'prop-types'
|
||||
import { loadJSON } from '../../libs/urlopen'
|
||||
import { loadJSON } from '../libs/urlopen'
|
||||
|
||||
import FeatureLayerPopup from './FeatureLayerPopup';
|
||||
import MapMapboxGlLayerPopup from './MapMapboxGlLayerPopup';
|
||||
|
||||
import 'ol/ol.css'
|
||||
import {apply} from 'ol-mapbox-style';
|
||||
|
@ -24,7 +24,7 @@ function renderCoords (coords) {
|
|||
}
|
||||
}
|
||||
|
||||
export default class OpenLayersMap extends React.Component {
|
||||
export default class MapOpenLayers extends React.Component {
|
||||
static propTypes = {
|
||||
onDataChange: PropTypes.func,
|
||||
mapStyle: PropTypes.object.isRequired,
|
||||
|
@ -152,7 +152,7 @@ export default class OpenLayersMap extends React.Component {
|
|||
>
|
||||
×
|
||||
</button>
|
||||
<FeatureLayerPopup
|
||||
<MapMapboxGlLayerPopup
|
||||
features={this.state.selectedFeatures || []}
|
||||
onLayerSelect={this.props.onLayerSelect}
|
||||
/>
|
|
@ -5,7 +5,7 @@ import AriaModal from 'react-aria-modal'
|
|||
import classnames from 'classnames';
|
||||
|
||||
|
||||
class Modal extends React.Component {
|
||||
export default class Modal extends React.Component {
|
||||
static propTypes = {
|
||||
"data-wd-key": PropTypes.string,
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
|
@ -73,4 +73,3 @@ class Modal extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default Modal
|
|
@ -1,15 +1,15 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import Button from '../Button'
|
||||
import Button from './Button'
|
||||
import Modal from './Modal'
|
||||
|
||||
import LayerTypeBlock from '../layers/LayerTypeBlock'
|
||||
import LayerIdBlock from '../layers/LayerIdBlock'
|
||||
import LayerSourceBlock from '../layers/LayerSourceBlock'
|
||||
import LayerSourceLayerBlock from '../layers/LayerSourceLayerBlock'
|
||||
import BlockType from './BlockType'
|
||||
import BlockId from './BlockId'
|
||||
import BlockSource from './BlockSource'
|
||||
import BlockSourceLayer from './BlockSourceLayer'
|
||||
|
||||
class AddModal extends React.Component {
|
||||
export default class ModalAdd extends React.Component {
|
||||
static propTypes = {
|
||||
layers: PropTypes.array.isRequired,
|
||||
onLayersChange: PropTypes.func.isRequired,
|
||||
|
@ -129,20 +129,20 @@ class AddModal extends React.Component {
|
|||
className="maputnik-add-modal"
|
||||
>
|
||||
<div className="maputnik-add-layer">
|
||||
<LayerIdBlock
|
||||
<BlockId
|
||||
value={this.state.id}
|
||||
wdKey="add-layer.layer-id"
|
||||
onChange={v => {
|
||||
this.setState({ id: v })
|
||||
}}
|
||||
/>
|
||||
<LayerTypeBlock
|
||||
<BlockType
|
||||
value={this.state.type}
|
||||
wdKey="add-layer.layer-type"
|
||||
onChange={v => this.setState({ type: v })}
|
||||
/>
|
||||
{this.state.type !== 'background' &&
|
||||
<LayerSourceBlock
|
||||
<BlockSource
|
||||
sourceIds={sources}
|
||||
wdKey="add-layer.layer-source-block"
|
||||
value={this.state.source}
|
||||
|
@ -150,7 +150,7 @@ class AddModal extends React.Component {
|
|||
/>
|
||||
}
|
||||
{['background', 'raster', 'hillshade', 'heatmap'].indexOf(this.state.type) < 0 &&
|
||||
<LayerSourceLayerBlock
|
||||
<BlockSourceLayer
|
||||
isFixed={true}
|
||||
sourceLayerIds={layers}
|
||||
value={this.state['source-layer']}
|
||||
|
@ -169,4 +169,3 @@ class AddModal extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default AddModal
|
|
@ -4,7 +4,7 @@ import PropTypes from 'prop-types'
|
|||
import Modal from './Modal'
|
||||
|
||||
|
||||
class DebugModal extends React.Component {
|
||||
export default class ModalDebug extends React.Component {
|
||||
static propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
renderer: PropTypes.string.isRequired,
|
||||
|
@ -70,4 +70,3 @@ class DebugModal extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default DebugModal;
|
|
@ -4,18 +4,18 @@ import Slugify from 'slugify'
|
|||
import { saveAs } from 'file-saver'
|
||||
|
||||
import {format} from '@mapbox/mapbox-gl-style-spec'
|
||||
import InputBlock from '../inputs/InputBlock'
|
||||
import StringInput from '../inputs/StringInput'
|
||||
import CheckboxInput from '../inputs/CheckboxInput'
|
||||
import Button from '../Button'
|
||||
import Block from './Block'
|
||||
import FieldString from './FieldString'
|
||||
import FieldCheckbox from './FieldCheckbox'
|
||||
import Button from './Button'
|
||||
import Modal from './Modal'
|
||||
import {MdFileDownload} from 'react-icons/md'
|
||||
import style from '../../libs/style'
|
||||
import fieldSpecAdditional from '../../libs/field-spec-additional'
|
||||
import style from '../libs/style'
|
||||
import fieldSpecAdditional from '../libs/field-spec-additional'
|
||||
|
||||
|
||||
|
||||
class ExportModal extends React.Component {
|
||||
export default class ModalExport extends React.Component {
|
||||
static propTypes = {
|
||||
mapStyle: PropTypes.object.isRequired,
|
||||
onStyleChanged: PropTypes.func.isRequired,
|
||||
|
@ -75,33 +75,33 @@ class ExportModal extends React.Component {
|
|||
</p>
|
||||
|
||||
<div>
|
||||
<InputBlock
|
||||
<Block
|
||||
label={fieldSpecAdditional.maputnik.mapbox_access_token.label}
|
||||
fieldSpec={fieldSpecAdditional.maputnik.mapbox_access_token}
|
||||
>
|
||||
<StringInput
|
||||
<FieldString
|
||||
value={(this.props.mapStyle.metadata || {})['maputnik:mapbox_access_token']}
|
||||
onChange={this.changeMetadataProperty.bind(this, "maputnik:mapbox_access_token")}
|
||||
/>
|
||||
</InputBlock>
|
||||
<InputBlock
|
||||
</Block>
|
||||
<Block
|
||||
label={fieldSpecAdditional.maputnik.maptiler_access_token.label}
|
||||
fieldSpec={fieldSpecAdditional.maputnik.maptiler_access_token}
|
||||
>
|
||||
<StringInput
|
||||
<FieldString
|
||||
value={(this.props.mapStyle.metadata || {})['maputnik:openmaptiles_access_token']}
|
||||
onChange={this.changeMetadataProperty.bind(this, "maputnik:openmaptiles_access_token")}
|
||||
/>
|
||||
</InputBlock>
|
||||
<InputBlock
|
||||
</Block>
|
||||
<Block
|
||||
label={fieldSpecAdditional.maputnik.thunderforest_access_token.label}
|
||||
fieldSpec={fieldSpecAdditional.maputnik.thunderforest_access_token}
|
||||
>
|
||||
<StringInput
|
||||
<FieldString
|
||||
value={(this.props.mapStyle.metadata || {})['maputnik:thunderforest_access_token']}
|
||||
onChange={this.changeMetadataProperty.bind(this, "maputnik:thunderforest_access_token")}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
|
@ -117,4 +117,3 @@ class ExportModal extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default ExportModal
|
|
@ -1,11 +1,11 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import Button from '../Button'
|
||||
import Button from './Button'
|
||||
import Modal from './Modal'
|
||||
|
||||
|
||||
class LoadingModal extends React.Component {
|
||||
export default class ModalLoading extends React.Component {
|
||||
static propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
onCancel: PropTypes.func.isRequired,
|
||||
|
@ -42,4 +42,3 @@ class LoadingModal extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default LoadingModal
|
|
@ -1,16 +1,16 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import LoadingModal from './LoadingModal'
|
||||
import ModalLoading from './ModalLoading'
|
||||
import Modal from './Modal'
|
||||
import Button from '../Button'
|
||||
import Button from './Button'
|
||||
import FileReaderInput from 'react-file-reader-input'
|
||||
import UrlInput from '../inputs/UrlInput'
|
||||
import FieldUrl from './FieldUrl'
|
||||
|
||||
import {MdFileUpload} from 'react-icons/md'
|
||||
import {MdAddCircleOutline} from 'react-icons/md'
|
||||
|
||||
import style from '../../libs/style.js'
|
||||
import publicStyles from '../../config/styles.json'
|
||||
import style from '../libs/style.js'
|
||||
import publicStyles from '../config/styles.json'
|
||||
|
||||
class PublicStyle extends React.Component {
|
||||
static propTypes = {
|
||||
|
@ -43,7 +43,7 @@ class PublicStyle extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
class OpenModal extends React.Component {
|
||||
export default class ModalOpen extends React.Component {
|
||||
static propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
onOpenToggle: PropTypes.func.isRequired,
|
||||
|
@ -211,7 +211,7 @@ class OpenModal extends React.Component {
|
|||
Load from a URL. Note that the URL must have <a href="https://enable-cors.org" target="_blank" rel="noopener noreferrer">CORS enabled</a>.
|
||||
</p>
|
||||
<form onSubmit={this.onSubmitUrl}>
|
||||
<UrlInput
|
||||
<FieldUrl
|
||||
data-wd-key="modal:open.url.input"
|
||||
type="text"
|
||||
className="maputnik-input"
|
||||
|
@ -242,7 +242,7 @@ class OpenModal extends React.Component {
|
|||
</section>
|
||||
</Modal>
|
||||
|
||||
<LoadingModal
|
||||
<ModalLoading
|
||||
isOpen={!!this.state.activeRequest}
|
||||
title={'Loading style'}
|
||||
onCancel={(e) => this.onCancelActiveRequest(e)}
|
||||
|
@ -253,4 +253,3 @@ class OpenModal extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default OpenModal
|
|
@ -2,18 +2,18 @@ import React from 'react'
|
|||
import PropTypes from 'prop-types'
|
||||
|
||||
import {latest} from '@mapbox/mapbox-gl-style-spec'
|
||||
import InputBlock from '../inputs/InputBlock'
|
||||
import ArrayInput from '../inputs/ArrayInput'
|
||||
import NumberInput from '../inputs/NumberInput'
|
||||
import StringInput from '../inputs/StringInput'
|
||||
import UrlInput from '../inputs/UrlInput'
|
||||
import SelectInput from '../inputs/SelectInput'
|
||||
import EnumInput from '../inputs/EnumInput'
|
||||
import ColorField from '../fields/ColorField'
|
||||
import Block from './Block'
|
||||
import FieldArray from './FieldArray'
|
||||
import FieldNumber from './FieldNumber'
|
||||
import FieldString from './FieldString'
|
||||
import FieldUrl from './FieldUrl'
|
||||
import FieldSelect from './FieldSelect'
|
||||
import FieldEnum from './FieldEnum'
|
||||
import FieldColor from './FieldColor'
|
||||
import Modal from './Modal'
|
||||
import fieldSpecAdditional from '../../libs/field-spec-additional'
|
||||
import fieldSpecAdditional from '../libs/field-spec-additional'
|
||||
|
||||
class SettingsModal extends React.Component {
|
||||
export default class ModalSettings extends React.Component {
|
||||
static propTypes = {
|
||||
mapStyle: PropTypes.object.isRequired,
|
||||
onStyleChanged: PropTypes.func.isRequired,
|
||||
|
@ -87,108 +87,108 @@ class SettingsModal extends React.Component {
|
|||
title={'Style Settings'}
|
||||
>
|
||||
<div className="modal:settings">
|
||||
<InputBlock label={"Name"} fieldSpec={latest.$root.name}>
|
||||
<StringInput {...inputProps}
|
||||
<Block label={"Name"} fieldSpec={latest.$root.name}>
|
||||
<FieldString {...inputProps}
|
||||
data-wd-key="modal:settings.name"
|
||||
value={this.props.mapStyle.name}
|
||||
onChange={this.changeStyleProperty.bind(this, "name")}
|
||||
/>
|
||||
</InputBlock>
|
||||
<InputBlock label={"Owner"} fieldSpec={{doc: "Owner ID of the style. Used by Mapbox or future style APIs."}}>
|
||||
<StringInput {...inputProps}
|
||||
</Block>
|
||||
<Block label={"Owner"} fieldSpec={{doc: "Owner ID of the style. Used by Mapbox or future style APIs."}}>
|
||||
<FieldString {...inputProps}
|
||||
data-wd-key="modal:settings.owner"
|
||||
value={this.props.mapStyle.owner}
|
||||
onChange={this.changeStyleProperty.bind(this, "owner")}
|
||||
/>
|
||||
</InputBlock>
|
||||
<InputBlock label={"Sprite URL"} fieldSpec={latest.$root.sprite}>
|
||||
<UrlInput {...inputProps}
|
||||
</Block>
|
||||
<Block label={"Sprite URL"} fieldSpec={latest.$root.sprite}>
|
||||
<FieldUrl {...inputProps}
|
||||
data-wd-key="modal:settings.sprite"
|
||||
value={this.props.mapStyle.sprite}
|
||||
onChange={this.changeStyleProperty.bind(this, "sprite")}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
|
||||
<InputBlock label={"Glyphs URL"} fieldSpec={latest.$root.glyphs}>
|
||||
<UrlInput {...inputProps}
|
||||
<Block label={"Glyphs URL"} fieldSpec={latest.$root.glyphs}>
|
||||
<FieldUrl {...inputProps}
|
||||
data-wd-key="modal:settings.glyphs"
|
||||
value={this.props.mapStyle.glyphs}
|
||||
onChange={this.changeStyleProperty.bind(this, "glyphs")}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
|
||||
<InputBlock
|
||||
<Block
|
||||
label={fieldSpecAdditional.maputnik.mapbox_access_token.label}
|
||||
fieldSpec={fieldSpecAdditional.maputnik.mapbox_access_token}
|
||||
>
|
||||
<StringInput {...inputProps}
|
||||
<FieldString {...inputProps}
|
||||
data-wd-key="modal:settings.maputnik:mapbox_access_token"
|
||||
value={metadata['maputnik:mapbox_access_token']}
|
||||
onChange={onChangeMetadataProperty.bind(this, "maputnik:mapbox_access_token")}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
|
||||
<InputBlock
|
||||
<Block
|
||||
label={fieldSpecAdditional.maputnik.maptiler_access_token.label}
|
||||
fieldSpec={fieldSpecAdditional.maputnik.maptiler_access_token}
|
||||
>
|
||||
<StringInput {...inputProps}
|
||||
<FieldString {...inputProps}
|
||||
data-wd-key="modal:settings.maputnik:openmaptiles_access_token"
|
||||
value={metadata['maputnik:openmaptiles_access_token']}
|
||||
onChange={onChangeMetadataProperty.bind(this, "maputnik:openmaptiles_access_token")}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
|
||||
<InputBlock
|
||||
<Block
|
||||
label={fieldSpecAdditional.maputnik.thunderforest_access_token.label}
|
||||
fieldSpec={fieldSpecAdditional.maputnik.thunderforest_access_token}
|
||||
>
|
||||
<StringInput {...inputProps}
|
||||
<FieldString {...inputProps}
|
||||
data-wd-key="modal:settings.maputnik:thunderforest_access_token"
|
||||
value={metadata['maputnik:thunderforest_access_token']}
|
||||
onChange={onChangeMetadataProperty.bind(this, "maputnik:thunderforest_access_token")}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
|
||||
<InputBlock label={"Center"} fieldSpec={latest.$root.center}>
|
||||
<ArrayInput
|
||||
<Block label={"Center"} fieldSpec={latest.$root.center}>
|
||||
<FieldArray
|
||||
length={2}
|
||||
type="number"
|
||||
value={mapStyle.center}
|
||||
default={latest.$root.center.default || [0, 0]}
|
||||
onChange={this.changeStyleProperty.bind(this, "center")}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
|
||||
<InputBlock label={"Zoom"} fieldSpec={latest.$root.zoom}>
|
||||
<NumberInput
|
||||
<Block label={"Zoom"} fieldSpec={latest.$root.zoom}>
|
||||
<FieldNumber
|
||||
{...inputProps}
|
||||
value={mapStyle.zoom}
|
||||
default={latest.$root.zoom.default || 0}
|
||||
onChange={this.changeStyleProperty.bind(this, "zoom")}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
|
||||
<InputBlock label={"Bearing"} fieldSpec={latest.$root.bearing}>
|
||||
<NumberInput
|
||||
<Block label={"Bearing"} fieldSpec={latest.$root.bearing}>
|
||||
<FieldNumber
|
||||
{...inputProps}
|
||||
value={mapStyle.bearing}
|
||||
default={latest.$root.bearing.default}
|
||||
onChange={this.changeStyleProperty.bind(this, "bearing")}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
|
||||
<InputBlock label={"Pitch"} fieldSpec={latest.$root.pitch}>
|
||||
<NumberInput
|
||||
<Block label={"Pitch"} fieldSpec={latest.$root.pitch}>
|
||||
<FieldNumber
|
||||
{...inputProps}
|
||||
value={mapStyle.pitch}
|
||||
default={latest.$root.pitch.default}
|
||||
onChange={this.changeStyleProperty.bind(this, "pitch")}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
|
||||
<InputBlock label={"Light anchor"} fieldSpec={latest.light.anchor}>
|
||||
<EnumInput
|
||||
<Block label={"Light anchor"} fieldSpec={latest.light.anchor}>
|
||||
<FieldEnum
|
||||
{...inputProps}
|
||||
name="light-anchor"
|
||||
value={light.anchor}
|
||||
|
@ -196,28 +196,28 @@ class SettingsModal extends React.Component {
|
|||
default={latest.light.anchor.default}
|
||||
onChange={this.changeLightProperty.bind(this, "anchor")}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
|
||||
<InputBlock label={"Light color"} fieldSpec={latest.light.color}>
|
||||
<ColorField
|
||||
<Block label={"Light color"} fieldSpec={latest.light.color}>
|
||||
<FieldColor
|
||||
{...inputProps}
|
||||
value={light.color}
|
||||
default={latest.light.color.default}
|
||||
onChange={this.changeLightProperty.bind(this, "color")}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
|
||||
<InputBlock label={"Light intensity"} fieldSpec={latest.light.intensity}>
|
||||
<NumberInput
|
||||
<Block label={"Light intensity"} fieldSpec={latest.light.intensity}>
|
||||
<FieldNumber
|
||||
{...inputProps}
|
||||
value={light.intensity}
|
||||
default={latest.light.intensity.default}
|
||||
onChange={this.changeLightProperty.bind(this, "intensity")}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
|
||||
<InputBlock label={"Light position"} fieldSpec={latest.light.position}>
|
||||
<ArrayInput
|
||||
<Block label={"Light position"} fieldSpec={latest.light.position}>
|
||||
<FieldArray
|
||||
{...inputProps}
|
||||
type="number"
|
||||
length={latest.light.position.length}
|
||||
|
@ -225,31 +225,31 @@ class SettingsModal extends React.Component {
|
|||
default={latest.light.position.default}
|
||||
onChange={this.changeLightProperty.bind(this, "position")}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
|
||||
<InputBlock label={"Transition delay"} fieldSpec={latest.transition.delay}>
|
||||
<NumberInput
|
||||
<Block label={"Transition delay"} fieldSpec={latest.transition.delay}>
|
||||
<FieldNumber
|
||||
{...inputProps}
|
||||
value={transition.delay}
|
||||
default={latest.transition.delay.default}
|
||||
onChange={this.changeTransitionProperty.bind(this, "delay")}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
|
||||
<InputBlock label={"Transition duration"} fieldSpec={latest.transition.duration}>
|
||||
<NumberInput
|
||||
<Block label={"Transition duration"} fieldSpec={latest.transition.duration}>
|
||||
<FieldNumber
|
||||
{...inputProps}
|
||||
value={transition.duration}
|
||||
default={latest.transition.duration.default}
|
||||
onChange={this.changeTransitionProperty.bind(this, "duration")}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
|
||||
<InputBlock
|
||||
<Block
|
||||
label={fieldSpecAdditional.maputnik.style_renderer.label}
|
||||
fieldSpec={fieldSpecAdditional.maputnik.style_renderer}
|
||||
>
|
||||
<SelectInput {...inputProps}
|
||||
<FieldSelect {...inputProps}
|
||||
data-wd-key="modal:settings.maputnik:renderer"
|
||||
options={[
|
||||
['mbgljs', 'MapboxGL JS'],
|
||||
|
@ -258,7 +258,7 @@ class SettingsModal extends React.Component {
|
|||
value={metadata['maputnik:renderer'] || 'mbgljs'}
|
||||
onChange={onChangeMetadataProperty.bind(this, 'maputnik:renderer')}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
|
||||
|
||||
|
||||
|
@ -267,4 +267,3 @@ class SettingsModal extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default SettingsModal
|
|
@ -4,7 +4,7 @@ import PropTypes from 'prop-types'
|
|||
import Modal from './Modal'
|
||||
|
||||
|
||||
class ShortcutsModal extends React.Component {
|
||||
export default class ModalShortcuts extends React.Component {
|
||||
static propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
onOpenToggle: PropTypes.func.isRequired,
|
||||
|
@ -130,4 +130,3 @@ class ShortcutsModal extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default ShortcutsModal
|
|
@ -2,15 +2,15 @@ import React from 'react'
|
|||
import PropTypes from 'prop-types'
|
||||
import {latest} from '@mapbox/mapbox-gl-style-spec'
|
||||
import Modal from './Modal'
|
||||
import Button from '../Button'
|
||||
import InputBlock from '../inputs/InputBlock'
|
||||
import StringInput from '../inputs/StringInput'
|
||||
import SelectInput from '../inputs/SelectInput'
|
||||
import SourceTypeEditor from '../sources/SourceTypeEditor'
|
||||
import Button from './Button'
|
||||
import Block from './Block'
|
||||
import FieldString from './FieldString'
|
||||
import FieldSelect from './FieldSelect'
|
||||
import ModalSourcesTypeEditor from './ModalSourcesTypeEditor'
|
||||
|
||||
import style from '../../libs/style'
|
||||
import { deleteSource, addSource, changeSource } from '../../libs/source'
|
||||
import publicSources from '../../config/tilesets.json'
|
||||
import style from '../libs/style'
|
||||
import { deleteSource, addSource, changeSource } from '../libs/source'
|
||||
import publicSources from '../config/tilesets.json'
|
||||
|
||||
import {MdAddCircleOutline, MdDelete} from 'react-icons/md'
|
||||
|
||||
|
@ -69,7 +69,7 @@ function editorMode(source) {
|
|||
return null
|
||||
}
|
||||
|
||||
class ActiveSourceTypeEditor extends React.Component {
|
||||
class ActiveModalSourcesTypeEditor extends React.Component {
|
||||
static propTypes = {
|
||||
sourceId: PropTypes.string.isRequired,
|
||||
source: PropTypes.object.isRequired,
|
||||
|
@ -92,7 +92,7 @@ class ActiveSourceTypeEditor extends React.Component {
|
|||
</Button>
|
||||
</div>
|
||||
<div className="maputnik-active-source-type-editor-content">
|
||||
<SourceTypeEditor
|
||||
<ModalSourcesTypeEditor
|
||||
onChange={this.props.onChange}
|
||||
mode={editorMode(this.props.source)}
|
||||
source={this.props.source}
|
||||
|
@ -207,14 +207,14 @@ class AddSource extends React.Component {
|
|||
};
|
||||
|
||||
return <div className="maputnik-add-source">
|
||||
<InputBlock label={"Source ID"} fieldSpec={{doc: "Unique ID that identifies the source and is used in the layer to reference the source."}}>
|
||||
<StringInput
|
||||
<Block label={"Source ID"} fieldSpec={{doc: "Unique ID that identifies the source and is used in the layer to reference the source."}}>
|
||||
<FieldString
|
||||
value={this.state.sourceId}
|
||||
onChange={v => this.setState({ sourceId: v})}
|
||||
/>
|
||||
</InputBlock>
|
||||
<InputBlock label={"Source Type"} fieldSpec={sourceTypeFieldSpec}>
|
||||
<SelectInput
|
||||
</Block>
|
||||
<Block label={"Source Type"} fieldSpec={sourceTypeFieldSpec}>
|
||||
<FieldSelect
|
||||
options={[
|
||||
['geojson_json', 'GeoJSON (JSON)'],
|
||||
['geojson_url', 'GeoJSON (URL)'],
|
||||
|
@ -230,8 +230,8 @@ class AddSource extends React.Component {
|
|||
onChange={mode => this.setState({mode: mode, source: this.defaultSource(mode)})}
|
||||
value={this.state.mode}
|
||||
/>
|
||||
</InputBlock>
|
||||
<SourceTypeEditor
|
||||
</Block>
|
||||
<ModalSourcesTypeEditor
|
||||
onChange={this.onChangeSource}
|
||||
mode={this.state.mode}
|
||||
source={this.state.source}
|
||||
|
@ -246,7 +246,7 @@ class AddSource extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
class SourcesModal extends React.Component {
|
||||
export default class ModalSources extends React.Component {
|
||||
static propTypes = {
|
||||
mapStyle: PropTypes.object.isRequired,
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
|
@ -264,7 +264,7 @@ class SourcesModal extends React.Component {
|
|||
const mapStyle = this.props.mapStyle
|
||||
const activeSources = Object.keys(mapStyle.sources).map(sourceId => {
|
||||
const source = mapStyle.sources[sourceId]
|
||||
return <ActiveSourceTypeEditor
|
||||
return <ActiveModalSourcesTypeEditor
|
||||
key={sourceId}
|
||||
sourceId={sourceId}
|
||||
source={source}
|
||||
|
@ -317,4 +317,3 @@ class SourcesModal extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default SourcesModal
|
|
@ -1,14 +1,14 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {latest} from '@mapbox/mapbox-gl-style-spec'
|
||||
import InputBlock from '../inputs/InputBlock'
|
||||
import StringInput from '../inputs/StringInput'
|
||||
import UrlInput from '../inputs/UrlInput'
|
||||
import NumberInput from '../inputs/NumberInput'
|
||||
import SelectInput from '../inputs/SelectInput'
|
||||
import DynamicArrayInput from '../inputs/DynamicArrayInput'
|
||||
import ArrayInput from '../inputs/ArrayInput'
|
||||
import JSONEditor from '../layers/JSONEditor'
|
||||
import Block from './Block'
|
||||
import FieldString from './FieldString'
|
||||
import FieldUrl from './FieldUrl'
|
||||
import FieldNumber from './FieldNumber'
|
||||
import FieldSelect from './FieldSelect'
|
||||
import FieldDynamicArray from './FieldDynamicArray'
|
||||
import FieldArray from './FieldArray'
|
||||
import FieldJsonEditor from './FieldJsonEditor'
|
||||
|
||||
|
||||
class TileJSONSourceEditor extends React.Component {
|
||||
|
@ -20,15 +20,15 @@ class TileJSONSourceEditor extends React.Component {
|
|||
|
||||
render() {
|
||||
return <div>
|
||||
<InputBlock label={"TileJSON URL"} fieldSpec={latest.source_vector.url}>
|
||||
<UrlInput
|
||||
<Block label={"TileJSON URL"} fieldSpec={latest.source_vector.url}>
|
||||
<FieldUrl
|
||||
value={this.props.source.url}
|
||||
onChange={url => this.props.onChange({
|
||||
...this.props.source,
|
||||
url: url
|
||||
})}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
{this.props.children}
|
||||
</div>
|
||||
}
|
||||
|
@ -50,36 +50,36 @@ class TileURLSourceEditor extends React.Component {
|
|||
|
||||
renderTileUrls() {
|
||||
const tiles = this.props.source.tiles || [];
|
||||
return <InputBlock label={"Tile URL"} fieldSpec={latest.source_vector.tiles}>
|
||||
<DynamicArrayInput
|
||||
return <Block label={"Tile URL"} fieldSpec={latest.source_vector.tiles}>
|
||||
<FieldDynamicArray
|
||||
type="url"
|
||||
value={tiles}
|
||||
onChange={this.changeTileUrls.bind(this)}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div>
|
||||
{this.renderTileUrls()}
|
||||
<InputBlock label={"Min Zoom"} fieldSpec={latest.source_vector.minzoom}>
|
||||
<NumberInput
|
||||
<Block label={"Min Zoom"} fieldSpec={latest.source_vector.minzoom}>
|
||||
<FieldNumber
|
||||
value={this.props.source.minzoom || 0}
|
||||
onChange={minzoom => this.props.onChange({
|
||||
...this.props.source,
|
||||
minzoom: minzoom
|
||||
})}
|
||||
/>
|
||||
</InputBlock>
|
||||
<InputBlock label={"Max Zoom"} fieldSpec={latest.source_vector.maxzoom}>
|
||||
<NumberInput
|
||||
</Block>
|
||||
<Block label={"Max Zoom"} fieldSpec={latest.source_vector.maxzoom}>
|
||||
<FieldNumber
|
||||
value={this.props.source.maxzoom || 22}
|
||||
onChange={maxzoom => this.props.onChange({
|
||||
...this.props.source,
|
||||
maxzoom: maxzoom
|
||||
})}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
{this.props.children}
|
||||
</div>
|
||||
|
||||
|
@ -104,26 +104,26 @@ class ImageSourceEditor extends React.Component {
|
|||
}
|
||||
|
||||
return <div>
|
||||
<InputBlock label={"Image URL"} fieldSpec={latest.source_image.url}>
|
||||
<UrlInput
|
||||
<Block label={"Image URL"} fieldSpec={latest.source_image.url}>
|
||||
<FieldUrl
|
||||
value={this.props.source.url}
|
||||
onChange={url => this.props.onChange({
|
||||
...this.props.source,
|
||||
url,
|
||||
})}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
{["top left", "top right", "bottom right", "bottom left"].map((label, idx) => {
|
||||
return (
|
||||
<InputBlock label={`Coord ${label}`} key={label}>
|
||||
<ArrayInput
|
||||
<Block label={`Coord ${label}`} key={label}>
|
||||
<FieldArray
|
||||
length={2}
|
||||
type="number"
|
||||
value={this.props.source.coordinates[idx]}
|
||||
default={[0, 0]}
|
||||
onChange={(val) => changeCoord(idx, val)}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
@ -155,25 +155,25 @@ class VideoSourceEditor extends React.Component {
|
|||
}
|
||||
|
||||
return <div>
|
||||
<InputBlock label={"Video URL"} fieldSpec={latest.source_video.urls}>
|
||||
<DynamicArrayInput
|
||||
<Block label={"Video URL"} fieldSpec={latest.source_video.urls}>
|
||||
<FieldDynamicArray
|
||||
type="string"
|
||||
value={this.props.source.urls}
|
||||
default={""}
|
||||
onChange={changeUrls}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
{["top left", "top right", "bottom right", "bottom left"].map((label, idx) => {
|
||||
return (
|
||||
<InputBlock label={`Coord ${label}`} key={label}>
|
||||
<ArrayInput
|
||||
<Block label={`Coord ${label}`} key={label}>
|
||||
<FieldArray
|
||||
length={2}
|
||||
type="number"
|
||||
value={this.props.source.coordinates[idx]}
|
||||
default={[0, 0]}
|
||||
onChange={val => changeCoord(idx, val)}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
@ -187,27 +187,27 @@ class GeoJSONSourceUrlEditor extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
return <InputBlock label={"GeoJSON URL"} fieldSpec={latest.source_geojson.data}>
|
||||
<UrlInput
|
||||
return <Block label={"GeoJSON URL"} fieldSpec={latest.source_geojson.data}>
|
||||
<FieldUrl
|
||||
value={this.props.source.data}
|
||||
onChange={data => this.props.onChange({
|
||||
...this.props.source,
|
||||
data: data
|
||||
})}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
}
|
||||
}
|
||||
|
||||
class GeoJSONSourceJSONEditor extends React.Component {
|
||||
class GeoJSONSourceFieldJsonEditor extends React.Component {
|
||||
static propTypes = {
|
||||
source: PropTypes.object.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
render() {
|
||||
return <InputBlock label={"GeoJSON"} fieldSpec={latest.source_geojson.data}>
|
||||
<JSONEditor
|
||||
return <Block label={"GeoJSON"} fieldSpec={latest.source_geojson.data}>
|
||||
<FieldJsonEditor
|
||||
layer={this.props.source.data}
|
||||
maxHeight={200}
|
||||
mode={{
|
||||
|
@ -222,11 +222,11 @@ class GeoJSONSourceJSONEditor extends React.Component {
|
|||
})
|
||||
}}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
}
|
||||
}
|
||||
|
||||
class SourceTypeEditor extends React.Component {
|
||||
export default class ModalSourcesTypeEditor extends React.Component {
|
||||
static propTypes = {
|
||||
mode: PropTypes.string.isRequired,
|
||||
source: PropTypes.object.isRequired,
|
||||
|
@ -240,15 +240,15 @@ class SourceTypeEditor extends React.Component {
|
|||
}
|
||||
switch(this.props.mode) {
|
||||
case 'geojson_url': return <GeoJSONSourceUrlEditor {...commonProps} />
|
||||
case 'geojson_json': return <GeoJSONSourceJSONEditor {...commonProps} />
|
||||
case 'geojson_json': return <GeoJSONSourceFieldJsonEditor {...commonProps} />
|
||||
case 'tilejson_vector': return <TileJSONSourceEditor {...commonProps} />
|
||||
case 'tilexyz_vector': return <TileURLSourceEditor {...commonProps} />
|
||||
case 'tilejson_raster': return <TileJSONSourceEditor {...commonProps} />
|
||||
case 'tilexyz_raster': return <TileURLSourceEditor {...commonProps} />
|
||||
case 'tilejson_raster-dem': return <TileJSONSourceEditor {...commonProps} />
|
||||
case 'tilexyz_raster-dem': return <TileURLSourceEditor {...commonProps}>
|
||||
<InputBlock label={"Encoding"} fieldSpec={latest.source_raster_dem.encoding}>
|
||||
<SelectInput
|
||||
<Block label={"Encoding"} fieldSpec={latest.source_raster_dem.encoding}>
|
||||
<FieldSelect
|
||||
options={Object.keys(latest.source_raster_dem.encoding.values)}
|
||||
onChange={encoding => this.props.onChange({
|
||||
...this.props.source,
|
||||
|
@ -256,7 +256,7 @@ class SourceTypeEditor extends React.Component {
|
|||
})}
|
||||
value={this.props.source.encoding || latest.source_raster_dem.encoding.default}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
</TileURLSourceEditor>
|
||||
case 'image': return <ImageSourceEditor {...commonProps} />
|
||||
case 'video': return <VideoSourceEditor {...commonProps} />
|
||||
|
@ -265,4 +265,3 @@ class SourceTypeEditor extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default SourceTypeEditor
|
|
@ -1,12 +1,12 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import Button from '../Button'
|
||||
import Button from './Button'
|
||||
import Modal from './Modal'
|
||||
|
||||
import logoImage from 'maputnik-design/logos/logo-color.svg'
|
||||
|
||||
class SurveyModal extends React.Component {
|
||||
export default class ModalSurvey extends React.Component {
|
||||
static propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
onOpenToggle: PropTypes.func.isRequired,
|
||||
|
@ -36,4 +36,3 @@ class SurveyModal extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default SurveyModal
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import FunctionSpecField from './FunctionSpecField'
|
||||
import FieldFunction from './FieldFunction'
|
||||
const iconProperties = ['background-pattern', 'fill-pattern', 'line-pattern', 'fill-extrusion-pattern', 'icon-image']
|
||||
|
||||
/** Extract field spec by {@fieldName} from the {@layerType} in the
|
||||
|
@ -58,7 +58,7 @@ export default class PropertyGroup extends React.Component {
|
|||
const fieldValue = fieldName in paint ? paint[fieldName] : layout[fieldName]
|
||||
const fieldType = fieldName in paint ? 'paint' : 'layout';
|
||||
|
||||
return <FunctionSpecField
|
||||
return <FieldFunction
|
||||
errors={errors}
|
||||
onChange={this.onPropertyChange}
|
||||
key={fieldName}
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
class ScrollContainer extends React.Component {
|
||||
export default class ScrollContainer extends React.Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node
|
||||
}
|
||||
|
@ -13,4 +13,3 @@ class ScrollContainer extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default ScrollContainer
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import { otherFilterOps } from '../../libs/filterops.js'
|
||||
import StringInput from '../inputs/StringInput'
|
||||
import AutocompleteInput from '../inputs/AutocompleteInput'
|
||||
import SelectInput from '../inputs/SelectInput'
|
||||
import { otherFilterOps } from '../libs/filterops.js'
|
||||
import FieldString from './FieldString'
|
||||
import FieldAutocomplete from './FieldAutocomplete'
|
||||
import FieldSelect from './FieldSelect'
|
||||
|
||||
function tryParseInt(v) {
|
||||
if (v === '') return v
|
||||
|
@ -35,7 +35,7 @@ function parseFilter(v) {
|
|||
return v;
|
||||
}
|
||||
|
||||
class SingleFilterEditor extends React.Component {
|
||||
export default class SingleFilterEditor extends React.Component {
|
||||
static propTypes = {
|
||||
filter: PropTypes.array.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
|
@ -64,14 +64,14 @@ class SingleFilterEditor extends React.Component {
|
|||
|
||||
return <div className="maputnik-filter-editor-single">
|
||||
<div className="maputnik-filter-editor-property">
|
||||
<AutocompleteInput
|
||||
<FieldAutocomplete
|
||||
value={propertyName}
|
||||
options={Object.keys(this.props.properties).map(propName => [propName, propName])}
|
||||
onChange={newPropertyName => this.onFilterPartChanged(filterOp, newPropertyName, filterArgs)}
|
||||
/>
|
||||
</div>
|
||||
<div className="maputnik-filter-editor-operator">
|
||||
<SelectInput
|
||||
<FieldSelect
|
||||
value={filterOp}
|
||||
onChange={newFilterOp => this.onFilterPartChanged(newFilterOp, propertyName, filterArgs)}
|
||||
options={otherFilterOps}
|
||||
|
@ -79,7 +79,7 @@ class SingleFilterEditor extends React.Component {
|
|||
</div>
|
||||
{filterArgs.length > 0 &&
|
||||
<div className="maputnik-filter-editor-args">
|
||||
<StringInput
|
||||
<FieldString
|
||||
value={filterArgs.join(',')}
|
||||
onChange={ v=> this.onFilterPartChanged(filterOp, propertyName, v.split(','))}
|
||||
/>
|
||||
|
@ -90,4 +90,3 @@ class SingleFilterEditor extends React.Component {
|
|||
|
||||
}
|
||||
|
||||
export default SingleFilterEditor
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
|
|||
import './SmallError.scss';
|
||||
|
||||
|
||||
class SmallError extends React.Component {
|
||||
export default class SmallError extends React.Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node,
|
||||
}
|
||||
|
@ -17,4 +17,3 @@ class SmallError extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default SmallError
|
|
@ -1,4 +1,4 @@
|
|||
@import '../../styles/vars';
|
||||
@import '../styles/vars';
|
||||
|
||||
.SmallError {
|
||||
color: #E57373;
|
|
@ -1,17 +1,17 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import ColorField from './ColorField'
|
||||
import NumberInput from '../inputs/NumberInput'
|
||||
import CheckboxInput from '../inputs/CheckboxInput'
|
||||
import StringInput from '../inputs/StringInput'
|
||||
import SelectInput from '../inputs/SelectInput'
|
||||
import MultiButtonInput from '../inputs/MultiButtonInput'
|
||||
import ArrayInput from '../inputs/ArrayInput'
|
||||
import DynamicArrayInput from '../inputs/DynamicArrayInput'
|
||||
import FontInput from '../inputs/FontInput'
|
||||
import IconInput from '../inputs/IconInput'
|
||||
import EnumInput from '../inputs/EnumInput'
|
||||
import FieldColor from './FieldColor'
|
||||
import FieldNumber from './FieldNumber'
|
||||
import FieldCheckbox from './FieldCheckbox'
|
||||
import FieldString from './FieldString'
|
||||
import FieldSelect from './FieldSelect'
|
||||
import FieldMultiInput from './FieldMultiInput'
|
||||
import FieldArray from './FieldArray'
|
||||
import FieldDynamicArray from './FieldDynamicArray'
|
||||
import FieldFont from './FieldFont'
|
||||
import FieldSymbol from './FieldSymbol'
|
||||
import FieldEnum from './FieldEnum'
|
||||
import capitalize from 'lodash.capitalize'
|
||||
|
||||
const iconProperties = ['background-pattern', 'fill-pattern', 'line-pattern', 'fill-extrusion-pattern', 'icon-image']
|
||||
|
@ -62,7 +62,7 @@ export default class SpecField extends React.Component {
|
|||
function childNodes() {
|
||||
switch(this.props.fieldSpec.type) {
|
||||
case 'number': return (
|
||||
<NumberInput
|
||||
<FieldNumber
|
||||
{...commonProps}
|
||||
min={this.props.fieldSpec.minimum}
|
||||
max={this.props.fieldSpec.maximum}
|
||||
|
@ -71,7 +71,7 @@ export default class SpecField extends React.Component {
|
|||
case 'enum':
|
||||
const options = Object.keys(this.props.fieldSpec.values).map(v => [v, capitalize(v)])
|
||||
|
||||
return <EnumInput
|
||||
return <FieldEnum
|
||||
{...commonProps}
|
||||
options={options}
|
||||
/>
|
||||
|
@ -79,40 +79,40 @@ export default class SpecField extends React.Component {
|
|||
case 'formatted':
|
||||
case 'string':
|
||||
if(iconProperties.indexOf(this.props.fieldName) >= 0) {
|
||||
return <IconInput
|
||||
return <FieldSymbol
|
||||
{...commonProps}
|
||||
icons={this.props.fieldSpec.values}
|
||||
/>
|
||||
} else {
|
||||
return <StringInput
|
||||
return <FieldString
|
||||
{...commonProps}
|
||||
/>
|
||||
}
|
||||
case 'color': return (
|
||||
<ColorField
|
||||
<FieldColor
|
||||
{...commonProps}
|
||||
/>
|
||||
)
|
||||
case 'boolean': return (
|
||||
<CheckboxInput
|
||||
<FieldCheckbox
|
||||
{...commonProps}
|
||||
/>
|
||||
)
|
||||
case 'array':
|
||||
if(this.props.fieldName === 'text-font') {
|
||||
return <FontInput
|
||||
return <FieldFont
|
||||
{...commonProps}
|
||||
fonts={this.props.fieldSpec.values}
|
||||
/>
|
||||
} else {
|
||||
if (this.props.fieldSpec.length) {
|
||||
return <ArrayInput
|
||||
return <FieldArray
|
||||
{...commonProps}
|
||||
type={this.props.fieldSpec.value}
|
||||
length={this.props.fieldSpec.length}
|
||||
/>
|
||||
} else {
|
||||
return <DynamicArrayInput
|
||||
return <FieldDynamicArray
|
||||
{...commonProps}
|
||||
fieldSpec={this.props.fieldSpec}
|
||||
type={this.props.fieldSpec.value}
|
|
@ -2,15 +2,15 @@ import React from 'react'
|
|||
import PropTypes from 'prop-types'
|
||||
import {mdiFunctionVariant, mdiTableRowPlusAfter} from '@mdi/js';
|
||||
|
||||
import Button from '../Button'
|
||||
import Button from './Button'
|
||||
import SpecField from './SpecField'
|
||||
import NumberInput from '../inputs/NumberInput'
|
||||
import StringInput from '../inputs/StringInput'
|
||||
import SelectInput from '../inputs/SelectInput'
|
||||
import DocLabel from './DocLabel'
|
||||
import InputBlock from '../inputs/InputBlock'
|
||||
import docUid from '../../libs/document-uid'
|
||||
import sortNumerically from '../../libs/sort-numerically'
|
||||
import FieldNumber from './FieldNumber'
|
||||
import FieldString from './FieldString'
|
||||
import FieldSelect from './FieldSelect'
|
||||
import Doc from './Doc'
|
||||
import Block from './Block'
|
||||
import docUid from '../libs/document-uid'
|
||||
import sortNumerically from '../libs/sort-numerically'
|
||||
import {findDefaultFromSpec} from '../util/spec-helper';
|
||||
|
||||
import labelFromFieldName from './_labelFromFieldName'
|
||||
|
@ -195,16 +195,16 @@ export default class DataProperty extends React.Component {
|
|||
|
||||
let dataInput;
|
||||
if(this.props.value.type === "categorical") {
|
||||
dataInput = <StringInput {...dataProps} />
|
||||
dataInput = <FieldString {...dataProps} />
|
||||
}
|
||||
else {
|
||||
dataInput = <NumberInput {...dataProps} />
|
||||
dataInput = <FieldNumber {...dataProps} />
|
||||
}
|
||||
|
||||
let zoomInput = null;
|
||||
if(zoomLevel !== undefined) {
|
||||
zoomInput = <div className="maputnik-data-spec-property-stop-edit">
|
||||
<NumberInput
|
||||
<FieldNumber
|
||||
value={zoomLevel}
|
||||
onChange={newZoom => this.changeStop(idx, {zoom: newZoom, value: dataLevel}, value)}
|
||||
min={0}
|
||||
|
@ -223,7 +223,7 @@ export default class DataProperty extends React.Component {
|
|||
}).join("");
|
||||
const error = message ? {message} : undefined;
|
||||
|
||||
return <InputBlock
|
||||
return <Block
|
||||
error={error}
|
||||
key={key}
|
||||
action={deleteStopBtn}
|
||||
|
@ -241,22 +241,22 @@ export default class DataProperty extends React.Component {
|
|||
onChange={(_, newValue) => this.changeStop(idx, {zoom: zoomLevel, value: dataLevel}, newValue)}
|
||||
/>
|
||||
</div>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
})
|
||||
}
|
||||
|
||||
return <div className="maputnik-data-spec-block">
|
||||
<div className="maputnik-data-spec-property">
|
||||
<InputBlock
|
||||
<Block
|
||||
fieldSpec={this.props.fieldSpec}
|
||||
label={labelFromFieldName(this.props.fieldName)}
|
||||
>
|
||||
<div className="maputnik-data-spec-property-group">
|
||||
<DocLabel
|
||||
<Doc
|
||||
label="Type"
|
||||
/>
|
||||
<div className="maputnik-data-spec-property-input">
|
||||
<SelectInput
|
||||
<FieldSelect
|
||||
value={this.props.value.type}
|
||||
onChange={propVal => this.changeDataProperty("type", propVal)}
|
||||
title={"Select a type of data scale (default is 'categorical')."}
|
||||
|
@ -265,11 +265,11 @@ export default class DataProperty extends React.Component {
|
|||
</div>
|
||||
</div>
|
||||
<div className="maputnik-data-spec-property-group">
|
||||
<DocLabel
|
||||
<Doc
|
||||
label="Property"
|
||||
/>
|
||||
<div className="maputnik-data-spec-property-input">
|
||||
<StringInput
|
||||
<FieldString
|
||||
value={this.props.value.property}
|
||||
title={"Input a data property to base styles off of."}
|
||||
onChange={propVal => this.changeDataProperty("property", propVal)}
|
||||
|
@ -278,7 +278,7 @@ export default class DataProperty extends React.Component {
|
|||
</div>
|
||||
{dataFields &&
|
||||
<div className="maputnik-data-spec-property-group">
|
||||
<DocLabel
|
||||
<Doc
|
||||
label="Default"
|
||||
/>
|
||||
<div className="maputnik-data-spec-property-input">
|
||||
|
@ -291,7 +291,7 @@ export default class DataProperty extends React.Component {
|
|||
</div>
|
||||
</div>
|
||||
}
|
||||
</InputBlock>
|
||||
</Block>
|
||||
</div>
|
||||
{dataFields &&
|
||||
<>
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import Button from '../Button'
|
||||
import Button from './Button'
|
||||
import {MdDelete} from 'react-icons/md'
|
||||
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import InputBlock from '../inputs/InputBlock'
|
||||
import Button from '../Button'
|
||||
import Block from './Block'
|
||||
import Button from './Button'
|
||||
import {MdDelete, MdUndo} from 'react-icons/md'
|
||||
import StringInput from '../inputs/StringInput'
|
||||
import FieldString from './FieldString'
|
||||
|
||||
import labelFromFieldName from './_labelFromFieldName'
|
||||
import stringifyPretty from 'json-stringify-pretty-compact'
|
||||
import JSONEditor from '../layers/JSONEditor'
|
||||
import FieldJsonEditor from './FieldJsonEditor'
|
||||
|
||||
|
||||
export default class ExpressionProperty extends React.Component {
|
||||
|
@ -107,14 +107,14 @@ export default class ExpressionProperty extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
return <InputBlock
|
||||
return <Block
|
||||
error={foundErrors}
|
||||
fieldSpec={this.props.fieldSpec}
|
||||
label={labelFromFieldName(this.props.fieldName)}
|
||||
action={deleteStopBtn}
|
||||
wideMode={true}
|
||||
>
|
||||
<JSONEditor
|
||||
<FieldJsonEditor
|
||||
mode={{name: "mgl"}}
|
||||
lint={{
|
||||
context: "expression",
|
||||
|
@ -132,6 +132,6 @@ export default class ExpressionProperty extends React.Component {
|
|||
getValue={getValue}
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import Button from '../Button'
|
||||
import Button from './Button'
|
||||
import {MdFunctions, MdInsertChart} from 'react-icons/md'
|
||||
import {mdiFunctionVariant} from '@mdi/js';
|
||||
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
|
|||
|
||||
import SpecField from './SpecField'
|
||||
import FunctionButtons from './_FunctionButtons'
|
||||
import InputBlock from '../inputs/InputBlock'
|
||||
import Block from './Block'
|
||||
|
||||
import labelFromFieldName from './_labelFromFieldName'
|
||||
|
||||
|
@ -37,13 +37,13 @@ export default class SpecProperty extends React.Component {
|
|||
|
||||
const error = errors[fieldType+"."+fieldName];
|
||||
|
||||
return <InputBlock
|
||||
return <Block
|
||||
error={error}
|
||||
fieldSpec={this.props.fieldSpec}
|
||||
label={labelFromFieldName(this.props.fieldName)}
|
||||
action={functionBtn}
|
||||
>
|
||||
<SpecField {...this.props} />
|
||||
</InputBlock>
|
||||
</Block>
|
||||
}
|
||||
}
|
|
@ -2,16 +2,16 @@ import React from 'react'
|
|||
import PropTypes from 'prop-types'
|
||||
import {mdiFunctionVariant, mdiTableRowPlusAfter} from '@mdi/js';
|
||||
|
||||
import Button from '../Button'
|
||||
import Button from './Button'
|
||||
import SpecField from './SpecField'
|
||||
import NumberInput from '../inputs/NumberInput'
|
||||
import InputBlock from '../inputs/InputBlock'
|
||||
import FieldNumber from './FieldNumber'
|
||||
import Block from './Block'
|
||||
|
||||
import DeleteStopButton from './_DeleteStopButton'
|
||||
import labelFromFieldName from './_labelFromFieldName'
|
||||
|
||||
import docUid from '../../libs/document-uid'
|
||||
import sortNumerically from '../../libs/sort-numerically'
|
||||
import docUid from '../libs/document-uid'
|
||||
import sortNumerically from '../libs/sort-numerically'
|
||||
|
||||
|
||||
/**
|
||||
|
@ -143,7 +143,7 @@ export default class ZoomProperty extends React.Component {
|
|||
}).join("");
|
||||
const error = message ? {message} : undefined;
|
||||
|
||||
return <InputBlock
|
||||
return <Block
|
||||
error={error}
|
||||
key={key}
|
||||
fieldSpec={this.props.fieldSpec}
|
||||
|
@ -152,7 +152,7 @@ export default class ZoomProperty extends React.Component {
|
|||
>
|
||||
<div>
|
||||
<div className="maputnik-zoom-spec-property-stop-edit">
|
||||
<NumberInput
|
||||
<FieldNumber
|
||||
value={zoomLevel}
|
||||
onChange={changedStop => this.changeZoomStop(idx, changedStop, value)}
|
||||
min={0}
|
||||
|
@ -168,7 +168,7 @@ export default class ZoomProperty extends React.Component {
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
</InputBlock>
|
||||
</Block>
|
||||
});
|
||||
|
||||
return <div className="maputnik-zoom-spec-property">
|
|
@ -1,34 +0,0 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import LineIcon from './LineIcon.jsx'
|
||||
import FillIcon from './FillIcon.jsx'
|
||||
import SymbolIcon from './SymbolIcon.jsx'
|
||||
import BackgroundIcon from './BackgroundIcon.jsx'
|
||||
import CircleIcon from './CircleIcon.jsx'
|
||||
import MissingIcon from './MissingIcon.jsx'
|
||||
|
||||
class LayerIcon extends React.Component {
|
||||
static propTypes = {
|
||||
type: PropTypes.string.isRequired,
|
||||
style: PropTypes.object,
|
||||
}
|
||||
|
||||
render() {
|
||||
const iconProps = { style: this.props.style }
|
||||
switch(this.props.type) {
|
||||
case 'fill-extrusion': return <BackgroundIcon {...iconProps} />
|
||||
case 'raster': return <FillIcon {...iconProps} />
|
||||
case 'hillshade': return <FillIcon {...iconProps} />
|
||||
case 'heatmap': return <FillIcon {...iconProps} />
|
||||
case 'fill': return <FillIcon {...iconProps} />
|
||||
case 'background': return <BackgroundIcon {...iconProps} />
|
||||
case 'line': return <LineIcon {...iconProps} />
|
||||
case 'symbol': return <SymbolIcon {...iconProps} />
|
||||
case 'circle': return <CircleIcon {...iconProps} />
|
||||
default: return <MissingIcon {...iconProps} />
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default LayerIcon
|
26
stories/0-Welcome.stories.js
Normal file
26
stories/0-Welcome.stories.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
import '../src/styles/index.scss';
|
||||
import React from 'react';
|
||||
import {Describe} from './ui';
|
||||
|
||||
|
||||
export default {
|
||||
title: 'Welcome',
|
||||
};
|
||||
|
||||
export const ToStorybook = () => {
|
||||
return (
|
||||
<Describe>
|
||||
<h1>Maputnik component library</h1>
|
||||
<p>
|
||||
This is the Maputnik component library, which shows the uses of some commonly used components from the Maputnik editor. This is a stand alone place where we can better refine them and improve their API separate from their use inside the editor.
|
||||
</p>
|
||||
<p>
|
||||
This should also help us better refine our CSS and make it more modular as currently we rely on the cascade quite a bit in a number of places.
|
||||
</p>
|
||||
</Describe>
|
||||
);
|
||||
}
|
||||
|
||||
ToStorybook.story = {
|
||||
name: 'Intro',
|
||||
};
|
21
stories/Button.stories.js
Normal file
21
stories/Button.stories.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
import React from 'react';
|
||||
import Button from '../src/components/Button';
|
||||
import {action} from '@storybook/addon-actions';
|
||||
import {Wrapper} from './ui';
|
||||
import {withA11y} from '@storybook/addon-a11y';
|
||||
|
||||
|
||||
export default {
|
||||
title: 'Button',
|
||||
component: Button,
|
||||
decorators: [withA11y],
|
||||
};
|
||||
|
||||
export const Basic = () => (
|
||||
<Wrapper>
|
||||
<Button onClick={action('onClick')}>
|
||||
Hello Button
|
||||
</Button>
|
||||
</Wrapper>
|
||||
);
|
||||
|
44
stories/FieldArray.stories.js
Normal file
44
stories/FieldArray.stories.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
import React from 'react';
|
||||
import {useActionState} from './helper';
|
||||
import FieldArray from '../src/components/FieldArray';
|
||||
import {Wrapper} from './ui';
|
||||
import {withA11y} from '@storybook/addon-a11y';
|
||||
|
||||
export default {
|
||||
title: 'FieldArray',
|
||||
component: FieldArray,
|
||||
decorators: [withA11y],
|
||||
};
|
||||
|
||||
|
||||
export const NumberType = () => {
|
||||
const [value, setValue] = useActionState("onChange", [1,2,3]);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldArray
|
||||
type="number"
|
||||
value={value}
|
||||
length={3}
|
||||
onChange={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export const StringType = () => {
|
||||
const [value, setValue] = useActionState("onChange", ["a", "b", "c"]);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldArray
|
||||
type="string"
|
||||
value={value}
|
||||
length={3}
|
||||
onChange={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
|
28
stories/FieldAutocomplete.stories.js
Normal file
28
stories/FieldAutocomplete.stories.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
import React from 'react';
|
||||
import {useActionState} from './helper';
|
||||
import FieldAutocomplete from '../src/components/FieldAutocomplete';
|
||||
import {Wrapper} from './ui';
|
||||
import {withA11y} from '@storybook/addon-a11y';
|
||||
|
||||
export default {
|
||||
title: 'FieldAutocomplete',
|
||||
component: FieldAutocomplete,
|
||||
decorators: [withA11y],
|
||||
};
|
||||
|
||||
|
||||
export const Basic = () => {
|
||||
const options = [["FOO", "foo"], ["BAR", "bar"], ["BAZ", "baz"]];
|
||||
const [value, setValue] = useActionState("onChange", "bar");
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldAutocomplete
|
||||
options={options}
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
39
stories/FieldCheckbox.stories.js
Normal file
39
stories/FieldCheckbox.stories.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
import React from 'react';
|
||||
import {useActionState} from './helper';
|
||||
import FieldCheckbox from '../src/components/FieldCheckbox';
|
||||
import {Wrapper} from './ui';
|
||||
import {withA11y} from '@storybook/addon-a11y';
|
||||
|
||||
export default {
|
||||
title: 'FieldCheckbox',
|
||||
component: FieldCheckbox,
|
||||
decorators: [withA11y],
|
||||
};
|
||||
|
||||
|
||||
export const BasicUnchecked = () => {
|
||||
const [value, setValue] = useActionState("onChange", false);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldCheckbox
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export const BasicChecked = () => {
|
||||
const [value, setValue] = useActionState("onChange", true);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldCheckbox
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
27
stories/FieldColor.stories.js
Normal file
27
stories/FieldColor.stories.js
Normal file
|
@ -0,0 +1,27 @@
|
|||
import React from 'react';
|
||||
import {useActionState} from './helper';
|
||||
import FieldColor from '../src/components/FieldColor';
|
||||
import {Wrapper} from './ui';
|
||||
import {withA11y} from '@storybook/addon-a11y';
|
||||
|
||||
export default {
|
||||
title: 'FieldColor',
|
||||
component: FieldColor,
|
||||
decorators: [withA11y],
|
||||
};
|
||||
|
||||
|
||||
export const Basic = () => {
|
||||
const [color, setColor] = useActionState("onChange", "#ff0000");
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldColor
|
||||
name="color"
|
||||
value={color}
|
||||
onChange={setColor}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
55
stories/FieldDynamicArray.stories.js
Normal file
55
stories/FieldDynamicArray.stories.js
Normal file
|
@ -0,0 +1,55 @@
|
|||
import React from 'react';
|
||||
import {useActionState} from './helper';
|
||||
import FieldDynamicArray from '../src/components/FieldDynamicArray';
|
||||
import {Wrapper} from './ui';
|
||||
import {withA11y} from '@storybook/addon-a11y';
|
||||
|
||||
export default {
|
||||
title: 'FieldDynamicArray',
|
||||
component: FieldDynamicArray,
|
||||
decorators: [withA11y],
|
||||
};
|
||||
|
||||
|
||||
export const NumberType = () => {
|
||||
const [value, setValue] = useActionState("onChange", [1,2,3]);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldDynamicArray
|
||||
type="number"
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export const UrlType = () => {
|
||||
const [value, setValue] = useActionState("onChange", ["http://example.com"]);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldDynamicArray
|
||||
type="url"
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export const EnumType = () => {
|
||||
const [value, setValue] = useActionState("onChange", ["foo"]);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldDynamicArray
|
||||
fieldSpec={{values: {"foo": null, "bar": null, "baz": null}}}
|
||||
type="enum"
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
76
stories/FieldEnum.stories.js
Normal file
76
stories/FieldEnum.stories.js
Normal file
|
@ -0,0 +1,76 @@
|
|||
import React from 'react';
|
||||
import {useActionState} from './helper';
|
||||
import FieldEnum from '../src/components/FieldEnum';
|
||||
import {Wrapper} from './ui';
|
||||
import {withA11y} from '@storybook/addon-a11y';
|
||||
|
||||
export default {
|
||||
title: 'FieldEnum',
|
||||
component: FieldEnum,
|
||||
decorators: [withA11y],
|
||||
};
|
||||
|
||||
|
||||
export const BasicFew = () => {
|
||||
const options = ["Foo", "Bar", "Baz"];
|
||||
const [value, setValue] = useActionState("onChange", "Foo");
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldEnum
|
||||
options={options}
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export const BasicFewWithDefault = () => {
|
||||
const options = ["Foo", "Bar", "Baz"];
|
||||
const [value, setValue] = useActionState("onChange", null);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldEnum
|
||||
options={options}
|
||||
default={"Baz"}
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export const BasicMany = () => {
|
||||
const options = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"];
|
||||
const [value, setValue] = useActionState("onChange", "a");
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldEnum
|
||||
options={options}
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export const BasicManyWithDefault = () => {
|
||||
const options = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"];
|
||||
const [value, setValue] = useActionState("onChange", "a");
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldEnum
|
||||
options={options}A
|
||||
default={"h"}
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
|
28
stories/FieldFont.stories.js
Normal file
28
stories/FieldFont.stories.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
import React from 'react';
|
||||
import {useActionState} from './helper';
|
||||
import FieldFont from '../src/components/FieldFont';
|
||||
import {Wrapper} from './ui';
|
||||
import {withA11y} from '@storybook/addon-a11y';
|
||||
|
||||
export default {
|
||||
title: 'FieldFont',
|
||||
component: FieldFont,
|
||||
decorators: [withA11y],
|
||||
};
|
||||
|
||||
|
||||
export const Basic = () => {
|
||||
const fonts = ["Comic Sans", "Helvectica", "Gotham"];
|
||||
const [value, setValue] = useActionState("onChange", ["Comic Sans"]);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldFont
|
||||
fonts={fonts}
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
28
stories/FieldMultiInput.stories.js
Normal file
28
stories/FieldMultiInput.stories.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
import React from 'react';
|
||||
import {useActionState} from './helper';
|
||||
import FieldMultiInput from '../src/components/FieldMultiInput';
|
||||
import {Wrapper} from './ui';
|
||||
import {withA11y} from '@storybook/addon-a11y';
|
||||
|
||||
export default {
|
||||
title: 'FieldMultiInput',
|
||||
component: FieldMultiInput,
|
||||
decorators: [withA11y],
|
||||
};
|
||||
|
||||
|
||||
export const Basic = () => {
|
||||
const options = [["FOO", "foo"], ["BAR", "bar"], ["BAZ", "baz"]];
|
||||
const [value, setValue] = useActionState("onChange", "FOO");
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldMultiInput
|
||||
options={options}
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
43
stories/FieldNumber.stories.js
Normal file
43
stories/FieldNumber.stories.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
import React from 'react';
|
||||
import {useActionState} from './helper';
|
||||
import FieldNumber from '../src/components/FieldNumber';
|
||||
import {Wrapper} from './ui';
|
||||
import {withA11y} from '@storybook/addon-a11y';
|
||||
|
||||
export default {
|
||||
title: 'FieldNumber',
|
||||
component: FieldNumber,
|
||||
decorators: [withA11y],
|
||||
};
|
||||
|
||||
export const Basic = () => {
|
||||
const [value, setValue] = useActionState("onChange", 1);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldNumber
|
||||
name="number"
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export const Range = () => {
|
||||
const [value, setValue] = useActionState("onChange", 1);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldNumber
|
||||
name="number"
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
min={1}
|
||||
max={24}
|
||||
allowRange={true}
|
||||
rangeStep={1}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
29
stories/FieldSelect.stories.js
Normal file
29
stories/FieldSelect.stories.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
import React from 'react';
|
||||
import {useActionState} from './helper';
|
||||
import FieldSelect from '../src/components/FieldSelect';
|
||||
import {Wrapper} from './ui';
|
||||
import {withA11y} from '@storybook/addon-a11y';
|
||||
|
||||
export default {
|
||||
title: 'FieldSelect',
|
||||
component: FieldSelect,
|
||||
decorators: [withA11y],
|
||||
};
|
||||
|
||||
|
||||
export const Basic = () => {
|
||||
const options = [["FOO", "Foo"], ["BAR", "Bar"], ["BAZ", "Baz"]];
|
||||
const [value, setValue] = useActionState("onChange", "FOO");
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldSelect
|
||||
options={options}
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
|
69
stories/FieldString.stories.js
Normal file
69
stories/FieldString.stories.js
Normal file
|
@ -0,0 +1,69 @@
|
|||
import React from 'react';
|
||||
import {useActionState} from './helper';
|
||||
import FieldString from '../src/components/FieldString';
|
||||
import {Wrapper} from './ui';
|
||||
import {withA11y} from '@storybook/addon-a11y';
|
||||
|
||||
export default {
|
||||
title: 'FieldString',
|
||||
component: FieldString,
|
||||
decorators: [withA11y],
|
||||
};
|
||||
|
||||
|
||||
export const Basic = () => {
|
||||
const [value, setValue] = useActionState("onChange", "Hello world");
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldString
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export const WithDefault = () => {
|
||||
const [value, setValue] = useActionState("onChange", null);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldString
|
||||
value={value}
|
||||
default={"Edit me..."}
|
||||
onChange={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export const Multiline = () => {
|
||||
const [value, setValue] = useActionState("onChange", "Hello\nworld");
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldString
|
||||
multi={true}
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export const MultilineWithDefault = () => {
|
||||
const [value, setValue] = useActionState("onChange", null);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldString
|
||||
multi={true}
|
||||
default={"Edit\nme.."}
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
29
stories/FieldSymbol.stories.js
Normal file
29
stories/FieldSymbol.stories.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
import React from 'react';
|
||||
import {useActionState} from './helper';
|
||||
import FieldSymbol from '../src/components/FieldSymbol';
|
||||
import {Wrapper} from './ui';
|
||||
import {withA11y} from '@storybook/addon-a11y';
|
||||
|
||||
export default {
|
||||
title: 'FieldSymbol',
|
||||
component: FieldSymbol,
|
||||
decorators: [withA11y],
|
||||
};
|
||||
|
||||
|
||||
export const Basic = () => {
|
||||
const icons = ["Bicycle", "Ski", "Ramp"];
|
||||
const [value, setValue] = useActionState("onChange", "Ski");
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldSymbol
|
||||
icons={icons}
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
|
42
stories/FieldUrl.stories.js
Normal file
42
stories/FieldUrl.stories.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
import React from 'react';
|
||||
import {useActionState} from './helper';
|
||||
import FieldUrl from '../src/components/FieldUrl';
|
||||
import {Wrapper} from './ui';
|
||||
import {withA11y} from '@storybook/addon-a11y';
|
||||
|
||||
export default {
|
||||
title: 'FieldUrl',
|
||||
component: FieldUrl,
|
||||
decorators: [withA11y],
|
||||
};
|
||||
|
||||
|
||||
export const Valid = () => {
|
||||
const [value, setValue] = useActionState("onChange", "http://example.com");
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldUrl
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
onInput={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export const Invalid = () => {
|
||||
const [value, setValue] = useActionState("onChange", "foo");
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<FieldUrl
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
onInput={setValue}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
|
12
stories/helper.js
Normal file
12
stories/helper.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
import React, {useState} from 'react';
|
||||
import {action} from '@storybook/addon-actions';
|
||||
|
||||
export function useActionState (name, initialVal) {
|
||||
const [val, fn] = useState(initialVal);
|
||||
const actionFn = action(name);
|
||||
function retFn(val) {
|
||||
actionFn(val);
|
||||
return fn(val);
|
||||
}
|
||||
return [val, retFn];
|
||||
}
|
19
stories/ui.js
Normal file
19
stories/ui.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
import React from 'react';
|
||||
|
||||
|
||||
export function Describe ({children}) {
|
||||
return (
|
||||
<div style={{maxWidth: "600px", margin: "0.8em"}}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function Wrapper ({children}) {
|
||||
return (
|
||||
<div style={{maxWidth: "180px", margin: "0.4em"}}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
Loading…
Reference in a new issue