@colisweb/rescript-toolkit 5.44.5 → 5.46.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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@colisweb/rescript-toolkit",
3
- "version": "5.44.5",
3
+ "version": "5.46.0",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "clean": "rescript clean",
@@ -35,6 +35,8 @@
35
35
  "@greenlabs/ppx-spice": "0.2.1",
36
36
  "@headlessui/react": "2.2.1",
37
37
  "@headlessui/tailwindcss": "0.2.2",
38
+ "@radix-ui/react-context-menu": "^2.2.16",
39
+ "@radix-ui/react-dialog": "1.1.15",
38
40
  "@radix-ui/react-dropdown-menu": "2.1.7",
39
41
  "@radix-ui/react-popover": "1.1.7",
40
42
  "@radix-ui/react-scroll-area": "1.2.4",
@@ -73,6 +73,30 @@ module Date = {
73
73
  type t = @spice.codec(codec) date
74
74
  }
75
75
 
76
+ module LocalDate = {
77
+ type date = Js.Date.t
78
+
79
+ let encoder: Spice.encoder<date> = date =>
80
+ date->DateFns.formatWithPattern("yyyy-MM-dd")->Spice.stringToJson
81
+
82
+ let decoder: Spice.decoder<date> = json =>
83
+ switch Spice.stringFromJson(json) {
84
+ | Ok(v) =>
85
+ DateFns.parseWithPatternWithOptions(
86
+ v,
87
+ "yyyy-MM-dd",
88
+ Js.Date.make()->DateFns.startOfDay,
89
+ {locale: DateFns.frLocale},
90
+ )->Ok
91
+ | Error(_) as err => err
92
+ }
93
+
94
+ let codec: Spice.codec<date> = (encoder, decoder)
95
+
96
+ @spice
97
+ type t = @spice.codec(codec) date
98
+ }
99
+
76
100
  module LocalDatetime = {
77
101
  type date = Js.Date.t
78
102
 
@@ -237,7 +237,7 @@ module Make = (Config: RouterConfig) => {
237
237
  let make = () => <div className="border-b" />
238
238
  }
239
239
 
240
- let commonClassName = "flex items-center py-3 hover:bg-primary-100 focus:bg-primary-100 focus:shadow-none text-neutral-700 rounded relative font-semibold transition-all ease-linear duration-200"
240
+ let commonClassName = "flex items-center py-3 hover:bg-primary-100 focus:bg-primary-100 focus:shadow-none text-neutral-700 rounded relative font-semibold transition-all ease-linear duration-200 overflow-hidden"
241
241
 
242
242
  module SingleLink = {
243
243
  @react.component
@@ -262,7 +262,7 @@ module Make = (Config: RouterConfig) => {
262
262
  className={cx([
263
263
  commonClassName,
264
264
  "py-3 sidenav-link",
265
- isSubLink ? "ml-3" : "",
265
+ isSubLink ? "group-hover:ml-3" : "",
266
266
  containerClassName,
267
267
  ])}>
268
268
  <span className="overflow-hidden flex">
@@ -272,21 +272,13 @@ module Make = (Config: RouterConfig) => {
272
272
  <span
273
273
  className={cx([
274
274
  "transition-all duration-200 ease-in-out absolute ml-12 w-40 transform top-1/2 -translate-y-1/2",
275
- isNavOpen ? "pl-1 opacity-100 delay-75" : "opacity-0 invisible",
276
- isSubLink ? "text-sm" : "",
275
+ "lg:opacity-0 group-hover:opacity-100 group-hover:delay-100",
276
+ // isNavOpen ? "pl-1 opacity-100 delay-75" : "opacity-0 invisible",
277
+ isSubLink ? "text-sm focus:bg-primary-200" : "",
277
278
  labelClassName,
278
279
  ])}>
279
280
  label
280
281
  </span>
281
- {isNavOpen
282
- ? React.null
283
- : <div
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
- ])}>
288
- label
289
- </div>}
290
282
  </span>
291
283
  </a>
292
284
  | App(config) =>
@@ -298,12 +290,15 @@ module Make = (Config: RouterConfig) => {
298
290
  route
299
291
  className={cx([
300
292
  commonClassName,
301
- isSubLink ? "ml-3" : "",
302
293
  config.icon->Option.isNone ? "py-5" : "",
303
294
  "sidenav-link",
304
295
  containerClassName,
296
+ isActive && isSubLink && !disabledActiveLink
297
+ ? "bg-primary-100/50 text-neutral-700"
298
+ : "",
305
299
  isActive && !disabledActiveLink ? "bg-primary-100/75 text-neutral-700" : "",
306
300
  isActive && !disabledActiveLink ? activeClassName : "",
301
+ isSubLink ? "group-hover:ml-3" : "",
307
302
  ])}
308
303
  activeClassName={cx([
309
304
  disabledActiveLink ? "" : "bg-primary-100/75 text-neutral-700",
@@ -317,21 +312,13 @@ module Make = (Config: RouterConfig) => {
317
312
  <span
318
313
  className={cx([
319
314
  "transition-all duration-200 ease-in-out absolute ml-12 w-40 transform top-1/2 -translate-y-1/2",
320
- isNavOpen ? "pl-1 opacity-100 delay-75" : "opacity-0 invisible",
315
+ "lg:opacity-0 group-hover:opacity-100 group-hover:delay-100",
316
+ // isNavOpen ? "pl-1 opacity-100 delay-75" : "opacity-0 invisible",
321
317
  isSubLink ? "text-sm" : "",
322
318
  labelClassName,
323
319
  ])}>
324
320
  label
325
321
  </span>
326
- {isNavOpen
327
- ? React.null
328
- : <div
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
- ])}>
333
- label
334
- </div>}
335
322
  </span>
336
323
  </Link>
337
324
  }
@@ -366,7 +353,6 @@ module Make = (Config: RouterConfig) => {
366
353
  ~links: array<link>,
367
354
  ~isNavOpen: bool,
368
355
  ~onLinkClick=() => (),
369
- ~openMenu,
370
356
  ~iconClassName="",
371
357
  ~labelClassName="",
372
358
  ) => {
@@ -403,7 +389,6 @@ module Make = (Config: RouterConfig) => {
403
389
  <React.Fragment>
404
390
  <button
405
391
  onClick={_ => {
406
- openMenu()
407
392
  toggle()
408
393
  }}
409
394
  className={cx([
@@ -411,19 +396,22 @@ module Make = (Config: RouterConfig) => {
411
396
  "flex items-center w-full sidenav-link",
412
397
  hasActiveSubRoute || relativeRoute->Option.isSome ? "bg-primary-100/75" : "",
413
398
  ])}>
414
- <span
415
- className={cx(["mr-2 text-neutral-800", isNavOpen ? "pl-2" : "px-2", iconClassName])}>
399
+ <span className={cx(["mr-2 text-neutral-800 px-2", iconClassName])}>
416
400
  groupInfo.icon
417
401
  </span>
418
402
  <span
419
403
  className={cx([
420
404
  "transition-all duration-200 ease-in-out absolute ml-12 w-40 transform top-1/2 -translate-y-1/2 text-left",
421
- isNavOpen ? "pl-1 opacity-100 delay-75" : "opacity-0 invisible",
405
+ "lg:opacity-0 group-hover:opacity-100 group-hover:delay-100",
422
406
  labelClassName,
423
407
  ])}>
424
408
  groupInfo.label
425
409
  </span>
426
- <span className={cx(["absolute right-0 mr-2", isNavOpen ? "opacity-100" : "opacity-0"])}>
410
+ <span
411
+ className={cx([
412
+ "absolute right-0 mr-2 group-hover:opacity-100 delay-100",
413
+ isNavOpen ? "opacity-100" : "opacity-0",
414
+ ])}>
427
415
  <ReactIcons.MdKeyboardArrowRight
428
416
  size=24
429
417
  className={cx([
@@ -432,12 +420,6 @@ module Make = (Config: RouterConfig) => {
432
420
  ])}
433
421
  />
434
422
  </span>
435
- {isNavOpen
436
- ? React.null
437
- : <div
438
- className="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">
439
- groupInfo.label
440
- </div>}
441
423
  </button>
442
424
  <div
443
425
  className={cx([
@@ -23,6 +23,8 @@ module.exports = {
23
23
  },
24
24
  animation: {
25
25
  backforth: "backforth 2s ease-in-out infinite",
26
+ overlayShow: "overlayShow 200ms cubic-bezier(0.16, 1, 0.3, 1)",
27
+ contentShow: "contentShow 300ms cubic-bezier(0.16, 1, 0.3, 1)",
26
28
  },
27
29
  keyframes: {
28
30
  backforth: {
@@ -30,6 +32,17 @@ module.exports = {
30
32
  "50%": { left: "100%" },
31
33
  "100%": { left: "0px" },
32
34
  },
35
+ overlayShow: {
36
+ from: { opacity: "0" },
37
+ to: { opacity: "1" },
38
+ },
39
+ contentShow: {
40
+ from: {
41
+ opacity: "0",
42
+ transform: "scale(0.95)",
43
+ },
44
+ to: { opacity: "1", transform: "scale(1)" },
45
+ },
33
46
  },
34
47
  },
35
48
  screens: {
@@ -8,38 +8,23 @@ type itemContent = {
8
8
  ...DropdownMenu.Item.options,
9
9
  ...item,
10
10
  }
11
+ type checkboxItemContent = {
12
+ ...DropdownMenu.CheckboxItem.options,
13
+ ...item,
14
+ }
11
15
  type subTrigger = {...DropdownMenu.SubTrigger.options, ...item}
12
16
 
13
- type content =
17
+ type rec content =
14
18
  | Item(itemContent)
19
+ | CheckboxItem(checkboxItemContent)
15
20
  | Separator
16
21
  | Label(React.element)
17
- | SubItems(subTrigger, array<itemContent>)
22
+ | SubItems(subTrigger, array<content>)
18
23
 
19
24
  %%private(let renderRightSlot = rightSlot => <div className="RightSlot"> rightSlot </div>)
20
25
 
21
- @react.component
22
- let make = (
23
- ~trigger,
24
- ~triggerOptions: option<DropdownMenu.Trigger.options>=?,
25
- ~rootOptions: option<DropdownMenu.Root.options>=?,
26
- ~contentOptions: option<DropdownMenu.Content.options>=?,
27
- ~content: array<content>,
28
- ) => {
29
- <DropdownMenu.Root {...(rootOptions->Option.getWithDefault({})->Obj.magic)}>
30
- <DropdownMenu.Trigger {...(triggerOptions->Option.getWithDefault({})->Obj.magic)}>
31
- trigger
32
- </DropdownMenu.Trigger>
33
- <DropdownMenu.Portal>
34
- <DropdownMenu.Content
35
- {...(contentOptions->Option.getWithDefault({})->Obj.magic)}
36
- className="DropdownMenuContent"
37
- sideOffset={contentOptions
38
- ->Option.flatMap(v => v.sideOffset)
39
- ->Option.getWithDefault(5)}>
40
- {content
41
- ->Array.mapWithIndex((i, content) => {
42
- switch content {
26
+
27
+ let rec renderContent = (content, i) => switch content {
43
28
  | Label(element) =>
44
29
  <DropdownMenu.Label
45
30
  key={i->Int.toString ++ "dropdown-menu-item"} className="DropdownMenuLabel">
@@ -58,6 +43,21 @@ let make = (
58
43
  {item.label}
59
44
  {item.rightSlot->Option.mapWithDefault(React.null, renderRightSlot)}
60
45
  </DropdownMenu.Item>
46
+ | CheckboxItem(item) =>
47
+ <DropdownMenu.CheckboxItem
48
+ key={i->Int.toString ++ "dropdown-menu-item"}
49
+ className="DropdownMenuCheckboxItem"
50
+ checked={item.checked}
51
+ disabled=?{item.disabled}
52
+ textValue=?{item.textValue}
53
+ onCheckedChange={item.onCheckedChange}
54
+ onSelect=?{item.onSelect}>
55
+ <DropdownMenu.ItemIndicator className="DropdownMenuItemIndicator">
56
+ <ReactIcons.FaCheck size=8 />
57
+ </DropdownMenu.ItemIndicator>
58
+ {item.label}
59
+ {item.rightSlot->Option.mapWithDefault(React.null, renderRightSlot)}
60
+ </DropdownMenu.CheckboxItem>
61
61
 
62
62
  | SubItems(item, subContent) =>
63
63
  <DropdownMenu.Sub key={i->Int.toString ++ "dropdown-menu-item"}>
@@ -70,20 +70,36 @@ let make = (
70
70
  className="DropdownMenuSubContent" sideOffset={2} alignOffset={-5}>
71
71
  {subContent
72
72
  ->Array.mapWithIndex((j, item) => {
73
- <DropdownMenu.Item
74
- key={i->Int.toString ++ j->Int.toString ++ "dropdown-menu-item"}
75
- disabled=?{item.disabled}
76
- onSelect=?{item.onSelect}
77
- className="DropdownMenuItem">
78
- {item.label}
79
- {item.rightSlot->Option.mapWithDefault(React.null, renderRightSlot)}
80
- </DropdownMenu.Item>
73
+ renderContent(item,j)
81
74
  })
82
75
  ->React.array}
83
76
  </DropdownMenu.SubContent>
84
77
  </DropdownMenu.Portal>
85
78
  </DropdownMenu.Sub>
86
79
  }
80
+
81
+ @react.component
82
+ let make = (
83
+ ~trigger,
84
+ ~triggerOptions: option<DropdownMenu.Trigger.options>=?,
85
+ ~rootOptions: option<DropdownMenu.Root.options>=?,
86
+ ~contentOptions: option<DropdownMenu.Content.options>=?,
87
+ ~content: array<content>,
88
+ ) => {
89
+ <DropdownMenu.Root {...(rootOptions->Option.getWithDefault({})->Obj.magic)}>
90
+ <DropdownMenu.Trigger {...(triggerOptions->Option.getWithDefault({})->Obj.magic)}>
91
+ trigger
92
+ </DropdownMenu.Trigger>
93
+ <DropdownMenu.Portal>
94
+ <DropdownMenu.Content
95
+ {...(contentOptions->Option.getWithDefault({})->Obj.magic)}
96
+ className="DropdownMenuContent"
97
+ sideOffset={contentOptions
98
+ ->Option.flatMap(v => v.sideOffset)
99
+ ->Option.getWithDefault(5)}>
100
+ {content
101
+ ->Array.mapWithIndex((i, content) => {
102
+ renderContent(content,i)
87
103
  })
88
104
  ->React.array}
89
105
  <DropdownMenu.Arrow className="DropdownMenuArrow" />
@@ -39,7 +39,8 @@ module App = {
39
39
  className="bg-white h-16 border-b flex items-center px-1 justify-between fixed top-0 left-0 w-full z-40 print:hidden">
40
40
  <div className="flex items-center px-1 gap-1">
41
41
  <button
42
- onClick=toggleMenu className="text-neutral-800 hover:bg-neutral-300 rounded-full p-2">
42
+ onClick=toggleMenu
43
+ className="text-neutral-800 hover:bg-neutral-300 rounded-full p-2 block lg:hidden">
43
44
  <ReactIcons.MdMenu size=32 />
44
45
  </button>
45
46
  <a
@@ -52,7 +53,7 @@ module App = {
52
53
  <img
53
54
  src={logoSrc->Option.getWithDefault("/assets/logo.svg")}
54
55
  alt="Colisweb"
55
- className="w-16 ml-4"
56
+ className="w-16"
56
57
  />
57
58
  </a>
58
59
  {environment->Option.mapWithDefault(React.null, environment => {
@@ -112,8 +113,8 @@ module App = {
112
113
  <React.Fragment>
113
114
  <nav
114
115
  className={cx([
115
- "sidenav",
116
- "lg:flex border-r px-2 py-3 fixed flex-col bg-white justify-between transition-all duration-300 ease-in-out z-40 print:hidden",
116
+ "sidenav group",
117
+ "lg:flex border-r px-2 py-3 fixed flex-col hover:w-64 bg-white justify-between transition-all duration-300 ease-in-out z-40 print:hidden hover:overflow-y-auto",
117
118
  isNavOpen ? "w-64 overflow-y-auto" : "w-16 hidden sidenav--closed",
118
119
  ])}>
119
120
  {children({onLinkClick, isNavOpen, openMenu})}
@@ -121,7 +122,7 @@ module App = {
121
122
  <div className={!isNavOpen ? "overflow-hidden" : ""}>
122
123
  <div
123
124
  className={cx([
124
- "flex flex-col justify-end transition-all duration-300 ease-in-out w-[14.75rem]",
125
+ "flex flex-col group-hover:opacity-100 justify-end transition-all duration-300 ease-in-out w-[14.75rem]",
125
126
  isNavOpen ? "opacity-100" : "opacity-0",
126
127
  ])}>
127
128
  content
@@ -153,23 +154,12 @@ module App = {
153
154
  ~logoSrc=?,
154
155
  ~environment=?,
155
156
  ) => {
156
- let {isLg} = Toolkit__Hooks.useMediaQuery()
157
- let (isNavOpen, setOpen) = React.useState(() =>
158
- Browser.LocalStorage.getItem(localStorageNavKey)
159
- ->Js.Nullable.toOption
160
- ->Option.flatMap(value => value->bool_of_string_opt)
161
- ->Option.flatMap(isOpen => isLg ? Some(isOpen) : None)
162
- ->Option.getWithDefault(false)
163
- )
157
+ let (isNavOpen, setOpen) = React.useState(() => false)
164
158
 
165
159
  let toggleMenu = React.useCallback(_ =>
166
160
  setOpen(value => {
167
161
  let newValue = !value
168
162
 
169
- Browser.LocalStorage.setItem(
170
- localStorageNavKey,
171
- newValue->string_of_bool->Js.Nullable.return,
172
- )
173
163
  newValue
174
164
  })
175
165
  , [])
@@ -187,8 +177,8 @@ module App = {
187
177
  <main
188
178
  className={cx([
189
179
  className,
190
- "flex-initial w-full transition-all duration-300 ease-in-out mt-16 z-20 print:mt-0 print:!pl-0",
191
- isNavOpen ? "navOpen lg:pl-64" : "lg:pl-16",
180
+ "flex-initial w-full lg:pl-16 transition-all duration-300 ease-in-out mt-16 z-20 print:mt-0 print:!pl-0",
181
+ isNavOpen ? "navOpen " : "",
192
182
  ])}>
193
183
  children
194
184
  </main>
@@ -118,3 +118,89 @@ let make = (
118
118
  </HeadlessUi.Dialog.Panel>
119
119
  </div>
120
120
  </HeadlessUi.Dialog>
121
+
122
+ module Radix = {
123
+ open Radix
124
+ @react.component
125
+ let make = (
126
+ ~isVisible,
127
+ ~title: option<React.element>=?,
128
+ ~body: React.element,
129
+ ~hide,
130
+ ~size=#md,
131
+ ~type_=#default,
132
+ ~footer=?,
133
+ ~ariaLabel="",
134
+ ~icon: option<module(ReactIcons.Icon)>=?,
135
+ ) => {
136
+ // let (isOpen, setIsOpen) = React.useState(() => isVisible)
137
+ <Dialog.Root
138
+ \"open"=isVisible
139
+ onOpenChange={isOpen => {
140
+ if !isOpen {
141
+ hide()
142
+ }
143
+ }}>
144
+ <Dialog.Portal>
145
+ <Dialog.Overlay
146
+ className="z-40 fixed inset-0 bg-black/30 data-[state=open]:animate-overlayShow"
147
+ />
148
+ <div
149
+ className="z-50 fixed inset-0 overflow-y-auto flex min-h-full items-start justify-center p-4">
150
+ <Dialog.Content
151
+ className={cx([
152
+ "bg-white pb-5 shadow-lg w-full mt-[10vh] data-[state=open]:animate-contentShow",
153
+ modalStyle(~type_),
154
+ ])}
155
+ style={ReactDOMStyle.make(
156
+ ~maxWidth={
157
+ let value = switch size {
158
+ | #xs => 480
159
+ | #sm => 600
160
+ | #md => 768
161
+ | #lg => 900
162
+ | #custom(value) => value
163
+ }
164
+ `${value->Int.toString}px`
165
+ },
166
+ (),
167
+ )}>
168
+ <header
169
+ className={cx([
170
+ "flex items-center justify-between mb-4 pl-5 pr-3 pt-2 pb-1",
171
+ headerStyle(~type_),
172
+ ])}>
173
+ {title->Option.mapWithDefault(React.null, title =>
174
+ <Dialog.Title
175
+ className={cx([
176
+ "text-2xl pb-1 inline-flex items-center gap-2 font-display",
177
+ titleStyle(~type_),
178
+ ])}>
179
+ {icon->Option.mapWithDefault(React.null, icon => {
180
+ let module(Icon) = icon
181
+
182
+ <Icon />
183
+ })}
184
+ title
185
+ </Dialog.Title>
186
+ )}
187
+ <button
188
+ onClick={_ => hide()}
189
+ className={cx([
190
+ title->Option.isSome ? "ml-4" : "ml-auto",
191
+ "p-1 rounded-full modal-close-button",
192
+ closeIconStyle(~type_),
193
+ ])}>
194
+ <ReactIcons.MdClose size=28 />
195
+ </button>
196
+ </header>
197
+ <div className="px-1 sm:px-2 md:px-5"> body </div>
198
+ {footer->Option.mapWithDefault(React.null, footer =>
199
+ <div className="flex flex-row justify-end mt-6 pr-4"> footer </div>
200
+ )}
201
+ </Dialog.Content>
202
+ </div>
203
+ </Dialog.Portal>
204
+ </Dialog.Root>
205
+ }
206
+ }
@@ -14,3 +14,18 @@ let make: (
14
14
  ~ariaLabel: string=?,
15
15
  ~icon: module(ReactIcons.Icon)=?,
16
16
  ) => React.element
17
+
18
+ module Radix: {
19
+ @react.component
20
+ let make: (
21
+ ~isVisible: bool,
22
+ ~title: React.element=?,
23
+ ~body: React.element,
24
+ ~hide: unit => unit,
25
+ ~size: size=?, // default: `md
26
+ ~type_: style=?, // default: `default
27
+ ~footer: React.element=?,
28
+ ~ariaLabel: string=?,
29
+ ~icon: module(ReactIcons.Icon)=?,
30
+ ) => React.element
31
+ }
@@ -1,6 +1,14 @@
1
1
  @react.component
2
- let make = (~onChange, ~value=?, ~id=?, ~disabled=false, ~isInvalid=false, ~className="") =>
3
- <div className="relative">
2
+ let make = (
3
+ ~onChange,
4
+ ~value=?,
5
+ ~id=?,
6
+ ~disabled=false,
7
+ ~isInvalid=false,
8
+ ~className="",
9
+ ~containerClassName="",
10
+ ) =>
11
+ <div className={cx(["relative", containerClassName])}>
4
12
  <input
5
13
  ?id
6
14
  value=?{value->Option.map(d => d->DateFns.formatWithPattern("yyyy-MM-dd"))}
@@ -6,4 +6,5 @@ let make: (
6
6
  ~disabled: bool=?,
7
7
  ~isInvalid: bool=?,
8
8
  ~className: string=?,
9
+ ~containerClassName: string=?,
9
10
  ) => React.element
@@ -49,6 +49,16 @@ external isWithinInterval: (Js.Date.t, intervalObject) => bool = "isWithinInterv
49
49
 
50
50
  // parse
51
51
 
52
+ type parseOptions = {locale?: dateFnsLocale}
53
+
54
+ @module("date-fns")
55
+ external parse: string => Js.Date.t = "parse"
56
+ @module("date-fns")
57
+ external parseWithPattern: (string, string) => Js.Date.t = "parse"
58
+ @module("date-fns")
59
+ external parseWithPatternWithOptions: (string, string, Js.Date.t, parseOptions) => Js.Date.t =
60
+ "parse"
61
+
52
62
  @module("date-fns")
53
63
  external parseISO: string => Js.Date.t = "parseISO"
54
64
 
@@ -137,6 +147,21 @@ external isSameMonth: (Js.Date.t, Js.Date.t) => bool = "isSameMonth"
137
147
  @module("date-fns")
138
148
  external isFirstDayOfMonth: Js.Date.t => bool = "isFirstDayOfMonth"
139
149
 
150
+ @module("date-fns")
151
+ external isMonday: Js.Date.t => bool = "isMonday"
152
+ @module("date-fns")
153
+ external isTuesday: Js.Date.t => bool = "isTuesday"
154
+ @module("date-fns")
155
+ external isWednesday: Js.Date.t => bool = "isWednesday"
156
+ @module("date-fns")
157
+ external isThursday: Js.Date.t => bool = "isThursday"
158
+ @module("date-fns")
159
+ external isFriday: Js.Date.t => bool = "isFriday"
160
+ @module("date-fns")
161
+ external isSaturday: Js.Date.t => bool = "isSaturday"
162
+ @module("date-fns")
163
+ external isSunday: Js.Date.t => bool = "isSunday"
164
+
140
165
  // other
141
166
 
142
167
  @module("date-fns")
@@ -149,9 +174,6 @@ external getDay: Js.Date.t => int = "getDay"
149
174
  @module("date-fns")
150
175
  external getHours: Js.Date.t => int = "getHours"
151
176
 
152
- @module("date-fns")
153
- external parse: string => Js.Date.t = "parse"
154
-
155
177
  @module("date-fns")
156
178
  external nextTuesday: Js.Date.t => Js.Date.t = "nextTuesday"
157
179
  @module("date-fns")
@@ -166,19 +188,9 @@ external nextSaturday: Js.Date.t => Js.Date.t = "nextSaturday"
166
188
  external nextSunday: Js.Date.t => Js.Date.t = "nextSunday"
167
189
 
168
190
  @module("date-fns")
169
- external isMonday: Js.Date.t => bool = "isMonday"
170
- @module("date-fns")
171
- external isTuesday: Js.Date.t => bool = "isTuesday"
172
- @module("date-fns")
173
- external isWednesday: Js.Date.t => bool = "isWednesday"
174
- @module("date-fns")
175
- external isThursday: Js.Date.t => bool = "isThursday"
176
- @module("date-fns")
177
- external isFriday: Js.Date.t => bool = "isFriday"
178
- @module("date-fns")
179
- external isSaturday: Js.Date.t => bool = "isSaturday"
180
- @module("date-fns")
181
- external isSunday: Js.Date.t => bool = "isSunday"
191
+ external minutesToHours: int => int = "minutesToHours"
182
192
 
183
193
  @module("date-fns")
184
- external minutesToHours: int => int = "minutesToHours"
194
+ external max: array<Js.Date.t> => Js.Date.t = "max"
195
+ @module("date-fns")
196
+ external min: array<Js.Date.t> => Js.Date.t = "min"
@@ -164,7 +164,7 @@ module DropdownMenu = {
164
164
  external make: React.component<props> = "Root"
165
165
  }
166
166
  module Trigger = {
167
- type options = {asChild?: bool}
167
+ type options = {asChild?: bool, disabled?: bool}
168
168
  type props = {...options, children: React.element}
169
169
  @module("@radix-ui/react-dropdown-menu")
170
170
  external make: React.component<props> = "Trigger"
@@ -262,10 +262,10 @@ module DropdownMenu = {
262
262
  module CheckboxItem = {
263
263
  type options = {
264
264
  className?: string,
265
- checked?: bool,
265
+ checked: bool,
266
266
  disabled?: bool,
267
267
  textValue?: bool,
268
- onCheckedChange?: bool => unit,
268
+ onCheckedChange: bool => unit,
269
269
  onSelect?: ReactEvent.Mouse.t => unit,
270
270
  }
271
271
 
@@ -471,3 +471,143 @@ module Toast = {
471
471
  external make: React.component<props> = "Close"
472
472
  }
473
473
  }
474
+
475
+ module Dialog = {
476
+ module Root = {
477
+ type options = {
478
+ defaultOpen?: bool,
479
+ \"open": bool,
480
+ onOpenChange?: bool => unit,
481
+ modal?: bool,
482
+ }
483
+ type props = {
484
+ ...options,
485
+ children: React.element,
486
+ }
487
+ @module("@radix-ui/react-dialog")
488
+ external make: React.component<props> = "Root"
489
+ }
490
+ module Trigger = {
491
+ type props = {children: React.element, asChild?: bool}
492
+ @module("@radix-ui/react-dialog")
493
+ external make: React.component<props> = "Trigger"
494
+ }
495
+
496
+ module Portal = {
497
+ @module("@radix-ui/react-dialog") @react.component
498
+ external make: (
499
+ ~children: React.element,
500
+ ~forceMount: bool=?,
501
+ ~className: string=?,
502
+ ) => React.element = "Portal"
503
+ }
504
+ module Overlay = {
505
+ @module("@radix-ui/react-dialog") @react.component
506
+ external make: (
507
+ ~children: React.element=?,
508
+ ~className: string=?,
509
+ ~asChild: bool=?,
510
+ ~forceMount: bool=?,
511
+ ) => React.element = "Overlay"
512
+ }
513
+ module Content = {
514
+ type align =
515
+ | @as("center") Center
516
+ | @as("start") Start
517
+ | @as("end") End
518
+
519
+ type side =
520
+ | @as("top") Top
521
+ | @as("right") Right
522
+ | @as("bottom") Bottom
523
+ | @as("left") Left
524
+
525
+ type options = {
526
+ asChild?: bool,
527
+ forceMount?: bool,
528
+ onOpenAutoFocus?: ReactEvent.Focus.t => unit,
529
+ onCloseAutoFocus?: ReactEvent.Focus.t => unit,
530
+ onEscapeKeyDown?: ReactEvent.Keyboard.t => unit,
531
+ onPointerDownOutside?: ReactEvent.Mouse.t => unit,
532
+ onInteractOutside?: ReactEvent.Mouse.t => unit,
533
+ className?: string,
534
+ style?: ReactDOMStyle.t,
535
+ }
536
+
537
+ type props = {
538
+ ...options,
539
+ children: React.element,
540
+ }
541
+ @module("@radix-ui/react-dialog")
542
+ external make: React.component<props> = "Content"
543
+ }
544
+ module Close = {
545
+ type props = {className?: string, children?: React.element, asChild?: bool}
546
+ @module("@radix-ui/react-dialog")
547
+ external make: React.component<props> = "Close"
548
+ }
549
+ module Title = {
550
+ type props = {className?: string, asChild?: bool, children?: React.element}
551
+ @module("@radix-ui/react-dialog")
552
+ external make: React.component<props> = "Title"
553
+ }
554
+ }
555
+
556
+ // module ContextMenu = {
557
+ // module Root = {
558
+ // type options = {onOpenChange?: bool => unit, modal?: bool}
559
+ // type props = {
560
+ // ...options,
561
+ // children: React.element,
562
+ // }
563
+ // @module("@radix-ui/react-context-menu")
564
+ // external make: React.component<props> = "Root"
565
+ // }
566
+
567
+ // module Trigger = {
568
+ // type props = {children: React.element, disabled?: bool, asChild?: bool, className?: string}
569
+ // @module("@radix-ui/react-context-menu")
570
+ // external make: React.component<props> = "Trigger"
571
+ // }
572
+
573
+ // module Portal = {
574
+ // @module("@radix-ui/react-context-menu") @react.component
575
+ // external make: (~children: React.element) => React.element = "Portal"
576
+ // }
577
+ // module Content = {
578
+ // type options = {alignOffset?: int, sideOffset?: int, align?: string}
579
+
580
+ // type props = {
581
+ // ...options,
582
+ // className?: string,
583
+ // children: React.element,
584
+ // }
585
+ // @module("@radix-ui/react-context-menu")
586
+ // external make: React.component<props> = "Content"
587
+
588
+ // let className = "z-50 min-w-[220px] bg-white rounded-md overflow-hidden p-[5px] shadow-lg"
589
+ // }
590
+ // module Arrow = {
591
+ // type props = {className?: string, width?: int, height?: int}
592
+ // @module("@radix-ui/react-context-menu")
593
+ // external make: React.component<props> = "Arrow"
594
+ // }
595
+ // module Label = {
596
+ // type props = {className?: string, width?: int, height?: int}
597
+ // @module("@radix-ui/react-context-menu")
598
+ // external make: React.component<props> = "Label"
599
+ // }
600
+ // module Item = {
601
+ // type props = {
602
+ // className?: string,
603
+ // disabled?: bool,
604
+ // onSelect?: ReactEvent.Mouse.t => unit,
605
+ // textValue: string,
606
+ // children: React.element,
607
+ // }
608
+ // @module("@radix-ui/react-context-menu")
609
+ // external make: React.component<props> = "Item"
610
+
611
+ // let className = "text-sm leading-none text-neutral-700 rounded-[3px] flex items-center h-[25px] py-[5px] relative pl-[25px] select-none outline-none data-[disabled]:text-neutral-900 data-[disabled]:pointer-events-none data-[highlighted]:text-neutral-500 data-[highlighted]:bg-neutral-100"
612
+ // }
613
+ // }
@@ -68,3 +68,16 @@ type scrollCoords = {
68
68
 
69
69
  @module("react-use")
70
70
  external useWindowScroll: unit => scrollCoords = "useWindowScroll"
71
+
72
+ type measure = {
73
+ x: int,
74
+ y: int,
75
+ width: int,
76
+ height: int,
77
+ top: int,
78
+ right: int,
79
+ bottom: int,
80
+ left: int,
81
+ }
82
+ @module("react-use")
83
+ external useMeasure: unit => (React.ref<Js.Nullable.t<Dom.element>>, measure) = "useMeasure"
@@ -1,184 +0,0 @@
1
- type coreRowModel
2
- type sortedRowModel
3
- type filteredRowModel
4
- type paginationRowModel
5
-
6
- @module("@tanstack/react-table")
7
- external getCoreRowModel: unit => coreRowModel = "getCoreRowModel"
8
- @module("@tanstack/react-table")
9
- external getSortedRowModel: unit => sortedRowModel = "getSortedRowModel"
10
- @module("@tanstack/react-table")
11
- external getFilteredRowModel: unit => filteredRowModel = "getFilteredRowModel"
12
- @module("@tanstack/react-table")
13
- external getPaginationRowModel: unit => paginationRowModel = "getPaginationRowModel"
14
-
15
- type paginationState = {
16
- pageIndex: int,
17
- pageSize: int,
18
- }
19
-
20
- type rowSelectionState = Js.Dict.t<bool>
21
- type filterState = {id: string, value: unknown}
22
- type sortingState = {id: string, desc: bool}
23
-
24
- @unboxed type sortState = Bool(bool) | SortOrder(string)
25
-
26
- type tableState = {
27
- pagination: paginationState,
28
- rowSelection: rowSelectionState,
29
- columnFilters?: array<filterState>,
30
- sorting?: array<sortingState>,
31
- }
32
- type tableInitialState = {
33
- pagination?: paginationState,
34
- rowSelection?: rowSelectionState,
35
- columnFilters?: array<filterState>,
36
- sorting?: array<sortingState>,
37
- }
38
-
39
- module TableAPI = {
40
- type t = {initialState: tableInitialState}
41
- }
42
-
43
- module ColumnDef = {
44
- type tableContext = {
45
- getIsAllRowsSelected: unit => bool,
46
- getIsSomeRowsSelected: unit => bool,
47
- getToggleAllRowsSelectedHandler: (unit, ReactEvent.Form.t) => unit,
48
- }
49
-
50
- type rowOptions = {
51
- getIsSelected: unit => bool,
52
- getCanSelect: unit => bool,
53
- getIsSomeSelected: unit => bool,
54
- getToggleSelectedHandler: (unit, ReactEvent.Form.t) => unit,
55
- }
56
-
57
- type cellOptions<'columnData> = {
58
- getValue: unit => 'columnData,
59
- row: rowOptions,
60
- }
61
-
62
- type columnMeta<'filterVariant> = {filterVariant?: 'filterVariant}
63
- type filterFnVariant = | @as("equals") Equals
64
- type t<'tableData, 'filterVariant>
65
- @obj
66
- external make: (
67
- ~id: string=?,
68
- ~accessorFn: 'tableData => 'columnData,
69
- ~header: 'columnData => React.element=?,
70
- ~footer: unit => React.element=?,
71
- ~cell: cellOptions<'columnData> => React.element,
72
- ~meta: columnMeta<'filterVariant>=?,
73
- ~enableResizing: int=?,
74
- ~maxSize: int=?,
75
- ~minSize: int=?,
76
- ~size: int=?,
77
- ~enableSorting: bool=?,
78
- ~filterFn: filterFnVariant=?,
79
- unit,
80
- ) => t<'tableData, 'filterVariant> = ""
81
- }
82
-
83
- module Header = {
84
- type t
85
- type tableContext = {setColumnFilters: (array<filterState> => array<filterState>) => unit}
86
- type context = {table: tableContext}
87
-
88
- @module("@tanstack/react-table")
89
- external flexRender: (t, context) => React.element = "flexRender"
90
- }
91
-
92
- module Cell = {
93
- type t
94
- type context
95
-
96
- @module("@tanstack/react-table")
97
- external flexRender: (t, context) => React.element = "flexRender"
98
- }
99
-
100
- type rec rowModel<'filterVariant> = {rows: array<row<'filterVariant>>}
101
- and row<'filterVariant> = {
102
- getVisibleCells: unit => array<rowModelCell<'filterVariant>>,
103
- id: string,
104
- }
105
- and rowModelCell<'filterVariant> = {
106
- id: string,
107
- isPlaceholder: bool,
108
- column: 'filterValue. parentColumn<'filterValue, 'filterVariant>,
109
- getContext: unit => Cell.context,
110
- }
111
-
112
- and parentColumn<'filterValue, 'filterVariant> = {
113
- columnDef: parentColumnDef<'filterVariant>,
114
- getFilterValue: unit => 'filterValue,
115
- setFilterValue: 'filterValue => unit,
116
- getCanSort: unit => bool,
117
- getIsSorted: unit => sortState,
118
- getToggleSortingHandler: 'a. (. unit) => 'a => unit,
119
- }
120
- and parentColumnDef<'filterVariant> = {
121
- header: Header.t,
122
- cell: Cell.t,
123
- meta?: ColumnDef.columnMeta<'filterVariant>,
124
- }
125
-
126
- type rec headerGroup<'filterVariant> = {headers: array<header<'filterVariant>>, id: string}
127
- and header<'filterVariant> = {
128
- isPlaceholder: bool,
129
- column: 'a. parentColumn<'a, 'filterVariant>,
130
- colSpan: int,
131
- getSize: unit => int,
132
- getContext: unit => Header.context,
133
- id: string,
134
- }
135
-
136
- type columnInstance = {setFilterValue: 'a. 'a => unit}
137
-
138
- type rec tableInstance<'tableData, 'filterVariant> = {
139
- getHeaderGroups: unit => array<headerGroup<'filterVariant>>,
140
- getRowModel: unit => rowModel<'filterVariant>,
141
- getFooterGroups: unit => array<headerGroup<'filterVariant>>,
142
- getPageCount: unit => int,
143
- getCanPreviousPage: unit => bool,
144
- getCanNextPage: unit => bool,
145
- getIsAllRowsSelected: unit => bool,
146
- getIsSomeRowsSelected: unit => bool,
147
- getToggleAllRowsSelectedHandler: (unit, ReactEvent.Form.t) => unit,
148
- setPageIndex: (int => int) => unit,
149
- setPageSize: int => unit,
150
- previousPage: unit => unit,
151
- nextPage: unit => unit,
152
- getState: unit => tableState,
153
- setOptions: (
154
- tableOptions<'tableData, 'filterVariant> => tableOptions<'tableData, 'filterVariant>
155
- ) => unit,
156
- setColumnFilters: (array<filterState> => array<filterState>) => unit,
157
- getColumn: string => option<columnInstance>,
158
- }
159
- and tableOptions<'tableData, 'filterVariant> = {
160
- data: array<'tableData>,
161
- columns: array<ColumnDef.t<'tableData, 'filterVariant>>,
162
- getCoreRowModel: coreRowModel,
163
- getSortedRowModel?: sortedRowModel,
164
- onSortingChange?: (array<sortingState> => array<sortingState>) => unit,
165
- getFilteredRowModel?: filteredRowModel,
166
- getPaginationRowModel?: paginationRowModel,
167
- onPaginationChange?: (paginationState => paginationState) => paginationState,
168
- onRowSelectionChange?: (rowSelectionState => rowSelectionState) => unit,
169
- pageCount?: int,
170
- initialState?: tableInitialState,
171
- state?: tableInitialState,
172
- manualPagination?: bool,
173
- manualSorting?: bool,
174
- manualFiltering?: bool,
175
- enableRowSelection?: bool,
176
- enableMultiRowSelection?: bool,
177
- debugTable?: bool,
178
- }
179
-
180
- @module("@tanstack/react-table")
181
- external useReactTable: tableOptions<'tableData, 'filterVariant> => tableInstance<
182
- 'tableData,
183
- 'filterVariant,
184
- > = "useReactTable"