@colisweb/rescript-toolkit 2.71.1 → 3.0.1

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.
Files changed (65) hide show
  1. package/.yarn/cache/@colisweb-restorative-npm-1.0.0-5eac899f0c-6e80ecc641.zip +0 -0
  2. package/.yarn/cache/@rescript-react-npm-0.11.0-687f8fa3b5-c399d114f7.zip +0 -0
  3. package/.yarn/cache/{rescript-npm-10.0.1-c064c63c72-59ae153c7f.zip → rescript-npm-10.1.2-eb312a329e-e70ae09da1.zip} +0 -0
  4. package/.yarn/install-state.gz +0 -0
  5. package/bsconfig.json +2 -2
  6. package/locale/fr.json +5 -0
  7. package/package.json +4 -5
  8. package/playground/PlaygroundApp.res +12 -0
  9. package/playground/PlaygroundBindings.res +106 -0
  10. package/playground/PlaygroundHooks.res +4 -4
  11. package/playground/PlaygroundRouter.res +18 -0
  12. package/playground/bindings/Playground_Bindings_Reach.res +143 -0
  13. package/playground/components/Playground_Form.res +56 -3
  14. package/playground/components/Playground_Modal.res +20 -5
  15. package/playground/components/Playground_Select.res +14 -4
  16. package/playground/hooks/{Playground_Clipboard.res → Playground_Hooks_Clipboard.res} +1 -1
  17. package/playground/hooks/{Playground_Disclosure.res → Playground_Hooks_Disclosure.res} +1 -1
  18. package/playground/hooks/{Playground_LazyLoad.res → Playground_Hooks_LazyLoad.res} +1 -1
  19. package/playground/hooks/{Playground_MediaQueries.res → Playground_Hooks_MediaQueries.res} +1 -1
  20. package/src/decoders/Toolkit__Decoders.res +1 -1
  21. package/src/form/Reform.res +8 -36
  22. package/src/form/Toolkit__Form.res +114 -55
  23. package/src/hooks/Toolkit__Hooks.res +1 -1
  24. package/src/intl/Toolkit__Intl.res +1 -1
  25. package/src/intl/Toolkit__Intl.resi +1 -1
  26. package/src/logger/Toolkit__NativeLogger.res +1 -1
  27. package/src/router/Toolkit__Router.res +0 -6
  28. package/src/ui/Toolkit__Ui.res +0 -2
  29. package/src/ui/Toolkit__Ui_Dropdown.res +13 -7
  30. package/src/ui/Toolkit__Ui_Dropdown.resi +2 -0
  31. package/src/ui/Toolkit__Ui_Layout.res +1 -6
  32. package/src/ui/Toolkit__Ui_MultiSelect.res +10 -4
  33. package/src/ui/Toolkit__Ui_MultiSelect.resi +5 -1
  34. package/src/ui/Toolkit__Ui_NativeDatePicker.res +2 -2
  35. package/src/ui/Toolkit__Ui_Select.res +22 -5
  36. package/src/ui/Toolkit__Ui_Select.resi +13 -2
  37. package/src/ui/Toolkit__Ui_SelectPolyvariant.res +45 -0
  38. package/src/ui/Toolkit__Ui_Table.res +11 -6
  39. package/src/ui/Toolkit__Ui_TextInput.res +2 -2
  40. package/src/ui/Toolkit__Ui_WeekDateFilter.res +16 -16
  41. package/src/utils/Toolkit__Utils_UnitMeasure.res +4 -4
  42. package/src/vendors/{BsCopyToClipboard.res → CopyToClipboard.res} +0 -0
  43. package/src/vendors/{BsDateFns.res → DateFns.res} +0 -0
  44. package/src/vendors/{BsJsCookie.res → JsCookie.res} +0 -0
  45. package/src/vendors/{BsReactDayPicker.res → ReactDayPicker.res} +0 -1
  46. package/src/vendors/{BsReactGoogleMaps.res → ReactGoogleMaps.res} +0 -0
  47. package/src/vendors/ReactIcons.res +11 -0
  48. package/src/vendors/{BsReactSelect.res → ReactSelect.res} +58 -58
  49. package/src/vendors/{BsSentryReactNative.res → SentryReactNative.res} +0 -0
  50. package/src/vendors/reach-ui/ReachUi_Accordion.res +12 -14
  51. package/src/vendors/reach-ui/ReachUi_AlertDialog.res +8 -34
  52. package/src/vendors/reach-ui/ReachUi_Dialog.res +7 -10
  53. package/src/vendors/reach-ui/ReachUi_Listbox.res +8 -9
  54. package/src/vendors/reach-ui/ReachUi_MenuButton.res +7 -30
  55. package/src/vendors/reach-ui/ReachUi_Popover.res +0 -6
  56. package/src/vendors/reach-ui/ReachUi_Tabs.res +18 -27
  57. package/.yarn/cache/@colisweb-restorative-npm-0.5.1-2ffe068813-cd8332a7eb.zip +0 -0
  58. package/.yarn/cache/@rescript-react-npm-0.10.3-26bd5d697f-8561282f78.zip +0 -0
  59. package/.yarn/cache/compute-scroll-into-view-npm-1.0.16-a8a68c1929-4334db6397.zip +0 -0
  60. package/.yarn/cache/downshift-npm-5.2.5-14bb33ffd8-498b4764a8.zip +0 -0
  61. package/src/mock/MockOverlay.resi +0 -4
  62. package/src/ui/Toolkit__Ui_Listbox.res +0 -123
  63. package/src/ui/Toolkit__Ui_ListboxInput.res +0 -673
  64. package/src/vendors/BsAnalytics.res +0 -34
  65. package/src/vendors/BsDownshift.res +0 -596
