Kaynağa Gözat

add MassMarks & example.

windsome.feng 7 yıl önce
ebeveyn
işleme
67573e309a
8 değiştirilmiş dosya ile 415 ekleme ve 142 silme
  1. 5 0
      package-lock.json
  2. 1 0
      package.json
  3. 141 1
      src/App.js
  4. 14 11
      src/Map.js
  5. 9 8
      src/Marker.js
  6. 90 0
      src/MassMarks.js
  7. 151 122
      src/api.js
  8. 4 0
      yarn.lock

+ 5 - 0
package-lock.json

@@ -4,6 +4,11 @@
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
+    "classnames": {
+      "version": "2.2.6",
+      "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
+      "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
+    },
     "lodash": {
       "version": "4.17.10",
       "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",

+ 1 - 0
package.json

@@ -3,6 +3,7 @@
   "version": "0.1.0",
   "private": true,
   "dependencies": {
+    "classnames": "^2.2.6",
     "lodash": "^4.17.10",
     "react": "^16.4.1",
     "react-dom": "^16.4.1",

+ 141 - 1
src/App.js

@@ -1,11 +1,14 @@
 import React, { Component } from 'react';
+import cx from 'classnames';
 import './App.css';
 
+import loadJs from './loadScript';
 import { loadMap } from './api';
 import Map from './Map';
 import Marker from './Marker';
+import MassMarks from './MassMarks';
 
-class App extends Component {
+class MarkerTest extends Component {
   constructor() {
     super();
     this.state = {};
@@ -31,6 +34,7 @@ class App extends Component {
   render() {
     return (
       <div>
+      <div>
         <div style={{margin:2}}>
           <span style={{marginRight:2}}>改Map位置:</span>
           <input type='button' onClick={() => this.setState({ center: [116.39, 39.9] })} value='北京' />
@@ -96,6 +100,142 @@ class App extends Component {
           </Marker>
         </Map>
       </div>
+      </div>
+    );
+  }
+
+}
+
+
+class MassMarkTest extends Component {
+  constructor() {
+    super();
+    this.state = {};
+    this._mapDblclick = this._mapDblclick.bind(this);
+    this._changeStyle = this._changeStyle.bind(this);
+  }
+
+  componentDidMount() {
+    loadMap('0325e3d6d69cd56de4980b4f28906fd8').then(AMap => {
+      let roadNet = new AMap.TileLayer.RoadNet();
+      let traffic = new AMap.TileLayer.Traffic({
+        autoRefresh: true, //是否自动刷新,默认为false
+        interval: 15 //刷新间隔,默认180s
+      });
+      let style = [{
+        url: 'https://a.amap.com/jsapi_demos/static/images/mass0.png',
+        anchor: new AMap.Pixel(16, 16),
+        size: new AMap.Size(21, 21)
+      },{
+        url: 'https://a.amap.com/jsapi_demos/static/images/mass1.png',
+        anchor: new AMap.Pixel(24, 24),
+        size: new AMap.Size(17, 17)
+      },{
+        url: 'https://a.amap.com/jsapi_demos/static/images/mass2.png',
+        anchor: new AMap.Pixel(23, 23),
+        size: new AMap.Size(5, 5)
+      }
+    ];
+
+      this.setState({ AMap, layers: [roadNet, traffic], style });
+    });
+    loadJs('https://a.amap.com/jsapi_demos/static/citys.js','js').then(ret => {
+      console.log('ret:', ret, window.citys);
+      // this.setState({citys:window.citys});
+      let citys = window.citys.map ((item, index) => {
+        return {...item, id: index};
+      })
+      this.setState({citys});
+    })
+  }
+
+  _mapDblclick() {
+    this.setState({msg:'双击了Map!'});
+  }
+  _changeStyle(item) {
+    let style = (item.style+1) % 3;
+    let data = this.state.citys
+    let data2 = [...data];
+    data2[item.id] = {...item, style};
+    this.setState({citys:data2});
+  }
+
+  render() {
+    return (
+      <div>
+      <div>
+        <div style={{margin:2}}>
+          <span style={{marginRight:2}}>改Map位置:</span>
+          <input type='button' onClick={() => this.setState({ center: [116.39, 39.9] })} value='北京' />
+          <span onClick={() => this.setState({ center: [115.39, 38.9] })}>
+            北京-1
+          </span>
+          <span onClick={() => this.setState({ center: [114.39, 37.9] })}>
+            北京-2
+          </span>
+        </div>
+        <div style={{margin:2}}>
+          {'消息:'+this.state.msg}
+        </div>
+        <Map
+          AMap={this.state.AMap}
+          style={{ width: 1100, height: 800 }}
+          options={{ center: this.state.center, layers: this.state.layers }}
+          events={{
+            // click:e=>this.setState({msg: '点击了Map'}),
+            dblclick: this._mapDblclick,
+          }}
+      >
+          <MassMarks
+            AMap={this.state.AMap}
+            options={{
+              data: this.state.citys,
+              opacity:0.8,
+              zIndex: 111,
+              cursor:'pointer',
+              style: this.state.style
+            }}
+            events={{
+              click:e=> {
+                console.log('e:', e);
+                this._changeStyle(e.data);
+                this.setState({msg: '点击了MassMarks:'+JSON.stringify(e.data)})
+              }
+            }}
+          >
+          </MassMarks>
+        </Map>
+      </div>
+      </div>
+    );
+  }
+
+}
+
+class App extends Component {
+  constructor() {
+    super();
+    this.state = {};
+  }
+
+  render() {
+    return (
+      <div>
+        <div>
+          <span style={{padding:5, margin: 5, backgroundColor:(this.state.test === 'marker')?'#ff0':'#fff'}} onClick={()=>this.setState({test: 'marker'})}> MarkerTest </span>
+          <span style={{padding:5, margin: 5, backgroundColor:(this.state.test === 'massmarks')?'#ff0':'#fff'}} onClick={()=>this.setState({test: 'massmarks'})}> MassMarksTest </span>
+          <span style={{padding:5, margin: 5, backgroundColor:(this.state.test === 'mess')?'#ff0':'#fff'}} onClick={()=>this.setState({test: 'mess'})}> MessMarkerTest </span>
+        </div>
+        <div>
+          {this.state.test === 'marker' &&
+          <MarkerTest />
+          }
+          {this.state.test === 'massmarks' &&
+          <MassMarkTest />
+          }
+          
+        </div>
+      </div>
     );
   }
 }

+ 14 - 11
src/Map.js

@@ -2,6 +2,8 @@ import React, { Component, PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { loadMap, createMap, updateMap } from './api';
 
+const __com__ = 'Map';
+
 export class Map extends Component {
   static propTypes = {
     AMap: PropTypes.object,
@@ -20,15 +22,15 @@ export class Map extends Component {
     super();
     this.refElement = null;
     this._entity = null;
-    console.log('wcomponent constructor', this.refElement, this._entity);
+    console.log(__com__, 'component constructor', this.refElement, this._entity);
   }
 
   componentWillMount() {
-    console.log('wcomponentWillMount', this.refElement, this._entity);
+    console.log(__com__, 'componentWillMount', this.refElement, this._entity);
   }
 
   componentDidMount() {
-    console.log('wcomponentDidMount', this.refElement, this._entity);
+    console.log(__com__, 'componentDidMount', this.refElement, this._entity);
     let { AMap, refMap, options, events } = this.props;
     this._entity = createMap(AMap, this.refElement, options, events);
     if (this._entity) {
@@ -38,15 +40,15 @@ export class Map extends Component {
   }
 
   componentWillReceiveProps(nextProps) {
-    console.log('wcomponentWillReceiveProps', this.refElement, this._entity);
+    console.log(__com__, 'componentWillReceiveProps', this.refElement, this._entity);
   }
 
   componentWillUpdate() {
-    console.log('wcomponentWillUpdate', this.refElement, this._entity);
+    console.log(__com__, 'componentWillUpdate', this.refElement, this._entity);
   }
 
   componentDidUpdate(prevProps) {
-    console.log('wcomponentDidUpdate', this.refElement, this._entity);
+    console.log(__com__, 'componentDidUpdate', this.refElement, this._entity);
     let { AMap, refMap, options, events } = this.props;
     if (!this._entity) {
       this._entity = createMap(AMap, this.refElement, options, events);
@@ -68,7 +70,7 @@ export class Map extends Component {
   }
 
   componentWillUnmount() {
-    console.log('wcomponentWillUnmount', this.refElement, this._entity);
+    console.log(__com__, 'componentWillUnmount', this.refElement, this._entity);
     if (this._entity) {
       let { refMap } = this.props;
       //   this._entity.clearMap();
@@ -88,24 +90,25 @@ export class Map extends Component {
          * 2. DOM 元素
          */
         if (cType.preventAmap || typeof cType === 'string') {
-          console.log('wcomponent renderChildren orig');
+          console.log(__com__, 'component renderChildren orig');
           return child;
         }
-        console.log('wcomponent renderChildren add __map__');
+        console.log(__com__, 'component renderChildren add __map__');
         return React.cloneElement(child, {
           __map__
         });
       }
-      console.log('wcomponent renderChildren null');
+      console.log(__com__, 'component renderChildren null');
       return child;
     });
   }
 
   render() {
-    console.log('wcomponent render', this.refElement, this._entity);
+    console.log(__com__, 'component render', this.refElement, this._entity);
     let {
       AMap,
       options,
+      events,
       match,
       location,
       history,

+ 9 - 8
src/Marker.js

@@ -1,6 +1,7 @@
 import React, { Component, PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { createMarker, updateMarker } from './api';
+const __component__ = 'Marker';
 
 export class Marker extends Component {
   static propTypes = {
@@ -21,15 +22,15 @@ export class Marker extends Component {
     super();
     this.refElement = null;
     this._entity = null;
-    console.log('maker constructor', this._entity);
+    console.log(__component__, 'constructor', this._entity);
   }
 
   componentWillMount() {
-    console.log('makerWillMount', this.props.children, this._entity);
+    console.log(__component__, 'componentWillMount', this.props.children, this._entity);
   }
 
   componentDidMount() {
-    console.log('makerDidMount', this.props.children, this._entity);
+    console.log(__component__, 'componentDidMount', this.props.children, this._entity);
     let { AMap, __map__, options, events, children } = this.props;
     //let opts = { ...(options || {}), map: __map__, content: children };
     let opts = { ...(options || {}), map: __map__ };
@@ -37,15 +38,15 @@ export class Marker extends Component {
   }
 
   componentWillReceiveProps(nextProps) {
-    console.log('makerWillReceiveProps', this.props.children, this._entity);
+    console.log(__component__, 'componentWillReceiveProps', this.props.children, this._entity);
   }
 
   componentWillUpdate() {
-    console.log('makerWillUpdate', this.props.children, this._entity);
+    console.log(__component__, 'componentWillUpdate', this.props.children, this._entity);
   }
 
   componentDidUpdate(prevProps) {
-    console.log('makerDidUpdate', this.props.children, this._entity);
+    console.log(__component__, 'componentDidUpdate', this.props.children, this._entity);
     let { AMap, __map__, options, events, children } = this.props;
     //let opts = { ...(options || {}), map: __map__, content: children };
     let opts = { ...(options || {}), map: __map__ };
@@ -64,7 +65,7 @@ export class Marker extends Component {
   }
 
   componentWillUnmount() {
-    console.log('makerWillUnmount', this.props.children, this._entity);
+    console.log(__component__, 'componentWillUnmount', this.props.children, this._entity);
     if (this._entity) {
       //   this._entity.clearMap();
       this._entity.setMap(null);
@@ -75,7 +76,7 @@ export class Marker extends Component {
   }
 
   render() {
-    console.log('maker render', this.props.children, this._entity);
+    console.log(__component__, 'render', this.props.children, this._entity);
     let {
       AMap,
       options,

+ 90 - 0
src/MassMarks.js

@@ -0,0 +1,90 @@
+import React, { Component, PureComponent } from 'react';
+import PropTypes from 'prop-types';
+import { createMassMarks, updateMassMarks } from './api';
+const __com__ = 'MassMarks';
+
+export class MassMarks extends Component {
+  static propTypes = {
+    AMap: PropTypes.object,
+    __map__: PropTypes.object,
+    options: PropTypes.object,
+    events: PropTypes.object
+  };
+
+  constructor() {
+    super();
+    this.refElement = null;
+    this._entity = null;
+    console.log(__com__, 'constructor', this._entity);
+  }
+
+  componentWillMount() {
+    console.log(__com__, 'componentWillMount', this.props.children, this._entity);
+  }
+
+  componentDidMount() {
+    console.log(__com__, 'componentDidMount', this.props.children, this._entity);
+    let { AMap, __map__, options, events, children } = this.props;
+    //let opts = { ...(options || {}), map: __map__, content: children };
+    let opts = { ...(options || {}), map: __map__ };
+    this._entity = createMassMarks(AMap, opts, events);
+  }
+
+  componentWillReceiveProps(nextProps) {
+    console.log(__com__, 'componentWillReceiveProps', this.props.children, this._entity);
+  }
+
+  componentWillUpdate() {
+    console.log(__com__, 'componentWillUpdate', this.props.children, this._entity);
+  }
+
+  componentDidUpdate(prevProps) {
+    console.log(__com__, 'componentDidUpdate', this.props.children, this._entity);
+    let { AMap, __map__, options, events, children } = this.props;
+    //let opts = { ...(options || {}), map: __map__, content: children };
+    let opts = { ...(options || {}), map: __map__ };
+    if (!this._entity) {
+      this._entity = createMassMarks(AMap, opts, events);
+      return;
+    }
+
+    // need check props changes, then update.
+    let oldOpts = {
+      ...(prevProps.options || {}),
+      map: prevProps.__map__,
+      content: prevProps.children
+    };
+    updateMassMarks(this._entity, opts, events, oldOpts, prevProps.events);
+  }
+
+  componentWillUnmount() {
+    console.log(__com__, 'componentWillUnmount', this.props.children, this._entity);
+    if (this._entity) {
+      //   this._entity.clearMap();
+      this._entity.setMap(null);
+      delete this._entity;
+      //   delete this._entity;
+      this._entity = null;
+    }
+  }
+
+  render() {
+    console.log(__com__, 'render', this.props.children, this._entity);
+    let {
+      AMap,
+      options,
+      match,
+      location,
+      history,
+      staticContext,
+      ...rest
+    } = this.props;
+    return null;
+    // return (
+    //   <React.Fragment>
+    //   </React.Fragment>
+    // )
+  }
+}
+
+export default MassMarks;

+ 151 - 122
src/api.js

@@ -69,32 +69,35 @@ export const loadPlugin = name => {
 // Map
 ////////////////////////////////////////////////////////////
 export const createMap = (AMap, dom, options, events) => {
+  const __func__ = 'createMap';
   if (!AMap) {
-    console.log('createMap fail! no AMap!');
+    console.log(__func__, 'fail! no AMap!');
     return null;
   }
   if (!dom) {
-    console.log('createMap fail! no dom!');
+    console.log(__func__, 'fail! no dom!');
     return null;
   }
   let map = new AMap.Map(dom, { ...(options || {}) });
   forOwn(events, (value, key) => {
-    console.log('createMap event on ' + key);
+    console.log(__func__, 'event on ' + key);
     map.on(key, value);
   });
-  console.log('createMap ok!');
+  console.log(__func__, 'ok!');
   return map;
 };
 
-export const updateMap = (
-  map,
+export const commonUpdate = (
+  entity,
   newOptions,
   newEvents,
   oldOptions,
-  oldEvents
+  oldEvents,
+  operators
 ) => {
-  if (!map) {
-    console.log('updateMap fail! no map!');
+  const __func__ = 'commonUpdate';
+  if (!entity) {
+    console.log(__func__, 'fail! no entity!');
     return false;
   }
 
@@ -141,6 +144,72 @@ export const updateMap = (
       });
   }
 
+  // let operators = {
+  //   map: v => entity.setMap(v),
+  //   position: v => entity.setPosition(v),
+  //   offset: v => entity.setOffset(v),
+  //   icon: v => entity.setIcon(v),
+  //   content: v => entity.setContent(v),
+  //   topWhenClick: null,
+  //   bubble: null,
+  //   draggable: v => entity.setDraggable(v),
+  //   raiseOnDrag: null,
+  //   cursor: v => entity.setCursor(v),
+  //   visible: null,
+  //   zIndex: v => entity.setzIndex(v),
+  //   angle: v => entity.setAngle(v),
+  //   autoRotation: null,
+  //   animation: v => entity.setAnimation(v),
+  //   shadow: v => entity.setShadow(v),
+  //   title: v => entity.setTitle(v),
+  //   clickable: v => entity.setClickable(v),
+  //   shape: v => entity.setShape(v),
+  //   extData: v => entity.setExtData(v),
+  //   label: v => entity.setLabel(v)
+  // };
+
+  forOwn(props, (value, key) => {
+    if (value) {
+      let func = operators[key];
+      if (func) {
+        func(value);
+      } else {
+        // ignore properties can not set.
+        console.log(__func__, 'warning! no setter! can not update ' + key);
+      }
+    } else {
+      // key removed, not support!
+      console.log(__func__, 'warning! remove prop not support! key=' + key);
+    }
+  });
+  forOwn(events, (value, key) => {
+    let oldFunc = oldEvents && oldEvents[key];
+    if (oldFunc) {
+      entity.off(key, oldFunc);
+    }
+    if (value) {
+      entity.on(key, value);
+    }
+  });
+  console.log(
+    __func__, 'update:',
+    props,
+    events,
+    newOptions,
+    newEvents,
+    oldOptions,
+    oldEvents
+  );
+  return true;
+};
+
+export const updateMap = (
+  map,
+  newOptions,
+  newEvents,
+  oldOptions,
+  oldEvents
+) => {
   let operators = {
     view: null,
     layers: v => map.setLayers(v),
@@ -177,42 +246,14 @@ export const updateMap = (
     skyColor: null,
     preloadMode: null
   };
-
-  forOwn(props, (value, key) => {
-    if (value) {
-      let func = operators[key];
-      if (func) {
-        func(value);
-      } else {
-        // ignore properties can not set.
-        console.log('updateMap: warning! no setter! can not update ' + key);
-      }
-    } else {
-      // key removed, not support!
-      console.log('updateMap: warning! remove prop not support! key=' + key);
-    }
-  });
-  forOwn(events, (value, key) => {
-    let oldFunc = oldEvents && oldEvents[key];
-    if (oldFunc) {
-      console.log('updateMap: event off ' + key);
-      map.off(key, oldFunc);
-    }
-    if (value) {
-      console.log('updateMap: event on ' + key);
-      map.on(key, value);
-    }
-  });
-  console.log(
-    'updateMap: update:',
-    props,
-    events,
+  return commonUpdate (
+    map,
     newOptions,
     newEvents,
     oldOptions,
-    oldEvents
-  );
-  return true;
+    oldEvents,
+    operators
+  )
 };
 
 ////////////////////////////////////////////////////////////
@@ -226,16 +267,17 @@ export const updateMap = (
  * @param {*} events
  */
 export const createMarker = (AMap, options, events) => {
+  const __func__ = 'createMarker';
   if (!AMap) {
-    console.log('createMarker fail! no AMap!');
+    console.log(__func__, 'fail! no AMap!');
     return null;
   }
   if (!options) {
-    console.log('createMarker fail! no options!');
+    console.log(__func__, 'fail! no options!');
     return null;
   }
   if (!options.map) {
-    console.log('createMarker fail! no options.map!');
+    console.log(__func__, 'fail! no options.map!');
     return null;
   }
   // let marker = new AMap.Marker({
@@ -247,7 +289,7 @@ export const createMarker = (AMap, options, events) => {
   forOwn(events, (value, key) => {
     marker.on(key, value);
   });
-  console.log('createMarker ok!');
+  console.log(__func__, 'ok!');
   return marker;
 };
 
@@ -258,54 +300,6 @@ export const updateMarker = (
   oldOptions,
   oldEvents
 ) => {
-  if (!entity) {
-    console.log('updateMarker fail! no entity!');
-    return false;
-  }
-
-  // 找到改变的属性集合,包含添加,删除及修改的属性,删除的置为null
-  let props = {};
-  if (newOptions != oldOptions) {
-    oldOptions &&
-      forOwn(oldOptions, (value, key) => {
-        // 找到改变的旧属性,用新属性取代
-        let newValue = newOptions && newOptions[key];
-        if (!isEqual(newValue, value)) {
-          if (!(isNil(newValue) && isNil(value)))
-            props[key] = newValue;
-        }
-      });
-    newOptions &&
-      forOwn(newOptions, (value, key) => {
-        // 找到新加的属性,添加进去
-        let oldValue = oldOptions && oldOptions[key];
-        if (isNil(oldValue) && !isNil(value)) {
-          props[key] = value;
-        }
-      });
-  }
-  // 找到改变的事件集合,包含添加,删除及修改的事件处理函数,删除的置为null
-  let events = {};
-  if (newEvents != oldEvents) {
-    oldEvents &&
-      forOwn(oldEvents, (value, key) => {
-        // 找到改变的旧属性,用新属性取代
-        let newValue = newEvents && newEvents[key];
-        if (!isEqual(newValue, value)) {
-          if (!(isNil(newValue) && isNil(value)))
-            events[key] = newValue;
-        }
-      });
-    newEvents &&
-      forOwn(newEvents, (value, key) => {
-        // 找到新加的属性,添加进去
-        let oldValue = oldEvents && oldEvents[key];
-        if (isNil(oldValue) && !isNil(value)) {
-          events[key] = value;
-        }
-      });
-  }
-
   let operators = {
     map: v => entity.setMap(v),
     position: v => entity.setPosition(v),
@@ -330,37 +324,72 @@ export const updateMarker = (
     label: v => entity.setLabel(v)
   };
 
-  forOwn(props, (value, key) => {
-    if (value) {
-      let func = operators[key];
-      if (func) {
-        func(value);
-      } else {
-        // ignore properties can not set.
-        console.log('updateMarker: warning! no setter! can not update ' + key);
-      }
-    } else {
-      // key removed, not support!
-      console.log('updateMarker: warning! remove prop not support! key=' + key);
-    }
-  });
+  return commonUpdate (
+    entity,
+    newOptions,
+    newEvents,
+    oldOptions,
+    oldEvents,
+    operators
+  )
+};
+
+////////////////////////////////////////////////////////////
+// MassMarks, warning! is a layer!
+////////////////////////////////////////////////////////////
+/**
+ *
+ * @param {*} AMap
+ * @param {*} map
+ * @param {*} options 如果有dom用来显示,则其中的content字段即被填充为dom,不再用独立参数表示dom
+ * @param {*} events
+ */
+export const createMassMarks = (AMap, options, events) => {
+  const __func__ = 'createMassMarks';
+  if (!AMap) {
+    console.log(__func__, 'fail! no AMap!');
+    return null;
+  }
+  if (!options) {
+    console.log(__func__, 'fail! no options!');
+    return null;
+  }
+  let {map, data, ...restOpts} = options;
+  let entity = new AMap.MassMarks(data, restOpts);
   forOwn(events, (value, key) => {
-    let oldFunc = oldEvents && oldEvents[key];
-    if (oldFunc) {
-      entity.off(key, oldFunc);
-    }
-    if (value) {
-      entity.on(key, value);
-    }
+    entity.on(key, value);
   });
-  console.log(
-    'updateMarker: update:',
-    props,
-    events,
+  if (map) {
+    entity.setMap(map);
+  }
+  console.log(__func__, 'ok!');
+  return entity;
+};
+
+export const updateMassMarks = (
+  entity,
+  newOptions,
+  newEvents,
+  oldOptions,
+  oldEvents
+) => {
+  let operators = {
+    zIndex: v => entity.setzIndex(v),
+    opacity: null,
+    zooms: null,
+    cursor: v => entity.setCursor(v),
+    alwaysRender: null,
+    style: v => entity.setStyle(v),
+    map: v => entity.setMap(v),
+    data: v=> entity.setData(v)
+  };
+
+  return commonUpdate (
+    entity,
     newOptions,
     newEvents,
     oldOptions,
-    oldEvents
-  );
-  return true;
+    oldEvents,
+    operators
+  )
 };

+ 4 - 0
yarn.lock

@@ -1427,6 +1427,10 @@ class-utils@^0.3.5:
     isobject "^3.0.0"
     static-extend "^0.1.1"
 
+classnames@^2.2.6:
+  version "2.2.6"
+  resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
+
 clean-css@4.1.x:
   version "4.1.11"
   resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.1.11.tgz#2ecdf145aba38f54740f26cefd0ff3e03e125d6a"