@colisweb/rescript-toolkit 4.13.0 → 4.14.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/package.json
CHANGED
package/src/ui/Toolkit__Ui.res
CHANGED
|
@@ -31,6 +31,7 @@ module Layout = Toolkit__Ui_Layout
|
|
|
31
31
|
module SpinnerFullScreen = Toolkit__Ui_SpinnerFullScreen
|
|
32
32
|
module MultiSelect = Toolkit__Ui_MultiSelect
|
|
33
33
|
module MultiSelectWithValidation = Toolkit__Ui_MultiSelectWithValidation
|
|
34
|
+
module SelectWithValidation = Toolkit__Ui_SelectWithValidation
|
|
34
35
|
module Notice = Toolkit__Ui_Notice
|
|
35
36
|
module NativeDatePicker = Toolkit__Ui_NativeDatePicker
|
|
36
37
|
module ErrorBoundary = Toolkit__Ui_ErrorBoundary
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
open ReactIntl
|
|
2
|
+
|
|
3
|
+
type item = {
|
|
4
|
+
itemLabel?: React.element,
|
|
5
|
+
label: string,
|
|
6
|
+
value: string,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
type options = array<item>
|
|
10
|
+
|
|
11
|
+
module Footer = {
|
|
12
|
+
@react.component
|
|
13
|
+
let make = (~onCancel, ~onValidateClick) => {
|
|
14
|
+
let dropdownContext = React.useContext(Toolkit__Ui_Dropdown.dropdownContext)
|
|
15
|
+
|
|
16
|
+
<footer className="bg-white p-1 flex flex-row justify-between">
|
|
17
|
+
<Toolkit__Ui_Button
|
|
18
|
+
type_="button"
|
|
19
|
+
onClick={_ => {
|
|
20
|
+
dropdownContext.hide()
|
|
21
|
+
onCancel()
|
|
22
|
+
}}>
|
|
23
|
+
<FormattedMessage defaultMessage={"Annuler"} />
|
|
24
|
+
</Toolkit__Ui_Button>
|
|
25
|
+
<Toolkit__Ui_Button
|
|
26
|
+
color=#primary
|
|
27
|
+
type_="button"
|
|
28
|
+
onClick={_ => {
|
|
29
|
+
onValidateClick()
|
|
30
|
+
dropdownContext.hide()
|
|
31
|
+
}}>
|
|
32
|
+
<FormattedMessage defaultMessage={"Valider"} />
|
|
33
|
+
</Toolkit__Ui_Button>
|
|
34
|
+
</footer>
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module Options = {
|
|
39
|
+
@react.component
|
|
40
|
+
let make = (~options, ~deferredSearch, ~itemClassName, ~setSelectedOption, ~selectedOption) => {
|
|
41
|
+
options
|
|
42
|
+
->Array.keep(({label}) =>
|
|
43
|
+
deferredSearch == "" ||
|
|
44
|
+
label->Toolkit__Primitives.String.normalizeForSearch->Js.String2.includes(deferredSearch)
|
|
45
|
+
)
|
|
46
|
+
->Array.mapWithIndex((i, item) => {
|
|
47
|
+
let {label, value} = item
|
|
48
|
+
|
|
49
|
+
<div
|
|
50
|
+
key={`multiselectoption-${label}-${value}-${i->Int.toString}`}
|
|
51
|
+
className={cx([
|
|
52
|
+
"group flex flex-row items-center gap-2 pt-3 text-left relative",
|
|
53
|
+
i > 0 ? "mt-3" : "",
|
|
54
|
+
itemClassName,
|
|
55
|
+
])}>
|
|
56
|
+
<Toolkit__Ui_Radio
|
|
57
|
+
value
|
|
58
|
+
className="w-full flex-shrink-0 relative"
|
|
59
|
+
checked={selectedOption->Option.mapWithDefault(false, selectedOption => {
|
|
60
|
+
item.label == selectedOption.label && item.value == selectedOption.value
|
|
61
|
+
})}
|
|
62
|
+
onChange={_ => {
|
|
63
|
+
setSelectedOption(_ => {
|
|
64
|
+
Some(item)
|
|
65
|
+
})
|
|
66
|
+
}}>
|
|
67
|
+
{item.itemLabel->Option.getWithDefault(label->React.string)}
|
|
68
|
+
</Toolkit__Ui_Radio>
|
|
69
|
+
</div>
|
|
70
|
+
})
|
|
71
|
+
->React.array
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@react.component
|
|
76
|
+
let make = (
|
|
77
|
+
~options: options,
|
|
78
|
+
~placeholder: React.element,
|
|
79
|
+
~buttonClassName="",
|
|
80
|
+
~dropdownClassName="",
|
|
81
|
+
~itemClassName="",
|
|
82
|
+
~searchPlaceholder: option<string>=?,
|
|
83
|
+
~allowFilter=true,
|
|
84
|
+
~defaultValue: option<item>=?,
|
|
85
|
+
~onValidate: item => unit,
|
|
86
|
+
~disabled: option<bool>=?,
|
|
87
|
+
~onCancel: option<unit => unit>=?,
|
|
88
|
+
) => {
|
|
89
|
+
let (selectedOption, setSelectedOption) = React.useState(() => defaultValue)
|
|
90
|
+
let previousDefaultValue = Toolkit__Hooks.usePrevious(defaultValue)
|
|
91
|
+
let (search, setSearch) = React.useState(() => "")
|
|
92
|
+
let deferredSearch = React.useDeferredValue(search)
|
|
93
|
+
let allowFilter = options->Array.length > 5 && allowFilter
|
|
94
|
+
|
|
95
|
+
React.useEffect2(() => {
|
|
96
|
+
switch (previousDefaultValue, defaultValue) {
|
|
97
|
+
| (Some(Some(v)), Some(v2)) if v !== v2 => setSelectedOption(_ => defaultValue)
|
|
98
|
+
| _ => ()
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
None
|
|
102
|
+
}, (previousDefaultValue, defaultValue))
|
|
103
|
+
|
|
104
|
+
<Toolkit__Ui_Dropdown
|
|
105
|
+
?disabled
|
|
106
|
+
buttonClassName
|
|
107
|
+
onClose={_ => setSelectedOption(_ => defaultValue)}
|
|
108
|
+
dropdownClassName
|
|
109
|
+
position=#bottom
|
|
110
|
+
label={switch selectedOption {
|
|
111
|
+
| None =>
|
|
112
|
+
<p className="flex flex-row gap-2 w-full items-center relative">
|
|
113
|
+
<span className="ml-1"> {placeholder} </span>
|
|
114
|
+
<span className="absolute inset-y-0 right-0 flex items-center">
|
|
115
|
+
<ReactIcons.FaAngleDown />
|
|
116
|
+
</span>
|
|
117
|
+
</p>
|
|
118
|
+
| Some({label}) =>
|
|
119
|
+
<div className="table table-fixed w-full" title={label}>
|
|
120
|
+
<span className="table-cell truncate text-left"> {label->React.string} </span>
|
|
121
|
+
</div>
|
|
122
|
+
}}>
|
|
123
|
+
<div className="py-2 pl-2 pr-1 max-h-[300px] overflow-y-scroll">
|
|
124
|
+
{allowFilter
|
|
125
|
+
? <div className="mb-3">
|
|
126
|
+
<Toolkit__Ui_TextInput
|
|
127
|
+
id="search"
|
|
128
|
+
autoFocus={true}
|
|
129
|
+
placeholder=?{searchPlaceholder}
|
|
130
|
+
allowWhiteSpace={true}
|
|
131
|
+
value={search}
|
|
132
|
+
onChange={event => {
|
|
133
|
+
let target = event->ReactEvent.Form.currentTarget
|
|
134
|
+
|
|
135
|
+
setSearch(_ => target["value"]->Toolkit__Primitives.String.normalizeForSearch)
|
|
136
|
+
}}
|
|
137
|
+
/>
|
|
138
|
+
</div>
|
|
139
|
+
: React.null}
|
|
140
|
+
<Options deferredSearch options setSelectedOption selectedOption itemClassName />
|
|
141
|
+
</div>
|
|
142
|
+
<Footer
|
|
143
|
+
onCancel={() => {
|
|
144
|
+
setSelectedOption(_ => defaultValue)
|
|
145
|
+
onCancel->Option.forEach(fn => fn())
|
|
146
|
+
}}
|
|
147
|
+
onValidateClick={() => selectedOption->Option.forEach(onValidate)}
|
|
148
|
+
/>
|
|
149
|
+
</Toolkit__Ui_Dropdown>
|
|
150
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
type item = {itemLabel?: React.element, label: string, value: string}
|
|
2
|
+
type options = array<item>
|
|
3
|
+
|
|
4
|
+
@react.component
|
|
5
|
+
let make: (
|
|
6
|
+
~options: options,
|
|
7
|
+
~placeholder: React.element,
|
|
8
|
+
~buttonClassName: string=?,
|
|
9
|
+
~dropdownClassName: string=?,
|
|
10
|
+
~itemClassName: string=?,
|
|
11
|
+
~searchPlaceholder: string=?,
|
|
12
|
+
~allowFilter: bool=?,
|
|
13
|
+
~defaultValue: item=?,
|
|
14
|
+
~onValidate: item => unit,
|
|
15
|
+
~disabled: bool=?,
|
|
16
|
+
~onCancel: unit => unit=?,
|
|
17
|
+
) => React.element
|
package/src/vendors/Browser.res
CHANGED