Skip to content

Commit 491eedf

Browse files
committed
Convert to ReScript
1 parent b41ad6a commit 491eedf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+5240
-5728
lines changed

bsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"rescript-logger"
1818
],
1919
"bs-dev-dependencies": [
20-
"re-classnames"
20+
"rescript-classnames"
2121
],
2222
"reason": {
2323
"react-jsx": 3

docs/01-GettingStartedGuide.md

Lines changed: 89 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ In this guide, we will build simple flat list with draggable items.
2121
2222
First, let's shape up a state. This is going to be an array of ints:
2323

24-
```reason
25-
type item = int;
26-
type state = array(item);
24+
```rescript
25+
type item = int
26+
type state = array<item>
2727
```
2828

2929
To create components that handle all drag & drop business, we need to call `Dnd.Make()` functor:
3030

31-
```reason
32-
module Items = Dnd.Make(Item, Container);
31+
```rescript
32+
module Items = Dnd.Make(Item, Container)
3333
```
3434

3535
This code wouldn't compile yet because we need to provide two modules to the `Dnd.Make` functor:
@@ -39,10 +39,10 @@ This code wouldn't compile yet because we need to provide two modules to the `Dn
3939

4040
Both of these modules has the same signature:
4141

42-
```reason
43-
type t;
44-
let eq: (t, t) => bool;
45-
let cmp: (t, t) => int;
42+
```rescript
43+
type t
44+
let eq: (t, t) => bool
45+
let cmp: (t, t) => int
4646
```
4747

4848
Basically, functor asks you to answer the following questions:
@@ -52,35 +52,35 @@ Basically, functor asks you to answer the following questions:
5252

5353
Let's start with very simple (and in general not 100% safe) implementation of `Item` container:
5454

55-
```reason
55+
```rescript
5656
module Item = {
57-
type t = item; // `item` is a type alias we defined above which is resolved to `int`
58-
let eq = (x1, x2) => x1 == x2; // or more concise: let eq = (==);
59-
let cmp = compare; // default comparator from Pervasives module
57+
type t = item // `item` is a type alias we defined above which is resolved to `int`
58+
let eq = (x1, x2) => x1 == x2 // or more concise: let eq = (==)
59+
let cmp = compare // default comparator from Pervasives module
6060
}
6161
```
6262

6363
Regarding `Container` type, there is no specific entity in the app domain which can be associated with this single abstract box that holds our flat list of items in UI. So we need to keep its configuration abstract, e.g.:
6464

65-
```reason
65+
```rescript
6666
module Container = {
67-
type t; // abstract type
68-
external id: unit => t = "%identity"; // `Container.id()` would produce value of abstract type `t`
69-
let eq = (_, _) => true; // since `Container` is singleton, it's always equal to self
70-
let cmp = (_, _) => 0; // same logic applies
67+
type t // abstract type
68+
external id: unit => t = "%identity" // `Container.id()` would produce value of abstract type `t`
69+
let eq = (_, _) => true // since `Container` is singleton, it's always equal to self
70+
let cmp = (_, _) => 0 // same logic applies
7171
}
7272
```
7373

7474
For convenience, `re-dnd` exposes functor which would create such singleton for you, so you don't have to type this boilerplate yourself:
7575

76-
```reason
77-
module Container = Dnd.MakeSingletonContainer();
76+
```rescript
77+
module Container = Dnd.MakeSingletonContainer()
7878
```
7979

8080
Now, when we have complete configuration defined, we can create module which holds React components:
8181

82-
```reason
83-
module Items = Dnd.Make(Item, Container);
82+
```rescript
83+
module Items = Dnd.Make(Item, Container)
8484
```
8585

8686
Module `Items` holds 3 components (each link below leads to component's api):
@@ -90,52 +90,48 @@ Module `Items` holds 3 components (each link below leads to component's api):
9090

9191
Let's render those:
9292

93-
```reason
94-
let (state, dispatch) = reducer->React.useReducer(initialState);
93+
```rescript
94+
let (state, dispatch) = reducer->React.useReducer(initialState)
9595
9696
<Items.DndManager onReorder={result => ReorderItems(result)->dispatch}>
9797
<Items.DroppableContainer id={Container.id()} axis=Y>
9898
{state
99-
->Array.mapWithIndex((index, item) => {
100-
<Items.DraggableItem
101-
id={item}
102-
key={item->Int.toString}
103-
containerId={Container.id()}
104-
index>
105-
{`Children(item->Int.toString->React.string)}
106-
</Items.DraggableItem>;
107-
})
108-
->React.array}
99+
->Array.mapWithIndex((index, item) =>
100+
<Items.DraggableItem
101+
id=item key={item->Int.toString} containerId={Container.id()} index>
102+
#Children(item->Int.toString->React.string)
103+
</Items.DraggableItem>
104+
)
105+
->React.array}
109106
</Items.DroppableContainer>
110-
</Items.DndManager>;
107+
</Items.DndManager>
111108
```
112109

113110
Even though render tree looks good, to finish this component we still need to implement handler that would persist result of reordering when item gets dropped.
114111

115112
This is how corresponding `action` constructor type looks like:
116113

117-
```reason
118-
type action =
119-
| ReorderItems(Dnd.result(Item.t, Container.t));
114+
```rescript
115+
type action = ReorderItems(Dnd.result<Item.t, Container.t>)
120116
```
121117

122118
What `Dnd.result` type is?
123119

