Created
March 6, 2018 13:18
-
-
Save dborisenko/0303839c089a7dc25acd2418f2bea8c4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.dbrsn.sortable | |
| import scala.collection.mutable.ListBuffer | |
| /** | |
| * A change in index of an item generated by dragging | |
| * | |
| * @param oldIndex The item's old index | |
| * @param newIndex The item's new index | |
| */ | |
| case class IndexChange(oldIndex: Int, newIndex: Int) { | |
| def updatedList[A](l: List[A]): List[A] = { | |
| val lb = ListBuffer(l: _*) | |
| val e = lb.remove(oldIndex) | |
| lb.insert(newIndex, e) | |
| lb.toList | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.dbrsn.sortable | |
| import japgolly.scalajs.react.{ Callback, Children, GenericComponent, JsComponent } | |
| import scala.language.higherKinds | |
| import scala.scalajs.js | |
| object SortableContainer { | |
| @js.native | |
| protected trait Permutation extends js.Object { | |
| val oldIndex: Int = js.native | |
| val newIndex: Int = js.native | |
| } | |
| @js.native | |
| trait Props extends js.Object { | |
| val axis: js.UndefOr[String] = js.native | |
| val lockAxis: js.UndefOr[String] = js.native | |
| val helperClass: js.UndefOr[String] = js.native | |
| val transitionDuration: js.UndefOr[Int] = js.native | |
| val pressDelay: js.UndefOr[Int] = js.native | |
| val distance: js.UndefOr[Int] = js.native | |
| val useDragHandle: js.UndefOr[Boolean] = js.native | |
| val useWindowAsScrollContainer: js.UndefOr[Boolean] = js.native | |
| val hideSortableGhost: js.UndefOr[Boolean] = js.native | |
| val lockToContainerEdges: js.UndefOr[Boolean] = js.native | |
| //Note this function actually gets "{oldIndex, newIndex, collection}, e", but we don't have much use for the other arguments | |
| val onSortEnd: js.Function1[Permutation, Unit] = js.native | |
| } | |
| object Props { | |
| def apply( | |
| axis: js.UndefOr[String] = js.undefined, | |
| lockAxis: js.UndefOr[String] = js.undefined, | |
| helperClass: js.UndefOr[String] = SortableView.HandleClassName, | |
| transitionDuration: js.UndefOr[Int] = js.undefined, | |
| pressDelay: js.UndefOr[Int] = js.undefined, | |
| distance: js.UndefOr[Int] = js.undefined, | |
| useDragHandle: js.UndefOr[Boolean] = js.undefined, | |
| useWindowAsScrollContainer: js.UndefOr[Boolean] = js.undefined, | |
| hideSortableGhost: js.UndefOr[Boolean] = js.undefined, | |
| lockToContainerEdges: js.UndefOr[Boolean] = js.undefined, | |
| //Note this function actually gets "{oldIndex, newIndex, collection}, e", but we don't have much use for the other arguments | |
| onSortEnd: IndexChange => Callback = _ => Callback.empty | |
| ): Props = | |
| js.Dynamic.literal( | |
| axis = axis, lockAxis = lockAxis, helperClass = helperClass, transitionDuration = transitionDuration, pressDelay = pressDelay, | |
| distance = distance, useDragHandle = useDragHandle, useWindowAsScrollContainer = useWindowAsScrollContainer, | |
| hideSortableGhost = hideSortableGhost, lockToContainerEdges = lockToContainerEdges, | |
| onSortEnd = js.defined { p: Permutation => onSortEnd(IndexChange(p.oldIndex, p.newIndex)).runNow() } | |
| ).asInstanceOf[Props] | |
| } | |
| /** | |
| * Wrap another component | |
| * | |
| * @param wrappedComponent The wrapped component itself | |
| * @tparam P The type of Props of the wrapped component | |
| * @return A component wrapping the wrapped component... | |
| */ | |
| def apply[P, CT[_, _]](wrappedComponent: GenericComponent[P, CT, _]): Props => P => JsComponent.Unmounted[js.Object, Null] = { (props) => (wrappedProps) => { | |
| val reactElement = SortableHOC.SortableContainer(wrappedComponent.raw) | |
| val component = JsComponent[js.Object, Children.None, Null](reactElement) | |
| val mergedProps = js.Dynamic.literal() | |
| mergedProps.updateDynamic("axis")(props.axis) | |
| mergedProps.updateDynamic("lockAxis")(props.lockAxis) | |
| mergedProps.updateDynamic("helperClass")(props.helperClass) | |
| mergedProps.updateDynamic("transitionDuration")(props.transitionDuration) | |
| mergedProps.updateDynamic("pressDelay")(props.pressDelay) | |
| mergedProps.updateDynamic("distance")(props.distance) | |
| mergedProps.updateDynamic("useDragHandle")(props.useDragHandle) | |
| mergedProps.updateDynamic("useWindowAsScrollContainer")(props.useWindowAsScrollContainer) | |
| mergedProps.updateDynamic("hideSortableGhost")(props.hideSortableGhost) | |
| mergedProps.updateDynamic("lockToContainerEdges")(props.lockToContainerEdges) | |
| mergedProps.updateDynamic("onSortEnd")(props.onSortEnd) | |
| mergedProps.updateDynamic("a")(wrappedProps.asInstanceOf[js.Any]) | |
| component(mergedProps.asInstanceOf[js.Object]) | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.dbrsn.sortable | |
| import japgolly.scalajs.react.{ Children, GenericComponent, JsComponent } | |
| import scala.language.higherKinds | |
| import scala.scalajs.js | |
| object SortableElement { | |
| @js.native | |
| trait Props extends js.Object { | |
| var index: Int = js.native | |
| var collection: Int = js.native | |
| var disabled: Boolean = js.native | |
| } | |
| object Props { | |
| def apply( | |
| index: Int, | |
| collection: Int = 0, | |
| disabled: Boolean = false | |
| ): Props = | |
| js.Dynamic.literal(index = index, collection = collection, disabled = disabled).asInstanceOf[Props] | |
| } | |
| /** | |
| * Wrap another component | |
| * | |
| * @param wrappedComponent The wrapped component itself | |
| * @tparam P The type of Props of the wrapped component | |
| * @return A component wrapping the wrapped component... | |
| */ | |
| def apply[P, CT[_, _]](wrappedComponent: GenericComponent[P, CT, _]): Props => P => JsComponent.Unmounted[js.Object, Null] = { (props) => (wrappedProps) => { | |
| val reactElement = SortableHOC.SortableElement(wrappedComponent.raw) | |
| val component = JsComponent[js.Object, Children.None, Null](reactElement) | |
| val mergedProps = js.Dynamic.literal() | |
| mergedProps.updateDynamic("index")(props.index) | |
| mergedProps.updateDynamic("collection")(props.collection) | |
| mergedProps.updateDynamic("disabled")(props.disabled) | |
| mergedProps.updateDynamic("a")(wrappedProps.asInstanceOf[js.Any]) | |
| component(mergedProps.asInstanceOf[js.Object]) | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.dbrsn.sortable | |
| import japgolly.scalajs.react._ | |
| import scala.language.higherKinds | |
| import scala.scalajs.js | |
| object SortableHandle { | |
| /** | |
| * Wrap another component | |
| * | |
| * @param wrappedComponent The wrapped component itself | |
| * @tparam P The type of Props of the wrapped component | |
| * @return A component wrapping the wrapped component | |
| */ | |
| def apply[P, CT[_, _]](wrappedComponent: GenericComponent[P, CT, _]): P => JsComponent.Unmounted[js.Object, Null] = { | |
| (wrappedProps) => | |
| { | |
| val reactElement = SortableHOC.SortableHandle(wrappedComponent.raw) | |
| val component = JsComponent[js.Object, Children.None, Null](reactElement) | |
| val mergedProps = js.Dynamic.literal() | |
| mergedProps.updateDynamic("a")(wrappedProps.asInstanceOf[js.Any]) | |
| component(mergedProps.asInstanceOf[js.Object]) | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.dbrsn.sortable | |
| import japgolly.scalajs.react.component.Generic.ComponentRaw | |
| import japgolly.scalajs.react.raw.ReactElement | |
| import scala.scalajs.js | |
| import scala.scalajs.js.annotation.JSImport | |
| @js.native | |
| @JSImport("react-sortable-hoc", JSImport.Namespace) | |
| private[sortable] object SortableHOC extends js.Object { | |
| def SortableContainer(component: ComponentRaw#Raw): ReactElement = js.native | |
| def SortableElement(component: ComponentRaw#Raw): ReactElement = js.native | |
| def SortableHandle(component: ComponentRaw#Raw): ReactElement = js.native | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.dbrsn.sortable | |
| import japgolly.scalajs.react._ | |
| import japgolly.scalajs.react.component.Js.Unmounted | |
| import japgolly.scalajs.react.vdom.html_<^._ | |
| import scala.scalajs.js | |
| object SortableView { | |
| import japgolly.scalajs.react.vdom.SvgAttrs._ | |
| import japgolly.scalajs.react.vdom.SvgTags._ | |
| final val HandleClassName: String = "react-sortable-handle" | |
| final case class Props( | |
| handleClassName: String = HandleClassName, | |
| color: String = "#A0A0A0", | |
| height: Int = 20 | |
| ) | |
| private val handleGrip = ScalaComponent.builder[Props]("HandleGrip") | |
| .render_P { p => | |
| <.div( | |
| ^.className := p.handleClassName, | |
| svg( | |
| ^.className := "react-sortable-handle-svg", | |
| viewBox := "0 0 24 24", | |
| fill := p.color, | |
| height := p.height, | |
| path(d := "M9,8c1.1,0,2-0.9,2-2s-0.9-2-2-2S7,4.9,7,6S7.9,8,9,8z M9,10c-1.1,0-2,0.9-2,2s0.9,2,2,2s2-0.9,2-2S10.1,10,9,10z M9,16c-1.1,0-2,0.9-2,2s0.9,2,2,2s2-0.9,2-2S10.1,16,9,16z"), | |
| path(d := "M15,8c1.1,0,2-0.9,2-2s-0.9-2-2-2s-2,0.9-2,2S13.9,8,15,8z M15,10c-1.1,0-2,0.9-2,2s0.9,2,2,2s2-0.9,2-2S16.1,10,15,10z M15,16c-1.1,0-2,0.9-2,2s0.9,2,2,2s2-0.9,2-2S16.1,16,15,16z") | |
| ) | |
| ) | |
| } | |
| .build | |
| def handleWithProps(props: Props): Unmounted[js.Object, Null] = SortableHandle(handleGrip)(props) | |
| val handle: Unmounted[js.Object, Null] = handleWithProps(Props()) | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example of usage: