kmod-cli 1.0.10

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 (66) hide show
  1. package/README.md +53 -0
  2. package/bin/gen-components.js +68 -0
  3. package/bin/index.js +153 -0
  4. package/component-templates/components/access-denied.tsx +130 -0
  5. package/component-templates/components/breadcumb.tsx +42 -0
  6. package/component-templates/components/count-down.tsx +94 -0
  7. package/component-templates/components/count-input.tsx +221 -0
  8. package/component-templates/components/date-range-calendar/button.tsx +61 -0
  9. package/component-templates/components/date-range-calendar/calendar.tsx +132 -0
  10. package/component-templates/components/date-range-calendar/date-input.tsx +259 -0
  11. package/component-templates/components/date-range-calendar/date-range-picker.tsx +594 -0
  12. package/component-templates/components/date-range-calendar/label.tsx +31 -0
  13. package/component-templates/components/date-range-calendar/popover.tsx +32 -0
  14. package/component-templates/components/date-range-calendar/select.tsx +125 -0
  15. package/component-templates/components/date-range-calendar/switch.tsx +30 -0
  16. package/component-templates/components/datetime-picker/button.tsx +61 -0
  17. package/component-templates/components/datetime-picker/calendar.tsx +156 -0
  18. package/component-templates/components/datetime-picker/datetime-picker.tsx +75 -0
  19. package/component-templates/components/datetime-picker/input.tsx +20 -0
  20. package/component-templates/components/datetime-picker/label.tsx +18 -0
  21. package/component-templates/components/datetime-picker/period-input.tsx +62 -0
  22. package/component-templates/components/datetime-picker/popover.tsx +32 -0
  23. package/component-templates/components/datetime-picker/select.tsx +125 -0
  24. package/component-templates/components/datetime-picker/time-picker-input.tsx +131 -0
  25. package/component-templates/components/datetime-picker/time-picker-utils.tsx +204 -0
  26. package/component-templates/components/datetime-picker/time-picker.tsx +59 -0
  27. package/component-templates/components/gradient-outline.tsx +233 -0
  28. package/component-templates/components/gradient-svg.tsx +157 -0
  29. package/component-templates/components/grid-layout.tsx +69 -0
  30. package/component-templates/components/hydrate-guard.tsx +40 -0
  31. package/component-templates/components/image.tsx +92 -0
  32. package/component-templates/components/loader-slash-gradient.tsx +85 -0
  33. package/component-templates/components/masonry-gallery.tsx +221 -0
  34. package/component-templates/components/modal.tsx +110 -0
  35. package/component-templates/components/multi-select.tsx +447 -0
  36. package/component-templates/components/non-hydration.tsx +27 -0
  37. package/component-templates/components/portal.tsx +34 -0
  38. package/component-templates/components/segments-circle.tsx +235 -0
  39. package/component-templates/components/single-select.tsx +248 -0
  40. package/component-templates/components/stroke-circle.tsx +57 -0
  41. package/component-templates/components/table/column-table.tsx +15 -0
  42. package/component-templates/components/table/data-table.tsx +339 -0
  43. package/component-templates/components/table/readme.tsx +95 -0
  44. package/component-templates/components/table/table.tsx +60 -0
  45. package/component-templates/components/text-hover-effect.tsx +120 -0
  46. package/component-templates/components/timout-loader.tsx +52 -0
  47. package/component-templates/components/toast.tsx +994 -0
  48. package/component-templates/configs/config.ts +33 -0
  49. package/component-templates/configs/feature-config.tsx +432 -0
  50. package/component-templates/configs/keys.ts +7 -0
  51. package/component-templates/core/api-service.ts +202 -0
  52. package/component-templates/core/calculate.ts +18 -0
  53. package/component-templates/core/idb.ts +166 -0
  54. package/component-templates/core/storage.ts +213 -0
  55. package/component-templates/hooks/count-down.ts +38 -0
  56. package/component-templates/hooks/fade-on-scroll.ts +52 -0
  57. package/component-templates/hooks/safe-action.ts +59 -0
  58. package/component-templates/hooks/spam-guard.ts +31 -0
  59. package/component-templates/lib/utils.ts +6 -0
  60. package/component-templates/providers/feature-guard.tsx +432 -0
  61. package/component-templates/queries/query.tsx +775 -0
  62. package/component-templates/utils/colors/color-by-text.ts +307 -0
  63. package/component-templates/utils/colors/stripe-effect.ts +100 -0
  64. package/component-templates/utils/hash/hash-aes.ts +35 -0
  65. package/components.json +348 -0
  66. package/package.json +60 -0
