import React, { useCallback, useRef, useState } from 'react';
import TreeView, { type TreeViewRef } from 'devextreme-react/tree-view';
import Sortable, { type SortableTypes } from 'devextreme-react/sortable';
import service from './data.ts';
const getStateFieldName = (driveName: string) => (driveName === 'driveC'
  ? 'itemsDriveC'
  : 'itemsDriveD');
const calculateToIndex = (e: SortableTypes.DragChangeEvent) => {
  if (e.fromComponent !== e.toComponent || e.dropInsideItem) {
    return e.toIndex;
  }
  return e.fromIndex >= e.toIndex
    ? e.toIndex
    : e.toIndex + 1;
};
const findNode = (treeView, index: string | number) => {
  const nodeElement = treeView.element().querySelectorAll('.dx-treeview-node')[index];
  if (nodeElement) {
    return findNodeById(treeView.getNodes(), nodeElement.getAttribute('data-item-id'));
  }
  return null;
};
const findNodeById = (nodes, id) => {
  for (let i = 0; i < nodes.length; i += 1) {
    if (nodes[i].itemData.id === id) {
      return nodes[i];
    }
    if (nodes[i].children) {
      const node = findNodeById(nodes[i].children, id);
      if (node != null) {
        return node;
      }
    }
  }
  return null;
};
const moveNode = (fromNode, toNode, fromItems, toItems, isDropInsideItem) => {
  const fromIndex = fromItems.findIndex((item) => item.id === fromNode.itemData.id);
  fromItems.splice(fromIndex, 1);
  const toIndex = toNode === null || isDropInsideItem
    ? toItems.length
    : toItems.findIndex((item) => item.id === toNode.itemData.id);
  toItems.splice(toIndex, 0, fromNode.itemData);
  moveChildren(fromNode, fromItems, toItems);
  if (isDropInsideItem) {
    fromNode.itemData.parentId = toNode.itemData.id;
  } else {
    fromNode.itemData.parentId = toNode != null
      ? toNode.itemData.parentId
      : undefined;
  }
};
const moveChildren = (node, fromDataSource, toDataSource: any[]) => {
  if (!node.itemData.isDirectory) {
    return;
  }
  node.children.forEach((child) => {
    if (child.itemData.isDirectory) {
      moveChildren(child, fromDataSource, toDataSource);
    }
    const fromIndex = fromDataSource.findIndex((item) => item.id === child.itemData.id);
    fromDataSource.splice(fromIndex, 1);
    toDataSource.splice(toDataSource.length, 0, child.itemData);
  });
};
const isChildNode = (parentNode: { itemData: { id: any; }; }, childNode: { parent: any; }) => {
  let { parent } = childNode;
  while (parent !== null) {
    if (parent.itemData.id === parentNode.itemData.id) {
      return true;
    }
    parent = parent.parent;
  }
  return false;
};
const getTopVisibleNode = (component) => {
  const treeViewElement = component.element();
  const treeViewTopPosition = treeViewElement.getBoundingClientRect().top;
  const nodes = treeViewElement.querySelectorAll('.dx-treeview-node');
  for (let i = 0; i < nodes.length; i += 1) {
    const nodeTopPosition = nodes[i].getBoundingClientRect().top;
    if (nodeTopPosition >= treeViewTopPosition) {
      return nodes[i];
    }
  }
  return null;
};
const App = () => {
  const treeViewDriveCRef = useRef<TreeViewRef>(null);
  const treeViewDriveDRef = useRef<TreeViewRef>(null);
  const [itemsDriveC, setItemsDriveC] = useState(service.getItemsDriveC());
  const [itemsDriveD, setItemsDriveD] = useState(service.getItemsDriveD());
  const getTreeView = useCallback((driveName: string) => (driveName === 'driveC'
    ? treeViewDriveCRef.current.instance()
    : treeViewDriveDRef.current.instance()), []);
  const onDragChange = useCallback((e: SortableTypes.DragChangeEvent) => {
    if (e.fromComponent === e.toComponent) {
      const fromNode = findNode(getTreeView(e.fromData), e.fromIndex);
      const toNode = findNode(getTreeView(e.toData), calculateToIndex(e));
      if (toNode !== null && isChildNode(fromNode, toNode)) {
        e.cancel = true;
      }
    }
  }, [getTreeView]);
  const onDragEnd = useCallback((e: SortableTypes.DragEndEvent) => {
    if (e.fromComponent === e.toComponent && e.fromIndex === e.toIndex) {
      return;
    }
    const fromTreeView = getTreeView(e.fromData);
    const toTreeView = getTreeView(e.toData);
    const fromNode = findNode(fromTreeView, e.fromIndex);
    const toNode = findNode(toTreeView, calculateToIndex(e));
    if (e.dropInsideItem && toNode !== null && !toNode.itemData.isDirectory) {
      return;
    }
    const fromTopVisibleNode = getTopVisibleNode(e.fromComponent);
    const toTopVisibleNode = getTopVisibleNode(e.toComponent);
    const fromItems = getStateFieldName(e.fromData) === 'itemsDriveC'
      ? itemsDriveC
      : itemsDriveD;
    const toItems = getStateFieldName(e.toData) === 'itemsDriveC'
      ? itemsDriveC
      : itemsDriveD;
    moveNode(fromNode, toNode, fromItems, toItems, e.dropInsideItem);
    if (getStateFieldName(e.fromData) === 'itemsDriveC') {
      setItemsDriveC([...fromItems]);
    } else {
      setItemsDriveD([...fromItems]);
    }
    if (getStateFieldName(e.toData) === 'itemsDriveC') {
      setItemsDriveC([...toItems]);
    } else {
      setItemsDriveD([...toItems]);
    }
    fromTreeView.scrollToItem(fromTopVisibleNode);
    toTreeView.scrollToItem(toTopVisibleNode);
  }, [getTreeView, itemsDriveC, itemsDriveD, setItemsDriveC, setItemsDriveD]);
  return (
    <div className="form">
      <div className="drive-panel">
        <div className="drive-header dx-treeview-item"><div className="dx-treeview-item-content"><i className="dx-icon dx-icon-activefolder"></i><span>Drive C:</span></div></div>
        <Sortable
          filter=".dx-treeview-item"
          group="shared"
          data="driveC"
          allowDropInsideItem={true}
          allowReordering={true}
          onDragChange={onDragChange}
          onDragEnd={onDragEnd}
        >
          <TreeView
            id="treeviewDriveC"
            expandNodesRecursive={false}
            dataStructure="plain"
            ref={treeViewDriveCRef}
            items={itemsDriveC}
            width={250}
            height={380}
            displayExpr="name"
          />
        </Sortable>
      </div>
      <div className="drive-panel">
        <div className="drive-header dx-treeview-item"><div className="dx-treeview-item-content"><i className="dx-icon dx-icon-activefolder"></i><span>Drive D:</span></div></div>
        <Sortable
          filter=".dx-treeview-item"
          group="shared"
          data="driveD"
          allowDropInsideItem={true}
          allowReordering={true}
          onDragChange={onDragChange}
          onDragEnd={onDragEnd}
        >
          <TreeView
            id="treeviewDriveD"
            expandNodesRecursive={false}
            dataStructure="plain"
            ref={treeViewDriveDRef}
            items={itemsDriveD}
            width={250}
            height={380}
            displayExpr="name"
          />
        </Sortable>
      </div>
    </div>
  );
};
export default App;
    
    import React, { useCallback, useRef, useState } from 'react';
