cssAudio - Activefile-genericCSS - ActiveGeneric - ActiveHTML - ActiveImage - ActiveJS - ActiveSVG - ActiveText - Activefile-genericVideo - ActiveLovehtmlicon-new-collectionicon-personicon-teamlog-outoctocatpop-outspinnerstartv

Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

            
              $green: #B0DE6B
$blue: #76C9DE
$dark-gray: #948F8F
$light-gray: #ddd

body
  background: $light-gray

*
  box-sizing: border-box

.dnd-example
  display: flex
  flex-wrap: wrap
  width: 740px
  padding: 30px
  margin: 100px auto 0
  background: white
  font-family: sans-serif
  font-size: 19px
  text-align: center

  &,
  div
    border-radius: 10px
    user-select: none

  &.dragging *
    cursor: grabbing

.drop-description
  width: 100%
  font-weight: 300
  margin: 1em 0 0

.dnd-source-objects
  margin-right: 30px

.dnd-source-object
  width: 240px
  line-height: 38px
  border-radius: 10px
  font-weight: bold
  font-size: 24px
  color: rgba(0,0,0,.2)
  cursor: grab

  &:not(:last-child)
    margin: 0 0 10px

  &.green
    background: $green

  &.blue
    background: $blue

.dnd-drop-targets
  background: $dark-gray
  flex: 1
  padding: 15px

.dnd-drop-target
  position: relative
  background: white
  line-height: 50px
  font-weight: 300
  overflow: hidden

  &:not(:last-child)
    margin: 0 0 10px

  &.green:before,
  &.blue:after
    content: ''
    position: absolute
    left: 0
    width: 20px
    height: 100%
    background: $green

  &.blue:after
    background: $blue

  &.green.blue:after
    left: 20px

  &.active.hover
    &:after,
    &:before
      display: none

  &.active-green.active
    box-shadow: 0 0 0 3px $dark-gray, 0 0 0 4px $green
    &.hover
      background: $green

  &.active-blue.active
    box-shadow: 0 0 0 3px $dark-gray, 0 0 0 4px $blue
    &.hover
      background: $blue

  &.disabled
    opacity: .2
    cursor: no-drop

.dnd-draggable.dragging
  z-index: 1
  pointer-events: none
  box-shadow: 0 2px 5px rgba(0,0,0,.8)
            
          
!
            
              {div, p} = React.DOM

LEFT_BUTTON = 0
DRAG_THRESHOLD = 3 # pixels

document.addEventListener 'DOMContentLoaded', ->
  React.renderComponent Example(), document.body

Example = React.createClass
  getInitialState: ->
    currentDragItem: null

  render: ->
    div
      className: "dnd-example #{'dragging' if @state.currentDragItem}"
      children: [
        SourceObjects
          onDragStart: @onDragStart
          onDragStop: @onDragStop
        DropTargets
          currentDragItem: @state.currentDragItem
          onDrop: @onDrop
        @dropDescription()
      ]

  onDragStart: (details) ->
    @setState currentDragItem: details

  onDragStop: ->
    @setState currentDragItem: null

  onDrop: (target) ->
    @setState lastDrop:
      source: @state.currentDragItem
      target: target

  dropDescription: ->
    if drop = @state.lastDrop
      p
        className: 'drop-description'
        children: "Dropped source #{drop.source.type}-#{drop.source.index} on target #{drop.target.index}"

SourceObjects = React.createClass
  render: ->
    div
      className: 'dnd-source-objects'
      children: for object, i in @objects()
        SourceObject
          type: object.type
          index: i + 1
          children: i + 1
          onDragStart: @props.onDragStart
          onDragStop: @props.onDragStop

  objects: ->
    _.flatten [
      { type: 'green' } for i in [0..2]
      { type: 'blue' } for i in [0..2]
    ]

SourceObject = React.createClass
  render: ->
    Draggable
      className: "dnd-source-object #{@props.type}"
      children: @props.children
      onDragStart: @props.onDragStart
      onDragStop: @props.onDragStop
      dragData: @dragData

  dragData: ->
    type: @props.type
    index: @props.index

Draggable = React.createClass
  getInitialState: ->
    mouseDown: false
    dragging: false

  render: ->
    @transferPropsTo div
      style: @style()
      className: "dnd-draggable #{'dragging' if @state.dragging}"
      children: @props.children
      onMouseDown: @onMouseDown

  style: ->
    if @state.dragging
      position: 'absolute'
      left: @state.left
      top: @state.top
    else
      {}

  onMouseDown: (event) ->
    if event.button == LEFT_BUTTON
      event.stopPropagation()
      @addEvents()
      pageOffset = @getDOMNode().getBoundingClientRect()
      @setState
        mouseDown: true
        originX: event.pageX
        originY: event.pageY
        elementX: pageOffset.left
        elementY: pageOffset.top

  onMouseMove: (event) ->
    deltaX = event.pageX - @state.originX
    deltaY = event.pageY - @state.originY
    distance = Math.abs(deltaX) + Math.abs(deltaY)

    if !@state.dragging and distance > DRAG_THRESHOLD
      @setState dragging: true
      @props.onDragStart? @props.dragData?()

    if @state.dragging
      @setState
        left: @state.elementX + deltaX + document.body.scrollLeft
        top: @state.elementY + deltaY + document.body.scrollTop

  onMouseUp: ->
    @removeEvents()
    if @state.dragging
      @props.onDragStop()
      @setState dragging: false

  addEvents: ->
    document.addEventListener 'mousemove', @onMouseMove
    document.addEventListener 'mouseup', @onMouseUp

  removeEvents: ->
    document.removeEventListener 'mousemove', @onMouseMove
    document.removeEventListener 'mouseup', @onMouseUp

DropTargets = React.createClass
  render: ->
    div
      className: 'dnd-drop-targets'
      children: for target, i in @targets()
        DropTarget
          target: target
          index: i
          currentDragItem: @props.currentDragItem
          onDrop: @props.onDrop

  targets: ->
    [
      { accepts: ['blue'] }
      { accepts: ['green'] }
      { accepts: ['blue', 'green'] }
      { accepts: [] }
    ]

DropTarget = React.createClass
  getInitialState: ->
    hover: false

  render: ->
    div
      className: @classes()
      children: 'accepts ' + @acceptsDescription()
      onMouseEnter: => @setState hover: true
      onMouseLeave: => @setState hover: false
      onMouseUp: @onDrop

  classes: ->
    [
      'dnd-drop-target'
      "#{@props.target.accepts.join ' '}"
      'active' if @active()
      'active-green' if @active() and @props.currentDragItem.type == 'green'
      'active-blue' if @active() and @props.currentDragItem.type == 'blue'
      'disabled' if @disabled()
      'hover' if @state.hover
    ].join ' '

  active: ->
    item = @props.currentDragItem
    item and item.type in @props.target.accepts

  disabled: ->
    item = @props.currentDragItem 
    item and item.type not in @props.target.accepts

  acceptsDescription: ->
    if @props.target.accepts.length > 0
      @props.target.accepts.join ' & '
    else
      'nothing'

  onDrop: ->
    if @active()
      @props.onDrop? index: @props.index + 1

            
          
!
999px
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.
Loading ..................

Console