@colisweb/rescript-toolkit 2.13.6 → 2.16.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": "2.13.6",
3
+ "version": "2.16.0",
4
4
  "scripts": {
5
5
  "clean": "rescript clean",
6
6
  "build": "rescript build",
@@ -121,27 +121,27 @@ module type EnumConfig = {
121
121
  }
122
122
 
123
123
  module Enum = (Config: EnumConfig) => {
124
- type enum = Config.enum
124
+ %%private(
125
+ let encoder = value => value->Config.enumToJs->Decco.stringToJson
125
126
 
126
- let encoder = value => value->Config.enumToJs->Decco.stringToJson
127
-
128
- let decoder = json =>
129
- switch Decco.stringFromJson(json) {
130
- | Ok(value) =>
131
- switch Config.enumFromJs(value) {
132
- | None => Decco.error(~path="", "Invalid enum " ++ value, json)
133
- | Some(value) => Ok(value)
127
+ let decoder = json =>
128
+ switch Decco.stringFromJson(json) {
129
+ | Ok(value) =>
130
+ switch Config.enumFromJs(value) {
131
+ | None => Decco.error(~path="", "Invalid enum " ++ value, json)
132
+ | Some(value) => Ok(value)
133
+ }
134
+ | Error(_) as error => error
134
135
  }
135
- | Error(_) as error => error
136
- }
137
136
 
138
- let codec = (encoder, decoder)
137
+ let codec = (encoder, decoder)
138
+ )
139
139
 
140
140
  let toString = v => v->Config.enumToJs
141
141
  let fromString = v => v->Config.enumFromJs
142
142
 
143
143
  @decco
144
- type t = @decco.codec(codec) enum
144
+ type t = @decco.codec(codec) Config.enum
145
145
  }
146
146
 
147
147
  module Option = {
@@ -161,337 +161,219 @@ module Option = {
161
161
  }
162
162
 
163
163
  module UnitMeasure = {
164
- module Dimension = {
165
- module WithUnit = {
166
- let encoder: Decco.encoder<Toolkit__Utils_UnitMeasure.Dimension.t> = value =>
167
- value->Toolkit__Utils_UnitMeasure.Dimension.toString()->Decco.stringToJson
164
+ module type MakeConfig = {
165
+ type t
166
+ let toString: t => string
167
+ let toValue: t => float
168
+ let display: (t, ~digits: int=?, unit) => string
168
169
 
169
- let decoder: Decco.decoder<Toolkit__Utils_UnitMeasure.Dimension.t> = json =>
170
- switch Decco.stringFromJson(json) {
171
- | Belt.Result.Ok(v) =>
172
- let valueUnitArray = v->Js.String2.split(" ")
173
- switch (
174
- valueUnitArray[0]->Belt.Option.flatMap(Belt.Float.fromString),
175
- valueUnitArray[1],
176
- ) {
177
- | (Some(v), Some("mm")) => #mm(v)->Ok
178
- | (Some(v), Some("cm")) => #cm(v)->Ok
179
- | (Some(v), Some("dm")) => #dm(v)->Ok
180
- | (Some(v), Some("km")) => #km(v)->Ok
181
- | (None, _) => Decco.error("unhandled no value", json)
182
- | (_, None) => Decco.error("unhandled no unit", json)
183
- | (_, Some(_)) => Decco.error("unhandled dimension unit", json)
184
- }
185
- | Belt.Result.Error(_) as err => err
186
- }
170
+ let wrapValue: float => t
171
+ }
187
172
 
188
- let codec: Decco.codec<Toolkit__Utils_UnitMeasure.Dimension.t> = (encoder, decoder)
189
- let toValue = Toolkit__Utils_UnitMeasure.Dimension.toValue
190
- let toString = Toolkit__Utils_UnitMeasure.Dimension.toString
173
+ module Make = (C: MakeConfig) => {
174
+ type dimension = C.t
191
175
 
192
- @decco
193
- type t = @decco.codec(codec) Toolkit__Utils_UnitMeasure.Dimension.t
194
- }
176
+ let encoder: Decco.encoder<C.t> = value => value->C.toString->Decco.stringToJson
195
177
 
196
- module type DimensionConfig = {
197
- let convert: float => Toolkit__Utils_UnitMeasure.Dimension.t
198
- }
199
- module Make = (C: DimensionConfig) => {
200
- type dimension = Toolkit__Utils_UnitMeasure.Dimension.t
178
+ let decoder: Decco.decoder<C.t> = json =>
179
+ switch Decco.floatFromJson(json) {
180
+ | Ok(v) => v->C.wrapValue->Ok
181
+ | Error(_) as err => err
182
+ }
201
183
 
202
- let encoder: Decco.encoder<Toolkit__Utils_UnitMeasure.Dimension.t> = value =>
203
- value->Toolkit__Utils_UnitMeasure.Dimension.toString()->Decco.stringToJson
184
+ let codec: Decco.codec<dimension> = (encoder, decoder)
204
185
 
205
- let decoder: Decco.decoder<Toolkit__Utils_UnitMeasure.Dimension.t> = json =>
206
- switch Decco.floatFromJson(json) {
207
- | Ok(v) => v->C.convert->Ok
186
+ let toValue = C.toValue
187
+ let display = C.display
188
+ let toString = C.toString
208
189
 
209
- | Error(_) as err => err
210
- }
190
+ @decco
191
+ type t = @decco.codec(codec) C.t
192
+ }
211
193
 
212
- let codec: Decco.codec<dimension> = (encoder, decoder)
194
+ module type MakeWithUnitConfig = {
195
+ type t
196
+ let toString: t => string
197
+ let toValue: t => float
198
+ let display: (t, ~digits: int=?, unit) => string
213
199
 
214
- @decco
215
- type t = @decco.codec(codec) Toolkit__Utils_UnitMeasure.Dimension.t
216
- }
200
+ type unitEnum
201
+ let unitEnum_decode: Js.Json.t => result<unitEnum, Decco.decodeError>
202
+ let unitEnum_encode: unitEnum => Js.Json.t
217
203
 
218
- module Mm = Make({
219
- let convert = Toolkit__Utils_UnitMeasure.Dimension.makeMm
220
- })
221
- module Cm = Make({
222
- let convert = Toolkit__Utils_UnitMeasure.Dimension.makeCm
223
- })
224
- module Dm = Make({
225
- let convert = Toolkit__Utils_UnitMeasure.Dimension.makeDm
226
- })
227
- module Km = Make({
228
- let convert = Toolkit__Utils_UnitMeasure.Dimension.makeKm
229
- })
230
- }
204
+ let wrapValue: (unitEnum, float) => t
231
205
 
232
- module Weight = {
233
- module WithUnit = {
234
- let encoder: Decco.encoder<Toolkit__Utils_UnitMeasure.Weight.t> = value =>
235
- value->Toolkit__Utils_UnitMeasure.Weight.display()->Decco.stringToJson
206
+ let errorPrefix: string
207
+ }
236
208
 
237
- let decoder: Decco.decoder<Toolkit__Utils_UnitMeasure.Weight.t> = json =>
238
- switch Decco.stringFromJson(json) {
239
- | Ok(v) =>
240
- let valueUnitArray = v->Js.String2.split(" ")
241
- switch (
242
- valueUnitArray[0]->Belt.Option.flatMap(Belt.Float.fromString),
243
- valueUnitArray[1],
244
- ) {
245
- | (Some(v), Some("g")) => #g(v)->Ok
246
- | (Some(v), Some("kg")) => #kg(v)->Ok
247
- | (None, _) => Decco.error("unhandled no value", json)
248
- | (_, None) => Decco.error("unhandled no unit", json)
249
- | (_, Some(_)) => Decco.error("unhandled weight unit", json)
250
- }
209
+ module MakeWithUnit = (Config: MakeWithUnitConfig) => {
210
+ let decodeFromString = (string: string) => {
211
+ // match a positive int or float followed by it's unit (capturing int/float in group1 and unit in group2)
212
+ let regexp = %re("/^(\d+(?:\.\d*)?)\s*(\D*)$/")
251
213
 
252
- | Error(_) as err => err
253
- }
214
+ // regexpCaptures: [match , captureGroup1, captureGroup2]
215
+ let regexpCaptures =
216
+ Js.Re.exec_(regexp, string)->Belt.Option.map(r =>
217
+ r->Js.Re.captures->Array.map(Js.Nullable.toOption)
218
+ )
254
219
 
255
- let codec: Decco.codec<Toolkit__Utils_UnitMeasure.Weight.t> = (encoder, decoder)
220
+ let jsonString = string->Js.Json.string
256
221
 
257
- @decco
258
- type t = @decco.codec(codec) Toolkit__Utils_UnitMeasure.Weight.t
259
- }
222
+ let errorPrefix = Config.errorPrefix
260
223
 
261
- module type WeightConfig = {
262
- let convert: float => Toolkit__Utils_UnitMeasure.Weight.t
224
+ switch regexpCaptures {
225
+ | None => Decco.error(`${errorPrefix} unhandled format`, jsonString)
226
+ | Some([None, _value, _unit]) => Decco.error(`${errorPrefix} unhandled format`, jsonString)
227
+ | Some([_match, _value, None]) => Decco.error(`${errorPrefix} unhandled no unit`, jsonString)
228
+ | Some([_match, None, _unit]) => Decco.error(`${errorPrefix} unhandled no value`, jsonString)
229
+ | Some([Some(_match), Some(value), Some(unit)]) => {
230
+ let value = value->Js.Float.fromString
231
+ switch unit->Js.Json.string->Config.unitEnum_decode {
232
+ | Ok(unit) => Config.wrapValue(unit, value)->Ok
233
+ | Error(_) => Decco.error(`${errorPrefix} unhandled unit '${unit}'`, jsonString)
234
+ }
235
+ }
236
+ | Some(_) => Decco.error(`${errorPrefix} regex capture group error`, jsonString)
237
+ }
263
238
  }
264
239
 
265
- module Make = (C: WeightConfig) => {
266
- type weight = Toolkit__Utils_UnitMeasure.Weight.t
267
-
268
- let encoder: Decco.encoder<Toolkit__Utils_UnitMeasure.Weight.t> = value =>
269
- value->Toolkit__Utils_UnitMeasure.Weight.display()->Decco.stringToJson
270
-
271
- let decoder: Decco.decoder<Toolkit__Utils_UnitMeasure.Weight.t> = json =>
272
- switch Decco.floatFromJson(json) {
273
- | Ok(v) => v->C.convert->Ok
240
+ %%private(
241
+ let encoder: Decco.encoder<Config.t> = value => value->Config.toString->Decco.stringToJson
242
+ let decoder: Decco.decoder<Config.t> = json =>
243
+ switch Decco.stringFromJson(json) {
244
+ | Ok(v) => v->decodeFromString
274
245
  | Error(_) as err => err
275
246
  }
247
+ let codec: Decco.codec<Config.t> = (encoder, decoder)
248
+ )
276
249
 
277
- let codec: Decco.codec<weight> = (encoder, decoder)
250
+ let toValue = Config.toValue
251
+ let toString = Config.toString
252
+ let display = Config.display
278
253
 
279
- let toValue = Toolkit__Utils_UnitMeasure.Weight.toValue
280
- let display = Toolkit__Utils_UnitMeasure.Weight.display
254
+ @decco
255
+ type t = @decco.codec(codec) Config.t
256
+ }
281
257
 
282
- @decco
283
- type t = @decco.codec(codec) Toolkit__Utils_UnitMeasure.Weight.t
284
- }
258
+ module Dimension = {
259
+ module Config = Toolkit__Utils_UnitMeasure.Dimension
285
260
 
286
- module G = Make({
287
- let convert = Toolkit__Utils_UnitMeasure.Weight.makeG
261
+ module WithUnit = MakeWithUnit({
262
+ include Config
263
+ let errorPrefix = "Dimension with unit"
288
264
  })
289
- module Kg = Make({
290
- let convert = Toolkit__Utils_UnitMeasure.Weight.makeKg
265
+
266
+ module Mm = Make({
267
+ include Config
268
+ let wrapValue = Config.wrapValue(#mm)
269
+ })
270
+ module Cm = Make({
271
+ include Config
272
+ let wrapValue = Config.wrapValue(#cm)
273
+ })
274
+ module Dm = Make({
275
+ include Config
276
+ let wrapValue = Config.wrapValue(#dm)
277
+ })
278
+ module M = Make({
279
+ include Config
280
+ let wrapValue = Config.wrapValue(#m)
281
+ })
282
+ module Km = Make({
283
+ include Config
284
+ let wrapValue = Config.wrapValue(#km)
291
285
  })
292
286
  }
293
287
 
294
- module Time = {
295
- module WithUnit = {
296
- let encoder: Decco.encoder<Toolkit__Utils_UnitMeasure.Time.t> = value =>
297
- switch value {
298
- | #min(v) => Js.Json.string(v->Js.Float.toString ++ " min")
299
- | #h(v) => Js.Json.string(v->Js.Float.toString ++ " h")
300
- }
301
-
302
- let decoder: Decco.decoder<Toolkit__Utils_UnitMeasure.Time.t> = json =>
303
- switch Decco.stringFromJson(json) {
304
- | Ok(v) =>
305
- let valueUnitArray = v->Js.String2.split(" ")
306
- switch (
307
- valueUnitArray[0]->Belt.Option.flatMap(Belt.Float.fromString),
308
- valueUnitArray[1],
309
- ) {
310
- | (Some(v), Some("min")) => #min(v)->Ok
311
- | (Some(v), Some("h")) => #h(v)->Ok
312
- | (None, _) => Decco.error("unhandled no value", json)
313
- | (_, None) => Decco.error("unhandled no unit", json)
314
- | (_, Some(_)) => Decco.error("unhandled time unit", json)
315
- }
288
+ module Volume = {
289
+ module Config = Toolkit__Utils_UnitMeasure.Volume
316
290
 
317
- | Error(_) as err => err
318
- }
319
-
320
- let codec: Decco.codec<Toolkit__Utils_UnitMeasure.Time.t> = (encoder, decoder)
321
-
322
- @decco
323
- type t = @decco.codec(codec) Toolkit__Utils_UnitMeasure.Time.t
324
- }
325
-
326
- module type TimeConfig = {
327
- let convert: float => Toolkit__Utils_UnitMeasure.Time.t
328
- }
291
+ module WithUnit = MakeWithUnit({
292
+ include Config
293
+ let errorPrefix = "Volume with unit"
294
+ })
329
295
 
330
- module Make = (C: TimeConfig) => {
331
- type time = Toolkit__Utils_UnitMeasure.Time.t
296
+ module M3 = Make({
297
+ include Config
298
+ let wrapValue = Config.wrapValue(#m3)
299
+ })
300
+ }
332
301
 
333
- let encoder: Decco.encoder<Toolkit__Utils_UnitMeasure.Time.t> = value =>
334
- switch value {
335
- | #min(v) => Js.Json.string(v->Js.Float.toString ++ " min")
336
- | #h(v) => Js.Json.string(v->Js.Float.toString ++ " h")
337
- }
302
+ module Weight = {
303
+ module Config = Toolkit__Utils_UnitMeasure.Weight
338
304
 
339
- let decoder: Decco.decoder<Toolkit__Utils_UnitMeasure.Time.t> = json =>
340
- switch Decco.floatFromJson(json) {
341
- | Ok(v) => v->C.convert->Ok
342
- | Error(_) as err => err
343
- }
305
+ module WithUnit = MakeWithUnit({
306
+ include Config
307
+ let errorPrefix = "Weight with unit"
308
+ })
344
309
 
345
- let codec: Decco.codec<time> = (encoder, decoder)
310
+ module G = Make({
311
+ include Config
312
+ let wrapValue = Config.wrapValue(#g)
313
+ })
314
+ module Kg = Make({
315
+ include Config
316
+ let wrapValue = Config.wrapValue(#kg)
317
+ })
318
+ }
346
319
 
347
- let toValue = Toolkit__Utils_UnitMeasure.Time.toValue
348
- let display = Toolkit__Utils_UnitMeasure.Time.display
320
+ module Time = {
321
+ module Config = Toolkit__Utils_UnitMeasure.Time
349
322
 
350
- @decco
351
- type t = @decco.codec(codec) Toolkit__Utils_UnitMeasure.Time.t
352
- }
323
+ module WithUnit = MakeWithUnit({
324
+ include Config
325
+ let errorPrefix = "Time with unit"
326
+ })
353
327
 
354
328
  module Min = Make({
355
- let convert = Toolkit__Utils_UnitMeasure.Time.makeMin
329
+ include Config
330
+ let wrapValue = Config.wrapValue(#min)
356
331
  })
357
332
  module H = Make({
358
- let convert = Toolkit__Utils_UnitMeasure.Time.makeH
333
+ include Config
334
+ let wrapValue = Config.wrapValue(#h)
359
335
  })
360
336
  }
361
337
 
362
338
  module Currency = {
363
- module WithUnit = {
364
- let encoder: Decco.encoder<Toolkit__Utils_UnitMeasure.Currency.t> = value =>
365
- switch value {
366
- | #EUR(v) => Js.Json.string(v->Js.Float.toString ++ " EUR")
367
- }
368
-
369
- let decoder: Decco.decoder<Toolkit__Utils_UnitMeasure.Currency.t> = json =>
370
- switch Decco.stringFromJson(json) {
371
- | Ok(v) =>
372
- let valueUnitArray = v->Js.String2.split(" ")
373
- switch (
374
- valueUnitArray[0]->Belt.Option.flatMap(Belt.Float.fromString),
375
- valueUnitArray[1],
376
- ) {
377
- | (Some(v), Some("EUR")) => #EUR(v)->Ok
378
- | (None, _) => Decco.error("unhandled no value", json)
379
- | (_, None) => Decco.error("unhandled no unit", json)
380
- | (_, Some(_)) => Decco.error("unhandled currency unit", json)
381
- }
382
-
383
- | Error(_) as err => err
384
- }
339
+ module Config = Toolkit__Utils_UnitMeasure.Currency
385
340
 
386
- let codec: Decco.codec<Toolkit__Utils_UnitMeasure.Currency.t> = (encoder, decoder)
387
-
388
- @decco
389
- type t = @decco.codec(codec) Toolkit__Utils_UnitMeasure.Currency.t
390
- }
391
-
392
- module type CurrencyConfig = {
393
- let convert: float => Toolkit__Utils_UnitMeasure.Currency.t
394
- }
395
-
396
- module Make = (C: CurrencyConfig) => {
397
- type currency = Toolkit__Utils_UnitMeasure.Currency.t
398
-
399
- let encoder: Decco.encoder<Toolkit__Utils_UnitMeasure.Currency.t> = value =>
400
- switch value {
401
- | #EUR(v) => Js.Json.string(v->Js.Float.toString ++ " EUR")
402
- }
403
-
404
- let decoder: Decco.decoder<Toolkit__Utils_UnitMeasure.Currency.t> = json =>
405
- switch Decco.floatFromJson(json) {
406
- | Ok(v) => v->C.convert->Ok
407
- | Error(_) as err => err
408
- }
409
-
410
- let codec: Decco.codec<currency> = (encoder, decoder)
411
-
412
- let toValue = Toolkit__Utils_UnitMeasure.Currency.toValue
413
- let display = Toolkit__Utils_UnitMeasure.Currency.toString
414
-
415
- @decco
416
- type t = @decco.codec(codec) Toolkit__Utils_UnitMeasure.Currency.t
417
- }
341
+ module WithUnit = MakeWithUnit({
342
+ include Config
343
+ let errorPrefix = "Curency with unit"
344
+ })
418
345
 
419
346
  module EUR = Make({
420
- let convert = Toolkit__Utils_UnitMeasure.Currency.makeEUR
347
+ include Config
348
+ let wrapValue = Config.wrapValue(#EUR)
421
349
  })
422
350
  }
423
351
 
424
352
  module CompositeUnits = {
425
353
  module CurrencyPerDistance = {
426
- module WithUnit = {
427
- let encoder: Decco.encoder<
428
- Toolkit__Utils_UnitMeasure.CompositeUnits.CurrencyPerDistance.t,
429
- > = value =>
430
- switch value {
431
- | #EUR_km(v) => Js.Json.string(v->Js.Float.toString ++ " EUR/km")
432
- }
433
-
434
- let decoder: Decco.decoder<
435
- Toolkit__Utils_UnitMeasure.CompositeUnits.CurrencyPerDistance.t,
436
- > = json =>
437
- switch Decco.stringFromJson(json) {
438
- | Ok(v) =>
439
- let valueUnitArray = v->Js.String2.split(" ")
440
- switch (
441
- valueUnitArray[0]->Belt.Option.flatMap(Belt.Float.fromString),
442
- valueUnitArray[1],
443
- ) {
444
- | (Some(v), Some("EUR/km")) => #EUR_km(v)->Ok
445
- | (None, _) => Decco.error("unhandled no value", json)
446
- | (_, None) => Decco.error("unhandled no unit", json)
447
- | (_, Some(_)) => Decco.error("unhandled currencyPerDistance unit", json)
448
- }
449
-
450
- | Error(_) as err => err
451
- }
452
-
453
- let codec: Decco.codec<Toolkit__Utils_UnitMeasure.CompositeUnits.CurrencyPerDistance.t> = (
454
- encoder,
455
- decoder,
456
- )
354
+ module Config = Toolkit__Utils_UnitMeasure.CompositeUnits.CurrencyPerDistance
457
355
 
458
- @decco
459
- type t = @decco.codec(codec) Toolkit__Utils_UnitMeasure.CompositeUnits.CurrencyPerDistance.t
460
- }
461
-
462
- module type CurrencyPerDistanceConfig = {
463
- let convert: float => Toolkit__Utils_UnitMeasure.CompositeUnits.CurrencyPerDistance.t
464
- }
465
-
466
- module Make = (C: CurrencyPerDistanceConfig) => {
467
- type currencyPerDistance = Toolkit__Utils_UnitMeasure.CompositeUnits.CurrencyPerDistance.t
468
-
469
- let encoder: Decco.encoder<
470
- Toolkit__Utils_UnitMeasure.CompositeUnits.CurrencyPerDistance.t,
471
- > = value =>
472
- switch value {
473
- | #EUR_km(v) => Js.Json.string(v->Js.Float.toString ++ " EUR/km")
474
- }
475
-
476
- let decoder: Decco.decoder<
477
- Toolkit__Utils_UnitMeasure.CompositeUnits.CurrencyPerDistance.t,
478
- > = json =>
479
- switch Decco.floatFromJson(json) {
480
- | Ok(v) => v->C.convert->Ok
481
- | Error(_) as err => err
482
- }
483
-
484
- let codec: Decco.codec<currencyPerDistance> = (encoder, decoder)
356
+ module WithUnit = MakeWithUnit({
357
+ include Config
358
+ let errorPrefix = "Curency per distance with unit"
359
+ })
485
360
 
486
- let toValue = Toolkit__Utils_UnitMeasure.CompositeUnits.CurrencyPerDistance.toValue
487
- let display = Toolkit__Utils_UnitMeasure.CompositeUnits.CurrencyPerDistance.toString
361
+ module EUR_km = Make({
362
+ include Config
363
+ let wrapValue = Config.wrapValue(#EUR_km)
364
+ })
365
+ }
366
+ module CurrencyPerTime = {
367
+ module Config = Toolkit__Utils_UnitMeasure.CompositeUnits.CurrencyPerTime
488
368
 
489
- @decco
490
- type t = @decco.codec(codec) Toolkit__Utils_UnitMeasure.CompositeUnits.CurrencyPerDistance.t
491
- }
369
+ module WithUnit = MakeWithUnit({
370
+ include Config
371
+ let errorPrefix = "Curency per time with unit"
372
+ })
492
373
 
493
- module EUR_km = Make({
494
- let convert = Toolkit__Utils_UnitMeasure.CompositeUnits.CurrencyPerDistance.makeEUR_km
374
+ module EUR_h = Make({
375
+ include Config
376
+ let wrapValue = Config.wrapValue(#EUR_h)
495
377
  })
496
378
  }
497
379
  }
@@ -1,5 +1,11 @@
1
1
  type size = [#md | #lg]
2
-
2
+ type color = [
3
+ | #info
4
+ | #success
5
+ | #primary
6
+ | #neutral
7
+ | #danger
8
+ ]
3
9
  let getBulletSize = size =>
4
10
  switch size {
5
11
  | #md => "w-5 h-5"
@@ -14,8 +20,8 @@ let getLabelSize = size =>
14
20
 
15
21
  let getTranslateBySize = size =>
16
22
  switch size {
17
- | #md => "translate-x-5"
18
- | #lg => "translate-x-8"
23
+ | #md => "translate-x-6"
24
+ | #lg => "translate-x-9"
19
25
  }
20
26
 
21
27
  @react.component
@@ -33,6 +39,7 @@ let make = (
33
39
  ~checkedSwitchClassName="",
34
40
  ~disabledSwitchClassName="",
35
41
  ~switchRef: option<ReactDOM.domRef>=?,
42
+ ~color=#primary,
36
43
  ) => {
37
44
  let (isChecked, setIsChecked) = React.useState(() => checked->Option.getWithDefault(false))
38
45
 
@@ -46,9 +53,17 @@ let make = (
46
53
  ])}>
47
54
  <span
48
55
  className={cx([
49
- "flex items-center relative rounded-full py-1 cursor-pointer border transition-all",
56
+ "flex items-center relative rounded-full py-[2px] cursor-pointer border transition-all",
50
57
  getLabelSize(size),
51
- isChecked ? "bg-info-500" : "bg-gray-300",
58
+ isChecked
59
+ ? switch color {
60
+ | #info => "bg-info-500 border-info-500"
61
+ | #success => "bg-success-500 border-success-500"
62
+ | #primary => "bg-primary-700 border-primary-700"
63
+ | #neutral => "bg-neutral-700 border-neutral-700"
64
+ | #danger => "bg-danger-500 border-danger-500"
65
+ }
66
+ : "bg-gray-300",
52
67
  switchClassName,
53
68
  isChecked ? checkedSwitchClassName : "",
54
69
  disabled->Option.getWithDefault(false) ? disabledSwitchClassName : "",
@@ -1,4 +1,11 @@
1
1
  type size = [#md | #lg]
2
+ type color = [
3
+ | #info
4
+ | #success
5
+ | #primary
6
+ | #neutral
7
+ | #danger
8
+ ]
2
9
 
3
10
  @react.component
4
11
  let make: (
@@ -15,4 +22,5 @@ let make: (
15
22
  ~checkedSwitchClassName: string=?,
16
23
  ~disabledSwitchClassName: string=?,
17
24
  ~switchRef: ReactDOM.domRef=?,
25
+ ~color: color=?,
18
26
  ) => React.element
@@ -1 +1,2 @@
1
1
  module UnitMeasure = Toolkit__Utils_UnitMeasure
2
+ module Regex = Toolkit__Utils_Regex
@@ -0,0 +1,7 @@
1
+ let positiveIntRegex = %re("/^[0-9]+$/")
2
+ let positiveIntOrFloatRegex = %re("/^[0-9]+(?:\.?[0-9]+)?$/")
3
+
4
+ module Test = {
5
+ let isPositiveInt = Js.Re.test_(positiveIntRegex, _)
6
+ let isPositiveIntOrFloat = Js.Re.test_(positiveIntOrFloatRegex, _)
7
+ }
@@ -1,6 +1,49 @@
1
+ module type UnitConfig = {
2
+ type unitEnum
3
+ let unitEnumToJs: unitEnum => string
4
+ let unitEnumFromJs: string => option<unitEnum>
5
+ }
6
+
7
+ module Unit = (Config: UnitConfig) => {
8
+ %%private(
9
+ let encoder = value => value->Config.unitEnumToJs->Decco.stringToJson
10
+
11
+ let decoder = json =>
12
+ switch Decco.stringFromJson(json) {
13
+ | Ok(value) =>
14
+ switch Config.unitEnumFromJs(value) {
15
+ | None => Decco.error(~path="", "Invalid unitEnum " ++ value, json)
16
+ | Some(value) => Ok(value)
17
+ }
18
+ | Error(_) as error => error
19
+ }
20
+
21
+ let codec = (encoder, decoder)
22
+ )
23
+
24
+ @decco
25
+ type unitEnum = @decco.codec(codec) Config.unitEnum
26
+
27
+ let unitEnumToString = v => v->Config.unitEnumToJs
28
+ let unitEnumFromString = v => v->Config.unitEnumFromJs
29
+ }
30
+
1
31
  module Weight = {
32
+ include Unit({
33
+ @deriving(jsConverter)
34
+ type unitEnum = [#g | #kg]
35
+ })
36
+
37
+ @decco
2
38
  type t = [#g(float) | #kg(float)]
3
39
 
40
+ let wrapValue = (unit, value) => {
41
+ switch unit {
42
+ | #g => #g(value)
43
+ | #kg => #kg(value)
44
+ }
45
+ }
46
+
4
47
  let toValue = value =>
5
48
  switch value {
6
49
  | #g(v)
@@ -12,23 +55,40 @@ module Weight = {
12
55
  | #g(v) => v->Js.Float.toFixedWithPrecision(~digits) ++ " g"
13
56
  | #kg(v) => v->Js.Float.toFixedWithPrecision(~digits) ++ " kg"
14
57
  }
58
+ let toString = value =>
59
+ switch value {
60
+ | #g(v) => v->Float.toString ++ " g"
61
+ | #kg(v) => v->Float.toString ++ " kg"
62
+ }
15
63
 
16
64
  let makeG = (value: float) => #g(value)
17
65
  let makeKg = (value: float) => #kg(value)
18
66
  }
19
67
 
20
68
  module Time = {
69
+ include Unit({
70
+ @deriving(jsConverter)
71
+ type unitEnum = [#min | #h]
72
+ })
73
+
21
74
  type t = [#min(float) | #h(float)]
22
75
 
76
+ let wrapValue = (unit, value) => {
77
+ switch unit {
78
+ | #min => #min(value)
79
+ | #h => #h(value)
80
+ }
81
+ }
82
+
23
83
  let toValue = value =>
24
84
  switch value {
25
85
  | #min(v)
26
86
  | #h(v) => v
27
87
  }
28
88
 
29
- type separator = [#units | #colon]
30
- let display = (value, ~separator=#units, ()) => {
89
+ let display = (value, ~digits as _=2, ()) => {
31
90
  let _initialDate = Js.Date.make()
91
+
32
92
  let duration = switch value {
33
93
  | #min(v) =>
34
94
  BsDateFns.intervalToDuration(
@@ -43,32 +103,35 @@ module Time = {
43
103
  )
44
104
  }
45
105
 
46
- let mainSeparator = {
47
- switch separator {
48
- | #units => " h "
49
- | #colon => ":"
50
- }
51
- }
52
- let secondarySeparator = {
53
- switch separator {
54
- | #units => " min"
55
- | #colon => ""
56
- }
57
- }
58
-
59
106
  switch (duration.hours, duration.minutes) {
60
- | (Some(h), Some(min)) =>
61
- `${h->Int.toString}${mainSeparator}${min->Int.toString}${secondarySeparator}`
107
+ | (Some(h), Some(min)) if min->Int.toString->String.length === 1 =>
108
+ `${h->Int.toString} : 0${min->Int.toString}`
109
+ | (Some(h), Some(min)) => `${h->Int.toString} : ${min->Int.toString}`
62
110
  | (Some(h), _) => `${h->Int.toString} h`
63
111
  | (_, Some(min)) => `${min->Int.toString} min`
64
112
  | _ => ""
65
113
  }
66
114
  }
67
- let makeMin = (value: float) => #min(value)
68
- let makeH = (value: float) => #h(value)
115
+
116
+ let toString = value =>
117
+ switch value {
118
+ | #min(v) => v->Float.toString ++ " min"
119
+ | #h(v) => v->Float.toString ++ " h"
120
+ }
69
121
  }
70
122
 
71
123
  module Dimension = {
124
+ include Unit({
125
+ @deriving(jsConverter)
126
+ type unitEnum = [
127
+ | #mm
128
+ | #cm
129
+ | #dm
130
+ | #m
131
+ | #km
132
+ ]
133
+ })
134
+
72
135
  type t = [
73
136
  | #mm(float)
74
137
  | #cm(float)
@@ -77,6 +140,15 @@ module Dimension = {
77
140
  | #km(float)
78
141
  ]
79
142
 
143
+ let wrapValue = (unit: unitEnum, value: float): t =>
144
+ switch unit {
145
+ | #mm => #mm(value)
146
+ | #cm => #cm(value)
147
+ | #dm => #dm(value)
148
+ | #m => #m(value)
149
+ | #km => #km(value)
150
+ }
151
+
80
152
  let toValue = value =>
81
153
  switch value {
82
154
  | #mm(v)
@@ -86,7 +158,7 @@ module Dimension = {
86
158
  | #km(v) => v
87
159
  }
88
160
 
89
- let toString = (value, ~digits=2, ()) => {
161
+ let display = (value, ~digits=2, ()) => {
90
162
  open Js.Float
91
163
  switch value {
92
164
  | #mm(v) => v->toFixedWithPrecision(~digits) ++ " mm"
@@ -97,18 +169,70 @@ module Dimension = {
97
169
  }
98
170
  }
99
171
 
100
- let makeMm = (value: float) => #mm(value)
101
- let makeCm = (value: float) => #cm(value)
102
- let makeDm = (value: float) => #dm(value)
103
- let makeM = (value: float) => #m(value)
104
- let makeKm = (value: float) => #km(value)
172
+ let toString = value => {
173
+ switch value {
174
+ | #mm(v) => v->Float.toString ++ " mm"
175
+ | #cm(v) => v->Float.toString ++ " cm"
176
+ | #dm(v) => v->Float.toString ++ " dm"
177
+ | #m(v) => v->Float.toString ++ " m"
178
+ | #km(v) => v->Float.toString ++ " km"
179
+ }
180
+ }
181
+ }
182
+
183
+ module Volume = {
184
+ include Unit({
185
+ @deriving(jsConverter)
186
+ type unitEnum = [
187
+ | @as(`m³`) #m3
188
+ ]
189
+ })
190
+
191
+ type t = [
192
+ | #m3(float)
193
+ ]
194
+
195
+ let wrapValue = (unit: unitEnum, value: float): t =>
196
+ switch unit {
197
+ | #m3 => #m3(value)
198
+ }
199
+
200
+ let toValue = value =>
201
+ switch value {
202
+ | #m3(value) => value
203
+ }
204
+
205
+ let display = (value, ~digits=2, ()) => {
206
+ open Js.Float
207
+ switch value {
208
+ | #m3(v) => v->toFixedWithPrecision(~digits) ++ ` m³`
209
+ }
210
+ }
211
+
212
+ let toString = value => {
213
+ switch value {
214
+ | #m3(v) => v->Float.toString ++ ` m³`
215
+ }
216
+ }
105
217
  }
106
218
 
107
219
  module Currency = {
220
+ include Unit({
221
+ @deriving(jsConverter)
222
+ type unitEnum = [
223
+ | #EUR
224
+ ]
225
+ })
226
+
108
227
  type t = [
109
228
  | #EUR(float)
110
229
  ]
111
230
 
231
+ let wrapValue = (unit: unitEnum, value: float): t =>
232
+ switch unit {
233
+ | #EUR => #EUR(value)
234
+ }
235
+
112
236
  let toValue = value =>
113
237
  switch value {
114
238
  | #EUR(v) => v
@@ -120,15 +244,31 @@ module Currency = {
120
244
  }
121
245
  }
122
246
 
123
- let makeEUR = (value: float) => #EUR(value)
247
+ let display = (value, ~digits=2, ()) => {
248
+ switch value {
249
+ | #EUR(v) => v->Js.Float.toFixedWithPrecision(~digits) ++ " EUR"
250
+ }
251
+ }
124
252
  }
125
253
 
126
254
  module CompositeUnits = {
127
255
  module CurrencyPerDistance = {
256
+ include Unit({
257
+ @deriving(jsConverter)
258
+ type unitEnum = [
259
+ | @as("EUR/km") #EUR_km
260
+ ]
261
+ })
262
+
128
263
  type t = [
129
264
  | #EUR_km(float)
130
265
  ]
131
266
 
267
+ let wrapValue = (unit: unitEnum, value: float): t =>
268
+ switch unit {
269
+ | #EUR_km => #EUR_km(value)
270
+ }
271
+
132
272
  let toValue = value =>
133
273
  switch value {
134
274
  | #EUR_km(v) => v
@@ -140,6 +280,45 @@ module CompositeUnits = {
140
280
  }
141
281
  }
142
282
 
143
- let makeEUR_km = (value: float) => #EUR_km(value)
283
+ let display = (value, ~digits=2, ()) => {
284
+ switch value {
285
+ | #EUR_km(v) => v->Js.Float.toFixedWithPrecision(~digits) ++ " EUR/km"
286
+ }
287
+ }
288
+ }
289
+
290
+ module CurrencyPerTime = {
291
+ include Unit({
292
+ @deriving(jsConverter)
293
+ type unitEnum = [
294
+ | @as("EUR/h") #EUR_h
295
+ ]
296
+ })
297
+
298
+ type t = [
299
+ | #EUR_h(float)
300
+ ]
301
+
302
+ let wrapValue = (unit: unitEnum, value: float): t =>
303
+ switch unit {
304
+ | #EUR_h => #EUR_h(value)
305
+ }
306
+
307
+ let toValue = value =>
308
+ switch value {
309
+ | #EUR_h(v) => v
310
+ }
311
+
312
+ let toString = value => {
313
+ switch value {
314
+ | #EUR_h(v) => v->Float.toString ++ " EUR/h"
315
+ }
316
+ }
317
+
318
+ let display = (value, ~digits=2, ()) => {
319
+ switch value {
320
+ | #EUR_h(v) => v->Js.Float.toFixedWithPrecision(~digits) ++ " EUR/h"
321
+ }
322
+ }
144
323
  }
145
324
  }
@@ -127,3 +127,39 @@ external isFirstDayOfMonth: Js.Date.t => bool = "isFirstDayOfMonth"
127
127
 
128
128
  @module("date-fns")
129
129
  external getWeekNumber: (Js.Date.t, startOfWeekOptions) => int = "getWeek"
130
+
131
+ @module("date-fns")
132
+ external getDay: Js.Date.t => int = "getDay"
133
+ @module("date-fns")
134
+ external getHours: Js.Date.t => int = "getHours"
135
+
136
+ @module("date-fns")
137
+ external parse: string => Js.Date.t = "parse"
138
+
139
+ @module("date-fns")
140
+ external nextTuesday: Js.Date.t => Js.Date.t = "nextTuesday"
141
+ @module("date-fns")
142
+ external nextWednesday: Js.Date.t => Js.Date.t = "nextWednesday"
143
+ @module("date-fns")
144
+ external nextThursday: Js.Date.t => Js.Date.t = "nextThursday"
145
+ @module("date-fns")
146
+ external nextFriday: Js.Date.t => Js.Date.t = "nextFriday"
147
+ @module("date-fns")
148
+ external nextSaturday: Js.Date.t => Js.Date.t = "nextSaturday"
149
+ @module("date-fns")
150
+ external nextSunday: Js.Date.t => Js.Date.t = "nextSunday"
151
+
152
+ @module("date-fns")
153
+ external isMonday: Js.Date.t => bool = "isMonday"
154
+ @module("date-fns")
155
+ external isTuesday: Js.Date.t => bool = "isTuesday"
156
+ @module("date-fns")
157
+ external isWednesday: Js.Date.t => bool = "isWednesday"
158
+ @module("date-fns")
159
+ external isThursday: Js.Date.t => bool = "isThursday"
160
+ @module("date-fns")
161
+ external isFriday: Js.Date.t => bool = "isFriday"
162
+ @module("date-fns")
163
+ external isSaturday: Js.Date.t => bool = "isSaturday"
164
+ @module("date-fns")
165
+ external isSunday: Js.Date.t => bool = "isSunday"
@@ -0,0 +1,72 @@
1
+ type event<'a> = {
2
+ title: string,
3
+ start: Js.Date.t,
4
+ end: Js.Date.t,
5
+ resource: 'a,
6
+ }
7
+
8
+ type view = [
9
+ | #month
10
+ | #week
11
+ | #work_week
12
+ | #day
13
+ | #agenda
14
+ ]
15
+
16
+ type eventProp<'a> = {
17
+ resource: 'a,
18
+ start: Js.Date.t,
19
+ end: Js.Date.t,
20
+ isSelected: bool,
21
+ title: string,
22
+ }
23
+
24
+ type eventClassStyle
25
+
26
+ @obj
27
+ external makeEventClassStyle: (
28
+ ~className: string=?,
29
+ ~style: ReactDOM.Style.t=?,
30
+ unit,
31
+ ) => eventClassStyle = ""
32
+
33
+ type timeSlot = {
34
+ start: Js.Date.t,
35
+ end: Js.Date.t,
36
+ }
37
+
38
+ @module("react-big-calendar") @react.component
39
+ external make: (
40
+ ~localizer: 'a,
41
+ ~events: array<event<'b>>,
42
+ ~defaultView: view=?,
43
+ ~views: array<view>=?,
44
+ ~culture: string=?,
45
+ ~toolbar: bool=?,
46
+ ~selectable: bool=?,
47
+ ~timeslots: int=?,
48
+ ~min: Js.Date.t=?,
49
+ ~max: Js.Date.t=?,
50
+ ~step: int=?,
51
+ ~components: 'z=?,
52
+ ~eventPropGetter: eventProp<'b> => eventClassStyle=?,
53
+ ~messages: Js.t<'message>=?,
54
+ ~formats: Js.t<'formats>=?,
55
+ ~onSelectEvent: event<'b> => unit=?,
56
+ ~onView: view => unit=?,
57
+ ~onNavigate: Js.Date.t => unit=?,
58
+ ~onSelectSlot: timeSlot => unit=?,
59
+ ) => React.element = "Calendar"
60
+
61
+ type calendarLocalizer
62
+
63
+ @module("react-big-calendar")
64
+ external dateFnsLocalizer: 'a => calendarLocalizer = "dateFnsLocalizer"
65
+
66
+ module Constants = {
67
+ @module("react-big-calendar/lib/utils/constants") @scope("navigate")
68
+ external previous: string = "PREVIOUS"
69
+
70
+ @module("react-big-calendar/lib/utils/constants") @scope("navigate")
71
+ external next: string = "NEXT"
72
+ }