@colisweb/rescript-toolkit 5.44.5 → 5.45.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.45.0",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "clean": "rescript clean",
@@ -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([
@@ -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>
@@ -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
 
@@ -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"