@colisweb/rescript-toolkit 3.2.5 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.yarn/cache/@headlessui-react-npm-1.7.14-bf2f6f6d3e-9122114d7a.zip +0 -0
- package/.yarn/cache/client-only-npm-0.0.1-07d3e9505c-0c16bf660d.zip +0 -0
- package/.yarn/install-state.gz +0 -0
- package/package.json +2 -1
- package/playground/PlaygroundComponents.res +1 -0
- package/playground/components/Playground_Listbox.res +61 -0
- package/src/ui/Toolkit__Ui.res +1 -0
- package/src/ui/Toolkit__Ui_Listbox.res +185 -0
- package/src/ui/Toolkit__Ui_Listbox.resi +24 -0
|
Binary file
|
package/.yarn/install-state.gz
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colisweb/rescript-toolkit",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"clean": "rescript clean",
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"@colisweb/react-day-picker": "7.4.16",
|
|
32
32
|
"@colisweb/restorative": "1.0.0",
|
|
33
33
|
"@datadog/browser-rum": "4.26.0",
|
|
34
|
+
"@headlessui/react": "^1.7.14",
|
|
34
35
|
"@reach/accordion": "0.18.0",
|
|
35
36
|
"@reach/alert-dialog": "0.18.0",
|
|
36
37
|
"@reach/auto-id": "0.18.0",
|
|
@@ -36,6 +36,7 @@ let components: array<(string, module(Config))> = [
|
|
|
36
36
|
("Combobox", module(Playground_Combobox)),
|
|
37
37
|
("IconButton", module(Playground_IconButton)),
|
|
38
38
|
("CopyWrapper", module(Playground_CopyWrapper)),
|
|
39
|
+
("Listbox", module(Playground_Listbox)),
|
|
39
40
|
]
|
|
40
41
|
|
|
41
42
|
module List = {
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
open Toolkit__Ui
|
|
2
|
+
|
|
3
|
+
@module("@root/src/ui/Toolkit__Ui_Listbox.resi?raw")
|
|
4
|
+
external resi: string = "default"
|
|
5
|
+
|
|
6
|
+
@module("@root/playground/components/Playground_Listbox.res?raw")
|
|
7
|
+
external codeExample: string = "default"
|
|
8
|
+
|
|
9
|
+
@react.component
|
|
10
|
+
let make = () => {
|
|
11
|
+
let (uncontrolledValue, setUncontrolledValue) = React.useState((): option<
|
|
12
|
+
Toolkit__Ui_Listbox.selectOption<string>,
|
|
13
|
+
> => None)
|
|
14
|
+
|
|
15
|
+
let options: Toolkit__Ui_Listbox.options<string> = [
|
|
16
|
+
{
|
|
17
|
+
label: "Label1",
|
|
18
|
+
value: "1",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
label: "Label2",
|
|
22
|
+
value: "2",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
label: "Label3 disabled",
|
|
26
|
+
value: "3",
|
|
27
|
+
disabled: true,
|
|
28
|
+
},
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
<div className="flex flex-col gap-6">
|
|
32
|
+
<div>
|
|
33
|
+
<Label htmlFor="test" optionalMessage={"Optional"->React.string}>
|
|
34
|
+
{"Listbox uncontrolled"->React.string}
|
|
35
|
+
</Label>
|
|
36
|
+
<Listbox
|
|
37
|
+
placeholder="This is a placeholder"
|
|
38
|
+
compare={ValueEquality}
|
|
39
|
+
onChange={value => setUncontrolledValue(_ => Some(value))}
|
|
40
|
+
options
|
|
41
|
+
/>
|
|
42
|
+
<div className="mt-4">
|
|
43
|
+
<p> {"selected value :"->React.string} </p>
|
|
44
|
+
{uncontrolledValue->Option.mapWithDefault(React.null, value =>
|
|
45
|
+
<p> {value.label->React.string} </p>
|
|
46
|
+
)}
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
<div>
|
|
50
|
+
<Label htmlFor="test" optionalMessage={"Optional"->React.string}>
|
|
51
|
+
{"Listbox uncontrolled defaultOption selected"->React.string}
|
|
52
|
+
</Label>
|
|
53
|
+
<Listbox
|
|
54
|
+
placeholder="This is a placeholder"
|
|
55
|
+
compare={ValueEquality}
|
|
56
|
+
defaultOption=?{options[1]}
|
|
57
|
+
options
|
|
58
|
+
/>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
}
|
package/src/ui/Toolkit__Ui.res
CHANGED
|
@@ -19,6 +19,7 @@ module IconButton = Toolkit__Ui_IconButton
|
|
|
19
19
|
module Tag = Toolkit__Ui_Tag
|
|
20
20
|
module Select = Toolkit__Ui_Select
|
|
21
21
|
module SelectPolyvariant = Toolkit__Ui_SelectPolyvariant
|
|
22
|
+
module Listbox = Toolkit__Ui_Listbox
|
|
22
23
|
module Table = Toolkit__Ui_Table
|
|
23
24
|
module Reference = Toolkit__Ui_Reference
|
|
24
25
|
module RichText = Toolkit__Ui_RichText
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
type selectOption<'value> = {
|
|
2
|
+
label: string,
|
|
3
|
+
value: 'value,
|
|
4
|
+
disabled?: bool,
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
type options<'value> = array<selectOption<'value>>
|
|
8
|
+
|
|
9
|
+
type compare<'value> =
|
|
10
|
+
| Key(string)
|
|
11
|
+
| ValueEquality
|
|
12
|
+
| Function((option<selectOption<'value>>, selectOption<'value>) => bool)
|
|
13
|
+
|
|
14
|
+
module Listbox = {
|
|
15
|
+
type renderProps = {
|
|
16
|
+
@as("open")
|
|
17
|
+
isOpen: bool,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@module("@headlessui/react") @react.component
|
|
21
|
+
external make: (
|
|
22
|
+
~children: renderProps => React.element,
|
|
23
|
+
~value: 'value,
|
|
24
|
+
~defaultValue: selectOption<'value>=?,
|
|
25
|
+
~onChange: selectOption<'value> => unit=?,
|
|
26
|
+
~disabled: bool=?,
|
|
27
|
+
~by: 'a=?,
|
|
28
|
+
~name: string=?,
|
|
29
|
+
~className: string=?,
|
|
30
|
+
) => React.element = "Listbox"
|
|
31
|
+
|
|
32
|
+
module Button = {
|
|
33
|
+
type renderProps<'value> = {value: 'value}
|
|
34
|
+
@module("@headlessui/react") @scope("Listbox") @react.component
|
|
35
|
+
external make: (
|
|
36
|
+
~children: renderProps<'value> => React.element,
|
|
37
|
+
~className: string=?,
|
|
38
|
+
) => React.element = "Button"
|
|
39
|
+
}
|
|
40
|
+
module Options = {
|
|
41
|
+
@module("@headlessui/react") @scope("Listbox") @react.component
|
|
42
|
+
external make: (
|
|
43
|
+
~children: React.element,
|
|
44
|
+
~className: string=?,
|
|
45
|
+
~static: bool=?,
|
|
46
|
+
) => React.element = "Options"
|
|
47
|
+
}
|
|
48
|
+
module Option = {
|
|
49
|
+
type renderProps = {
|
|
50
|
+
active: bool,
|
|
51
|
+
selected: bool,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@module("@headlessui/react") @scope("Listbox") @react.component
|
|
55
|
+
external make: (
|
|
56
|
+
~children: renderProps => React.element,
|
|
57
|
+
~value: 'value=?,
|
|
58
|
+
~disabled: bool=?,
|
|
59
|
+
~className: string=?,
|
|
60
|
+
) => React.element = "Option"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
module Transition = {
|
|
65
|
+
@module("@headlessui/react") @react.component
|
|
66
|
+
external make: (
|
|
67
|
+
~show: bool,
|
|
68
|
+
~children: React.element,
|
|
69
|
+
~enter: string=?,
|
|
70
|
+
~enterFrom: string=?,
|
|
71
|
+
~enterTo: string=?,
|
|
72
|
+
~leave: string=?,
|
|
73
|
+
~leaveFrom: string=?,
|
|
74
|
+
~leaveTo: string=?,
|
|
75
|
+
~className: string=?,
|
|
76
|
+
) => React.element = "Transition"
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@react.component
|
|
80
|
+
let make = (
|
|
81
|
+
~options: options<'value>,
|
|
82
|
+
~compare: compare<'value>,
|
|
83
|
+
~onChange: option<selectOption<'value> => unit>=?,
|
|
84
|
+
~placeholder=?,
|
|
85
|
+
~defaultOption: option<selectOption<'value>>=?,
|
|
86
|
+
~isDisabled=?,
|
|
87
|
+
~value=?,
|
|
88
|
+
~name=?,
|
|
89
|
+
) => {
|
|
90
|
+
<div className="relative">
|
|
91
|
+
<Listbox
|
|
92
|
+
value
|
|
93
|
+
by={switch compare {
|
|
94
|
+
| Key(objectKey) => objectKey
|
|
95
|
+
| ValueEquality =>
|
|
96
|
+
(
|
|
97
|
+
(selectedValue, v2) => {
|
|
98
|
+
selectedValue->Option.mapWithDefault(false, selectedOption =>
|
|
99
|
+
selectedOption.value === v2.value
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
)->Obj.magic
|
|
103
|
+
|
|
104
|
+
| Function(fn) => fn->Obj.magic
|
|
105
|
+
}}
|
|
106
|
+
onChange={value => {
|
|
107
|
+
onChange->Option.forEach(fn => {
|
|
108
|
+
fn({...value, value: value.value->Option.getUnsafe})
|
|
109
|
+
})
|
|
110
|
+
}}
|
|
111
|
+
disabled=?{isDisabled}
|
|
112
|
+
?name
|
|
113
|
+
defaultValue=?{defaultOption->Obj.magic}>
|
|
114
|
+
{props => {
|
|
115
|
+
<>
|
|
116
|
+
<Listbox.Button
|
|
117
|
+
className="relative w-full cursor-default rounded-lg bg-white py-2 pl-3 pr-10 text-left shadow-md focus:outline-none focus-visible:border-indigo-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-orange-300 sm:text-sm">
|
|
118
|
+
{props => {
|
|
119
|
+
switch (props.value, placeholder) {
|
|
120
|
+
| (None, Some(p)) => p->React.string
|
|
121
|
+
| (Some(Some(selectedOption)), _) => selectedOption.label->React.string
|
|
122
|
+
|
|
123
|
+
| _ => React.null
|
|
124
|
+
}
|
|
125
|
+
}}
|
|
126
|
+
</Listbox.Button>
|
|
127
|
+
<Transition
|
|
128
|
+
show={props.isOpen}
|
|
129
|
+
className="relative z-20"
|
|
130
|
+
enter="transition duration-100 ease-out"
|
|
131
|
+
enterFrom="transform scale-95 opacity-0"
|
|
132
|
+
enterTo="transform scale-100 opacity-100"
|
|
133
|
+
leave="transition duration-75 ease-out"
|
|
134
|
+
leaveFrom="transform scale-100 opacity-100"
|
|
135
|
+
leaveTo="transform scale-95 opacity-0">
|
|
136
|
+
<Listbox.Options
|
|
137
|
+
static={true}
|
|
138
|
+
className="absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm z-20">
|
|
139
|
+
{options
|
|
140
|
+
->Array.mapWithIndex((i, option) => {
|
|
141
|
+
<Listbox.Option
|
|
142
|
+
key={`listbox-${i->Int.toString}`} value={option} disabled=?{option.disabled}>
|
|
143
|
+
{props => {
|
|
144
|
+
<div
|
|
145
|
+
className={cx([
|
|
146
|
+
"relative cursor-default select-none py-2 pl-4 pr-4 text-gray-900 flex flex-row items-center gap-2",
|
|
147
|
+
props.active ? "bg-primary-50" : "bg-white",
|
|
148
|
+
switch option.disabled {
|
|
149
|
+
| Some(true) => "text-gray-500"
|
|
150
|
+
| _ => "text-gray-900"
|
|
151
|
+
},
|
|
152
|
+
])}>
|
|
153
|
+
{props.selected
|
|
154
|
+
? <div
|
|
155
|
+
className={cx([
|
|
156
|
+
"w-6 h-6 rounded-full border inline-flex items-center justify-center",
|
|
157
|
+
switch option.disabled {
|
|
158
|
+
| Some(true) => "bg-gray-100 border-gray-200"
|
|
159
|
+
| _ => "bg-white border-gray-500"
|
|
160
|
+
},
|
|
161
|
+
])}>
|
|
162
|
+
<div className="w-4 h-4 rounded-full bg-primary-700" />
|
|
163
|
+
</div>
|
|
164
|
+
: <div
|
|
165
|
+
className={cx([
|
|
166
|
+
"w-6 h-6 rounded-full border border-gray-500 bg-white",
|
|
167
|
+
switch option.disabled {
|
|
168
|
+
| Some(true) => "border-gray-200"
|
|
169
|
+
| _ => "bg-white border-gray-500"
|
|
170
|
+
},
|
|
171
|
+
])}
|
|
172
|
+
/>}
|
|
173
|
+
{option.label->React.string}
|
|
174
|
+
</div>
|
|
175
|
+
}}
|
|
176
|
+
</Listbox.Option>
|
|
177
|
+
})
|
|
178
|
+
->React.array}
|
|
179
|
+
</Listbox.Options>
|
|
180
|
+
</Transition>
|
|
181
|
+
</>
|
|
182
|
+
}}
|
|
183
|
+
</Listbox>
|
|
184
|
+
</div>
|
|
185
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
type selectOption<'value> = {
|
|
2
|
+
label: string,
|
|
3
|
+
value: 'value,
|
|
4
|
+
disabled?: bool,
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
type options<'value> = array<selectOption<'value>>
|
|
8
|
+
|
|
9
|
+
type compare<'value> =
|
|
10
|
+
| Key(string)
|
|
11
|
+
| ValueEquality
|
|
12
|
+
| Function((option<selectOption<'value>>, selectOption<'value>) => bool)
|
|
13
|
+
|
|
14
|
+
@react.component
|
|
15
|
+
let make: (
|
|
16
|
+
~options: options<'value>,
|
|
17
|
+
~compare: compare<'value>,
|
|
18
|
+
~onChange: selectOption<'value> => unit=?,
|
|
19
|
+
~placeholder: string=?,
|
|
20
|
+
~defaultOption: selectOption<'value>=?,
|
|
21
|
+
~isDisabled: bool=?,
|
|
22
|
+
~value: 'value=?,
|
|
23
|
+
~name: string=?,
|
|
24
|
+
) => React.element
|