import TreeView from 'devextreme-react/tree-view';
import Sortable from 'devextreme-react/sortable';
import service from './data.js';
const getStateFieldName = (driveName) => (driveName === 'driveC' ? 'itemsDriveC' : 'itemsDriveD');
const calculateToIndex = (e) => {
  if (e.fromComponent !== e.toComponent || e.dropInsideItem) {
    return e.toIndex;
  }
  return e.fromIndex >= e.toIndex ? e.toIndex : e.toIndex + 1;
};
const findNode = (treeView, index) => {
  const nodeElement = treeView.element().querySelectorAll('.dx-treeview-node')[index];
  if (nodeElement) {
    return findNodeById(treeView.getNodes(), nodeElement.getAttribute('data-item-id'));
  }
  return null;
};
const findNodeById = (nodes, id) => {
  for (let i = 0; i < nodes.length; i += 1) {
    if (nodes[i].itemData.id === id) {
      return nodes[i];
    }
    if (nodes[i].children) {
      const node = findNodeById(nodes[i].children, id);
      if (node != null) {
        return node;
      }
    }
  }
  return null;
};
const moveNode = (fromNode, toNode, fromItems, toItems, isDropInsideItem) => {
  const fromIndex = fromItems.findIndex((item) => item.id === fromNode.itemData.id);
  fromItems.splice(fromIndex, 1);
  const toIndex = toNode === null || isDropInsideItem
    ? toItems.length
    : toItems.findIndex((item) => item.id === toNode.itemData.id);
  toItems.splice(toIndex, 0, fromNode.itemData);
  moveChildren(fromNode, fromItems, toItems);
  if (isDropInsideItem) {
    fromNode.itemData.parentId = toNode.itemData.id;
  } else {
    fromNode.itemData.parentId = toNode != null ? toNode.itemData.parentId : undefined;
  }
};
const moveChildren = (node, fromDataSource, toDataSource) => {
  if (!node.itemData.isDirectory) {
    return;
  }
  node.children.forEach((child) => {
    if (child.itemData.isDirectory) {
      moveChildren(child, fromDataSource, toDataSource);
    }
    const fromIndex = fromDataSource.findIndex((item) => item.id === child.itemData.id);
    fromDataSource.splice(fromIndex, 1);
    toDataSource.splice(toDataSource.length, 0, child.itemData);
  });
};
const isChildNode = (parentNode, childNode) => {
  let { parent } = childNode;
  while (parent !== null) {
    if (parent.itemData.id === parentNode.itemData.id) {
      return true;
    }
    parent = parent.parent;
  }
  return false;
};
const getTopVisibleNode = (component) => {
  const treeViewElement = component.element();
  const treeViewTopPosition = treeViewElement.getBoundingClientRect().top;
  const nodes = treeViewElement.querySelectorAll('.dx-treeview-node');
  for (let i = 0; i < nodes.length; i += 1) {
    const nodeTopPosition = nodes[i].getBoundingClientRect().top;
    if (nodeTopPosition >= treeViewTopPosition) {
      return nodes[i];
    }
  }
  return null;
};
const App = () => {
  const treeViewDriveCRef = useRef(null);
  const treeViewDriveDRef = useRef(null);
  const [itemsDriveC, setItemsDriveC] = useState(service.getItemsDriveC());
  const [itemsDriveD, setItemsDriveD] = useState(service.getItemsDriveD());
  const getTreeView = useCallback(
    (driveName) =>
      (driveName === 'driveC'
        ? treeViewDriveCRef.current.instance()
        : treeViewDriveDRef.current.instance()),
    [],
  );
  const onDragChange = useCallback(
    (e) => {
      if (e.fromComponent === e.toComponent) {
        const fromNode = findNode(getTreeView(e.fromData), e.fromIndex);
        const toNode = findNode(getTreeView(e.toData), calculateToIndex(e));
        if (toNode !== null && isChildNode(fromNode, toNode)) {
          e.cancel = true;
        }
      }
    },
    [getTreeView],
  );
  const onDragEnd = useCallback(
    (e) => {
      if (e.fromComponent === e.toComponent && e.fromIndex === e.toIndex) {
        return;
      }
      const fromTreeView = getTreeView(e.fromData);
      const toTreeView = getTreeView(e.toData);
      const fromNode = findNode(fromTreeView, e.fromIndex);
      const toNode = findNode(toTreeView, calculateToIndex(e));
      if (e.dropInsideItem && toNode !== null && !toNode.itemData.isDirectory) {
        return;
      }
      const fromTopVisibleNode = getTopVisibleNode(e.fromComponent);
      const toTopVisibleNode = getTopVisibleNode(e.toComponent);
      const fromItems = getStateFieldName(e.fromData) === 'itemsDriveC' ? itemsDriveC : itemsDriveD;
      const toItems = getStateFieldName(e.toData) === 'itemsDriveC' ? itemsDriveC : itemsDriveD;
      moveNode(fromNode, toNode, fromItems, toItems, e.dropInsideItem);
      if (getStateFieldName(e.fromData) === 'itemsDriveC') {
        setItemsDriveC([...fromItems]);
      } else {
        setItemsDriveD([...fromItems]);
      }
      if (getStateFieldName(e.toData) === 'itemsDriveC') {
        setItemsDriveC([...toItems]);
      } else {
        setItemsDriveD([...toItems]);
      }
      fromTreeView.scrollToItem(fromTopVisibleNode);
      toTreeView.scrollToItem(toTopVisibleNode);
    },
    [getTreeView, itemsDriveC, itemsDriveD, setItemsDriveC, setItemsDriveD],
  );
  return (
    <div className="form">
      <div className="drive-panel">
        <div className="drive-header dx-treeview-item">
          <div className="dx-treeview-item-content">
            <i className="dx-icon dx-icon-activefolder"></i>
            <span>Drive C:</span>
          </div>
        </div>
        <Sortable
          filter=".dx-treeview-item"
          group="shared"
          data="driveC"
          allowDropInsideItem={true}
          allowReordering={true}
          onDragChange={onDragChange}
          onDragEnd={onDragEnd}
        >
          <TreeView
            id="treeviewDriveC"
            expandNodesRecursive={false}
            dataStructure="plain"
            ref={treeViewDriveCRef}
            items={itemsDriveC}
            width={250}
            height={380}
            displayExpr="name"
          />
        </Sortable>
      </div>
      <div className="drive-panel">
        <div className="drive-header dx-treeview-item">
          <div className="dx-treeview-item-content">
            <i className="dx-icon dx-icon-activefolder"></i>
            <span>Drive D:</span>
          </div>
        </div>
        <Sortable
          filter=".dx-treeview-item"
          group="shared"
          data="driveD"
          allowDropInsideItem={true}
          allowReordering={true}
          onDragChange={onDragChange}
          onDragEnd={onDragEnd}
        >
          <TreeView
            id="treeviewDriveD"
            expandNodesRecursive={false}
            dataStructure="plain"
            ref={treeViewDriveDRef}
            items={itemsDriveD}
            width={250}
            height={380}
            displayExpr="name"
          />
        </Sortable>
      </div>
    </div>
  );
};
export default App;
    
    import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