124-
```reason
125-
type result('item, 'container) = option(reorderResult('item, 'container))
120+
```rescript
121+
type rec result<'item, 'container> = option<reorderResult<'item, 'container>>
126122
127-
and reorderResult('item, 'container) =
128-
| SameContainer('item, placement('item))
129-
| NewContainer('item, 'container, placement('item))
123+
and reorderResult<'item, 'container> =
124+
| SameContainer('item, placement<'item>)
125+
| NewContainer('item, 'container, placement<'item>)
130126
131-
and placement('item) =
127+
and placement<'item> =
132128
| Before('item)
133-
| Last;
129+
| Last
134130
```
135131

136132
Let's break down possible cases:
137133

138-
```reason
134+
```rescript
139135
| ReorderItems(None) =>
140136
// `None` means nothing has changed:
141137
// either user dropped the item on the same position
@@ -161,91 +157,85 @@ Let's break down possible cases:
161157

162158
So with this in mind, let's implement reducer for our case:
163159

164-
```reason
165-
let reducer = (state, action) => switch (action) {
166-
| ReorderItems(Some(SameContainer(item, placement))) =>
167-
// Item has landed in the new position of the same container,
168-
// so it should be reinserted from the old position
169-
// in the array into the new one.
170-
// `ArrayExt.reinsert` is a helper which does just this.
171-
state->ArrayExt.reinsert(
172-
~value=item,
173-
~place=
174-
switch (placement) {
175-
| Before(id) => `Before(id)
176-
| Last => `Last
160+
```rescript
161+
let reducer = (state, action) =>
162+
switch action {
163+
| ReorderItems(Some(SameContainer(item, placement))) =>
164+
// Item has landed in the new position of the same container,
165+
// so it should be reinserted from the old position
166+
// in the array into the new one.
167+
// `ArrayExt.reinsert` is a helper which does just this.
168+
state->ArrayExt.reinsert(
169+
~value=item,
170+
~place=switch placement {
171+
| Before(id) => #Before(id)
172+
| Last => #Last
177173
},
178-
)
174+
)
179175
180-
// not possible since we have only one container
181-
| ReorderItems(Some(NewContainer(_)))
182-
| ReorderItems(None) => state
183-
}
176+
// not possible since we have only one container
177+
| ReorderItems(Some(NewContainer(_)))
178+
| ReorderItems(None) => state
179+
}
184180
```
185181

186182
> `ArrayExt.reinsert` is not a part of the public API since usually in a real-world app reordering is handled differently. If you want to inspect it or use it in your own code, you can find its definition in the [examples](../examples/libs/ArrayExt.re).
187183
188184
Looks like we have everything in place. This is how the final module looks like:
189185

190-
```reason
191-
type item = int;
186+
```rescript
187+
type item = int
192188
193189
module Item = {
194-
type t = item;
195-
let eq = (x1, x2) => x1 == x2;
196-
let cmp = compare;
197-
};
190+
type t = item
191+
let eq = (x1, x2) => x1 == x2
192+
let cmp = compare
193+
}
198194
199-
module Container =
200-
Dnd.MakeSingletonContainer({});
195+
module Container = Dnd.MakeSingletonContainer()
201196
202-
module Items = Dnd.Make(Item, Container);
197+
module Items = Dnd.Make(Item, Container)
203198
204-
type state = array(item);
199+
type state = array<item>
205200
206-
type action =
207-
| ReorderItems(Dnd.result(Item.t, Container.t));
201+
type action = ReorderItems(Dnd.result<Item.t, Container.t>)
208202
209203
let reducer = (state, action) =>
210-
switch (action) {
204+
switch action {
211205
| ReorderItems(Some(SameContainer(item, placement))) =>
212206
state->ArrayExt.reinsert(
213207
~value=item,
214-
~place=
215-
switch (placement) {
216-
| Before(id) => `Before(id)
217-
| Last => `Last
218-
},
208+
~place=switch placement {
209+
| Before(id) => #Before(id)
210+
| Last => #Last
211+
},
219212
)
220213
| ReorderItems(Some(NewContainer(_)))
221214
| ReorderItems(None) => state
222-
};
215+
}
223216
224-
let initialState = [|1, 2, 3, 4, 5, 6, 7|];
217+
let initialState = [1, 2, 3, 4, 5, 6, 7]
225218
226-
[@react.component]
219+
@react.component
227220
let make = () => {
228-
let (state, dispatch) = reducer->React.useReducer(initialState);
221+
let (state, dispatch) = reducer->React.useReducer(initialState)
229222
230223
<Items.DndManager onReorder={result => ReorderItems(result)->dispatch}>
231224
<Items.DroppableContainer id={Container.id()} axis=Y>
232225
{state
233-
->Array.mapWithIndex((index, item) =>
234-
<Items.DraggableItem
235-
id=item
236-
key={item->Int.toString}
237-
containerId={Container.id()}
238-
index>
239-
{`Children(item->Int.toString->React.string)}
240-
</Items.DraggableItem>
241-
)
242-
->React.array}
226+
->Array.mapWithIndex((index, item) =>
227+
<Items.DraggableItem
228+
id=item key={item->Int.toString} containerId={Container.id()} index>
229+
#Children(item->Int.toString->React.string)
230+
</Items.DraggableItem>
231+
)
232+
->React.array}
243233
</Items.DroppableContainer>
244-
</Items.DndManager>;
245-
};
234+
</Items.DndManager>
235+
}
246236
```
247237

248-
_Source code of the final module for this guide: [`GettingStartedGuide.re`](../examples/guides/GettingStartedGuide.re)_
238+
_Source code of the final module for this guide: [`GettingStartedGuide.res`](../examples/guides/GettingStartedGuide.res)_
249239

250240
---
251241
This guide gives base overview of how `re-dnd` works. To find out more about how to make it safer and how to deal with multiple containers—proceed to the [next guide](./02-SaferIdentifiersAndMultipleContainersGuide.md).

0 commit comments

Comments
 (0)