@@ -109,34 +109,24 @@ module Make = (Config: Config) => {
109
109
  )
110
110
  }
111
111
 
112
- let formContext: React.Context.t<option<api>> = React.createContext(None)
112
+ let formContext: React.Context.t<api> = React.createContext(Obj.magic(None))
113
113
 
114
114
  let useFormContext = () => React.useContext(formContext)
115
115
 
116
116
  let useField = field => {
117
- let interface = useFormContext()
118
- interface->Belt.Option.map(({
119
- handleChange,
120
- getFieldError,
121
- getFieldState,
122
- validateField,
123
- state,
124
- }) => {
117
+ let {handleChange, getFieldError, getFieldState, validateField, state} = useFormContext()
118
+
119
+ {
125
120
  handleChange: handleChange(field),
126
121
  error: getFieldError(Field(field)),
127
122
  state: getFieldState(Field(field)),
128
123
  validate: () => validateField(Field(field)),
129
124
  value: state.values->Config.get(field),
130
- })
125
+ }
131
126
  }
132
127
 
133
128
  module Provider = {
134
- let provider = React.Context.provider(formContext)
135
-
136
- @react.component
137
- let make = (~value: api, ~children) => {
138
- React.createElement(provider, {"value": Some(value), "children": children})
139
- }
129
+ let make = React.Context.provider(formContext)
140
130
  }
141
131
 
142
132
  module Field = {
@@ -148,26 +138,8 @@ module Make = (Config: Config) => {
148
138
  (),
149
139
  ) => {
150
140
  let fieldInterface = useField(field)
151
- React.useMemo3(
152
- () =>
153
- fieldInterface
154
- ->Belt.Option.map(render)
155
- ->Belt.Option.getWithDefault(renderOnMissingContext),
156
- (
157
- {
158
- open Belt.Option
159
- fieldInterface->flatMap(({error}) => error)->getWithDefault("")
160
- },
161
- {
162
- open Belt.Option
163
- fieldInterface->map(({value}) => value)
164
- },
165
- {
166
- open Belt.Option
167
- fieldInterface->map(({state}) => state)
168
- },
169
- ),
170
- )
141
+
142
+ render(fieldInterface)
171
143
  }
172
144
  }
173
145
 
@@ -9,6 +9,11 @@ module Helpers = {
9
9
  }
10
10
  }
11
11
 
12
+ module Msg = {
13
+ @@intl.messages
14
+ let optionNonEmpty = {defaultMessage: "Le champ est requis."}
15
+ }
16
+
12
17
  module ErrorMessage = {
13
18
  @react.component
14
19
  let make = (~error=?, ~className="") =>
@@ -62,10 +67,28 @@ module Make = (StateLenses: Config) => {
62
67
  )
63
68
  }
64
69
 