ReactDOM.render(
  <App />,
  document.getElementById('app'),
);
    
    const itemsDriveD = [];
const itemsDriveC = [{
  id: '1',
  name: 'Documents',
  icon: 'activefolder',
  isDirectory: true,
  expanded: true,
}, {
  id: '2',
  parentId: '1',
  name: 'Projects',
  icon: 'activefolder',
  isDirectory: true,
  expanded: true,
}, {
  id: '3',
  parentId: '2',
  name: 'About.rtf',
  icon: 'file',
  isDirectory: false,
  expanded: true,
}, {
  id: '4',
  parentId: '2',
  name: 'Passwords.rtf',
  icon: 'file',
  isDirectory: false,
  expanded: true,
}, {
  id: '5',
  parentId: '2',
  name: 'About.xml',
  icon: 'file',
  isDirectory: false,
  expanded: true,
}, {
  id: '6',
  parentId: '2',
  name: 'Managers.rtf',
  icon: 'file',
  isDirectory: false,
  expanded: true,
}, {
  id: '7',
  parentId: '2',
  name: 'ToDo.txt',
  icon: 'file',
  isDirectory: false,
  expanded: true,
}, {
  id: '8',
  name: 'Images',
  icon: 'activefolder',
  isDirectory: true,
  expanded: true,
}, {
  id: '9',
  parentId: '8',
  name: 'logo.png',
  icon: 'file',
  isDirectory: false,
  expanded: true,
}, {
  id: '10',
  parentId: '8',
  name: 'banner.gif',
  icon: 'file',
  isDirectory: false,
  expanded: true,
}, {
  id: '11',
  name: 'System',
  icon: 'activefolder',
  isDirectory: true,
  expanded: true,
}, {
  id: '12',
  parentId: '11',
  name: 'Employees.txt',
  icon: 'file',
  isDirectory: false,
  expanded: true,
}, {
  id: '13',
  parentId: '11',
  name: 'PasswordList.txt',
  icon: 'file',
  isDirectory: false,
  expanded: true,
}, {
  id: '14',
  name: 'Description.rtf',
  icon: 'file',
  isDirectory: false,
  expanded: true,
}, {
  id: '15',
  name: 'Description.txt',
  icon: 'file',
  isDirectory: false,
  expanded: true,
}];
export default {
  getItemsDriveC() {
    return itemsDriveC;
  },
  getItemsDriveD() {
    return itemsDriveD;
  },
};
    
    window.exports = window.exports || {};
