@colisweb/rescript-toolkit 5.38.2 → 5.40.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
|
@@ -21,6 +21,34 @@ module type Config = {
|
|
|
21
21
|
module Make = (StateLenses: Config) => {
|
|
22
22
|
include Reform.Make(StateLenses)
|
|
23
23
|
|
|
24
|
+
module RadioGroupEnum = {
|
|
25
|
+
@react.component
|
|
26
|
+
let make = (
|
|
27
|
+
type enum,
|
|
28
|
+
~enum: module(Toolkit__Utils.Enum with type t = enum),
|
|
29
|
+
~field,
|
|
30
|
+
~elements,
|
|
31
|
+
~variant=?,
|
|
32
|
+
~inline=?,
|
|
33
|
+
~containerClassName=?,
|
|
34
|
+
) =>
|
|
35
|
+
<Field
|
|
36
|
+
field
|
|
37
|
+
render={({handleChange, error, value}) =>
|
|
38
|
+
<React.Fragment>
|
|
39
|
+
<Toolkit__Ui_RadioGroupEnum
|
|
40
|
+
enum
|
|
41
|
+
?containerClassName
|
|
42
|
+
?variant
|
|
43
|
+
defaultValue=?value
|
|
44
|
+
onChange={v => handleChange(v)}
|
|
45
|
+
elements
|
|
46
|
+
?inline
|
|
47
|
+
/>
|
|
48
|
+
<ErrorMessage ?error />
|
|
49
|
+
</React.Fragment>}
|
|
50
|
+
/>
|
|
51
|
+
}
|
|
24
52
|
module RadioGroup = {
|
|
25
53
|
@react.component
|
|
26
54
|
let make = (~field, ~elements, ~variant=?, ~inline=?, ~containerClassName=?) =>
|
|
@@ -510,6 +538,69 @@ module Make = (StateLenses: Config) => {
|
|
|
510
538
|
/>
|
|
511
539
|
}
|
|
512
540
|
}
|
|
541
|
+
module SelectEnum = {
|
|
542
|
+
@react.component
|
|
543
|
+
let make = (
|
|
544
|
+
type enum,
|
|
545
|
+
~enum: module(Toolkit__Utils.Enum with type t = enum),
|
|
546
|
+
~field,
|
|
547
|
+
~label=?,
|
|
548
|
+
~id,
|
|
549
|
+
~name=?,
|
|
550
|
+
~options: Toolkit__Ui_SelectEnum.options<enum>,
|
|
551
|
+
~placeholder=?,
|
|
552
|
+
~autoFocus=?,
|
|
553
|
+
~disabled=?,
|
|
554
|
+
~isOptional=?,
|
|
555
|
+
~className=?,
|
|
556
|
+
) => {
|
|
557
|
+
<Field
|
|
558
|
+
field
|
|
559
|
+
render={({handleChange, error, value, validate, state}) => {
|
|
560
|
+
let isInvalid = error->Option.isSome
|
|
561
|
+
|
|
562
|
+
let onBlur = _ => {
|
|
563
|
+
switch state {
|
|
564
|
+
| Pristine => ()
|
|
565
|
+
| _ => validate()
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
<React.Fragment>
|
|
570
|
+
{switch label {
|
|
571
|
+
| None => React.null
|
|
572
|
+
| Some(label) =>
|
|
573
|
+
<Toolkit__Ui_Label
|
|
574
|
+
htmlFor=id
|
|
575
|
+
optionalMessage={isOptional->Option.getWithDefault(false)
|
|
576
|
+
? <FormattedMessage defaultMessage="(Optionnel)" />
|
|
577
|
+
: React.null}>
|
|
578
|
+
label
|
|
579
|
+
</Toolkit__Ui_Label>
|
|
580
|
+
}}
|
|
581
|
+
<Toolkit__Ui_SelectEnum
|
|
582
|
+
enum
|
|
583
|
+
options
|
|
584
|
+
?name
|
|
585
|
+
?placeholder
|
|
586
|
+
?autoFocus
|
|
587
|
+
?className
|
|
588
|
+
isDisabled=?{disabled}
|
|
589
|
+
onBlur
|
|
590
|
+
id
|
|
591
|
+
isInvalid
|
|
592
|
+
?value
|
|
593
|
+
onChange={selectedValue => {
|
|
594
|
+
Js.log(selectedValue)
|
|
595
|
+
handleChange(selectedValue)
|
|
596
|
+
}}
|
|
597
|
+
/>
|
|
598
|
+
<ErrorMessage ?error />
|
|
599
|
+
</React.Fragment>
|
|
600
|
+
}}
|
|
601
|
+
/>
|
|
602
|
+
}
|
|
603
|
+
}
|
|
513
604
|
|
|
514
605
|
module SearchSelect = {
|
|
515
606
|
open! ReactSelect
|
|
@@ -247,6 +247,10 @@ module Make = (Config: RouterConfig) => {
|
|
|
247
247
|
~isSubLink=false,
|
|
248
248
|
~isActive=false,
|
|
249
249
|
~onLinkClick=() => (),
|
|
250
|
+
~containerClassName="",
|
|
251
|
+
~labelClassName="",
|
|
252
|
+
~tooltipClassName="",
|
|
253
|
+
~activeClassName="",
|
|
250
254
|
) =>
|
|
251
255
|
switch link {
|
|
252
256
|
| Custom(element) => element
|
|
@@ -255,7 +259,12 @@ module Make = (Config: RouterConfig) => {
|
|
|
255
259
|
<a
|
|
256
260
|
href=url
|
|
257
261
|
target="_blank"
|
|
258
|
-
className={cx([
|
|
262
|
+
className={cx([
|
|
263
|
+
commonClassName,
|
|
264
|
+
"py-3 sidenav-link",
|
|
265
|
+
isSubLink ? "ml-3" : "",
|
|
266
|
+
containerClassName,
|
|
267
|
+
])}>
|
|
259
268
|
<span className="overflow-hidden flex">
|
|
260
269
|
{config.icon->Option.mapWithDefault(React.null, icon =>
|
|
261
270
|
<div className={cx(["text-neutral-800", isNavOpen ? "pl-2" : "px-2"])}> icon </div>
|
|
@@ -265,13 +274,17 @@ module Make = (Config: RouterConfig) => {
|
|
|
265
274
|
"transition-all duration-200 ease-in-out absolute ml-12 w-40 transform top-1/2 -translate-y-1/2",
|
|
266
275
|
isNavOpen ? "pl-1 opacity-100 delay-75" : "opacity-0 invisible",
|
|
267
276
|
isSubLink ? "text-sm" : "",
|
|
277
|
+
labelClassName,
|
|
268
278
|
])}>
|
|
269
279
|
label
|
|
270
280
|
</span>
|
|
271
281
|
{isNavOpen
|
|
272
282
|
? React.null
|
|
273
283
|
: <div
|
|
274
|
-
className=
|
|
284
|
+
className={cx([
|
|
285
|
+
"sidenav-link-tooltip absolute left-0 p-2 bg-neutral-700 text-white rounded transform top-1/2 -translate-y-1/2 transition-all duration-200 ease-in-out opacity-0 invisible ml-16 whitespace-nowrap",
|
|
286
|
+
tooltipClassName,
|
|
287
|
+
])}>
|
|
275
288
|
label
|
|
276
289
|
</div>}
|
|
277
290
|
</span>
|
|
@@ -288,9 +301,14 @@ module Make = (Config: RouterConfig) => {
|
|
|
288
301
|
isSubLink ? "ml-3" : "",
|
|
289
302
|
config.icon->Option.isNone ? "py-5" : "",
|
|
290
303
|
"sidenav-link",
|
|
304
|
+
containerClassName,
|
|
291
305
|
isActive && !disabledActiveLink ? "bg-primary-100/75 text-neutral-700" : "",
|
|
306
|
+
isActive && !disabledActiveLink ? activeClassName : "",
|
|
307
|
+
])}
|
|
308
|
+
activeClassName={cx([
|
|
309
|
+
disabledActiveLink ? "" : "bg-primary-100/75 text-neutral-700",
|
|
310
|
+
disabledActiveLink ? "" : activeClassName,
|
|
292
311
|
])}
|
|
293
|
-
activeClassName={disabledActiveLink ? "" : "bg-primary-100/75 text-neutral-700"}
|
|
294
312
|
onClick={_ => onLinkClick()}>
|
|
295
313
|
<span className="overflow-hidden flex">
|
|
296
314
|
{config.icon->Option.mapWithDefault(React.null, icon =>
|
|
@@ -301,13 +319,17 @@ module Make = (Config: RouterConfig) => {
|
|
|
301
319
|
"transition-all duration-200 ease-in-out absolute ml-12 w-40 transform top-1/2 -translate-y-1/2",
|
|
302
320
|
isNavOpen ? "pl-1 opacity-100 delay-75" : "opacity-0 invisible",
|
|
303
321
|
isSubLink ? "text-sm" : "",
|
|
322
|
+
labelClassName,
|
|
304
323
|
])}>
|
|
305
324
|
label
|
|
306
325
|
</span>
|
|
307
326
|
{isNavOpen
|
|
308
327
|
? React.null
|
|
309
328
|
: <div
|
|
310
|
-
className=
|
|
329
|
+
className={cx([
|
|
330
|
+
"sidenav-link-tooltip absolute left-0 p-2 bg-neutral-700 text-white rounded transform top-1/2 -translate-y-1/2 transition-all duration-200 ease-in-out opacity-0 invisible ml-16 whitespace-nowrap",
|
|
331
|
+
tooltipClassName,
|
|
332
|
+
])}>
|
|
311
333
|
label
|
|
312
334
|
</div>}
|
|
313
335
|
</span>
|
|
@@ -345,6 +367,8 @@ module Make = (Config: RouterConfig) => {
|
|
|
345
367
|
~isNavOpen: bool,
|
|
346
368
|
~onLinkClick=() => (),
|
|
347
369
|
~openMenu,
|
|
370
|
+
~iconClassName="",
|
|
371
|
+
~labelClassName="",
|
|
348
372
|
) => {
|
|
349
373
|
let (isOpen, setIsOpen) = React.useState(() => false)
|
|
350
374
|
let currentRoute = useRoute()
|
|
@@ -387,13 +411,15 @@ module Make = (Config: RouterConfig) => {
|
|
|
387
411
|
"flex items-center w-full sidenav-link",
|
|
388
412
|
hasActiveSubRoute || relativeRoute->Option.isSome ? "bg-primary-100/75" : "",
|
|
389
413
|
])}>
|
|
390
|
-
<span
|
|
414
|
+
<span
|
|
415
|
+
className={cx(["mr-2 text-neutral-800", isNavOpen ? "pl-2" : "px-2", iconClassName])}>
|
|
391
416
|
groupInfo.icon
|
|
392
417
|
</span>
|
|
393
418
|
<span
|
|
394
419
|
className={cx([
|
|
395
420
|
"transition-all duration-200 ease-in-out absolute ml-12 w-40 transform top-1/2 -translate-y-1/2 text-left",
|
|
396
421
|
isNavOpen ? "pl-1 opacity-100 delay-75" : "opacity-0 invisible",
|
|
422
|
+
labelClassName,
|
|
397
423
|
])}>
|
|
398
424
|
groupInfo.label
|
|
399
425
|
</span>
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
type size = [#xs | #sm | #md | #lg]
|
|
2
|
+
type variant =
|
|
3
|
+
| Default
|
|
4
|
+
| Filled
|
|
5
|
+
|
|
6
|
+
@react.component
|
|
7
|
+
let make = (
|
|
8
|
+
type enum,
|
|
9
|
+
~enum: module(Toolkit__Utils.Enum with type t = enum),
|
|
10
|
+
~value: enum,
|
|
11
|
+
~children: option<React.element>=?,
|
|
12
|
+
~disabled: option<bool>=?,
|
|
13
|
+
~onChange=?,
|
|
14
|
+
~name=?,
|
|
15
|
+
~checked=?,
|
|
16
|
+
~className="",
|
|
17
|
+
~contentClassName="",
|
|
18
|
+
~size: size=#sm,
|
|
19
|
+
~variant: variant=Default,
|
|
20
|
+
~icon: option<module(ReactIcons.Icon)>=?,
|
|
21
|
+
) => {
|
|
22
|
+
<label
|
|
23
|
+
className={cx([
|
|
24
|
+
"flex items-center cw-radio relative",
|
|
25
|
+
switch variant {
|
|
26
|
+
| Default => "cw-radio--default"
|
|
27
|
+
| Filled => "self-start bg-neutral-100 font-medium px-2 py-1 rounded-full cw-radio--filled"
|
|
28
|
+
},
|
|
29
|
+
disabled->Option.getWithDefault(false)
|
|
30
|
+
? "cursor-not-allowed opacity-75 text-gray-600"
|
|
31
|
+
: "cursor-pointer",
|
|
32
|
+
className,
|
|
33
|
+
])}>
|
|
34
|
+
<input
|
|
35
|
+
type_="radio"
|
|
36
|
+
value={Toolkit__Utils.encodeEnumToString(value, enum)}
|
|
37
|
+
className="opacity-0 w-0 h-0 peer cw-radio-input"
|
|
38
|
+
onChange={event => {
|
|
39
|
+
let target = ReactEvent.Form.target(event)
|
|
40
|
+
let value = target["value"]
|
|
41
|
+
|
|
42
|
+
onChange->Option.forEach(fn =>
|
|
43
|
+
fn(Toolkit__Utils.decodeEnumFromString(value, enum)->Option.getExn)
|
|
44
|
+
)
|
|
45
|
+
}}
|
|
46
|
+
?disabled
|
|
47
|
+
?name
|
|
48
|
+
?checked
|
|
49
|
+
/>
|
|
50
|
+
{switch variant {
|
|
51
|
+
| Default => React.null
|
|
52
|
+
| Filled =>
|
|
53
|
+
<span
|
|
54
|
+
className="cw-radio-filled-bg peer-checked:bg-primary-700 w-full h-full absolute rounded-full left-0 top-0"
|
|
55
|
+
/>
|
|
56
|
+
}}
|
|
57
|
+
<span
|
|
58
|
+
className={cx([
|
|
59
|
+
"bg-white flex-shrink-0 cw-radio-circle",
|
|
60
|
+
{
|
|
61
|
+
switch variant {
|
|
62
|
+
| Default => "border peer-checked:border-4 peer-checked:border-primary-700 peer-checked:text-primary-700"
|
|
63
|
+
| Filled => "border-2 peer-checked:border-primary-700 peer-checked:text-white"
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"checkmark rounded-full mr-2 border-neutral-700 transform transition-all ease-in-out flex items-center justify-center",
|
|
67
|
+
switch size {
|
|
68
|
+
| #xs => "w-4 h-4"
|
|
69
|
+
| #sm => "w-6 h-6"
|
|
70
|
+
| #md => "w-8 h-8"
|
|
71
|
+
| #lg => "w-10 h-10"
|
|
72
|
+
},
|
|
73
|
+
])}>
|
|
74
|
+
{switch variant {
|
|
75
|
+
| Default => React.null
|
|
76
|
+
| Filled =>
|
|
77
|
+
<span
|
|
78
|
+
className={cx([
|
|
79
|
+
"transform transition-all ease-in-out cw-radio-circle-content rounded-full",
|
|
80
|
+
switch size {
|
|
81
|
+
| #xs => "w-2 h-2"
|
|
82
|
+
| #sm => "w-3 h-3"
|
|
83
|
+
| #md => "w-4 h-4"
|
|
84
|
+
| #lg => "w-6 h-6"
|
|
85
|
+
},
|
|
86
|
+
])}
|
|
87
|
+
/>
|
|
88
|
+
}}
|
|
89
|
+
</span>
|
|
90
|
+
<span
|
|
91
|
+
className={cx([
|
|
92
|
+
"flex flex-row items-center gap-2",
|
|
93
|
+
{
|
|
94
|
+
switch variant {
|
|
95
|
+
| Default => ""
|
|
96
|
+
| Filled => "peer-checked:text-white relative pr-1"
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
contentClassName,
|
|
100
|
+
])}>
|
|
101
|
+
{icon->Option.mapWithDefault(React.null, icon => {
|
|
102
|
+
let module(Icon) = icon
|
|
103
|
+
|
|
104
|
+
<Icon
|
|
105
|
+
size={switch size {
|
|
106
|
+
| #lg => 26
|
|
107
|
+
| #md => 24
|
|
108
|
+
| #sm => 20
|
|
109
|
+
| #xs => 16
|
|
110
|
+
}}
|
|
111
|
+
/>
|
|
112
|
+
})}
|
|
113
|
+
{children->Option.getWithDefault(React.null)}
|
|
114
|
+
</span>
|
|
115
|
+
</label>
|
|
116
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module Radio = Toolkit__Ui_RadioEnum
|
|
2
|
+
|
|
3
|
+
type element<'value> = {
|
|
4
|
+
label: React.element,
|
|
5
|
+
value: 'value,
|
|
6
|
+
disabled?: bool,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
@react.component
|
|
10
|
+
let make = (
|
|
11
|
+
type enum,
|
|
12
|
+
~enum: module(Toolkit__Utils.Enum with type t = enum),
|
|
13
|
+
~onChange,
|
|
14
|
+
~elements: array<element<enum>>,
|
|
15
|
+
~variant=?,
|
|
16
|
+
~defaultValue: option<enum>=?,
|
|
17
|
+
~containerClassName="",
|
|
18
|
+
~inline=false,
|
|
19
|
+
) => {
|
|
20
|
+
let name = "radio-" ++ ReachUi_AutoId.use("")
|
|
21
|
+
let (value, setValue) = React.useState(() => defaultValue)
|
|
22
|
+
|
|
23
|
+
React.useEffect(() => {
|
|
24
|
+
onChange(value)
|
|
25
|
+
None
|
|
26
|
+
}, [value])
|
|
27
|
+
|
|
28
|
+
<div className={cx([inline ? "flex gap-3" : "", containerClassName])}>
|
|
29
|
+
{elements
|
|
30
|
+
->Array.mapWithIndex((i, element) =>
|
|
31
|
+
<Radio
|
|
32
|
+
enum
|
|
33
|
+
?variant
|
|
34
|
+
key={"radio-" ++ string_of_int(i)}
|
|
35
|
+
value=element.value
|
|
36
|
+
name
|
|
37
|
+
disabled=?element.disabled
|
|
38
|
+
checked={Some(element.value) === value}
|
|
39
|
+
onChange={value => {
|
|
40
|
+
setValue(_ => Some(value))
|
|
41
|
+
}}>
|
|
42
|
+
element.label
|
|
43
|
+
</Radio>
|
|
44
|
+
)
|
|
45
|
+
->React.array}
|
|
46
|
+
</div>
|
|
47
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
type selectOption<'value> = {
|
|
2
|
+
label: string,
|
|
3
|
+
value: 'value,
|
|
4
|
+
disabled?: bool,
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
type options<'value> = array<selectOption<'value>>
|
|
8
|
+
|
|
9
|
+
@react.component
|
|
10
|
+
let make = (
|
|
11
|
+
type enum,
|
|
12
|
+
~enum: module(Toolkit__Utils.Enum with type t = enum),
|
|
13
|
+
~options: options<enum>,
|
|
14
|
+
~onChange: option<enum> => unit,
|
|
15
|
+
~onBlur=?,
|
|
16
|
+
~placeholder=?,
|
|
17
|
+
~defaultValue=?,
|
|
18
|
+
~isDisabled=?,
|
|
19
|
+
~isInvalid=?,
|
|
20
|
+
~className="",
|
|
21
|
+
~containerClassName="",
|
|
22
|
+
~id=?,
|
|
23
|
+
~value: option<enum>=?,
|
|
24
|
+
~name=?,
|
|
25
|
+
~autoFocus=?,
|
|
26
|
+
) =>
|
|
27
|
+
<Toolkit__Ui_Select
|
|
28
|
+
?id
|
|
29
|
+
?name
|
|
30
|
+
containerClassName
|
|
31
|
+
className
|
|
32
|
+
?autoFocus
|
|
33
|
+
?onBlur
|
|
34
|
+
?isDisabled
|
|
35
|
+
?isInvalid
|
|
36
|
+
?placeholder
|
|
37
|
+
value=?{value->Option.map(v => Toolkit__Utils.encodeEnumToString(v, enum))}
|
|
38
|
+
defaultValue=?{defaultValue->Option.map(v => v->Toolkit__Utils.encodeEnumToString(enum))}
|
|
39
|
+
options={options->Array.map((option): Toolkit__Ui_Select.selectOption => {
|
|
40
|
+
label: option.label,
|
|
41
|
+
value: option.value->Toolkit__Utils.encodeEnumToString(enum),
|
|
42
|
+
disabled: ?option.disabled,
|
|
43
|
+
})}
|
|
44
|
+
onChange={value => {
|
|
45
|
+
value->Toolkit__Utils.decodeEnumFromString(enum)->onChange
|
|
46
|
+
}}
|
|
47
|
+
/>
|