@@ -0,0 +1,594 @@
1
+ /* eslint-disable max-lines */
2
+ 'use client'
3
+
4
+ import React, {
5
+ type FC,
6
+ JSX,
7
+ useEffect,
8
+ useRef,
9
+ useState,
10
+ } from 'react';
11
+
12
+ import {
13
+ CheckIcon,
14
+ ChevronDownIcon,
15
+ ChevronUpIcon,
16
+ } from '@radix-ui/react-icons';
17
+
18
+ import { cn } from '../../lib/utils';
19
+ import { Button } from './button';
20
+ import { Calendar } from './calendar';
21
+ import { DateInput } from './date-input';
22
+ import { Label } from './label';
23
+ import {
24
+ Popover,
25
+ PopoverContent,
26
+ PopoverTrigger,
27
+ } from './popover';
28
+ import {
29
+ Select,
30
+ SelectContent,
31
+ SelectItem,
32
+ SelectTrigger,
33
+ SelectValue,
34
+ } from './select';
35
+ import { Switch } from './switch';
36
+
37
+ export interface DateRangePickerProps {
38
+ /** Click handler for applying the updates from DateRangePicker. */
39
+ onUpdate?: (values: { range: DateRange, rangeCompare?: DateRange }) => void
40
+ /** Initial value for start date */
41
+ initialDateFrom?: Date | string
42
+ /** Initial value for end date */
43
+ initialDateTo?: Date | string
44
+ /** Initial value for start date for compare */
45
+ initialCompareFrom?: Date | string
46
+ /** Initial value for end date for compare */
47
+ initialCompareTo?: Date | string
48
+ /** Alignment of popover */
49
+ align?: 'start' | 'center' | 'end'
50
+ /** Option for locale */
51
+ locale?: string
52
+ /** Option for showing compare feature */
53
+ showCompare?: boolean
54
+ /** Class of trigger button */
55
+ className?: string
56
+ /** Class of content popover */
57
+ classNameContent?: string
58
+ /** Clear handler */
59
+ onClear?: () => void
60
+ }
61
+
62
+ const formatDate = (date: Date, locale: string = 'en-us'): string => {
63
+ return date.toLocaleDateString(locale, {
64
+ month: 'short',
65
+ day: 'numeric',
66
+ year: 'numeric'
67
+ })
68
+ }
69
+
70
+ const getDateAdjustedForTimezone = (dateInput: Date | string): Date => {
71
+ if (typeof dateInput === 'string') {
72
+ // Split the date string to get year, month, and day parts
73
+ const parts = dateInput.split('-').map((part) => parseInt(part, 10))
74
+ // Create a new Date object using the local timezone
75
+ // Note: Month is 0-indexed, so subtract 1 from the month part
76
+ const date = new Date(parts[0], parts[1] - 1, parts[2])
77
+ return date
78
+ } else {
79
+ // If dateInput is already a Date object, return it directly
80
+ return dateInput
81
+ }
82
+ }
83
+
84
+ interface DateRange {
85
+ from: Date
86
+ to: Date | undefined
87
+ }
88
+
89
+ interface Preset {
90
+ name: string
91
+ label: string
92
+ }
93
+
94
+ // Define presets
95
+ const PRESETS: Preset[] = [
96
+ { name: 'today', label: 'Today' },
97
+ { name: 'yesterday', label: 'Yesterday' },
98
+ { name: 'last7', label: 'Last 7 days' },
99
+ { name: 'last14', label: 'Last 14 days' },
100
+ { name: 'last30', label: 'Last 30 days' },
101
+ { name: 'thisWeek', label: 'This Week' },
102
+ { name: 'lastWeek', label: 'Last Week' },
103
+ { name: 'thisMonth', label: 'This Month' },
104
+ { name: 'lastMonth', label: 'Last Month' }
105
+ ]
106
+
107
+ /** The DateRangePicker component allows a user to select a range of dates */
108
+ export const DateRangePicker: FC<DateRangePickerProps> & {
109
+ filePath: string
110
+ } = ({
111
+ initialDateFrom = new Date(new Date().setHours(0, 0, 0, 0)),
112
+ initialDateTo,
113
+ initialCompareFrom,
114
+ initialCompareTo,
115
+ onUpdate,
116
+ align = 'end',
117
+ locale = 'en-US',
118
+ showCompare = true,
119
+ className,
120
+ classNameContent,
121
+ onClear
122
+ }): JSX.Element => {
123
+ const [isOpen, setIsOpen] = useState(false)
124
+
125
+ const [range, setRange] = useState<DateRange>({
126
+ from: getDateAdjustedForTimezone(initialDateFrom),
127
+ to: initialDateTo
128
+ ? getDateAdjustedForTimezone(initialDateTo)
129
+ : getDateAdjustedForTimezone(initialDateFrom)
130
+ })
131
+ const [rangeCompare, setRangeCompare] = useState<DateRange | undefined>(
132
+ initialCompareFrom
133
+ ? {
134
+ from: new Date(new Date(initialCompareFrom).setHours(0, 0, 0, 0)),
135
+ to: initialCompareTo
136
+ ? new Date(new Date(initialCompareTo).setHours(0, 0, 0, 0))
137
+ : new Date(new Date(initialCompareFrom).setHours(0, 0, 0, 0))
138
+ }
139
+ : undefined
140
+ )
141
+
142
+ // Refs to store the values of range and rangeCompare when the date picker is opened
143
+ const openedRangeRef = useRef<DateRange | undefined>(undefined)
144
+ const openedRangeCompareRef = useRef<DateRange | undefined>(undefined)
145
+
146
+ const [selectedPreset, setSelectedPreset] = useState<string | undefined>(undefined)
147
+
148
+ const [isSmallScreen, setIsSmallScreen] = useState(
149
+ typeof window !== 'undefined' ? window.innerWidth < 960 : false
150
+ )
151
+
152
+ useEffect(() => {
153
+ const handleResize = (): void => {
154
+ setIsSmallScreen(window.innerWidth < 960)
155
+ }
156
+
157
+ window.addEventListener('resize', handleResize)
158
+
159
+ // Clean up event listener on unmount
160
+ return () => {
161
+ window.removeEventListener('resize', handleResize)
162
+ }
163
+ }, [])
164
+
165
+ const getPresetRange = (presetName: string): DateRange => {
166
+ const preset = PRESETS.find(({ name }) => name === presetName)
167
+ if (!preset) throw new Error(`Unknown date range preset: ${presetName}`)
168
+ const from = new Date()
169
+ const to = new Date()
170
+ const first = from.getDate() - from.getDay()
171
+
172
+ switch (preset.name) {
173
+ case 'today':
174
+ from.setHours(0, 0, 0, 0)
175
+ to.setHours(23, 59, 59, 999)
176
+ break
177
+ case 'yesterday':
178
+ from.setDate(from.getDate() - 1)
179
+ from.setHours(0, 0, 0, 0)
180
+ to.setDate(to.getDate() - 1)
181
+ to.setHours(23, 59, 59, 999)
182
+ break
183
+ case 'last7':
184
+ from.setDate(from.getDate() - 6)
185
+ from.setHours(0, 0, 0, 0)
186
+ to.setHours(23, 59, 59, 999)
187
+ break
188
+ case 'last14':
189
+ from.setDate(from.getDate() - 13)
190
+ from.setHours(0, 0, 0, 0)
191
+ to.setHours(23, 59, 59, 999)
192
+ break
193
+ case 'last30':
194
+ from.setDate(from.getDate() - 29)
195
+ from.setHours(0, 0, 0, 0)
196
+ to.setHours(23, 59, 59, 999)
197
+ break
198
+ case 'thisWeek':
199
+ from.setDate(first)
200
+ from.setHours(0, 0, 0, 0)
201
+ to.setHours(23, 59, 59, 999)
202
+ break
203
+ case 'lastWeek':
204
+ from.setDate(from.getDate() - 7 - from.getDay())
205
+ to.setDate(to.getDate() - to.getDay() - 1)
206
+ from.setHours(0, 0, 0, 0)
207
+ to.setHours(23, 59, 59, 999)
208
+ break
209
+ case 'thisMonth':
210
+ from.setDate(1)
211
+ from.setHours(0, 0, 0, 0)
212
+ to.setHours(23, 59, 59, 999)
213
+ break
214
+ case 'lastMonth':
215
+ from.setMonth(from.getMonth() - 1)
216
+ from.setDate(1)
217
+ from.setHours(0, 0, 0, 0)
218
+ to.setDate(0)
219
+ to.setHours(23, 59, 59, 999)
220
+ break
221
+ }
222
+
223
+ return { from, to }
224
+ }
225
+
226
+ const setPreset = (preset: string): void => {
227
+ const range = getPresetRange(preset)
228
+ setRange(range)
229
+ if (rangeCompare) {
230
+ const rangeCompare = {
231
+ from: new Date(
232
+ range.from.getFullYear() - 1,
233
+ range.from.getMonth(),
234
+ range.from.getDate()
235
+ ),
236
+ to: range.to
237
+ ? new Date(
238
+ range.to.getFullYear() - 1,
239
+ range.to.getMonth(),
240
+ range.to.getDate()
241
+ )
242
+ : undefined
243
+ }
244
+ setRangeCompare(rangeCompare)
245
+ }
246
+ }
247
+
248
+ const checkPreset = (): void => {
249
+ for (const preset of PRESETS) {
250
+ const presetRange = getPresetRange(preset.name)
251
+
252
+ const normalizedRangeFrom = new Date(range.from);
253
+ normalizedRangeFrom.setHours(0, 0, 0, 0);
254
+ const normalizedPresetFrom = new Date(
255
+ presetRange.from.setHours(0, 0, 0, 0)
256
+ )
257
+
258
+ const normalizedRangeTo = new Date(range.to ?? 0);
259
+ normalizedRangeTo.setHours(0, 0, 0, 0);
260
+ const normalizedPresetTo = new Date(
261
+ presetRange.to?.setHours(0, 0, 0, 0) ?? 0
262
+ )
263
+
264
+ if (
265
+ normalizedRangeFrom.getTime() === normalizedPresetFrom.getTime() &&
266
+ normalizedRangeTo.getTime() === normalizedPresetTo.getTime()
267
+ ) {
268
+ setSelectedPreset(preset.name)
269
+ return
270
+ }
271
+ }
272
+
273
+ setSelectedPreset(undefined)
274
+ }
275
+
276
+ const resetValues = (): void => {
277
+ setRange({
278
+ from:
279
+ typeof initialDateFrom === 'string'
280
+ ? getDateAdjustedForTimezone(initialDateFrom)
281
+ : initialDateFrom,
282
+ to: initialDateTo
283
+ ? typeof initialDateTo === 'string'
284
+ ? getDateAdjustedForTimezone(initialDateTo)
285
+ : initialDateTo
286
+ : typeof initialDateFrom === 'string'
287
+ ? getDateAdjustedForTimezone(initialDateFrom)
288
+ : initialDateFrom
289
+ })
290
+ setRangeCompare(
291
+ initialCompareFrom
292
+ ? {
293
+ from:
294
+ typeof initialCompareFrom === 'string'
295
+ ? getDateAdjustedForTimezone(initialCompareFrom)
296
+ : initialCompareFrom,
297
+ to: initialCompareTo
298
+ ? typeof initialCompareTo === 'string'
299
+ ? getDateAdjustedForTimezone(initialCompareTo)
300
+ : initialCompareTo
301
+ : typeof initialCompareFrom === 'string'
302
+ ? getDateAdjustedForTimezone(initialCompareFrom)
303
+ : initialCompareFrom
304
+ }
305
+ : undefined
306
+ )
307
+ }
308
+
309
+ useEffect(() => {
310
+ checkPreset()
311
+ }, [range])
312
+
313
+ const PresetButton = ({
314
+ preset,
315
+ label,
316
+ isSelected
317
+ }: {
318
+ preset: string
319
+ label: string
320
+ isSelected: boolean
321
+ }): JSX.Element => (
322
+ <Button
323
+ className={cn(isSelected && 'bg-muted pointer-events-none')}
324
+ variant="ghost"
325
+ onClick={() => {
326
+ setPreset(preset)
327
+ }}
328
+ >
329
+ <>
330
+ <span className={cn('pr-2 opacity-0', isSelected && 'opacity-70')}>
331
+ <CheckIcon width={18} height={18} />
332
+ </span>
333
+ {label}
334
+ </>
335
+ </Button>
336
+ )
337
+
338
+ // Helper function to check if two date ranges are equal
339
+ const areRangesEqual = (a?: DateRange, b?: DateRange): boolean => {
340
+ if (!a || !b) return a === b // If either is undefined, return true if both are undefined
341
+ return (
342
+ a.from.getTime() === b.from.getTime() &&
343
+ (!a.to || !b.to || a.to.getTime() === b.to.getTime())
344
+ )
345
+ }
346
+
347
+ useEffect(() => {
348
+ if (isOpen) {
349
+ openedRangeRef.current = range
350
+ openedRangeCompareRef.current = rangeCompare
351
+ }
352
+ }, [isOpen])
353
+
354
+ return (
355
+ <Popover
356
+ modal={true}
357
+ open={isOpen}
358
+ onOpenChange={(open: boolean) => {
359
+ if (!open) {
360
+ resetValues()
361
+ }
362
+ setIsOpen(open)
363
+ }}
364
+ >
365
+ <PopoverTrigger asChild>
366
+ <Button variant="outline" className={cn("rounded-md flex flex-nowrap text-nowrap",className)}>
367
+ <div className="text-right flex flex-nowrap text-nowrap">
368
+ <div className="py-1 flex flex-nowrap text-nowrap">
369
+ <div>{`${formatDate(range.from, locale)}${
370
+ range.to != null ? ' - ' + formatDate(range.to, locale) : ''
371
+ }`}</div>
372
+ </div>
373
+ {rangeCompare != null && (
374
+ <div className="opacity-60 text-xs -mt-1 flex flex-nowrap text-nowrap">
375
+ <>
376
+ vs. {formatDate(rangeCompare.from, locale)}
377
+ {rangeCompare.to != null
378
+ ? ` - ${formatDate(rangeCompare.to, locale)}`
379
+ : ''}
380
+ </>
381
+ </div>
382
+ )}
383
+ </div>
384
+ <div className="pl-1 opacity-60 -mr-2 scale-125">
385
+ {isOpen ? (<ChevronUpIcon width={24} />) : (<ChevronDownIcon width={24} />)}
386
+ </div>
387
+ </Button>
388
+ </PopoverTrigger>
389
+ <PopoverContent align={align} className={cn("w-auto z-[101]", classNameContent)}>
390
+ <div className="flex py-2">
391
+ <div className="flex">
392
+ <div className="flex flex-col">
393
+ <div className="flex flex-col lg:flex-row gap-2 px-3 justify-end items-center lg:items-start pb-4 lg:pb-0">
394
+ {showCompare && (
395
+ <div className="flex items-center space-x-2 pr-4 py-1">
396
+ <Switch
397
+ defaultChecked={Boolean(rangeCompare)}
398
+ onCheckedChange={(checked: boolean) => {
399
+ if (checked) {
400
+ if (!range.to) {
401
+ setRange({
402
+ from: range.from,
403
+ to: range.from
404
+ })
405
+ }
406
+ setRangeCompare({
407
+ from: new Date(
408
+ range.from.getFullYear(),
409
+ range.from.getMonth(),
410
+ range.from.getDate() - 365
411
+ ),
412
+ to: range.to
413
+ ? new Date(
414
+ range.to.getFullYear() - 1,
415
+ range.to.getMonth(),
416
+ range.to.getDate()
417
+ )
418
+ : new Date(
419
+ range.from.getFullYear() - 1,
420
+ range.from.getMonth(),
421
+ range.from.getDate()
422
+ )
423
+ })
424
+ } else {
425
+ setRangeCompare(undefined)
426
+ }
427
+ }}
428
+ id="compare-mode"
429
+ />
430
+ <Label htmlFor="compare-mode">Compare</Label>
431
+ </div>
432
+ )}
433
+ <div className="flex flex-col gap-2">
434
+ <div className="flex gap-2">
435
+ <DateInput
436
+ value={range.from}
437
+ onChange={(date) => {
438
+ const toDate =
439
+ range.to == null || date > range.to ? date : range.to
440
+ setRange((prevRange) => ({
441
+ ...prevRange,
442
+ from: date,
443
+ to: toDate
444
+ }))
445
+ }}
446
+ />
447
+ <div className="py-1">-</div>
448
+ <DateInput
449
+ value={range.to}
450
+ onChange={(date) => {
451
+ const fromDate = date < range.from ? date : range.from
452
+ setRange((prevRange) => ({
453
+ ...prevRange,
454
+ from: fromDate,
455
+ to: date
456
+ }))
457
+ }}
458
+ />
459
+ </div>
460
+ {rangeCompare != null && (
461
+ <div className="flex gap-2">
462
+ <DateInput
463
+ value={rangeCompare?.from}
464
+ onChange={(date) => {
465
+ if (rangeCompare) {
466
+ const compareToDate =
467
+ rangeCompare.to == null || date > rangeCompare.to
468
+ ? date
469
+ : rangeCompare.to
470
+ setRangeCompare((prevRangeCompare) => ({
471
+ ...prevRangeCompare,
472
+ from: date,
473
+ to: compareToDate
474
+ }))
475
+ } else {
476
+ setRangeCompare({
477
+ from: date,
478
+ to: new Date()
479
+ })
480
+ }
481
+ }}
482
+ />
483
+ <div className="py-1">-</div>
484
+ <DateInput
485
+ value={rangeCompare?.to}
486
+ onChange={(date) => {
487
+ if (rangeCompare && rangeCompare.from) {
488
+ const compareFromDate =
489
+ date < rangeCompare.from
490
+ ? date
491
+ : rangeCompare.from
492
+ setRangeCompare({
493
+ ...rangeCompare,
494
+ from: compareFromDate,
495
+ to: date
496
+ })
497
+ }
498
+ }}
499
+ />
500
+ </div>
501
+ )}
502
+ </div>
503
+ </div>
504
+ { isSmallScreen && (
505
+ <Select defaultValue={selectedPreset} onValueChange={(value) => { setPreset(value) }}>
506
+ <SelectTrigger className="w-[180px] mx-auto mb-2">
507
+ <SelectValue placeholder="Select..." />
508
+ </SelectTrigger>
509
+ <SelectContent>
510
+ {PRESETS.map((preset) => (
511
+ <SelectItem key={preset.name} value={preset.name}>
512
+ {preset.label}
513
+ </SelectItem>
514
+ ))}
515
+ </SelectContent>
516
+ </Select>
517
+ )}
518
+ <div>
519
+ <Calendar
520
+ mode="range"
521
+ onSelect={(value: { from?: Date, to?: Date } | undefined) => {
522
+ if (value?.from != null) {
523
+ setRange({ from: value.from, to: value?.to })
524
+ }
525
+ }}
526
+ selected={range}
527
+ numberOfMonths={isSmallScreen ? 1 : 2}
528
+ defaultMonth={
529
+ new Date(
530
+ new Date().setMonth(
531
+ new Date().getMonth() - (isSmallScreen ? 0 : 1)
532
+ )
533
+ )
534
+ }
535
+ />
536
+ </div>
537
+ </div>
538
+ </div>
539
+ {!isSmallScreen && (
540
+ <div className="flex flex-col items-end gap-1 pr-2 pl-6 pb-6">
541
+ <div className="flex w-full flex-col items-end gap-1 pr-2 pl-6 pb-6">
542
+ {PRESETS.map((preset) => (
543
+ <PresetButton
544
+ key={preset.name}
545
+ preset={preset.name}
546
+ label={preset.label}
547
+ isSelected={selectedPreset === preset.name}
548
+ />
549
+ ))}
550
+ </div>
551
+ </div>
552
+ )}
553
+ </div>
554
+ <div className="flex justify-end gap-2 py-2 pr-4">
555
+ <Button
556
+ onClick={() => {
557
+ onClear?.()
558
+ }}
559
+ variant="ghost"
560
+ >
561
+ Clear
562
+ </Button>
563
+ <Button
564
+ onClick={() => {
565
+ setIsOpen(false)
566
+ resetValues()
567
+ }}
568
+ variant="ghost"
569
+ >
570
+ Cancel
571
+ </Button>
572
+ <Button
573
+ className="!text-background"
574
+ onClick={() => {
575
+ setIsOpen(false)
576
+ if (
577
+ !areRangesEqual(range, openedRangeRef.current) ||
578
+ !areRangesEqual(rangeCompare, openedRangeCompareRef.current)
579
+ ) {
580
+ onUpdate?.({ range, rangeCompare })
581
+ }
582
+ }}
583
+ >
584
+ Update
585
+ </Button>
586
+ </div>
587
+ </PopoverContent>
588
+ </Popover>
589
+ )
590
+ }
591
+
592
+ DateRangePicker.displayName = 'DateRangePicker'
593
+ DateRangePicker.filePath =
594
+ 'libs/shared/ui-kit/src/lib/date-range-picker/date-range-picker.tsx'
@@ -0,0 +1,31 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react';
4
+
5
+ import {
6
+ cva,
7
+ type VariantProps,
8
+ } from 'class-variance-authority';
9
+
10
+ import * as LabelPrimitive from '@radix-ui/react-label';
11
+
12
+ import { cn } from '../../lib/utils';
13
+
14
+ const labelVariants = cva(
15
+ 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70'
16
+ )
17
+
18
+ const Label = React.forwardRef<
19
+ React.ElementRef<typeof LabelPrimitive.Root>,
20
+ React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
21
+ VariantProps<typeof labelVariants>
22
+ >(({ className, ...props }, ref) => (
23
+ <LabelPrimitive.Root
24
+ ref={ref}
25
+ className={cn(labelVariants(), className)}
26
+ {...props}
27
+ />
28
+ ))
29
+ Label.displayName = LabelPrimitive.Root.displayName
30
+
31
+ export { Label };
@@ -0,0 +1,32 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react';
4
+
5
+ import * as PopoverPrimitive from '@radix-ui/react-popover';
6
+
7
+ import { cn } from '../../lib/utils';
8
+
9
+ const Popover = PopoverPrimitive.Root
10
+
11
+ const PopoverTrigger = PopoverPrimitive.Trigger
12
+
13
+ const PopoverContent = React.forwardRef<
14
+ React.ElementRef<typeof PopoverPrimitive.Content>,
15
+ React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
16
+ >(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (
17
+ <PopoverPrimitive.Portal>
18
+ <PopoverPrimitive.Content
19
+ ref={ref}
20
+ align={align}
21
+ sideOffset={sideOffset}
22
+ className={cn(
23
+ 'z-50 w-72 rounded-md border bg-white p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
24
+ className
25
+ )}
26
+ {...props}
27
+ />
28
+ </PopoverPrimitive.Portal>
29
+ ))
30
+ PopoverContent.displayName = PopoverPrimitive.Content.displayName
31
+
32
+ export { Popover, PopoverContent, PopoverTrigger };