70
+ module CustomValidation = {
71
+ let optionNonEmpty = (intl, lense) => Form.Validation.Custom(
72
+ lense,
73
+ values =>
74
+ values->StateLenses.get(lense)->Option.isNone
75
+ ? Error(intl->Intl.formatMessage(Msg.optionNonEmpty))
76
+ : Valid,
77
+ )
78
+
79
+ let arrayNonEmpty = (intl, lense) => Form.Validation.Custom(
80
+ lense,
81
+ values =>
82
+ values->StateLenses.get(lense)->Array.length == 0
83
+ ? Error(intl->Intl.formatMessage(Msg.optionNonEmpty))
84
+ : Valid,
85
+ )
86
+ }
87
+
65
88
  module Wrapper = {
66
89
  @react.component
67
90
  let make = (~id=?, ~className=?, ~children) => {
68
- let form = Form.useFormContext()->Option.getExn
91
+ let form = Form.useFormContext()
69
92
  <form
70
93
  ?id
71
94
  ?className
@@ -444,29 +467,19 @@ module Make = (StateLenses: Config) => {
444
467
  ~label=?,
445
468
  ~id,
446
469
  ~name=?,
447
- ~items,
448
- ~itemToLabel=?,
449
- ~itemToId=?,
470
+ ~options: Toolkit__Ui_Select.options,
450
471
  ~placeholder=?,
451
- ~hasPlaceholderOption=?,
452
472
  ~autoFocus=?,
453
473
  ~disabled=?,
454
474
  ~isOptional=?,
455
475
  ~className=?,
456
476
  ) => {
457
- let valueRef = React.useRef(None)
458
-
459
477
  <Form.Field
460
478
  field
461
479
  render={({handleChange, error, value, validate, state}) => {
462
480
  let isInvalid = error->Option.isSome
463
481
 
464
- let onChange = value => valueRef.current = Some(value)
465
-
466
482
  let onBlur = _ => {
467
- valueRef.current->Option.map(handleChange)->ignore
468
- valueRef.current = None
469
-
470
483
  switch state {
471
484
  | Pristine => ()
472
485
  | _ => validate()
@@ -485,21 +498,84 @@ module Make = (StateLenses: Config) => {
485
498
  label
486
499
  </Toolkit__Ui_Label>
487
500
  }}
488
- <Toolkit__Ui_ListboxInput.Select
489
- ?className
490
- items
501
+ <Toolkit__Ui_Select
502
+ options
491
503
  ?name
492
- ?itemToLabel
493
- ?itemToId
494
- id
495
- ?disabled
496
504
  ?placeholder
497
- ?hasPlaceholderOption
498
505
  ?autoFocus
506
+ ?className
507
+ isDisabled=?{disabled}
508
+ onBlur
509
+ id
499
510
  isInvalid
500
- onChange
511
+ value
512
+ onChange={selectedValue => {
513
+ handleChange(selectedValue)
514
+ }}
515
+ />
516
+ <ErrorMessage ?error />
517
+ </>
518
+ }}
519
+ />
520
+ }
521
+ }
522
+
523
+ module SelectPolyvariant = {
524
+ @react.component
525
+ let make = (
526
+ ~field,
527
+ ~label=?,
528
+ ~id,
529
+ ~name=?,
530
+ ~options: Toolkit__Ui_SelectPolyvariant.options<'value>,
531
+ ~encodeValueToString: 'value => string,
532
+ ~decodeValueFromString,
533
+ ~placeholder=?,
534
+ ~autoFocus=?,
535
+ ~disabled=?,
536
+ ~isOptional=?,
537
+ ~className=?,
538
+ ) => {
539
+ <Form.Field
540
+ field
541
+ render={({handleChange, error, value, validate, state}) => {
542
+ let isInvalid = error->Option.isSome
543
+
544
+ let onBlur = _ => {
545
+ switch state {
546
+ | Pristine => ()
547
+ | _ => validate()
548
+ }
549
+ }
550
+
551
+ <>
552
+ {switch label {
553
+ | None => React.null
554
+ | Some(label) =>
555
+ <Toolkit__Ui_Label
556
+ htmlFor=id
557
+ optionalMessage={isOptional->Option.getWithDefault(false)
558
+ ? <FormattedMessage defaultMessage="(Optionnel)" />
559
+ : React.null}>
560
+ label
561
+ </Toolkit__Ui_Label>
562
+ }}
563
+ <Toolkit__Ui_SelectPolyvariant
564
+ options
565
+ ?name
566
+ ?placeholder
567
+ ?autoFocus
568
+ ?className
569
+ isDisabled=?{disabled}
501
570
  onBlur
502
- defaultValue=?value
571
+ id
572
+ isInvalid
573
+ ?value
574
+ encodeValueToString
575
+ decodeValueFromString
576
+ onChange={selectedValue => {
577
+ handleChange(selectedValue)
578
+ }}
503
579
  />
504
580
  <ErrorMessage ?error />
505
581
  </>
@@ -509,7 +585,7 @@ module Make = (StateLenses: Config) => {
509
585
  }
510
586
 
511
587
  module SearchSelect = {
512
- open! BsReactSelect
588
+ open! ReactSelect
513
589
 
514
590
  @react.component
515
591
  let make = (
@@ -567,30 +643,18 @@ module Make = (StateLenses: Config) => {
567
643
  ~field,
568
644
  ~label=?,
569
645
  ~id,
570
- ~name=?,
571
- ~items,
572
- ~itemToLabel,
573
- ~itemToId,
574
- ~placeholder=?,
575
- ~hasPlaceholderOption=?,
576
- ~autoFocus=?,
646
+ ~options: Toolkit__Ui_MultiSelect.options,
647
+ ~placeholder,
577
648
  ~disabled=?,
578
649
  ~isOptional=?,
579
- ~className=?,
650
+ ~buttonClassName=?,
651
+ ~dropdownClassName=?,
652
+ ~itemClassName=?,
580
653
  ) => {
581
- let valueRef = React.useRef(None)
582
-
583
654
  <Form.Field
584
655
  field
585
656
  render={({handleChange, error, value, validate, state}) => {
586
- let isInvalid = error->Option.isSome
587
-
588
- let onChange = value => valueRef.current = Some(value)
589
-
590
- let onBlur = _ => {
591
- valueRef.current->Option.map(handleChange)->ignore
592
- valueRef.current = None
593
-
657
+ let onClose = _ => {
594
658
  switch state {
595
659
  | Pristine => ()
596
660
  | _ => validate()
@@ -609,21 +673,16 @@ module Make = (StateLenses: Config) => {
609
673
  label
610
674
  </Toolkit__Ui_Label>
611
675
  }}
612
- <Toolkit__Ui_ListboxInput.MultiSelect
613
- ?className
614
- items
615
- ?name
616
- itemToLabel
617
- itemToId
618
- id
619
- value
676
+ <Toolkit__Ui_MultiSelect
677
+ ?buttonClassName
678
+ ?dropdownClassName
679
+ ?itemClassName
680
+ options
681
+ defaultValue={value}
620
682
  ?disabled
621
- ?placeholder
622
- ?hasPlaceholderOption
623
- ?autoFocus
624
- isInvalid
625
- onChange
626
- onBlur
683
+ onChange={items => handleChange(items)}
684
+ onClose
685
+ placeholder
627
686
  />
628
687
  <ErrorMessage ?error />
629
688
  </>
@@ -133,7 +133,7 @@ let useClipboard = (~onCopyNotificationMessage: option<string>=?, value: string)
133
133
  Toolkit__Ui_Snackbar.show(~title=message, ~variant=#success, ())->ignore
134
134
  )
135
135
 
136
- let didCopy = BsCopyToClipboard.copy(value)
136
+ let didCopy = CopyToClipboard.copy(value)
137
137
  setHasCopied(_ => didCopy)
138
138
  }, [value])
139
139
 
@@ -84,7 +84,7 @@ module Make = (Config: IntlConfig) => {
84
84
 
85
85
  let getDateFnsLocale = locale =>
86
86
  switch locale {
87
- | #fr => BsDateFns.frLocale
87
+ | #fr => DateFns.frLocale
88
88
  }
89
89
 
90
90
  module Provider = {
@@ -25,7 +25,7 @@ module Make: (Config: IntlConfig) =>
25
25
  let useIntl: unit => ReactIntl.Intl.t
26
26
  let useCurrentLocale: unit => availableLanguages
27
27
  let setCurrentLocale: availableLanguages => unit
28
- let getDateFnsLocale: availableLanguages => BsDateFns.dateFnsLocale
28
+ let getDateFnsLocale: availableLanguages => DateFns.dateFnsLocale
29
29
 
30
30
  module Provider: {
31
31
  @react.component
@@ -1,4 +1,4 @@
1
- open BsSentryReactNative
1
+ open SentryReactNative
2
2
 
3
3
  @val external isDev: bool = "__DEV__"
4
4
 
@@ -19,12 +19,6 @@ module Make = (Config: RouterConfig) => {
19
19
  })
20
20
 
21
21
  module RouterContextProvider = {
22
- let makeProps = (~value: contextState, ~children, ()) =>
23
- {
24
- "value": value,
25
- "children": children,
26
- }
27
-
28
22
  let make = React.Context.provider(routerContext)
29
23
  }
30
24
 
@@ -18,8 +18,6 @@ module Alert = Toolkit__Ui_Alert
18
18
  module IconButton = Toolkit__Ui_IconButton
19
19
  module Tag = Toolkit__Ui_Tag
20
20
  module Select = Toolkit__Ui_Select
21
- module Listbox = Toolkit__Ui_Listbox
22
- module ListboxInput = Toolkit__Ui_ListboxInput
23
21
  module Table = Toolkit__Ui_Table
24
22
  module Reference = Toolkit__Ui_Reference
25
23
  module RichText = Toolkit__Ui_RichText
@@ -17,6 +17,8 @@ let make = (
17
17
  ~buttonSize: Toolkit__Ui_Button.size=#md,
18
18
  ~buttonVariant: Toolkit__Ui_Button.variant=#default,
19
19
  ~position=#bottom,
20
+ ~disabled: bool=?,
21
+ ~onClose: unit => unit=?,
20
22
  ) => {
21
23
  let dropDownRef = React.useRef(Js.Nullable.null)
22
24
  let buttonRef = React.useRef(Js.Nullable.null)
@@ -25,6 +27,7 @@ let make = (
25
27
 
26
28
  Toolkit__Hooks.useOnClickOutside(buttonRef, _ => {
27
29
  hide()
30
+ onClose->Option.forEach(fn => fn())
28
31
  })
29
32
 
30
33
  let (adjustmentStyle, setAdjustmentStyle) = React.useState(() => None)
@@ -40,14 +43,16 @@ let make = (
40
43
  | #left if left < 0. => setPosition(_ => #right)
41
44
  | #right if right < 0. => setPosition(_ => #left)
42
45
  | _ =>
43
- setAdjustmentStyle(_ => Some(
44
- ReactDOM.Style.make(
45
- ~marginLeft=left < 0. ? `${-.left->Js.Float.toString}px` : "",
46
- ~marginRight=right < 0. ? `${-.right->Js.Float.toString}px` : "",
47
- ~opacity="1",
48
- (),
46
+ setAdjustmentStyle(
47
+ _ => Some(
48
+ ReactDOM.Style.make(
49
+ ~marginLeft=left < 0. ? `${-.left->Js.Float.toString}px` : "",
50
+ ~marginRight=right < 0. ? `${-.right->Js.Float.toString}px` : "",
51
+ ~opacity="1",
52
+ (),
53
+ ),
49
54
  ),
50
- ))
55
+ )
51
56
  }
52
57
  })
53
58
  } else {
@@ -60,6 +65,7 @@ let make = (
60
65
  <Toolkit__Ui_Button
61
66
  variant=buttonVariant
62
67
  size=buttonSize
68
+ ?disabled
63
69
  type_="button"
64
70
  color=buttonColor
65
71
  buttonRef={ReactDOM.Ref.domRef(buttonRef)}
@@ -17,4 +17,6 @@ let make: (
17
17
  ~buttonSize: Toolkit__Ui_Button.size=?,
18
18
  ~buttonVariant: Toolkit__Ui_Button.variant=?,
19
19
  ~position: position=?,
20
+ ~disabled: bool=?,
21
+ ~onClose: unit => unit=?,
20
22
  ) => React.element
@@ -25,12 +25,7 @@ module NavOpenContext = {
25
25
  let context = React.createContext(false)
26
26
 
27
27
  module Provider = {
28
- let provider = React.Context.provider(context)
29
-
30
- @react.component
31
- let make = (~value, ~children) => {
32
- React.createElement(provider, {"value": value, "children": children})
33
- }
28
+ let make = React.Context.provider(context)
34
29
  }
35
30
  }
36
31
 
@@ -1,12 +1,14 @@
1
1
  type item = {
2
- itemLabel: React.element,
2
+ itemLabel?: React.element,
3
3
  label: string,
4
4
  value: string,
5
5
  }
6
6
 
7
+ type options = array<item>
8
+
7
9
  @react.component
8
10
  let make = (
9
- ~options: array<item>,
11
+ ~options: options,
10
12
  ~placeholder: React.element,
11
13
  ~buttonClassName="",
12
14
  ~dropdownClassName="",
@@ -15,6 +17,8 @@ let make = (
15
17
  ~allowFilter=true,
16
18
  ~defaultValue: array<item>=[],
17
19
  ~onChange: array<item> => unit,
20
+ ~disabled: bool=?,
21
+ ~onClose: unit => unit=?,
18
22
  ) => {
19
23
  let (selectedOptions, setSelectedOptions) = React.useState(() => defaultValue)
20
24
  let previousDefaultValue = Toolkit__Hooks.usePrevious(defaultValue)
@@ -49,7 +53,9 @@ let make = (
49
53
  }
50
54
 
51
55
  <Toolkit__Ui_Dropdown
56
+ ?disabled
52
57
  buttonClassName
58
+ ?onClose
53
59
  dropdownClassName
54
60
  position=#bottom
55
61
  label={switch selectedOptions {
@@ -109,7 +115,7 @@ let make = (
109
115
  ->Js.String2.includes(search)
110
116
  )
111
117
  ->Array.mapWithIndex((i, item) => {
112
- let {itemLabel, label, value} = item
118
+ let {label, value} = item
113
119
 
114
120
  <div
115
121
  key={`multiselectoption-${label}-${value}`}
@@ -144,7 +150,7 @@ let make = (
144
150
  })
145
151
  }
146
152
  }}>
147
- itemLabel
153
+ {item.itemLabel->Option.getWithDefault(label->React.string)}
148
154
  </Toolkit__Ui_Checkbox>
149
155
  </div>
150
156
  })
@@ -1,9 +1,11 @@
1
1
  type item = {
2
- itemLabel: React.element,
2
+ itemLabel?: React.element,
3
3
  label: string,
4
4
  value: string,
5
5
  }
6
6
 
7
+ type options = array<item>
8
+
7
9
  @react.component
8
10
  let make: (
9
11
  ~options: array<item>,
@@ -15,4 +17,6 @@ let make: (
15
17
  ~allowFilter: bool=?,
16
18
  ~defaultValue: array<item>=?,
17
19
  ~onChange: array<item> => unit,
20
+ ~disabled: bool=?,
21
+ ~onClose: unit => unit=?,
18
22
  ) => React.element
@@ -3,12 +3,12 @@ let make = (~onChange, ~value=?, ~id=?, ~disabled=false, ~isInvalid=false, ~clas
3
3
  <div className="relative">
4
4
  <input
5
5
  ?id
6
- value=?{value->Option.map(d => d->BsDateFns.formatWithPattern("yyyy-MM-dd"))}
6
+ value=?{value->Option.map(d => d->DateFns.formatWithPattern("yyyy-MM-dd"))}
7
7
  disabled
8
8
  ariaDisabled={disabled}
9
9
  onChange={event => {
10
10
  let value = ReactEvent.Form.target(event)["value"]
11
- onChange(Some(Js.Date.fromString(value))->Option.keep(BsDateFns.isValid))
11
+ onChange(Some(Js.Date.fromString(value))->Option.keep(DateFns.isValid))
12
12
  }}
13
13
  className={cx([
14
14
  "h-[38px] border rounded transition-all duration-150 ease-in-out py-2 pl-4 pr-8 appearance-none w-full bg-white text-gray-800 leading-tight focus:outline-none focus:shadow-none focus:border-info-500 disabled:bg-gray-200 disabled:text-gray-700 focus:z30 relative border-gray-300",
@@ -1,7 +1,16 @@
1
+ type selectOption = {
2
+ label: string,
3
+ value: string,
4
+ disabled?: bool,
5
+ }
6
+
7
+ type options = array<selectOption>
8
+
1
9
  @react.component
2
10
  let make = (
3
- ~options,
4
- ~onChange,
11
+ ~options: options,
12
+ ~onChange: string => unit,
13
+ ~onBlur=?,
5
14
  ~placeholder=?,
6
15
  ~defaultValue=?,
7
16
  ~isDisabled=?,
@@ -10,12 +19,17 @@ let make = (
10
19
  ~containerClassName="",
11
20
  ~id=?,
12
21
  ~value=?,
22
+ ~name=?,
23
+ ~autoFocus=?,
13
24
  ) =>
14
25
  <div className={cx(["relative", containerClassName])}>
15
26
  <select
16
27
  ?id
28
+ ?name
29
+ ?autoFocus
17
30
  disabled={isDisabled->Option.getWithDefault(false)}
18
31
  ariaDisabled={isDisabled->Option.getWithDefault(false)}
32
+ ?onBlur
19
33
  className={cx([
20
34
  "border rounded transition-all duration-150 ease-in-out py-2 pl-4 pr-8 appearance-none w-full bg-white text-gray-800 leading-tight focus:outline-none focus:shadow-none focus:border-info-500 disabled:bg-gray-200 disabled:text-gray-700 focus:z30 relative",
21
35
  switch isInvalid {
@@ -35,9 +49,12 @@ let make = (
35
49
  <option value=""> {placeholder->React.string} </option>
36
50
  )}
37
51
  {options
38
- ->Array.mapWithIndex((i, (label, value, enabled)) =>
39
- <option key={"select_option_" ++ i->Int.toString} value disabled={!enabled}>
40
- {label->React.string}
52
+ ->Array.mapWithIndex((i, option) =>
53
+ <option
54
+ key={"select_option_" ++ i->Int.toString}
55
+ value={option.value}
56
+ disabled=?{option.disabled}>
57
+ {option.label->React.string}
41
58
  </option>
42
59
  )
43
60
  ->React.array}
@@ -1,7 +1,16 @@
1
+ type selectOption = {
2
+ label: string,
3
+ value: string,
4
+ disabled?: bool,
5
+ }
6
+
7
+ type options = array<selectOption>
8
+
1
9
  @react.component
2
10
  let make: (
3
- ~options: array<(string, string, bool)>,
4
- ~onChange: 'value => unit,
11
+ ~options: options,
12
+ ~onChange: string => unit,
13
+ ~onBlur: ReactEvent.Focus.t => unit=?,
5
14
  ~placeholder: string=?,
6
15
  ~defaultValue: string=?,
7
16
  ~isDisabled: bool=?,
@@ -10,4 +19,6 @@ let make: (
10
19
  ~containerClassName: string=?,
11
20
  ~id: string=?,
12
21
  ~value: string=?,
22
+ ~name: string=?,
23
+ ~autoFocus: bool=?,
13
24
  ) => React.element
@@ -0,0 +1,45 @@
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
+ ~options: options<'value>,
12
+ ~onChange: option<'value> => unit,
13
+ ~encodeValueToString: 'value => string,
14
+ ~decodeValueFromString,
15
+ ~onBlur=?,
16
+ ~placeholder=?,
17
+ ~defaultValue=?,
18
+ ~isDisabled=?,
19
+ ~isInvalid=?,
20
+ ~className="",
21
+ ~containerClassName="",
22
+ ~id=?,
23
+ ~value=?,
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(encodeValueToString)}
38
+ defaultValue=?{defaultValue->Option.map(encodeValueToString)}
39
+ options={options->Array.map((option): Toolkit__Ui.Select.selectOption => {
40
+ label: option.label,
41
+ value: option.value->encodeValueToString,
42
+ disabled: ?option.disabled,
43
+ })}
44
+ onChange={value => value->decodeValueFromString->onChange}
45
+ />
@@ -27,12 +27,17 @@ module Pagination = {
27
27
  <div className="w-20">
28
28
  <Toolkit__Ui_Select
29
29
  value={table.state.pageSize->Int.toString}
30
- onChange={value => table.setPageSize(value)}
31
- options={[25, 50, 100]->Array.map(pageSize => (
32
- pageSize->Int.toString,
33
- pageSize->Int.toString,
34
- true,
35
- ))}
30
+ onChange={value => {
31
+ value
32
+ ->Int.fromString
33
+ ->Option.forEach(pageSize => {
34
+ table.setPageSize(pageSize)
35
+ })
36
+ }}
37
+ options={[25, 50, 100]->Array.map((pageSize): Toolkit__Ui_Select.selectOption => {
38
+ label: pageSize->Int.toString,
39
+ value: pageSize->Int.toString,
40
+ })}
36
41
  />
37
42
  </div>
38
43
  </div>