window.config = {
  transpiler: 'ts',
  typescriptOptions: {
    module: 'system',
    emitDecoratorMetadata: true,
    experimentalDecorators: true,
    jsx: 'react',
  },
  meta: {
    'react': {
      'esModule': true,
    },
    'typescript': {
      'exports': 'ts',
    },
    'devextreme/time_zone_utils.js': {
      'esModule': true,
    },
    'devextreme/localization.js': {
      'esModule': true,
    },
    'devextreme/viz/palette.js': {
      'esModule': true,
    },
    'openai': {
      'esModule': true,
    },
  },
  paths: {
    'npm:': 'https://cdn.jsdelivr.net/npm/',
    'bundles:': '../../../../bundles/',
    'externals:': '../../../../bundles/externals/',
  },
  defaultExtension: 'js',
  map: {
    'ts': 'npm:plugin-typescript@8.0.0/lib/plugin.js',
    'typescript': 'npm:typescript@4.2.4/lib/typescript.js',
    'jszip': 'npm:jszip@3.10.1/dist/jszip.min.js',
    'react': 'npm:react@17.0.2/umd/react.development.js',
    'react-dom': 'npm:react-dom@17.0.2/umd/react-dom.development.js',
    'prop-types': 'npm:prop-types/prop-types.js',
    'rrule': 'npm:rrule@2.6.4/dist/es5/rrule.js',
    'luxon': 'npm:luxon@3.4.4/build/global/luxon.min.js',
    'es6-object-assign': 'npm:es6-object-assign',
    'devextreme': 'npm:devextreme@link:../../packages/devextreme/artifacts/npm/devextreme/cjs',
    'devextreme-react': 'npm:devextreme-react@link:../../packages/devextreme-react/npm/cjs',
    'devextreme-quill': 'npm:devextreme-quill@1.7.6/dist/dx-quill.min.js',
    'devexpress-diagram': 'npm:devexpress-diagram@2.2.24/dist/dx-diagram.js',
    'devexpress-gantt': 'npm:devexpress-gantt@4.1.64/dist/dx-gantt.js',
    'inferno': 'npm:inferno@8.2.3/dist/inferno.min.js',
    'inferno-compat': 'npm:inferno-compat/dist/inferno-compat.min.js',
    'inferno-create-element': 'npm:inferno-create-element@8.2.3/dist/inferno-create-element.min.js',
    'inferno-dom': 'npm:inferno-dom/dist/inferno-dom.min.js',
    'inferno-hydrate': 'npm:inferno-hydrate/dist/inferno-hydrate.min.js',
    'inferno-clone-vnode': 'npm:inferno-clone-vnode/dist/inferno-clone-vnode.min.js',
    'inferno-create-class': 'npm:inferno-create-class/dist/inferno-create-class.min.js',
    'inferno-extras': 'npm:inferno-extras/dist/inferno-extras.min.js',
    '@preact/signals-core': 'npm:@preact/signals-core@1.8.0/dist/signals-core.min.js',
    'devextreme-cldr-data': 'npm:devextreme-cldr-data@1.0.3',
    // SystemJS plugins
    'plugin-babel': 'npm:systemjs-plugin-babel@0.0.25/plugin-babel.js',
    'systemjs-babel-build': 'npm:systemjs-plugin-babel@0.0.25/systemjs-babel-browser.js',
    // Prettier
    'prettier/standalone': 'npm:prettier@2.8.8/standalone.js',
    'prettier/parser-html': 'npm:prettier@2.8.8/parser-html.js',
  },
  packages: {
    'devextreme': {
      defaultExtension: 'js',
    },
    'devextreme-react': {
      main: 'index.js',
    },
    'devextreme-react/common': {
      main: 'index.js',
    },
    'devextreme/events/utils': {
      main: 'index',
    },
    'devextreme/common/core/events/utils': {
      main: 'index',
    },
    'devextreme/localization/messages': {
      format: 'json',
      defaultExtension: 'json',
    },
    'devextreme/events': {
      main: 'index',
    },
    'es6-object-assign': {
      main: './index.js',
      defaultExtension: 'js',
    },
  },
  packageConfigPaths: [
    'npm:@devextreme/*/package.json',
  ],
  babelOptions: {
    sourceMaps: false,
    stage0: true,
    react: true,
  },
};
System.config(window.config);
// eslint-disable-next-line
const useTgzInCSB = ['openai'];
    
    import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
