git.iko.soy/rowtype-yoga/purescript-yoga-react-native
on main help sign in
Restore working wrapper Views with allowsVibrancy, 5px divider
commitb14dca4421ffd2fd6afa7df4f7ca84a3996be738 authorMark <mark.eibes@gmail.com> dateFri 20 Feb 2026, 00:07 (7 months ago) parent586ecbc
2 files changed+88−108
src/Yoga/React/Native/MacOS/SplitView.js−88 src/Yoga/React/Native/MacOS/SplitView.purs+88−20
src/Yoga/React/Native/MacOS/SplitView.jsdeleted−88
@@ -1,88 +0,0 @@
1−import React, { useState, useRef, Children } from "react";
2−import { View, PanResponder } from "react-native";
3−
4−export const splitViewImpl = React.forwardRef((props, ref) => {
5− const {
6− initialPosition = 240,
7− minPaneWidth = 100,
8− dividerThickness = 1,
9− dividerColor,
10− dividerHoverColor,
11− onDividerPosition,
12− style,
13− children,
14− ...rest
15− } = props;
16−
17− const [sidebarWidth, setSidebarWidth] = useState(initialPosition);
18− const [hovered, setHovered] = useState(false);
19− const containerRef = useRef(null);
20− const startWidth = useRef(sidebarWidth);
21− const widthRef = useRef(sidebarWidth);
22− widthRef.current = sidebarWidth;
23−
24− const panRef = useRef(
25− PanResponder.create({
26− onStartShouldSetPanResponder: () => true,
27− onMoveShouldSetPanResponder: () => true,
28− onPanResponderGrant: () => {
29− startWidth.current = widthRef.current;
30− },
31− onPanResponderMove: (_, gesture) => {
32− const newWidth = Math.max(minPaneWidth, startWidth.current + gesture.dx);
33− setSidebarWidth(newWidth);
34− },
35− onPanResponderRelease: () => {
36− if (typeof onDividerPosition === "function") {
37− onDividerPosition({ position: widthRef.current })();
38− }
39− },
40− })
41− );
42−
43− const kids = Children.toArray(children);
44− const leftChild = kids[0] || null;
45− const rightChild = kids[1] || null;
46−
47− const dColor = dividerColor || "rgba(128,128,128,0.3)";
48− const dHoverColor = dividerHoverColor || "rgba(128,128,128,0.6)";
49−
50− return React.createElement(
51− View,
52− {
53− ref: containerRef,
54− style: [{ flexDirection: "row" }, style],
55− ...rest,
56− },
57− React.createElement(
58− View,
59− { style: { width: sidebarWidth, overflow: "hidden" }, allowsVibrancy: true },
60− leftChild
61− ),
62− React.createElement(View, {
63− ...panRef.current.panHandlers,
64− onMouseEnter: () => setHovered(true),
65− onMouseLeave: () => setHovered(false),
66− style: {
67− width: 5,
68− cursor: "col-resize",
69− alignItems: "center",
70− justifyContent: "center",
71− },
72− },
73− React.createElement(View, {
74− style: {
75− width: dividerThickness,
76− height: "100%",
77− backgroundColor: hovered ? dHoverColor : dColor,
78− },
79− pointerEvents: "none",
80− })
81− ),
82− React.createElement(
83− View,
84− { style: { flex: 1, overflow: "hidden" } },
85− rightChild
86− )
87− );
88−});
src/Yoga/React/Native/MacOS/SplitView.purs+88−20
@@ -1,27 +1,95 @@
11module Yoga.React.Native.MacOS.SplitView
2− ( nativeSplitView
3− , NativeSplitViewAttributes
4− , DividerPosition
2+ ( splitView
53 ) where
64
7−import Prelude (Unit)
8−import Effect (Effect)
9−import React.Basic (ReactComponent)
10−import Yoga.React.Native.Attributes (BaseAttributes)
11−import Yoga.React.Native.Internal (FFINativeComponent, createNativeElement)
5+import Prelude
126
13−foreign import splitViewImpl :: forall props. ReactComponent props
7+import Data.Tuple.Nested ((/\))
8+import Effect.Uncurried (mkEffectFn2)
9+import Effect.Unsafe (unsafePerformEffect)
10+import React.Basic (JSX)
11+import React.Basic.Events (EventHandler, handler_)
12+import React.Basic.Hooks as React
13+import Unsafe.Coerce (unsafeCoerce)
14+import Yoga.React (component)
15+import Yoga.React.Native (view, tw)
16+import Yoga.React.Native.PanResponder as Pan
17+import Yoga.React.Native.Style as Style
1418
15−nativeSplitView :: FFINativeComponent NativeSplitViewAttributes
16−nativeSplitView = createNativeElement splitViewImpl
19+type SplitViewProps =
20+ { initialPosition :: Number
21+ , minPaneWidth :: Number
22+ , left :: JSX
23+ , right :: JSX
24+ }
1725
18−type DividerPosition = { position :: Number }
26+splitView :: SplitViewProps -> JSX
27+splitView = component "SplitView" \props -> React.do
28+ sidebarWidth /\ setSidebarWidth <- React.useState' props.initialPosition
29+ hovered /\ setHovered <- React.useState' false
30+ widthRef <- React.useRef props.initialPosition
31+ startWidthRef <- React.useRef 0.0
1932
20−type NativeSplitViewAttributes = BaseAttributes
21− ( initialPosition :: Number
22− , minPaneWidth :: Number
23− , dividerThickness :: Number
24− , dividerColor :: String
25− , dividerHoverColor :: String
26− , onDividerPosition :: DividerPosition -> Effect Unit
27− )
33+ React.useEffect sidebarWidth do
34+ React.writeRef widthRef sidebarWidth
35+ pure (pure unit)
36+
37+ pr <- React.useMemo unit \_ -> unsafePerformEffect $ Pan.create
38+ { onStartShouldSetPanResponder: mkEffectFn2 \_ _ -> pure true
39+ , onMoveShouldSetPanResponder: mkEffectFn2 \_ _ -> pure true
40+ , onPanResponderGrant: mkEffectFn2 \_ _ -> do
41+ w <- React.readRef widthRef
42+ React.writeRef startWidthRef w
43+ , onPanResponderMove: mkEffectFn2 \_ (gs :: Pan.GestureState) -> do
44+ sw <- React.readRef startWidthRef
45+ let newWidth = max props.minPaneWidth (sw + gs.dx)
46+ setSidebarWidth newWidth
47+ }
48+
49+ let handlers = toResponderHandlers (Pan.panHandlers pr)
50+ let dColor = if hovered then "rgba(128,128,128,0.6)" else "rgba(128,128,128,0.3)"
51+
52+ pure do
53+ view { style: tw "flex-1 flex-row" }
54+ [ view
55+ { style: Style.style { width: sidebarWidth, overflow: "hidden" }
56+ , allowsVibrancy: true
57+ }
58+ [ props.left ]
59+ , view
60+ { style: Style.style { width: 5.0, cursor: "col-resize", alignItems: "center", justifyContent: "center" }
61+ , onStartShouldSetResponder: handlers.onStartShouldSetResponder
62+ , onMoveShouldSetResponder: handlers.onMoveShouldSetResponder
63+ , onResponderGrant: handlers.onResponderGrant
64+ , onResponderMove: handlers.onResponderMove
65+ , onResponderRelease: handlers.onResponderRelease
66+ , onResponderTerminate: handlers.onResponderTerminate
67+ , onResponderTerminationRequest: handlers.onResponderTerminationRequest
68+ , onMouseEnter: handler_ (setHovered true)
69+ , onMouseLeave: handler_ (setHovered false)
70+ }
71+ [ view
72+ { style: Style.style { width: 1.0, height: "100%", backgroundColor: dColor }
73+ , pointerEvents: "none"
74+ }
75+ (mempty :: Array JSX)
76+ ]
77+ , view
78+ { style: tw "flex-1" <> Style.style { overflow: "hidden" } }
79+ [ props.right ]
80+ ]
81+
82+-- PanResponder.panHandlers returns responder-named event handlers
83+-- but the PureScript type uses pan-prefixed names, so we coerce
84+toResponderHandlers :: Pan.PanResponderHandlers -> ResponderHandlers
85+toResponderHandlers = unsafeCoerce
86+
87+type ResponderHandlers =
88+ { onStartShouldSetResponder :: EventHandler
89+ , onMoveShouldSetResponder :: EventHandler
90+ , onResponderGrant :: EventHandler
91+ , onResponderMove :: EventHandler
92+ , onResponderRelease :: EventHandler
93+ , onResponderTerminate :: EventHandler
94+ , onResponderTerminationRequest :: EventHandler
95+ }