@@ -1,24 +1,27 @@
1module Yoga.Grimoire.Component where
1module Yoga.Grimoire.Component where
3import Prelude
3import Prelude
4−import Data.Array (mapWithIndex, zip, (!!))
4+import Data.Array (length, mapWithIndex, zip, (!!), (..))
5import Data.Array as Array
5import Data.Array as Array
6import Data.FoldableWithIndex (findWithIndex)
6import Data.FoldableWithIndex (findWithIndex)
7import Data.Interpolate as Interp
7import Data.Interpolate as Interp
8import Data.Lens (set)
8import Data.Lens (set)
9import Data.Lens.Index (ix)
9import Data.Lens.Index (ix)
10−import Data.Maybe (Maybe(..), fromMaybe)
10+import Data.Maybe (Maybe(..), fromMaybe, fromMaybe')
11import Data.Nullable (Nullable)
11import Data.Nullable (Nullable)
12import Data.Nullable as Nullable
12import Data.Nullable as Nullable
13import Data.Symbol (SProxy(..))
13import Data.Symbol (SProxy(..))
14import Data.Traversable (for, sequence)
14import Data.Traversable (for, sequence)
15import Data.Tuple.Nested ((/\), type (/\))
15import Data.Tuple.Nested ((/\), type (/\))
16+import Debug.Trace (spy)
16import Effect (Effect)
17import Effect (Effect)
18+import Effect.Class.Console (log)
17import Justifill (justifill)
19import Justifill (justifill)
20+import Partial.Unsafe (unsafeCrashWith)
18import React.Basic (ReactComponent)
21import React.Basic (ReactComponent)
19import React.Basic.DOM (css)
22import React.Basic.DOM (css)
20import React.Basic.Helpers (jsx)
23import React.Basic.Helpers (jsx)
21−import React.Basic.Hooks (Ref, component, element, readRef, useLayoutEffect, useRef, writeRef)
24+import React.Basic.Hooks (Ref, component, element, readRef, useLayoutEffect, useRef, useState, writeRef)
22import React.Basic.Hooks as React
25import React.Basic.Hooks as React
23import React.Basic.Hooks.Spring (animatedDiv, useSprings)
26import React.Basic.Hooks.Spring (animatedDiv, useSprings)
24import React.Basic.Hooks.UseGesture (useDrag, withDragProps)
27import React.Basic.Hooks.UseGesture (useDrag, withDragProps)
@@ -31,7 +34,6 @@ import Web.HTML.HTMLElement as HTMLElement
31import Yoga.Grid.Component as Grid
34import Yoga.Grid.Component as Grid
32import Yoga.Grimoire.Spell.Component as GrimoireSpell
35import Yoga.Grimoire.Spell.Component as GrimoireSpell
33import Yoga.Grimoire.Styles (styles)
36import Yoga.Grimoire.Styles (styles)
34−import Yoga.Helpers ((?||))
35import Yoga.Resize.Hook (useResize)
37import Yoga.Resize.Hook (useResize)
36import Yoga.Spell.Types (Spell)
38import Yoga.Spell.Types (Spell)
37import Yoga.Theme.Styles (makeStylesJSS, useTheme)
39import Yoga.Theme.Styles (makeStylesJSS, useTheme)
@@ -69,11 +71,80 @@ translate (x /\ y) { top, right, bottom, left, width, height } =
76+ (\_ -> unsafeCrashWith msg)
78+idxOrThrow ∷ ∀ a. Array a -> Int -> a
79+idxOrThrow arr i = arr !! i # orDie (Interp.i "Invalid index " i " in array")
81+infixl 8 idxOrThrow as !!!
72−swap ∷ ∀ a. Int -> Int -> Array a -> Maybe (Array a)
83+swap ∷ ∀ a. Int -> Int -> Array a -> Array a
73−swap i j arr = do
84+swap i j arr = swapped # orDie "Couldn't swap"
74− valueI <- arr !! i
87+ valueI <- arr !! i
75− valueJ <- arr !! j
88+ valueJ <- arr !! j
76− pure $ (set (ix i) valueJ <<< set (ix j) valueI) arr
89+ pure $ (set (ix i) valueJ <<< set (ix j) valueI) arr
91+springsteen init rectsRef positionsRef arg mx my down springs = do
93+ rects <- readRef rectsRef
94+ positionsBefore <- readRef positionsRef
96+ rectDragged = rects !!! (positionsBefore !!! arg)
97+ currentPosDragged = rectDragged # translate (mx /\ my)
98+ orderedRectsBefore = positionsBefore <#> (rects !!! _)
99+ overlapsOtherBefore = orderedRectsBefore # findWithIndex \i rect -> i /= arg && overlaps currentPosDragged rect
100+ case down, overlapsOtherBefore of
101+ false, Just { index } -> do
103+ newPositions = swap arg index positionsBefore
104+ writeRef positionsRef $ spy "new posis" newPositions
106+ -- alles gut bis hierher, glaube ich
107+ positions <- readRef positionsRef
108+ springs.set \i -> do
111+ isTheDraggedOne = i == arg
112+ originalRect = rects !!! i
113+ currentRect = rects !!! j
114+ leftOffset = currentRect.left - originalRect.left
115+ topOffset = currentRect.top - originalRect.top
116+ case isTheDraggedOne, down, overlapsOtherBefore of
118+ { x: mx + leftOffset
121+ , transform: "scale3d(1.1, 1.1, 1.1)"
122+ , borderRadius: "var(--s-2)"
125+ , immediate: \n -> n == "x" || n == "y" || n == "zIndex"
127+ false, true, Just { index, value }
129+ { x: rectDragged.left - currentRect.left + leftOffset
130+ , y: rectDragged.top - currentRect.top + topOffset
134+ , transform: "scale3d(1.0, 1.0, 1.0)"
135+ , borderRadius: "var(--s-2)"
136+ , immediate: const false
143+ , borderRadius: "var(--s-2)"
145+ , transform: "scale3d(1.0, 1.0, 1.0)"
146+ , immediate: const false
78makeComponent ∷ Effect (ReactComponent Props)
149makeComponent ∷ Effect (ReactComponent Props)
79makeComponent = do
150makeComponent = do
@@ -90,95 +161,45 @@ makeComponent = do
90 , shadow: 2
161 , shadow: 2
91 , borderRadius: "var(--s-2)"
162 , borderRadius: "var(--s-2)"
92 , zIndex: 0
163 , zIndex: 0
93− , immediate: const false
164+ , immediate: const true
94 , transform: "scale3d(1.0,1.0,1.0)"
165 , transform: "scale3d(1.0,1.0,1.0)"
97− useSprings (Array.length props.spells) defaultSprings
167+ springs <- useSprings (Array.length props.spells) defaultSprings
98− nodeRefs <- useRef (props.spells $> Nullable.null)
168+ nodeRefs ∷ Ref (Array (Nullable (_))) <- useRef (props.spells $> Nullable.null)
169+ spells /\ updateSpells <- useState props.spells
99− positionsRef <- useRef ([] ∷ _ DOMRect)
170+ positionsRef <- useRef ([] ∷ _ Int)
100− originalPositionsRef <- useRef ([] ∷ _ DOMRect)
171+ rectsRef <- useRef ([] ∷ _ DOMRect)
101 initialisedRef <- useRef false
172 initialisedRef <- useRef false
102 windowSize <- useResize
173 windowSize <- useResize
104 init = do
175 init = do
105 initialised <- readRef initialisedRef
176 initialised <- readRef initialisedRef
106 unless initialised do
177 unless initialised do
107− rects <- getRects nodeRefs
179+ refs <- getRects nodeRefs
180+ positions <- readRef positionsRef
108− writeRef positionsRef (rects <#> fromMaybe emptyDomRect)
181+ writeRef positionsRef (0 .. (length props.spells - 1))
109− writeRef originalPositionsRef (rects <#> fromMaybe emptyDomRect)
183+ rects = refs <#> fromMaybe emptyDomRect
184+ writeRef rectsRef rects
110 writeRef initialisedRef true
185 writeRef initialisedRef true
111 useLayoutEffect windowSize do
186 useLayoutEffect windowSize do
113− writeRef initialisedRef false
114 springs.set defaultSprings
187 springs.set defaultSprings
188+ positionsBefore <- readRef positionsRef
189+ when (positionsBefore == []) do
190+ log "resetting positions"
191+ writeRef positionsRef (0 .. (length props.spells - 1))
192+ positions <- readRef positionsRef
193+ updateSpells (const $ positions <#> (spells !!! _))
194+ nodes <- readRef nodeRefs
195+ writeRef nodeRefs (positions <#> (nodes !!! _))
196+ writeRef initialisedRef false
116 theme ∷ CSSTheme <- useTheme
199 theme ∷ CSSTheme <- useTheme
117 bindDragProps <-
200 bindDragProps <-
118− useDrag (justifill { filterTaps: true }) \{ arg, down, movement: mx /\ my } -> do
201+ useDrag (justifill { filterTaps: true }) \{ arg, down, movement: mx /\ my } ->
119− init
202+ springsteen init rectsRef positionsRef arg mx my down springs
120− originalPositions <- readRef originalPositionsRef
121− positionsBefore <- readRef positionsRef
123− originalPosDraggedBefore = positionsBefore !! arg ?|| emptyDomRect
125− currentPosDraggedBefore = originalPosDraggedBefore # translate (mx /\ my)
127− overlapsOtherBefore = positionsBefore # findWithIndex \i' pos -> i' /= arg && overlaps currentPosDraggedBefore pos
128− case down, overlapsOtherBefore of
129− false, Just { index, value } -> do
131− swapped = swap arg index positionsBefore ?|| positionsBefore
132− writeRef positionsRef swapped
134− positions <- readRef positionsRef
136− originalPosDragged = positions !! arg ?|| emptyDomRect
138− currentPosDragged = originalPosDragged # translate (mx /\ my)
140− overlapsOther = positions # findWithIndex \i' pos -> i' /= arg && overlaps currentPosDragged pos
141− springs.set \i -> do
143− iPos = positions !! i ?|| emptyDomRect
145− origIPos = originalPositions !! i ?|| emptyDomRect
147− leftOffset = if iPos == origIPos then 0.0 else iPos.left - origIPos.left
149− topOffset = if iPos == origIPos then 0.0 else iPos.top - origIPos.top
150− case i == arg, down, overlapsOther of
151− false, true, Just { index, value }
153− { x: originalPosDragged.left - value.left + leftOffset
154− , y: originalPosDragged.top - value.top + topOffset
158− , transform: "scale3d(1.0, 1.0, 1.0)"
159− , borderRadius: "var(--s-2)"
160− , immediate: const false
163− { x: mx + leftOffset
166− , transform: "scale3d(1.1, 1.1, 1.1)"
167− , borderRadius: "var(--s-2)"
170− , immediate: \n -> n == "x" || n == "y" || n == "zIndex"
177− , borderRadius: "var(--s-2)"
179− , transform: "scale3d(1.0, 1.0, 1.0)"
180− , immediate: const false
183 renderSpells =
204 renderSpells =
184 mapWithIndex \i (spell /\ style) ->
205 mapWithIndex \i (spell /\ style) ->
@@ -196,7 +217,7 @@ makeComponent = do
196 `withDragProps`
217 `withDragProps`
197 bindDragProps i
218 bindDragProps i
199− $ jsx grid {} (renderSpells (props.spells `zip` springs.styles))
220+ $ jsx grid {} (renderSpells (spells `zip` springs.styles))
201foreign import unsafeArraySetAt ∷ ∀ a. Int -> a -> Array a -> Array a
222foreign import unsafeArraySetAt ∷ ∀ a. Int -> a -> Array a -> Array a