ReactDOM.render(<App />, document.getElementById('app'));
    
    const itemsDriveD = [];
const itemsDriveC = [
  {
    id: '1',
    name: 'Documents',
    icon: 'activefolder',
    isDirectory: true,
    expanded: true,
  },
  {
    id: '2',
    parentId: '1',
    name: 'Projects',
    icon: 'activefolder',
    isDirectory: true,
    expanded: true,
  },
  {
    id: '3',
    parentId: '2',
    name: 'About.rtf',
    icon: 'file',
    isDirectory: false,
    expanded: true,
  },
  {
    id: '4',
    parentId: '2',
    name: 'Passwords.rtf',
    icon: 'file',
    isDirectory: false,
    expanded: true,
  },
  {
    id: '5',
    parentId: '2',
    name: 'About.xml',
    icon: 'file',
    isDirectory: false,
    expanded: true,
  },
  {
    id: '6',
    parentId: '2',
    name: 'Managers.rtf',
    icon: 'file',
    isDirectory: false,
    expanded: true,
  },
  {
    id: '7',
    parentId: '2',
    name: 'ToDo.txt',
    icon: 'file',
    isDirectory: false,
    expanded: true,
  },
  {
    id: '8',
    name: 'Images',
    icon: 'activefolder',
    isDirectory: true,
    expanded: true,
  },
  {
    id: '9',
    parentId: '8',
    name: 'logo.png',
    icon: 'file',
    isDirectory: false,
    expanded: true,
  },
  {
    id: '10',
    parentId: '8',
    name: 'banner.gif',
    icon: 'file',
    isDirectory: false,
    expanded: true,
  },
  {
    id: '11',
    name: 'System',
    icon: 'activefolder',
    isDirectory: true,
    expanded: true,
  },
  {
    id: '12',
    parentId: '11',
    name: 'Employees.txt',
    icon: 'file',
    isDirectory: false,
    expanded: true,
  },
  {
    id: '13',
    parentId: '11',
    name: 'PasswordList.txt',
    icon: 'file',
    isDirectory: false,
    expanded: true,
  },
  {
    id: '14',
    name: 'Description.rtf',
    icon: 'file',
    isDirectory: false,
    expanded: true,
  },
  {
    id: '15',
    name: 'Description.txt',
    icon: 'file',
    isDirectory: false,
    expanded: true,
  },
];
export default {
  getItemsDriveC() {
    return itemsDriveC;
  },
  getItemsDriveD() {
    return itemsDriveD;
  },
};
    
    <!DOCTYPE html>
<html lang="en">
  <head>
    <title>DevExtreme Demo</title>
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" />
    <link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/25.1.6/css/dx.light.css" />
    <link rel="stylesheet" type="text/css" href="styles.css" />
    <script src="https://cdn.jsdelivr.net/npm/core-js@2.6.12/client/shim.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/systemjs@0.21.3/dist/system.js"></script>
    <script type="text/javascript" src="config.js"></script>
    <script type="text/javascript">
      System.import("./index.tsx");
    </script>
  </head>
  <body class="dx-viewport">
    <div class="demo-container">
      <div id="app"></div>
    </div>
  </body>
</html>
    
    .form {
  display: flex;
}
.form > div {
  display: inline-block;
  vertical-align: top;
}
.dx-treeview-item {
  box-sizing: border-box;
}
.drive-header {
  min-height: auto;
  padding: 0;
  cursor: default;
  margin-bottom: 10px;
}
.drive-panel {
  padding: 20px 30px;
  font-size: 115%;
  font-weight: bold;
  border-right: 1px solid rgba(165, 165, 165, 0.4);
  height: 100%;
}
.drive-panel:last-of-type {
  border-right: none;
}